From 4b37f3a12100d949cbb4f43552816ba53f359f88 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Tue, 11 Nov 2025 19:34:05 -0800 Subject: [PATCH] Add a helper method for setting the "reference time" of the self-updating repo --- .../eta/InMemorySelfUpdatingETARepository.ts | 3 ++ .../eta/RedisSelfUpdatingETARepository.ts | 53 +++++++++++++++++-- .../shuttle/eta/SelfUpdatingETARepository.ts | 7 +++ 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/repositories/shuttle/eta/InMemorySelfUpdatingETARepository.ts b/src/repositories/shuttle/eta/InMemorySelfUpdatingETARepository.ts index de42361..a94955d 100644 --- a/src/repositories/shuttle/eta/InMemorySelfUpdatingETARepository.ts +++ b/src/repositories/shuttle/eta/InMemorySelfUpdatingETARepository.ts @@ -8,6 +8,9 @@ export class InMemorySelfUpdatingETARepository extends BaseInMemoryETARepository ) { super(); } + setReferenceTime(referenceTime: Date): void { + throw new Error("Method not implemented."); + } getAverageTravelTimeSeconds(identifier: ShuttleTravelTimeDataIdentifier, dateFilter: ShuttleTravelTimeDateFilterArguments): Promise { throw new Error("Method not implemented."); diff --git a/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts b/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts index 5899cfd..971c21e 100644 --- a/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts +++ b/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts @@ -16,30 +16,73 @@ export class RedisSelfUpdatingETARepository extends BaseRedisETARepository imple reconnectStrategy: REDIS_RECONNECT_INTERVAL, }, }), + private referenceTime: Date | null = null, ) { super(redisClient); } + setReferenceTime(referenceTime: Date) { + this.referenceTime = referenceTime; + } + getAverageTravelTimeSeconds(identifier: ShuttleTravelTimeDataIdentifier, dateFilter: ShuttleTravelTimeDateFilterArguments): Promise { throw new Error("Method not implemented."); } startListeningForUpdates() { this.shuttleRepository.addListener(ShuttleRepositoryEvent.SHUTTLE_UPDATED, this.handleShuttleUpdate); - this.shuttleRepository.addListener(ShuttleRepositoryEvent.SHUTTLE_WILL_ARRIVE_AT_STOP, this.handleShuttleArriveAtStop) + this.shuttleRepository.addListener(ShuttleRepositoryEvent.SHUTTLE_WILL_ARRIVE_AT_STOP, this.handleShuttleWillArriveAtStop) } stopListeningForUpdates() { this.shuttleRepository.removeListener(ShuttleRepositoryEvent.SHUTTLE_UPDATED, this.handleShuttleUpdate); - this.shuttleRepository.removeListener(ShuttleRepositoryEvent.SHUTTLE_WILL_ARRIVE_AT_STOP, this.handleShuttleArriveAtStop); + this.shuttleRepository.removeListener(ShuttleRepositoryEvent.SHUTTLE_WILL_ARRIVE_AT_STOP, this.handleShuttleWillArriveAtStop); } private handleShuttleUpdate(shuttle: IShuttle) { // TODO: handle shuttle update } - private handleShuttleArriveAtStop(shuttleArrival: ShuttleStopArrival) { - // TODO: handle shuttle arrive at stop - + private async handleShuttleWillArriveAtStop( + shuttleArrival: ShuttleStopArrival, + + ) { + const lastStop = await this.shuttleRepository.getShuttleLastStopArrival(shuttleArrival.shuttleId); + if (lastStop == undefined) return; + + const shuttle = await this.shuttleRepository.getShuttleById(shuttleArrival.shuttleId); + if (shuttle == null) return; + + let referenceCurrentTime = new Date(); + if (this.referenceTime != null) { + referenceCurrentTime = this.referenceTime; + } + + const oneWeekAgo = new Date(referenceCurrentTime.getTime() - (60 * 60 * 24 * 7 * 1000)); + + const lastOrderedStop = await this.shuttleRepository.getOrderedStopByRouteAndStopId(shuttle.routeId, lastStop.stopId); + const nextStop = lastOrderedStop?.nextStop; + if (nextStop == null) return; + + const travelTimeSeconds = await this.getAverageTravelTimeSeconds({ + routeId: shuttle.routeId, + fromStopId: lastStop.stopId, + toStopId: nextStop.stopId, + }, { + from: oneWeekAgo, + to: new Date(oneWeekAgo.getTime() + (60 * 60 * 1000)) + }); + if (travelTimeSeconds == undefined) return; + + const elapsedTimeMs = referenceCurrentTime.getTime() - lastStop.timestamp.getTime(); + const predictedTimeSeconds = travelTimeSeconds - (elapsedTimeMs / 1000); + + await this.addOrUpdateEta({ + secondsRemaining: predictedTimeSeconds, + shuttleId: shuttle.id, + stopId: nextStop.stopId, + systemId: nextStop.systemId, + updatedTime: new Date(), + }); } } diff --git a/src/repositories/shuttle/eta/SelfUpdatingETARepository.ts b/src/repositories/shuttle/eta/SelfUpdatingETARepository.ts index 331e1cc..4dae81a 100644 --- a/src/repositories/shuttle/eta/SelfUpdatingETARepository.ts +++ b/src/repositories/shuttle/eta/SelfUpdatingETARepository.ts @@ -18,4 +18,11 @@ export interface SelfUpdatingETARepository extends ETAGetterRepository { identifier: ShuttleTravelTimeDataIdentifier, dateFilter: ShuttleTravelTimeDateFilterArguments ): Promise; + + /** + * Set the "current time" as the class knows it, in order to calculate + * ETAs based on past data. + * @param referenceTime + */ + setReferenceTime(referenceTime: Date): void; }