Update shuttle repository implementations to remove ETA functionality

This commit is contained in:
2025-11-11 15:28:11 -08:00
parent 5eb40ff8a5
commit 747477cff4
2 changed files with 13 additions and 282 deletions

View File

@@ -1,9 +1,8 @@
import EventEmitter from "node:events";
import { ShuttleGetterSetterRepository } from "./ShuttleGetterSetterRepository";
import { IEta, IOrderedStop, IRoute, IShuttle, IStop, shuttleHasArrivedAtStop } from "../../entities/ShuttleRepositoryEntities";
import { IOrderedStop, IRoute, IShuttle, IStop, shuttleHasArrivedAtStop } from "../../entities/ShuttleRepositoryEntities";
import { IEntityWithId } from "../../entities/SharedEntities";
import {
ShuttleRepositoryEvent,
ShuttleRepositoryEventListener,
ShuttleRepositoryEventName,
ShuttleRepositoryEventPayloads,
@@ -71,7 +70,6 @@ export class UnoptimizedInMemoryShuttleRepository
private stops: IStop[] = [];
private routes: IRoute[] = [];
private shuttles: IShuttle[] = [];
private etas: IEta[] = [];
private orderedStops: IOrderedStop[] = [];
private shuttleLastStopArrivals: Map<string, ShuttleStopArrival> = new Map();
private travelTimeData: Map<string, Array<{ timestamp: number; seconds: number }>> = new Map();
@@ -104,18 +102,6 @@ export class UnoptimizedInMemoryShuttleRepository
return this.findEntityById(shuttleId, this.shuttles);
}
public async getEtasForShuttleId(shuttleId: string): Promise<IEta[]> {
return this.etas.filter(eta => eta.shuttleId === shuttleId);
}
public async getEtasForStopId(stopId: string) {
return this.etas.filter(eta => eta.stopId === stopId);
}
public async getEtaForShuttleAndStopId(shuttleId: string, stopId: string) {
return this.findEntityByMatcher<IEta>((value) => value.stopId === stopId && value.shuttleId === shuttleId, this.etas);
}
public async getOrderedStopByRouteAndStopId(routeId: string, stopId: string) {
return this.findEntityByMatcher<IOrderedStop>((value) => value.routeId === routeId && value.stopId === stopId, this.orderedStops)
}
@@ -161,8 +147,7 @@ export class UnoptimizedInMemoryShuttleRepository
this.shuttles.push(shuttle);
}
await this.updateLastStopArrivalAndTravelTimeDataPoints(shuttle, travelTimeTimestamp);
await this.updateEtasBasedOnHistoricalData(shuttle, referenceCurrentTime);
await this.updateLastStopArrival(shuttle, travelTimeTimestamp);
}
public async addOrUpdateStop(stop: IStop): Promise<void> {
@@ -183,89 +168,21 @@ export class UnoptimizedInMemoryShuttleRepository
}
}
private async addOrUpdateEta(eta: IEta): Promise<void> {
const index = this.etas.findIndex((e) => e.stopId === eta.stopId && e.shuttleId === eta.shuttleId);
if (index !== -1) {
this.etas[index] = eta;
} else {
this.etas.push(eta);
}
this.emit(ShuttleRepositoryEvent.ETA_UPDATED, eta);
}
public async addOrUpdateEtaFromExternalSource(eta: IEta): Promise<void> {
await this.addOrUpdateEta(eta);
}
private async updateEtasBasedOnHistoricalData(
shuttle: IShuttle,
referenceCurrentTime: Date = new Date(),
) {
const oneWeekAgo = new Date(referenceCurrentTime.getTime() - (60 * 60 * 24 * 7 * 1000));
const lastStopArrival = await this.getShuttleLastStopArrival(shuttle.id);
if (lastStopArrival == undefined) return;
const lastOrderedStop = await this.getOrderedStopByRouteAndStopId(shuttle.routeId, lastStopArrival.stopId);
const nextStop = lastOrderedStop?.nextStop;
if (nextStop == null) return;
const travelTimeSeconds = await this.getAverageTravelTimeSeconds({
routeId: shuttle.routeId,
fromStopId: lastStopArrival.stopId,
toStopId: nextStop.stopId,
}, {
from: oneWeekAgo,
to: new Date(oneWeekAgo.getTime() + (60 * 60 * 1000))
});
if (travelTimeSeconds == undefined) return;
const elapsedTimeMs = referenceCurrentTime.getTime() - lastStopArrival.timestamp.getTime();
const predictedTimeSeconds = travelTimeSeconds - (elapsedTimeMs / 1000);
await this.addOrUpdateEta({
secondsRemaining: predictedTimeSeconds,
shuttleId: shuttle.id,
stopId: nextStop.stopId,
systemId: nextStop.systemId,
updatedTime: new Date(),
});
}
private async updateLastStopArrivalAndTravelTimeDataPoints(
private async updateLastStopArrival(
shuttle: IShuttle,
travelTimeTimestamp = Date.now(),
) {
const arrivedStop = await this.getArrivedStopIfExists(shuttle);
if (arrivedStop != undefined) {
const lastStopTimestamp = await this.getShuttleLastStopArrival(shuttle.id);
if (lastStopTimestamp != undefined) {
const routeId = shuttle.routeId;
const fromStopId = lastStopTimestamp.stopId;
const toStopId = arrivedStop.id;
const travelTimeSeconds = (travelTimeTimestamp - lastStopTimestamp.timestamp.getTime()) / 1000;
await this.addTravelTimeDataPoint({ routeId, fromStopId, toStopId }, travelTimeSeconds, travelTimeTimestamp);
}
await this.updateShuttleLastStopArrival(shuttle.id, {
stopId: arrivedStop.id,
timestamp: new Date(travelTimeTimestamp),
shuttleId: shuttle.id,
});
}
}
private async addTravelTimeDataPoint(
{ routeId, fromStopId, toStopId }: ShuttleTravelTimeDataIdentifier,
travelTimeSeconds: number,
timestamp = Date.now(),
): Promise<void> {
const key = `${routeId}:${fromStopId}:${toStopId}`;
const dataPoints = this.travelTimeData.get(key) || [];
dataPoints.push({ timestamp, seconds: travelTimeSeconds });
this.travelTimeData.set(key, dataPoints);
}
private async updateShuttleLastStopArrival(shuttleId: string, lastStopArrival: ShuttleStopArrival) {
this.shuttleLastStopArrivals.set(shuttleId, lastStopArrival);
@@ -350,27 +267,10 @@ export class UnoptimizedInMemoryShuttleRepository
}, this.orderedStops);
}
public async removeEtaIfExists(shuttleId: string, stopId: string): Promise<IEta | null> {
const removedEta = await this.removeEntityByMatcherIfExists((eta) => {
return eta.stopId === stopId
&& eta.shuttleId === shuttleId
}, this.etas);
if (removedEta) {
this.emit(ShuttleRepositoryEvent.ETA_REMOVED, removedEta);
}
return removedEta;
}
public async clearShuttleData(): Promise<void> {
this.shuttles = [];
}
public async clearEtaData(): Promise<void> {
const removedEtas = [...this.etas];
this.etas = [];
this.emit(ShuttleRepositoryEvent.ETA_DATA_CLEARED, removedEtas);
}
public async clearOrderedStopData(): Promise<void> {
this.orderedStops = [];
}