UNPKG

minotor

Version:

A lightweight client-side transit routing library.

104 lines (88 loc) 2.9 kB
import { Stop } from '../stops/stops.js'; import { Duration } from '../timetable/duration.js'; import { Time } from '../timetable/time.js'; import { ServiceRoute, TransferType } from '../timetable/timetable.js'; export type PickUpDropOffType = | 'REGULAR' | 'NOT_AVAILABLE' | 'MUST_PHONE_AGENCY' | 'MUST_COORDINATE_WITH_DRIVER'; export type BaseLeg = { from: Stop; to: Stop; }; export type Transfer = BaseLeg & { minTransferTime?: Duration; type: TransferType; }; export type VehicleLeg = BaseLeg & { route: ServiceRoute; departureTime: Time; arrivalTime: Time; // TODO support pick up and drop off types /* pickUpType: PickUpDropOffType; dropOffType: PickUpDropOffType; */ }; export type Leg = Transfer | VehicleLeg; export class Route { legs: Leg[]; constructor(legs: Leg[]) { this.legs = legs; } departureTime(): Time { const cumulativeTransferTime: Duration = Duration.zero(); for (let i = 0; i < this.legs.length; i++) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const leg = this.legs[i]!; if ('departureTime' in leg) { return leg.departureTime.minus(cumulativeTransferTime); } if ('minTransferTime' in leg && leg.minTransferTime) { cumulativeTransferTime.add(leg.minTransferTime); } } throw new Error('No vehicle leg found in route'); } arrivalTime(): Time { let lastVehicleArrivalTime: Time = Time.origin(); const totalTransferTime: Duration = Duration.zero(); let vehicleLegFound = false; for (let i = this.legs.length - 1; i >= 0; i--) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const leg = this.legs[i]!; if ('arrivalTime' in leg && !vehicleLegFound) { lastVehicleArrivalTime = leg.arrivalTime; vehicleLegFound = true; } else if ( 'minTransferTime' in leg && leg.minTransferTime && vehicleLegFound ) { totalTransferTime.add(leg.minTransferTime); } } if (!vehicleLegFound) { throw new Error('No vehicle leg found in route'); } return lastVehicleArrivalTime.plus(totalTransferTime); } totalDuration(): Duration { if (this.legs.length === 0) return Duration.zero(); return this.arrivalTime().diff(this.departureTime()); } print(): string { return this.legs .map((leg, index) => { if ('route' in leg) { return `Leg ${index + 1}: ${leg.from.name} to ${leg.to.name} via route ${leg.route.type} ${leg.route.name}, departs at ${leg.departureTime.toString()}, arrives at ${leg.arrivalTime.toString()}`; } return `Leg ${index + 1}: Transfer from ${leg.from.name} to ${leg.to.name}, minimum transfer time: ${leg.minTransferTime?.toString() ?? 'not specified'}`; }) .join('\n'); } }