Add ARS rules for stop rails

h137
orwell96 2019-02-19 21:54:17 +01:00
parent 0684c6edd7
commit f2c2aad329
3 changed files with 107 additions and 82 deletions

View File

@ -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

View File

@ -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

View File

@ -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