mirror of
https://github.com/brendan-ch/project-inter-server.git
synced 2026-04-19 08:50:29 +00:00
Implement in-memory equivalents of both ETA repositories
This commit is contained in:
@@ -1,22 +1,118 @@
|
||||
import { SelfUpdatingETARepository } from "./SelfUpdatingETARepository";
|
||||
import { ShuttleGetterRepository, ShuttleTravelTimeDataIdentifier, ShuttleTravelTimeDateFilterArguments } from "../ShuttleGetterRepository";
|
||||
import { ShuttleGetterRepository, ShuttleRepositoryEvent, ShuttleStopArrival, ShuttleTravelTimeDataIdentifier, ShuttleTravelTimeDateFilterArguments } from "../ShuttleGetterRepository";
|
||||
import { BaseInMemoryETARepository } from "./BaseInMemoryETARepository";
|
||||
import { IShuttle } from "../../../entities/ShuttleRepositoryEntities";
|
||||
|
||||
export class InMemorySelfUpdatingETARepository extends BaseInMemoryETARepository implements SelfUpdatingETARepository {
|
||||
private referenceTime: Date | null = null;
|
||||
private travelTimeData: Map<string, Array<{ timestamp: number; seconds: number }>> = new Map();
|
||||
|
||||
constructor(
|
||||
readonly shuttleRepository: ShuttleGetterRepository
|
||||
) {
|
||||
super();
|
||||
}
|
||||
setReferenceTime(referenceTime: Date): void {
|
||||
throw new Error("Method not implemented.");
|
||||
|
||||
this.setReferenceTime = this.setReferenceTime.bind(this);
|
||||
this.getAverageTravelTimeSeconds = this.getAverageTravelTimeSeconds.bind(this);
|
||||
this.startListeningForUpdates = this.startListeningForUpdates.bind(this);
|
||||
this.handleShuttleUpdate = this.handleShuttleUpdate.bind(this);
|
||||
this.handleShuttleWillArriveAtStop = this.handleShuttleWillArriveAtStop.bind(this);
|
||||
}
|
||||
|
||||
getAverageTravelTimeSeconds(identifier: ShuttleTravelTimeDataIdentifier, dateFilter: ShuttleTravelTimeDateFilterArguments): Promise<number | undefined> {
|
||||
throw new Error("Method not implemented.");
|
||||
setReferenceTime(referenceTime: Date): void {
|
||||
this.referenceTime = referenceTime;
|
||||
}
|
||||
|
||||
async getAverageTravelTimeSeconds(
|
||||
{ routeId, fromStopId, toStopId }: ShuttleTravelTimeDataIdentifier,
|
||||
{ from, to }: ShuttleTravelTimeDateFilterArguments
|
||||
): Promise<number | undefined> {
|
||||
const key = `${routeId}:${fromStopId}:${toStopId}`;
|
||||
const dataPoints = this.travelTimeData.get(key);
|
||||
|
||||
if (!dataPoints || dataPoints.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const fromTimestamp = from.getTime();
|
||||
const toTimestamp = to.getTime();
|
||||
|
||||
const filteredPoints = dataPoints.filter(
|
||||
(point) => point.timestamp >= fromTimestamp && point.timestamp <= toTimestamp
|
||||
);
|
||||
|
||||
if (filteredPoints.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const sum = filteredPoints.reduce((acc, point) => acc + point.seconds, 0);
|
||||
return sum / filteredPoints.length;
|
||||
}
|
||||
|
||||
startListeningForUpdates(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
this.shuttleRepository.addListener(ShuttleRepositoryEvent.SHUTTLE_UPDATED, this.handleShuttleUpdate);
|
||||
this.shuttleRepository.addListener(ShuttleRepositoryEvent.SHUTTLE_WILL_ARRIVE_AT_STOP, this.handleShuttleWillArriveAtStop);
|
||||
}
|
||||
|
||||
private async handleShuttleUpdate(shuttle: IShuttle): Promise<void> {
|
||||
const lastStop = await this.shuttleRepository.getShuttleLastStopArrival(shuttle.id);
|
||||
if (!lastStop) return;
|
||||
|
||||
const lastOrderedStop = await this.shuttleRepository.getOrderedStopByRouteAndStopId(shuttle.routeId, lastStop.stopId);
|
||||
const nextStop = lastOrderedStop?.nextStop;
|
||||
if (!nextStop) return;
|
||||
|
||||
let referenceCurrentTime = new Date();
|
||||
if (this.referenceTime != null) {
|
||||
referenceCurrentTime = this.referenceTime;
|
||||
}
|
||||
const oneWeekAgo = new Date(referenceCurrentTime.getTime() - (60 * 60 * 24 * 7 * 1000));
|
||||
|
||||
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(),
|
||||
});
|
||||
}
|
||||
|
||||
private async handleShuttleWillArriveAtStop(shuttleArrival: ShuttleStopArrival): Promise<void> {
|
||||
const lastStopTimestamp = await this.shuttleRepository.getShuttleLastStopArrival(shuttleArrival.shuttleId);
|
||||
if (lastStopTimestamp) {
|
||||
const shuttle = await this.shuttleRepository.getShuttleById(lastStopTimestamp.shuttleId);
|
||||
if (!shuttle) return;
|
||||
|
||||
const routeId = shuttle.routeId;
|
||||
const fromStopId = lastStopTimestamp.stopId;
|
||||
const toStopId = shuttleArrival.stopId;
|
||||
|
||||
const travelTimeSeconds = (shuttleArrival.timestamp.getTime() - lastStopTimestamp.timestamp.getTime()) / 1000;
|
||||
await this.addTravelTimeDataPoint({ routeId, fromStopId, toStopId }, travelTimeSeconds, shuttleArrival.timestamp.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user