diff --git a/CloudServer/server.js b/CloudServer/server.js index efc4936..2501e6e 100644 --- a/CloudServer/server.js +++ b/CloudServer/server.js @@ -2139,7 +2139,10 @@ function handleTrainArrival(ws, data) { const lineCode = data.lineCode || (stationCode ? stationCode.split('-')[0] : 'UNK'); const destCode = data.destCode || getStationCodeFromName(data.destination) || 'UNK'; - const nextCode = data.nextCode || getStationCodeFromName(data.nextStation) || 'UNK'; + const nextStationRaw = data.nextStation ? String(data.nextStation).trim() : ''; + const nextCodeRaw = data.nextCode ? String(data.nextCode).trim() : (nextStationRaw ? getStationCodeFromName(nextStationRaw) : ''); + const hasNextStation = nextStationRaw && nextStationRaw !== '' && nextCodeRaw && nextCodeRaw !== 'UNK' && nextCodeRaw !== ''; + const finalNextCode = hasNextStation ? nextCodeRaw : null; const existingIndex = activeTrains.findIndex(t => t.trainId === trainId); const trainData = { @@ -2155,7 +2158,7 @@ function handleTrainArrival(ws, data) { activeTrains.push(trainData); } - log('INFO', `Train ${trainId} arrived at ${stationName}. Broadcasting...`); + log('INFO', `Train ${trainId} arrived at ${stationName}. Broadcasting... nextStation=${nextStationRaw || '(none/terminal)'} nextCode=${finalNextCode || '(none)'}`); saveData(); broadcastUpdate(); @@ -2173,11 +2176,18 @@ function handleTrainArrival(ws, data) { })); // Broadcast Audio Logic - const seq = [ - 'ksts', - `ja-${finalPlatform}`, 'ja-zt', `ja-${lineCode}`, `ja-${destCode}`, 'ja-to', 'ja-nextsta', `ja-${nextCode}`, 'ja-warn', - `ch-${finalPlatform}`, 'ch-zt', `ch-${lineCode}`, 'ch-to', `ch-${destCode}`, 'ch-nextsta', `ch-${nextCode}`, 'ch-warn' - ]; + const seq = ['ksts']; + if (finalNextCode) { + seq.push( + `ja-${finalPlatform}`, 'ja-zt', `ja-${lineCode}`, `ja-${destCode}`, 'ja-to', 'ja-nextsta', `ja-${finalNextCode}`, 'ja-warn', + `ch-${finalPlatform}`, 'ch-zt', `ch-${lineCode}`, 'ch-to', `ch-${destCode}`, 'ch-nextsta', `ch-${finalNextCode}`, 'ch-warn' + ); + } else { + seq.push( + `ja-${finalPlatform}`, 'ja-zt', `ja-${lineCode}`, `ja-${destCode}`, 'ja-warn', + `ch-${finalPlatform}`, 'ch-zt', `ch-${lineCode}`, 'ch-to', `ch-${destCode}`, 'ch-warn' + ); + } enqueueHlsPush(stationName, seq); diff --git a/station_broadcast.lua b/station_broadcast.lua index d52a197..7dc64ac 100644 --- a/station_broadcast.lua +++ b/station_broadcast.lua @@ -1,6 +1,6 @@ -- 1. Configuration & Constants -local APP_VERSION_TEXT = "v1.0.69" +local APP_VERSION_TEXT = "v1.0.70" local CONFIG = { CLOUD_URL = "ws://stabadmin.fse-media.group", @@ -975,7 +975,6 @@ function Utils.getNextStation(schedule, currentStationName) end if matchFoundIndex then - -- Search forward for i = matchFoundIndex + 1, maxIdx do local entry = schedule.entries[i] if entry and entry.instruction then @@ -985,16 +984,6 @@ function Utils.getNextStation(schedule, currentStationName) end end end - -- Loop around to beginning - for i = 1, matchFoundIndex - 1 do - local entry = schedule.entries[i] - if entry and entry.instruction then - local inst = entry.instruction - if inst.id == "create:station" or inst.id == "create:destination" then - return (inst.data and inst.data.text) or inst.text - end - end - end end return nil @@ -3053,6 +3042,99 @@ local function isStationDestination(destName) return true end +local function looksLikeValidDestinationText(text) + if not text then return false end + local s = tostring(text) + if s == "" then return false end + local lower = string.lower(s) + if lower == "unknown" then return false end + local questionMarkCount = 0 + for i = 1, #s do + 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 + local hasRealChar = false + for i = 1, #s do + local b = string.byte(s, i) + if b and b >= 48 and b <= 57 then hasRealChar = true break end + if b and b >= 65 and b <= 90 then hasRealChar = true break end + if b and b >= 97 and b <= 122 then hasRealChar = true break end + if b and b >= 128 then hasRealChar = true break end + end + if not hasRealChar then return false end + return isStationDestination(s) +end + +local function tryCorrectUpcomingEntryWithCurrentTrain(entry) + if not State.currentTrain or not entry then return entry end + local ctId = State.currentTrain.id + local ctDest = State.currentTrain.dest + local ctPlatform = tostring(State.stationPlatform or State.currentTrain.platform or "1") + local entryPlatform = tostring(entry.platform or "1") + local samePlatform = (entryPlatform == ctPlatform) + local sameTrain = false + if ctId and entry.trainName then + sameTrain = Utils.isSameTrain(ctId, entry.trainName) + end + if not sameTrain and not samePlatform then return entry end + local validId = looksLikeValidDestinationText(entry.trainName) + local validDest = looksLikeValidDestinationText(entry.dest) + if not validId and ctId and ctId ~= "" then + entry.trainName = ctId + end + if not validDest and ctDest and ctDest ~= "" then + entry.dest = ctDest + elseif sameTrain and ctDest and ctDest ~= "" then + if not Utils.isFuzzyMatch(entry.dest or "", ctDest) then + local entryDestValid = looksLikeValidDestinationText(entry.dest) + if not entryDestValid then + entry.dest = ctDest + end + end + end + return entry +end + +local function checkIsAtStationWithCurrentTrain(trainName, destination, platform) + if not State.currentTrain then return false end + local ctId = State.currentTrain.id + local ctDest = State.currentTrain.dest + local ctPlatform = tostring(State.stationPlatform or State.currentTrain.platform or "1") + local trainPlatform = tostring(platform or "1") + if trainPlatform == ctPlatform then + return true + end + local sameTrain = false + if ctId and trainName then + if ctId == trainName then + sameTrain = true + else + local validCT = looksLikeValidDestinationText(ctId) + local validEntry = looksLikeValidDestinationText(trainName) + if validCT and validEntry then + sameTrain = Utils.isSameTrain(ctId, trainName) + elseif (not validEntry) and validCT then + sameTrain = Utils.isFuzzyMatch(ctDest or "", destination or "") + end + end + end + if sameTrain then + local entryIdValid = looksLikeValidDestinationText(trainName) + if entryIdValid then + return true + else + if Utils.isFuzzyMatch(ctDest or "", destination or "") then + return true + end + if not looksLikeValidDestinationText(destination) then + return true + end + end + end + return false +end + function Main.loop() while true do local now = os.epoch("utc") @@ -3204,23 +3286,7 @@ function Main.loop() end end - local isAtStation = false - local trainPlatform = tostring(platform or State.stationPlatform or "1") - local currentPlatform = tostring(State.stationPlatform or "1") - - if State.currentTrain then - if trainPlatform == currentPlatform then - isAtStation = true - elseif State.currentTrain.id == trainName then - if trainName == "???" or trainName == "Unknown" or trainName == "" then - if Utils.isFuzzyMatch(State.currentTrain.dest, destination) then - isAtStation = true - end - else - isAtStation = true - end - end - end + local isAtStation = checkIsAtStationWithCurrentTrain(trainName, destination, platform) if not isAtStation and etaSeconds > 0 and etaSeconds <= 45 then if not seenApproachKeys[announceKey] then seenApproachKeys[announceKey] = true @@ -3358,23 +3424,7 @@ function Main.loop() end end - local isAtStation = false - local trainPlatform = tostring(platform or State.stationPlatform or "1") - local currentPlatform = tostring(State.stationPlatform or "1") - - if State.currentTrain then - if trainPlatform == currentPlatform then - isAtStation = true - elseif State.currentTrain.id == tName then - if tName == "???" or tName == "Unknown" or tName == "" then - if Utils.isFuzzyMatch(State.currentTrain.dest, dest) then - isAtStation = true - end - else - isAtStation = true - end - end - end + local isAtStation = checkIsAtStationWithCurrentTrain(tName, dest, platform or State.stationPlatform or "1") if not isAtStation and etaSeconds > 0 and etaSeconds <= 45 then if not seenApproachKeys[announceKey] then seenApproachKeys[announceKey] = true @@ -3424,6 +3474,10 @@ function Main.loop() end + for _, entry in ipairs(newUpcoming) do + tryCorrectUpcomingEntryWithCurrentTrain(entry) + end + State.upcomingTrains = newUpcoming if not Peripherals.station then