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