aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--advtrains_interlocking/ars.lua31
-rw-r--r--advtrains_interlocking/database.lua5
-rw-r--r--advtrains_interlocking/routesetting.lua85
-rwxr-xr-xadvtrains_interlocking/tcb_ts_ui.lua33
4 files changed, 104 insertions, 50 deletions
diff --git a/advtrains_interlocking/ars.lua b/advtrains_interlocking/ars.lua
index fc9f2a3..5182cd3 100644
--- a/advtrains_interlocking/ars.lua
+++ b/advtrains_interlocking/ars.lua
@@ -245,16 +245,29 @@ function il.ars_check_rule_match(ars, train)
end
local function sort_priority(sprio)
- -- TODO implement and return the correct sorted table
- -- for now just minimum
- local maxk,maxv = nil,10000
- for k,v in pairs(sprio) do
- if v<maxv then
- maxv = v
- maxk = k
+ -- insertion sort
+ local order = {}
+ local oprio = {}
+ for rteid, prio in pairs(sprio) do
+ local inspos = 1
+ while order[inspos] do
+ if oprio[inspos] > prio then
+ -- next item has higher priority number (= less urgent), insert before it
+ break
+ elseif oprio[inspos] == prio and order[inspos] > rteid then
+ -- next item has same priority as current and a higher routeid, insert before it
+ break
+ end
+ inspos = inspos + 1
end
+ table.insert(order, inspos, rteid)
+ table.insert(oprio, inspos, prio)
+ end
+ --atdebug("sort_priority",sprio,"result",order,oprio)
+ if #order == 1 then
+ return order[1] -- only one route, table doesnt make sense
end
- return maxk
+ return order
end
local function find_rtematch(routes, train)
@@ -278,12 +291,10 @@ local function find_rtematch(routes, train)
end
end
if next(sprio) then
- atdebug("Ars: SMultiArs", sprio, "is not implemented yet!")
return sort_priority(sprio)
elseif default then
return default
elseif next(dprio) then
- atdebug("Ars: DMultiArs", dprio, "is not implemented yet!")
return sort_priority(dprio)
else
return nil
diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua
index 844d350..5e35dba 100644
--- a/advtrains_interlocking/database.lua
+++ b/advtrains_interlocking/database.lua
@@ -214,10 +214,11 @@ TCB data structure
-- aspect will be set accordingly.
routeset = <index in routes> -- Route set from this signal. This is the entry that is cleared once
-- train has passed the signal. (which will set the aspect to "danger" again)
- route_committed = <boolean> -- When setting/requesting a route, routetar will be set accordingly,
+ -- routeset may be a table (e.g. {1,2}) while the route is not committed yet, indicating a wait for multiple routes at once (Multi-ARS)
+ route_committed = <boolean> -- When setting/requesting a route, routeset will be set accordingly,
-- while the signal still displays danger and nothing is written to the TCs
-- As soon as the route can actually be set, all relevant TCs and turnouts are set and this field
- -- is set true, clearing the signal
+ -- is set true, clearing the signal (when this is true, routeset is never a table)
aspect = <asp> -- The aspect the signal should show. If this is nil, should show the most restrictive aspect (red)
signal_name = <string> -- The human-readable name of the signal, only for documenting purposes
routes = { <route definition> } -- a collection of routes from this signal
diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua
index 1065cad..9901d23 100644
--- a/advtrains_interlocking/routesetting.lua
+++ b/advtrains_interlocking/routesetting.lua
@@ -363,7 +363,7 @@ end
-- route setting
-- Call this function to set and cancel routes!
-- sigd, tcbs: self-explanatory
--- newrte: If a new route should be set, the route index of it (in tcbs.routes). nil otherwise
+-- newrte: If a new route should be set, the route index of it (in tcbs.routes). Can also be a table (multi-ars). nil otherwise
-- cancel: true in combination with newrte=nil causes cancellation of the current route.
function ilrs.update_route(sigd, tcbs, newrte, cancel)
--atdebug("Update_Route for",sigd,tcbs.signal_name)
@@ -390,37 +390,66 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
if tcbs.route_committed then
return
end
- if newrte then tcbs.routeset = newrte end
+ if newrte then
+ if type(newrte)=="table" and not next(newrte) then
+ error("update_route got multi-ARS with empty table, this is not allowed")
+ end
+ tcbs.routeset = newrte
+ else
+ if type(tcbs.routeset)=="table" and not next(tcbs.routeset) then
+ -- just unset, don't error
+ atwarn(sigd, "had multi-ARS route set with empty list! Cancelled!")
+ tcbs.routeset = nil
+ return
+ end
+ end
--atdebug("Setting:",tcbs.routeset)
- local succ, rsn, cbts, cblk
- local route = tcbs.routes[tcbs.routeset]
- if route then
- succ, rsn, cbts, cblk = ilrs.set_route(sigd, route)
+ -- check: single-ars or multi-ars?
+ local multi_rte
+ if type(tcbs.routeset) == "table" then
+ multi_rte = tcbs.routeset
else
- succ = false
- rsn = attrans("Route state changed.")
+ multi_rte = {tcbs.routeset}
end
- if not succ then
- tcbs.route_rsn = rsn
- --atdebug("Routesetting failed:",rsn)
- -- add cbts or cblk to callback table
- if cbts then
- --atdebug("cbts =",cbts)
- if not ilrs.rte_callbacks.ts[cbts] then ilrs.rte_callbacks.ts[cbts]={} end
- advtrains.insert_once(ilrs.rte_callbacks.ts[cbts], sigd, sigd_equal)
- end
- if cblk then
- --atdebug("cblk =",cblk)
- if not ilrs.rte_callbacks.lck[cblk] then ilrs.rte_callbacks.lck[cblk]={} end
- advtrains.insert_once(ilrs.rte_callbacks.lck[cblk], sigd, sigd_equal)
+ for multi_idx, rteid in ipairs(multi_rte) do
+ local succ, rsn, cbts, cblk
+ local route = tcbs.routes[rteid]
+ if route then
+ succ, rsn, cbts, cblk = ilrs.set_route(sigd, route)
+ else
+ succ = false
+ rsn = attrans("Route with index @1 not found", rteid)
end
- else
- --atdebug("Committed Route:",tcbs.routeset)
- -- set_route now sets the signal aspects
- --has_changed_aspect = true
- -- route success. apply default_autoworking flag if requested
- if route.default_autoworking then
- tcbs.route_auto = true --FIX 2025-01-08: never set it to false if it was true!
+ if not succ then
+ if multi_idx==1 then
+ tcbs.route_rsn = rsn
+ else
+ tcbs.route_rsn = (tcbs.route_rsn or "").."\n"..rsn
+ end
+ --atdebug("Routesetting",rteid,"failed:",rsn,"(multi-idx",multi_idx,")")
+ -- add cbts or cblk to callback table
+ if cbts then
+ --atdebug("cbts =",cbts)
+ if not ilrs.rte_callbacks.ts[cbts] then ilrs.rte_callbacks.ts[cbts]={} end
+ advtrains.insert_once(ilrs.rte_callbacks.ts[cbts], sigd, sigd_equal)
+ end
+ if cblk then
+ --atdebug("cblk =",cblk)
+ if not ilrs.rte_callbacks.lck[cblk] then ilrs.rte_callbacks.lck[cblk]={} end
+ advtrains.insert_once(ilrs.rte_callbacks.lck[cblk], sigd, sigd_equal)
+ end
+ else
+ --atdebug("Committed Route:",rteid,"(multi-idx",multi_idx,")")
+ -- replace multi_route by single actually committed route
+ tcbs.routeset = rteid
+ -- set_route now sets the signal aspects
+ --has_changed_aspect = true
+ -- route success. apply default_autoworking flag if requested
+ if route.default_autoworking then
+ tcbs.route_auto = true --FIX 2025-01-08: never set it to false if it was true!
+ end
+ -- break out of the for loop, dont try any more routes
+ break
end
end
end
diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua
index 814a11a..0be943a 100755
--- a/advtrains_interlocking/tcb_ts_ui.lua
+++ b/advtrains_interlocking/tcb_ts_ui.lua
@@ -828,14 +828,29 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, calle
form = form.."button[5.5,1.2;1,1;setname;Set]"
if tcbs.routeset then
- local rte = tcbs.routes[tcbs.routeset]
- if not rte then
- atwarn("Unknown route set from signal!")
- tcbs.routeset = nil
- return
+ if type(tcbs.routeset)=="table" then
+ local rtenames = {}
+ for midx,rteid in ipairs(tcbs.routeset) do
+ local rte = tcbs.routes[rteid]
+ if not rte then
+ atwarn("Unknown route set from signal!")
+ tcbs.routeset = nil
+ return
+ end
+ rtenames[midx] = rte.name
+ end
+ form = form.."label[0.5,2.5;Multiple routes are requested (first available is set):]"
+ form = form.."label[0.5,3.0;"..minetest.formspec_escape(table.concat(rtenames,", ")).."]"
+ else
+ local rte = tcbs.routes[tcbs.routeset]
+ if not rte then
+ atwarn("Unknown route set from signal!")
+ tcbs.routeset = nil
+ return
+ end
+ form = form.."label[0.5,2.5;A route is requested from this signal:]"
+ form = form.."label[0.5,3.0;"..minetest.formspec_escape(rte.name).."]"
end
- form = form.."label[0.5,2.5;A route is requested from this signal:]"
- form = form.."label[0.5,3.0;"..minetest.formspec_escape(rte.name).."]"
if tcbs.route_committed then
form = form.."label[0.5,3.5;Route has been set.]"
else
@@ -1000,9 +1015,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end
if tcbs.routeset and fields.cancelroute then
- if tcbs.routes[tcbs.routeset] and tcbs.routes[tcbs.routeset].ars then
- tcbs.ars_ignore_next = true
- end
+ tcbs.ars_ignore_next = true
-- if route committed, cancel route ts info
ilrs.update_route(sigd, tcbs, nil, true)
end