minotor 3.0.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -3
- package/README.md +1 -0
- package/dist/cli.mjs +175 -98
- package/dist/cli.mjs.map +1 -1
- package/dist/gtfs/trips.d.ts +6 -1
- package/dist/parser.cjs.js +172 -94
- package/dist/parser.cjs.js.map +1 -1
- package/dist/parser.esm.js +172 -94
- package/dist/parser.esm.js.map +1 -1
- package/dist/router.cjs.js +1 -1
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.esm.js +1 -1
- package/dist/router.esm.js.map +1 -1
- package/dist/router.umd.js +1 -1
- package/dist/router.umd.js.map +1 -1
- package/dist/timetable/proto/timetable.d.ts +2 -1
- package/dist/timetable/route.d.ts +6 -4
- package/dist/timetable/timetable.d.ts +1 -1
- package/package.json +1 -1
- package/src/__e2e__/timetable/timetable.bin +2 -2
- package/src/cli/repl.ts +0 -1
- package/src/gtfs/__tests__/trips.test.ts +15 -26
- package/src/gtfs/parser.ts +49 -9
- package/src/gtfs/trips.ts +176 -95
- package/src/timetable/__tests__/route.test.ts +25 -17
- package/src/timetable/__tests__/timetable.test.ts +7 -11
- package/src/timetable/proto/timetable.proto +2 -1
- package/src/timetable/proto/timetable.ts +2 -1
- package/src/timetable/route.ts +26 -12
- package/src/timetable/timetable.ts +1 -1
package/dist/gtfs/trips.d.ts
CHANGED
|
@@ -5,8 +5,13 @@ import { ParsedStopsMap } from './stops.js';
|
|
|
5
5
|
import { TransfersMap } from './transfers.js';
|
|
6
6
|
export type TripId = string;
|
|
7
7
|
export type TripIdsMap = Map<TripId, ServiceRouteId>;
|
|
8
|
-
export type GtfsPickupDropOffType = '' | 0 | 1 | 2 | 3;
|
|
8
|
+
export type GtfsPickupDropOffType = '' | '0' | '1' | '2' | '3';
|
|
9
9
|
export type SerializedPickUpDropOffType = 0 | 1 | 2 | 3;
|
|
10
|
+
/**
|
|
11
|
+
* Encodes pickup/drop-off types into a Uint8Array using 2 bits per value.
|
|
12
|
+
* Layout per byte: [drop_off_1][pickup_1][drop_off_0][pickup_0] for stops 0 and 1
|
|
13
|
+
*/
|
|
14
|
+
export declare const encodePickUpDropOffTypes: (pickUpTypes: SerializedPickUpDropOffType[], dropOffTypes: SerializedPickUpDropOffType[]) => Uint8Array;
|
|
10
15
|
/**
|
|
11
16
|
* Parses the trips.txt file from a GTFS feed
|
|
12
17
|
*
|
package/dist/parser.cjs.js
CHANGED
|
@@ -13444,11 +13444,16 @@ class Route {
|
|
|
13444
13444
|
* @returns The pick-up type at the specified stop and trip.
|
|
13445
13445
|
*/
|
|
13446
13446
|
pickUpTypeFrom(stopId, tripIndex) {
|
|
13447
|
-
const
|
|
13448
|
-
const
|
|
13449
|
-
|
|
13447
|
+
const globalIndex = tripIndex * this.stops.length + this.stopIndex(stopId);
|
|
13448
|
+
const byteIndex = Math.floor(globalIndex / 2);
|
|
13449
|
+
const isSecondPair = globalIndex % 2 === 1;
|
|
13450
|
+
const byte = this.pickUpDropOffTypes[byteIndex];
|
|
13451
|
+
if (byte === undefined) {
|
|
13450
13452
|
throw new Error(`Pick up type not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13451
13453
|
}
|
|
13454
|
+
const pickUpValue = isSecondPair
|
|
13455
|
+
? (byte >> 6) & 0x03 // Upper 2 bits for second pair
|
|
13456
|
+
: (byte >> 2) & 0x03; // Bits 2-3 for first pair
|
|
13452
13457
|
return toPickupDropOffType(pickUpValue);
|
|
13453
13458
|
}
|
|
13454
13459
|
/**
|
|
@@ -13459,11 +13464,16 @@ class Route {
|
|
|
13459
13464
|
* @returns The drop-off type at the specified stop and trip.
|
|
13460
13465
|
*/
|
|
13461
13466
|
dropOffTypeAt(stopId, tripIndex) {
|
|
13462
|
-
const
|
|
13463
|
-
const
|
|
13464
|
-
|
|
13467
|
+
const globalIndex = tripIndex * this.stops.length + this.stopIndex(stopId);
|
|
13468
|
+
const byteIndex = Math.floor(globalIndex / 2);
|
|
13469
|
+
const isSecondPair = globalIndex % 2 === 1;
|
|
13470
|
+
const byte = this.pickUpDropOffTypes[byteIndex];
|
|
13471
|
+
if (byte === undefined) {
|
|
13465
13472
|
throw new Error(`Drop off type not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13466
13473
|
}
|
|
13474
|
+
const dropOffValue = isSecondPair
|
|
13475
|
+
? (byte >> 4) & 0x03 // Bits 4-5 for second pair
|
|
13476
|
+
: byte & 0x03; // Lower 2 bits for first pair
|
|
13467
13477
|
return toPickupDropOffType(dropOffValue);
|
|
13468
13478
|
}
|
|
13469
13479
|
/**
|
|
@@ -13765,7 +13775,7 @@ const ALL_TRANSPORT_MODES = new Set([
|
|
|
13765
13775
|
'TROLLEYBUS',
|
|
13766
13776
|
'MONORAIL',
|
|
13767
13777
|
]);
|
|
13768
|
-
const CURRENT_VERSION = '0.0.
|
|
13778
|
+
const CURRENT_VERSION = '0.0.4';
|
|
13769
13779
|
/**
|
|
13770
13780
|
* The internal transit timetable format.
|
|
13771
13781
|
*/
|
|
@@ -16196,6 +16206,86 @@ const parseGtfsTransferType = (gtfsTransferType) => {
|
|
|
16196
16206
|
}
|
|
16197
16207
|
};
|
|
16198
16208
|
|
|
16209
|
+
/**
|
|
16210
|
+
* Encodes pickup/drop-off types into a Uint8Array using 2 bits per value.
|
|
16211
|
+
* Layout per byte: [drop_off_1][pickup_1][drop_off_0][pickup_0] for stops 0 and 1
|
|
16212
|
+
*/
|
|
16213
|
+
const encodePickUpDropOffTypes = (pickUpTypes, dropOffTypes) => {
|
|
16214
|
+
const stopsCount = pickUpTypes.length;
|
|
16215
|
+
// Each byte stores 2 pickup/drop-off pairs (4 bits each)
|
|
16216
|
+
const arraySize = Math.ceil(stopsCount / 2);
|
|
16217
|
+
const encoded = new Uint8Array(arraySize);
|
|
16218
|
+
for (let i = 0; i < stopsCount; i++) {
|
|
16219
|
+
const byteIndex = Math.floor(i / 2);
|
|
16220
|
+
const isSecondPair = i % 2 === 1;
|
|
16221
|
+
const dropOffType = dropOffTypes[i];
|
|
16222
|
+
const pickUpType = pickUpTypes[i];
|
|
16223
|
+
if (dropOffType !== undefined &&
|
|
16224
|
+
pickUpType !== undefined &&
|
|
16225
|
+
byteIndex < encoded.length) {
|
|
16226
|
+
if (isSecondPair) {
|
|
16227
|
+
// Second pair: upper 4 bits
|
|
16228
|
+
const currentByte = encoded[byteIndex];
|
|
16229
|
+
if (currentByte !== undefined) {
|
|
16230
|
+
encoded[byteIndex] =
|
|
16231
|
+
currentByte | (dropOffType << 4) | (pickUpType << 6);
|
|
16232
|
+
}
|
|
16233
|
+
}
|
|
16234
|
+
else {
|
|
16235
|
+
// First pair: lower 4 bits
|
|
16236
|
+
const currentByte = encoded[byteIndex];
|
|
16237
|
+
if (currentByte !== undefined) {
|
|
16238
|
+
encoded[byteIndex] = currentByte | dropOffType | (pickUpType << 2);
|
|
16239
|
+
}
|
|
16240
|
+
}
|
|
16241
|
+
}
|
|
16242
|
+
}
|
|
16243
|
+
return encoded;
|
|
16244
|
+
};
|
|
16245
|
+
/**
|
|
16246
|
+
* Sorts trips by departure time and creates optimized typed arrays
|
|
16247
|
+
*/
|
|
16248
|
+
const finalizeRouteFromBuilder = (builder) => {
|
|
16249
|
+
builder.trips.sort((a, b) => a.firstDeparture - b.firstDeparture);
|
|
16250
|
+
const stopsCount = builder.stops.length;
|
|
16251
|
+
const tripsCount = builder.trips.length;
|
|
16252
|
+
const stopsArray = new Uint32Array(builder.stops);
|
|
16253
|
+
const stopTimesArray = new Uint16Array(stopsCount * tripsCount * 2);
|
|
16254
|
+
const allPickUpTypes = [];
|
|
16255
|
+
const allDropOffTypes = [];
|
|
16256
|
+
for (let tripIndex = 0; tripIndex < tripsCount; tripIndex++) {
|
|
16257
|
+
const trip = builder.trips[tripIndex];
|
|
16258
|
+
if (!trip) {
|
|
16259
|
+
throw new Error(`Missing trip data at index ${tripIndex}`);
|
|
16260
|
+
}
|
|
16261
|
+
const baseIndex = tripIndex * stopsCount * 2;
|
|
16262
|
+
for (let stopIndex = 0; stopIndex < stopsCount; stopIndex++) {
|
|
16263
|
+
const timeIndex = baseIndex + stopIndex * 2;
|
|
16264
|
+
const arrivalTime = trip.arrivalTimes[stopIndex];
|
|
16265
|
+
const departureTime = trip.departureTimes[stopIndex];
|
|
16266
|
+
const pickUpType = trip.pickUpTypes[stopIndex];
|
|
16267
|
+
const dropOffType = trip.dropOffTypes[stopIndex];
|
|
16268
|
+
if (arrivalTime === undefined ||
|
|
16269
|
+
departureTime === undefined ||
|
|
16270
|
+
pickUpType === undefined ||
|
|
16271
|
+
dropOffType === undefined) {
|
|
16272
|
+
throw new Error(`Missing trip data for trip ${tripIndex} at stop ${stopIndex}`);
|
|
16273
|
+
}
|
|
16274
|
+
stopTimesArray[timeIndex] = arrivalTime;
|
|
16275
|
+
stopTimesArray[timeIndex + 1] = departureTime;
|
|
16276
|
+
allDropOffTypes.push(dropOffType);
|
|
16277
|
+
allPickUpTypes.push(pickUpType);
|
|
16278
|
+
}
|
|
16279
|
+
}
|
|
16280
|
+
// Use 2-bit encoding for pickup/drop-off types
|
|
16281
|
+
const pickUpDropOffTypesArray = encodePickUpDropOffTypes(allPickUpTypes, allDropOffTypes);
|
|
16282
|
+
return {
|
|
16283
|
+
serviceRouteId: builder.serviceRouteId,
|
|
16284
|
+
stops: stopsArray,
|
|
16285
|
+
stopTimes: stopTimesArray,
|
|
16286
|
+
pickUpDropOffTypes: pickUpDropOffTypesArray,
|
|
16287
|
+
};
|
|
16288
|
+
};
|
|
16199
16289
|
/**
|
|
16200
16290
|
* Parses the trips.txt file from a GTFS feed
|
|
16201
16291
|
*
|
|
@@ -16273,11 +16363,11 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
16273
16363
|
var _a, e_2, _b, _c;
|
|
16274
16364
|
var _d, _e;
|
|
16275
16365
|
/**
|
|
16276
|
-
*
|
|
16366
|
+
* Adds a trip to the appropriate route builder
|
|
16277
16367
|
*/
|
|
16278
16368
|
const addTrip = (currentTripId) => {
|
|
16279
16369
|
const gtfsRouteId = validTripIds.get(currentTripId);
|
|
16280
|
-
if (!gtfsRouteId) {
|
|
16370
|
+
if (!gtfsRouteId || stops.length === 0) {
|
|
16281
16371
|
stops = [];
|
|
16282
16372
|
arrivalTimes = [];
|
|
16283
16373
|
departureTimes = [];
|
|
@@ -16286,83 +16376,42 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
16286
16376
|
return;
|
|
16287
16377
|
}
|
|
16288
16378
|
const routeId = `${gtfsRouteId}_${hashIds(stops)}`;
|
|
16289
|
-
|
|
16290
|
-
if (
|
|
16291
|
-
|
|
16292
|
-
|
|
16293
|
-
|
|
16294
|
-
|
|
16295
|
-
|
|
16296
|
-
|
|
16297
|
-
|
|
16298
|
-
|
|
16299
|
-
|
|
16300
|
-
|
|
16301
|
-
|
|
16302
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
16303
|
-
pickUpDropOffTypesArray[i * 2] = pickUpTypes[i];
|
|
16304
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
16305
|
-
pickUpDropOffTypesArray[i * 2 + 1] = dropOffTypes[i];
|
|
16306
|
-
}
|
|
16307
|
-
route = {
|
|
16379
|
+
const firstDeparture = departureTimes[0];
|
|
16380
|
+
if (firstDeparture === undefined) {
|
|
16381
|
+
console.warn(`Empty trip ${currentTripId}`);
|
|
16382
|
+
stops = [];
|
|
16383
|
+
arrivalTimes = [];
|
|
16384
|
+
departureTimes = [];
|
|
16385
|
+
pickUpTypes = [];
|
|
16386
|
+
dropOffTypes = [];
|
|
16387
|
+
return;
|
|
16388
|
+
}
|
|
16389
|
+
let routeBuilder = routeBuilders.get(routeId);
|
|
16390
|
+
if (!routeBuilder) {
|
|
16391
|
+
routeBuilder = {
|
|
16308
16392
|
serviceRouteId: gtfsRouteId,
|
|
16309
|
-
stops:
|
|
16310
|
-
|
|
16311
|
-
pickUpDropOffTypes: pickUpDropOffTypesArray,
|
|
16393
|
+
stops: [...stops],
|
|
16394
|
+
trips: [],
|
|
16312
16395
|
};
|
|
16313
|
-
|
|
16396
|
+
routeBuilders.set(routeId, routeBuilder);
|
|
16314
16397
|
for (const stop of stops) {
|
|
16315
16398
|
validStopIds.add(stop);
|
|
16316
16399
|
}
|
|
16317
16400
|
}
|
|
16318
|
-
|
|
16319
|
-
|
|
16320
|
-
|
|
16321
|
-
|
|
16322
|
-
|
|
16323
|
-
|
|
16324
|
-
|
|
16325
|
-
let insertPosition = 0;
|
|
16326
|
-
const existingTripsCount = route.stopTimes.length / (stopsCount * 2);
|
|
16327
|
-
for (let tripIndex = 0; tripIndex < existingTripsCount; tripIndex++) {
|
|
16328
|
-
const currentDeparture = route.stopTimes[tripIndex * stopsCount * 2 + 1];
|
|
16329
|
-
if (currentDeparture && tripFirstStopDeparture > currentDeparture) {
|
|
16330
|
-
insertPosition = (tripIndex + 1) * stopsCount;
|
|
16331
|
-
}
|
|
16332
|
-
else {
|
|
16333
|
-
break;
|
|
16334
|
-
}
|
|
16335
|
-
}
|
|
16336
|
-
// insert data for the new trip at the right place
|
|
16337
|
-
const newStopTimesLength = route.stopTimes.length + stopsCount * 2;
|
|
16338
|
-
const newStopTimes = new Uint16Array(newStopTimesLength);
|
|
16339
|
-
const newPickUpDropOffTypes = new Uint8Array(newStopTimesLength);
|
|
16340
|
-
newStopTimes.set(route.stopTimes.slice(0, insertPosition * 2), 0);
|
|
16341
|
-
newPickUpDropOffTypes.set(route.pickUpDropOffTypes.slice(0, insertPosition * 2), 0);
|
|
16342
|
-
for (let i = 0; i < stopsCount; i++) {
|
|
16343
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
16344
|
-
newStopTimes[(insertPosition + i) * 2] = arrivalTimes[i];
|
|
16345
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
16346
|
-
newStopTimes[(insertPosition + i) * 2 + 1] = departureTimes[i];
|
|
16347
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
16348
|
-
newPickUpDropOffTypes[(insertPosition + i) * 2] = pickUpTypes[i];
|
|
16349
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
16350
|
-
newPickUpDropOffTypes[(insertPosition + i) * 2 + 1] = dropOffTypes[i];
|
|
16351
|
-
}
|
|
16352
|
-
const afterInsertionSlice = route.stopTimes.slice(insertPosition * 2);
|
|
16353
|
-
newStopTimes.set(afterInsertionSlice, (insertPosition + stopsCount) * 2);
|
|
16354
|
-
const afterInsertionTypesSlice = route.pickUpDropOffTypes.slice(insertPosition * 2);
|
|
16355
|
-
newPickUpDropOffTypes.set(afterInsertionTypesSlice, (insertPosition + stopsCount) * 2);
|
|
16356
|
-
route.stopTimes = newStopTimes;
|
|
16357
|
-
route.pickUpDropOffTypes = newPickUpDropOffTypes;
|
|
16358
|
-
}
|
|
16401
|
+
routeBuilder.trips.push({
|
|
16402
|
+
firstDeparture,
|
|
16403
|
+
arrivalTimes: [...arrivalTimes],
|
|
16404
|
+
departureTimes: [...departureTimes],
|
|
16405
|
+
pickUpTypes: [...pickUpTypes],
|
|
16406
|
+
dropOffTypes: [...dropOffTypes],
|
|
16407
|
+
});
|
|
16359
16408
|
stops = [];
|
|
16360
16409
|
arrivalTimes = [];
|
|
16361
16410
|
departureTimes = [];
|
|
16362
16411
|
pickUpTypes = [];
|
|
16363
16412
|
dropOffTypes = [];
|
|
16364
16413
|
};
|
|
16365
|
-
const
|
|
16414
|
+
const routeBuilders = new Map();
|
|
16366
16415
|
let previousSeq = 0;
|
|
16367
16416
|
let stops = [];
|
|
16368
16417
|
let arrivalTimes = [];
|
|
@@ -16377,27 +16426,33 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
16377
16426
|
const rawLine = _c;
|
|
16378
16427
|
const line = rawLine;
|
|
16379
16428
|
if (line.trip_id === currentTripId && line.stop_sequence <= previousSeq) {
|
|
16380
|
-
console.warn(`Stop sequences not increasing for trip ${line.trip_id}.`);
|
|
16429
|
+
console.warn(`Stop sequences not increasing for trip ${line.trip_id}: ${line.stop_sequence} > ${previousSeq}.`);
|
|
16381
16430
|
continue;
|
|
16382
16431
|
}
|
|
16383
16432
|
if (!line.arrival_time && !line.departure_time) {
|
|
16384
16433
|
console.warn(`Missing arrival or departure time for ${line.trip_id} at stop ${line.stop_id}.`);
|
|
16385
16434
|
continue;
|
|
16386
16435
|
}
|
|
16387
|
-
if (line.pickup_type === 1 && line.drop_off_type === 1) {
|
|
16436
|
+
if (line.pickup_type === '1' && line.drop_off_type === '1') {
|
|
16388
16437
|
continue;
|
|
16389
16438
|
}
|
|
16390
16439
|
if (currentTripId && line.trip_id !== currentTripId && stops.length > 0) {
|
|
16391
16440
|
addTrip(currentTripId);
|
|
16392
16441
|
}
|
|
16393
16442
|
currentTripId = line.trip_id;
|
|
16394
|
-
|
|
16395
|
-
|
|
16443
|
+
const stopData = stopsMap.get(line.stop_id);
|
|
16444
|
+
if (!stopData) {
|
|
16445
|
+
console.warn(`Unknown stop ID: ${line.stop_id}`);
|
|
16446
|
+
continue;
|
|
16447
|
+
}
|
|
16448
|
+
stops.push(stopData.id);
|
|
16396
16449
|
const departure = (_d = line.departure_time) !== null && _d !== void 0 ? _d : line.arrival_time;
|
|
16397
16450
|
const arrival = (_e = line.arrival_time) !== null && _e !== void 0 ? _e : line.departure_time;
|
|
16398
|
-
|
|
16451
|
+
if (!arrival || !departure) {
|
|
16452
|
+
console.warn(`Missing time data for ${line.trip_id} at stop ${line.stop_id}`);
|
|
16453
|
+
continue;
|
|
16454
|
+
}
|
|
16399
16455
|
arrivalTimes.push(toTime(arrival).toMinutes());
|
|
16400
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
16401
16456
|
departureTimes.push(toTime(departure).toMinutes());
|
|
16402
16457
|
pickUpTypes.push(parsePickupDropOffType(line.pickup_type));
|
|
16403
16458
|
dropOffTypes.push(parsePickupDropOffType(line.drop_off_type));
|
|
@@ -16415,7 +16470,8 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
16415
16470
|
addTrip(currentTripId);
|
|
16416
16471
|
}
|
|
16417
16472
|
const routesAdjacency = new Map();
|
|
16418
|
-
for (const [routeId,
|
|
16473
|
+
for (const [routeId, routeBuilder] of routeBuilders) {
|
|
16474
|
+
const routeData = finalizeRouteFromBuilder(routeBuilder);
|
|
16419
16475
|
routesAdjacency.set(routeId, new Route(routeData.stopTimes, routeData.pickUpDropOffTypes, routeData.stops, routeData.serviceRouteId));
|
|
16420
16476
|
}
|
|
16421
16477
|
return routesAdjacency;
|
|
@@ -16424,13 +16480,13 @@ const parsePickupDropOffType = (gtfsType) => {
|
|
|
16424
16480
|
switch (gtfsType) {
|
|
16425
16481
|
default:
|
|
16426
16482
|
return REGULAR;
|
|
16427
|
-
case 0:
|
|
16483
|
+
case '0':
|
|
16428
16484
|
return REGULAR;
|
|
16429
|
-
case 1:
|
|
16485
|
+
case '1':
|
|
16430
16486
|
return NOT_AVAILABLE;
|
|
16431
|
-
case 2:
|
|
16487
|
+
case '2':
|
|
16432
16488
|
return MUST_PHONE_AGENCY;
|
|
16433
|
-
case 3:
|
|
16489
|
+
case '3':
|
|
16434
16490
|
return MUST_COORDINATE_WITH_DRIVER;
|
|
16435
16491
|
}
|
|
16436
16492
|
};
|
|
@@ -16458,54 +16514,74 @@ class GtfsParser {
|
|
|
16458
16514
|
*/
|
|
16459
16515
|
parse(date) {
|
|
16460
16516
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16517
|
+
log.setLevel('INFO');
|
|
16461
16518
|
const zip = new StreamZip.async({ file: this.path });
|
|
16462
16519
|
const entries = yield zip.entries();
|
|
16463
16520
|
const datetime = DateTime.fromJSDate(date);
|
|
16464
16521
|
const validServiceIds = new Set();
|
|
16465
16522
|
const validStopIds = new Set();
|
|
16466
16523
|
log.info(`Parsing ${STOPS_FILE}`);
|
|
16524
|
+
const stopsStart = performance.now();
|
|
16467
16525
|
const stopsStream = yield zip.stream(STOPS_FILE);
|
|
16468
16526
|
const parsedStops = yield parseStops(stopsStream, this.profile.platformParser);
|
|
16469
|
-
|
|
16527
|
+
const stopsEnd = performance.now();
|
|
16528
|
+
log.info(`${parsedStops.size} parsed stops. (${(stopsEnd - stopsStart).toFixed(2)}ms)`);
|
|
16470
16529
|
if (entries[CALENDAR_FILE]) {
|
|
16471
16530
|
log.info(`Parsing ${CALENDAR_FILE}`);
|
|
16531
|
+
const calendarStart = performance.now();
|
|
16472
16532
|
const calendarStream = yield zip.stream(CALENDAR_FILE);
|
|
16473
16533
|
yield parseCalendar(calendarStream, validServiceIds, datetime);
|
|
16474
|
-
|
|
16534
|
+
const calendarEnd = performance.now();
|
|
16535
|
+
log.info(`${validServiceIds.size} valid services. (${(calendarEnd - calendarStart).toFixed(2)}ms)`);
|
|
16475
16536
|
}
|
|
16476
16537
|
if (entries[CALENDAR_DATES_FILE]) {
|
|
16477
16538
|
log.info(`Parsing ${CALENDAR_DATES_FILE}`);
|
|
16539
|
+
const calendarDatesStart = performance.now();
|
|
16478
16540
|
const calendarDatesStream = yield zip.stream(CALENDAR_DATES_FILE);
|
|
16479
16541
|
yield parseCalendarDates(calendarDatesStream, validServiceIds, datetime);
|
|
16480
|
-
|
|
16542
|
+
const calendarDatesEnd = performance.now();
|
|
16543
|
+
log.info(`${validServiceIds.size} valid services. (${(calendarDatesEnd - calendarDatesStart).toFixed(2)}ms)`);
|
|
16481
16544
|
}
|
|
16482
16545
|
log.info(`Parsing ${ROUTES_FILE}`);
|
|
16546
|
+
const routesStart = performance.now();
|
|
16483
16547
|
const routesStream = yield zip.stream(ROUTES_FILE);
|
|
16484
16548
|
const validGtfsRoutes = yield parseRoutes(routesStream, this.profile);
|
|
16485
|
-
|
|
16549
|
+
const routesEnd = performance.now();
|
|
16550
|
+
log.info(`${validGtfsRoutes.size} valid GTFS routes. (${(routesEnd - routesStart).toFixed(2)}ms)`);
|
|
16486
16551
|
log.info(`Parsing ${TRIPS_FILE}`);
|
|
16552
|
+
const tripsStart = performance.now();
|
|
16487
16553
|
const tripsStream = yield zip.stream(TRIPS_FILE);
|
|
16488
16554
|
const trips = yield parseTrips(tripsStream, validServiceIds, validGtfsRoutes);
|
|
16489
|
-
|
|
16555
|
+
const tripsEnd = performance.now();
|
|
16556
|
+
log.info(`${trips.size} valid trips. (${(tripsEnd - tripsStart).toFixed(2)}ms)`);
|
|
16490
16557
|
let transfers = new Map();
|
|
16491
16558
|
if (entries[TRANSFERS_FILE]) {
|
|
16492
16559
|
log.info(`Parsing ${TRANSFERS_FILE}`);
|
|
16560
|
+
const transfersStart = performance.now();
|
|
16493
16561
|
const transfersStream = yield zip.stream(TRANSFERS_FILE);
|
|
16494
16562
|
transfers = yield parseTransfers(transfersStream, parsedStops);
|
|
16495
|
-
|
|
16563
|
+
const transfersEnd = performance.now();
|
|
16564
|
+
log.info(`${transfers.size} valid transfers. (${(transfersEnd - transfersStart).toFixed(2)}ms)`);
|
|
16496
16565
|
}
|
|
16497
16566
|
log.info(`Parsing ${STOP_TIMES_FILE}`);
|
|
16567
|
+
const stopTimesStart = performance.now();
|
|
16498
16568
|
const stopTimesStream = yield zip.stream(STOP_TIMES_FILE);
|
|
16499
16569
|
const routesAdjacency = yield parseStopTimes(stopTimesStream, parsedStops, trips, validStopIds);
|
|
16500
16570
|
const stopsAdjacency = buildStopsAdjacencyStructure(validStopIds, routesAdjacency, transfers);
|
|
16501
|
-
|
|
16571
|
+
const stopTimesEnd = performance.now();
|
|
16572
|
+
log.info(`${routesAdjacency.size} valid unique routes. (${(stopTimesEnd - stopTimesStart).toFixed(2)}ms)`);
|
|
16502
16573
|
log.info(`Removing unused stops.`);
|
|
16574
|
+
const indexStopsStart = performance.now();
|
|
16503
16575
|
const stops = indexStops(parsedStops, validStopIds);
|
|
16504
|
-
|
|
16576
|
+
const indexStopsEnd = performance.now();
|
|
16577
|
+
log.info(`${stops.size} used stop stops, ${parsedStops.size - stops.size} unused. (${(indexStopsEnd - indexStopsStart).toFixed(2)}ms)`);
|
|
16505
16578
|
yield zip.close();
|
|
16506
16579
|
const timetable = new Timetable(stopsAdjacency, routesAdjacency, validGtfsRoutes);
|
|
16507
16580
|
log.info(`Building stops index.`);
|
|
16581
|
+
const stopsIndexStart = performance.now();
|
|
16508
16582
|
const stopsIndex = new StopsIndex(stops);
|
|
16583
|
+
const stopsIndexEnd = performance.now();
|
|
16584
|
+
log.info(`Stops index built. (${(stopsIndexEnd - stopsIndexStart).toFixed(2)}ms)`);
|
|
16509
16585
|
log.info('Parsing complete.');
|
|
16510
16586
|
return { timetable, stopsIndex };
|
|
16511
16587
|
});
|
|
@@ -16521,9 +16597,11 @@ class GtfsParser {
|
|
|
16521
16597
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16522
16598
|
const zip = new StreamZip.async({ file: this.path });
|
|
16523
16599
|
log.info(`Parsing ${STOPS_FILE}`);
|
|
16600
|
+
const stopsStart = performance.now();
|
|
16524
16601
|
const stopsStream = yield zip.stream(STOPS_FILE);
|
|
16525
16602
|
const stops = indexStops(yield parseStops(stopsStream, this.profile.platformParser));
|
|
16526
|
-
|
|
16603
|
+
const stopsEnd = performance.now();
|
|
16604
|
+
log.info(`${stops.size} parsed stops. (${(stopsEnd - stopsStart).toFixed(2)}ms)`);
|
|
16527
16605
|
yield zip.close();
|
|
16528
16606
|
return new StopsIndex(stops);
|
|
16529
16607
|
});
|