minotor 2.0.1 → 3.0.1
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/.cspell.json +3 -1
- package/CHANGELOG.md +2 -2
- package/README.md +13 -3
- 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.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 -2
- 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/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/.cspell.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
## [
|
|
1
|
+
## [3.0.1](https://github.com/aubryio/minotor/compare/v3.0.0...v3.0.1) (2025-06-03)
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
### Bug Fixes
|
|
5
5
|
|
|
6
|
-
*
|
|
6
|
+
* do not pin point lib version for the repl ([#18](https://github.com/aubryio/minotor/issues/18)) ([2cef9e7](https://github.com/aubryio/minotor/commit/2cef9e7488f09743aba52e2ebb0ae52bead476c6))
|
package/README.md
CHANGED
|
@@ -13,13 +13,23 @@ Privacy-conscious applications where the user does not want to share their locat
|
|
|
13
13
|
The transit router and the stops index of **minotor** can run in the browser, on react-native or in a Node.js environment.
|
|
14
14
|
Transit data (GTFS) parsing runs on Node.js, and the resulting data is serialized as a protobuf binary that can be loaded from the router.
|
|
15
15
|
|
|
16
|
+
Minotor routing algorithm is mostly based on RAPTOR. See [Round-Based Public Transit Routing, D. Delling et al. 2012](https://www.microsoft.com/en-us/research/wp-content/uploads/2012/01/raptor_alenex.pdf).
|
|
17
|
+
|
|
16
18
|
## Examples
|
|
17
19
|
|
|
18
20
|
### In-browser transit router
|
|
19
21
|
|
|
20
22
|
An example client-side transit router running in the browser with a web worker.
|
|
21
23
|
|
|
22
|
-
[Demo](https://www.minotor.dev/#
|
|
24
|
+
[Demo](https://www.minotor.dev/#router) | [Code](https://github.com/aubryio/minotor.dev/tree/main/app/examples/planner)
|
|
25
|
+
|
|
26
|
+
### Isochrone maps
|
|
27
|
+
|
|
28
|
+
An example implementation of dynamic isochrone maps using minotor in the browser.
|
|
29
|
+
|
|
30
|
+
[Demo](https://www.minotor.dev/#isochrones) | [Code](https://github.com/aubryio/minotor.dev/tree/main/app/examples/isochrones)
|
|
31
|
+
|
|
32
|
+
A more complete isochrone map showcase can be found on [isochrone.ch](https://isochrone.ch).
|
|
23
33
|
|
|
24
34
|
## Features
|
|
25
35
|
|
|
@@ -32,7 +42,7 @@ An example client-side transit router running in the browser with a web worker.
|
|
|
32
42
|
|
|
33
43
|
| Feed | Parsing time | Timetable Size for a Day (Compressed) |
|
|
34
44
|
| ------------------------------------------------------------------------------------------ | ------------ | ------------------------------------- |
|
|
35
|
-
| [Swiss GTFS feed](https://data.opentransportdata.swiss/en/dataset/timetable-2025-gtfs2020) | ~2 minutes |
|
|
45
|
+
| [Swiss GTFS feed](https://data.opentransportdata.swiss/en/dataset/timetable-2025-gtfs2020) | ~2 minutes | 20 MB (5MB) |
|
|
36
46
|
|
|
37
47
|
## Get started
|
|
38
48
|
|
|
@@ -63,7 +73,7 @@ const destinations = stopsIndex.findStopsByName('Moles'); // Partial name search
|
|
|
63
73
|
|
|
64
74
|
Query stops by ID:
|
|
65
75
|
|
|
66
|
-
`const stopFromId = stopsIndex.
|
|
76
|
+
`const stopFromId = stopsIndex.findStopBySourceId('8592374:0:A');`
|
|
67
77
|
|
|
68
78
|
Or by location:
|
|
69
79
|
|
package/dist/cli.mjs
CHANGED
|
@@ -16756,6 +16756,35 @@ function bytesToUint32Array(bytes) {
|
|
|
16756
16756
|
}
|
|
16757
16757
|
return result;
|
|
16758
16758
|
}
|
|
16759
|
+
function uint16ArrayToBytes(array) {
|
|
16760
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
16761
|
+
return new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
16762
|
+
}
|
|
16763
|
+
// If endianness doesn't match, we need to swap byte order
|
|
16764
|
+
const result = new Uint8Array(array.length * 2);
|
|
16765
|
+
const view = new DataView(result.buffer);
|
|
16766
|
+
for (let i = 0; i < array.length; i++) {
|
|
16767
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
16768
|
+
view.setUint16(i * 2, array[i], STANDARD_ENDIANNESS);
|
|
16769
|
+
}
|
|
16770
|
+
return result;
|
|
16771
|
+
}
|
|
16772
|
+
function bytesToUint16Array(bytes) {
|
|
16773
|
+
if (bytes.byteLength % 2 !== 0) {
|
|
16774
|
+
throw new Error('Byte array length must be a multiple of 2 to convert to Uint16Array');
|
|
16775
|
+
}
|
|
16776
|
+
// If system endianness matches our standard, we can create a view directly
|
|
16777
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
16778
|
+
return new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2);
|
|
16779
|
+
}
|
|
16780
|
+
// If endianness doesn't match, we need to swap byte order
|
|
16781
|
+
const result = new Uint16Array(bytes.byteLength / 2);
|
|
16782
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
16783
|
+
for (let i = 0; i < result.length; i++) {
|
|
16784
|
+
result[i] = view.getUint16(i * 2, STANDARD_ENDIANNESS);
|
|
16785
|
+
}
|
|
16786
|
+
return result;
|
|
16787
|
+
}
|
|
16759
16788
|
const serializeStopsAdjacency = (stopsAdjacency) => {
|
|
16760
16789
|
const protoStopsAdjacency = {
|
|
16761
16790
|
stops: {},
|
|
@@ -16776,7 +16805,7 @@ const serializeRoutesAdjacency = (routesAdjacency) => {
|
|
|
16776
16805
|
};
|
|
16777
16806
|
routesAdjacency.forEach((value, key) => {
|
|
16778
16807
|
protoRoutesAdjacency.routes[key] = {
|
|
16779
|
-
stopTimes:
|
|
16808
|
+
stopTimes: uint16ArrayToBytes(value.stopTimes),
|
|
16780
16809
|
pickUpDropOffTypes: value.pickUpDropOffTypes,
|
|
16781
16810
|
stops: uint32ArrayToBytes(value.stops),
|
|
16782
16811
|
serviceRouteId: value.serviceRouteId,
|
|
@@ -16819,7 +16848,7 @@ const deserializeRoutesAdjacency = (protoRoutesAdjacency) => {
|
|
|
16819
16848
|
indices.set(stops[i], i);
|
|
16820
16849
|
}
|
|
16821
16850
|
routesAdjacency.set(key, {
|
|
16822
|
-
stopTimes:
|
|
16851
|
+
stopTimes: bytesToUint16Array(value.stopTimes),
|
|
16823
16852
|
pickUpDropOffTypes: value.pickUpDropOffTypes,
|
|
16824
16853
|
stops: stops,
|
|
16825
16854
|
stopIndices: indices,
|
|
@@ -16917,7 +16946,7 @@ const serializeRouteType = (type) => {
|
|
|
16917
16946
|
};
|
|
16918
16947
|
|
|
16919
16948
|
/**
|
|
16920
|
-
* A class representing a time
|
|
16949
|
+
* A class representing a time as minutes since midnight.
|
|
16921
16950
|
*/
|
|
16922
16951
|
class Time {
|
|
16923
16952
|
/**
|
|
@@ -16932,25 +16961,26 @@ class Time {
|
|
|
16932
16961
|
/**
|
|
16933
16962
|
* Gets the midnight time as a Time instance.
|
|
16934
16963
|
*
|
|
16935
|
-
* @returns A Time instance representing midnight
|
|
16964
|
+
* @returns A Time instance representing midnight.
|
|
16936
16965
|
*/
|
|
16937
16966
|
static origin() {
|
|
16938
16967
|
return new Time(0);
|
|
16939
16968
|
}
|
|
16940
|
-
constructor(
|
|
16941
|
-
this.
|
|
16969
|
+
constructor(minutes) {
|
|
16970
|
+
this.minutesSinceMidnight = minutes;
|
|
16942
16971
|
}
|
|
16943
16972
|
/**
|
|
16944
|
-
* Creates a Time instance from the number of
|
|
16973
|
+
* Creates a Time instance from the number of minutes since midnight.
|
|
16945
16974
|
*
|
|
16946
|
-
* @param
|
|
16975
|
+
* @param minutes - The number of minutes since midnight.
|
|
16947
16976
|
* @returns A Time instance representing the specified time.
|
|
16948
16977
|
*/
|
|
16949
|
-
static
|
|
16950
|
-
return new Time(
|
|
16978
|
+
static fromMinutes(minutes) {
|
|
16979
|
+
return new Time(minutes);
|
|
16951
16980
|
}
|
|
16952
16981
|
/**
|
|
16953
16982
|
* Creates a Time instance from hours, minutes, and seconds.
|
|
16983
|
+
* Rounds to the closest minute as times are represented in minutes from midnight.
|
|
16954
16984
|
*
|
|
16955
16985
|
* @param hours - The hours component of the time.
|
|
16956
16986
|
* @param minutes - The minutes component of the time.
|
|
@@ -16965,7 +16995,22 @@ class Time {
|
|
|
16965
16995
|
seconds >= 60) {
|
|
16966
16996
|
throw new Error('Invalid time. Ensure hours, minutes, and seconds are valid values.');
|
|
16967
16997
|
}
|
|
16968
|
-
|
|
16998
|
+
const totalSeconds = seconds + 60 * minutes + 3600 * hours;
|
|
16999
|
+
const roundedMinutes = Math.round(totalSeconds / 60);
|
|
17000
|
+
return new Time(roundedMinutes);
|
|
17001
|
+
}
|
|
17002
|
+
/**
|
|
17003
|
+
* Creates a Time instance from hours, minutes.
|
|
17004
|
+
*
|
|
17005
|
+
* @param hours - The hours component of the time.
|
|
17006
|
+
* @param minutes - The minutes component of the time.
|
|
17007
|
+
* @returns A Time instance representing the specified time.
|
|
17008
|
+
*/
|
|
17009
|
+
static fromHM(hours, minutes) {
|
|
17010
|
+
if (hours < 0 || minutes < 0 || minutes >= 60) {
|
|
17011
|
+
throw new Error('Invalid time. Ensure hours and minutes are valid values.');
|
|
17012
|
+
}
|
|
17013
|
+
return new Time(minutes + hours * 60);
|
|
16969
17014
|
}
|
|
16970
17015
|
/**
|
|
16971
17016
|
* Parses a JavaScript Date object and creates a Time instance.
|
|
@@ -16977,7 +17022,7 @@ class Time {
|
|
|
16977
17022
|
const hours = date.getHours();
|
|
16978
17023
|
const minutes = date.getMinutes();
|
|
16979
17024
|
const seconds = date.getSeconds();
|
|
16980
|
-
return
|
|
17025
|
+
return Time.fromHMS(hours, minutes, seconds);
|
|
16981
17026
|
}
|
|
16982
17027
|
/**
|
|
16983
17028
|
* Parses a time string in the format "HH:MM:SS" or "HH:MM" and creates a Time instance.
|
|
@@ -16997,7 +17042,7 @@ class Time {
|
|
|
16997
17042
|
const hours = parseInt(hoursStr, 10);
|
|
16998
17043
|
const minutes = parseInt(minutesStr, 10);
|
|
16999
17044
|
const seconds = secondsStr !== undefined ? parseInt(secondsStr, 10) : 0;
|
|
17000
|
-
return
|
|
17045
|
+
return Time.fromHMS(hours, minutes, seconds);
|
|
17001
17046
|
}
|
|
17002
17047
|
/**
|
|
17003
17048
|
* Converts the Time instance to a string in "HH:MM:SS" format.
|
|
@@ -17005,20 +17050,17 @@ class Time {
|
|
|
17005
17050
|
* @returns A string representing the time.
|
|
17006
17051
|
*/
|
|
17007
17052
|
toString() {
|
|
17008
|
-
const hours = Math.floor(this.
|
|
17009
|
-
const minutes = Math.floor(
|
|
17010
|
-
|
|
17011
|
-
return `${hours.toString().padStart(2, '0')}:${minutes
|
|
17012
|
-
.toString()
|
|
17013
|
-
.padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|
17053
|
+
const hours = Math.floor(this.minutesSinceMidnight / 60);
|
|
17054
|
+
const minutes = Math.floor(this.minutesSinceMidnight % 60);
|
|
17055
|
+
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
17014
17056
|
}
|
|
17015
17057
|
/**
|
|
17016
|
-
*
|
|
17058
|
+
* Converts the Time instance to the total number of minutes since midnight, rounded to the closest minute.
|
|
17017
17059
|
*
|
|
17018
|
-
* @returns The time in
|
|
17060
|
+
* @returns The time in minutes since midnight.
|
|
17019
17061
|
*/
|
|
17020
|
-
|
|
17021
|
-
return this.
|
|
17062
|
+
toMinutes() {
|
|
17063
|
+
return this.minutesSinceMidnight;
|
|
17022
17064
|
}
|
|
17023
17065
|
/**
|
|
17024
17066
|
* Adds a Duration to the current Time instance and returns a new Time instance.
|
|
@@ -17027,8 +17069,8 @@ class Time {
|
|
|
17027
17069
|
* @returns A new Time instance with the added duration.
|
|
17028
17070
|
*/
|
|
17029
17071
|
plus(duration) {
|
|
17030
|
-
const totalSeconds = this.
|
|
17031
|
-
return new Time(totalSeconds);
|
|
17072
|
+
const totalSeconds = this.minutesSinceMidnight * 60 + duration.toSeconds();
|
|
17073
|
+
return new Time(Math.round(totalSeconds / 60));
|
|
17032
17074
|
}
|
|
17033
17075
|
/**
|
|
17034
17076
|
* Subtracts a Duration from the current Time instance and returns a new Time instance.
|
|
@@ -17037,11 +17079,11 @@ class Time {
|
|
|
17037
17079
|
* @returns A new Time instance with the subtracted duration.
|
|
17038
17080
|
*/
|
|
17039
17081
|
minus(duration) {
|
|
17040
|
-
let totalSeconds = this.
|
|
17082
|
+
let totalSeconds = this.minutesSinceMidnight * 60 - duration.toSeconds();
|
|
17041
17083
|
if (totalSeconds < 0) {
|
|
17042
17084
|
totalSeconds += 24 * 3600; // Adjust for negative time to loop back to previous day
|
|
17043
17085
|
}
|
|
17044
|
-
return new Time(totalSeconds);
|
|
17086
|
+
return new Time(Math.round(totalSeconds / 60));
|
|
17045
17087
|
}
|
|
17046
17088
|
/**
|
|
17047
17089
|
* Subtracts another Time instance from the current Time instance and returns the Duration.
|
|
@@ -17050,8 +17092,8 @@ class Time {
|
|
|
17050
17092
|
* @returns A Duration instance representing the time difference.
|
|
17051
17093
|
*/
|
|
17052
17094
|
diff(otherTime) {
|
|
17053
|
-
const
|
|
17054
|
-
return Duration.fromSeconds(Math.abs(
|
|
17095
|
+
const totalMinutes = this.minutesSinceMidnight - otherTime.toMinutes();
|
|
17096
|
+
return Duration.fromSeconds(Math.abs(totalMinutes * 60));
|
|
17055
17097
|
}
|
|
17056
17098
|
/**
|
|
17057
17099
|
* Computes the maximum Time instance among the provided Time instances.
|
|
@@ -17064,7 +17106,7 @@ class Time {
|
|
|
17064
17106
|
throw new Error('At least one Time instance is required.');
|
|
17065
17107
|
}
|
|
17066
17108
|
return times.reduce((maxTime, currentTime) => {
|
|
17067
|
-
return currentTime.
|
|
17109
|
+
return currentTime.toMinutes() > maxTime.toMinutes()
|
|
17068
17110
|
? currentTime
|
|
17069
17111
|
: maxTime;
|
|
17070
17112
|
});
|
|
@@ -17080,7 +17122,7 @@ class Time {
|
|
|
17080
17122
|
throw new Error('At least one Time instance is required.');
|
|
17081
17123
|
}
|
|
17082
17124
|
return times.reduce((minTime, currentTime) => {
|
|
17083
|
-
return currentTime.
|
|
17125
|
+
return currentTime.toMinutes() < minTime.toMinutes()
|
|
17084
17126
|
? currentTime
|
|
17085
17127
|
: minTime;
|
|
17086
17128
|
});
|
|
@@ -17103,7 +17145,7 @@ const ALL_TRANSPORT_MODES = [
|
|
|
17103
17145
|
'TROLLEYBUS',
|
|
17104
17146
|
'MONORAIL',
|
|
17105
17147
|
];
|
|
17106
|
-
const CURRENT_VERSION = '0.0.
|
|
17148
|
+
const CURRENT_VERSION = '0.0.3';
|
|
17107
17149
|
/**
|
|
17108
17150
|
* The internal transit timetable format
|
|
17109
17151
|
* reuses some GTFS concepts for the sake of simplicity for now.
|
|
@@ -17225,7 +17267,7 @@ class Timetable {
|
|
|
17225
17267
|
const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
|
|
17226
17268
|
const departure = route.stopTimes[stopTimeIndex * 2 + 1];
|
|
17227
17269
|
const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
|
|
17228
|
-
if (departure >= after.
|
|
17270
|
+
if (departure >= after.toMinutes() && pickUpType !== NOT_AVAILABLE) {
|
|
17229
17271
|
return tripIndex;
|
|
17230
17272
|
}
|
|
17231
17273
|
}
|
|
@@ -17239,14 +17281,14 @@ class Timetable {
|
|
|
17239
17281
|
const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
|
|
17240
17282
|
const departure = route.stopTimes[stopTimeIndex * 2 + 1];
|
|
17241
17283
|
const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
|
|
17242
|
-
if (departure < after.
|
|
17284
|
+
if (departure < after.toMinutes()) {
|
|
17243
17285
|
break;
|
|
17244
17286
|
}
|
|
17245
17287
|
if (pickUpType !== NOT_AVAILABLE &&
|
|
17246
17288
|
(earliestDeparture === undefined ||
|
|
17247
|
-
departure < earliestDeparture.
|
|
17289
|
+
departure < earliestDeparture.toMinutes())) {
|
|
17248
17290
|
earliestTripIndex = tripIndex;
|
|
17249
|
-
earliestDeparture = Time.
|
|
17291
|
+
earliestDeparture = Time.fromMinutes(departure);
|
|
17250
17292
|
}
|
|
17251
17293
|
}
|
|
17252
17294
|
return earliestTripIndex;
|
|
@@ -19611,7 +19653,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
19611
19653
|
if (!route) {
|
|
19612
19654
|
const stopsCount = stops.length;
|
|
19613
19655
|
const stopsArray = new Uint32Array(stops);
|
|
19614
|
-
const stopTimesArray = new
|
|
19656
|
+
const stopTimesArray = new Uint16Array(stopsCount * 2);
|
|
19615
19657
|
for (let i = 0; i < stopsCount; i++) {
|
|
19616
19658
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
19617
19659
|
stopTimesArray[i * 2] = arrivalTimes[i];
|
|
@@ -19657,7 +19699,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
19657
19699
|
}
|
|
19658
19700
|
// insert data for the new trip at the right place
|
|
19659
19701
|
const newStopTimesLength = route.stopTimes.length + stopsCount * 2;
|
|
19660
|
-
const newStopTimes = new
|
|
19702
|
+
const newStopTimes = new Uint16Array(newStopTimesLength);
|
|
19661
19703
|
const newPickUpDropOffTypes = new Uint8Array(newStopTimesLength);
|
|
19662
19704
|
newStopTimes.set(route.stopTimes.slice(0, insertPosition * 2), 0);
|
|
19663
19705
|
newPickUpDropOffTypes.set(route.pickUpDropOffTypes.slice(0, insertPosition * 2), 0);
|
|
@@ -19718,9 +19760,9 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
19718
19760
|
const departure = (_d = line.departure_time) !== null && _d !== void 0 ? _d : line.arrival_time;
|
|
19719
19761
|
const arrival = (_e = line.arrival_time) !== null && _e !== void 0 ? _e : line.departure_time;
|
|
19720
19762
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
19721
|
-
arrivalTimes.push(toTime(arrival).
|
|
19763
|
+
arrivalTimes.push(toTime(arrival).toMinutes());
|
|
19722
19764
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
19723
|
-
departureTimes.push(toTime(departure).
|
|
19765
|
+
departureTimes.push(toTime(departure).toMinutes());
|
|
19724
19766
|
pickUpTypes.push(parsePickupDropOffType(line.pickup_type));
|
|
19725
19767
|
dropOffTypes.push(parsePickupDropOffType(line.drop_off_type));
|
|
19726
19768
|
previousSeq = line.stop_sequence;
|
|
@@ -20099,7 +20141,7 @@ class Result {
|
|
|
20099
20141
|
const arrivalTime = this.earliestArrivals.get(destination.id);
|
|
20100
20142
|
if (arrivalTime !== undefined) {
|
|
20101
20143
|
if (fastestTime === undefined ||
|
|
20102
|
-
arrivalTime.time.
|
|
20144
|
+
arrivalTime.time.toMinutes() < fastestTime.time.toMinutes()) {
|
|
20103
20145
|
fastestDestination = destination.id;
|
|
20104
20146
|
fastestTime = arrivalTime;
|
|
20105
20147
|
}
|
|
@@ -20142,7 +20184,7 @@ class Result {
|
|
|
20142
20184
|
const arrivalTime = relevantArrivals.get(equivalentStop.id);
|
|
20143
20185
|
if (arrivalTime !== undefined) {
|
|
20144
20186
|
if (earliestArrival === undefined ||
|
|
20145
|
-
arrivalTime.time.
|
|
20187
|
+
arrivalTime.time.toMinutes() < earliestArrival.time.toMinutes()) {
|
|
20146
20188
|
earliestArrival = arrivalTime;
|
|
20147
20189
|
}
|
|
20148
20190
|
}
|
|
@@ -20182,7 +20224,7 @@ class Router {
|
|
|
20182
20224
|
.get(stop)
|
|
20183
20225
|
.time.plus(transferTime);
|
|
20184
20226
|
const originalArrival = (_b = (_a = arrivalsAtCurrentRound.get(transfer.destination)) === null || _a === undefined ? undefined : _a.time) !== null && _b !== undefined ? _b : UNREACHED;
|
|
20185
|
-
if (arrivalAfterTransfer.
|
|
20227
|
+
if (arrivalAfterTransfer.toMinutes() < originalArrival.toMinutes()) {
|
|
20186
20228
|
const origin = (_d = (_c = arrivalsAtCurrentRound.get(stop)) === null || _c === undefined ? undefined : _c.origin) !== null && _d !== undefined ? _d : stop;
|
|
20187
20229
|
arrivalsAtCurrentRound.set(transfer.destination, {
|
|
20188
20230
|
time: arrivalAfterTransfer,
|
|
@@ -20260,7 +20302,7 @@ class Router {
|
|
|
20260
20302
|
const stopNumbers = route.stops.length;
|
|
20261
20303
|
if (currentTrip !== undefined) {
|
|
20262
20304
|
const currentArrivalIndex = (currentTrip.trip * stopNumbers + i) * 2;
|
|
20263
|
-
const currentArrivalTime = Time.
|
|
20305
|
+
const currentArrivalTime = Time.fromMinutes(route.stopTimes[currentArrivalIndex]);
|
|
20264
20306
|
const currentDropOffType = route.pickUpDropOffTypes[i * 2 + 1];
|
|
20265
20307
|
const earliestArrivalAtCurrentStop = (_b = (_a = earliestArrivals.get(currentStop)) === null || _a === undefined ? undefined : _a.time) !== null && _b !== undefined ? _b : UNREACHED;
|
|
20266
20308
|
let arrivalToImprove = earliestArrivalAtCurrentStop;
|
|
@@ -20276,10 +20318,10 @@ class Router {
|
|
|
20276
20318
|
arrivalToImprove = Time.min(earliestArrivalAtCurrentStop, earliestArrivalAtDestination);
|
|
20277
20319
|
}
|
|
20278
20320
|
if (currentDropOffType !== NOT_AVAILABLE &&
|
|
20279
|
-
currentArrivalTime.
|
|
20321
|
+
currentArrivalTime.toMinutes() < arrivalToImprove.toMinutes()) {
|
|
20280
20322
|
const bestHopOnStopIndex = route.stopIndices.get(currentTrip.bestHopOnStop);
|
|
20281
20323
|
const bestHopOnStopDepartureIndex = currentTrip.trip * stopNumbers * 2 + bestHopOnStopIndex * 2 + 1;
|
|
20282
|
-
const bestHopOnDepartureTime = Time.
|
|
20324
|
+
const bestHopOnDepartureTime = Time.fromMinutes(route.stopTimes[bestHopOnStopDepartureIndex]);
|
|
20283
20325
|
arrivalsAtCurrentRound.set(currentStop, {
|
|
20284
20326
|
time: currentArrivalTime,
|
|
20285
20327
|
legNumber: round,
|
|
@@ -20305,7 +20347,7 @@ class Router {
|
|
|
20305
20347
|
const earliestArrivalOnPreviousRound = (_e = arrivalsAtPreviousRound.get(currentStop)) === null || _e === undefined ? undefined : _e.time;
|
|
20306
20348
|
if (earliestArrivalOnPreviousRound !== undefined &&
|
|
20307
20349
|
(currentTrip === undefined ||
|
|
20308
|
-
earliestArrivalOnPreviousRound.
|
|
20350
|
+
earliestArrivalOnPreviousRound.toMinutes() <=
|
|
20309
20351
|
route.stopTimes[(currentTrip.trip * stopNumbers + i) * 2])) {
|
|
20310
20352
|
const earliestTrip = this.timetable.findEarliestTrip(route, currentStop, currentTrip === null || currentTrip === undefined ? undefined : currentTrip.trip, earliestArrivalOnPreviousRound);
|
|
20311
20353
|
if (earliestTrip !== undefined) {
|