UNPKG

connection-scan-algorithm

Version:
156 lines (155 loc) 5.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const gtfs = require("gtfs-stream"); const ts_array_utils_1 = require("ts-array-utils"); const Service_1 = require("./Service"); /** * Returns trips, transfers, interchange time and calendars from a GTFS zip. */ class GtfsLoader { constructor(timeParser) { this.timeParser = timeParser; } load(input) { return new Promise(resolve => { const processor = new StatefulGtfsLoader(this.timeParser); input .pipe(gtfs({ raw: true })) .on("data", entity => processor[entity.type] && processor[entity.type](entity.data)) .on("end", () => resolve(processor.finalize())); }); } } exports.GtfsLoader = GtfsLoader; /** * Encapsulation of the GTFS data while it is being loaded from the zip */ class StatefulGtfsLoader { constructor(timeParser) { this.timeParser = timeParser; this.trips = []; this.transfers = {}; this.interchange = {}; this.calendars = {}; this.dates = {}; this.stopTimes = {}; this.stops = {}; } link(row) { const t = { origin: row.from_stop_id, destination: row.to_stop_id, duration: +row.duration, startTime: this.timeParser.getTime(row.start_time), endTime: this.timeParser.getTime(row.end_time) }; ts_array_utils_1.pushNested(t, this.transfers, row.from_stop_id); } calendar(row) { this.calendars[row.service_id] = { serviceId: row.service_id, startDate: +row.start_date, endDate: +row.end_date, days: { 0: row.sunday === "1", 1: row.monday === "1", 2: row.tuesday === "1", 3: row.wednesday === "1", 4: row.thursday === "1", 5: row.friday === "1", 6: row.saturday === "1" }, include: {}, exclude: {} }; } calendar_date(row) { ts_array_utils_1.setNested(row.exception_type === "1", this.dates, row.service_id, row.date); } trip(row) { this.trips.push({ serviceId: row.service_id, tripId: row.trip_id, stopTimes: [], service: {} }); } stop_time(row) { const stopTime = { stop: row.stop_id, departureTime: this.timeParser.getTime(row.departure_time), arrivalTime: this.timeParser.getTime(row.arrival_time), pickUp: row.pickup_type === "0", dropOff: row.drop_off_type === "0" }; ts_array_utils_1.pushNested(stopTime, this.stopTimes, row.trip_id); } transfer(row) { if (row.from_stop_id === row.to_stop_id) { this.interchange[row.from_stop_id] = +row.min_transfer_time; } else { const t = { origin: row.from_stop_id, destination: row.to_stop_id, duration: +row.min_transfer_time, startTime: 0, endTime: Number.MAX_SAFE_INTEGER }; ts_array_utils_1.pushNested(t, this.transfers, row.from_stop_id); } } stop(row) { const stop = { id: row.stop_id, code: row.stop_code, name: row.stop_name, description: row.stop_desc, latitude: +row.stop_lat, longitude: +row.stop_lon, timezone: row.zone_id }; ts_array_utils_1.setNested(stop, this.stops, row.stop_id); } finalize() { const services = {}; const connections = []; for (const c of Object.values(this.calendars)) { services[c.serviceId] = new Service_1.Service(c.startDate, c.endDate, c.days, this.dates[c.serviceId] || {}); } for (const t of this.trips) { t.stopTimes = this.stopTimes[t.tripId]; t.service = services[t.serviceId]; connections.push(...this.getConnectionsFromTrip(t)); } connections.sort((a, b) => a.arrivalTime - b.arrivalTime); for (const stop of Object.keys(this.stops)) { this.transfers[stop] = this.transfers[stop] || []; } return { connections, transfers: this.transfers, interchange: this.interchange, stops: this.stops }; } getConnectionsFromTrip(t) { const connections = []; for (let i = 0; i < t.stopTimes.length - 1; i++) { if (t.stopTimes[i].pickUp) { const j = this.getNextDropOff(t.stopTimes, i); if (j !== -1) { connections.push({ origin: t.stopTimes[i].stop, destination: t.stopTimes[j].stop, departureTime: t.stopTimes[i].departureTime, arrivalTime: t.stopTimes[j].arrivalTime, trip: t }); } } } return connections; } /** * Return the index of the first drop off point */ getNextDropOff(rows, i) { for (let j = i + 1; j < rows.length; j++) { if (rows[j].dropOff) { return j; } } return -1; } }