diff options
author | Singularis <singularis@volny.cz> | 2025-01-26 18:06:40 +0100 |
---|---|---|
committer | orwell <orwell@bleipb.de> | 2025-05-27 20:22:01 +0200 |
commit | 6ac6558b3b716a49bf29f6e5ce40cc6bc0443ae7 (patch) | |
tree | 53fa96b0e7d7beaed6d04999c10406d3374b2445 | |
parent | ef4ba201bf9bef7bdeaa573b4a549da8b06a5e07 (diff) | |
download | advtrains-6ac6558b3b716a49bf29f6e5ce40cc6bc0443ae7.tar.gz advtrains-6ac6558b3b716a49bf29f6e5ce40cc6bc0443ae7.tar.bz2 advtrains-6ac6558b3b716a49bf29f6e5ce40cc6bc0443ae7.zip |
[advtrains_line_automation] vývoj
- staničnímu rozhlasu přidán režim (odjezdy/příjezdy)
- do editoru variant linek přidána možnost pokračování a nastavení
předpokládané doby stání na zastávkách
- přidána podpora času ve formátu MM:SS
-rw-r--r-- | advtrains_line_automation/line_editor.lua | 89 | ||||
-rw-r--r-- | advtrains_line_automation/line_functions.lua | 300 | ||||
-rw-r--r-- | advtrains_line_automation/models/advtrains_tuber.obj | 80 | ||||
-rw-r--r-- | advtrains_line_automation/models/license.txt | 2 | ||||
-rw-r--r-- | advtrains_line_automation/station_announcement.lua | 351 | ||||
-rw-r--r-- | advtrains_line_automation/structs.md | 21 |
6 files changed, 590 insertions, 253 deletions
diff --git a/advtrains_line_automation/line_editor.lua b/advtrains_line_automation/line_editor.lua index 240ac54..d1cab75 100644 --- a/advtrains_line_automation/line_editor.lua +++ b/advtrains_line_automation/line_editor.lua @@ -179,7 +179,8 @@ local function get_formspec(custom_state) table.insert(formspec, "field[7,7;4,0.75;owner;spravuje:;") end table.insert(formspec, F(custom_state.owner).."]".. - "checkbox[11.25,7.25;disable_linevar;vypnout;"..custom_state.disable_linevar.."]") + "checkbox[11.25,7.25;disable_linevar;vypnout;"..custom_state.disable_linevar.."]".. + "field[13.5,7;3,0.75;continues;pokračování:;"..F(custom_state.continues).."]") if custom_state.message ~= "" then table.insert(formspec, "label[0.5,8.25;"..F(custom_state.message).."]") @@ -204,10 +205,11 @@ local function get_formspec(custom_state) table.insert(formspec, "container[0,8.75]".. "label[0.5,0.25;odjezd]".. - "label[2,0.25;kód dop.]".. - "label[4.75,0.25;režim zastávky]".. - "label[9.5,0.25;kolej]".. - "label[11,0.25;omezení pozice]".. + "label[2,0.25;stání]".. + "label[3.5,0.25;kód dop.]".. + "label[6.25,0.25;režim zastávky]".. + "label[11,0.25;kolej]".. + "label[12.5,0.25;omezení pozice]".. "scrollbaroptions[min=0;max=550;arrows=show]".. "scrollbar[19,0.5;0.5,5.5;vertical;evl_scroll;"..custom_state.evl_scroll.."]".. "scroll_container[0.5,0.5;18.5,5.5;evl_scroll;vertical]".. @@ -216,11 +218,12 @@ local function get_formspec(custom_state) -- výchozí zastávka: table.insert(formspec, "label[0.1,0.4;0]".. - "field[1.5,0;2.5,0.75;s01_stn;;"..F(custom_state.stops[1].stn).."]".. - "dropdown[4.25,0;4.5,0.75;s01_mode;výchozí,skrytá (výchozí);"..custom_state.stops[1].mode..";true]".. - "field[9,0;1.25,0.75;s01_track;;"..F(custom_state.stops[1].track).."]".. - "field[10.5,0;3,0.75;s01_pos;;"..F(custom_state.stops[1].pos).."]".. - "label[13.75,0.4;"..F(custom_state.stops[1].label).."]") + "field[1.5,0;1.25,0.75;s01_wait;;"..F(custom_state.stops[1].wait).."]".. + "field[3,0;2.5,0.75;s01_stn;;"..F(custom_state.stops[1].stn).."]".. + "dropdown[5.75,0;4.5,0.75;s01_mode;výchozí,skrytá (výchozí);"..custom_state.stops[1].mode..";true]".. + "field[10.5,0;1.25,0.75;s01_track;;"..F(custom_state.stops[1].track).."]".. + "field[12,0;3,0.75;s01_pos;;"..F(custom_state.stops[1].pos).."]".. + "label[15.25,0.4;"..F(custom_state.stops[1].label).."]") -- ostatní zastávky: local y_base, y_scale = 0, 1 @@ -236,33 +239,35 @@ local function get_formspec(custom_state) local y2 = string.format("%f", y_base + (i - 1) * y_scale + 0.4) -- for a label table.insert(formspec, "field[0,"..y..";1.25,0.75;s"..n.."_dep;;"..F(stop.dep).."]".. - "field[1.5,"..y..";2.5,0.75;s"..n.."_stn;;"..F(stop.stn).."]".. - "dropdown[4.25,"..y..";4.5,0.75;s"..n.. + "field[1.5,"..y..";1.25,0.75;s"..n.."_wait;;"..F(stop.wait).."]".. + "field[3,"..y..";2.5,0.75;s"..n.."_stn;;"..F(stop.stn).."]".. + "dropdown[5.75,"..y..";4.5,0.75;s"..n.. "_mode;normální,na znamení (experimentální),skrytá (mezilehlá),vypnutá,koncová,koncová skrytá,".. "koncová (pokračuje);"..stop.mode..";true]".. - "field[9,"..y..";1.25,0.75;s"..n.."_track;;"..F(stop.track).."]".. - "field[10.5,"..y..";3,0.75;s"..n.."_pos;;"..F(stop.pos).."]".. - "label[13.75,"..y2..";"..F(stop.label).."]") + "field[10.5,"..y..";1.25,0.75;s"..n.."_track;;"..F(stop.track).."]".. + "field[12,"..y..";3,0.75;s"..n.."_pos;;"..F(stop.pos).."]".. + "label[15.25,"..y2..";"..F(stop.label).."]") end table.insert(formspec, "scroll_container_end[]".. - "tooltip[0,0;2,1;Odjezd: očekávaná jízdní doba v sekundách od odjezdu z výchozí zastávky\n".. + "tooltip[0,0;1.5,1;Odjezd: očekávaná jízdní doba v sekundách od odjezdu z výchozí zastávky\n".. "do odjezdu z dané zastávky. Podle ní se počítá zpoždění. Hodnota musí být jedinečná\n".. "pro každou zastávku na lince a podle ní se zastávky seřadí.\n".. "Pro úplné smazání dopravny z linky nechte pole prázdné.]".. - "tooltip[2,0;2.75,1;Kód dopravny: kód dopravny\\, kde má vlak zastavit. Vlak bude ignorovat\n".. + "tooltip[1.5,0;1.5,1;Stání: očekáváná doba stání před odjezdem. Pro koncové zastávky očekávaná doba stání po příjezdu.]".. + "tooltip[3.5,0;2.75,1;Kód dopravny: kód dopravny\\, kde má vlak zastavit. Vlak bude ignorovat\n".. "ARS pravidla a zastaví na první zastávkové koleji v dopravně pro odpovídající počet vagonů.\n".. "Kód dopravny se na lince může opakovat.]".. - "tooltip[4.75,0;4.75,1;Režim zastávky: výchozí/normální - vždy zastaví\\;\n".. + "tooltip[6.25,0;4.75,1;Režim zastávky: výchozí/normální - vždy zastaví\\;\n".. "na znamení: zastaví na znamení (zatím experimentální)\\;\n".. "skrytá – vždy zastaví\\, ale nezobrazí se v jízdních řádech\\;\n".. "vypnutá – nezastaví (použijte při výlukách nebo při zrušení zastávky)\\;\n".. "koncová – vždy zastaví a tím ukončí spoj\\, vlak se stane nelinkovým\\;\n".. "koncová (pokračuje) – jako koncová\\, ale vlak se může na odjezdu opět stát linkovým.]".. - "tooltip[9.5,0;1.5,1;Kolej: nepovinný\\, orientační údaj do jízdních řádů – na které koleji\n".. + "tooltip[10.5,0;1.5,1;Kolej: nepovinný\\, orientační údaj do jízdních řádů – na které koleji\n".. "vlaky obvykle zastavují. Nepovinný údaj.]".. - "tooltip[10.5,0;3.5,1;Omezení pozice: Zadávejte jen v případě potřeby.\n".. + "tooltip[12.5,0;3.5,1;Omezení pozice: Zadávejte jen v případě potřeby.\n".. "Je-li zadáno\\, vlak v dané dopravně nezastaví na žádné jiné zastávkové koleji\n".. "než na té\\, která leží přesně na zadané pozici. Příklad platné hodnoty:\n123,7,-13]".. "container_end[]") @@ -317,6 +322,7 @@ local function custom_state_set_selection_index(custom_state, new_selection_inde if stop ~= nil then stops[i] = { dep = tostring(assert(stop.dep)), + wait = tostring(stop.wait or 10), stn = assert(stop.stn), mode = mode_to_formspec(i, stop.mode), track = stop.track or "", @@ -326,6 +332,7 @@ local function custom_state_set_selection_index(custom_state, new_selection_inde else stops[i] = { dep = ifthenelse(i == 1, "0", ""), + wait = "10", stn = "", mode = 1, track = "", @@ -341,12 +348,17 @@ local function custom_state_set_selection_index(custom_state, new_selection_inde custom_state.train_name = current_linevar.train_name or "" custom_state.owner = assert(current_linevar.owner) custom_state.disable_linevar = ifthenelse(current_linevar.disabled, "true", "false") + custom_state.continues = current_linevar.continue_line or "" + if custom_state.continues ~= "" then + custom_state.continues = custom_state.continues.."/"..(current_linevar.continue_rc or "") + end else custom_state.line = "" custom_state.rc = "" custom_state.train_name = "" custom_state.owner = custom_state.player_name custom_state.disable_linevar = "false" + custom_state.continues = "" end custom_state.owner = ch_core.prihlasovaci_na_zobrazovaci(custom_state.owner) custom_state.compiled_linevar = nil @@ -413,6 +425,8 @@ local function custom_state_compile_linevar(custom_state) return false, "Správa linky musí být vyplněná!" elseif train_name:len() > 256 then return false, "Jméno vlaku je příliš dlouhé!" + elseif custom_state.continues:len() - custom_state.continues:gsub("/", ""):len() > 1 then + return false, "Pole 'pokračování' smí obsahovat nejvýše jedno lomítko!" end -- Zkontrolovat zastávky: local errcount = 0 @@ -468,6 +482,10 @@ local function custom_state_compile_linevar(custom_state) if stop.track ~= "" then new_stop.track = stop.track end + local new_wait = tonumber(stop.wait) + if new_wait ~= nil and new_wait == math.floor(new_wait) and new_wait >= 0 and new_wait <= 3600 then + new_stop.wait = new_wait + end table.insert(stops, new_stop) if stop.stn ~= "" then stop.label = color_green.."= "..assert(stations[stop.stn].name) @@ -482,11 +500,30 @@ local function custom_state_compile_linevar(custom_state) return false, "Varianta linky musí obsahovat alespoň jednu koncovou zastávku!" end table.sort(stops, function(a, b) return a.dep < b.dep end) + + local index_vychozi, index_cil + for i, stop in ipairs(stops) do + local mode = stop.mode or MODE_NORMAL + if mode ~= MODE_DISABLED and mode ~= MODE_HIDDEN and mode ~= MODE_FINAL_HIDDEN then + if index_vychozi == nil then + index_vychozi = i + end + index_cil = i + end + if mode == MODE_FINAL or mode == MODE_FINAL_CONTINUE or mode == MODE_FINAL_HIDDEN then + break + end + end + custom_state.compiled_linevar = { name = line.."/"..stops[1].stn.."/"..rc, line = line, owner = ch_core.jmeno_na_prihlasovaci(owner), stops = stops, + continue_line = "", + continue_rc = "", + index_vychozi = index_vychozi, + index_cil = index_cil, } if train_name ~= "" then custom_state.compiled_linevar.train_name = train_name @@ -494,6 +531,13 @@ local function custom_state_compile_linevar(custom_state) if custom_state.disable_linevar == "true" then custom_state.compiled_linevar.disabled = true end + local continues_split = custom_state.continues:find("/") + if continues_split == nil then + custom_state.compiled_linevar.continue_line = custom_state.continues + else + custom_state.compiled_linevar.continue_line = custom_state.continues:sub(1, continues_split - 1) + custom_state.compiled_linevar.continue_rc = custom_state.continues:sub(continues_split + 1, -1) + end return true, nil end @@ -524,14 +568,14 @@ local function formspec_callback(custom_state, player, formname, fields) end end -- fields: - for _, key in ipairs({"line", "rc", "train_name", "owner"}) do + for _, key in ipairs({"line", "rc", "train_name", "owner", "continues"}) do if fields[key] then custom_state[key] = fields[key] end end for i, stop in ipairs(custom_state.stops) do local prefix = string.format("s%02d_", i) - for _, key in ipairs({"dep", "stn", "track", "pos"}) do + for _, key in ipairs({"dep", "wait", "stn", "track", "pos"}) do local value = fields[prefix..key] if value then stop[key] = value @@ -712,6 +756,7 @@ local function show_editor_formspec(player, linevar_to_select) player_name = assert(player:get_player_name()), evl_scroll = 0, message = "", + continues = "", } if not custom_state_refresh_linevars(custom_state, linevar_to_select) then custom_state_set_selection_index(custom_state, 1) diff --git a/advtrains_line_automation/line_functions.lua b/advtrains_line_automation/line_functions.lua index 0963676..41776c3 100644 --- a/advtrains_line_automation/line_functions.lua +++ b/advtrains_line_automation/line_functions.lua @@ -107,34 +107,10 @@ end -- Předané linevar_def musí obsahovat platný seznam 'stops', ale nemusí obsahovat nic jiného (nemusí to být platná definice). -- V případě chyby vrací nil, nil. local function get_first_last_stations(linevar_def) - local stops = assert(linevar_def.stops) - assert(stops[1]) - assert(stops[2]) -- každá definice linky musí obsahovat alespoň dvě zastávky - local i_first, i_last, i_firstx, i_lastx - for i, stop in ipairs(stops) do - local mode = stop.mode or MODE_NORMAL - if mode ~= MODE_DISABLED then - if i_first == nil then - if mode ~= MODE_HIDDEN and mode ~= MODE_FINAL_HIDDEN then - i_first = i -- první neskrytá zastávka - end - if i_firstx == nil then - i_firstx = i -- první nevypnutá zastávka (může být skrytá) - end - end - i_lastx = i - if mode == MODE_NORMAL or mode == MODE_REQUEST_STOP or mode == MODE_FINAL or mode == MODE_FINAL_CONTINUE then - i_last = i - end - if mode == MODE_FINAL or mode == MODE_FINAL_CONTINUE or mode == MODE_FINAL_HIDDEN then - break - end - end - end - if i_first ~= nil and i_last ~= nil then - return stops[i_first].stn, stops[i_last].stn - elseif i_firstx ~= nil and i_lastx ~= nil then - return stops[i_firstx].stn, stops[i_lastx].stn + local a, b = linevar_def.index_vychozi, linevar_def.index_cil + if a ~= nil and b ~= nil then + local stops = linevar_def.stops + return stops[a].stn, stops[b].stn else return nil, nil end @@ -154,7 +130,6 @@ local function line_start(train, stn, departure_rwtime) end local linevar, linevar_def = al.try_get_linevar(train.line, stn, train.routingcode) if linevar == nil or linevar_def.disabled then - -- print("DEBUG: line_start() failed for "..(train.line or "").."/"..stn.."/"..(train.routingcode or "")) return false end ls.linevar = linevar @@ -171,7 +146,6 @@ local function line_start(train, stn, departure_rwtime) last_stop_uppercase = true, train_name = true, }) - -- print("DEBUG: line_start(): "..dump2({train_id = train.id, line_status = ls})) return true end @@ -183,13 +157,11 @@ end ]] local function should_stop(pos, stdata, train) if stdata == nil or stdata.stn == nil then - -- print("DEBUG: should_stop() == false, because stdata is invalid!") return nil -- neplatná data end local n_trainparts = #assert(train.trainparts) -- vyhovuje počet vagonů? if not ((stdata.minparts or 0) <= n_trainparts and n_trainparts <= (stdata.maxparts or 128)) then - -- print("DEBUG: should_stop("..stdata.stn..") == false, because n_trainparts is not in interval") return nil end local stn = assert(stdata.stn) -- zastávka stále může být anonymní @@ -201,12 +173,10 @@ local function should_stop(pos, stdata, train) -- jde o linkový vlak? if linevar_def ~= nil then if next_index == nil then - -- print("DEBUG: should_stop("..stn..") == false, because linevar=='"..ls.linevar.."' and next_index == nil") return nil end local stop = assert(linevar_def.stops[next_index]) if stop.pos ~= nil and stop.pos ~= string.format("%d,%d,%d", pos.x, pos.y, pos.z) then - -- print("DEBUG: should_stop("..stn..") == false, because the stop is limited to position "..stop.pos) return nil end if stop.mode ~= nil and stop.mode == MODE_REQUEST_STOP then @@ -218,17 +188,7 @@ local function should_stop(pos, stdata, train) return "on_request" end end - -- print("DEBUG: should_stop("..stn..") == true for "..linevar_def.name) return "true" - -- local result = next_index ~= nil -- zastávka má index => zastavit - --[[ - if result then - print("DEBUG: should_stop() == true, because linevar=='"..ls.linevar.."' and get_line_status() retuned next_index == "..next_index) - else - print("DEBUG: should_stop() == false, because linevar=='"..ls.linevar.."' and get_line_status() retuned next_index == nil") - end - ]] - -- return result -- TODO: zastávky na znamení else local ars = stdata.ars @@ -236,10 +196,8 @@ local function should_stop(pos, stdata, train) local result = ars and (ars.default or advtrains.interlocking.ars_check_rule_match(ars, train)) if result then return "true" - -- print("DEBUG: should_stop("..stn..") == true, because linevar==nil and ARS rules match") else return nil - -- print("DEBUG: should_stop("..stn..") == false, because linevar==nil and ARS rules don't match") end end end @@ -259,7 +217,6 @@ end function al.cancel_linevar(train) local ls = train.line_status if ls == nil or ls.linevar == nil then return false end - -- print("DEBUG: line_end(train_id = "..train.id..", linevar was: "..ls.linevar.."): "..dump2({line_status_old = ls})) ls.linevar = nil ls.linevar_station = nil ls.linevar_index = nil @@ -303,6 +260,48 @@ end a) index, stop_data -- pokud byla vyhovující předchozí zastávka nalezena b) nil, nil -- pokud nalezena nebyla ]] +function al.get_first_stop(linevar_def, allow_hidden_stops) + if allow_hidden_stops then + return 1, linevar_def.stops[1] + else + local result = linevar_def.index_vychozi + if result ~= nil then + return result, linevar_def.stops[result] + else + return nil, nil + end + end +end + +--[[ + Vrací: + a) index, stop_data -- pokud byla vyhovující předchozí zastávka nalezena + b) nil, nil -- pokud nalezena nebyla +]] +function al.get_last_stop(linevar_def, allow_hidden_stops) + if allow_hidden_stops then + local stops = linevar_def.stops[result] + for i = linevar_def.index_cil, #stops do + local stop = stops[i] + local mode = stop.mode + if mode == MODE_FINAL or mode == MODE_FINAL_CONTINUE or mode == MODE_FINAL_HIDDEN then + return i, stop + end + end + else + local result = linevar_def.index_cil + if result ~= nil then + return result, linevar_def.stops[result] + end + end + return nil, nil +end + +--[[ + Vrací: + a) index, stop_data -- pokud byla vyhovující předchozí zastávka nalezena + b) nil, nil -- pokud nalezena nebyla +]] function al.get_prev_stop(linevar_def, current_index, allow_hidden_stops) local stops = assert(linevar_def.stops) assert(current_index) @@ -342,6 +341,9 @@ end b) nil, nil -- pokud nalezena nebyla ]] function al.get_terminus(linevar_def, current_index, allow_hidden_stops) + if linevar_def.index_cil ~= nil then + return linevar_def.index_cil, linevar_def.stops[linevar_def.index_cil] + end local stops = assert(linevar_def.stops) local r_i, r_stop if current_index < #stops then @@ -507,7 +509,6 @@ end -- Je-li linevar_station == nil, doplní se z linevar. Je-li linevar == nil, vrátí nil, nil. function al.try_get_linevar_def(linevar, linevar_station) if linevar == nil then - -- print("DEBUG: try_get_linevar_def() => nil, because linevar == nil") return nil, nil end if linevar_station == nil then @@ -522,11 +523,7 @@ function al.try_get_linevar_def(linevar, linevar_station) t = t.linevars if t ~= nil then return t[linevar], linevar_station - -- else - -- print("DEBUG: no linevars for linevar_station '"..linevar_station.."'") end - -- else - -- print("DEBUG: no data for linevar_station '"..linevar_station.."'") end return nil, nil end @@ -541,11 +538,9 @@ function al.try_get_linevar(line, stn, rc) local linevar = line.."/"..stn.."/"..(rc or "") local result = al.try_get_linevar_def(linevar, stn) if result ~= nil then - -- print("DEBUG: linevar combination found: "..dump2({linevar = linevar, line = line, stn = stn, rc = rc or "", linevar_def = result})) return linevar, result end end - -- print("DEBUG: linevar combination not found for "..(line or "").."/"..(stn or "").."/"..(rc or "")) return nil, nil end @@ -560,7 +555,6 @@ function al.get_line_status(train) assert(train) if train.line_status == nil then train.line_status = {} - -- print("DEBUG: new empty line_status created for train "..train.id) return train.line_status, nil end local ls = train.line_status @@ -607,7 +601,6 @@ function al.on_train_approach(pos, train_id, train, index, has_entered) local pe = advtrains.encode_pos(pos) local stdata = advtrains.lines.stops[pe] if should_stop(pos, stdata, train) ~= nil then - -- print("DEBUG: on_train_approach(): will stop at station '"..stdata.stn.."'") advtrains.lzb_add_checkpoint(train, index, 2, nil) if train.line_status.linevar == nil then -- nelinkový vlak: @@ -700,7 +693,6 @@ function al.on_train_enter(pos, train_id, train, index) end local planned_departure = rwtime + wait debug_print("Vlak "..train_id.." zastavil na "..stn.." a odjede za "..wait.." sekund ("..planned_departure..").") - -- print("DEBUG: planned departure: "..planned_departure.." = "..rwtime.." + "..wait) stdata.last_dep = planned_departure -- naplánovaný čas odjezdu stdata.last_wait = wait -- naplánovaná doba čekání ls.standing_at = pe @@ -708,20 +700,17 @@ function al.on_train_enter(pos, train_id, train, index) -- zrušit stop_request, pokud jsme nezastavili na skryté zastávce: ls.stop_request = nil end - -- print("DEBUG: standing ls = "..dump2(ls)) local can_start_line local had_linevar = linevar_def ~= nil if linevar_def == nil then -- nelinkový vlak can_start_line = true - -- print("DEBUG: train "..train_id.." is non-line train, can start a new line") elseif next_index ~= nil then -- linkový vlak zastavil na své řádné zastávce assert(stn ~= "") -- dopravna musí mít kód local stop_def = assert(linevar_def.stops[next_index]) debug_print("Vlak "..train_id.." je linkový vlak ("..ls.linevar..") a zastavil na své pravidelné zastávce "..stn.." (index = "..next_index..")") - -- print("DEBUG: train "..train_id.." stopped at regular stop '"..stn.."': "..dump2({stop_def = stop_def})) record_skipped_stops(train_id, linevar_def, ls.linevar_index, next_index) local stop_smode = simple_modes[stop_def.mode or 0] if stop_smode == MODE_NORMAL then @@ -761,7 +750,6 @@ function al.on_train_enter(pos, train_id, train, index) debug_print("Vlak "..train_id.." je linkový vlak ("..ls.linevar.."), ale zastavil na sobě neznámé zastávce "..stn..", což by se nemělo stát.") can_start_line = false end - -- print("DEBUG: "..dump2({can_start_line = can_start_line})) -- ATC příkaz local atc_command = "B0 W O"..stdata.doors..(stdata.kick and "K" or "").." D"..wait.. @@ -794,7 +782,6 @@ function al.on_train_enter(pos, train_id, train, index) train.text_inside = get_station_name(stn) -- core.after(wait, function() train.text_inside = "" end) end - -- print("DEBUG: the train will wait for "..wait.." seconds") end function al.on_train_leave(pos, train_id, train, index) @@ -812,7 +799,6 @@ function al.on_train_leave(pos, train_id, train, index) debug_print("Vlak "..train_id.." zaznamenán na odjezdu: "..stn.." "..core.pos_to_string(pos).." @ "..rwtime) end - -- print("DEBUG: *on_train_leave("..train_id..") from "..(stdata and stdata.stn or "nil")) if ls.standing_at == pe then -- vlak stál v této dopravně ls.standing_at = nil @@ -824,7 +810,6 @@ function al.on_train_leave(pos, train_id, train, index) ls.stop_request = nil -- zrušit stop_request při odjezdu ze zastávky, pokud není nekoncová skrytá end if stn ~= "" then - -- print("DEBUG: on_train_leave from non-anonymous stop") debug_print("Vlak "..train_id.." odjel ze zastávky "..stn) if ls.linevar_last_dep ~= nil and ls.linevar_last_dep > rwtime then debug_print("Vlak "..train_id.." předčasně odjel z dopravny "..stn.." (zbývalo "..(ls.linevar_last_dep - rwtime).." sekund)") @@ -834,7 +819,6 @@ function al.on_train_leave(pos, train_id, train, index) end end else - -- print("DEBUG: on_train_leave from anonymous stop") debug_print("Vlak "..train_id.." odjel z anonymní zastávky "..core.pos_to_string(pos)..".") end train.text_inside = "" @@ -874,9 +858,9 @@ function al.on_train_leave(pos, train_id, train, index) --[[ průjezd? local stn = (stdata and stdata.stn) or "" if stn ~= "" then - debug_print("DEBUG: Vlak "..train_id.." projel (odjezd) zastávkou "..stn..".") + debug_print("Vlak "..train_id.." projel (odjezd) zastávkou "..stn..".") else - debug_print("DEBUG: Vlak "..train_id.." projel (odjezd) anonymní zastávkou "..core.pos_to_string(pos)..".") + debug_print("Vlak "..train_id.." projel (odjezd) anonymní zastávkou "..core.pos_to_string(pos)..".") end ]] end @@ -912,21 +896,6 @@ function al.get_last_passages(linevar_def) end end ---[[ DEBUG: -local debug_print = {} -function debug_print.print() - print(".") - core.after(1, debug_print.print) -end -debug_print.print() -]] - ---[[ -function al.rwt_to_cas() - return -end -]] - local function get_last_pos(line_status) assert(line_status) local last_enter, last_leave, standing_at = line_status.last_enter, line_status.last_leave, line_status.standing_at @@ -983,11 +952,90 @@ local function get_train_position(line_status, linevar_def, rwtime) end --[[ +local function prepare_prediction_for_dump(result) + local x = {} + for i, record in ipairs(result) do + local y = table.copy(record) + y.stdata = record.stdata.name + if y.arr_linevar_def ~= nil then + y.arr_linevar_def = y.arr_linevar_def.name + end + if y.dep_linevar_def ~= nil then + y.dep_linevar_def = y.dep_linevar_def.name + end + x[i] = y + end + return x +end +]] + +local function predict_train_continue(line, stn, rc, departure, result) + if line == nil or line == "" then + return + end + local linevar_def = al.try_get_linevar_def(line.."/"..stn.."/"..rc, stn) + if linevar_def == nil then + return + end + if #result == 0 then + return + end + local stops = assert(linevar_def.stops) + local last_record = result[#result] + last_record.dep = departure + last_record.dep_linevar_def = linevar_def + last_record.dep_index = 1 + local index = 2 + while stops[index] ~= nil do + local stop = stops[index] + local stdata = advtrains.lines.stations[stop.stn] + if stop.mode == MODE_FINAL or stop.mode == MODE_FINAL_CONTINUE or stop.mode == MODE_FINAL_HIDDEN then + -- koncová zastávka + local arr = departure + stop.dep + local record = { + stn = assert(stop.stn), + track = stop.track or "", + stdata = stdata, + arr = arr, + arr_linevar_def = linevar_def, + arr_index = index, + delay = 0, + hidden = stop.mode == MODE_FINAL_HIDDEN, + } + table.insert(result, record) + return + elseif stop.mode ~= MODE_DISABLED then + -- mezilehlá zastávka + local dep = departure + stop.dep + table.insert(result, { + stn = assert(stop.stn), + track = stop.track or "", + stdata = stdata, + arr = dep - (stop.wait or 10), + arr_linevar_def = linevar_def, + arr_index = index, + dep = dep, + dep_linevar_def = linevar_def, + dep_index = index, + delay = 0, + hidden = stop.mode == MODE_HIDDEN, + }) + end + index = index + 1 + end +end + +--[[ Zadaný vlak musí být linkový. Vrací: - {stn = string, track = string, stdata = table or nil, dep = int or nil, arr = int or nil, delay = int} + { + stn = string, track = string, delay = int, + stdata = table or nil, + dep = int or nil, dep_linevar_def = table or nil, dep_index = int or nil, + arr = int or nil, arr_linevar_def = table or nil, arr_index = int or nil, + } ]] -function al.predict_train(line_status, linevar_def, rwtime) +function al.predict_train(line_status, linevar_def, rwtime, allow_continue) assert(line_status) assert(linevar_def) local stops = linevar_def.stops @@ -1003,6 +1051,7 @@ function al.predict_train(line_status, linevar_def, rwtime) else delay = 0 end + local departure = line_status.linevar_dep if line_status.standing_at ~= nil then -- vlak stojí na zastávce local stop = assert(stops[index]) @@ -1012,9 +1061,10 @@ function al.predict_train(line_status, linevar_def, rwtime) track = stop.track or "", stdata = stdata, dep = assert(line_status.linevar_last_dep), - -- arr = nil, + dep_linevar_def = assert(linevar_def), + dep_index = index, + -- arr = nil, arr_index = nil, arr_linevar_def = nil, delay = delay, - index = index, hidden = stop.mode == MODE_HIDDEN }) end @@ -1024,31 +1074,43 @@ function al.predict_train(line_status, linevar_def, rwtime) local stdata = advtrains.lines.stations[stop.stn] if stop.mode == MODE_FINAL or stop.mode == MODE_FINAL_CONTINUE or stop.mode == MODE_FINAL_HIDDEN then -- koncová zastávka - table.insert(result, { + local arr = departure + stop.dep + delay + local record = { stn = assert(stop.stn), track = stop.track or "", stdata = stdata, - arr = line_status.linevar_dep + stop.dep + delay, + arr = arr, + arr_linevar_def = linevar_def, + arr_index = index, delay = delay, - index = index, hidden = stop.mode == MODE_FINAL_HIDDEN, - }) + final = true, + } + table.insert(result, record) + if allow_continue and (linevar_def.continue_line or "") ~= "" and stop.mode == MODE_FINAL_CONTINUE then + predict_train_continue(linevar_def.continue_line, stop.stn, linevar_def.continue_rc, arr + (stop.wait or 10), result) + end break elseif stop.mode ~= MODE_DISABLED then -- mezilehlá zastávka + local dep = departure + stop.dep + delay table.insert(result, { stn = assert(stop.stn), track = stop.track or "", stdata = stdata, - arr = line_status.linevar_dep + stop.dep + delay, -- TODO... - dep = line_status.linevar_dep + stop.dep + delay, + arr = dep - (stop.wait or 10), + arr_linevar_def = linevar_def, + arr_index = index, + dep = dep, + dep_linevar_def = assert(linevar_def), + dep_index = index, delay = delay, - index = index, hidden = stop.mode == MODE_HIDDEN, }) end index = index + 1 end + -- print("DEBUG: "..dump2({prediction = prepare_prediction_for_dump(result)})) return result end @@ -1131,36 +1193,44 @@ def = { } core.register_chatcommand("vlaky+", def) --- DEBUG: def = { -- params = "", description = "(pro ladění)", privs = {server = true}, func = function(player_name, param) - print("----") - for linevar, passages in pairs(last_passages) do - print("LINEVAR "..linevar..":") - local linevar_def = al.try_get_linevar_def(linevar) - if linevar_def ~= nil then - local stops = linevar_def.stops - for i, passage in ipairs(passages) do - print(" Passage #"..i..":") - for j, stop in ipairs(stops) do - local s - if passage[j] ~= nil then - s = tostring(passage[j]) - else - s = "-" - end - print(" - "..stop.stn.." = "..s.." ["..j.."]") - end - end + local train = advtrains.trains[param] + if train == nil then + return false, "Vlak "..param.." nenalezen!" + end + local line_status, linevar_def = al.get_line_status(train) + if linevar_def == nil then + return false, "Vlak "..param.." není linkový!" + end + -- function al.predict_train(line_status, linevar_def, rwtime, allow_continue) + local rwtime = rwt.to_secs(rwt.get_time()) + local predictions = al.predict_train(line_status, linevar_def, rwtime, true) + local result = {"----"} + local s + for i, record in ipairs(predictions) do + local arr, dep + if record.arr ~= nil then + arr = "("..(record.arr - rwtime)..", lv="..record.arr_linevar_def.name..", i="..record.arr_index..")" + else + arr = "nil" + end + if record.dep ~= nil then + dep = "("..(record.dep - rwtime)..", lv="..record.dep_linevar_def.name..", i="..record.dep_index..")" else - print("ERROR! definition not found") + dep = "nil" end + result[i + 1] = "- "..record.stn.." ["..record.track.."] arr="..arr.." dep="..dep.." delay="..record.delay end - print("----") + table.insert(result, "----") + s = table.concat(result, "\n") + print(s) + core.chat_send_player(player_name, s) return true end, } -core.register_chatcommand("odjezdy", def) +core.register_chatcommand("jřád", def) +core.register_chatcommand("jrad", def) diff --git a/advtrains_line_automation/models/advtrains_tuber.obj b/advtrains_line_automation/models/advtrains_tuber.obj index 25bc6dc..c93ce3e 100644 --- a/advtrains_line_automation/models/advtrains_tuber.obj +++ b/advtrains_line_automation/models/advtrains_tuber.obj @@ -2,46 +2,46 @@ # www.blender.org mtllib underch_dark_tuber.mtl o Cube -v 0.136329 -0.157988 0.702133 -v 0.136329 0.157988 0.702133 -v -0.136329 0.157988 0.702133 -v -0.136329 -0.157988 0.702133 -v 0.368861 -0.368861 -0.337695 -v 0.368861 0.368862 -0.466279 -v -0.381520 0.360664 -0.354918 -v -0.368861 -0.368861 -0.057503 -v 0.223277 -0.225624 0.028756 -v 0.216947 0.221525 0.018022 -v -0.262021 0.200536 -0.023957 -v -0.229606 -0.229722 0.156757 -v 0.100830 -0.108796 0.403707 -v 0.100830 0.108796 0.432070 -v -0.117708 0.097867 0.380743 -v -0.100830 -0.108796 0.439469 -v 0.264026 -0.267600 0.054980 -v 0.264026 0.267600 -0.003499 -v -0.264026 0.267600 0.054980 -v -0.264026 -0.267600 0.211890 -v 0.000000 -0.157988 0.702133 -v 0.000000 -0.461012 -0.167161 -v 0.000000 -0.263640 0.098449 -v 0.000000 -0.131624 0.421588 -v 0.000000 -0.316408 0.141084 -v -0.000000 0.157988 0.702133 -v -0.006330 0.456914 -0.441037 -v -0.025702 0.246997 -0.008661 -v -0.008439 0.126160 0.406407 -v -0.000000 0.316408 0.018092 -v -0.136329 -0.000000 0.702133 -v -0.467342 -0.004099 -0.175772 -v -0.286994 -0.016643 0.063482 -v -0.128968 -0.005465 0.410106 -v -0.312834 -0.000000 0.141084 -v 0.136329 0.000000 0.702133 -v 0.461012 0.000000 -0.432425 -v 0.261292 0.000000 0.026307 -v 0.120528 0.000000 0.417888 -v 0.312834 0.000000 0.018092 +v 0.068165 0.171006 0.601066 +v 0.068165 0.328994 0.601066 +v -0.068165 0.328994 0.601066 +v -0.068165 0.171006 0.601066 +v 0.184430 0.065570 0.081152 +v 0.184430 0.434431 0.016861 +v -0.190760 0.430332 0.072541 +v -0.184430 0.065570 0.221249 +v 0.111639 0.137188 0.264378 +v 0.108474 0.360762 0.259011 +v -0.131011 0.350268 0.238021 +v -0.114803 0.135139 0.328379 +v 0.050415 0.195602 0.451854 +v 0.050415 0.304398 0.466035 +v -0.058854 0.298933 0.440372 +v -0.050415 0.195602 0.469734 +v 0.132013 0.116200 0.277490 +v 0.132013 0.383800 0.248250 +v -0.132013 0.383800 0.277490 +v -0.132013 0.116200 0.355945 +v 0.000000 0.171006 0.601066 +v 0.000000 0.019494 0.166419 +v 0.000000 0.118180 0.299225 +v 0.000000 0.184188 0.460794 +v 0.000000 0.091796 0.320542 +v -0.000000 0.328994 0.601066 +v -0.003165 0.478457 0.029481 +v -0.012851 0.373499 0.245669 +v -0.004220 0.313080 0.453203 +v -0.000000 0.408204 0.259046 +v -0.068165 0.250000 0.601066 +v -0.233671 0.247951 0.162114 +v -0.143497 0.241679 0.281741 +v -0.064484 0.247267 0.455053 +v -0.156417 0.250000 0.320542 +v 0.068165 0.250000 0.601066 +v 0.230506 0.250000 0.033787 +v 0.130646 0.250000 0.263154 +v 0.060264 0.250000 0.458944 +v 0.156417 0.250000 0.259046 vt 1.000000 1.000000 vt 0.937500 1.000000 vt 0.875000 1.000000 diff --git a/advtrains_line_automation/models/license.txt b/advtrains_line_automation/models/license.txt index dae06a8..c76bd96 100644 --- a/advtrains_line_automation/models/license.txt +++ b/advtrains_line_automation/models/license.txt @@ -1,5 +1,5 @@ advtrains_tuber.obj Author: Hume2 Source: https://gitlab.com/h2mm/underch underch_dark_tuber.obj (Underground Challenge) - Modified (rotated) + Modified (rotated, scaled) License: CC0 diff --git a/advtrains_line_automation/station_announcement.lua b/advtrains_line_automation/station_announcement.lua index d465fd5..4f2e8fb 100644 --- a/advtrains_line_automation/station_announcement.lua +++ b/advtrains_line_automation/station_announcement.lua @@ -10,6 +10,10 @@ local has_signs_api = core.get_modpath("signs_api") local has_unifieddyes = core.get_modpath("unifieddyes") local rozhlas_node_name = "advtrains_line_automation:stanicni_rozhlas_experimental" +local RMODE_DEP = 1 +local RMODE_ARR = 2 +local RMODE_BOTH = 3 + local PAGE_SETUP_1 = 1 local PAGE_SETUP_2 = 2 local PAGE_IMPORT = 3 @@ -229,7 +233,6 @@ local function dosadit(format, data, defaults) success, min, max, align = lengths_from_string(tagfmt) end tag = tag_name - -- print("DEBUG: tag("..tag..") tagname("..tag_name..")") if tag:len() < 4 and ch_core.utf8_length(tag) == 1 and alphanum_chars_set[tag] == nil then -- speciální případ: zopakovat znak alespoň min-krát if min ~= nil then @@ -416,7 +419,6 @@ local function init_ann_data(stn, epos) version = 1, } anns[epos] = result - -- print("DEBUG: ann data initialized for '"..stn.."'/"..epos..": "..dump2(result)) return result end @@ -608,9 +610,12 @@ local function get_setup_formspec(custom_state) "label[7,0.5;omezit jen na koleje:]".. "field[10,0.2;4,0.6;koleje;;", data.fs_koleje or "", - "]container_end[]", + "]label[0,1.25;režim:]".. + "dropdown[1.75,1;3,0.6;rmode;odjezdy,příjezdy,odjezdy i příjezdy;", + tostring(data.rmode), + ";true]container_end[]", -- ---- - "container[0.5,2.75]".. + "container[0.5,3.25]".. "checkbox[0,0.25;fn_firstupper;první písmeno řádky odjezdu vždy velké;", ifthenelse(ifthenelse(custom_state.fn_firstupper ~= nil, custom_state.fn_firstupper, data.fn_firstupper), "true", "false"), "]field[0,1;3.25,0.75;fmt_nodelay;bez zpoždění;", F(data.fmt_nodelay or ""), "]".. @@ -732,7 +737,6 @@ local function get_setup_formspec(custom_state) end local function setup_formspec_callback(custom_state, player, formname, fields) - -- print("DEBUG: setup_formspec_callback(): "..dump2({custom_state = custom_state, fields = fields, player_name = custom_state.player_name})) assert(player:get_player_name() == custom_state.player_name) local node = core.get_node(custom_state.pos) if node.name ~= rozhlas_node_name then @@ -753,6 +757,12 @@ local function setup_formspec_callback(custom_state, player, formname, fields) -- přepnout dopravnu custom_state.station_index = tonumber(fields.dopravna) end + if fields.rmode then + local new_rmode = tonumber(fields.rmode) + if new_rmode ~= nil and new_rmode ~= data.rmode then + data.rmode = new_rmode + end + end -- zaškrtávací pole: if fields.fn_firstupper then @@ -831,6 +841,14 @@ local function setup_formspec_callback(custom_state, player, formname, fields) end set_ann_data(stn, custom_state.epos, data) custom_state.data = get_ann_data(stn, custom_state.epos, true) + -- update infotext: + local meta = core.get_meta(custom_state.pos) + local station_name = al.get_station_name(meta:get_string("stn")) + local koleje = custom_state.data.fs_koleje + if koleje ~= "" then + koleje = " ["..koleje:gsub("\\", "").."]" + end + meta:set_string("infotext", "staniční rozhlas\n"..station_name..koleje) end elseif page == PAGE_SETUP_2 then -- update fields: @@ -856,7 +874,6 @@ local function setup_formspec_callback(custom_state, player, formname, fields) new_cedule[i] = table.copy(data.cedule[i]) end get_ann_data(stn, custom_state.epos, false).cedule = new_cedule - -- print("DEBUG: new_cedule saved, ann_data = "..dump2(get_ann_data(stn, custom_state.epos, false))) return get_setup_formspec(custom_state) else for i = 1, 4 do @@ -949,65 +966,123 @@ end local debug_counter = 0 -local function update_ann(stn, epos, signs, deps, rwtime) - -- print("DEBUG: update_ann(): "..dump2({stn = stn, epos = epos, signs = signs, deps = deps, rwtime = rwtime})) +local function fill(line, prefix, rwtime_now, rwtime_value) + if rwtime_value == nil then + return + end + local secs = math.ceil((rwtime_value - rwtime_now) / 5) * 5 + if secs < 0 then + secs = -secs + line[prefix.."_Z"] = "-" + end + local n_s = secs % 60 + local n_m = (secs - n_s) / 60 + local s = tostring(n_s) + local m = tostring(n_m) + line[prefix] = tostring(secs) + line[prefix.."_M"] = m + line[prefix.."_S"] = s + if n_m < 10 then + line[prefix.."_MM"] = "0"..m + else + line[prefix.."_MM"] = m + end + if n_s < 10 then + line[prefix.."_SS"] = "0"..s + else + line[prefix.."_SS"] = s + end +end + +--[[ + records je tabulka záznamů z al.predict_train(), doplněných o následující pole: + start = string or nil, -- název výchozí zastávky, pokud vlak odněkud přijíždí, jinak "" + destination = string, -- název cílové zastávky, pokud vlak někam pokračuje, jinak "" + prev_stop = string, -- název předchozí zastávky, pokud vlak odněkud přijíždí a pokud jde o jinou zastávku než 'start', jinak "" + next_stop = string, -- název násl. zast., pokud vlak pokračuje a pokud jde o jinou zastávku než 'destination', jinak "" + last_pos = string, -- název poslední známé polohy vlaku, nebo "" + -- + stn = string, track = string, delay = int, + stdata = table or nil, + dep = int or nil, dep_linevar_def = table or nil, dep_index = int or nil, + arr = int or nil, arr_linevar_def = table or nil, arr_index = int or nil, +]] + +local function update_ann(stn, epos, signs, records, rwtime) local ann = get_ann_data(stn, epos) if ann == nil then core.log("error", "update_ann() called for "..stn.."/"..epos..", but ann is nil!") return end - local tracks = ann.koleje - if tracks ~= nil and type(tracks) ~= "table" then - if tracks == "" then - tracks = nil - else - tracks = {[tracks] = true} - end - end + local tracks local any_line = { - KOLEJE = "TODO", -- [ ] TODO ZDE = al.get_station_name(stn), } - -- print("DEBUG: "..dump2({tracks = tracks})) + if ann.fs_koleje ~= "" then + any_line.KOLEJE = ann.fs_koleje:gsub("\\", "") + tracks = ann.koleje + if tracks ~= nil and type(tracks) ~= "table" then + if tracks == "" then + tracks = nil + else + tracks = {[tracks] = true} + end + end + end local lines = {} - -- update_ann(assert(stn), assert(ann.rozh_epos), signs, deps) - for _, dep in ipairs(deps) do - if (tracks == nil or tracks[dep.track]) and (dep.dep == nil or dep.dep > rwtime) then - local linevar_def = dep.linevar_def + for _, record in ipairs(records) do + assert(record.start ~= nil) + assert(record.destination ~= nil) + assert(record.prev_stop ~= nil) + assert(record.next_stop ~= nil) + assert(record.last_pos ~= nil) + if + (tracks == nil or tracks[record.track]) and ( + (ann.rmode == RMODE_ARR and record.arr ~= nil) or + (ann.rmode == RMODE_DEP and record.dep ~= nil) or + (ann.rmode == RMODE_BOTH and (record.arr ~= nil or record.dep ~= nil)) + ) + then + local linevar_def, index + if record.dep ~= nil then + linevar_def, index = record.dep_linevar_def, record.dep_index + else + linevar_def, index = record.arr_linevar_def, record.arr_index + end local stops = linevar_def.stops local line = setmetatable({}, {__index = any_line}) line.LINKA = linevar_def.line or "" - line.VYCHOZI = al.get_line_description(linevar_def, {line_number = false, first_stop = true, last_stop = false}) - line.CIL = dep.destination - if dep.track ~= "" then - line.KOLEJ = dep.track + if record.start ~= "" then + line.VYCHOZI = record.start end - if dep.arr ~= nil then - line.PRIJZA = math.ceil((dep.arr - rwtime) / 5) * 5 + if record.destination ~= "" then + line.CIL = record.destination end - if dep.dep ~= nil then - line.ODJZA = math.ceil((dep.dep - rwtime) / 5) * 5 + if record.track ~= "" then + line.KOLEJ = record.track end - local abs_delay = math.abs(dep.delay) + fill(line, "PRIJZA", rwtime, record.arr) + fill(line, "ODJZA", rwtime, record.dep) + local abs_delay = math.abs(record.delay) if abs_delay < 5 then line.ZPOZDENI = ann.fmt_nodelay or "" else line.ZPOZDENI = dosadit( - ifthenelse(dep.delay > 0, ann.fmt_delay or "{}", ann.fmt_negdelay or "-{}"), + ifthenelse(record.delay > 0, ann.fmt_delay or "{}", ann.fmt_negdelay or "-{}"), {[""] = tostring(5 * math.ceil(abs_delay / 5))} ) end -- PREDCH - if dep.prev_stop ~= nil then - line.PREDCH = dep.prev_stop + if record.prev_stop ~= "" then + line.PREDCH = record.prev_stop end -- NASL - if dep.next_stop ~= nil then - line.NASL = dep.next_stop + if record.next_stop ~= "" then + line.NASL = record.next_stop end -- POLOHA - if dep.last_pos ~= nil then - line.POLOHA = dep.last_pos + if record.last_pos ~= "" then + line.POLOHA = record.last_pos end -- JMVLAKU if linevar_def.train_name ~= nil then @@ -1063,6 +1138,64 @@ local function update_ann(stn, epos, signs, deps, rwtime) end local globalstep_time = -5 +local first_run = true + +local function first_globalstep() + for stn, stdata in pairs(advtrains.lines.stations) do + local anns = stdata.anns + if stdata.anns ~= nil then + for rozh_epos, ann in pairs(stdata.anns) do + if ann.version < 2 then + if ann.version == 1 then + -- upgrade version 1 to version 2: + ann.rmode = RMODE_DEP + ann.version = 2 + end + end + end + end + end +end + +local function get_start_by_linevar_def(cache, linevar_def) + local result = cache[linevar_def.name] + if result == nil then + result = al.get_line_description(linevar_def, {first_stop = true, last_stop = false, last_stop_prefix = ""}) + if result == "???" then + result = "" + end + cache[linevar_def.name] = result + end + return result +end + +local function get_destination_by_linevar_def(cache, linevar_def) + local result = cache[linevar_def.name] + if result == nil then + result = al.get_line_description(linevar_def, {first_stop = false, last_stop = true, last_stop_prefix = ""}) + if result == "???" then + result = "" + end + cache[linevar_def.name] = result + end + return result +end + +local function get_name_by_stn(cache, stn, alt) + local result = cache[stn] + if result == nil then + result = al.get_station_name(stn) + if result == "???" then + result = "" + end + cache[stn] = result + end + if result == "" then + return alt + else + return result + end +end local function globalstep(dtime) globalstep_time = globalstep_time + dtime @@ -1071,7 +1204,13 @@ local function globalstep(dtime) end globalstep_time = globalstep_time - 5 + if first_run then + first_run = false + return first_globalstep() + end + local rwtime = rwt.to_secs(rwt.get_time()) + local rwtime_limit = rwtime + 3600 -- Shromáždit rozhlasy: local subscriptions = {--[[ [stn] = {{ @@ -1101,65 +1240,127 @@ local function globalstep(dtime) end if signs_count > 0 then -- nějaké cedule jsou aktivní - -- print("DEBUG: - "..rozh_epos.." : added ("..stn.."), because has "..signs_count.." active signs") table.insert(goa(subscriptions, stn), {rozh_pos = rozh_pos, rozh_epos = rozh_epos, rozh_def = ann, signs = signs}) signs = {} elseif core.compare_block_status(rozh_pos, "active") then -- cedule nejsou aktivní, ale rozhlas ano - -- print("DEBUG: - "..rozh_epos.." : added ("..stn.."), because is active") table.insert(goa(subscriptions, stn), {rozh_pos = rozh_pos, rozh_epos = rozh_epos, rozh_def = ann}) end end - else - -- print("DEBUG: - "..stn.." not added (anns: "..ifthenelse(stdata.anns == nil, "nil", "non-nil")..")") end end -- Shromáždit vlaky: - local deps_by_stn = {} + local by_stn = {} for stn, _ in pairs(subscriptions) do - deps_by_stn[stn] = {} + by_stn[stn] = {} end + local start_by_linevar = {} + local destination_by_linevar = {} + local name_by_stn = {} + for _, train in pairs(advtrains.trains) do local ls, linevar_def = al.get_line_status(train) if linevar_def ~= nil then - local prediction = al.predict_train(ls, linevar_def, rwtime) - local last_pos = al.get_last_pos_station_name(ls) - local destination = "???" - for i = #prediction, 1, -1 do - local p = prediction[i] - if not p.hidden then - destination = al.get_station_name(p.stn) - break - end - end - for _, record in ipairs(prediction) do - local deps = deps_by_stn[record.stn] - if deps ~= nil and record.dep ~= nil then - local record_index = assert(record.index) - local other_index, other_data = al.get_prev_stop(linevar_def, record_index, false) - if other_index ~= nil then - record.prev_stop = al.get_station_name(other_data.stn) - end - other_index, other_data = al.get_next_stop(linevar_def, record_index, false) - if other_index ~= nil then - record.next_stop = al.get_station_name(other_data.stn) - end + local prediction = al.predict_train(ls, linevar_def, rwtime, true) + local last_pos = al.get_last_pos_station_name(ls) or "" + for i, record in ipairs(prediction) do + local records = by_stn[record.stn] + if + records ~= nil and + (record.dep ~= nil or record.arr ~= nil) and + (record.dep == nil or record.dep < rwtime_limit) and + (record.arr == nil or record.arr < rwtime_limit) + then + -- nutno doplnit: start, destination, prev_stop, next_stop, last_pos record.last_pos = last_pos -- název poslední dopravny, kde byl vlak spatřen - record.linevar = linevar_def.name - record.linevar_def = linevar_def - record.destination = destination - table.insert(deps, record) + if record.final and record.arr ~= nil and record.dep ~= nil and record.arr_linevar_def.name ~= record.dep_linevar_def.name then + -- změna linky => rozdělit na příjezd a odjezd + local record2 = table.copy(record) + record2.dep = nil + record2.dep_linevar_def = nil + record2.dep_index = nil + record2.start = get_start_by_linevar_def(start_by_linevar, record.arr_linevar_def) + local other_index, other_data = al.get_prev_stop(record.arr_linevar_def, record.arr_index, false) + if other_index ~= nil then + record2.prev_stop = get_name_by_stn(name_by_stn, other_data.stn, "") + end + record2.next_stop = "" + record2.destination = get_destination_by_linevar_def(destination_by_linevar, record.arr_linevar_def) + table.insert(records, record2) + record.arr = nil + record.arr_linevar_def = nil + record.arr_index = nil + record.start = get_start_by_linevar_def(start_by_linevar, record.dep_linevar_def) + record.prev_stop = "" + other_index, other_data = al.get_next_stop(record.dep_linevar_def, record.dep_index, false) + if other_index ~= nil then + record.next_stop = get_name_by_stn(name_by_stn, other_data.stn, "") + end + record.destination = get_destination_by_linevar_def(destination_by_linevar, record.dep_linevar_def) + table.insert(records, record) + elseif record.dep ~= nil then + -- odjezd nebo příjezd/odjezd (ale na stejné lince!) + local linevar_def = record.dep_linevar_def + local index = record.dep_index + record.start = get_start_by_linevar_def(start_by_linevar, linevar_def) + record.destination = get_destination_by_linevar_def(destination_by_linevar, linevar_def) + record.prev_stop = "" + record.next_stop = "" + local other_index, other_data + if record.arr ~= nil then + other_index, other_data = al.get_prev_stop(linevar_def, index, false) + if other_index ~= nil then + record.prev_stop = get_name_by_stn(name_by_stn, other_data.stn, "") + end + end + other_index, other_data = al.get_next_stop(linevar_def, index, false) + if other_index ~= nil then + record.next_stop = get_name_by_stn(name_by_stn, other_data.stn, "") + end + record.destination = get_destination_by_linevar_def(destination_by_linevar, linevar_def) + table.insert(records, record) + elseif record.arr ~= nil then + -- jen příjezd + local linevar_def = record.arr_linevar_def + local index = record.arr_index + record.start = get_start_by_linevar_def(start_by_linevar, linevar_def) + local other_index, other_data = al.get_prev_stop(linevar_def, index, false) + if other_index ~= nil then + record.prev_stop = get_name_by_stn(name_by_stn, other_data.stn, "") + else + record.prev_stop = "" + end + record.next_stop = "" + record.destination = get_destination_by_linevar_def(destination_by_linevar, linevar_def) + table.insert(records, record) + end end end end end -- Aktualizovat rozhlasy: - for stn, deps in pairs(deps_by_stn) do - table.sort(deps, function(a, b) return assert(a.dep) < assert(b.dep) end) + for stn, records in pairs(by_stn) do + local deps = records + local arrs = table.copy(records) + table.sort(deps, function(a, b) + return assert(a.dep or a.arr) < assert(b.dep or b.arr) + end) + table.sort(arrs, function(a, b) + return (a.arr or 1.0e+100) < (b.arr or 1.0e+100) + end) + for i = #arrs, 1, -1 do + if arrs[i].arr == nil then + arrs[i] = nil -- ponechat jen příjezdy v rámci nejbližší hodiny + end + end for _, ann in ipairs(subscriptions[stn]) do - update_ann(assert(stn), assert(ann.rozh_epos), ann.signs, deps, rwtime) + if ann.rmode ~= RMODE_ARR then + update_ann(assert(stn), assert(ann.rozh_epos), ann.signs, deps, rwtime) + else + update_ann(assert(stn), assert(ann.rozh_epos), ann.signs, arrs, rwtime) + end end end end @@ -1324,8 +1525,8 @@ end local box = { type = "fixed", fixed = { - {-0.25, -0.25, 0, 0.25, 0.25, 0.5}, - {-0.5, -0.4, -0.25, 0.5, 0.4, 0}, + {-0.125, 0.125, 0.25, 0.125, 0.5, 0.5}, + {-0.25, 0.05, 0, 0.25, 0.45, 0.25}, }, } diff --git a/advtrains_line_automation/structs.md b/advtrains_line_automation/structs.md index c6f128a..68a759e 100644 --- a/advtrains_line_automation/structs.md +++ b/advtrains_line_automation/structs.md @@ -78,6 +78,19 @@ station = { -- je-li true, nové vlaky nemohou dostat tuto variantu přidělenu disabled = bool or nil, + -- je-li neprázdný řetězec, udává označení linky, na kterou bude vlak pravděpodobně pokračovat + -- ze zastávky v režimu MODE_FINAL_CONTINUE + continue_line = string or nil, + + -- je-li continue_line neprázdný řetězec, udává směrový kód pro pokračování + continue_rc = string or nil, + + -- index zobrazované výchozí zastávky v poli 'stops'; nil značí, že taková zastávka nebyla nalezena + index_vychozi = int or nil, + + -- index zobrazované cílové zastávky v poli 'stops'; nil značí, že taková zastávka nebyla nalezena + index_cil = int or nil, + -- seznam zastávek na lince, seřazený podle 'dep': stops = { { @@ -87,6 +100,11 @@ station = { -- plánovaný čas odjezdu, relativně vůči odjezdu z výchozí zastávky (v sekundách) dep = int, + -- předpokládaný čas stání před časem odjezdu (používá se k zjištění času příjezdu) + -- je-li nil, počítá se 10 sekund + -- výjimka: pro koncové zastávky udává předpokládanou dobu stání po čase 'dep' + wait = int or nil, + -- režim zastávky (podle konstant ve zdrojovém kódu) -- nil odpovídá 0 (normální zastavení) mode = int or nil, @@ -141,6 +159,9 @@ station = { -- je-li omezen na více kolejí, pak jde o množinu indexovanou označeními kolejí koleje = {[string] = true, ...} or string or nil, + -- režim rozhlasu (RMODE_*) + rmode = int, + -- číslo verze systému staničního rozhlasu (pro detekci zastaralých rozhlasů) version = int, |