minotor 3.0.1 → 3.0.2
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 +12 -1
- package/.gitattributes +3 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +3 -0
- package/.github/workflows/minotor.yml +17 -1
- package/CHANGELOG.md +2 -2
- package/README.md +34 -14
- package/dist/__e2e__/router.test.d.ts +1 -0
- package/dist/cli/perf.d.ts +28 -0
- package/dist/cli/utils.d.ts +6 -2
- package/dist/cli.mjs +1967 -823
- package/dist/cli.mjs.map +1 -1
- package/dist/gtfs/trips.d.ts +1 -0
- package/dist/gtfs/utils.d.ts +1 -1
- package/dist/parser.cjs.js +1030 -627
- package/dist/parser.cjs.js.map +1 -1
- package/dist/parser.d.ts +4 -2
- package/dist/parser.esm.js +1030 -627
- 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 +10 -5
- 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/__tests__/result.test.d.ts +1 -0
- package/dist/routing/query.d.ts +27 -6
- package/dist/routing/result.d.ts +1 -1
- package/dist/routing/route.d.ts +47 -2
- package/dist/routing/router.d.ts +15 -1
- package/dist/stops/stopsIndex.d.ts +3 -3
- package/dist/timetable/__tests__/route.test.d.ts +1 -0
- package/dist/timetable/__tests__/time.test.d.ts +1 -0
- package/dist/timetable/io.d.ts +7 -1
- package/dist/timetable/proto/timetable.d.ts +1 -1
- package/dist/timetable/route.d.ts +155 -0
- package/dist/timetable/time.d.ts +21 -0
- package/dist/timetable/timetable.d.ts +41 -61
- package/package.json +36 -34
- package/src/__e2e__/benchmark.json +22 -0
- package/src/__e2e__/router.test.ts +209 -0
- package/src/__e2e__/timetable/stops.bin +3 -0
- package/src/__e2e__/timetable/timetable.bin +3 -0
- package/src/cli/minotor.ts +51 -1
- package/src/cli/perf.ts +136 -0
- package/src/cli/repl.ts +26 -13
- package/src/cli/utils.ts +6 -28
- package/src/gtfs/__tests__/parser.test.ts +12 -15
- package/src/gtfs/__tests__/services.test.ts +1 -0
- package/src/gtfs/__tests__/transfers.test.ts +0 -1
- package/src/gtfs/__tests__/trips.test.ts +67 -74
- package/src/gtfs/profiles/ch.ts +1 -1
- package/src/gtfs/routes.ts +4 -4
- package/src/gtfs/services.ts +15 -2
- package/src/gtfs/stops.ts +7 -3
- package/src/gtfs/transfers.ts +6 -3
- package/src/gtfs/trips.ts +33 -16
- package/src/gtfs/utils.ts +13 -2
- package/src/parser.ts +4 -2
- package/src/router.ts +17 -11
- package/src/routing/__tests__/result.test.ts +392 -0
- package/src/routing/__tests__/router.test.ts +94 -137
- package/src/routing/query.ts +28 -7
- package/src/routing/result.ts +10 -5
- package/src/routing/route.ts +95 -9
- package/src/routing/router.ts +82 -66
- package/src/stops/__tests__/io.test.ts +1 -1
- package/src/stops/__tests__/stopFinder.test.ts +1 -1
- package/src/stops/proto/stops.ts +4 -4
- package/src/stops/stopsIndex.ts +3 -3
- package/src/timetable/__tests__/io.test.ts +16 -23
- package/src/timetable/__tests__/route.test.ts +317 -0
- package/src/timetable/__tests__/time.test.ts +494 -0
- package/src/timetable/__tests__/timetable.test.ts +64 -75
- package/src/timetable/io.ts +32 -26
- package/src/timetable/proto/timetable.proto +1 -1
- package/src/timetable/proto/timetable.ts +13 -13
- package/src/timetable/route.ts +347 -0
- package/src/timetable/time.ts +40 -8
- package/src/timetable/timetable.ts +74 -165
- package/tsconfig.build.json +1 -1
package/src/routing/router.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
-
import { StopId } from '../stops/stops.js';
|
|
2
|
+
import { Stop, StopId } from '../stops/stops.js';
|
|
3
3
|
import { StopsIndex } from '../stops/stopsIndex.js';
|
|
4
4
|
import { Duration } from '../timetable/duration.js';
|
|
5
|
+
import { TripIndex } from '../timetable/route.js';
|
|
5
6
|
import { Time } from '../timetable/time.js';
|
|
6
|
-
import {
|
|
7
|
+
import { Timetable } from '../timetable/timetable.js';
|
|
7
8
|
import { Query } from './query.js';
|
|
8
9
|
import { Result } from './result.js';
|
|
9
10
|
import { Leg } from './route.js';
|
|
@@ -15,17 +16,23 @@ export type TripLeg = ReachingTime & {
|
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
export type ReachingTime = {
|
|
18
|
-
|
|
19
|
+
arrival: Time;
|
|
19
20
|
legNumber: number;
|
|
20
21
|
origin: StopId;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
type CurrentTrip = {
|
|
24
|
-
|
|
25
|
+
tripIndex: TripIndex;
|
|
25
26
|
origin: StopId;
|
|
26
27
|
bestHopOnStop: StopId;
|
|
27
28
|
};
|
|
28
29
|
|
|
30
|
+
/**
|
|
31
|
+
* A public transportation network router utilizing the RAPTOR algorithm for
|
|
32
|
+
* efficient journey planning and routing. For more information on the RAPTOR
|
|
33
|
+
* algorithm, refer to its detailed explanation in the research paper:
|
|
34
|
+
* https://www.microsoft.com/en-us/research/wp-content/uploads/2012/01/raptor_alenex.pdf
|
|
35
|
+
*/
|
|
29
36
|
export class Router {
|
|
30
37
|
private readonly timetable: Timetable;
|
|
31
38
|
private readonly stopsIndex: StopsIndex;
|
|
@@ -50,6 +57,14 @@ export class Router {
|
|
|
50
57
|
const { options } = query;
|
|
51
58
|
const newlyMarkedStops: Set<StopId> = new Set();
|
|
52
59
|
for (const stop of markedStops) {
|
|
60
|
+
const currentArrival = arrivalsAtCurrentRound.get(stop);
|
|
61
|
+
if (!currentArrival) continue;
|
|
62
|
+
// Skip transfers if the last leg was also a transfer
|
|
63
|
+
const previousLeg = currentArrival.leg;
|
|
64
|
+
if (previousLeg && !('route' in previousLeg)) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
53
68
|
for (const transfer of this.timetable.getTransfers(stop)) {
|
|
54
69
|
let transferTime: Duration;
|
|
55
70
|
if (transfer.minTransferTime) {
|
|
@@ -59,15 +74,14 @@ export class Router {
|
|
|
59
74
|
} else {
|
|
60
75
|
transferTime = options.minTransferTime;
|
|
61
76
|
}
|
|
62
|
-
const arrivalAfterTransfer =
|
|
63
|
-
.get(stop)!
|
|
64
|
-
.time.plus(transferTime);
|
|
77
|
+
const arrivalAfterTransfer = currentArrival.arrival.plus(transferTime);
|
|
65
78
|
const originalArrival =
|
|
66
|
-
arrivalsAtCurrentRound.get(transfer.destination)?.
|
|
67
|
-
|
|
68
|
-
|
|
79
|
+
arrivalsAtCurrentRound.get(transfer.destination)?.arrival ??
|
|
80
|
+
UNREACHED;
|
|
81
|
+
if (arrivalAfterTransfer.isBefore(originalArrival)) {
|
|
82
|
+
const origin = currentArrival.origin;
|
|
69
83
|
arrivalsAtCurrentRound.set(transfer.destination, {
|
|
70
|
-
|
|
84
|
+
arrival: arrivalAfterTransfer,
|
|
71
85
|
legNumber: round,
|
|
72
86
|
origin: origin,
|
|
73
87
|
leg: {
|
|
@@ -78,7 +92,7 @@ export class Router {
|
|
|
78
92
|
},
|
|
79
93
|
});
|
|
80
94
|
earliestArrivals.set(transfer.destination, {
|
|
81
|
-
|
|
95
|
+
arrival: arrivalAfterTransfer,
|
|
82
96
|
legNumber: round,
|
|
83
97
|
origin: origin,
|
|
84
98
|
});
|
|
@@ -91,6 +105,29 @@ export class Router {
|
|
|
91
105
|
}
|
|
92
106
|
}
|
|
93
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Finds the earliest arrival time at any stop from a given set of destinations.
|
|
110
|
+
*
|
|
111
|
+
* @param earliestArrivals A map of stops to their earliest reaching times.
|
|
112
|
+
* @param destinations An array of destination stops to evaluate.
|
|
113
|
+
* @returns The earliest arrival time among the provided destinations.
|
|
114
|
+
*/
|
|
115
|
+
private earliestArrivalAtAnyStop(
|
|
116
|
+
earliestArrivals: Map<StopId, ReachingTime>,
|
|
117
|
+
destinations: Stop[],
|
|
118
|
+
): Time {
|
|
119
|
+
let earliestArrivalAtAnyDestination = UNREACHED;
|
|
120
|
+
for (const destination of destinations) {
|
|
121
|
+
const arrival =
|
|
122
|
+
earliestArrivals.get(destination.id)?.arrival ?? UNREACHED;
|
|
123
|
+
earliestArrivalAtAnyDestination = Time.min(
|
|
124
|
+
earliestArrivalAtAnyDestination,
|
|
125
|
+
arrival,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return earliestArrivalAtAnyDestination;
|
|
129
|
+
}
|
|
130
|
+
|
|
94
131
|
/**
|
|
95
132
|
* The main Raptor algorithm implementation.
|
|
96
133
|
*
|
|
@@ -102,7 +139,7 @@ export class Router {
|
|
|
102
139
|
// Consider children or siblings of the "from" stop as potential origins
|
|
103
140
|
const origins = this.stopsIndex.equivalentStops(from);
|
|
104
141
|
// Consider children or siblings of the "to" stop(s) as potential destinations
|
|
105
|
-
const destinations = to.flatMap((destination) =>
|
|
142
|
+
const destinations = Array.from(to).flatMap((destination) =>
|
|
106
143
|
this.stopsIndex.equivalentStops(destination),
|
|
107
144
|
);
|
|
108
145
|
const earliestArrivals = new Map<StopId, ReachingTime>();
|
|
@@ -115,12 +152,12 @@ export class Router {
|
|
|
115
152
|
for (const originStop of origins) {
|
|
116
153
|
markedStops.add(originStop.id);
|
|
117
154
|
earliestArrivals.set(originStop.id, {
|
|
118
|
-
|
|
155
|
+
arrival: departureTime,
|
|
119
156
|
legNumber: 0,
|
|
120
157
|
origin: originStop.id,
|
|
121
158
|
});
|
|
122
159
|
earliestArrivalsWithoutAnyLeg.set(originStop.id, {
|
|
123
|
-
|
|
160
|
+
arrival: departureTime,
|
|
124
161
|
legNumber: 0,
|
|
125
162
|
origin: originStop.id,
|
|
126
163
|
});
|
|
@@ -146,57 +183,33 @@ export class Router {
|
|
|
146
183
|
);
|
|
147
184
|
markedStops.clear();
|
|
148
185
|
// for each route that can be reached with at least round - 1 trips
|
|
149
|
-
for (const [
|
|
150
|
-
const route = this.timetable.getRoute(routeId)!;
|
|
186
|
+
for (const [route, hopOnStop] of reachableRoutes.entries()) {
|
|
151
187
|
let currentTrip: CurrentTrip | undefined = undefined;
|
|
152
|
-
const
|
|
153
|
-
// for each stop in the route starting with the hop-on one
|
|
154
|
-
for (let i = hopOnIndex; i < route.stops.length; i++) {
|
|
155
|
-
const currentStop = route.stops[i]!;
|
|
156
|
-
const stopNumbers = route.stops.length;
|
|
188
|
+
for (const currentStop of route.stopsIterator(hopOnStop)) {
|
|
157
189
|
if (currentTrip !== undefined) {
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
190
|
+
const currentArrivalTime = route.arrivalAt(
|
|
191
|
+
currentStop,
|
|
192
|
+
currentTrip.tripIndex,
|
|
193
|
+
);
|
|
194
|
+
const currentDropOffType = route.dropOffTypeAt(
|
|
195
|
+
currentStop,
|
|
196
|
+
currentTrip.tripIndex,
|
|
162
197
|
);
|
|
163
|
-
const currentDropOffType = route.pickUpDropOffTypes[i * 2 + 1];
|
|
164
198
|
const earliestArrivalAtCurrentStop =
|
|
165
|
-
earliestArrivals.get(currentStop)?.
|
|
166
|
-
let arrivalToImprove = earliestArrivalAtCurrentStop;
|
|
167
|
-
if (destinations.length > 0) {
|
|
168
|
-
const earliestArrivalsAtDestinations: Time[] = [];
|
|
169
|
-
// if multiple destinations are specified, the target pruning
|
|
170
|
-
// should compare to the earliest arrival at any of them
|
|
171
|
-
for (const destinationStop of destinations) {
|
|
172
|
-
const earliestArrivalAtDestination =
|
|
173
|
-
earliestArrivals.get(destinationStop.id)?.time ?? UNREACHED;
|
|
174
|
-
earliestArrivalsAtDestinations.push(
|
|
175
|
-
earliestArrivalAtDestination,
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
const earliestArrivalAtDestination = Time.min(
|
|
179
|
-
...earliestArrivalsAtDestinations,
|
|
180
|
-
);
|
|
181
|
-
arrivalToImprove = Time.min(
|
|
182
|
-
earliestArrivalAtCurrentStop,
|
|
183
|
-
earliestArrivalAtDestination,
|
|
184
|
-
);
|
|
185
|
-
}
|
|
199
|
+
earliestArrivals.get(currentStop)?.arrival ?? UNREACHED;
|
|
186
200
|
if (
|
|
187
|
-
currentDropOffType !== NOT_AVAILABLE &&
|
|
188
|
-
currentArrivalTime.
|
|
201
|
+
currentDropOffType !== 'NOT_AVAILABLE' &&
|
|
202
|
+
currentArrivalTime.isBefore(earliestArrivalAtCurrentStop) &&
|
|
203
|
+
currentArrivalTime.isBefore(
|
|
204
|
+
this.earliestArrivalAtAnyStop(earliestArrivals, destinations),
|
|
205
|
+
)
|
|
189
206
|
) {
|
|
190
|
-
const
|
|
207
|
+
const bestHopOnDepartureTime = route.departureFrom(
|
|
191
208
|
currentTrip.bestHopOnStop,
|
|
192
|
-
|
|
193
|
-
const bestHopOnStopDepartureIndex =
|
|
194
|
-
currentTrip.trip * stopNumbers * 2 + bestHopOnStopIndex * 2 + 1;
|
|
195
|
-
const bestHopOnDepartureTime = Time.fromMinutes(
|
|
196
|
-
route.stopTimes[bestHopOnStopDepartureIndex]!,
|
|
209
|
+
currentTrip.tripIndex,
|
|
197
210
|
);
|
|
198
211
|
arrivalsAtCurrentRound.set(currentStop, {
|
|
199
|
-
|
|
212
|
+
arrival: currentArrivalTime,
|
|
200
213
|
legNumber: round,
|
|
201
214
|
origin: currentTrip.origin,
|
|
202
215
|
leg: {
|
|
@@ -206,11 +219,11 @@ export class Router {
|
|
|
206
219
|
to: this.stopsIndex.findStopById(currentStop)!,
|
|
207
220
|
departureTime: bestHopOnDepartureTime,
|
|
208
221
|
arrivalTime: currentArrivalTime,
|
|
209
|
-
route: this.timetable.getServiceRoute(route
|
|
222
|
+
route: this.timetable.getServiceRoute(route),
|
|
210
223
|
},
|
|
211
224
|
});
|
|
212
225
|
earliestArrivals.set(currentStop, {
|
|
213
|
-
|
|
226
|
+
arrival: currentArrivalTime,
|
|
214
227
|
legNumber: round,
|
|
215
228
|
origin: currentTrip.origin,
|
|
216
229
|
});
|
|
@@ -220,22 +233,25 @@ export class Router {
|
|
|
220
233
|
// check if we can catch a previous trip at the current stop
|
|
221
234
|
// if there was no current trip, find the first one reachable
|
|
222
235
|
const earliestArrivalOnPreviousRound =
|
|
223
|
-
arrivalsAtPreviousRound.get(currentStop)?.
|
|
236
|
+
arrivalsAtPreviousRound.get(currentStop)?.arrival;
|
|
224
237
|
if (
|
|
225
238
|
earliestArrivalOnPreviousRound !== undefined &&
|
|
226
239
|
(currentTrip === undefined ||
|
|
227
|
-
earliestArrivalOnPreviousRound.
|
|
228
|
-
route.
|
|
240
|
+
earliestArrivalOnPreviousRound.isBefore(
|
|
241
|
+
route.arrivalAt(currentStop, currentTrip.tripIndex),
|
|
242
|
+
) ||
|
|
243
|
+
earliestArrivalOnPreviousRound.equals(
|
|
244
|
+
route.arrivalAt(currentStop, currentTrip.tripIndex),
|
|
245
|
+
))
|
|
229
246
|
) {
|
|
230
|
-
const earliestTrip =
|
|
231
|
-
route,
|
|
247
|
+
const earliestTrip = route.findEarliestTrip(
|
|
232
248
|
currentStop,
|
|
233
|
-
currentTrip?.trip,
|
|
234
249
|
earliestArrivalOnPreviousRound,
|
|
250
|
+
currentTrip?.tripIndex,
|
|
235
251
|
);
|
|
236
252
|
if (earliestTrip !== undefined) {
|
|
237
253
|
currentTrip = {
|
|
238
|
-
|
|
254
|
+
tripIndex: earliestTrip,
|
|
239
255
|
// we need to keep track of the best hop-on stop to reconstruct the route at the end
|
|
240
256
|
bestHopOnStop: currentStop,
|
|
241
257
|
origin:
|
package/src/stops/proto/stops.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
2
2
|
// versions:
|
|
3
|
-
// protoc-gen-ts_proto v2.
|
|
3
|
+
// protoc-gen-ts_proto v2.7.7
|
|
4
4
|
// protoc v4.23.4
|
|
5
5
|
// source: src/stops/proto/stops.proto
|
|
6
6
|
|
|
@@ -127,7 +127,7 @@ export const Stop: MessageFns<Stop> = {
|
|
|
127
127
|
|
|
128
128
|
decode(input: BinaryReader | Uint8Array, length?: number): Stop {
|
|
129
129
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
130
|
-
|
|
130
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
131
131
|
const message = createBaseStop();
|
|
132
132
|
while (reader.pos < end) {
|
|
133
133
|
const tag = reader.uint32();
|
|
@@ -291,7 +291,7 @@ export const StopsMap: MessageFns<StopsMap> = {
|
|
|
291
291
|
|
|
292
292
|
decode(input: BinaryReader | Uint8Array, length?: number): StopsMap {
|
|
293
293
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
294
|
-
|
|
294
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
295
295
|
const message = createBaseStopsMap();
|
|
296
296
|
while (reader.pos < end) {
|
|
297
297
|
const tag = reader.uint32();
|
|
@@ -386,7 +386,7 @@ export const StopsMap_StopsEntry: MessageFns<StopsMap_StopsEntry> = {
|
|
|
386
386
|
|
|
387
387
|
decode(input: BinaryReader | Uint8Array, length?: number): StopsMap_StopsEntry {
|
|
388
388
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
389
|
-
|
|
389
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
390
390
|
const message = createBaseStopsMap_StopsEntry();
|
|
391
391
|
while (reader.pos < end) {
|
|
392
392
|
const tag = reader.uint32();
|
package/src/stops/stopsIndex.ts
CHANGED
|
@@ -74,8 +74,8 @@ export class StopsIndex {
|
|
|
74
74
|
/**
|
|
75
75
|
* Deserializes a binary representation of the stops.
|
|
76
76
|
*
|
|
77
|
-
* @param
|
|
78
|
-
* @returns
|
|
77
|
+
* @param data - The binary data to deserialize.
|
|
78
|
+
* @returns The deserialized StopFinder.
|
|
79
79
|
*/
|
|
80
80
|
static fromData(data: Uint8Array): StopsIndex {
|
|
81
81
|
const reader = new BinaryReader(data);
|
|
@@ -87,7 +87,7 @@ export class StopsIndex {
|
|
|
87
87
|
/**
|
|
88
88
|
* Serializes the stops into a binary protobuf.
|
|
89
89
|
*
|
|
90
|
-
* @returns
|
|
90
|
+
* @returns The serialized binary data.
|
|
91
91
|
*/
|
|
92
92
|
serialize(): Uint8Array {
|
|
93
93
|
const protoStopsMap: ProtoStopsMap = serializeStopsMap(this.stopsMap);
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
serializeServiceRoutesMap,
|
|
11
11
|
serializeStopsAdjacency,
|
|
12
12
|
} from '../io.js';
|
|
13
|
+
import { REGULAR, Route } from '../route.js';
|
|
13
14
|
import { Time } from '../time.js';
|
|
14
15
|
import {
|
|
15
16
|
RoutesAdjacency,
|
|
@@ -17,7 +18,7 @@ import {
|
|
|
17
18
|
StopsAdjacency,
|
|
18
19
|
} from '../timetable.js';
|
|
19
20
|
|
|
20
|
-
describe('
|
|
21
|
+
describe('Timetable IO', () => {
|
|
21
22
|
const stopsAdjacency: StopsAdjacency = new Map([
|
|
22
23
|
[
|
|
23
24
|
1,
|
|
@@ -43,35 +44,27 @@ describe('timetable io', () => {
|
|
|
43
44
|
const routesAdjacency: RoutesAdjacency = new Map([
|
|
44
45
|
[
|
|
45
46
|
'route1',
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
new Route(
|
|
48
|
+
new Uint16Array([
|
|
48
49
|
Time.fromHMS(16, 40, 0).toMinutes(),
|
|
49
50
|
Time.fromHMS(16, 50, 0).toMinutes(),
|
|
50
51
|
]),
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
[2, 1],
|
|
56
|
-
]),
|
|
57
|
-
serviceRouteId: 'gtfs1',
|
|
58
|
-
},
|
|
52
|
+
new Uint8Array([REGULAR, REGULAR]),
|
|
53
|
+
new Uint32Array([1, 2]),
|
|
54
|
+
'gtfs1',
|
|
55
|
+
),
|
|
59
56
|
],
|
|
60
57
|
[
|
|
61
58
|
'route2',
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
new Route(
|
|
60
|
+
new Uint16Array([
|
|
64
61
|
Time.fromHMS(15, 20, 0).toMinutes(),
|
|
65
62
|
Time.fromHMS(15, 30, 0).toMinutes(),
|
|
66
63
|
]),
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
[1, 1],
|
|
72
|
-
]),
|
|
73
|
-
serviceRouteId: 'gtfs2',
|
|
74
|
-
},
|
|
64
|
+
new Uint8Array([REGULAR, REGULAR]),
|
|
65
|
+
new Uint32Array([2, 1]),
|
|
66
|
+
'gtfs2',
|
|
67
|
+
),
|
|
75
68
|
],
|
|
76
69
|
]);
|
|
77
70
|
const routes: ServiceRoutesMap = new Map([
|
|
@@ -106,7 +99,7 @@ describe('timetable io', () => {
|
|
|
106
99
|
Time.fromHMS(16, 50, 0).toMinutes(),
|
|
107
100
|
]).buffer,
|
|
108
101
|
),
|
|
109
|
-
pickUpDropOffTypes: new Uint8Array([
|
|
102
|
+
pickUpDropOffTypes: new Uint8Array([REGULAR, REGULAR]),
|
|
110
103
|
stops: new Uint8Array(new Uint32Array([1, 2]).buffer),
|
|
111
104
|
serviceRouteId: 'gtfs1',
|
|
112
105
|
},
|
|
@@ -117,7 +110,7 @@ describe('timetable io', () => {
|
|
|
117
110
|
Time.fromHMS(15, 30, 0).toMinutes(),
|
|
118
111
|
]).buffer,
|
|
119
112
|
),
|
|
120
|
-
pickUpDropOffTypes: new Uint8Array([
|
|
113
|
+
pickUpDropOffTypes: new Uint8Array([REGULAR, REGULAR]),
|
|
121
114
|
stops: new Uint8Array(new Uint32Array([2, 1]).buffer),
|
|
122
115
|
serviceRouteId: 'gtfs2',
|
|
123
116
|
},
|