diff --git a/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts b/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts index 76e3474..9b87919 100644 --- a/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts +++ b/src/repositories/shuttle/eta/RedisSelfUpdatingETARepository.ts @@ -3,7 +3,7 @@ import { BaseRedisETARepository } from "./BaseRedisETARepository"; import { createClient, RedisClientType } from "redis"; import { ShuttleGetterRepository, ShuttleRepositoryEvent, ShuttleStopArrival, ShuttleTravelTimeDataIdentifier, ShuttleTravelTimeDateFilterArguments } from "../ShuttleGetterRepository"; import { REDIS_RECONNECT_INTERVAL } from "../../../environment"; -import { IShuttle } from "../../../entities/ShuttleRepositoryEntities"; +import { IOrderedStop, IShuttle } from "../../../entities/ShuttleRepositoryEntities"; export class RedisSelfUpdatingETARepository extends BaseRedisETARepository implements SelfUpdatingETARepository { constructor( @@ -95,20 +95,43 @@ export class RedisSelfUpdatingETARepository extends BaseRedisETARepository imple if (!lastStop) return; const lastOrderedStop = await this.shuttleRepository.getOrderedStopByRouteAndStopId(shuttle.routeId, lastStop.stopId); - const nextStop = lastOrderedStop?.nextStop; + + await this.updateCascadingEta({ + shuttle, + currentStop: lastOrderedStop, + originalStopArrival: lastStop, + }); + } + + private async updateCascadingEta({ + shuttle, + currentStop, + originalStopArrival, + runningTravelTimeSeconds = 0 + }: { + shuttle: IShuttle; + currentStop: IOrderedStop | null; + originalStopArrival: ShuttleStopArrival; + runningTravelTimeSeconds?: number; + }) { + if (!currentStop) return; + const nextStop = currentStop?.nextStop; if (!nextStop) return; + // In case the system we have loops around + if (nextStop.stopId === originalStopArrival.stopId) return; let referenceCurrentTime = new Date(); if (this.referenceTime != null) { referenceCurrentTime = this.referenceTime; } + const oneWeekAgo = new Date(referenceCurrentTime.getTime() - (60 * 60 * 24 * 7 * 1000)); const oneDayAgo = new Date(referenceCurrentTime.getTime() - (60 * 60 * 24 * 1000)); const oneHourAgo = new Date(referenceCurrentTime.getTime() - (60 * 60 * 1000)); const travelTimeSeconds = await this.getAverageTravelTimeSecondsWithFallbacks({ routeId: shuttle.routeId, - fromStopId: lastStop.stopId, + fromStopId: currentStop.stopId, toStopId: nextStop.stopId, }, [ { @@ -127,10 +150,9 @@ export class RedisSelfUpdatingETARepository extends BaseRedisETARepository imple if (travelTimeSeconds == undefined) return; - const elapsedTimeMs = referenceCurrentTime.getTime() - lastStop.timestamp.getTime(); - const predictedTimeSeconds = travelTimeSeconds - (elapsedTimeMs / 1000); + const elapsedTimeMs = referenceCurrentTime.getTime() - originalStopArrival.timestamp.getTime(); + const predictedTimeSeconds = travelTimeSeconds - (elapsedTimeMs / 1000) + runningTravelTimeSeconds; - // TODO: update multiple ETAs await this.addOrUpdateEta({ secondsRemaining: predictedTimeSeconds, shuttleId: shuttle.id, @@ -138,8 +160,19 @@ export class RedisSelfUpdatingETARepository extends BaseRedisETARepository imple systemId: nextStop.systemId, updatedTime: new Date(), }); + + const nextStopWithNextNextStop = await this.shuttleRepository.getOrderedStopByRouteAndStopId(shuttle.routeId, nextStop.stopId); + await this.updateCascadingEta( + { + shuttle, + currentStop: nextStopWithNextNextStop, + originalStopArrival, + runningTravelTimeSeconds: runningTravelTimeSeconds + travelTimeSeconds, + }, + ) } + private async handleShuttleWillArriveAtStop( shuttleArrival: ShuttleStopArrival, ) {