-- environment_far.lua --[[ local STOP_TIME = 40 local STOPCMD="B0WO" local DEPCMD="A1OCD1SM" local RDEPCMD="RA1OCD1SM" local DYNAMIC_THR = 10 local DYNAMIC_EN = false ]] if S.trains == nil then S.trains = {} end if S.d == nil then S.d = {} end if S.datetime == nil then S.datetime = "" end if S.stop_display == nil then S.stop_display = false end if S.show_farpass_only == nil then S.show_farpass_only = false end if S.timetake == nil then S.timetake = {} end if S.ttp == nil then S.ttp = {} end if S.ttt == nil then S.ttt = {} end F.ttp={ FAR_E = { outside_text = "[FAR] Fareast End\nvia Halfway, Bayonne, Fucking", inside_line_desc = "FAR to Fareast End", stn_display = "FAR Fareast End", }, FAR_W = { outside_text = "[FAR] Salt Factory\nvia Fucking, Bayonne, Halfway", inside_line_desc = "FAR to Salt Factory", stn_display = "FAR Salt Factory", }, } F.print = function (str) if F.debug then print("".. (str or "nil") ) end end F.isempty = function (s) return s == nil or s == "" end F.get_rc_safe = function() return get_rc() or "" end F.get_line_safe = function() return get_line() or "" end F.get_train_length_safe = function() return train_length() or 0 end F.avg = function(t) local sum = 0 local count = 0 for k,v in pairs(t) do if type(v) == "number" then sum = sum + v count = count + 1 end end return (sum / count) end if event.init then F.debug = true F.printAllTrainsInfo = true F.max_displays = 15 F.STOP_TIME = 40 F.STOPCMD="B0WO" F.DEPCMD="A1OCD1SM" F.RDEPCMD="RA1OCD1SM" F.DYNAMIC_THR = 10 F.DYNAMIC_EN = false F.print("Initialized") end --[[ EXAMPLE: F.has_rc("LILSHUNTER", F.get_rc_safe() ) Merged F.has_rc and F.does_train_have_rc F.does_train_have_rc is deprecated ]] F.has_rc = function(query,rc_list) -- query = string, single entry for word in rc_list:gmatch("[^%s]+") do if word == query then return true end end return false end F.send_route = function(passive_name, route, show_print) local message = "" local return_value = false if can_set_route(passive_name, route) then set_route(passive_name, route) message = passive_name .. " has been set to " .. route return_value = true else message = route .. " cannot be set for " .. passive_name .. ". Try another." return_value = false end if show_print == true then F.print(message) end return return_value end --[[ F.save_train(POS(26201,24,1417), "east") ]] F.save_train = function(pos, direction) if event.train then if not atc_id then return end if S.trains then if F.isempty(pos) then pos_string = "" else pos_string = pos["x"] .. "," .. pos["y"] .. "," .. pos["z"] end if F.has_rc("FAREAST", F.get_rc_safe()) then if direction == nil or direction == "" then S.trains[atc_id] = { ["id"] = atc_id, ["rc"] = F.get_rc_safe(), ["ln"] = F.get_line_safe(), ["cars_count"] = F.get_train_length_safe(), ["pos"] = pos_string , ["direction"] = nil } else S.trains[atc_id] = { ["id"] = atc_id, ["rc"] = F.get_rc_safe(), ["ln"] = F.get_line_safe(), ["cars_count"] = F.get_train_length_safe(), ["pos"] = pos_string , ["direction"] = direction } end -- F.print("Train ID: " .. S.trains[atc_id]["id"] .. " at " .. S.trains[atc_id]["pos"]) -- remote_track = POS(30919,13,1812) -- interrupt_pos(remote_track, "display") end end end return end F.get_real_split_count = function(train_length_count, split_count) if split_count then if split_count == "all" then return 2 else F.print("train_length_count (" .. train_length_count .. ") - split_count (" .. split_count .. ")") train_length_count = train_length_count + 1 split_count = train_length_count - split_count return split_count end else return nil end end F.delete_train_info = function(train_id) if S.trains[train_id] then S.trains[train_id] = nil F.print("Deleted train id: " .. train_id) end end F.clear_main_depot_displays = function() for i = 1, F.max_displays, 1 do digiline_send("train_display" .. i, " ") end end F.send_update_displays = function() for i = 1, F.max_displays, 1 do digiline_send("train_display" .. i, "Updating...") end end F.date_formatted = function() date = os.date("%Y-%m-%d") return date end F.time_formatted = function() time = os.date("*t") return string.format("%02d:%02d:%02d %s", time.hour, time.min, time.sec, (time.isdst and "CEST") or "CET") end F.list_trains = function(print_info) if S.trains then number_of_displays = F.max_displays F.clear_main_depot_displays() number_of_displays = number_of_displays + 1 count_keys = 0 direction_display = "" trains_table = {} for k in pairs(S.trains) do table.insert(trains_table, k) count_keys = count_keys + 1 end table.sort(trains_table) -- x = number_of_displays - count_keys x = 1 for _, k in ipairs(trains_table) do if S.trains[k] then v = S.trains[k] if S.show_farpass_only == true and not F.has_rc("FARPASS", v["rc"]) then F.delete_train_info(v["id"]) end if F.has_rc("LILSHUNTER", v["rc"]) or F.has_rc("LIL", v["rc"]) then F.delete_train_info(v["id"]) else if v["ln"] == nil or v["ln"] == "" then line_number = "" else line_number = "| LN: [" .. v["ln"] .. "]" end if v["pos"] == nil or v["pos"] == "" then pos_string = "" else pos_string = "| POS: [" .. v["pos"] .. "]" end if v["rc"] == nil or v["rc"] == "" then rc_display = "" else rc_list = v["rc"] rc_list_cleansed = "" rc_list_unknown = "" rc_list_table = {} if F.has_rc("ERSTAZI", rc_list) and F.has_rc("FREIGHT", rc_list) then rc_list_cleansed = "ERSTAZI FREIGHT |" else rc_list_cleansed = "NO E,F |" end for rc in rc_list:gmatch("[^%s]+") do if rc == "ERSTAZI" or rc == "ERSTAZIDEPOT" or rc == "FREIGHT" then -- leaving for future use do_nothing = true else rc_list_unknown = rc_list_unknown .. " " .. rc end end rc_display = "" if not F.isempty(rc_list_unknown) then rc_display = rc_display .. "| RC:" .. rc_list_unknown end end if v["direction"] == nil or v["direction"] == "" then direction_display = " D: ??" else direction_display = " D: " .. v["direction"] end if v["cars_count"] == nil or v["cars_count"] == "" then cars_count_display = " L: 0" else cars_count = tonumber(v["cars_count"]) cars_count_display = " L: " .. cars_count end message = " ID: " .. v["id"] .. cars_count_display .. direction_display .. rc_display .. line_number .. pos_string if x > 0 then digiline_send("train_display" .. x, message) end if print_info then F.print(x .. ": " .. message) end x = x + 1 end end end -- S.datetime = os.date("%Y-%m-%d %H:%M:%S") -- digiline_send("time", " \n " .. S.datetime) else if print_info then F.print("no trains saved in S.trains") end end end F.slow_train_down = function(id) result = atc_send_to_train(id, "B1") if result == false then F.print("Train ID " .. id .. " does not exist") else F.print("Train ID " .. id .. " is slowed down to B1") end end -- init code for FAR timetable env -- stop, scheduled departure every -- d_int: Departure every n seconds (epoch modulo) -- d_off: Departure time offset function F.stop_sd(st_name, doors, departcommand, minstoptime, d_int, d_off) if event.train then local timenow = os.time() local timerdy = timenow + minstoptime local wait = d_int - ((timerdy-d_off) % d_int) local waitcorr = math.floor(wait*0.66) digiline_send("monitor", "Departure scheduled for: | "..os.date("%H:%M:%S", timenow+wait)) atc_send("B0 W O"..doors.." D"..waitcorr.." OCD1"..departcommand) else local timenow = os.time() digiline_send("monitor", "Time: "..os.date("%H:%M:%S", timenow)) end end function F.stop_sd_sched(st_name, doors, departcommand, minstoptime, d_int, d_off) depart = false if event.train then local time_now = rwt.now() local next_dep_time = rwt.next_rpt(rwt.add(time_now, minstoptime), d_int, d_off) digiline_send("monitor", "Departure scheduled for: | "..rwt.to_string(next_dep_time, true)) atc_set_text_inside(st_name.."\nDeparture: "..rwt.to_string(next_dep_time, true)) atc_send("B0 W O"..doors) schedule(next_dep_time, "depart") elseif event.schedule then atc_send("OCD1"..departcommand) digiline_send("monitor", "Last Departure: | "..rwt.to_string(rwt.now(), true)) atc_set_text_inside("") depart = true end end function F.timedisplay() digiline_send("time", "Time: | "..rwt.to_string(rwt.now(),true).." | "..os.date("%H:%M:%S")) schedule(rwt.next_rpt(rwt.now(),5,0), "") end -- Stat counter and timetaking utilities -- Stat from subway F.stat=function(line, init) -- statistics if init then reftrain = atc_id a_tbt = 30 a_tbtmax = 30 a_rtt = 500 a_not = 0 c_not = 0 c_tbtmax = 0 time_lt = os.time() time_rt=os.time() end if not a_tbtmax then a_tbtmax = 30 end if not c_tbtmax then c_tbtmax = 0 end if event.train then local time = os.time() c_not = c_not + 1 a_tbt = (a_tbt + (time - time_lt)) / 2 c_tbtmax = math.max(c_tbtmax, (time - time_lt)) if atc_id == reftrain then a_rtt = (a_rtt*0.2 + (time - time_rt)*0.8) a_not = c_not c_not = 0 a_tbtmax = (a_tbtmax + c_tbtmax) / 2 c_tbtmax = 0 end digiline_send("stats", "Stat: "..line.. " NoT:"..a_not.."("..c_not..")".. " TbT:"..math.floor(a_tbt).."("..(time-time_lt)..")".. " Tmx:"..math.floor(a_tbtmax).."("..c_tbtmax..")".. " R:"..math.floor(a_rtt).."("..(time - time_rt)..")" ) time_lt = time if atc_id == reftrain then time_rt = time end end end function F.timetake_start(ttname) if not atc_id then return end local nouw = rwt.to_secs(rwt.now()) if not S.timetake[ttname] then S.timetake[ttname] = {} end S.timetake[ttname][atc_id] = nouw end function F.timetake_end(ttname) if not atc_id then return end if not S.timetake[ttname] or not S.timetake[ttname][atc_id] then digiline_send("timetake", "No start time for "..atc_id) return end local first = S.timetake[ttname][atc_id] local nouw = rwt.to_secs(rwt.now()) local tdiff = nouw - first local cavg = S.timetake[ttname].avg local cmax = S.timetake[ttname].max local cmin = S.timetake[ttname].min if cavg and cmax and cmin then S.timetake[ttname].avg = tdiff*0.1 + cavg*0.9 S.timetake[ttname].min = math.min(tdiff, cmin) S.timetake[ttname].max = math.max(tdiff, cmax) else S.timetake[ttname].avg = tdiff S.timetake[ttname].min = tdiff S.timetake[ttname].max = tdiff end digiline_send("timetake", ttname.. " this:"..tdiff.. " min:"..math.floor(S.timetake[ttname].min).. " avg:"..math.floor(S.timetake[ttname].avg).. " max:"..math.floor(S.timetake[ttname].max) ) end --== Timetable prototype (TTP) === --[[ table structures: F.ttp - static timetable data - see below S.ttp[tt_name] = { - dynamic tt data recording_train = travel_times = { =