From f2c2aad32940311914cc0d8d9b6b216d02d34d55 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Tue, 19 Feb 2019 21:54:17 +0100 Subject: Add ARS rules for stop rails --- advtrains_interlocking/ars.lua | 81 ++++++++++++++++++++++++++++++---- advtrains_interlocking/route_ui.lua | 56 +---------------------- advtrains_line_automation/stoprail.lua | 52 ++++++++++++++-------- 3 files changed, 107 insertions(+), 82 deletions(-) diff --git a/advtrains_interlocking/ars.lua b/advtrains_interlocking/ars.lua index e20d189..dd5ff40 100644 --- a/advtrains_interlocking/ars.lua +++ b/advtrains_interlocking/ars.lua @@ -23,23 +23,67 @@ local il = advtrains.interlocking +-- The ARS data are saved in a table format, but are entered in text format. Utility functions to transform between both. +function il.ars_to_text(arstab) + if not arstab then + return "" + end + + local txt = {} + + for i, arsent in ipairs(arstab) do + if arsent.ln then + txt[#txt+1] = "LN "..arsent.ln + elseif arsent.rc then + txt[#txt+1] = "RC "..arsent.rc + elseif arsent.c then + txt[#txt+1] = "#"..arsent.c + end + end + + if arstab.default then + return "*\n" .. table.concat(txt, "\n") + end + return table.concat(txt, "\n") +end + +function il.text_to_ars(t) + if t=="" then + return nil + elseif t=="*" then + return {default=true} + end + local arstab = {} + for line in string.gmatch(t, "[^\r\n]+") do + if line=="*" then + arstab.default = true + else + local c, v = string.match(line, "^(..)%s(.*)$") + if c and v then + local tt=string.upper(c) + if tt=="LN" then + arstab[#arstab+1] = {ln=v} + elseif tt=="RC" then + arstab[#arstab+1] = {rc=v} + end + else + local ct = string.match(line, "^#(.*)$") + if ct then arstab[#arstab+1] = {c = ct} end + end + end + end + return arstab +end local function find_rtematch(routes, train) local default - local line = train.line - local routingcode = train.routingcode for rteid, route in ipairs(routes) do if route.ars then if route.ars.default then default = rteid else - for arskey, arsent in ipairs(route.ars) do - --atdebug(arsent, line, routingcode) - if arsent.ln and line and arsent.ln == line then - return rteid - elseif arsent.rc and routingcode and string.find(" "..routingcode.." ", " "..arsent.rc.." ", nil, true) then - return rteid - end + if il.ars_check_rule_match(route.ars, train) then + return rteid end end end @@ -47,6 +91,25 @@ local function find_rtematch(routes, train) return default end +-- Checks whether ARS rule explicitly matches. This does not take into account the "default" field, since a wider context is required for this. +-- Returns the rule number that matched, or nil if nothing matched +function il.ars_check_rule_match(ars, train) + if not ars then + return nil + end + local line = train.line + local routingcode = train.routingcode + for arskey, arsent in ipairs(ars) do + --atdebug(arsent, line, routingcode) + if arsent.ln and line and arsent.ln == line then + return arskey + elseif arsent.rc and routingcode and string.find(" "..routingcode.." ", " "..arsent.rc.." ", nil, true) then + return arskey + end + end + return nil +end + function advtrains.interlocking.ars_check(sigd, train) local tcbs = il.db.get_tcbs(sigd) if not tcbs or not tcbs.routes then return end diff --git a/advtrains_interlocking/route_ui.lua b/advtrains_interlocking/route_ui.lua index 45aaa82..4ddab0c 100644 --- a/advtrains_interlocking/route_ui.lua +++ b/advtrains_interlocking/route_ui.lua @@ -10,58 +10,6 @@ local function sigd_to_string(sigd) return minetest.pos_to_string(sigd.p).." / "..lntrans[sigd.s] end --- The ARS data are saved in a table format, but are entered in text format. Utility functions to transform between both. -local function ars_to_text(arstab) - if not arstab then - return "" - end - - local txt = {} - - for i, arsent in ipairs(arstab) do - if arsent.ln then - txt[#txt+1] = "LN "..arsent.ln - elseif arsent.rc then - txt[#txt+1] = "RC "..arsent.rc - elseif arsent.c then - txt[#txt+1] = "#"..arsent.c - end - end - - if arstab.default then - return "*\n" .. table.concat(txt, "\n") - end - return table.concat(txt, "\n") -end - -local function text_to_ars(t) - if t=="" then - return nil - elseif t=="*" then - return {default=true} - end - local arstab = {} - for line in string.gmatch(t, "[^\r\n]+") do - if line=="*" then - arstab.default = true - else - local c, v = string.match(line, "^(..)%s(.*)$") - if c and v then - local tt=string.upper(c) - if tt=="LN" then - arstab[#arstab+1] = {ln=v} - elseif tt=="RC" then - arstab[#arstab+1] = {rc=v} - end - else - local ct = string.match(line, "^#(.*)$") - if ct then arstab[#arstab+1] = {c = ct} end - end - end - end - return arstab -end - function atil.show_route_edit_form(pname, sigd, routeid) @@ -139,7 +87,7 @@ function atil.show_route_edit_form(pname, sigd, routeid) form = form.."button[5.5,6;2,1;delete;Delete Route]" --atdebug(route.ars) - form = form.."textarea[1,7.3;5.2,3;ars;ARS Rule List;"..ars_to_text(route.ars).."]" + form = form.."textarea[1,7.3;5.2,3;ars;ARS Rule List;"..atil.ars_to_text(route.ars).."]" form = form.."button[6,7.7;1,1;savears;Save]" minetest.show_formspec(pname, "at_il_routeedit_"..minetest.pos_to_string(sigd.p).."_"..sigd.s.."_"..routeid, form) @@ -192,7 +140,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end if fields.ars and fields.savears then - route.ars = text_to_ars(fields.ars) + route.ars = atil.text_to_ars(fields.ars) --atdebug(route.ars) end diff --git a/advtrains_line_automation/stoprail.lua b/advtrains_line_automation/stoprail.lua index 859813e..2e6072e 100644 --- a/advtrains_line_automation/stoprail.lua +++ b/advtrains_line_automation/stoprail.lua @@ -27,7 +27,7 @@ local function show_stoprailform(pos, player) local stdata = advtrains.lines.stops[pe] if not stdata then advtrains.lines.stops[pe] = { - stn="", track="", doors="R", wait=10 + stn="", track="", doors="R", wait=10, ars={default=true}, } stdata = advtrains.lines.stops[pe] end @@ -35,19 +35,21 @@ local function show_stoprailform(pos, player) local stn = advtrains.lines.stations[stdata.stn] local stnname = stn and stn.name or "" - local form = "size[8,6.5]" + local form = "size[8,7]" form = form.."field[0.5,1;7,1;stn;"..attrans("Station Code")..";"..minetest.formspec_escape(stdata.stn).."]" form = form.."field[0.5,2;7,1;stnname;"..attrans("Station Name")..";"..minetest.formspec_escape(stnname).."]" form = form.."label[0.5,3;Door side:]" - form = form.."dropdown[0.5,3.5;2;doors;Left,Right,Closed;"..door_dropdown[stdata.doors].."]" - form = form.."dropdown[3,3.5;1.5;reverse;---,Reverse;"..(stdata.reverse and 2 or 1).."]" + form = form.."dropdown[0.5,3;2;doors;Left,Right,Closed;"..door_dropdown[stdata.doors].."]" + form = form.."dropdown[3,3;1.5;reverse;---,Reverse;"..(stdata.reverse and 2 or 1).."]" form = form.."field[5,3.5;2,1;track;"..attrans("Track")..";"..stdata.track.."]" form = form.."field[5,4.5;2,1;wait;"..attrans("Stop Time")..";"..stdata.wait.."]" - form = form.."button[0.5,5.5;7,1;save;"..attrans("Save").."]" + form = form.."textarea[0.5,4;4,2;ars;Trains stopping here (ARS rules);"..advtrains.interlocking.ars_to_text(stdata.ars).."]" + + form = form.."button[0.5,6;7,1;save;"..attrans("Save").."]" minetest.show_formspec(pname, "at_lines_stop_"..pe, form) end @@ -107,6 +109,10 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) stdata.wait = tonumber(fields.wait) or 10 end + if fields.ars then + stdata.ars = advtrains.interlocking.text_to_ars(fields.ars) + end + --TODO: signal updatemeta(pos) @@ -136,13 +142,20 @@ local adefunc = function(def, preset, suffix, rotation) advtrains = { on_train_approach = function(pos,train_id, train, index) if train.path_cn[index] == 1 then - advtrains.interlocking.lzb_add_oncoming_npr(train, index, 2) local pe = advtrains.encode_pos(pos) local stdata = advtrains.lines.stops[pe] if stdata and stdata.stn then - local stn = advtrains.lines.stations[stdata.stn] - local stnname = stn and stn.name or "Unknown Station" - train.text_inside = "Next Stop:\n"..stnname + + --TODO REMOVE AFTER SOME TIME (only migration) + if not stdata.ars then + stdata.ars = {default=true} + end + if stdata.ars and (stdata.ars.default or advtrains.interlocking.ars_check_rule_match(stdata.ars, train) ) then + advtrains.interlocking.lzb_add_oncoming_npr(train, index, 2) + local stn = advtrains.lines.stations[stdata.stn] + local stnname = stn and stn.name or "Unknown Station" + train.text_inside = "Next Stop:\n"..stnname + end end end end, @@ -151,18 +164,19 @@ local adefunc = function(def, preset, suffix, rotation) local pe = advtrains.encode_pos(pos) local stdata = advtrains.lines.stops[pe] if not stdata then - advtrains.atc.train_set_command(train, "B0", true) - updatemeta(pos) + return end - local stn = advtrains.lines.stations[stdata.stn] - local stnname = stn and stn.name or "Unknown Station" - - -- Send ATC command and set text - advtrains.atc.train_set_command(train, "B0 W O"..stdata.doors.." D"..stdata.wait.." OC D1 "..(stdata.reverse and "R" or "").." SM", true) - train.text_inside = stnname - if tonumber(stdata.wait) then - minetest.after(tonumber(stdata.wait), function() train.text_inside = "" end) + if stdata.ars and (stdata.ars.default or advtrains.interlocking.ars_check_rule_match(stdata.ars, train) ) then + local stn = advtrains.lines.stations[stdata.stn] + local stnname = stn and stn.name or "Unknown Station" + + -- Send ATC command and set text + advtrains.atc.train_set_command(train, "B0 W O"..stdata.doors.." D"..stdata.wait.." OC D1 "..(stdata.reverse and "R" or "").." SM", true) + train.text_inside = stnname + if tonumber(stdata.wait) then + minetest.after(tonumber(stdata.wait), function() train.text_inside = "" end) + end end end end -- cgit v1.2.3