mirror of
https://github.com/tonytins/amtkstat.git
synced 2026-10-24 05:32:54 -04:00
Added handling for stale trains
- Renamed TrainLateness to LateTrain
This commit is contained in:
parent
e0077ec13b
commit
f8eef909d2
5 changed files with 72 additions and 17 deletions
|
|
@ -28,6 +28,10 @@ struct AmtrakClient {
|
||||||
try await get(trainsBaseURL)
|
try await get(trainsBaseURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchStaleStatus() async throws -> StaleData {
|
||||||
|
try await get(staleBaseURL)
|
||||||
|
}
|
||||||
|
|
||||||
func fetchAllTrainStatus(num trainNum: String) async throws -> [Train] {
|
func fetchAllTrainStatus(num trainNum: String) async throws -> [Train] {
|
||||||
let reponse = try await fetchTrain(number: trainNum)
|
let reponse = try await fetchTrain(number: trainNum)
|
||||||
return reponse.values.flatMap(\.self)
|
return reponse.values.flatMap(\.self)
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ struct AmtrakDateFormatting {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func isOnTime(actual: String?, scheduled: String?) -> TrainLateness {
|
func isOnTime(actual: String?, scheduled: String?) -> LateTrain {
|
||||||
|
|
||||||
guard
|
guard
|
||||||
let actualDate = parsedDate(from: actual),
|
let actualDate = parsedDate(from: actual),
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ struct ContentView: View {
|
||||||
|
|
||||||
let amtrakDate = AmtrakDateFormatting()
|
let amtrakDate = AmtrakDateFormatting()
|
||||||
let unknown = "Unknown"
|
let unknown = "Unknown"
|
||||||
|
let staleDataThreshold: TimeInterval = 60 * 60 * 24 // 24 hours
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
|
|
@ -146,15 +147,15 @@ struct ContentView: View {
|
||||||
where: { $0.code == code
|
where: { $0.code == code
|
||||||
},
|
},
|
||||||
)?.platform
|
)?.platform
|
||||||
await newRows
|
let row = await trainStatus(
|
||||||
.append(
|
|
||||||
trainStatus(
|
|
||||||
for: train,
|
for: train,
|
||||||
atStationCode: code,
|
code: code,
|
||||||
timeZone: lookup.timeZone,
|
zone: lookup.timeZone,
|
||||||
zoneCache: &zoneCache
|
cache: &zoneCache
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
if let row {
|
||||||
|
newRows.append(row)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,11 +172,16 @@ struct ContentView: View {
|
||||||
|
|
||||||
func trainStatus(
|
func trainStatus(
|
||||||
for train: Train,
|
for train: Train,
|
||||||
atStationCode code: String,
|
code stationCode: String,
|
||||||
timeZone: TimeZone?,
|
zone timeZone: TimeZone?,
|
||||||
zoneCache: inout [String: TimeZone?]
|
cache zoneCache: inout [String: TimeZone?]
|
||||||
) async -> TrainStatusRow {
|
) async -> TrainStatusRow? {
|
||||||
let leg = train.stations?.first { $0.code == code }
|
let leg = train.stations?.first { $0.code == stationCode }
|
||||||
|
|
||||||
|
guard !isStale(leg, timeZone: timeZone) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
let stationName = leg?.name ?? unknown
|
let stationName = leg?.name ?? unknown
|
||||||
let track = leg?.platform ?? ""
|
let track = leg?.platform ?? ""
|
||||||
|
|
||||||
|
|
@ -216,6 +222,45 @@ struct ContentView: View {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isStale(_ leg: Station?, timeZone: TimeZone?) -> Bool {
|
||||||
|
guard leg?.status == .departed else { return false }
|
||||||
|
|
||||||
|
guard
|
||||||
|
let deparatureDate = amtrakDate.parsedDate(
|
||||||
|
from: leg?.dep
|
||||||
|
) ?? amtrakDate.parsedDate(from: leg?.schDep)
|
||||||
|
else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var calendar = Calendar.current
|
||||||
|
calendar.timeZone = timeZone ?? .current
|
||||||
|
return calendar
|
||||||
|
.compare(
|
||||||
|
deparatureDate,
|
||||||
|
to: Date(),
|
||||||
|
toGranularity: .day
|
||||||
|
) == .orderedAscending
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDataStale(
|
||||||
|
_ trainId: String,
|
||||||
|
staleness: [String: TimeInterval]
|
||||||
|
) -> Bool {
|
||||||
|
guard let timeSince = staleness[trainId] else { return false }
|
||||||
|
return timeSince > staleDataThreshold
|
||||||
|
}
|
||||||
|
|
||||||
|
func staleTrainLookup() async -> [String: TimeInterval] {
|
||||||
|
guard let staleData = try? await client.fetchStaleStatus() else {
|
||||||
|
return [:]
|
||||||
|
}
|
||||||
|
return Dictionary(
|
||||||
|
staleData.lastUpdatedArr.map { ( $0.trainID, $0.timeSince) },
|
||||||
|
uniquingKeysWith: { first, _ in first }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func fetchTimeZone(forStationCode code: String, cache: inout [String: TimeZone?]) async -> TimeZone? {
|
func fetchTimeZone(forStationCode code: String, cache: inout [String: TimeZone?]) async -> TimeZone? {
|
||||||
if let cached = cache[code] {
|
if let cached = cache[code] {
|
||||||
return cached
|
return cached
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import SwiftCrossUI
|
import SwiftCrossUI
|
||||||
|
|
||||||
enum TrainLateness {
|
enum LateTrain {
|
||||||
case onTime
|
case onTime
|
||||||
case early(minutes: Int)
|
case early(minutes: Int)
|
||||||
case late(minutes: Int)
|
case late(minutes: Int)
|
||||||
|
|
@ -81,9 +81,15 @@ struct StationMeta: Codable {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StaleData: Codable {
|
struct StaleData: Codable {
|
||||||
var avgLastUpdate: Double
|
|
||||||
var activeTrains: Int
|
var activeTrains: Int
|
||||||
var stale: Bool
|
var avgLastUpdate: Double
|
||||||
|
var lastUpdatedArr: [TrainFreshness]
|
||||||
|
var medianLastUpdate: Double
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TrainFreshness: Codable, Sendable {
|
||||||
|
var trainID: String
|
||||||
|
var timeSince: Double
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias TrainResponse = [String: [Train]]
|
typealias TrainResponse = [String: [Train]]
|
||||||
|
|
@ -99,6 +105,6 @@ struct TrainStatusRow: Identifiable {
|
||||||
var train: String
|
var train: String
|
||||||
var to: String
|
var to: String
|
||||||
var from: String
|
var from: String
|
||||||
var status: TrainLateness
|
var status: LateTrain
|
||||||
var track: String
|
var track: String
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue