fix(crn): 修复CRN聚合站(如「千叶」)在CC中文环境下变????导致校正匹配失败引发终点站广播漏播
- 新增 extractAlphaNumCodes / hasSharedAlphaNumCode: 提取并比对字母数字代码(CB-03,CE-09等), 在中文变问号乱码环境下仍可通过代码完成跨源匹配 - looksLikeValidDestinationText: 放宽校验, 若问号超过50%但仍存在有效字母数字代码(如「????CB-03 6」)时不直接判为无效——保留代码供后续 hasSharedAlphaNumCode 匹配 - tryCorrectUpcomingEntryWithCurrentTrain: 1) 新增 etaSeconds 形参用于识别在站列车(eta≤0.5s), 据此触发校正 2) 新增 nearbyPlatform 条件: 站台号数字差≤1 时也进入校正候选 3) 新增 sharedCodeDest / sharedCodeTrain: 即使车次/站台全不匹配, 只要 dest 或 id 含有与权威值相同的字母数字代码即可触发 4) 新增兜底触发: (dest或id无效且eta=0) | (双无效且相邻站台) —— 专门覆盖CRN聚合名????这种彻底无代码的场景 5) 新增校正分支: 只要 sharedCodeTrain/sharedCodeDest 命中且 (etaAtStation|samePlatform|invalid) 即直接覆盖原值, 无需 fuzzy match 再次通过 - checkIsAtStationWithCurrentTrain: 1) 无 sameTrain 时用 hasSharedAlphaNumCode 二次匹配车次 2) 若车次/目的地双乱码 + 站台相邻, 也视为同车 3) 乱码目的地分支新增 hasSharedAlphaNumCode 成功即判停靠成功 - BlockReader/CreateTarget 两处预校正均移至 etaSeconds 计算之后, 并将 eta 传入函数, 确保看门条件里的 etaAtStation 可生效 - 全局校正循环也传入 entry.eta 版本升级至 v1.0.72
This commit is contained in:
+123
-39
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
-- 1. Configuration & Constants
|
-- 1. Configuration & Constants
|
||||||
local APP_VERSION_TEXT = "v1.0.71"
|
local APP_VERSION_TEXT = "v1.0.72"
|
||||||
|
|
||||||
local CONFIG = {
|
local CONFIG = {
|
||||||
CLOUD_URL = "ws://stabadmin.fse-media.group",
|
CLOUD_URL = "ws://stabadmin.fse-media.group",
|
||||||
@@ -3042,6 +3042,45 @@ local function isStationDestination(destName)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function extractAlphaNumCodes(text)
|
||||||
|
if not text then return {} end
|
||||||
|
local s = tostring(text)
|
||||||
|
local codes = {}
|
||||||
|
for code in string.gmatch(s, "[%a%d]+%-[%a%d]+") do
|
||||||
|
codes[code] = true
|
||||||
|
end
|
||||||
|
for code in string.gmatch(s, "%a+%d+") do
|
||||||
|
codes[code] = true
|
||||||
|
end
|
||||||
|
for code in string.gmatch(s, "%d+") do
|
||||||
|
codes[code] = true
|
||||||
|
end
|
||||||
|
local list = {}
|
||||||
|
for k, _ in pairs(codes) do
|
||||||
|
table.insert(list, k)
|
||||||
|
end
|
||||||
|
return list
|
||||||
|
end
|
||||||
|
|
||||||
|
local function hasSharedAlphaNumCode(a, b)
|
||||||
|
local codes1 = extractAlphaNumCodes(a)
|
||||||
|
local codes2 = extractAlphaNumCodes(b)
|
||||||
|
if #codes1 == 0 or #codes2 == 0 then return false end
|
||||||
|
for _, c1 in ipairs(codes1) do
|
||||||
|
for _, c2 in ipairs(codes2) do
|
||||||
|
if c1 == c2 then return true end
|
||||||
|
local lc1, lc2 = string.lower(c1), string.lower(c2)
|
||||||
|
if lc1 == lc2 then return true end
|
||||||
|
if #lc1 >= 3 and #lc2 >= 3 then
|
||||||
|
if string.find(lc1, lc2, 1, true) or string.find(lc2, lc1, 1, true) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local function looksLikeValidDestinationText(text)
|
local function looksLikeValidDestinationText(text)
|
||||||
if not text then return false end
|
if not text then return false end
|
||||||
local s = tostring(text)
|
local s = tostring(text)
|
||||||
@@ -3053,7 +3092,10 @@ local function looksLikeValidDestinationText(text)
|
|||||||
local c = string.sub(s, i, i)
|
local c = string.sub(s, i, i)
|
||||||
if c == "?" then questionMarkCount = questionMarkCount + 1 end
|
if c == "?" then questionMarkCount = questionMarkCount + 1 end
|
||||||
end
|
end
|
||||||
if #s > 0 and questionMarkCount / #s >= 0.5 then return false end
|
if #s > 0 and questionMarkCount / #s >= 0.5 then
|
||||||
|
local codes = extractAlphaNumCodes(s)
|
||||||
|
if #codes == 0 then return false end
|
||||||
|
end
|
||||||
local hasRealChar = false
|
local hasRealChar = false
|
||||||
for i = 1, #s do
|
for i = 1, #s do
|
||||||
local b = string.byte(s, i)
|
local b = string.byte(s, i)
|
||||||
@@ -3066,7 +3108,7 @@ local function looksLikeValidDestinationText(text)
|
|||||||
return isStationDestination(s)
|
return isStationDestination(s)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function tryCorrectUpcomingEntryWithCurrentTrain(entry)
|
local function tryCorrectUpcomingEntryWithCurrentTrain(entry, etaSeconds)
|
||||||
if not State.currentTrain or not entry then return entry end
|
if not State.currentTrain or not entry then return entry end
|
||||||
local ctId = State.currentTrain.id
|
local ctId = State.currentTrain.id
|
||||||
local ctDest = State.currentTrain.dest
|
local ctDest = State.currentTrain.dest
|
||||||
@@ -3077,7 +3119,29 @@ local function tryCorrectUpcomingEntryWithCurrentTrain(entry)
|
|||||||
if ctId and entry.trainName then
|
if ctId and entry.trainName then
|
||||||
sameTrain = Utils.isSameTrain(ctId, entry.trainName)
|
sameTrain = Utils.isSameTrain(ctId, entry.trainName)
|
||||||
end
|
end
|
||||||
if not sameTrain and not samePlatform then return entry end
|
|
||||||
|
local platformNum = tonumber((string.gsub(entryPlatform, "%D", "")))
|
||||||
|
local ctPlatformNum = tonumber((string.gsub(ctPlatform, "%D", "")))
|
||||||
|
local nearbyPlatform = false
|
||||||
|
if platformNum and ctPlatformNum then
|
||||||
|
nearbyPlatform = (math.abs(platformNum - ctPlatformNum) <= 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local sharedCodeDest = hasSharedAlphaNumCode(entry.dest, ctDest)
|
||||||
|
local sharedCodeTrain = hasSharedAlphaNumCode(entry.trainName, ctId)
|
||||||
|
|
||||||
|
local etaAtStation = (type(etaSeconds) == "number" and etaSeconds <= 0.5)
|
||||||
|
local destInvalid = not looksLikeValidDestinationText(entry.dest)
|
||||||
|
local idInvalid = not looksLikeValidDestinationText(entry.trainName)
|
||||||
|
|
||||||
|
local shouldCorrect = samePlatform or sameTrain
|
||||||
|
or (sharedCodeDest and (nearbyPlatform or etaAtStation))
|
||||||
|
or (sharedCodeTrain and (nearbyPlatform or etaAtStation))
|
||||||
|
or ((destInvalid or idInvalid) and etaAtStation)
|
||||||
|
or (destInvalid and idInvalid and nearbyPlatform)
|
||||||
|
|
||||||
|
if not shouldCorrect then return entry end
|
||||||
|
|
||||||
local validId = looksLikeValidDestinationText(entry.trainName)
|
local validId = looksLikeValidDestinationText(entry.trainName)
|
||||||
local validDest = looksLikeValidDestinationText(entry.dest)
|
local validDest = looksLikeValidDestinationText(entry.dest)
|
||||||
|
|
||||||
@@ -3085,19 +3149,25 @@ local function tryCorrectUpcomingEntryWithCurrentTrain(entry)
|
|||||||
entry.trainName = ctId
|
entry.trainName = ctId
|
||||||
end
|
end
|
||||||
if sameTrain and ctId and ctId ~= "" and tostring(entry.trainName or "") ~= tostring(ctId) then
|
if sameTrain and ctId and ctId ~= "" and tostring(entry.trainName or "") ~= tostring(ctId) then
|
||||||
if Utils.isFuzzyMatch(entry.trainName or "", ctId) or not validId then
|
if Utils.isFuzzyMatch(entry.trainName or "", ctId) or not validId or sharedCodeTrain then
|
||||||
entry.trainName = ctId
|
entry.trainName = ctId
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if ctId and ctId ~= "" and tostring(entry.trainName or "") ~= tostring(ctId) and sharedCodeTrain and (etaAtStation or samePlatform or idInvalid) then
|
||||||
|
entry.trainName = ctId
|
||||||
|
end
|
||||||
|
|
||||||
if not validDest and ctDest and ctDest ~= "" then
|
if not validDest and ctDest and ctDest ~= "" then
|
||||||
entry.dest = ctDest
|
entry.dest = ctDest
|
||||||
end
|
end
|
||||||
if (sameTrain or samePlatform) and ctDest and ctDest ~= "" and tostring(entry.dest or "") ~= tostring(ctDest) then
|
if (sameTrain or samePlatform or sharedCodeDest) and ctDest and ctDest ~= "" and tostring(entry.dest or "") ~= tostring(ctDest) then
|
||||||
if Utils.isFuzzyMatch(entry.dest or "", ctDest) or not validDest then
|
if Utils.isFuzzyMatch(entry.dest or "", ctDest) or not validDest or sharedCodeDest or etaAtStation then
|
||||||
entry.dest = ctDest
|
entry.dest = ctDest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if ctDest and ctDest ~= "" and tostring(entry.dest or "") ~= tostring(ctDest) and sharedCodeDest and (etaAtStation or samePlatform or destInvalid) then
|
||||||
|
entry.dest = ctDest
|
||||||
|
end
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
end
|
end
|
||||||
@@ -3125,6 +3195,16 @@ local function checkIsAtStationWithCurrentTrain(trainName, destination, platform
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if not sameTrain and hasSharedAlphaNumCode(trainName, ctId) then
|
||||||
|
sameTrain = true
|
||||||
|
end
|
||||||
|
if not sameTrain and (not looksLikeValidDestinationText(trainName)) and (not looksLikeValidDestinationText(destination)) then
|
||||||
|
local pNum = tonumber((string.gsub(trainPlatform, "%D", "")))
|
||||||
|
local ctPNum = tonumber((string.gsub(ctPlatform, "%D", "")))
|
||||||
|
if pNum and ctPNum and math.abs(pNum - ctPNum) <= 1 then
|
||||||
|
sameTrain = true
|
||||||
|
end
|
||||||
|
end
|
||||||
if sameTrain then
|
if sameTrain then
|
||||||
local entryIdValid = looksLikeValidDestinationText(trainName)
|
local entryIdValid = looksLikeValidDestinationText(trainName)
|
||||||
if entryIdValid then
|
if entryIdValid then
|
||||||
@@ -3136,6 +3216,9 @@ local function checkIsAtStationWithCurrentTrain(trainName, destination, platform
|
|||||||
if not looksLikeValidDestinationText(destination) then
|
if not looksLikeValidDestinationText(destination) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
if hasSharedAlphaNumCode(destination, ctDest) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
@@ -3223,20 +3306,6 @@ function Main.loop()
|
|||||||
platform = State.stationPlatform or "1"
|
platform = State.stationPlatform or "1"
|
||||||
end
|
end
|
||||||
|
|
||||||
local preCorrected = tryCorrectUpcomingEntryWithCurrentTrain({
|
|
||||||
trainName = trainName,
|
|
||||||
dest = destination,
|
|
||||||
platform = platform
|
|
||||||
})
|
|
||||||
if preCorrected then
|
|
||||||
if preCorrected.trainName and tostring(preCorrected.trainName) ~= tostring(trainName) then
|
|
||||||
trainName = preCorrected.trainName
|
|
||||||
end
|
|
||||||
if preCorrected.dest and tostring(preCorrected.dest) ~= tostring(destination) then
|
|
||||||
destination = preCorrected.dest
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if isStationDestination(destination) then
|
if isStationDestination(destination) then
|
||||||
local cancelled = false
|
local cancelled = false
|
||||||
local reason = nil
|
local reason = nil
|
||||||
@@ -3261,6 +3330,21 @@ function Main.loop()
|
|||||||
local etaTicks = realArrival - currentTick
|
local etaTicks = realArrival - currentTick
|
||||||
local etaSeconds = etaTicks / (State.tickRate or 20)
|
local etaSeconds = etaTicks / (State.tickRate or 20)
|
||||||
if etaSeconds < 0 then etaSeconds = 0 end
|
if etaSeconds < 0 then etaSeconds = 0 end
|
||||||
|
|
||||||
|
local preCorrected = tryCorrectUpcomingEntryWithCurrentTrain({
|
||||||
|
trainName = trainName,
|
||||||
|
dest = destination,
|
||||||
|
platform = platform
|
||||||
|
}, etaSeconds)
|
||||||
|
if preCorrected then
|
||||||
|
if preCorrected.trainName and tostring(preCorrected.trainName) ~= tostring(trainName) then
|
||||||
|
trainName = preCorrected.trainName
|
||||||
|
end
|
||||||
|
if preCorrected.dest and tostring(preCorrected.dest) ~= tostring(destination) then
|
||||||
|
destination = preCorrected.dest
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local announceKey = normalizeUpcomingKey(trainName, destination)
|
local announceKey = normalizeUpcomingKey(trainName, destination)
|
||||||
local etaLabel = buildEtaLabel(etaSeconds, etaTextByKey[announceKey])
|
local etaLabel = buildEtaLabel(etaSeconds, etaTextByKey[announceKey])
|
||||||
|
|
||||||
@@ -3383,24 +3467,7 @@ function Main.loop()
|
|||||||
platform, etaStr, tName, dest = string.match(cleanLine, "^([^%s]+)%s+(.-)%s+([^%s]+)%s+(.*)$")
|
platform, etaStr, tName, dest = string.match(cleanLine, "^([^%s]+)%s+(.-)%s+([^%s]+)%s+(.*)$")
|
||||||
end
|
end
|
||||||
|
|
||||||
local entryPlatform = platform or State.stationPlatform or "1"
|
|
||||||
local preCorrectedCT = tryCorrectUpcomingEntryWithCurrentTrain({
|
|
||||||
trainName = tName or "",
|
|
||||||
dest = dest or "",
|
|
||||||
platform = entryPlatform
|
|
||||||
})
|
|
||||||
if preCorrectedCT then
|
|
||||||
if preCorrectedCT.trainName and tostring(preCorrectedCT.trainName) ~= tostring(tName or "") then
|
|
||||||
tName = preCorrectedCT.trainName
|
|
||||||
end
|
|
||||||
if preCorrectedCT.dest and tostring(preCorrectedCT.dest) ~= tostring(dest or "") then
|
|
||||||
dest = preCorrectedCT.dest
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if tName and etaStr and isStationDestination(dest) then
|
if tName and etaStr and isStationDestination(dest) then
|
||||||
local announceKey = normalizeUpcomingKey(tName, dest)
|
|
||||||
|
|
||||||
local etaSeconds = -1
|
local etaSeconds = -1
|
||||||
local isNow = string.find(etaStr, "现在")
|
local isNow = string.find(etaStr, "现在")
|
||||||
|
|
||||||
@@ -3426,6 +3493,23 @@ function Main.loop()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local entryPlatform = platform or State.stationPlatform or "1"
|
||||||
|
local preCorrectedCT = tryCorrectUpcomingEntryWithCurrentTrain({
|
||||||
|
trainName = tName or "",
|
||||||
|
dest = dest or "",
|
||||||
|
platform = entryPlatform
|
||||||
|
}, etaSeconds >= 0 and etaSeconds or 0)
|
||||||
|
if preCorrectedCT then
|
||||||
|
if preCorrectedCT.trainName and tostring(preCorrectedCT.trainName) ~= tostring(tName or "") then
|
||||||
|
tName = preCorrectedCT.trainName
|
||||||
|
end
|
||||||
|
if preCorrectedCT.dest and tostring(preCorrectedCT.dest) ~= tostring(dest or "") then
|
||||||
|
dest = preCorrectedCT.dest
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local announceKey = normalizeUpcomingKey(tName, dest)
|
||||||
|
|
||||||
table.insert(newUpcoming, {
|
table.insert(newUpcoming, {
|
||||||
trainName = tName,
|
trainName = tName,
|
||||||
dest = dest,
|
dest = dest,
|
||||||
@@ -3511,7 +3595,7 @@ function Main.loop()
|
|||||||
|
|
||||||
|
|
||||||
for _, entry in ipairs(newUpcoming) do
|
for _, entry in ipairs(newUpcoming) do
|
||||||
tryCorrectUpcomingEntryWithCurrentTrain(entry)
|
tryCorrectUpcomingEntryWithCurrentTrain(entry, entry.eta)
|
||||||
end
|
end
|
||||||
|
|
||||||
State.upcomingTrains = newUpcoming
|
State.upcomingTrains = newUpcoming
|
||||||
|
|||||||
Reference in New Issue
Block a user