aboutsummaryrefslogtreecommitdiff
path: root/advtrains_line_automation/line_editor.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains_line_automation/line_editor.lua')
-rw-r--r--advtrains_line_automation/line_editor.lua856
1 files changed, 856 insertions, 0 deletions
diff --git a/advtrains_line_automation/line_editor.lua b/advtrains_line_automation/line_editor.lua
new file mode 100644
index 0000000..33686d1
--- /dev/null
+++ b/advtrains_line_automation/line_editor.lua
@@ -0,0 +1,856 @@
+local def
+local F = minetest.formspec_escape
+local ifthenelse = function(cond, a, b) if cond then return a else return b end end
+
+local max_stations = 60
+
+local MODE_NORMAL = 0 -- normální zastávka (výchozí nebo mezilehlá)
+local MODE_REQUEST_STOP = 1 -- zastávka na znamení (mezilehlá)
+local MODE_HIDDEN = 2 -- skrytá zastávka (výchozí nebo mezilehlá)
+local MODE_DISABLED = 3 -- vypnutá zastávka (mezilehlá nebo koncová)
+local MODE_FINAL = 4 -- koncová zastávka (linka zde jízdu končí)
+local MODE_FINAL_HIDDEN = 5 -- koncová zastávka skrytá
+local MODE_FINAL_CONTINUE = 6 -- koncová zastávka (vlak pokračuje jako jiná linka)
+
+local color_red = core.get_color_escape_sequence("#ff0000")
+local color_green = core.get_color_escape_sequence("#00ff00")
+
+local cancel_linevar = assert(advtrains.lines.cancel_linevar)
+local get_last_passages = assert(advtrains.lines.get_last_passages)
+local get_line_description = assert(advtrains.lines.get_line_description)
+local linevar_decompose = assert(advtrains.lines.linevar_decompose)
+local try_get_linevar_def = assert(advtrains.lines.try_get_linevar_def)
+
+local show_last_passages_formspec -- forward declaration
+
+local function check_rights(pinfo, owner)
+ if pinfo.role == "new" or pinfo.role == "none" then
+ return false
+ end
+ if owner == nil or pinfo.role == "admin" or pinfo.player_name == owner then
+ return true
+ end
+ return false
+end
+
+local function get_stn_from_linevar(linevar)
+ local line, stn = linevar_decompose(linevar)
+ return ifthenelse(line ~= nil, stn, nil)
+end
+
+local function add_linevar(stn, linevar_def)
+ local station = advtrains.lines.stations[stn]
+ if station == nil then
+ return false, "Chybná stanice!"
+ end
+ local linevars = station.linevars
+ if linevars == nil then
+ linevars = {}
+ station.linevars = linevars
+ end
+ if linevars[linevar_def.name] ~= nil then
+ return false, "Nemohu přidat, varianta linky '"..linevar_def.name.."' již existuje."
+ end
+ linevars[linevar_def.name] = linevar_def
+ return true, nil
+end
+
+local function same_stops(stops1, stops2)
+ assert(stops1)
+ assert(stops2)
+ if #stops1 ~= #stops2 then
+ return false
+ end
+ for i, stop in ipairs(stops1) do
+ if stop.stn ~= stops2[i].stn then
+ return false
+ end
+ end
+ return true
+end
+
+local function replace_linevar(stn, linevar_def)
+ local station = advtrains.lines.stations[stn]
+ if station == nil or station.linevars == nil then
+ return false, "Chybná stanice!"
+ end
+ local linevar = assert(linevar_def.name)
+ local linevars = station.linevars
+ local old_linevar_def = linevars[linevar]
+ if old_linevar_def == nil then
+ return false, "Nemohu nahradit, varianta linky '"..linevar.."' dosud neexistuje!"
+ end
+ linevars[linevar] = linevar_def
+ local restart_count = 0
+ if not same_stops(old_linevar_def.stops, linevar_def.stops) then
+ -- změnily se zastávky, musíme restartovat vlaky:
+ for train_id, train in pairs(advtrains.trains) do
+ local ls = train.line_status
+ if ls ~= nil and ls.linevar == linevar then
+ core.log("action", "Train "..train_id.." restarted from index "..ls.linevar_index.." due to replacement of linevar '"..linevar.."'.")
+ ls.linevar_index = 1
+ restart_count = restart_count + 1
+ end
+ end
+ end
+ if restart_count > 0 then
+ return true, restart_count.." vlak/ů restartován/o kvůli změnám"
+ else
+ return true, nil
+ end
+end
+
+local function delete_linevar(stn, linevar)
+ local station = advtrains.lines.stations[stn]
+ if station == nil or station.linevars == nil then
+ return false, "Chybná stanice!"
+ end
+ local linevars = station.linevars
+ if linevars[assert(linevar)] == nil then
+ return false, "Nemohu odstranit, varianta linky '"..linevar.."' nebyla nalezena!"
+ end
+ linevars[linevar] = nil
+ for train_id, train in pairs(advtrains.trains) do
+ local ls = train.line_status
+ if ls ~= nil and ls.linevar == linevar then
+ core.log("action", "Train "..train_id.." removed from deleted linevar '"..linevar.."'.")
+ cancel_linevar(train)
+ end
+ end
+ return true, nil
+end
+
+local function get_formspec(custom_state)
+ local pinfo = ch_core.normalize_player(assert(custom_state.player_name))
+ if pinfo.player == nil then
+ minetest.log("error", "Expected player not in game!")
+ return ""
+ end
+
+ local selection_index_raw = custom_state.selection_index
+ local selection_index = selection_index_raw or 1
+ local formspec = {
+ ch_core.formspec_header({formspec_version = 6, size = {20, 16}, auto_background = true}),
+ "label[0.5,0.6;Editor variant linek]"..
+ "style[s01_pos",
+ }
+ for i = 2, max_stations do
+ table.insert(formspec, string.format(",s%02d_pos", i))
+ end
+ table.insert(formspec, ";font=mono;font_size=-4]"..
+ "style[rc;font=mono]"..
+ "tablecolumns[color;text,align=right;text;text,align=center;color;text,width=7;color;text]"..
+ "table[0.5,1.25;19,5;linevar;#ffffff,LINKA,TRASA,SM. KÓD,#ffffff,SPRAVUJE,#ffffff,STAV")
+
+ for _, linevar_def in ipairs(custom_state.linevars) do
+ local lv_line, lv_stn, lv_rc = linevar_decompose(linevar_def.name)
+ local color = ifthenelse(linevar_def.disabled, "#cccccc", "#ffffff")
+ table.insert(formspec,
+ ","..color..","..F(lv_line)..","..F(get_line_description(linevar_def, {first_stop = true, last_stop = true}))..
+ ","..F(lv_rc)..","..ifthenelse(linevar_def.owner == pinfo.player_name, "#00ff00", color)..",")
+ table.insert(formspec, F(ch_core.prihlasovaci_na_zobrazovaci(linevar_def.owner)))
+ table.insert(formspec, ","..color..",")
+ if linevar_def.disabled then
+ table.insert(formspec, "vypnutá")
+ end
+ end
+ if selection_index_raw ~= nil then
+ table.insert(formspec, ";"..selection_index.."]")
+ else
+ table.insert(formspec, ";]")
+ end
+ if pinfo.role ~= "new" then
+ table.insert(formspec, "button[14.5,0.3;3.5,0.75;create;nová varianta...]")
+ end
+ local has_rights_to_open_variant =
+ pinfo.role == "admin" or selection_index == 1 or
+ pinfo.player_name == custom_state.linevars[selection_index - 1].owner
+
+ if selection_index > 1 and has_rights_to_open_variant then
+ table.insert(formspec, "button[10.5,0.3;3.5,0.75;delete;smazat variantu]")
+ end
+ table.insert(formspec, "button_exit[18.75,0.3;0.75,0.75;close;X]"..
+ "field[0.5,7;1.25,0.75;line;linka:;"..F(custom_state.line).."]"..
+ "field[2,7;1.5,0.75;rc;sm.kód:;"..F(custom_state.rc).."]"..
+ "field[3.75,7;3,0.75;train_name;jméno vlaku:;"..F(custom_state.train_name).."]")
+ if pinfo.role ~= "admin" then
+ table.insert(formspec, "label[7,6.75;spravuje:\n")
+ else
+ 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.."]"..
+ "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).."]")
+ end
+ if selection_index > 1 then
+ table.insert(formspec, "button[5,15;4.5,0.75;last_passages;poslední jízdy...]"..
+ "tooltip[last_passages;Zobrazí přehled časů několika posledních jízd na dané variantě linky.]")
+ end
+ if has_rights_to_open_variant then
+ table.insert(formspec, "button[10,15;4.5,0.75;save;"..
+ ifthenelse(custom_state.compiled_linevar == nil, "ověřit změny\npřed uložením]", "uložit změny]"))
+ end
+ table.insert(formspec, "button[15,15.25;4,0.5;reset;vrátit změny]")
+ table.insert(formspec, "tooltip[line;"..
+ "Označení linky. Musí být neprázdné. Varianta linky bude použita pouze na vlaky s tímto označením linky.]"..
+ "tooltip[rc;Směrový kód. Může být prázdný. Varianta linky bude použita pouze na vlaky\\,\n"..
+ "jejichž směrový kód se přesně shoduje se zadaným. Obvykle se toto pole nechává prázdné.]"..
+ "tooltip[train_name;Volitelný údaj. Je-li zadán\\, jízdní řády budou uvádět u spojů této\n"..
+ "varianty zadané jméno.]"..
+ "tooltip[disable_linevar;Zaškrtnutím variantu linky vypnete. Vypnutá varianta linky není používána\n"..
+ "na žádné další vlaky\\, stávající vlaky však mohou dojet do svých koncových zastávek.]")
+
+ table.insert(formspec, "container[0,8.75]"..
+ "label[0.5,0.25;odjezd]"..
+ "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]"..
+ "box[0,0;20,70;#00808040]") -- box[] = pozadí
+
+ -- výchozí zastávka:
+ table.insert(formspec,
+ "label[0.1,0.4;0]"..
+ "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
+ for i = 2, max_stations do
+ local stop = custom_state.stops[i]
+ local n
+ if i < 10 then
+ n = "0"..i
+ else
+ n = tostring(i)
+ end
+ local y = string.format("%f", y_base + (i - 1) * y_scale)
+ 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..";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[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;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[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[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[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[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[]")
+
+ -- if pinfo.role ~= "new" then
+ return table.concat(formspec)
+end
+
+local mode_from_formspec_map = {MODE_NORMAL, MODE_REQUEST_STOP, MODE_HIDDEN, MODE_DISABLED, MODE_FINAL, MODE_FINAL_HIDDEN, MODE_FINAL_CONTINUE}
+local mode_to_formspec_map = table.key_value_swap(mode_from_formspec_map)
+
+local function mode_to_formspec(i, raw_mode)
+ if i == 1 then
+ return ifthenelse(raw_mode ~= nil and raw_mode == MODE_HIDDEN, 2, 1)
+ elseif raw_mode == nil then
+ return 1
+ else
+ return mode_to_formspec_map[raw_mode] or 1
+ end
+end
+
+local function mode_from_formspec(i, fs_mode)
+ if i == 1 then
+ return ifthenelse(fs_mode == 2, MODE_HIDDEN, nil)
+ else
+ local result = mode_from_formspec_map[fs_mode]
+ return ifthenelse(result ~= nil and result ~= MODE_NORMAL, result, nil)
+ end
+end
+
+local function custom_state_set_selection_index(custom_state, new_selection_index)
+ -- this will also refresh stops and resets the changes
+ assert(custom_state.player_name)
+ assert(custom_state.linevars)
+ assert(new_selection_index)
+ local current_linevar = custom_state.linevars[new_selection_index - 1]
+ custom_state.selection_index = new_selection_index or 1
+ local stops = custom_state.stops
+ if stops == nil then
+ stops = {}
+ custom_state.stops = stops
+ end
+ local linevar_stops
+ if current_linevar ~= nil then
+ linevar_stops = current_linevar.stops
+ else
+ linevar_stops = {}
+ end
+
+ for i = 1, max_stations do
+ local stop = linevar_stops[i]
+ 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 "",
+ pos = stop.pos or "",
+ label = "",
+ }
+ else
+ stops[i] = {
+ dep = ifthenelse(i == 1, "0", ""),
+ wait = "10",
+ stn = "",
+ mode = 1,
+ track = "",
+ pos = "",
+ label = "",
+ }
+ end
+ end
+ if current_linevar ~= nil then
+ local lv_line, lv_stn, lv_rc = linevar_decompose(current_linevar.name)
+ custom_state.line = lv_line or ""
+ custom_state.rc = lv_rc or ""
+ 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
+ custom_state.evl_scroll = 0
+ custom_state.message = ""
+end
+
+local function num_transform(s)
+ local prefix = s:match("^([0-9]+)/")
+ if prefix == nil then
+ return s
+ end
+ return string.format(" %020d%s", tonumber(prefix) or 0, s:sub(#prefix, -1))
+end
+
+local function linevars_sorter(a, b)
+ return num_transform(a.name) < num_transform(b.name)
+end
+
+local function custom_state_refresh_linevars(custom_state, linevar_to_select)
+ assert(custom_state.player_name)
+ local linevars = {}
+ for _, stdata in pairs(advtrains.lines.stations) do
+ if stdata.linevars ~= nil then
+ for _, linevar_def in pairs(stdata.linevars) do
+ table.insert(linevars, linevar_def)
+ end
+ end
+ end
+ table.sort(linevars, linevars_sorter)
+ custom_state.selection_index = nil
+ custom_state.linevars = linevars
+ custom_state.compiled_linevar = nil
+ if linevar_to_select ~= nil then
+ for i, linevar_def in ipairs(linevars) do
+ if linevar_def.name == linevar_to_select then
+ custom_state_set_selection_index(custom_state, i + 1)
+ return true
+ end
+ end
+ return false
+ end
+end
+
+local function custom_state_compile_linevar(custom_state)
+ local stations = advtrains.lines.stations
+ local line = assert(custom_state.line)
+ local stn = assert(custom_state.stops[1].stn)
+ local rc = assert(custom_state.rc)
+ local train_name = assert(custom_state.train_name)
+ local owner = assert(custom_state.owner)
+ local stops = {}
+ if line == "" then
+ return false, "Označení linky nesmí být prázdné!"
+ elseif line:find("[/|\\]") then
+ return false, "Označení linky nesmí obsahovat znaky '/', '|' a '\\'!"
+ elseif line:len() > 256 then
+ return false, "Označení linky je příliš dlouhé!"
+ elseif stn == "" then
+ return false, "Výchozí zastávka musí být vyplněná!"
+ elseif rc:find("[/|\\]") then
+ return false, "Směrový kód nesmí obsahovat znaky '/', '|' a '\\'!"
+ elseif owner == "" then
+ 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
+ local finalcount = 0
+ local dep_to_index = {}
+ for i, stop in ipairs(assert(custom_state.stops)) do
+ local good_label
+ stop.label = ""
+ if stop.dep == "" then
+ -- přeskočit
+ elseif not stop.dep:match("^[0-9][0-9]*$") then
+ errcount = errcount + 1
+ stop.label = color_red.."Chybný formát času odjezdu!"
+ elseif tonumber(stop.dep) < 0 or tonumber(stop.dep) > 3600 then
+ errcount = errcount + 1
+ stop.label = color_red.."Čas odjezdu musí být v rozsahu 0 až 3600!"
+ elseif dep_to_index[tonumber(stop.dep)] ~= nil then
+ errcount = errcount + 1
+ stop.label = color_red.."Duplicitní čas odjezdu!"
+ else
+ dep_to_index[tonumber(stop.dep)] = i
+ if stop.stn == "" or stations[stop.stn] == nil or stations[stop.stn].name == nil then
+ errcount = errcount + 1
+ stop.label = color_red.."Neznámý kód dopravny!"
+ elseif stop.stn:find("[/|\\]") then
+ errcount = errcount + 1
+ stop.label = color_red.."Kód dopravny nesmí obsahovat znaky '/', '|' a '\\'!"
+ elseif stop.track:len() > 16 then
+ errcount = errcount + 1
+ stop.label = color_red.."Označení koleje je příliš dlouhé!"
+ elseif stop.pos ~= "" and not stop.pos:match("^[-0-9][0-9]*,[-0-9][0-9]*,[-0-9][0-9]*$") then
+ errcount = errcount + 1
+ stop.label = color_red.."Neplatný formát pozice!"
+ elseif stop.pos:len() > 22 then
+ errcount = errcount + 1
+ stop.label = color_red.."Specifikace pozice je příliš dlouhá!"
+ else
+ -- v pořádku:
+ local new_stop = {
+ stn = stop.stn,
+ dep = tonumber(stop.dep),
+ }
+ local new_mode = mode_from_formspec(i, stop.mode)
+ if new_mode ~= nil then
+ new_stop.mode = new_mode
+ if i > 1 and (new_mode == MODE_FINAL or new_mode == MODE_FINAL_CONTINUE or new_mode == MODE_FINAL_HIDDEN) then
+ finalcount = finalcount + 1
+ end
+ end
+ if stop.pos ~= "" then
+ new_stop.pos = stop.pos
+ end
+ 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)
+ end
+ end
+ end
+ end
+ if errcount > 0 then
+ return false, errcount.." chyb v seznamu zastávek!"
+ end
+ if finalcount == 0 then
+ 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,
+ 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
+ end
+ 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
+
+local function formspec_callback(custom_state, player, formname, fields)
+ local reload_stations, update_formspec = false, false
+ -- print("DEBUG: "..dump2({custom_state = custom_state, formname = formname, fields = fields}))
+
+ if fields.quit then
+ return
+ end
+ -- scrollbar:
+ if fields.evl_scroll then
+ local event = core.explode_scrollbar_event(fields.evl_scroll)
+ if event.type == "CHG" then
+ custom_state.evl_scroll = event.value
+ end
+ end
+ -- checkbox:
+ if fields.disable_linevar then
+ custom_state.disable_linevar = fields.disable_linevar
+ end
+ -- dropdowns:
+ for i = 1, max_stations do
+ local id = string.format("s%02d_mode", i)
+ local n = tonumber(fields[id])
+ if n ~= nil then
+ custom_state.stops[i].mode = n
+ end
+ end
+ -- fields:
+ 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", "wait", "stn", "track", "pos"}) do
+ local value = fields[prefix..key]
+ if value then
+ stop[key] = value
+ end
+ end
+ end
+ -- selection:
+ if fields.linevar then
+ local event = core.explode_table_event(fields.linevar)
+ if event.type == "CHG" or event.type == "DCL" then
+ custom_state_set_selection_index(custom_state, assert(tonumber(event.row)))
+ update_formspec = true
+ end
+ end
+
+ -- buttons:
+ if fields.create then
+ custom_state_set_selection_index(custom_state, 1)
+ update_formspec = true
+ elseif fields.reset then
+ custom_state_set_selection_index(custom_state, custom_state.selection_index or 1)
+ update_formspec = true
+ elseif fields.save then
+ local pinfo = ch_core.normalize_player(player)
+ if pinfo.role == "new" or pinfo.role == "none" then
+ core.log("error", "Access violation in line editor caused by '"..pinfo.player_name.."'!")
+ return -- access violation!
+ end
+ if custom_state.compiled_linevar == nil then
+ -- zkontrolovat a skompilovat
+ local success, errmsg = custom_state_compile_linevar(custom_state)
+ if success then
+ -- TODO: zkontrolovat práva a možnost přepsání i zde!
+ custom_state.message = color_green.."Úspěšně ověřeno. Varianta linky může být uložena."
+ else
+ custom_state.message = color_red.."Ověření selhalo: "..(errmsg or "Neznámý důvod")
+ end
+ update_formspec = true
+ else
+ -- pokusit se uložit...
+ custom_state.message = ""
+
+ local selection_index = custom_state.selection_index or 1
+ local selected_linevar, selected_linevar_def, selected_linevar_station
+ local to_linevar, to_linevar_def, to_linevar_station
+ local new_linevar, new_linevar_def, new_linevar_station
+
+ -- NEW:
+ new_linevar_def = custom_state.compiled_linevar
+ new_linevar = new_linevar_def.name
+ new_linevar_station = get_stn_from_linevar(new_linevar)
+
+ -- SELECTED:
+ if custom_state.selection_index > 1 and custom_state.linevars[selection_index - 1] ~= nil then
+ selected_linevar_def, selected_linevar_station = try_get_linevar_def(custom_state.linevars[selection_index - 1].name)
+ if selected_linevar_def ~= nil then
+ selected_linevar = selected_linevar_def.name
+ end
+ end
+
+ -- TO OVERWRITE:
+ to_linevar_def, to_linevar_station = try_get_linevar_def(new_linevar)
+ if to_linevar_def ~= nil then
+ to_linevar = to_linevar_def.name
+ end
+
+ local success, errmsg
+ if selected_linevar == nil then
+ if to_linevar == nil then
+ -- zcela nová varianta
+ core.log("action", "Will add a new linevar '"..new_linevar.."'")
+ success, errmsg = add_linevar(new_linevar_station, new_linevar_def)
+ else
+ -- replace
+ core.log("action", "Will replace an existing linevar '"..new_linevar.."'")
+ success = check_rights(pinfo, to_linevar_def.owner)
+ if success then
+ success, errmsg = replace_linevar(new_linevar_station, new_linevar_def)
+ else
+ errmsg = "Nedostatečná práva k variantě linky '"..to_linevar.."'."
+ end
+ end
+ elseif to_linevar == nil then
+ -- delete and add
+ core.log("action", "Will delete selected linevar '"..selected_linevar.."' and add new linevar '"..new_linevar.."'")
+ success = check_rights(pinfo, selected_linevar_def.owner)
+ if success then
+ success, errmsg = delete_linevar(selected_linevar_station, selected_linevar)
+ if success then
+ success, errmsg = add_linevar(new_linevar_station, new_linevar_def)
+ end
+ else
+ errmsg = "Nedostatečná práva k variantě linky '"..selected_linevar.."'."
+ end
+ elseif selected_linevar ~= to_linevar then
+ -- delete and replace
+ core.log("action", "Will add delete selected linevar '"..selected_linevar.."' and replace existing linevar '"..new_linevar.."'")
+ success = check_rights(pinfo, to_linevar_def.owner)
+ if success then
+ success = check_rights(pinfo, selected_linevar_def.owner)
+ if success then
+ success, errmsg = delete_linevar(selected_linevar_station, selected_linevar)
+ if success then
+ success, errmsg = replace_linevar(new_linevar_station, new_linevar_def)
+ end
+ else
+ errmsg = "Nedostatečná práva k variantě linky '"..selected_linevar.."'."
+ end
+ else
+ errmsg = "Nedostatečná práva k variantě linky '"..to_linevar.."'."
+ end
+ else
+ -- replace
+ core.log("action", "Will replace existing linevar '"..new_linevar.."'")
+ success = check_rights(pinfo, to_linevar_def.owner)
+ if success then
+ success, errmsg = replace_linevar(new_linevar_station, new_linevar_def)
+ else
+ errmsg = "Nedostatečná práva k variantě linky '"..to_linevar.."'."
+ end
+ end
+
+ if success then
+ custom_state.message = color_green.."Varianta linky '"..new_linevar.."' úspěšně uložena."
+ custom_state_refresh_linevars(custom_state, new_linevar)
+ else
+ custom_state.message = color_red.."Ukládání selhalo: "..(errmsg or "Neznámá chyba.")
+ end
+ update_formspec = true
+ end
+
+ elseif fields.delete then
+ local pinfo = ch_core.normalize_player(player)
+ if pinfo.role == "new" or pinfo.role == "none" then
+ core.log("error", "Access violation in line editor caused by '"..pinfo.player_name.."'!")
+ return -- access violation!
+ end
+ local selection_index = custom_state.selection_index or 1
+ local selected_linevar, selected_linevar_def, selected_linevar_station
+ if selection_index > 1 and custom_state.linevars[selection_index - 1] ~= nil then
+ selected_linevar_def, selected_linevar_station = try_get_linevar_def(custom_state.linevars[selection_index - 1].name)
+ if selected_linevar_def ~= nil then
+ selected_linevar = selected_linevar_def.name
+ end
+ local success, errmsg
+ success = check_rights(pinfo, selected_linevar_def.owner)
+ if success then
+ success, errmsg = delete_linevar(selected_linevar_station, selected_linevar)
+ else
+ errmsg = "Nedostatečná práva k variantě linky '"..selected_linevar.."'."
+ end
+ if success then
+ custom_state.message = "Varianta linky '"..selected_linevar.."' úspěšně smazána."
+ custom_state_refresh_linevars(custom_state)
+ custom_state_set_selection_index(custom_state, 1)
+ else
+ custom_state.message = "Mazání selhalo: "..(errmsg or "Neznámá chyba.")
+ end
+ update_formspec = true
+ end
+ elseif fields.last_passages then
+ local selected_linevar_def = try_get_linevar_def(custom_state.linevars[(custom_state.selection_index or 1) - 1].name)
+ if selected_linevar_def ~= nil then
+ assert(selected_linevar_def.name)
+ show_last_passages_formspec(player, selected_linevar_def, assert(selected_linevar_def.name))
+ return
+ end
+ end
+
+ if update_formspec then
+ return get_formspec(custom_state)
+ end
+end
+
+local function show_editor_formspec(player, linevar_to_select)
+ if player == nil then return false end
+ local custom_state = {
+ 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)
+ end
+ ch_core.show_formspec(player, "advtrains_line_automation:editor_linek", get_formspec(custom_state), formspec_callback, custom_state, {})
+end
+
+local function lp_formspec_callback(custom_state, player, formname, fields)
+ if fields.back then
+ show_editor_formspec(player, custom_state.selected_linevar)
+ end
+end
+
+show_last_passages_formspec = function(player, linevar_def, selected_linevar)
+ local formspec = {
+ "formspec_version[6]"..
+ "size[20,10]"..
+ "label[0.5,0.6;Poslední jízdy na variantě linky ",
+ F(assert(linevar_def.name)),
+ "]"..
+ "tablecolumns[text;text;text,width=5;text,width=5;text,width=5;text,width=5;text,width=5;text,width=5;text,width=5;text,width=5;text,width=5;text,width=5]",
+ "table[0.5,1.25;19,8;jizdy;KÓD,DOPRAVNA,1.j.,2.j.,3.j.,4.j.,5.j.,6.j.,7.j.,8.j.,9.j.,10.j."
+ }
+ local passages, stops = get_last_passages(linevar_def)
+ local max_time = {}
+ if passages ~= nil then
+ for j = 1, 10 do
+ max_time[j] = 0
+ if passages[j] == nil then
+ passages[j] = {}
+ end
+ end
+ -- stání na výchozí zastávce:
+ table.insert(formspec, ",,STÁNÍ NA V.Z.:")
+ for j = 1, 10 do
+ local wait = passages[j].wait
+ if wait ~= nil then
+ table.insert(formspec, ","..wait.." s")
+ else
+ table.insert(formspec, ",-")
+ end
+ end
+ -- odjezd z výchozí zastávky:
+ table.insert(formspec, ","..F(stops[1][1])..","..F(stops[1][2]).." (odj.)")
+ for j = 1, 10 do
+ local time = passages[j][1]
+ if time ~= nil then
+ table.insert(formspec, ",("..time..")")
+ if max_time[j] < time then
+ max_time[j] = time
+ end
+ else
+ table.insert(formspec, ",-")
+ end
+ end
+ -- odjezdy z ostatních zasŧávek:
+ for i = 2, #stops do -- i = index zastávky
+ table.insert(formspec, ","..F(stops[i][1])..","..F(stops[i][2]))
+ for j = 1, 10 do -- j = index jízdy
+ local dep_vych = passages[j][1]
+ local time = passages[j][i]
+ if time ~= nil and dep_vych ~= nil then
+ table.insert(formspec, ","..(time - dep_vych))
+ if max_time[j] < time then
+ max_time[j] = time
+ end
+ else
+ table.insert(formspec, ",-")
+ end
+ end
+ end
+ table.insert(formspec, ",,DOBA JÍZDY:")
+ for i = 1, 10 do
+ if max_time[i] ~= 0 then
+ table.insert(formspec, ",_"..(max_time[i] - passages[i][1]).."_")
+ else
+ table.insert(formspec, ",-")
+ end
+ end
+ end
+ table.insert(formspec, ";]"..
+ "button[17.75,0.3;1.75,0.75;back;zpět]"..
+ "tooltip[jizdy;Časové údaje jsou v sekundách železničního času.]")
+ formspec = table.concat(formspec)
+ local custom_state = {
+ player_name = player:get_player_name(),
+ selected_linevar = selected_linevar,
+ }
+ ch_core.show_formspec(player, "advtrains_line_automation:posledni_jizdy", formspec, lp_formspec_callback, custom_state, {})
+end
+
+def = {
+ -- params = "",
+ description = "Otevře editor variant linek",
+ privs = {railway_operator = true},
+ func = function(player_name, param) show_editor_formspec(minetest.get_player_by_name(player_name)) end,
+}
+core.register_chatcommand("linky", def)