minotor 8.0.0 → 9.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/.github/workflows/minotor.yml +1 -1
- package/CHANGELOG.md +3 -8
- package/README.md +1 -1
- package/dist/cli.mjs +352 -256
- package/dist/cli.mjs.map +1 -1
- package/dist/gtfs/transfers.d.ts +21 -6
- package/dist/gtfs/trips.d.ts +2 -2
- package/dist/parser.cjs.js +296 -188
- package/dist/parser.cjs.js.map +1 -1
- package/dist/parser.esm.js +296 -188
- 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/routing/router.d.ts +4 -4
- package/dist/timetable/io.d.ts +3 -3
- package/dist/timetable/proto/timetable.d.ts +6 -4
- package/dist/timetable/route.d.ts +13 -21
- package/dist/timetable/timetable.d.ts +13 -11
- package/dist/timetable/tripBoardingId.d.ts +34 -0
- package/package.json +1 -1
- package/src/__e2e__/timetable/timetable.bin +2 -2
- package/src/cli/repl.ts +53 -67
- package/src/gtfs/__tests__/parser.test.ts +19 -4
- package/src/gtfs/__tests__/transfers.test.ts +598 -318
- package/src/gtfs/__tests__/trips.test.ts +3 -44
- package/src/gtfs/parser.ts +26 -8
- package/src/gtfs/transfers.ts +151 -20
- package/src/gtfs/trips.ts +1 -39
- package/src/routing/__tests__/result.test.ts +10 -10
- package/src/routing/__tests__/router.test.ts +11 -9
- package/src/routing/result.ts +2 -2
- package/src/routing/router.ts +34 -22
- package/src/timetable/__tests__/io.test.ts +8 -7
- package/src/timetable/__tests__/route.test.ts +66 -80
- package/src/timetable/__tests__/timetable.test.ts +32 -29
- package/src/timetable/__tests__/tripBoardingId.test.ts +57 -0
- package/src/timetable/io.ts +21 -20
- package/src/timetable/proto/timetable.proto +6 -4
- package/src/timetable/proto/timetable.ts +84 -48
- package/src/timetable/route.ts +39 -56
- package/src/timetable/timetable.ts +37 -26
- package/src/timetable/tripBoardingId.ts +94 -0
- package/dist/timetable/tripId.d.ts +0 -15
- package/src/timetable/__tests__/tripId.test.ts +0 -27
- package/src/timetable/tripId.ts +0 -29
- /package/dist/timetable/__tests__/{tripId.test.d.ts → tripBoardingId.test.d.ts} +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -16607,12 +16607,12 @@ const Transfer = {
|
|
|
16607
16607
|
},
|
|
16608
16608
|
};
|
|
16609
16609
|
function createBaseTripBoarding() {
|
|
16610
|
-
return {
|
|
16610
|
+
return { hopOnStopIndex: 0, routeId: 0, tripIndex: 0 };
|
|
16611
16611
|
}
|
|
16612
16612
|
const TripBoarding = {
|
|
16613
16613
|
encode(message, writer = new BinaryWriter()) {
|
|
16614
|
-
if (message.
|
|
16615
|
-
writer.uint32(8).uint32(message.
|
|
16614
|
+
if (message.hopOnStopIndex !== 0) {
|
|
16615
|
+
writer.uint32(8).uint32(message.hopOnStopIndex);
|
|
16616
16616
|
}
|
|
16617
16617
|
if (message.routeId !== 0) {
|
|
16618
16618
|
writer.uint32(16).uint32(message.routeId);
|
|
@@ -16633,7 +16633,7 @@ const TripBoarding = {
|
|
|
16633
16633
|
if (tag !== 8) {
|
|
16634
16634
|
break;
|
|
16635
16635
|
}
|
|
16636
|
-
message.
|
|
16636
|
+
message.hopOnStopIndex = reader.uint32();
|
|
16637
16637
|
continue;
|
|
16638
16638
|
}
|
|
16639
16639
|
case 2: {
|
|
@@ -16660,15 +16660,15 @@ const TripBoarding = {
|
|
|
16660
16660
|
},
|
|
16661
16661
|
fromJSON(object) {
|
|
16662
16662
|
return {
|
|
16663
|
-
|
|
16663
|
+
hopOnStopIndex: isSet(object.hopOnStopIndex) ? globalThis.Number(object.hopOnStopIndex) : 0,
|
|
16664
16664
|
routeId: isSet(object.routeId) ? globalThis.Number(object.routeId) : 0,
|
|
16665
16665
|
tripIndex: isSet(object.tripIndex) ? globalThis.Number(object.tripIndex) : 0,
|
|
16666
16666
|
};
|
|
16667
16667
|
},
|
|
16668
16668
|
toJSON(message) {
|
|
16669
16669
|
const obj = {};
|
|
16670
|
-
if (message.
|
|
16671
|
-
obj.
|
|
16670
|
+
if (message.hopOnStopIndex !== 0) {
|
|
16671
|
+
obj.hopOnStopIndex = Math.round(message.hopOnStopIndex);
|
|
16672
16672
|
}
|
|
16673
16673
|
if (message.routeId !== 0) {
|
|
16674
16674
|
obj.routeId = Math.round(message.routeId);
|
|
@@ -16684,22 +16684,28 @@ const TripBoarding = {
|
|
|
16684
16684
|
fromPartial(object) {
|
|
16685
16685
|
var _a, _b, _c;
|
|
16686
16686
|
const message = createBaseTripBoarding();
|
|
16687
|
-
message.
|
|
16687
|
+
message.hopOnStopIndex = (_a = object.hopOnStopIndex) !== null && _a !== void 0 ? _a : 0;
|
|
16688
16688
|
message.routeId = (_b = object.routeId) !== null && _b !== void 0 ? _b : 0;
|
|
16689
16689
|
message.tripIndex = (_c = object.tripIndex) !== null && _c !== void 0 ? _c : 0;
|
|
16690
16690
|
return message;
|
|
16691
16691
|
},
|
|
16692
16692
|
};
|
|
16693
16693
|
function createBaseTripContinuationEntry() {
|
|
16694
|
-
return {
|
|
16694
|
+
return { originStopIndex: 0, originRouteId: 0, originTripIndex: 0, continuations: [] };
|
|
16695
16695
|
}
|
|
16696
16696
|
const TripContinuationEntry = {
|
|
16697
16697
|
encode(message, writer = new BinaryWriter()) {
|
|
16698
|
-
if (message.
|
|
16699
|
-
writer.uint32(8).uint32(message.
|
|
16698
|
+
if (message.originStopIndex !== 0) {
|
|
16699
|
+
writer.uint32(8).uint32(message.originStopIndex);
|
|
16700
16700
|
}
|
|
16701
|
-
|
|
16702
|
-
|
|
16701
|
+
if (message.originRouteId !== 0) {
|
|
16702
|
+
writer.uint32(16).uint32(message.originRouteId);
|
|
16703
|
+
}
|
|
16704
|
+
if (message.originTripIndex !== 0) {
|
|
16705
|
+
writer.uint32(24).uint32(message.originTripIndex);
|
|
16706
|
+
}
|
|
16707
|
+
for (const v of message.continuations) {
|
|
16708
|
+
TripBoarding.encode(v, writer.uint32(34).fork()).join();
|
|
16703
16709
|
}
|
|
16704
16710
|
return writer;
|
|
16705
16711
|
},
|
|
@@ -16714,14 +16720,28 @@ const TripContinuationEntry = {
|
|
|
16714
16720
|
if (tag !== 8) {
|
|
16715
16721
|
break;
|
|
16716
16722
|
}
|
|
16717
|
-
message.
|
|
16723
|
+
message.originStopIndex = reader.uint32();
|
|
16718
16724
|
continue;
|
|
16719
16725
|
}
|
|
16720
16726
|
case 2: {
|
|
16721
|
-
if (tag !==
|
|
16727
|
+
if (tag !== 16) {
|
|
16728
|
+
break;
|
|
16729
|
+
}
|
|
16730
|
+
message.originRouteId = reader.uint32();
|
|
16731
|
+
continue;
|
|
16732
|
+
}
|
|
16733
|
+
case 3: {
|
|
16734
|
+
if (tag !== 24) {
|
|
16722
16735
|
break;
|
|
16723
16736
|
}
|
|
16724
|
-
message.
|
|
16737
|
+
message.originTripIndex = reader.uint32();
|
|
16738
|
+
continue;
|
|
16739
|
+
}
|
|
16740
|
+
case 4: {
|
|
16741
|
+
if (tag !== 34) {
|
|
16742
|
+
break;
|
|
16743
|
+
}
|
|
16744
|
+
message.continuations.push(TripBoarding.decode(reader, reader.uint32()));
|
|
16725
16745
|
continue;
|
|
16726
16746
|
}
|
|
16727
16747
|
}
|
|
@@ -16734,18 +16754,28 @@ const TripContinuationEntry = {
|
|
|
16734
16754
|
},
|
|
16735
16755
|
fromJSON(object) {
|
|
16736
16756
|
return {
|
|
16737
|
-
|
|
16738
|
-
|
|
16757
|
+
originStopIndex: isSet(object.originStopIndex) ? globalThis.Number(object.originStopIndex) : 0,
|
|
16758
|
+
originRouteId: isSet(object.originRouteId) ? globalThis.Number(object.originRouteId) : 0,
|
|
16759
|
+
originTripIndex: isSet(object.originTripIndex) ? globalThis.Number(object.originTripIndex) : 0,
|
|
16760
|
+
continuations: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.continuations)
|
|
16761
|
+
? object.continuations.map((e) => TripBoarding.fromJSON(e))
|
|
16762
|
+
: [],
|
|
16739
16763
|
};
|
|
16740
16764
|
},
|
|
16741
16765
|
toJSON(message) {
|
|
16742
16766
|
var _a;
|
|
16743
16767
|
const obj = {};
|
|
16744
|
-
if (message.
|
|
16745
|
-
obj.
|
|
16768
|
+
if (message.originStopIndex !== 0) {
|
|
16769
|
+
obj.originStopIndex = Math.round(message.originStopIndex);
|
|
16770
|
+
}
|
|
16771
|
+
if (message.originRouteId !== 0) {
|
|
16772
|
+
obj.originRouteId = Math.round(message.originRouteId);
|
|
16746
16773
|
}
|
|
16747
|
-
if (
|
|
16748
|
-
obj.
|
|
16774
|
+
if (message.originTripIndex !== 0) {
|
|
16775
|
+
obj.originTripIndex = Math.round(message.originTripIndex);
|
|
16776
|
+
}
|
|
16777
|
+
if ((_a = message.continuations) === null || _a === void 0 ? void 0 : _a.length) {
|
|
16778
|
+
obj.continuations = message.continuations.map((e) => TripBoarding.toJSON(e));
|
|
16749
16779
|
}
|
|
16750
16780
|
return obj;
|
|
16751
16781
|
},
|
|
@@ -16753,15 +16783,17 @@ const TripContinuationEntry = {
|
|
|
16753
16783
|
return TripContinuationEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
16754
16784
|
},
|
|
16755
16785
|
fromPartial(object) {
|
|
16756
|
-
var _a, _b;
|
|
16786
|
+
var _a, _b, _c, _d;
|
|
16757
16787
|
const message = createBaseTripContinuationEntry();
|
|
16758
|
-
message.
|
|
16759
|
-
message.
|
|
16788
|
+
message.originStopIndex = (_a = object.originStopIndex) !== null && _a !== void 0 ? _a : 0;
|
|
16789
|
+
message.originRouteId = (_b = object.originRouteId) !== null && _b !== void 0 ? _b : 0;
|
|
16790
|
+
message.originTripIndex = (_c = object.originTripIndex) !== null && _c !== void 0 ? _c : 0;
|
|
16791
|
+
message.continuations = ((_d = object.continuations) === null || _d === void 0 ? void 0 : _d.map((e) => TripBoarding.fromPartial(e))) || [];
|
|
16760
16792
|
return message;
|
|
16761
16793
|
},
|
|
16762
16794
|
};
|
|
16763
16795
|
function createBaseStopAdjacency() {
|
|
16764
|
-
return { routes: [], transfers: []
|
|
16796
|
+
return { routes: [], transfers: [] };
|
|
16765
16797
|
}
|
|
16766
16798
|
const StopAdjacency = {
|
|
16767
16799
|
encode(message, writer = new BinaryWriter()) {
|
|
@@ -16773,9 +16805,6 @@ const StopAdjacency = {
|
|
|
16773
16805
|
for (const v of message.transfers) {
|
|
16774
16806
|
Transfer.encode(v, writer.uint32(18).fork()).join();
|
|
16775
16807
|
}
|
|
16776
|
-
for (const v of message.tripContinuations) {
|
|
16777
|
-
TripContinuationEntry.encode(v, writer.uint32(26).fork()).join();
|
|
16778
|
-
}
|
|
16779
16808
|
return writer;
|
|
16780
16809
|
},
|
|
16781
16810
|
decode(input, length) {
|
|
@@ -16806,13 +16835,6 @@ const StopAdjacency = {
|
|
|
16806
16835
|
message.transfers.push(Transfer.decode(reader, reader.uint32()));
|
|
16807
16836
|
continue;
|
|
16808
16837
|
}
|
|
16809
|
-
case 3: {
|
|
16810
|
-
if (tag !== 26) {
|
|
16811
|
-
break;
|
|
16812
|
-
}
|
|
16813
|
-
message.tripContinuations.push(TripContinuationEntry.decode(reader, reader.uint32()));
|
|
16814
|
-
continue;
|
|
16815
|
-
}
|
|
16816
16838
|
}
|
|
16817
16839
|
if ((tag & 7) === 4 || tag === 0) {
|
|
16818
16840
|
break;
|
|
@@ -16827,13 +16849,10 @@ const StopAdjacency = {
|
|
|
16827
16849
|
transfers: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.transfers)
|
|
16828
16850
|
? object.transfers.map((e) => Transfer.fromJSON(e))
|
|
16829
16851
|
: [],
|
|
16830
|
-
tripContinuations: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.tripContinuations)
|
|
16831
|
-
? object.tripContinuations.map((e) => TripContinuationEntry.fromJSON(e))
|
|
16832
|
-
: [],
|
|
16833
16852
|
};
|
|
16834
16853
|
},
|
|
16835
16854
|
toJSON(message) {
|
|
16836
|
-
var _a, _b
|
|
16855
|
+
var _a, _b;
|
|
16837
16856
|
const obj = {};
|
|
16838
16857
|
if ((_a = message.routes) === null || _a === void 0 ? void 0 : _a.length) {
|
|
16839
16858
|
obj.routes = message.routes.map((e) => Math.round(e));
|
|
@@ -16841,20 +16860,16 @@ const StopAdjacency = {
|
|
|
16841
16860
|
if ((_b = message.transfers) === null || _b === void 0 ? void 0 : _b.length) {
|
|
16842
16861
|
obj.transfers = message.transfers.map((e) => Transfer.toJSON(e));
|
|
16843
16862
|
}
|
|
16844
|
-
if ((_c = message.tripContinuations) === null || _c === void 0 ? void 0 : _c.length) {
|
|
16845
|
-
obj.tripContinuations = message.tripContinuations.map((e) => TripContinuationEntry.toJSON(e));
|
|
16846
|
-
}
|
|
16847
16863
|
return obj;
|
|
16848
16864
|
},
|
|
16849
16865
|
create(base) {
|
|
16850
16866
|
return StopAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
16851
16867
|
},
|
|
16852
16868
|
fromPartial(object) {
|
|
16853
|
-
var _a, _b
|
|
16869
|
+
var _a, _b;
|
|
16854
16870
|
const message = createBaseStopAdjacency();
|
|
16855
16871
|
message.routes = ((_a = object.routes) === null || _a === void 0 ? void 0 : _a.map((e) => e)) || [];
|
|
16856
16872
|
message.transfers = ((_b = object.transfers) === null || _b === void 0 ? void 0 : _b.map((e) => Transfer.fromPartial(e))) || [];
|
|
16857
|
-
message.tripContinuations = ((_c = object.tripContinuations) === null || _c === void 0 ? void 0 : _c.map((e) => TripContinuationEntry.fromPartial(e))) || [];
|
|
16858
16873
|
return message;
|
|
16859
16874
|
},
|
|
16860
16875
|
};
|
|
@@ -16953,7 +16968,7 @@ const ServiceRoute = {
|
|
|
16953
16968
|
},
|
|
16954
16969
|
};
|
|
16955
16970
|
function createBaseTimetable() {
|
|
16956
|
-
return { version: "", stopsAdjacency: [], routesAdjacency: [], serviceRoutes: [] };
|
|
16971
|
+
return { version: "", stopsAdjacency: [], routesAdjacency: [], serviceRoutes: [], tripContinuations: [] };
|
|
16957
16972
|
}
|
|
16958
16973
|
const Timetable$1 = {
|
|
16959
16974
|
encode(message, writer = new BinaryWriter()) {
|
|
@@ -16969,6 +16984,9 @@ const Timetable$1 = {
|
|
|
16969
16984
|
for (const v of message.serviceRoutes) {
|
|
16970
16985
|
ServiceRoute.encode(v, writer.uint32(34).fork()).join();
|
|
16971
16986
|
}
|
|
16987
|
+
for (const v of message.tripContinuations) {
|
|
16988
|
+
TripContinuationEntry.encode(v, writer.uint32(42).fork()).join();
|
|
16989
|
+
}
|
|
16972
16990
|
return writer;
|
|
16973
16991
|
},
|
|
16974
16992
|
decode(input, length) {
|
|
@@ -17006,6 +17024,13 @@ const Timetable$1 = {
|
|
|
17006
17024
|
message.serviceRoutes.push(ServiceRoute.decode(reader, reader.uint32()));
|
|
17007
17025
|
continue;
|
|
17008
17026
|
}
|
|
17027
|
+
case 5: {
|
|
17028
|
+
if (tag !== 42) {
|
|
17029
|
+
break;
|
|
17030
|
+
}
|
|
17031
|
+
message.tripContinuations.push(TripContinuationEntry.decode(reader, reader.uint32()));
|
|
17032
|
+
continue;
|
|
17033
|
+
}
|
|
17009
17034
|
}
|
|
17010
17035
|
if ((tag & 7) === 4 || tag === 0) {
|
|
17011
17036
|
break;
|
|
@@ -17026,10 +17051,13 @@ const Timetable$1 = {
|
|
|
17026
17051
|
serviceRoutes: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.serviceRoutes)
|
|
17027
17052
|
? object.serviceRoutes.map((e) => ServiceRoute.fromJSON(e))
|
|
17028
17053
|
: [],
|
|
17054
|
+
tripContinuations: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.tripContinuations)
|
|
17055
|
+
? object.tripContinuations.map((e) => TripContinuationEntry.fromJSON(e))
|
|
17056
|
+
: [],
|
|
17029
17057
|
};
|
|
17030
17058
|
},
|
|
17031
17059
|
toJSON(message) {
|
|
17032
|
-
var _a, _b, _c;
|
|
17060
|
+
var _a, _b, _c, _d;
|
|
17033
17061
|
const obj = {};
|
|
17034
17062
|
if (message.version !== "") {
|
|
17035
17063
|
obj.version = message.version;
|
|
@@ -17043,18 +17071,22 @@ const Timetable$1 = {
|
|
|
17043
17071
|
if ((_c = message.serviceRoutes) === null || _c === void 0 ? void 0 : _c.length) {
|
|
17044
17072
|
obj.serviceRoutes = message.serviceRoutes.map((e) => ServiceRoute.toJSON(e));
|
|
17045
17073
|
}
|
|
17074
|
+
if ((_d = message.tripContinuations) === null || _d === void 0 ? void 0 : _d.length) {
|
|
17075
|
+
obj.tripContinuations = message.tripContinuations.map((e) => TripContinuationEntry.toJSON(e));
|
|
17076
|
+
}
|
|
17046
17077
|
return obj;
|
|
17047
17078
|
},
|
|
17048
17079
|
create(base) {
|
|
17049
17080
|
return Timetable$1.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
17050
17081
|
},
|
|
17051
17082
|
fromPartial(object) {
|
|
17052
|
-
var _a, _b, _c, _d;
|
|
17083
|
+
var _a, _b, _c, _d, _e;
|
|
17053
17084
|
const message = createBaseTimetable();
|
|
17054
17085
|
message.version = (_a = object.version) !== null && _a !== void 0 ? _a : "";
|
|
17055
17086
|
message.stopsAdjacency = ((_b = object.stopsAdjacency) === null || _b === void 0 ? void 0 : _b.map((e) => StopAdjacency.fromPartial(e))) || [];
|
|
17056
17087
|
message.routesAdjacency = ((_c = object.routesAdjacency) === null || _c === void 0 ? void 0 : _c.map((e) => Route$2.fromPartial(e))) || [];
|
|
17057
17088
|
message.serviceRoutes = ((_d = object.serviceRoutes) === null || _d === void 0 ? void 0 : _d.map((e) => ServiceRoute.fromPartial(e))) || [];
|
|
17089
|
+
message.tripContinuations = ((_e = object.tripContinuations) === null || _e === void 0 ? void 0 : _e.map((e) => TripContinuationEntry.fromPartial(e))) || [];
|
|
17058
17090
|
return message;
|
|
17059
17091
|
},
|
|
17060
17092
|
};
|
|
@@ -17354,7 +17386,14 @@ let Route$1 = class Route {
|
|
|
17354
17386
|
this.stopIndices = new Map();
|
|
17355
17387
|
for (let i = 0; i < stops.length; i++) {
|
|
17356
17388
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
17357
|
-
|
|
17389
|
+
const stopId = stops[i];
|
|
17390
|
+
const existingIndices = this.stopIndices.get(stopId);
|
|
17391
|
+
if (existingIndices) {
|
|
17392
|
+
existingIndices.push(i);
|
|
17393
|
+
}
|
|
17394
|
+
else {
|
|
17395
|
+
this.stopIndices.set(stopId, [i]);
|
|
17396
|
+
}
|
|
17358
17397
|
}
|
|
17359
17398
|
}
|
|
17360
17399
|
/**
|
|
@@ -17442,24 +17481,6 @@ let Route$1 = class Route {
|
|
|
17442
17481
|
serviceRouteId: this.serviceRouteId,
|
|
17443
17482
|
};
|
|
17444
17483
|
}
|
|
17445
|
-
/**
|
|
17446
|
-
* Checks if stop A is before stop B in the route.
|
|
17447
|
-
*
|
|
17448
|
-
* @param stopA - The StopId of the first stop.
|
|
17449
|
-
* @param stopB - The StopId of the second stop.
|
|
17450
|
-
* @returns True if stop A is before stop B, false otherwise.
|
|
17451
|
-
*/
|
|
17452
|
-
isBefore(stopA, stopB) {
|
|
17453
|
-
const stopAIndex = this.stopIndices.get(stopA);
|
|
17454
|
-
if (stopAIndex === undefined) {
|
|
17455
|
-
throw new Error(`Stop index not found for ${stopA} in route ${this.serviceRouteId}`);
|
|
17456
|
-
}
|
|
17457
|
-
const stopBIndex = this.stopIndices.get(stopB);
|
|
17458
|
-
if (stopBIndex === undefined) {
|
|
17459
|
-
throw new Error(`Stop index not found for ${stopB} in route ${this.serviceRouteId}`);
|
|
17460
|
-
}
|
|
17461
|
-
return stopAIndex < stopBIndex;
|
|
17462
|
-
}
|
|
17463
17484
|
/**
|
|
17464
17485
|
* Retrieves the number of stops in the route.
|
|
17465
17486
|
*
|
|
@@ -17488,47 +17509,47 @@ let Route$1 = class Route {
|
|
|
17488
17509
|
/**
|
|
17489
17510
|
* Retrieves the arrival time at a specific stop for a given trip.
|
|
17490
17511
|
*
|
|
17491
|
-
* @param
|
|
17512
|
+
* @param stopIndex - The index of the stop in the route.
|
|
17492
17513
|
* @param tripIndex - The index of the trip.
|
|
17493
17514
|
* @returns The arrival time at the specified stop and trip as a Time object.
|
|
17494
17515
|
*/
|
|
17495
|
-
arrivalAt(
|
|
17496
|
-
const arrivalIndex = (tripIndex * this.stops.length +
|
|
17516
|
+
arrivalAt(stopIndex, tripIndex) {
|
|
17517
|
+
const arrivalIndex = (tripIndex * this.stops.length + stopIndex) * 2;
|
|
17497
17518
|
const arrival = this.stopTimes[arrivalIndex];
|
|
17498
17519
|
if (arrival === undefined) {
|
|
17499
|
-
throw new Error(`Arrival time not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
17520
|
+
throw new Error(`Arrival time not found for stop ${this.stopId(stopIndex)} (${stopIndex}) at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
17500
17521
|
}
|
|
17501
17522
|
return Time.fromMinutes(arrival);
|
|
17502
17523
|
}
|
|
17503
17524
|
/**
|
|
17504
17525
|
* Retrieves the departure time at a specific stop for a given trip.
|
|
17505
17526
|
*
|
|
17506
|
-
* @param
|
|
17527
|
+
* @param stopIndex - The index of the stop in the route.
|
|
17507
17528
|
* @param tripIndex - The index of the trip.
|
|
17508
17529
|
* @returns The departure time at the specified stop and trip as a Time object.
|
|
17509
17530
|
*/
|
|
17510
|
-
departureFrom(
|
|
17511
|
-
const departureIndex = (tripIndex * this.stops.length +
|
|
17531
|
+
departureFrom(stopIndex, tripIndex) {
|
|
17532
|
+
const departureIndex = (tripIndex * this.stops.length + stopIndex) * 2 + 1;
|
|
17512
17533
|
const departure = this.stopTimes[departureIndex];
|
|
17513
17534
|
if (departure === undefined) {
|
|
17514
|
-
throw new Error(`Departure time not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
17535
|
+
throw new Error(`Departure time not found for stop ${this.stopId(stopIndex)} (${stopIndex}) at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
17515
17536
|
}
|
|
17516
17537
|
return Time.fromMinutes(departure);
|
|
17517
17538
|
}
|
|
17518
17539
|
/**
|
|
17519
17540
|
* Retrieves the pick-up type for a specific stop and trip.
|
|
17520
17541
|
*
|
|
17521
|
-
* @param
|
|
17542
|
+
* @param stopIndex - The index of the stop in the route.
|
|
17522
17543
|
* @param tripIndex - The index of the trip.
|
|
17523
17544
|
* @returns The pick-up type at the specified stop and trip.
|
|
17524
17545
|
*/
|
|
17525
|
-
pickUpTypeFrom(
|
|
17526
|
-
const globalIndex = tripIndex * this.stops.length +
|
|
17546
|
+
pickUpTypeFrom(stopIndex, tripIndex) {
|
|
17547
|
+
const globalIndex = tripIndex * this.stops.length + stopIndex;
|
|
17527
17548
|
const byteIndex = Math.floor(globalIndex / 2);
|
|
17528
17549
|
const isSecondPair = globalIndex % 2 === 1;
|
|
17529
17550
|
const byte = this.pickUpDropOffTypes[byteIndex];
|
|
17530
17551
|
if (byte === undefined) {
|
|
17531
|
-
throw new Error(`Pick up type not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
17552
|
+
throw new Error(`Pick up type not found for stop ${this.stopId(stopIndex)} (${stopIndex}) at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
17532
17553
|
}
|
|
17533
17554
|
const pickUpValue = isSecondPair
|
|
17534
17555
|
? (byte >> 6) & 0x03 // Upper 2 bits for second pair
|
|
@@ -17538,17 +17559,17 @@ let Route$1 = class Route {
|
|
|
17538
17559
|
/**
|
|
17539
17560
|
* Retrieves the drop-off type for a specific stop and trip.
|
|
17540
17561
|
*
|
|
17541
|
-
* @param
|
|
17562
|
+
* @param stopIndex - The index of the stop in the route.
|
|
17542
17563
|
* @param tripIndex - The index of the trip.
|
|
17543
17564
|
* @returns The drop-off type at the specified stop and trip.
|
|
17544
17565
|
*/
|
|
17545
|
-
dropOffTypeAt(
|
|
17546
|
-
const globalIndex = tripIndex * this.stops.length +
|
|
17566
|
+
dropOffTypeAt(stopIndex, tripIndex) {
|
|
17567
|
+
const globalIndex = tripIndex * this.stops.length + stopIndex;
|
|
17547
17568
|
const byteIndex = Math.floor(globalIndex / 2);
|
|
17548
17569
|
const isSecondPair = globalIndex % 2 === 1;
|
|
17549
17570
|
const byte = this.pickUpDropOffTypes[byteIndex];
|
|
17550
17571
|
if (byte === undefined) {
|
|
17551
|
-
throw new Error(`Drop off type not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
17572
|
+
throw new Error(`Drop off type not found for stop ${this.stopId(stopIndex)} (${stopIndex}) at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
17552
17573
|
}
|
|
17553
17574
|
const dropOffValue = isSecondPair
|
|
17554
17575
|
? (byte >> 4) & 0x03 // Bits 4-5 for second pair
|
|
@@ -17560,14 +17581,14 @@ let Route$1 = class Route {
|
|
|
17560
17581
|
* optionally constrained by a latest trip index and a time before which the trip
|
|
17561
17582
|
* should not depart.
|
|
17562
17583
|
* *
|
|
17563
|
-
* @param
|
|
17584
|
+
* @param stopIndex - The route index of the stop where the trip should be found.
|
|
17564
17585
|
* @param [after=Time.origin()] - The earliest time after which the trip should depart.
|
|
17565
17586
|
* If not provided, searches all available trips.
|
|
17566
17587
|
* @param [beforeTrip] - (Optional) The index of the trip before which the search should be constrained.
|
|
17567
17588
|
* If not provided, searches all available trips.
|
|
17568
17589
|
* @returns The index of the earliest trip meeting the criteria, or undefined if no such trip is found.
|
|
17569
17590
|
*/
|
|
17570
|
-
findEarliestTrip(
|
|
17591
|
+
findEarliestTrip(stopIndex, after = Time.origin(), beforeTrip) {
|
|
17571
17592
|
if (this.nbTrips <= 0)
|
|
17572
17593
|
return undefined;
|
|
17573
17594
|
let hi = this.nbTrips - 1;
|
|
@@ -17579,7 +17600,7 @@ let Route$1 = class Route {
|
|
|
17579
17600
|
let lb = -1;
|
|
17580
17601
|
while (lo <= hi) {
|
|
17581
17602
|
const mid = (lo + hi) >>> 1;
|
|
17582
|
-
const depMid = this.departureFrom(
|
|
17603
|
+
const depMid = this.departureFrom(stopIndex, mid);
|
|
17583
17604
|
if (depMid.isBefore(after)) {
|
|
17584
17605
|
lo = mid + 1;
|
|
17585
17606
|
}
|
|
@@ -17591,7 +17612,7 @@ let Route$1 = class Route {
|
|
|
17591
17612
|
if (lb === -1)
|
|
17592
17613
|
return undefined;
|
|
17593
17614
|
for (let t = lb; t < (beforeTrip !== null && beforeTrip !== void 0 ? beforeTrip : this.nbTrips); t++) {
|
|
17594
|
-
const pickup = this.pickUpTypeFrom(
|
|
17615
|
+
const pickup = this.pickUpTypeFrom(stopIndex, t);
|
|
17595
17616
|
if (pickup !== 'NOT_AVAILABLE') {
|
|
17596
17617
|
return t;
|
|
17597
17618
|
}
|
|
@@ -17599,14 +17620,14 @@ let Route$1 = class Route {
|
|
|
17599
17620
|
return undefined;
|
|
17600
17621
|
}
|
|
17601
17622
|
/**
|
|
17602
|
-
* Retrieves the
|
|
17623
|
+
* Retrieves the indices of a stop within the route.
|
|
17603
17624
|
* @param stopId The StopId of the stop to locate in the route.
|
|
17604
|
-
* @returns
|
|
17625
|
+
* @returns An array of indices where the stop appears in the route, or an empty array if the stop is not found.
|
|
17605
17626
|
*/
|
|
17606
|
-
|
|
17627
|
+
stopRouteIndices(stopId) {
|
|
17607
17628
|
const stopIndex = this.stopIndices.get(stopId);
|
|
17608
17629
|
if (stopIndex === undefined) {
|
|
17609
|
-
|
|
17630
|
+
return [];
|
|
17610
17631
|
}
|
|
17611
17632
|
return stopIndex;
|
|
17612
17633
|
}
|
|
@@ -17624,6 +17645,51 @@ let Route$1 = class Route {
|
|
|
17624
17645
|
}
|
|
17625
17646
|
};
|
|
17626
17647
|
|
|
17648
|
+
// Each value uses 20 bits, allowing values from 0 to 1,048,575 (2^20 - 1)
|
|
17649
|
+
const VALUE_MASK = (BigInt(1) << BigInt(20)) - BigInt(1); // 0xFFFFF
|
|
17650
|
+
const MAX_VALUE = 1048575; // 2^20 - 1
|
|
17651
|
+
// Bit positions for each value in the 60-bit bigint
|
|
17652
|
+
const TRIP_INDEX_SHIFT = BigInt(0);
|
|
17653
|
+
const ROUTE_ID_SHIFT = BigInt(20);
|
|
17654
|
+
const STOP_INDEX_SHIFT = BigInt(40);
|
|
17655
|
+
/**
|
|
17656
|
+
* Validates that a value fits within 20 bits (0 to 1,048,575)
|
|
17657
|
+
* @param value - The value to validate
|
|
17658
|
+
* @param name - The name of the value for error reporting
|
|
17659
|
+
* @throws Error if the value is out of range
|
|
17660
|
+
*/
|
|
17661
|
+
const validateValue = (value, name) => {
|
|
17662
|
+
if (value < 0 || value > MAX_VALUE) {
|
|
17663
|
+
throw new Error(`${name} must be between 0 and ${MAX_VALUE}, got ${value}`);
|
|
17664
|
+
}
|
|
17665
|
+
};
|
|
17666
|
+
/**
|
|
17667
|
+
* Encodes a stop index, route ID, and trip index into a single trip boarding ID.
|
|
17668
|
+
* @param stopIndex - The index of the stop within the route (0 to 1,048,575)
|
|
17669
|
+
* @param routeId - The route identifier (0 to 1,048,575)
|
|
17670
|
+
* @param tripIndex - The index of the trip within the route (0 to 1,048,575)
|
|
17671
|
+
* @returns The encoded trip ID as a bigint
|
|
17672
|
+
*/
|
|
17673
|
+
const encode = (stopIndex, routeId, tripIndex) => {
|
|
17674
|
+
validateValue(stopIndex, 'stopIndex');
|
|
17675
|
+
validateValue(routeId, 'routeId');
|
|
17676
|
+
validateValue(tripIndex, 'tripIndex');
|
|
17677
|
+
return ((BigInt(stopIndex) << STOP_INDEX_SHIFT) |
|
|
17678
|
+
(BigInt(routeId) << ROUTE_ID_SHIFT) |
|
|
17679
|
+
(BigInt(tripIndex) << TRIP_INDEX_SHIFT));
|
|
17680
|
+
};
|
|
17681
|
+
/**
|
|
17682
|
+
* Decodes a trip boarding ID back into its constituent stop index, route ID, and trip index.
|
|
17683
|
+
* @param tripBoardingId - The encoded trip ID
|
|
17684
|
+
* @returns A tuple containing [stopIndex, routeId, tripIndex]
|
|
17685
|
+
*/
|
|
17686
|
+
const decode = (tripBoardingId) => {
|
|
17687
|
+
const stopIndex = Number((tripBoardingId >> STOP_INDEX_SHIFT) & VALUE_MASK);
|
|
17688
|
+
const routeId = Number((tripBoardingId >> ROUTE_ID_SHIFT) & VALUE_MASK);
|
|
17689
|
+
const tripIndex = Number((tripBoardingId >> TRIP_INDEX_SHIFT) & VALUE_MASK);
|
|
17690
|
+
return [stopIndex, routeId, tripIndex];
|
|
17691
|
+
};
|
|
17692
|
+
|
|
17627
17693
|
const isLittleEndian = (() => {
|
|
17628
17694
|
const buffer = new ArrayBuffer(4);
|
|
17629
17695
|
const view = new DataView(buffer);
|
|
@@ -17698,9 +17764,6 @@ const serializeStopsAdjacency = (stopsAdjacency) => {
|
|
|
17698
17764
|
}))))
|
|
17699
17765
|
: [],
|
|
17700
17766
|
routes: value.routes,
|
|
17701
|
-
tripContinuations: value.tripContinuations
|
|
17702
|
-
? serializeTripContinuations(value.tripContinuations)
|
|
17703
|
-
: [],
|
|
17704
17767
|
};
|
|
17705
17768
|
});
|
|
17706
17769
|
};
|
|
@@ -17746,10 +17809,6 @@ const deserializeStopsAdjacency = (protoStopsAdjacency) => {
|
|
|
17746
17809
|
if (transfers.length > 0) {
|
|
17747
17810
|
stopAdjacency.transfers = transfers;
|
|
17748
17811
|
}
|
|
17749
|
-
const deserializedTripContinuations = deserializeTripContinuations(value.tripContinuations);
|
|
17750
|
-
if (deserializedTripContinuations.size > 0) {
|
|
17751
|
-
stopAdjacency.tripContinuations = deserializedTripContinuations;
|
|
17752
|
-
}
|
|
17753
17812
|
result.push(stopAdjacency);
|
|
17754
17813
|
}
|
|
17755
17814
|
return result;
|
|
@@ -17856,11 +17915,14 @@ const serializeRouteType = (type) => {
|
|
|
17856
17915
|
};
|
|
17857
17916
|
const serializeTripContinuations = (tripContinuations) => {
|
|
17858
17917
|
const result = [];
|
|
17859
|
-
for (const [
|
|
17918
|
+
for (const [tripBoardingId, boardings] of tripContinuations.entries()) {
|
|
17919
|
+
const [originStopIndex, originRouteId, originTripIndex] = decode(tripBoardingId);
|
|
17860
17920
|
result.push({
|
|
17861
|
-
|
|
17862
|
-
|
|
17863
|
-
|
|
17921
|
+
originStopIndex,
|
|
17922
|
+
originRouteId,
|
|
17923
|
+
originTripIndex,
|
|
17924
|
+
continuations: boardings.map((tripBoarding) => ({
|
|
17925
|
+
hopOnStopIndex: tripBoarding.hopOnStopIndex,
|
|
17864
17926
|
routeId: tripBoarding.routeId,
|
|
17865
17927
|
tripIndex: tripBoarding.tripIndex,
|
|
17866
17928
|
})),
|
|
@@ -17873,28 +17935,17 @@ const deserializeTripContinuations = (protoTripContinuations) => {
|
|
|
17873
17935
|
for (let i = 0; i < protoTripContinuations.length; i++) {
|
|
17874
17936
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
17875
17937
|
const entry = protoTripContinuations[i];
|
|
17876
|
-
const
|
|
17877
|
-
|
|
17938
|
+
const tripBoardingId = encode(entry.originStopIndex, entry.originRouteId, entry.originTripIndex);
|
|
17939
|
+
const tripBoardings = entry.continuations.map((protoTripBoarding) => ({
|
|
17940
|
+
hopOnStopIndex: protoTripBoarding.hopOnStopIndex,
|
|
17878
17941
|
routeId: protoTripBoarding.routeId,
|
|
17879
17942
|
tripIndex: protoTripBoarding.tripIndex,
|
|
17880
17943
|
}));
|
|
17881
|
-
result.set(
|
|
17944
|
+
result.set(tripBoardingId, tripBoardings);
|
|
17882
17945
|
}
|
|
17883
17946
|
return result;
|
|
17884
17947
|
};
|
|
17885
17948
|
|
|
17886
|
-
// const ROUTE_ID_BITS = 17;
|
|
17887
|
-
const TRIP_INDEX_BITS = 15;
|
|
17888
|
-
/**
|
|
17889
|
-
* Encodes a route ID and trip index into a single trip ID.
|
|
17890
|
-
* @param routeId - The route identifier, needs to fit on 17 bits
|
|
17891
|
-
* @param tripIndex - The index of the trip within the route, needs to fit on 15 bits
|
|
17892
|
-
* @returns The encoded trip ID
|
|
17893
|
-
*/
|
|
17894
|
-
const encode = (routeId, tripIndex) => {
|
|
17895
|
-
return (routeId << TRIP_INDEX_BITS) | tripIndex;
|
|
17896
|
-
};
|
|
17897
|
-
|
|
17898
17949
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
17899
17950
|
const ALL_TRANSPORT_MODES = new Set([
|
|
17900
17951
|
'TRAM',
|
|
@@ -17909,21 +17960,21 @@ const ALL_TRANSPORT_MODES = new Set([
|
|
|
17909
17960
|
'MONORAIL',
|
|
17910
17961
|
]);
|
|
17911
17962
|
const EMPTY_TRIP_CONTINUATIONS = [];
|
|
17912
|
-
const CURRENT_VERSION = '0.0.
|
|
17963
|
+
const CURRENT_VERSION = '0.0.9';
|
|
17913
17964
|
/**
|
|
17914
17965
|
* The internal transit timetable format.
|
|
17915
17966
|
*/
|
|
17916
17967
|
class Timetable {
|
|
17917
|
-
constructor(stopsAdjacency, routesAdjacency, routes) {
|
|
17968
|
+
constructor(stopsAdjacency, routesAdjacency, routes, tripContinuations) {
|
|
17918
17969
|
this.stopsAdjacency = stopsAdjacency;
|
|
17919
17970
|
this.routesAdjacency = routesAdjacency;
|
|
17920
17971
|
this.serviceRoutes = routes;
|
|
17972
|
+
this.tripContinuations = tripContinuations;
|
|
17921
17973
|
this.activeStops = new Set();
|
|
17922
17974
|
for (let i = 0; i < stopsAdjacency.length; i++) {
|
|
17923
17975
|
const stop = stopsAdjacency[i];
|
|
17924
17976
|
if (stop.routes.length > 0 ||
|
|
17925
|
-
(stop.transfers && stop.transfers.length > 0)
|
|
17926
|
-
(stop.tripContinuations && stop.tripContinuations.size > 0)) {
|
|
17977
|
+
(stop.transfers && stop.transfers.length > 0)) {
|
|
17927
17978
|
this.activeStops.add(i);
|
|
17928
17979
|
}
|
|
17929
17980
|
}
|
|
@@ -17939,6 +17990,7 @@ class Timetable {
|
|
|
17939
17990
|
stopsAdjacency: serializeStopsAdjacency(this.stopsAdjacency),
|
|
17940
17991
|
routesAdjacency: serializeRoutesAdjacency(this.routesAdjacency),
|
|
17941
17992
|
serviceRoutes: serializeServiceRoutesMap(this.serviceRoutes),
|
|
17993
|
+
tripContinuations: serializeTripContinuations(this.tripContinuations || new Map()),
|
|
17942
17994
|
};
|
|
17943
17995
|
const writer = new BinaryWriter();
|
|
17944
17996
|
Timetable$1.encode(protoTimetable, writer);
|
|
@@ -17956,7 +18008,7 @@ class Timetable {
|
|
|
17956
18008
|
if (protoTimetable.version !== CURRENT_VERSION) {
|
|
17957
18009
|
throw new Error(`Unsupported timetable version ${protoTimetable.version}`);
|
|
17958
18010
|
}
|
|
17959
|
-
return new Timetable(deserializeStopsAdjacency(protoTimetable.stopsAdjacency), deserializeRoutesAdjacency(protoTimetable.routesAdjacency), deserializeServiceRoutesMap(protoTimetable.serviceRoutes));
|
|
18011
|
+
return new Timetable(deserializeStopsAdjacency(protoTimetable.stopsAdjacency), deserializeRoutesAdjacency(protoTimetable.routesAdjacency), deserializeServiceRoutesMap(protoTimetable.serviceRoutes), deserializeTripContinuations(protoTimetable.tripContinuations));
|
|
17960
18012
|
}
|
|
17961
18013
|
/**
|
|
17962
18014
|
* Checks if the given stop is active on the timetable.
|
|
@@ -17995,18 +18047,18 @@ class Timetable {
|
|
|
17995
18047
|
/**
|
|
17996
18048
|
* Retrieves all trip continuation options available at the specified stop for a given trip.
|
|
17997
18049
|
*
|
|
17998
|
-
* @param
|
|
18050
|
+
* @param stopIndex - The index in the route of the stop to get trip continuations for.
|
|
18051
|
+
* @param routeId - The ID of the route to get continuations for.
|
|
17999
18052
|
* @param tripIndex - The index of the trip to get continuations for.
|
|
18000
18053
|
* @returns An array of trip continuation options available at the stop for the specified trip.
|
|
18001
18054
|
*/
|
|
18002
|
-
getContinuousTrips(
|
|
18055
|
+
getContinuousTrips(stopIndex, routeId, tripIndex) {
|
|
18003
18056
|
var _a;
|
|
18004
|
-
const
|
|
18005
|
-
if (!
|
|
18006
|
-
|
|
18057
|
+
const tripContinuations = (_a = this.tripContinuations) === null || _a === void 0 ? void 0 : _a.get(encode(stopIndex, routeId, tripIndex));
|
|
18058
|
+
if (!tripContinuations) {
|
|
18059
|
+
return EMPTY_TRIP_CONTINUATIONS;
|
|
18007
18060
|
}
|
|
18008
|
-
return
|
|
18009
|
-
EMPTY_TRIP_CONTINUATIONS);
|
|
18061
|
+
return tripContinuations;
|
|
18010
18062
|
}
|
|
18011
18063
|
/**
|
|
18012
18064
|
* Retrieves the service route associated with the given route.
|
|
@@ -18046,12 +18098,12 @@ class Timetable {
|
|
|
18046
18098
|
}
|
|
18047
18099
|
/**
|
|
18048
18100
|
* Finds routes that are reachable from a set of stop IDs.
|
|
18049
|
-
* Also identifies the first stop available to hop on each route among
|
|
18101
|
+
* Also identifies the first stop index available to hop on each route among
|
|
18050
18102
|
* the input stops.
|
|
18051
18103
|
*
|
|
18052
18104
|
* @param fromStops - The set of stop IDs to find reachable routes from.
|
|
18053
18105
|
* @param transportModes - The set of transport modes to consider for reachable routes.
|
|
18054
|
-
* @returns A map of reachable routes to the first stop available to hop on each route.
|
|
18106
|
+
* @returns A map of reachable routes to the first stop index available to hop on each route.
|
|
18055
18107
|
*/
|
|
18056
18108
|
findReachableRoutes(fromStops, transportModes = ALL_TRANSPORT_MODES) {
|
|
18057
18109
|
const reachableRoutes = new Map();
|
|
@@ -18064,15 +18116,17 @@ class Timetable {
|
|
|
18064
18116
|
});
|
|
18065
18117
|
for (let j = 0; j < validRoutes.length; j++) {
|
|
18066
18118
|
const route = validRoutes[j];
|
|
18067
|
-
const
|
|
18068
|
-
|
|
18069
|
-
|
|
18119
|
+
const originStopIndices = route.stopRouteIndices(originStop);
|
|
18120
|
+
const originStopIndex = originStopIndices[0];
|
|
18121
|
+
const existingHopOnStopIndex = reachableRoutes.get(route);
|
|
18122
|
+
if (existingHopOnStopIndex !== undefined) {
|
|
18123
|
+
if (originStopIndex < existingHopOnStopIndex) {
|
|
18070
18124
|
// if the current stop is before the existing hop on stop, replace it
|
|
18071
|
-
reachableRoutes.set(route,
|
|
18125
|
+
reachableRoutes.set(route, originStopIndex);
|
|
18072
18126
|
}
|
|
18073
18127
|
}
|
|
18074
18128
|
else {
|
|
18075
|
-
reachableRoutes.set(route,
|
|
18129
|
+
reachableRoutes.set(route, originStopIndex);
|
|
18076
18130
|
}
|
|
18077
18131
|
}
|
|
18078
18132
|
}
|
|
@@ -20292,7 +20346,7 @@ const parseGtfsLocationType = (gtfsLocationType) => {
|
|
|
20292
20346
|
const parseTransfers = (transfersStream, stopsMap) => __awaiter(void 0, void 0, void 0, function* () {
|
|
20293
20347
|
var _a, e_1, _b, _c;
|
|
20294
20348
|
const transfers = new Map();
|
|
20295
|
-
const tripContinuations =
|
|
20349
|
+
const tripContinuations = [];
|
|
20296
20350
|
try {
|
|
20297
20351
|
for (var _d = true, _e = __asyncValues(parseCsv(transfersStream, [
|
|
20298
20352
|
'transfer_type',
|
|
@@ -20310,10 +20364,12 @@ const parseTransfers = (transfersStream, stopsMap) => __awaiter(void 0, void 0,
|
|
|
20310
20364
|
console.warn(`Missing transfer origin or destination stop.`);
|
|
20311
20365
|
continue;
|
|
20312
20366
|
}
|
|
20313
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
20314
20367
|
const fromStop = stopsMap.get(transferEntry.from_stop_id);
|
|
20315
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
20316
20368
|
const toStop = stopsMap.get(transferEntry.to_stop_id);
|
|
20369
|
+
if (!fromStop || !toStop) {
|
|
20370
|
+
console.warn(`Transfer references non-existent stop(s): from_stop_id=${transferEntry.from_stop_id}, to_stop_id=${transferEntry.to_stop_id}`);
|
|
20371
|
+
continue;
|
|
20372
|
+
}
|
|
20317
20373
|
if (transferEntry.transfer_type === 4) {
|
|
20318
20374
|
if (transferEntry.from_trip_id === undefined ||
|
|
20319
20375
|
transferEntry.from_trip_id === '' ||
|
|
@@ -20323,17 +20379,12 @@ const parseTransfers = (transfersStream, stopsMap) => __awaiter(void 0, void 0,
|
|
|
20323
20379
|
continue;
|
|
20324
20380
|
}
|
|
20325
20381
|
const tripBoardingEntry = {
|
|
20382
|
+
fromStop: fromStop.id,
|
|
20326
20383
|
fromTrip: transferEntry.from_trip_id,
|
|
20384
|
+
toStop: toStop.id,
|
|
20327
20385
|
toTrip: transferEntry.to_trip_id,
|
|
20328
|
-
hopOnStop: toStop.id,
|
|
20329
20386
|
};
|
|
20330
|
-
|
|
20331
|
-
if (existingBoardings) {
|
|
20332
|
-
existingBoardings.push(tripBoardingEntry);
|
|
20333
|
-
}
|
|
20334
|
-
else {
|
|
20335
|
-
tripContinuations.set(fromStop.id, [tripBoardingEntry]);
|
|
20336
|
-
}
|
|
20387
|
+
tripContinuations.push(tripBoardingEntry);
|
|
20337
20388
|
continue;
|
|
20338
20389
|
}
|
|
20339
20390
|
if (transferEntry.from_trip_id && transferEntry.to_trip_id) {
|
|
@@ -20348,7 +20399,7 @@ const parseTransfers = (transfersStream, stopsMap) => __awaiter(void 0, void 0,
|
|
|
20348
20399
|
transferEntry.min_transfer_time === undefined) {
|
|
20349
20400
|
console.info(`Missing minimum transfer time between ${transferEntry.from_stop_id} and ${transferEntry.to_stop_id}.`);
|
|
20350
20401
|
}
|
|
20351
|
-
const transfer = Object.assign({ destination: toStop.id, type: parseGtfsTransferType(transferEntry.transfer_type) }, (transferEntry.min_transfer_time && {
|
|
20402
|
+
const transfer = Object.assign({ destination: toStop.id, type: parseGtfsTransferType(transferEntry.transfer_type) }, (transferEntry.min_transfer_time !== undefined && {
|
|
20352
20403
|
minTransferTime: Duration.fromSeconds(transferEntry.min_transfer_time),
|
|
20353
20404
|
}));
|
|
20354
20405
|
const fromStopTransfers = transfers.get(fromStop.id) || [];
|
|
@@ -20368,6 +20419,91 @@ const parseTransfers = (transfersStream, stopsMap) => __awaiter(void 0, void 0,
|
|
|
20368
20419
|
tripContinuations,
|
|
20369
20420
|
};
|
|
20370
20421
|
});
|
|
20422
|
+
/**
|
|
20423
|
+
* Disambiguates stops involved in a transfer.
|
|
20424
|
+
*
|
|
20425
|
+
* The GTFS specification only refers to a stopId in the trip-to-trip transfers and not the
|
|
20426
|
+
* specific stop index in the route. For routes that have multiple stops with the same stopId,
|
|
20427
|
+
* we need to determine which are the from / to stop indices in respective routes.
|
|
20428
|
+
* We do so by picking the stop indices leading to the most coherent transfer.
|
|
20429
|
+
* (we pick the closest from stop index happening after the to stop index).
|
|
20430
|
+
*/
|
|
20431
|
+
const disambiguateTransferStopsIndices = (fromStop, fromRoute, fromTripIndex, toStop, toRoute, toTripIndex) => {
|
|
20432
|
+
const fromStopIndices = fromRoute.stopRouteIndices(fromStop);
|
|
20433
|
+
const toStopIndices = toRoute.stopRouteIndices(toStop);
|
|
20434
|
+
let bestFromStopIndex;
|
|
20435
|
+
let bestToStopIndex;
|
|
20436
|
+
let bestTimeDifference = Infinity;
|
|
20437
|
+
for (const originStopIndex of fromStopIndices) {
|
|
20438
|
+
const fromArrivalTime = fromRoute.arrivalAt(originStopIndex, fromTripIndex);
|
|
20439
|
+
for (const toStopIndex of toStopIndices) {
|
|
20440
|
+
const toDepartureTime = toRoute.departureFrom(toStopIndex, toTripIndex);
|
|
20441
|
+
if (toDepartureTime.isAfter(fromArrivalTime)) {
|
|
20442
|
+
const timeDifference = toDepartureTime.toMinutes() - fromArrivalTime.toMinutes();
|
|
20443
|
+
if (timeDifference < bestTimeDifference) {
|
|
20444
|
+
bestTimeDifference = timeDifference;
|
|
20445
|
+
bestFromStopIndex = originStopIndex;
|
|
20446
|
+
bestToStopIndex = toStopIndex;
|
|
20447
|
+
}
|
|
20448
|
+
}
|
|
20449
|
+
}
|
|
20450
|
+
}
|
|
20451
|
+
if (bestFromStopIndex !== undefined && bestToStopIndex !== undefined) {
|
|
20452
|
+
return {
|
|
20453
|
+
fromStopIndex: bestFromStopIndex,
|
|
20454
|
+
toStopIndex: bestToStopIndex,
|
|
20455
|
+
};
|
|
20456
|
+
}
|
|
20457
|
+
return undefined;
|
|
20458
|
+
};
|
|
20459
|
+
/**
|
|
20460
|
+
* Builds trip continuations map from GTFS trip continuation data.
|
|
20461
|
+
*
|
|
20462
|
+
* This function processes GTFS in-seat transfer data and creates a mapping
|
|
20463
|
+
* from trip boarding IDs to continuation boarding information. It disambiguates
|
|
20464
|
+
* stop indices when routes have multiple stops with the same ID by finding
|
|
20465
|
+
* the most coherent transfer timing.
|
|
20466
|
+
*
|
|
20467
|
+
* @param tripsMapping Mapping from GTFS trip IDs to internal trip representations
|
|
20468
|
+
* @param tripContinuations Array of GTFS trip continuation data from transfers.txt
|
|
20469
|
+
* @param timetable The timetable containing route and timing information
|
|
20470
|
+
* @param activeStopIds Set of stop IDs that are active/enabled in the system
|
|
20471
|
+
* @returns A map from trip boarding IDs to arrays of continuation boarding options
|
|
20472
|
+
*/
|
|
20473
|
+
const buildTripContinuations = (tripsMapping, tripContinuations, timetable, activeStopIds) => {
|
|
20474
|
+
const continuations = new Map();
|
|
20475
|
+
for (const gtfsContinuation of tripContinuations) {
|
|
20476
|
+
if (!activeStopIds.has(gtfsContinuation.fromStop) ||
|
|
20477
|
+
!activeStopIds.has(gtfsContinuation.toStop)) {
|
|
20478
|
+
continue;
|
|
20479
|
+
}
|
|
20480
|
+
const fromTripMapping = tripsMapping.get(gtfsContinuation.fromTrip);
|
|
20481
|
+
const toTripMapping = tripsMapping.get(gtfsContinuation.toTrip);
|
|
20482
|
+
if (!fromTripMapping || !toTripMapping) {
|
|
20483
|
+
continue;
|
|
20484
|
+
}
|
|
20485
|
+
const fromRoute = timetable.getRoute(fromTripMapping.routeId);
|
|
20486
|
+
const toRoute = timetable.getRoute(toTripMapping.routeId);
|
|
20487
|
+
if (!fromRoute || !toRoute) {
|
|
20488
|
+
continue;
|
|
20489
|
+
}
|
|
20490
|
+
const bestStopIndices = disambiguateTransferStopsIndices(gtfsContinuation.fromStop, fromRoute, fromTripMapping.tripRouteIndex, gtfsContinuation.toStop, toRoute, toTripMapping.tripRouteIndex);
|
|
20491
|
+
if (!bestStopIndices) {
|
|
20492
|
+
// No valid continuation found
|
|
20493
|
+
continue;
|
|
20494
|
+
}
|
|
20495
|
+
const tripBoardingId = encode(bestStopIndices.fromStopIndex, fromTripMapping.routeId, fromTripMapping.tripRouteIndex);
|
|
20496
|
+
const continuationBoarding = {
|
|
20497
|
+
hopOnStopIndex: bestStopIndices.toStopIndex,
|
|
20498
|
+
routeId: toTripMapping.routeId,
|
|
20499
|
+
tripIndex: toTripMapping.tripRouteIndex,
|
|
20500
|
+
};
|
|
20501
|
+
const existingContinuations = continuations.get(tripBoardingId) || [];
|
|
20502
|
+
existingContinuations.push(continuationBoarding);
|
|
20503
|
+
continuations.set(tripBoardingId, existingContinuations);
|
|
20504
|
+
}
|
|
20505
|
+
return continuations;
|
|
20506
|
+
};
|
|
20371
20507
|
const parseGtfsTransferType = (gtfsTransferType) => {
|
|
20372
20508
|
switch (gtfsTransferType) {
|
|
20373
20509
|
case 0:
|
|
@@ -20504,7 +20640,7 @@ const parseTrips = (tripsStream, serviceIds, validGtfsRoutes) => __awaiter(void
|
|
|
20504
20640
|
}
|
|
20505
20641
|
return trips;
|
|
20506
20642
|
});
|
|
20507
|
-
const buildStopsAdjacencyStructure = (
|
|
20643
|
+
const buildStopsAdjacencyStructure = (serviceRoutes, routes, transfersMap, nbStops, activeStops) => {
|
|
20508
20644
|
const stopsAdjacency = new Array(nbStops);
|
|
20509
20645
|
for (let i = 0; i < nbStops; i++) {
|
|
20510
20646
|
stopsAdjacency[i] = {
|
|
@@ -20544,40 +20680,6 @@ const buildStopsAdjacencyStructure = (tripsMapping, serviceRoutes, routes, trans
|
|
|
20544
20680
|
}
|
|
20545
20681
|
}
|
|
20546
20682
|
}
|
|
20547
|
-
for (const [stop, tripContinuations] of tripContinuationsMap) {
|
|
20548
|
-
for (let i = 0; i < tripContinuations.length; i++) {
|
|
20549
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
20550
|
-
const tripContinuation = tripContinuations[i];
|
|
20551
|
-
if (activeStops.has(stop) ||
|
|
20552
|
-
activeStops.has(tripContinuation.hopOnStop)) {
|
|
20553
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
20554
|
-
const stopAdj = stopsAdjacency[stop];
|
|
20555
|
-
if (!stopAdj.tripContinuations) {
|
|
20556
|
-
stopAdj.tripContinuations = new Map();
|
|
20557
|
-
}
|
|
20558
|
-
const originTrip = tripsMapping.get(tripContinuation.fromTrip);
|
|
20559
|
-
const destinationTrip = tripsMapping.get(tripContinuation.toTrip);
|
|
20560
|
-
if (destinationTrip === undefined || originTrip === undefined) {
|
|
20561
|
-
continue;
|
|
20562
|
-
}
|
|
20563
|
-
const tripBoarding = {
|
|
20564
|
-
hopOnStop: tripContinuation.hopOnStop,
|
|
20565
|
-
routeId: destinationTrip.routeId,
|
|
20566
|
-
tripIndex: destinationTrip.tripRouteIndex,
|
|
20567
|
-
};
|
|
20568
|
-
const tripId = encode(originTrip.routeId, originTrip.tripRouteIndex);
|
|
20569
|
-
const existingContinuations = stopAdj.tripContinuations.get(tripId);
|
|
20570
|
-
if (existingContinuations) {
|
|
20571
|
-
existingContinuations.push(tripBoarding);
|
|
20572
|
-
}
|
|
20573
|
-
else {
|
|
20574
|
-
stopAdj.tripContinuations.set(tripId, [tripBoarding]);
|
|
20575
|
-
}
|
|
20576
|
-
activeStops.add(tripContinuation.hopOnStop);
|
|
20577
|
-
activeStops.add(stop);
|
|
20578
|
-
}
|
|
20579
|
-
}
|
|
20580
|
-
}
|
|
20581
20683
|
return stopsAdjacency;
|
|
20582
20684
|
};
|
|
20583
20685
|
/**
|
|
@@ -20804,16 +20906,16 @@ class GtfsParser {
|
|
|
20804
20906
|
const tripsEnd = performance.now();
|
|
20805
20907
|
log.info(`${trips.size} valid trips. (${(tripsEnd - tripsStart).toFixed(2)}ms)`);
|
|
20806
20908
|
let transfers = new Map();
|
|
20807
|
-
let
|
|
20909
|
+
let tripContinuationsMap = [];
|
|
20808
20910
|
if (entries[TRANSFERS_FILE]) {
|
|
20809
20911
|
log.info(`Parsing ${TRANSFERS_FILE}`);
|
|
20810
20912
|
const transfersStart = performance.now();
|
|
20811
20913
|
const transfersStream = yield zip.stream(TRANSFERS_FILE);
|
|
20812
20914
|
const { transfers: parsedTransfers, tripContinuations: parsedTripContinuations, } = yield parseTransfers(transfersStream, parsedStops);
|
|
20813
20915
|
transfers = parsedTransfers;
|
|
20814
|
-
|
|
20916
|
+
tripContinuationsMap = parsedTripContinuations;
|
|
20815
20917
|
const transfersEnd = performance.now();
|
|
20816
|
-
log.info(`${transfers.size} valid transfers and ${
|
|
20918
|
+
log.info(`${transfers.size} valid transfers and ${tripContinuationsMap.length} trip continuations. (${(transfersEnd - transfersStart).toFixed(2)}ms)`);
|
|
20817
20919
|
}
|
|
20818
20920
|
log.info(`Parsing ${STOP_TIMES_FILE}`);
|
|
20819
20921
|
const stopTimesStart = performance.now();
|
|
@@ -20824,13 +20926,19 @@ class GtfsParser {
|
|
|
20824
20926
|
log.info(`${routes.length} valid unique routes. (${(stopTimesEnd - stopTimesStart).toFixed(2)}ms)`);
|
|
20825
20927
|
log.info('Building stops adjacency structure');
|
|
20826
20928
|
const stopsAdjacencyStart = performance.now();
|
|
20827
|
-
const stopsAdjacency = buildStopsAdjacencyStructure(
|
|
20929
|
+
const stopsAdjacency = buildStopsAdjacencyStructure(serviceRoutes, routes, transfers, parsedStops.size, activeStopIds);
|
|
20828
20930
|
const stopsAdjacencyEnd = performance.now();
|
|
20829
20931
|
log.info(`${stopsAdjacency.length} valid stops in the structure. (${(stopsAdjacencyEnd - stopsAdjacencyStart).toFixed(2)}ms)`);
|
|
20830
20932
|
yield zip.close();
|
|
20933
|
+
// temporary timetable for building continuations
|
|
20831
20934
|
const timetable = new Timetable(stopsAdjacency, routes, serviceRoutes);
|
|
20935
|
+
log.info('Building in-seat trip continuations');
|
|
20936
|
+
const tripContinuationsStart = performance.now();
|
|
20937
|
+
const tripContinuations = buildTripContinuations(tripsMapping, tripContinuationsMap, timetable, activeStopIds);
|
|
20938
|
+
const tripContinuationsEnd = performance.now();
|
|
20939
|
+
log.info(`${tripContinuations.size} in-seat trip continuations origins created. (${(tripContinuationsEnd - tripContinuationsStart).toFixed(2)}ms)`);
|
|
20832
20940
|
log.info('Parsing complete.');
|
|
20833
|
-
return
|
|
20941
|
+
return new Timetable(stopsAdjacency, routes, serviceRoutes, tripContinuations);
|
|
20834
20942
|
});
|
|
20835
20943
|
}
|
|
20836
20944
|
/**
|
|
@@ -21430,9 +21538,9 @@ class Result {
|
|
|
21430
21538
|
const lastRoute = this.timetable.getRoute(lastEdge.routeId);
|
|
21431
21539
|
return {
|
|
21432
21540
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
21433
|
-
from: this.stopsIndex.findStopById(firstEdge.from),
|
|
21541
|
+
from: this.stopsIndex.findStopById(firstRoute.stopId(firstEdge.from)),
|
|
21434
21542
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
21435
|
-
to: this.stopsIndex.findStopById(lastEdge.to),
|
|
21543
|
+
to: this.stopsIndex.findStopById(lastRoute.stopId(lastEdge.to)),
|
|
21436
21544
|
// The route info comes from the first boarded route in case on continuous trips
|
|
21437
21545
|
route: this.timetable.getServiceRouteInfo(firstRoute),
|
|
21438
21546
|
departureTime: firstRoute.departureFrom(firstEdge.from, firstEdge.tripIndex),
|
|
@@ -21533,8 +21641,8 @@ class Router {
|
|
|
21533
21641
|
const reachableRoutes = this.timetable.findReachableRoutes(markedStops, query.options.transportModes);
|
|
21534
21642
|
markedStops.clear();
|
|
21535
21643
|
// for each route that can be reached with at least round - 1 trips
|
|
21536
|
-
for (const [route,
|
|
21537
|
-
const newlyMarkedStops = this.scanRoute(route,
|
|
21644
|
+
for (const [route, hopOnStopIndex] of reachableRoutes) {
|
|
21645
|
+
const newlyMarkedStops = this.scanRoute(route, hopOnStopIndex, round, routingState);
|
|
21538
21646
|
for (const newStop of newlyMarkedStops) {
|
|
21539
21647
|
markedStops.add(newStop);
|
|
21540
21648
|
}
|
|
@@ -21545,7 +21653,7 @@ class Router {
|
|
|
21545
21653
|
const stopsFromContinuations = new Set();
|
|
21546
21654
|
for (const continuation of continuations) {
|
|
21547
21655
|
const route = this.timetable.getRoute(continuation.routeId);
|
|
21548
|
-
const routeScanResults = this.scanRoute(route, continuation.
|
|
21656
|
+
const routeScanResults = this.scanRoute(route, continuation.hopOnStopIndex, round, routingState, continuation);
|
|
21549
21657
|
for (const newStop of routeScanResults) {
|
|
21550
21658
|
stopsFromContinuations.add(newStop);
|
|
21551
21659
|
}
|
|
@@ -21576,12 +21684,12 @@ class Router {
|
|
|
21576
21684
|
const arrival = edgesAtCurrentRound.get(stopId);
|
|
21577
21685
|
if (!arrival || !('routeId' in arrival))
|
|
21578
21686
|
continue;
|
|
21579
|
-
const continuousTrips = this.timetable.getContinuousTrips(
|
|
21687
|
+
const continuousTrips = this.timetable.getContinuousTrips(arrival.to, arrival.routeId, arrival.tripIndex);
|
|
21580
21688
|
for (let i = 0; i < continuousTrips.length; i++) {
|
|
21581
21689
|
const trip = continuousTrips[i];
|
|
21582
21690
|
continuations.push({
|
|
21583
21691
|
routeId: trip.routeId,
|
|
21584
|
-
|
|
21692
|
+
hopOnStopIndex: trip.hopOnStopIndex,
|
|
21585
21693
|
tripIndex: trip.tripIndex,
|
|
21586
21694
|
previousEdge: arrival,
|
|
21587
21695
|
});
|
|
@@ -21636,32 +21744,31 @@ class Router {
|
|
|
21636
21744
|
* are available if no given trip is provided as a parameter.
|
|
21637
21745
|
*
|
|
21638
21746
|
* @param route The route to scan for possible trips
|
|
21639
|
-
* @param
|
|
21747
|
+
* @param hopOnStopIndex The stop index where passengers can board the route
|
|
21640
21748
|
* @param round The current round number in the RAPTOR algorithm
|
|
21641
21749
|
* @param routingState The current routing state containing arrival times and marked stops
|
|
21642
21750
|
*/
|
|
21643
|
-
scanRoute(route,
|
|
21751
|
+
scanRoute(route, hopOnStopIndex, round, routingState, tripContinuation) {
|
|
21644
21752
|
var _a, _b, _c;
|
|
21645
21753
|
const newlyMarkedStops = new Set();
|
|
21646
21754
|
let activeTrip = tripContinuation
|
|
21647
21755
|
? {
|
|
21648
21756
|
routeId: route.id,
|
|
21649
|
-
|
|
21757
|
+
hopOnStopIndex,
|
|
21650
21758
|
tripIndex: tripContinuation.tripIndex,
|
|
21651
21759
|
}
|
|
21652
21760
|
: undefined;
|
|
21653
21761
|
const edgesAtCurrentRound = routingState.graph[round];
|
|
21654
21762
|
const edgesAtPreviousRound = routingState.graph[round - 1];
|
|
21655
|
-
const startIndex = route.stopRouteIndex(hopOnStop);
|
|
21656
21763
|
// Compute target pruning criteria only once per route
|
|
21657
21764
|
const earliestArrivalAtAnyDestination = this.earliestArrivalAtAnyStop(routingState.earliestArrivals, routingState.destinations);
|
|
21658
|
-
for (let
|
|
21659
|
-
const currentStop = route.stops[
|
|
21765
|
+
for (let currentStopIndex = hopOnStopIndex; currentStopIndex < route.getNbStops(); currentStopIndex++) {
|
|
21766
|
+
const currentStop = route.stops[currentStopIndex];
|
|
21660
21767
|
// If we're currently on a trip,
|
|
21661
21768
|
// check if arrival at the stop improves the earliest arrival time
|
|
21662
21769
|
if (activeTrip !== undefined) {
|
|
21663
|
-
const arrivalTime = route.arrivalAt(
|
|
21664
|
-
const dropOffType = route.dropOffTypeAt(
|
|
21770
|
+
const arrivalTime = route.arrivalAt(currentStopIndex, activeTrip.tripIndex);
|
|
21771
|
+
const dropOffType = route.dropOffTypeAt(currentStopIndex, activeTrip.tripIndex);
|
|
21665
21772
|
const earliestArrivalAtCurrentStop = (_b = (_a = routingState.earliestArrivals.get(currentStop)) === null || _a === void 0 ? void 0 : _a.arrival) !== null && _b !== void 0 ? _b : UNREACHED;
|
|
21666
21773
|
if (dropOffType !== 'NOT_AVAILABLE' &&
|
|
21667
21774
|
arrivalTime.isBefore(earliestArrivalAtCurrentStop) &&
|
|
@@ -21670,8 +21777,8 @@ class Router {
|
|
|
21670
21777
|
arrival: arrivalTime,
|
|
21671
21778
|
routeId: route.id,
|
|
21672
21779
|
tripIndex: activeTrip.tripIndex,
|
|
21673
|
-
from: activeTrip.
|
|
21674
|
-
to:
|
|
21780
|
+
from: activeTrip.hopOnStopIndex,
|
|
21781
|
+
to: currentStopIndex,
|
|
21675
21782
|
};
|
|
21676
21783
|
if (tripContinuation) {
|
|
21677
21784
|
// In case of continuous trip, we set a pointer to the previous edge
|
|
@@ -21698,14 +21805,14 @@ class Router {
|
|
|
21698
21805
|
// (or later at route reconstruction time)
|
|
21699
21806
|
if (earliestArrivalOnPreviousRound !== undefined &&
|
|
21700
21807
|
(activeTrip === undefined ||
|
|
21701
|
-
earliestArrivalOnPreviousRound.isBefore(route.departureFrom(
|
|
21702
|
-
earliestArrivalOnPreviousRound.equals(route.departureFrom(
|
|
21703
|
-
const earliestTrip = route.findEarliestTrip(
|
|
21808
|
+
earliestArrivalOnPreviousRound.isBefore(route.departureFrom(currentStopIndex, activeTrip.tripIndex)) ||
|
|
21809
|
+
earliestArrivalOnPreviousRound.equals(route.departureFrom(currentStopIndex, activeTrip.tripIndex)))) {
|
|
21810
|
+
const earliestTrip = route.findEarliestTrip(currentStopIndex, earliestArrivalOnPreviousRound, activeTrip === null || activeTrip === void 0 ? void 0 : activeTrip.tripIndex);
|
|
21704
21811
|
if (earliestTrip !== undefined) {
|
|
21705
21812
|
activeTrip = {
|
|
21706
21813
|
routeId: route.id,
|
|
21707
21814
|
tripIndex: earliestTrip,
|
|
21708
|
-
|
|
21815
|
+
hopOnStopIndex: currentStopIndex,
|
|
21709
21816
|
};
|
|
21710
21817
|
}
|
|
21711
21818
|
}
|
|
@@ -21980,7 +22087,6 @@ const startRepl = (stopsPath, timetablePath) => {
|
|
|
21980
22087
|
if (bestRoute) {
|
|
21981
22088
|
console.log(`Found route from ${fromStop.name} to ${toStop.name}:`);
|
|
21982
22089
|
console.log(bestRoute.toString());
|
|
21983
|
-
console.log(bestRoute.asJson());
|
|
21984
22090
|
}
|
|
21985
22091
|
else {
|
|
21986
22092
|
console.log('No route found');
|
|
@@ -22087,7 +22193,6 @@ const startRepl = (stopsPath, timetablePath) => {
|
|
|
22087
22193
|
return;
|
|
22088
22194
|
}
|
|
22089
22195
|
const inspectRoute = (routeIdStr) => {
|
|
22090
|
-
var _a, _b, _c;
|
|
22091
22196
|
const routeId = parseInt(routeIdStr.trim());
|
|
22092
22197
|
if (isNaN(routeId)) {
|
|
22093
22198
|
console.log('Usage: .inspect route <routeId>');
|
|
@@ -22109,29 +22214,30 @@ const startRepl = (stopsPath, timetablePath) => {
|
|
|
22109
22214
|
console.log('\n--- Stops ---');
|
|
22110
22215
|
for (let i = 0; i < route.stops.length; i++) {
|
|
22111
22216
|
const stopId = route.stopId(i);
|
|
22217
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
22112
22218
|
const stop = stopsIndex.findStopById(stopId);
|
|
22113
|
-
const platform =
|
|
22114
|
-
console.log(`${i + 1}. ${
|
|
22219
|
+
const platform = stop.platform ? ` (Pl. ${stop.platform})` : '';
|
|
22220
|
+
console.log(`${i + 1}. ${stop.name}${platform} (${stopId}, ${stop.sourceStopId})`);
|
|
22115
22221
|
}
|
|
22116
22222
|
console.log('\n--- Trips ---');
|
|
22117
22223
|
for (let tripIndex = 0; tripIndex < route.getNbTrips(); tripIndex++) {
|
|
22118
22224
|
console.log(`\nTrip ${tripIndex}:`);
|
|
22119
22225
|
for (let stopIndex = 0; stopIndex < route.stops.length; stopIndex++) {
|
|
22120
22226
|
const stopId = route.stopId(stopIndex);
|
|
22227
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
22121
22228
|
const stop = stopsIndex.findStopById(stopId);
|
|
22122
|
-
const departure = route.departureFrom(
|
|
22123
|
-
const arrival = route.arrivalAt(
|
|
22124
|
-
const pickupType = route.pickUpTypeFrom(
|
|
22125
|
-
const dropOffType = route.dropOffTypeAt(
|
|
22229
|
+
const departure = route.departureFrom(stopIndex, tripIndex);
|
|
22230
|
+
const arrival = route.arrivalAt(stopIndex, tripIndex);
|
|
22231
|
+
const pickupType = route.pickUpTypeFrom(stopIndex, tripIndex);
|
|
22232
|
+
const dropOffType = route.dropOffTypeAt(stopIndex, tripIndex);
|
|
22126
22233
|
const pickupStr = formatPickupDropoffType(pickupType);
|
|
22127
22234
|
const dropOffStr = formatPickupDropoffType(dropOffType);
|
|
22128
|
-
console.log(` ${stopIndex + 1}. ${
|
|
22235
|
+
console.log(` ${stopIndex + 1}. ${stop.name}: arr ${arrival.toString()} (${pickupStr}) → dep ${departure.toString()} (${dropOffStr})`);
|
|
22129
22236
|
}
|
|
22130
22237
|
}
|
|
22131
22238
|
console.log();
|
|
22132
22239
|
};
|
|
22133
22240
|
const inspectStop = (stopIdStr) => {
|
|
22134
|
-
var _a, _b, _c;
|
|
22135
22241
|
let stop;
|
|
22136
22242
|
const stopBySourceId = stopsIndex.findStopBySourceStopId(stopIdStr);
|
|
22137
22243
|
if (stopBySourceId !== undefined) {
|
|
@@ -22199,48 +22305,38 @@ const startRepl = (stopsPath, timetablePath) => {
|
|
|
22199
22305
|
});
|
|
22200
22306
|
}
|
|
22201
22307
|
let totalContinuations = 0;
|
|
22202
|
-
|
|
22308
|
+
console.log('\n--- Trip Continuations ---');
|
|
22203
22309
|
routes.forEach((route) => {
|
|
22310
|
+
const serviceRouteInfo = timetable.getServiceRouteInfo(route);
|
|
22311
|
+
const stopIndices = route.stopRouteIndices(stop.id);
|
|
22204
22312
|
for (let tripIndex = 0; tripIndex < route.getNbTrips(); tripIndex++) {
|
|
22205
|
-
const
|
|
22206
|
-
|
|
22207
|
-
|
|
22208
|
-
|
|
22209
|
-
|
|
22210
|
-
|
|
22211
|
-
|
|
22212
|
-
|
|
22213
|
-
|
|
22313
|
+
for (const stopIndex of stopIndices) {
|
|
22314
|
+
const continuations = timetable.getContinuousTrips(stopIndex, route.id, tripIndex);
|
|
22315
|
+
for (const continuation of continuations) {
|
|
22316
|
+
totalContinuations++;
|
|
22317
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
22318
|
+
const destRoute = timetable.getRoute(continuation.routeId);
|
|
22319
|
+
const destStopId = destRoute.stopId(continuation.hopOnStopIndex);
|
|
22320
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
22321
|
+
const destStop = stopsIndex.findStopById(destStopId);
|
|
22322
|
+
const destPlatform = destStop.platform
|
|
22323
|
+
? ` (Pl. ${destStop.platform})`
|
|
22324
|
+
: '';
|
|
22325
|
+
const destServiceRouteInfo = timetable.getServiceRouteInfo(destRoute);
|
|
22326
|
+
const originTime = route.departureFrom(stopIndex, tripIndex);
|
|
22327
|
+
const continuationTime = destRoute.departureFrom(continuation.hopOnStopIndex, continuation.tripIndex);
|
|
22328
|
+
console.log(`${totalContinuations}. From Route ${route.id} (${serviceRouteInfo.name}) Trip ${tripIndex} at ${originTime.toString()} → ` +
|
|
22329
|
+
`Route ${continuation.routeId} (${destServiceRouteInfo.name}) Trip ${continuation.tripIndex} at ${continuationTime.toString()} ` +
|
|
22330
|
+
`at ${destStop.name}${destPlatform} (${destStopId}, ${destStop.sourceStopId})`);
|
|
22331
|
+
}
|
|
22214
22332
|
}
|
|
22215
22333
|
}
|
|
22216
22334
|
});
|
|
22217
|
-
|
|
22218
|
-
|
|
22219
|
-
|
|
22220
|
-
|
|
22221
|
-
|
|
22222
|
-
const { route, tripIndex, continuations } = value;
|
|
22223
|
-
const serviceRouteInfo = timetable.getServiceRouteInfo(route);
|
|
22224
|
-
for (const continuation of continuations) {
|
|
22225
|
-
const destStop = stopsIndex.findStopById(continuation.hopOnStop);
|
|
22226
|
-
const destPlatform = (destStop === null || destStop === void 0 ? void 0 : destStop.platform)
|
|
22227
|
-
? ` (Pl. ${destStop.platform})`
|
|
22228
|
-
: '';
|
|
22229
|
-
const destRoute = timetable.getRoute(continuation.routeId);
|
|
22230
|
-
const destServiceRouteInfo = destRoute
|
|
22231
|
-
? timetable.getServiceRouteInfo(destRoute)
|
|
22232
|
-
: null;
|
|
22233
|
-
const originTime = route.departureFrom(stop.id, tripIndex);
|
|
22234
|
-
const continuationTime = destRoute === null || destRoute === void 0 ? void 0 : destRoute.departureFrom(continuation.hopOnStop, continuation.tripIndex);
|
|
22235
|
-
const continuationTimeStr = continuationTime
|
|
22236
|
-
? ` at ${continuationTime.toString()}`
|
|
22237
|
-
: '';
|
|
22238
|
-
console.log(`${continuationIndex}. From Route ${route.id} (${serviceRouteInfo.name}) Trip ${tripIndex} at ${originTime.toString()} → ` +
|
|
22239
|
-
`Route ${continuation.routeId} (${(_a = destServiceRouteInfo === null || destServiceRouteInfo === void 0 ? void 0 : destServiceRouteInfo.name) !== null && _a !== void 0 ? _a : 'Unknown'}) Trip ${continuation.tripIndex}${continuationTimeStr} ` +
|
|
22240
|
-
`at ${(_b = destStop === null || destStop === void 0 ? void 0 : destStop.name) !== null && _b !== void 0 ? _b : 'Unknown'}${destPlatform} (${continuation.hopOnStop}, ${(_c = destStop === null || destStop === void 0 ? void 0 : destStop.sourceStopId) !== null && _c !== void 0 ? _c : 'N/A'})`);
|
|
22241
|
-
continuationIndex++;
|
|
22242
|
-
}
|
|
22243
|
-
}
|
|
22335
|
+
if (totalContinuations === 0) {
|
|
22336
|
+
console.log('No trip continuations found.');
|
|
22337
|
+
}
|
|
22338
|
+
else {
|
|
22339
|
+
console.log(`\nTotal trip continuations: ${totalContinuations}`);
|
|
22244
22340
|
}
|
|
22245
22341
|
console.log();
|
|
22246
22342
|
};
|