From cd5b1d47b01e06dd438d453a87a2a7ad31ef8693 Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Sun, 16 Aug 2026 13:25:39 +0800 Subject: [PATCH] =?UTF-8?q?fix(crn):=20=E4=BF=AE=E5=A4=8DCRN=E8=81=9A?= =?UTF-8?q?=E5=90=88=E7=AB=99(=E5=A6=82=E3=80=8C=E5=8D=83=E5=8F=B6?= =?UTF-8?q?=E3=80=8D)=E5=9C=A8CC=E4=B8=AD=E6=96=87=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E4=B8=8B=E5=8F=98=3F=3F=3F=3F=E5=AF=BC=E8=87=B4=E6=A0=A1?= =?UTF-8?q?=E6=AD=A3=E5=8C=B9=E9=85=8D=E5=A4=B1=E8=B4=A5=E5=BC=95=E5=8F=91?= =?UTF-8?q?=E7=BB=88=E7=82=B9=E7=AB=99=E5=B9=BF=E6=92=AD=E6=BC=8F=E6=92=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 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 --- station_broadcast.lua | 162 ++++++++++++++++++++++++++++++++---------- 1 file changed, 123 insertions(+), 39 deletions(-) diff --git a/station_broadcast.lua b/station_broadcast.lua index e329200..724beef 100644 --- a/station_broadcast.lua +++ b/station_broadcast.lua @@ -1,6 +1,6 @@ -- 1. Configuration & Constants -local APP_VERSION_TEXT = "v1.0.71" +local APP_VERSION_TEXT = "v1.0.72" local CONFIG = { CLOUD_URL = "ws://stabadmin.fse-media.group", @@ -3042,6 +3042,45 @@ local function isStationDestination(destName) return true 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) if not text then return false end local s = tostring(text) @@ -3053,7 +3092,10 @@ local function looksLikeValidDestinationText(text) local c = string.sub(s, i, i) if c == "?" then questionMarkCount = questionMarkCount + 1 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 for i = 1, #s do local b = string.byte(s, i) @@ -3066,7 +3108,7 @@ local function looksLikeValidDestinationText(text) return isStationDestination(s) end -local function tryCorrectUpcomingEntryWithCurrentTrain(entry) +local function tryCorrectUpcomingEntryWithCurrentTrain(entry, etaSeconds) if not State.currentTrain or not entry then return entry end local ctId = State.currentTrain.id local ctDest = State.currentTrain.dest @@ -3077,7 +3119,29 @@ local function tryCorrectUpcomingEntryWithCurrentTrain(entry) if ctId and entry.trainName then sameTrain = Utils.isSameTrain(ctId, entry.trainName) 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 validDest = looksLikeValidDestinationText(entry.dest) @@ -3085,19 +3149,25 @@ local function tryCorrectUpcomingEntryWithCurrentTrain(entry) entry.trainName = ctId end 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 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 entry.dest = ctDest end - if (sameTrain or samePlatform) and ctDest and ctDest ~= "" and tostring(entry.dest or "") ~= tostring(ctDest) then - if Utils.isFuzzyMatch(entry.dest or "", ctDest) or not validDest 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 or sharedCodeDest or etaAtStation then entry.dest = ctDest 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 end @@ -3125,6 +3195,16 @@ local function checkIsAtStationWithCurrentTrain(trainName, destination, platform 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 local entryIdValid = looksLikeValidDestinationText(trainName) if entryIdValid then @@ -3136,6 +3216,9 @@ local function checkIsAtStationWithCurrentTrain(trainName, destination, platform if not looksLikeValidDestinationText(destination) then return true end + if hasSharedAlphaNumCode(destination, ctDest) then + return true + end end end return false @@ -3222,20 +3305,6 @@ function Main.loop() else platform = State.stationPlatform or "1" 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 local cancelled = false @@ -3261,6 +3330,21 @@ function Main.loop() local etaTicks = realArrival - currentTick local etaSeconds = etaTicks / (State.tickRate or 20) 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 etaLabel = buildEtaLabel(etaSeconds, etaTextByKey[announceKey]) @@ -3382,25 +3466,8 @@ function Main.loop() if not tName then platform, etaStr, tName, dest = string.match(cleanLine, "^([^%s]+)%s+(.-)%s+([^%s]+)%s+(.*)$") 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 - local announceKey = normalizeUpcomingKey(tName, dest) - local etaSeconds = -1 local isNow = string.find(etaStr, "现在") @@ -3426,6 +3493,23 @@ function Main.loop() 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, { trainName = tName, dest = dest, @@ -3511,7 +3595,7 @@ function Main.loop() for _, entry in ipairs(newUpcoming) do - tryCorrectUpcomingEntryWithCurrentTrain(entry) + tryCorrectUpcomingEntryWithCurrentTrain(entry, entry.eta) end State.upcomingTrains = newUpcoming