#define UPDATE_CKEY_MOB(__ckey) var/mob/result = selected_ckeys_mobs[__ckey];\ if(!result || result.ckey != __ckey){\ result = get_mob_by_ckey(__ckey);\ selected_ckeys_mobs[__ckey] = result;\ } #define RECORD_WARN_LIMIT 1000 #define RECORD_HARD_LIMIT 2500 /datum/log_viewer var/time_from = 0 var/time_to = 4 HOURS // 4 Hours should be enough. INFINITY would screw the UI up var/list/selected_mobs = list() // The mobs in question. var/list/selected_ckeys = list() // The ckeys selected to search for. Will show all mobs the ckey is attached to var/list/mob/selected_ckeys_mobs = list() var/list/selected_log_types = ALL_LOGS // The log types being searched for var/list/log_records = list() // Found and sorted records /datum/log_viewer/proc/clear_all() selected_mobs.Cut() selected_log_types = ALL_LOGS selected_ckeys.Cut() selected_ckeys_mobs.Cut() time_from = initial(time_from) time_to = initial(time_to) log_records.Cut() return /datum/log_viewer/proc/search(user) log_records.Cut() // Empty the old results var/list/invalid_mobs = list() var/list/ckeys = selected_ckeys.Copy() for(var/i in selected_mobs) var/mob/M = i if(!M || QDELETED(M) || !M.last_known_ckey) invalid_mobs |= M continue ckeys |= M.last_known_ckey for(var/ckey in ckeys) for(var/log_type in selected_log_types) var/list/logs = GLOB.logging.get_logs_by_type(ckey, log_type) var/len_logs = length(logs) if(len_logs) var/start_index = get_earliest_log_index(logs) if(!start_index) // No log found that matches the starting time criteria continue var/end_index = get_latest_log_index(logs) if(!end_index) // No log found that matches the end time criteria continue log_records.Add(logs.Copy(start_index, end_index + 1)) if(length(invalid_mobs)) to_chat(user, "The search criteria contained invalid mobs. They have been removed from the criteria.") for(var/i in invalid_mobs) selected_mobs -= i // Cleanup log_records = sortTim(log_records, GLOBAL_PROC_REF(compare_log_record)) /** Binary search like implementation to find the earliest log * Returns the index of the earliest log using the time_from value for the given list of logs. * It will return 0 if no log after time_from is found */ /datum/log_viewer/proc/get_earliest_log_index(list/logs) if(!time_from) return 1 var/start = 1 var/end = length(logs) var/mid do mid = round_down((end + start) / 2) var/datum/log_record/L = logs[mid] if(L.raw_time >= time_from) end = mid else start = mid while(end - start > 1) var/datum/log_record/L = logs[end] if(L.raw_time >= time_from) // Check if there is atleast one valid log return end return 0 /** Binary search like implementation to find the latest log * Returns the index of the latest log using the time_to value (1 second is added to prevent rounding weirdness) for the given list of logs. * It will return 0 if no log before time_to + 10 is found */ /datum/log_viewer/proc/get_latest_log_index(list/logs) if(world.time < time_to) return length(logs) var/end = length(logs) var/start = 1 var/mid var/max_time = time_to + 10 do mid = round((end + start) / 2 + 0.5) var/datum/log_record/L = logs[mid] if(L.raw_time >= max_time) end = mid else start = mid while(end - start > 1) var/datum/log_record/L = logs[start] if(L.raw_time < max_time) // Check if there is atleast one valid log return start return 0 /datum/log_viewer/proc/add_mobs(list/mob/mobs) if(!length(mobs)) return for(var/i in mobs) add_mob(usr, i, FALSE) /datum/log_viewer/proc/add_ckey(mob/user, ckey) if(!user || !ckey) return selected_ckeys |= ckey UPDATE_CKEY_MOB(ckey) show_ui(user) /datum/log_viewer/proc/add_mob(mob/user, mob/M, show_the_ui = TRUE) if(!M || !user) return selected_mobs |= M show_ui(user) /datum/log_viewer/proc/show_ui(mob/user) var/all_log_types = ALL_LOGS var/trStyleTop = "border-top:2px solid; border-bottom:2px solid; padding-top: 5px; padding-bottom: 5px;" var/trStyle = "border-top:1px solid; border-bottom:1px solid; padding-top: 5px; padding-bottom: 5px;" var/list/dat = list() dat += "
" dat += "| When | Type | Who | What | Target | Where |
|---|---|---|---|---|---|
| [time] | [L.log_type] | \[L.who] | [L.what] | \[L.target] | [L.where] |