diff options
-rw-r--r-- | advtrains_interlocking/ars.lua | 31 | ||||
-rw-r--r-- | advtrains_interlocking/database.lua | 5 | ||||
-rw-r--r-- | advtrains_interlocking/routesetting.lua | 85 | ||||
-rwxr-xr-x | advtrains_interlocking/tcb_ts_ui.lua | 33 |
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 |