fix(client): 优化停站时间获取,并在列车停站时禁用进站预告

1. 修复 `Utils.getStopTime` 和 `Utils.getNextStation` 会误匹配“非车站指令”(如修改最高速度等指令)中的文本的问题,现在仅在 `instruction.id == create:station`
或 `create:destination` 的条目中扫描,保证了 CC 电脑从 `create:track_station`
获取到的时刻表信息(包括计算出的停站时间)100% 准确。
2. 修复显示器(Display Board / NBT)在列车停站后依然显示“离站倒计时 ETA”,导致触发 `train_approaching` 的问题:如果当前列车已经在站内(`State.currentTrain` 存在且匹配),将强制忽略该列车的 `train_approaching` 触发逻辑,彻底解决列车停站时倒秒导致的重复播报。
This commit is contained in:
2026-08-03 12:20:54 +08:00
parent 87fda31485
commit fdbcfa3b9b
+24 -39
View File
@@ -1,6 +1,6 @@
-- 1. Configuration & Constants
local APP_VERSION_TEXT = "v1.0.54"
local APP_VERSION_TEXT = "v1.0.55"
local CONFIG = {
CLOUD_URL = "ws://stabadmin.fse-media.group",
@@ -778,16 +778,16 @@ function Utils.getStopTime(schedule, stationName)
for i = 1, maxIdx do
local entry = schedule.entries[i]
if entry then
local function scanRecursive(obj, depth)
if depth > 5 or not obj then return false end
for k, v in pairs(obj) do
if type(v) == "string" then
local entryText = v:lower()
local isStationEntry = false
if entry.instruction and (entry.instruction.id == "create:station" or entry.instruction.id == "create:destination") then
local text = (entry.instruction.data and entry.instruction.data.text) or entry.instruction.text
if type(text) == "string" then
local entryText = text:lower()
local entryCode = Utils.getStationCode(entryText)
local entryAlpha = entryText:gsub("[^%w%d]", "")
local entryBase = Utils.getBaseName(entryText)
Utils.log("DEBUG", string.format(" [%d] SCAN '%s': '%s' (Code: %s)", i, k, entryText, tostring(entryCode)))
Utils.log("DEBUG", string.format(" [%d] SCAN STATION: '%s' (Code: %s)", i, entryText, tostring(entryCode)))
local isMatch = (target == entryText)
or (targetCode and entryCode and targetCode == entryCode)
@@ -796,17 +796,13 @@ function Utils.getStopTime(schedule, stationName)
or Utils.isFuzzyMatch(target, entryText)
if isMatch then
Utils.log("DEBUG", string.format(" >>> MATCH FOUND AT ENTRY %d (via field '%s')", i, k))
return true
end
elseif type(v) == "table" then
if scanRecursive(v, depth + 1) then return true end
Utils.log("DEBUG", string.format(" >>> MATCH FOUND AT ENTRY %d", i))
isStationEntry = true
end
end
return false
end
if scanRecursive(entry, 0) then
if isStationEntry then
matchFoundIndex = i
local s = findTimeInConditions(entry.conditions)
if s then
@@ -833,19 +829,10 @@ function Utils.getStopTime(schedule, stationName)
local entry = schedule.entries[i]
if entry then
local isOtherStation = false
local function checkIsStation(obj, depth)
if depth > 2 or not obj then return false end
for k, v in pairs(obj) do
if type(v) == "string" then
local lk = tostring(k):lower()
if lk:find("text") or lk:find("station") or lk:find("destination") then return true end
elseif type(v) == "table" then
if checkIsStation(v, depth + 1) then return true end
if entry.instruction and (entry.instruction.id == "create:station" or entry.instruction.id == "create:destination") then
isOtherStation = true
end
end
return false
end
if checkIsStation(entry, 0) then break end
if isOtherStation then break end
local s = findTimeInConditions(entry.conditions)
if s then
@@ -887,11 +874,11 @@ function Utils.getNextStation(schedule, currentStationName)
for i = 1, maxIdx do
local entry = schedule.entries[i]
if entry then
local function scanRecursive(obj, depth)
if depth > 5 or not obj then return false end
for k, v in pairs(obj) do
if type(v) == "string" then
local entryText = v:lower()
local isStationEntry = false
if entry.instruction and (entry.instruction.id == "create:station" or entry.instruction.id == "create:destination") then
local text = (entry.instruction.data and entry.instruction.data.text) or entry.instruction.text
if type(text) == "string" then
local entryText = text:lower()
local entryCode = Utils.getStationCode(entryText)
local entryAlpha = entryText:gsub("[^%w%d]", "")
local entryBase = Utils.getBaseName(entryText)
@@ -902,15 +889,11 @@ function Utils.getNextStation(schedule, currentStationName)
or (targetBase ~= "" and entryBase ~= "" and (targetBase == entryBase or targetBase:find(entryBase, 1, true) or entryBase:find(targetBase, 1, true)))
or Utils.isFuzzyMatch(target, entryText)
if isMatch then return true end
elseif type(v) == "table" then
if scanRecursive(v, depth + 1) then return true end
if isMatch then isStationEntry = true end
end
end
return false
end
if scanRecursive(entry, 0) then
if isStationEntry then
matchFoundIndex = i
break
end
@@ -2751,7 +2734,8 @@ function Main.loop()
end
end
if etaSeconds > 0 and etaSeconds <= 45 then
local isAtStation = State.currentTrain and State.currentTrain.id == trainName and State.currentTrain.dest == destination
if not isAtStation and etaSeconds > 0 and etaSeconds <= 45 then
if not seenApproachKeys[announceKey] then
seenApproachKeys[announceKey] = true
local pending = State.pendingApproaching[announceKey]
@@ -2888,7 +2872,8 @@ function Main.loop()
end
end
if etaSeconds > 0 and etaSeconds <= 45 then
local isAtStation = State.currentTrain and State.currentTrain.id == tName and State.currentTrain.dest == dest
if not isAtStation and etaSeconds > 0 and etaSeconds <= 45 then
if not seenApproachKeys[announceKey] then
seenApproachKeys[announceKey] = true
local pending = State.pendingApproaching[announceKey]