minotor 2.0.0 → 3.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 +4 -4
- package/dist/cli.mjs +89 -47
- package/dist/cli.mjs.map +1 -1
- package/dist/parser.cjs.js +82 -40
- package/dist/parser.cjs.js.map +1 -1
- package/dist/parser.esm.js +82 -40
- 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.d.ts +2 -2
- 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/time.d.ts +18 -9
- package/dist/timetable/timetable.d.ts +3 -3
- package/package.json +1 -1
- package/src/gtfs/__tests__/parser.test.ts +4 -4
- package/src/gtfs/__tests__/time.test.ts +2 -2
- package/src/gtfs/__tests__/trips.test.ts +36 -36
- package/src/gtfs/trips.ts +4 -4
- package/src/router.ts +3 -2
- package/src/routing/__tests__/route.test.ts +4 -4
- package/src/routing/__tests__/router.test.ts +60 -60
- package/src/routing/result.ts +2 -2
- package/src/routing/router.ts +5 -5
- package/src/timetable/__tests__/io.test.ts +12 -12
- package/src/timetable/__tests__/timetable.test.ts +16 -16
- package/src/timetable/io.ts +46 -2
- package/src/timetable/time.ts +51 -30
- package/src/timetable/timetable.ts +7 -7
package/dist/parser.cjs.js
CHANGED
|
@@ -12992,6 +12992,35 @@ function bytesToUint32Array(bytes) {
|
|
|
12992
12992
|
}
|
|
12993
12993
|
return result;
|
|
12994
12994
|
}
|
|
12995
|
+
function uint16ArrayToBytes(array) {
|
|
12996
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
12997
|
+
return new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
12998
|
+
}
|
|
12999
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13000
|
+
const result = new Uint8Array(array.length * 2);
|
|
13001
|
+
const view = new DataView(result.buffer);
|
|
13002
|
+
for (let i = 0; i < array.length; i++) {
|
|
13003
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13004
|
+
view.setUint16(i * 2, array[i], STANDARD_ENDIANNESS);
|
|
13005
|
+
}
|
|
13006
|
+
return result;
|
|
13007
|
+
}
|
|
13008
|
+
function bytesToUint16Array(bytes) {
|
|
13009
|
+
if (bytes.byteLength % 2 !== 0) {
|
|
13010
|
+
throw new Error('Byte array length must be a multiple of 2 to convert to Uint16Array');
|
|
13011
|
+
}
|
|
13012
|
+
// If system endianness matches our standard, we can create a view directly
|
|
13013
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
13014
|
+
return new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2);
|
|
13015
|
+
}
|
|
13016
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13017
|
+
const result = new Uint16Array(bytes.byteLength / 2);
|
|
13018
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13019
|
+
for (let i = 0; i < result.length; i++) {
|
|
13020
|
+
result[i] = view.getUint16(i * 2, STANDARD_ENDIANNESS);
|
|
13021
|
+
}
|
|
13022
|
+
return result;
|
|
13023
|
+
}
|
|
12995
13024
|
const serializeStopsAdjacency = (stopsAdjacency) => {
|
|
12996
13025
|
const protoStopsAdjacency = {
|
|
12997
13026
|
stops: {},
|
|
@@ -13012,7 +13041,7 @@ const serializeRoutesAdjacency = (routesAdjacency) => {
|
|
|
13012
13041
|
};
|
|
13013
13042
|
routesAdjacency.forEach((value, key) => {
|
|
13014
13043
|
protoRoutesAdjacency.routes[key] = {
|
|
13015
|
-
stopTimes:
|
|
13044
|
+
stopTimes: uint16ArrayToBytes(value.stopTimes),
|
|
13016
13045
|
pickUpDropOffTypes: value.pickUpDropOffTypes,
|
|
13017
13046
|
stops: uint32ArrayToBytes(value.stops),
|
|
13018
13047
|
serviceRouteId: value.serviceRouteId,
|
|
@@ -13055,7 +13084,7 @@ const deserializeRoutesAdjacency = (protoRoutesAdjacency) => {
|
|
|
13055
13084
|
indices.set(stops[i], i);
|
|
13056
13085
|
}
|
|
13057
13086
|
routesAdjacency.set(key, {
|
|
13058
|
-
stopTimes:
|
|
13087
|
+
stopTimes: bytesToUint16Array(value.stopTimes),
|
|
13059
13088
|
pickUpDropOffTypes: value.pickUpDropOffTypes,
|
|
13060
13089
|
stops: stops,
|
|
13061
13090
|
stopIndices: indices,
|
|
@@ -13153,7 +13182,7 @@ const serializeRouteType = (type) => {
|
|
|
13153
13182
|
};
|
|
13154
13183
|
|
|
13155
13184
|
/**
|
|
13156
|
-
* A class representing a time
|
|
13185
|
+
* A class representing a time as minutes since midnight.
|
|
13157
13186
|
*/
|
|
13158
13187
|
class Time {
|
|
13159
13188
|
/**
|
|
@@ -13168,25 +13197,26 @@ class Time {
|
|
|
13168
13197
|
/**
|
|
13169
13198
|
* Gets the midnight time as a Time instance.
|
|
13170
13199
|
*
|
|
13171
|
-
* @returns A Time instance representing midnight
|
|
13200
|
+
* @returns A Time instance representing midnight.
|
|
13172
13201
|
*/
|
|
13173
13202
|
static origin() {
|
|
13174
13203
|
return new Time(0);
|
|
13175
13204
|
}
|
|
13176
|
-
constructor(
|
|
13177
|
-
this.
|
|
13205
|
+
constructor(minutes) {
|
|
13206
|
+
this.minutesSinceMidnight = minutes;
|
|
13178
13207
|
}
|
|
13179
13208
|
/**
|
|
13180
|
-
* Creates a Time instance from the number of
|
|
13209
|
+
* Creates a Time instance from the number of minutes since midnight.
|
|
13181
13210
|
*
|
|
13182
|
-
* @param
|
|
13211
|
+
* @param minutes - The number of minutes since midnight.
|
|
13183
13212
|
* @returns A Time instance representing the specified time.
|
|
13184
13213
|
*/
|
|
13185
|
-
static
|
|
13186
|
-
return new Time(
|
|
13214
|
+
static fromMinutes(minutes) {
|
|
13215
|
+
return new Time(minutes);
|
|
13187
13216
|
}
|
|
13188
13217
|
/**
|
|
13189
13218
|
* Creates a Time instance from hours, minutes, and seconds.
|
|
13219
|
+
* Rounds to the closest minute as times are represented in minutes from midnight.
|
|
13190
13220
|
*
|
|
13191
13221
|
* @param hours - The hours component of the time.
|
|
13192
13222
|
* @param minutes - The minutes component of the time.
|
|
@@ -13201,7 +13231,22 @@ class Time {
|
|
|
13201
13231
|
seconds >= 60) {
|
|
13202
13232
|
throw new Error('Invalid time. Ensure hours, minutes, and seconds are valid values.');
|
|
13203
13233
|
}
|
|
13204
|
-
|
|
13234
|
+
const totalSeconds = seconds + 60 * minutes + 3600 * hours;
|
|
13235
|
+
const roundedMinutes = Math.round(totalSeconds / 60);
|
|
13236
|
+
return new Time(roundedMinutes);
|
|
13237
|
+
}
|
|
13238
|
+
/**
|
|
13239
|
+
* Creates a Time instance from hours, minutes.
|
|
13240
|
+
*
|
|
13241
|
+
* @param hours - The hours component of the time.
|
|
13242
|
+
* @param minutes - The minutes component of the time.
|
|
13243
|
+
* @returns A Time instance representing the specified time.
|
|
13244
|
+
*/
|
|
13245
|
+
static fromHM(hours, minutes) {
|
|
13246
|
+
if (hours < 0 || minutes < 0 || minutes >= 60) {
|
|
13247
|
+
throw new Error('Invalid time. Ensure hours and minutes are valid values.');
|
|
13248
|
+
}
|
|
13249
|
+
return new Time(minutes + hours * 60);
|
|
13205
13250
|
}
|
|
13206
13251
|
/**
|
|
13207
13252
|
* Parses a JavaScript Date object and creates a Time instance.
|
|
@@ -13213,7 +13258,7 @@ class Time {
|
|
|
13213
13258
|
const hours = date.getHours();
|
|
13214
13259
|
const minutes = date.getMinutes();
|
|
13215
13260
|
const seconds = date.getSeconds();
|
|
13216
|
-
return
|
|
13261
|
+
return Time.fromHMS(hours, minutes, seconds);
|
|
13217
13262
|
}
|
|
13218
13263
|
/**
|
|
13219
13264
|
* Parses a time string in the format "HH:MM:SS" or "HH:MM" and creates a Time instance.
|
|
@@ -13233,7 +13278,7 @@ class Time {
|
|
|
13233
13278
|
const hours = parseInt(hoursStr, 10);
|
|
13234
13279
|
const minutes = parseInt(minutesStr, 10);
|
|
13235
13280
|
const seconds = secondsStr !== undefined ? parseInt(secondsStr, 10) : 0;
|
|
13236
|
-
return
|
|
13281
|
+
return Time.fromHMS(hours, minutes, seconds);
|
|
13237
13282
|
}
|
|
13238
13283
|
/**
|
|
13239
13284
|
* Converts the Time instance to a string in "HH:MM:SS" format.
|
|
@@ -13241,20 +13286,17 @@ class Time {
|
|
|
13241
13286
|
* @returns A string representing the time.
|
|
13242
13287
|
*/
|
|
13243
13288
|
toString() {
|
|
13244
|
-
const hours = Math.floor(this.
|
|
13245
|
-
const minutes = Math.floor(
|
|
13246
|
-
|
|
13247
|
-
return `${hours.toString().padStart(2, '0')}:${minutes
|
|
13248
|
-
.toString()
|
|
13249
|
-
.padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|
13289
|
+
const hours = Math.floor(this.minutesSinceMidnight / 60);
|
|
13290
|
+
const minutes = Math.floor(this.minutesSinceMidnight % 60);
|
|
13291
|
+
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
13250
13292
|
}
|
|
13251
13293
|
/**
|
|
13252
|
-
*
|
|
13294
|
+
* Converts the Time instance to the total number of minutes since midnight, rounded to the closest minute.
|
|
13253
13295
|
*
|
|
13254
|
-
* @returns The time in
|
|
13296
|
+
* @returns The time in minutes since midnight.
|
|
13255
13297
|
*/
|
|
13256
|
-
|
|
13257
|
-
return this.
|
|
13298
|
+
toMinutes() {
|
|
13299
|
+
return this.minutesSinceMidnight;
|
|
13258
13300
|
}
|
|
13259
13301
|
/**
|
|
13260
13302
|
* Adds a Duration to the current Time instance and returns a new Time instance.
|
|
@@ -13263,8 +13305,8 @@ class Time {
|
|
|
13263
13305
|
* @returns A new Time instance with the added duration.
|
|
13264
13306
|
*/
|
|
13265
13307
|
plus(duration) {
|
|
13266
|
-
const totalSeconds = this.
|
|
13267
|
-
return new Time(totalSeconds);
|
|
13308
|
+
const totalSeconds = this.minutesSinceMidnight * 60 + duration.toSeconds();
|
|
13309
|
+
return new Time(Math.round(totalSeconds / 60));
|
|
13268
13310
|
}
|
|
13269
13311
|
/**
|
|
13270
13312
|
* Subtracts a Duration from the current Time instance and returns a new Time instance.
|
|
@@ -13273,11 +13315,11 @@ class Time {
|
|
|
13273
13315
|
* @returns A new Time instance with the subtracted duration.
|
|
13274
13316
|
*/
|
|
13275
13317
|
minus(duration) {
|
|
13276
|
-
let totalSeconds = this.
|
|
13318
|
+
let totalSeconds = this.minutesSinceMidnight * 60 - duration.toSeconds();
|
|
13277
13319
|
if (totalSeconds < 0) {
|
|
13278
13320
|
totalSeconds += 24 * 3600; // Adjust for negative time to loop back to previous day
|
|
13279
13321
|
}
|
|
13280
|
-
return new Time(totalSeconds);
|
|
13322
|
+
return new Time(Math.round(totalSeconds / 60));
|
|
13281
13323
|
}
|
|
13282
13324
|
/**
|
|
13283
13325
|
* Subtracts another Time instance from the current Time instance and returns the Duration.
|
|
@@ -13286,8 +13328,8 @@ class Time {
|
|
|
13286
13328
|
* @returns A Duration instance representing the time difference.
|
|
13287
13329
|
*/
|
|
13288
13330
|
diff(otherTime) {
|
|
13289
|
-
const
|
|
13290
|
-
return Duration.fromSeconds(Math.abs(
|
|
13331
|
+
const totalMinutes = this.minutesSinceMidnight - otherTime.toMinutes();
|
|
13332
|
+
return Duration.fromSeconds(Math.abs(totalMinutes * 60));
|
|
13291
13333
|
}
|
|
13292
13334
|
/**
|
|
13293
13335
|
* Computes the maximum Time instance among the provided Time instances.
|
|
@@ -13300,7 +13342,7 @@ class Time {
|
|
|
13300
13342
|
throw new Error('At least one Time instance is required.');
|
|
13301
13343
|
}
|
|
13302
13344
|
return times.reduce((maxTime, currentTime) => {
|
|
13303
|
-
return currentTime.
|
|
13345
|
+
return currentTime.toMinutes() > maxTime.toMinutes()
|
|
13304
13346
|
? currentTime
|
|
13305
13347
|
: maxTime;
|
|
13306
13348
|
});
|
|
@@ -13316,7 +13358,7 @@ class Time {
|
|
|
13316
13358
|
throw new Error('At least one Time instance is required.');
|
|
13317
13359
|
}
|
|
13318
13360
|
return times.reduce((minTime, currentTime) => {
|
|
13319
|
-
return currentTime.
|
|
13361
|
+
return currentTime.toMinutes() < minTime.toMinutes()
|
|
13320
13362
|
? currentTime
|
|
13321
13363
|
: minTime;
|
|
13322
13364
|
});
|
|
@@ -13339,7 +13381,7 @@ const ALL_TRANSPORT_MODES = [
|
|
|
13339
13381
|
'TROLLEYBUS',
|
|
13340
13382
|
'MONORAIL',
|
|
13341
13383
|
];
|
|
13342
|
-
const CURRENT_VERSION = '0.0.
|
|
13384
|
+
const CURRENT_VERSION = '0.0.3';
|
|
13343
13385
|
/**
|
|
13344
13386
|
* The internal transit timetable format
|
|
13345
13387
|
* reuses some GTFS concepts for the sake of simplicity for now.
|
|
@@ -13461,7 +13503,7 @@ class Timetable {
|
|
|
13461
13503
|
const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
|
|
13462
13504
|
const departure = route.stopTimes[stopTimeIndex * 2 + 1];
|
|
13463
13505
|
const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
|
|
13464
|
-
if (departure >= after.
|
|
13506
|
+
if (departure >= after.toMinutes() && pickUpType !== NOT_AVAILABLE) {
|
|
13465
13507
|
return tripIndex;
|
|
13466
13508
|
}
|
|
13467
13509
|
}
|
|
@@ -13475,14 +13517,14 @@ class Timetable {
|
|
|
13475
13517
|
const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
|
|
13476
13518
|
const departure = route.stopTimes[stopTimeIndex * 2 + 1];
|
|
13477
13519
|
const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
|
|
13478
|
-
if (departure < after.
|
|
13520
|
+
if (departure < after.toMinutes()) {
|
|
13479
13521
|
break;
|
|
13480
13522
|
}
|
|
13481
13523
|
if (pickUpType !== NOT_AVAILABLE &&
|
|
13482
13524
|
(earliestDeparture === undefined ||
|
|
13483
|
-
departure < earliestDeparture.
|
|
13525
|
+
departure < earliestDeparture.toMinutes())) {
|
|
13484
13526
|
earliestTripIndex = tripIndex;
|
|
13485
|
-
earliestDeparture = Time.
|
|
13527
|
+
earliestDeparture = Time.fromMinutes(departure);
|
|
13486
13528
|
}
|
|
13487
13529
|
}
|
|
13488
13530
|
return earliestTripIndex;
|
|
@@ -15847,7 +15889,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
15847
15889
|
if (!route) {
|
|
15848
15890
|
const stopsCount = stops.length;
|
|
15849
15891
|
const stopsArray = new Uint32Array(stops);
|
|
15850
|
-
const stopTimesArray = new
|
|
15892
|
+
const stopTimesArray = new Uint16Array(stopsCount * 2);
|
|
15851
15893
|
for (let i = 0; i < stopsCount; i++) {
|
|
15852
15894
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15853
15895
|
stopTimesArray[i * 2] = arrivalTimes[i];
|
|
@@ -15893,7 +15935,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
15893
15935
|
}
|
|
15894
15936
|
// insert data for the new trip at the right place
|
|
15895
15937
|
const newStopTimesLength = route.stopTimes.length + stopsCount * 2;
|
|
15896
|
-
const newStopTimes = new
|
|
15938
|
+
const newStopTimes = new Uint16Array(newStopTimesLength);
|
|
15897
15939
|
const newPickUpDropOffTypes = new Uint8Array(newStopTimesLength);
|
|
15898
15940
|
newStopTimes.set(route.stopTimes.slice(0, insertPosition * 2), 0);
|
|
15899
15941
|
newPickUpDropOffTypes.set(route.pickUpDropOffTypes.slice(0, insertPosition * 2), 0);
|
|
@@ -15954,9 +15996,9 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
15954
15996
|
const departure = (_d = line.departure_time) !== null && _d !== void 0 ? _d : line.arrival_time;
|
|
15955
15997
|
const arrival = (_e = line.arrival_time) !== null && _e !== void 0 ? _e : line.departure_time;
|
|
15956
15998
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15957
|
-
arrivalTimes.push(toTime(arrival).
|
|
15999
|
+
arrivalTimes.push(toTime(arrival).toMinutes());
|
|
15958
16000
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15959
|
-
departureTimes.push(toTime(departure).
|
|
16001
|
+
departureTimes.push(toTime(departure).toMinutes());
|
|
15960
16002
|
pickUpTypes.push(parsePickupDropOffType(line.pickup_type));
|
|
15961
16003
|
dropOffTypes.push(parsePickupDropOffType(line.drop_off_type));
|
|
15962
16004
|
previousSeq = line.stop_sequence;
|