minotor 7.0.2 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cspell.json +11 -1
- package/CHANGELOG.md +8 -3
- package/README.md +26 -24
- package/dist/cli.mjs +1786 -791
- package/dist/cli.mjs.map +1 -1
- package/dist/gtfs/transfers.d.ts +29 -5
- package/dist/gtfs/trips.d.ts +10 -5
- package/dist/parser.cjs.js +972 -525
- package/dist/parser.cjs.js.map +1 -1
- package/dist/parser.esm.js +972 -525
- package/dist/parser.esm.js.map +1 -1
- package/dist/router.cjs.js +1 -1
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +2 -2
- package/dist/router.esm.js +1 -1
- package/dist/router.esm.js.map +1 -1
- package/dist/router.umd.js +1 -1
- package/dist/router.umd.js.map +1 -1
- package/dist/routing/__tests__/plotter.test.d.ts +1 -0
- package/dist/routing/plotter.d.ts +42 -3
- package/dist/routing/result.d.ts +23 -7
- package/dist/routing/route.d.ts +2 -0
- package/dist/routing/router.d.ts +78 -19
- package/dist/timetable/__tests__/tripBoardingId.test.d.ts +1 -0
- package/dist/timetable/io.d.ts +4 -2
- package/dist/timetable/proto/timetable.d.ts +15 -1
- package/dist/timetable/route.d.ts +48 -23
- package/dist/timetable/timetable.d.ts +24 -7
- package/dist/timetable/tripBoardingId.d.ts +34 -0
- package/package.json +1 -1
- package/src/__e2e__/router.test.ts +114 -105
- package/src/__e2e__/timetable/stops.bin +2 -2
- package/src/__e2e__/timetable/timetable.bin +2 -2
- package/src/cli/repl.ts +245 -1
- package/src/gtfs/__tests__/parser.test.ts +19 -4
- package/src/gtfs/__tests__/transfers.test.ts +773 -37
- package/src/gtfs/__tests__/trips.test.ts +308 -27
- package/src/gtfs/parser.ts +36 -6
- package/src/gtfs/transfers.ts +193 -19
- package/src/gtfs/trips.ts +58 -21
- package/src/router.ts +2 -2
- package/src/routing/__tests__/plotter.test.ts +230 -0
- package/src/routing/__tests__/result.test.ts +486 -125
- package/src/routing/__tests__/route.test.ts +7 -3
- package/src/routing/__tests__/router.test.ts +380 -172
- package/src/routing/plotter.ts +279 -48
- package/src/routing/result.ts +114 -34
- package/src/routing/route.ts +0 -3
- package/src/routing/router.ts +344 -211
- package/src/timetable/__tests__/io.test.ts +34 -1
- package/src/timetable/__tests__/route.test.ts +74 -81
- package/src/timetable/__tests__/timetable.test.ts +232 -61
- package/src/timetable/__tests__/tripBoardingId.test.ts +57 -0
- package/src/timetable/io.ts +72 -10
- package/src/timetable/proto/timetable.proto +16 -2
- package/src/timetable/proto/timetable.ts +256 -22
- package/src/timetable/route.ts +174 -58
- package/src/timetable/timetable.ts +66 -16
- package/src/timetable/tripBoardingId.ts +94 -0
- package/tsconfig.json +2 -2
|
@@ -13,32 +13,47 @@ import { TransfersMap } from '../transfers.js';
|
|
|
13
13
|
import {
|
|
14
14
|
buildStopsAdjacencyStructure,
|
|
15
15
|
encodePickUpDropOffTypes,
|
|
16
|
+
GtfsTripIdsMap,
|
|
16
17
|
parseStopTimes,
|
|
17
18
|
parseTrips,
|
|
18
|
-
TripIdsMap,
|
|
19
19
|
} from '../trips.js';
|
|
20
20
|
|
|
21
21
|
describe('buildStopsAdjacencyStructure', () => {
|
|
22
22
|
it('should correctly build stops adjacency for valid routes and transfers', () => {
|
|
23
23
|
const validStops: Set<StopId> = new Set([0]);
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
const routes = [
|
|
25
|
+
Route.of({
|
|
26
|
+
id: 0,
|
|
27
|
+
serviceRouteId: 0,
|
|
28
|
+
trips: [
|
|
29
|
+
{
|
|
30
|
+
stops: [
|
|
31
|
+
{
|
|
32
|
+
id: 0,
|
|
33
|
+
arrivalTime: Time.fromHMS(8, 0, 0),
|
|
34
|
+
departureTime: Time.fromHMS(8, 0, 0),
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 1,
|
|
38
|
+
arrivalTime: Time.fromHMS(8, 5, 0),
|
|
39
|
+
departureTime: Time.fromHMS(8, 5, 0),
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
}),
|
|
31
45
|
];
|
|
32
46
|
const transfersMap: TransfersMap = new Map([
|
|
33
47
|
[0, [{ destination: 1, type: 'RECOMMENDED' }]],
|
|
34
48
|
]);
|
|
49
|
+
|
|
35
50
|
const serviceRoutes: ServiceRoute[] = [
|
|
36
51
|
{ type: 'BUS', name: 'B1', routes: [] },
|
|
37
52
|
];
|
|
38
53
|
|
|
39
54
|
const stopsAdjacency = buildStopsAdjacencyStructure(
|
|
40
55
|
serviceRoutes,
|
|
41
|
-
|
|
56
|
+
routes,
|
|
42
57
|
transfersMap,
|
|
43
58
|
2,
|
|
44
59
|
validStops,
|
|
@@ -61,7 +76,6 @@ describe('buildStopsAdjacencyStructure', () => {
|
|
|
61
76
|
1,
|
|
62
77
|
{
|
|
63
78
|
routes: [],
|
|
64
|
-
transfers: [],
|
|
65
79
|
},
|
|
66
80
|
],
|
|
67
81
|
]);
|
|
@@ -70,13 +84,27 @@ describe('buildStopsAdjacencyStructure', () => {
|
|
|
70
84
|
|
|
71
85
|
it('should ignore transfers to invalid stops', () => {
|
|
72
86
|
const validStops: Set<StopId> = new Set([0, 1]);
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
87
|
+
const routes = [
|
|
88
|
+
Route.of({
|
|
89
|
+
id: 0,
|
|
90
|
+
serviceRouteId: 0,
|
|
91
|
+
trips: [
|
|
92
|
+
{
|
|
93
|
+
stops: [
|
|
94
|
+
{
|
|
95
|
+
id: 0,
|
|
96
|
+
arrivalTime: Time.fromHMS(8, 0, 0),
|
|
97
|
+
departureTime: Time.fromHMS(8, 0, 0),
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 1,
|
|
101
|
+
arrivalTime: Time.fromHMS(8, 5, 0),
|
|
102
|
+
departureTime: Time.fromHMS(8, 5, 0),
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
}),
|
|
80
108
|
];
|
|
81
109
|
const transfersMap: TransfersMap = new Map([
|
|
82
110
|
[3, [{ destination: 2, type: 'RECOMMENDED' }]],
|
|
@@ -87,7 +115,7 @@ describe('buildStopsAdjacencyStructure', () => {
|
|
|
87
115
|
|
|
88
116
|
const stopsAdjacency = buildStopsAdjacencyStructure(
|
|
89
117
|
serviceRoutes,
|
|
90
|
-
|
|
118
|
+
routes,
|
|
91
119
|
transfersMap,
|
|
92
120
|
4,
|
|
93
121
|
validStops,
|
|
@@ -98,33 +126,194 @@ describe('buildStopsAdjacencyStructure', () => {
|
|
|
98
126
|
0,
|
|
99
127
|
{
|
|
100
128
|
routes: [0],
|
|
101
|
-
transfers: [],
|
|
102
129
|
},
|
|
103
130
|
],
|
|
104
131
|
[
|
|
105
132
|
1,
|
|
106
133
|
{
|
|
107
134
|
routes: [0],
|
|
108
|
-
transfers: [],
|
|
109
135
|
},
|
|
110
136
|
],
|
|
111
137
|
[
|
|
112
138
|
2,
|
|
113
139
|
{
|
|
114
140
|
routes: [],
|
|
115
|
-
transfers: [],
|
|
116
141
|
},
|
|
117
142
|
],
|
|
118
143
|
[
|
|
119
144
|
3,
|
|
120
145
|
{
|
|
121
146
|
routes: [],
|
|
122
|
-
transfers: [],
|
|
123
147
|
},
|
|
124
148
|
],
|
|
125
149
|
]);
|
|
126
150
|
assert.deepEqual(serviceRoutes[0]?.routes, [0]);
|
|
127
151
|
});
|
|
152
|
+
|
|
153
|
+
it('should correctly handle trip continuations', () => {
|
|
154
|
+
const validStops: Set<StopId> = new Set([0, 1]);
|
|
155
|
+
const routes = [
|
|
156
|
+
Route.of({
|
|
157
|
+
id: 0,
|
|
158
|
+
serviceRouteId: 0,
|
|
159
|
+
trips: [
|
|
160
|
+
{
|
|
161
|
+
stops: [
|
|
162
|
+
{
|
|
163
|
+
id: 0,
|
|
164
|
+
arrivalTime: Time.fromHMS(8, 0, 0),
|
|
165
|
+
departureTime: Time.fromHMS(8, 0, 0),
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
}),
|
|
171
|
+
Route.of({
|
|
172
|
+
id: 1,
|
|
173
|
+
serviceRouteId: 0,
|
|
174
|
+
trips: [
|
|
175
|
+
{
|
|
176
|
+
stops: [
|
|
177
|
+
{
|
|
178
|
+
id: 1,
|
|
179
|
+
arrivalTime: Time.fromHMS(8, 30, 0),
|
|
180
|
+
departureTime: Time.fromHMS(8, 30, 0),
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
}),
|
|
186
|
+
];
|
|
187
|
+
const transfersMap: TransfersMap = new Map();
|
|
188
|
+
const serviceRoutes: ServiceRoute[] = [
|
|
189
|
+
{ type: 'BUS', name: 'B1', routes: [] },
|
|
190
|
+
];
|
|
191
|
+
|
|
192
|
+
const stopsAdjacency = buildStopsAdjacencyStructure(
|
|
193
|
+
serviceRoutes,
|
|
194
|
+
routes,
|
|
195
|
+
transfersMap,
|
|
196
|
+
2,
|
|
197
|
+
validStops,
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
assert.deepEqual(Array.from(stopsAdjacency.entries()), [
|
|
201
|
+
[
|
|
202
|
+
0,
|
|
203
|
+
{
|
|
204
|
+
routes: [0],
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
[
|
|
208
|
+
1,
|
|
209
|
+
{
|
|
210
|
+
routes: [1],
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
]);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should ignore trip continuations with invalid trip IDs', () => {
|
|
217
|
+
const validStops: Set<StopId> = new Set([0]);
|
|
218
|
+
const routes = [
|
|
219
|
+
Route.of({
|
|
220
|
+
id: 0,
|
|
221
|
+
serviceRouteId: 0,
|
|
222
|
+
trips: [
|
|
223
|
+
{
|
|
224
|
+
stops: [
|
|
225
|
+
{
|
|
226
|
+
id: 0,
|
|
227
|
+
arrivalTime: Time.fromHMS(8, 0, 0),
|
|
228
|
+
departureTime: Time.fromHMS(8, 0, 0),
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
}),
|
|
234
|
+
];
|
|
235
|
+
const transfersMap: TransfersMap = new Map();
|
|
236
|
+
const serviceRoutes: ServiceRoute[] = [
|
|
237
|
+
{ type: 'BUS', name: 'B1', routes: [] },
|
|
238
|
+
];
|
|
239
|
+
|
|
240
|
+
const stopsAdjacency = buildStopsAdjacencyStructure(
|
|
241
|
+
serviceRoutes,
|
|
242
|
+
routes,
|
|
243
|
+
transfersMap,
|
|
244
|
+
1,
|
|
245
|
+
validStops,
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
assert.deepEqual(Array.from(stopsAdjacency.entries()), [
|
|
249
|
+
[
|
|
250
|
+
0,
|
|
251
|
+
{
|
|
252
|
+
routes: [0],
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
]);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('should ignore trip continuations for inactive stops', () => {
|
|
259
|
+
const validStops: Set<StopId> = new Set([0]); // Only stop 0 is active
|
|
260
|
+
const routes = [
|
|
261
|
+
Route.of({
|
|
262
|
+
id: 0,
|
|
263
|
+
serviceRouteId: 0,
|
|
264
|
+
trips: [
|
|
265
|
+
{
|
|
266
|
+
stops: [
|
|
267
|
+
{
|
|
268
|
+
id: 0,
|
|
269
|
+
arrivalTime: Time.fromHMS(8, 0, 0),
|
|
270
|
+
departureTime: Time.fromHMS(8, 0, 0),
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
}),
|
|
276
|
+
];
|
|
277
|
+
const transfersMap: TransfersMap = new Map();
|
|
278
|
+
const serviceRoutes: ServiceRoute[] = [
|
|
279
|
+
{ type: 'BUS', name: 'B1', routes: [] },
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
const stopsAdjacency = buildStopsAdjacencyStructure(
|
|
283
|
+
serviceRoutes,
|
|
284
|
+
routes,
|
|
285
|
+
transfersMap,
|
|
286
|
+
4,
|
|
287
|
+
validStops,
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
assert.deepEqual(Array.from(stopsAdjacency.entries()), [
|
|
291
|
+
[
|
|
292
|
+
0,
|
|
293
|
+
{
|
|
294
|
+
routes: [0],
|
|
295
|
+
},
|
|
296
|
+
],
|
|
297
|
+
[
|
|
298
|
+
1,
|
|
299
|
+
{
|
|
300
|
+
routes: [],
|
|
301
|
+
},
|
|
302
|
+
],
|
|
303
|
+
[
|
|
304
|
+
2,
|
|
305
|
+
{
|
|
306
|
+
routes: [],
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
[
|
|
310
|
+
3,
|
|
311
|
+
{
|
|
312
|
+
routes: [],
|
|
313
|
+
},
|
|
314
|
+
],
|
|
315
|
+
]);
|
|
316
|
+
});
|
|
128
317
|
});
|
|
129
318
|
describe('GTFS trips parser', () => {
|
|
130
319
|
it('should correctly parse valid trips', async () => {
|
|
@@ -207,7 +396,7 @@ describe('GTFS stop times parser', () => {
|
|
|
207
396
|
mockedStream.push('"tripA","08:10:00","08:15:00","stop2","2","0","0"\n');
|
|
208
397
|
mockedStream.push(null);
|
|
209
398
|
|
|
210
|
-
const validTripIds:
|
|
399
|
+
const validTripIds: GtfsTripIdsMap = new Map([['tripA', 'routeA']]);
|
|
211
400
|
const validStopIds: Set<StopId> = new Set([0, 1]);
|
|
212
401
|
const stopsMap: GtfsStopsMap = new Map([
|
|
213
402
|
[
|
|
@@ -243,6 +432,7 @@ describe('GTFS stop times parser', () => {
|
|
|
243
432
|
);
|
|
244
433
|
assert.deepEqual(result.routes, [
|
|
245
434
|
new Route(
|
|
435
|
+
0,
|
|
246
436
|
new Uint16Array([
|
|
247
437
|
Time.fromHMS(8, 0, 0).toMinutes(),
|
|
248
438
|
Time.fromHMS(8, 5, 0).toMinutes(),
|
|
@@ -254,6 +444,10 @@ describe('GTFS stop times parser', () => {
|
|
|
254
444
|
0,
|
|
255
445
|
),
|
|
256
446
|
]);
|
|
447
|
+
assert.deepEqual(
|
|
448
|
+
result.tripsMapping,
|
|
449
|
+
new Map([['tripA', { routeId: 0, tripRouteIndex: 0 }]]),
|
|
450
|
+
);
|
|
257
451
|
});
|
|
258
452
|
|
|
259
453
|
it('should create same route for same GTFS route with same stops', async () => {
|
|
@@ -267,7 +461,7 @@ describe('GTFS stop times parser', () => {
|
|
|
267
461
|
mockedStream.push('"tripB","09:10:00","09:15:00","stop2","2","0","0"\n');
|
|
268
462
|
mockedStream.push(null);
|
|
269
463
|
|
|
270
|
-
const validTripIds:
|
|
464
|
+
const validTripIds: GtfsTripIdsMap = new Map([
|
|
271
465
|
['tripA', 'routeA'],
|
|
272
466
|
['tripB', 'routeA'],
|
|
273
467
|
]);
|
|
@@ -303,6 +497,7 @@ describe('GTFS stop times parser', () => {
|
|
|
303
497
|
);
|
|
304
498
|
assert.deepEqual(result.routes, [
|
|
305
499
|
new Route(
|
|
500
|
+
0,
|
|
306
501
|
new Uint16Array([
|
|
307
502
|
Time.fromHMS(8, 0, 0).toMinutes(),
|
|
308
503
|
Time.fromHMS(8, 5, 0).toMinutes(),
|
|
@@ -321,6 +516,13 @@ describe('GTFS stop times parser', () => {
|
|
|
321
516
|
0,
|
|
322
517
|
),
|
|
323
518
|
]);
|
|
519
|
+
assert.deepEqual(
|
|
520
|
+
result.tripsMapping,
|
|
521
|
+
new Map([
|
|
522
|
+
['tripA', { routeId: 0, tripRouteIndex: 0 }],
|
|
523
|
+
['tripB', { routeId: 0, tripRouteIndex: 1 }],
|
|
524
|
+
]),
|
|
525
|
+
);
|
|
324
526
|
});
|
|
325
527
|
|
|
326
528
|
it('should support unsorted trips within a route', async () => {
|
|
@@ -334,7 +536,7 @@ describe('GTFS stop times parser', () => {
|
|
|
334
536
|
mockedStream.push('"tripA","08:10:00","08:15:00","stop2","2","0","0"\n');
|
|
335
537
|
mockedStream.push(null);
|
|
336
538
|
|
|
337
|
-
const validTripIds:
|
|
539
|
+
const validTripIds: GtfsTripIdsMap = new Map([
|
|
338
540
|
['tripA', 'routeA'],
|
|
339
541
|
['tripB', 'routeA'],
|
|
340
542
|
]);
|
|
@@ -370,6 +572,7 @@ describe('GTFS stop times parser', () => {
|
|
|
370
572
|
);
|
|
371
573
|
assert.deepEqual(result.routes, [
|
|
372
574
|
new Route(
|
|
575
|
+
0,
|
|
373
576
|
new Uint16Array([
|
|
374
577
|
Time.fromHMS(8, 0, 0).toMinutes(),
|
|
375
578
|
Time.fromHMS(8, 5, 0).toMinutes(),
|
|
@@ -400,7 +603,7 @@ describe('GTFS stop times parser', () => {
|
|
|
400
603
|
mockedStream.push('"tripB","09:00:00","09:15:00","stop1","1","0","0"\n');
|
|
401
604
|
mockedStream.push(null);
|
|
402
605
|
|
|
403
|
-
const validTripIds:
|
|
606
|
+
const validTripIds: GtfsTripIdsMap = new Map([
|
|
404
607
|
['tripA', 'routeA'],
|
|
405
608
|
['tripB', 'routeA'],
|
|
406
609
|
]);
|
|
@@ -436,6 +639,7 @@ describe('GTFS stop times parser', () => {
|
|
|
436
639
|
);
|
|
437
640
|
assert.deepEqual(result.routes, [
|
|
438
641
|
new Route(
|
|
642
|
+
0,
|
|
439
643
|
new Uint16Array([
|
|
440
644
|
Time.fromHMS(8, 0, 0).toMinutes(),
|
|
441
645
|
Time.fromHMS(8, 5, 0).toMinutes(),
|
|
@@ -447,6 +651,7 @@ describe('GTFS stop times parser', () => {
|
|
|
447
651
|
0,
|
|
448
652
|
),
|
|
449
653
|
new Route(
|
|
654
|
+
1,
|
|
450
655
|
new Uint16Array([
|
|
451
656
|
Time.fromHMS(9, 0, 0).toMinutes(),
|
|
452
657
|
Time.fromHMS(9, 15, 0).toMinutes(),
|
|
@@ -467,7 +672,7 @@ describe('GTFS stop times parser', () => {
|
|
|
467
672
|
mockedStream.push('"tripA","08:10:00","08:15:00","stop2","1","0","0"\n');
|
|
468
673
|
mockedStream.push(null);
|
|
469
674
|
|
|
470
|
-
const validTripIds:
|
|
675
|
+
const validTripIds: GtfsTripIdsMap = new Map([['tripA', 'routeA']]);
|
|
471
676
|
const validStopIds: Set<StopId> = new Set([0, 1]);
|
|
472
677
|
const stopsMap: GtfsStopsMap = new Map([
|
|
473
678
|
[
|
|
@@ -500,6 +705,7 @@ describe('GTFS stop times parser', () => {
|
|
|
500
705
|
);
|
|
501
706
|
assert.deepEqual(result.routes, [
|
|
502
707
|
new Route(
|
|
708
|
+
0,
|
|
503
709
|
new Uint16Array([
|
|
504
710
|
Time.fromHMS(8, 0, 0).toMinutes(),
|
|
505
711
|
Time.fromHMS(8, 5, 0).toMinutes(),
|
|
@@ -509,5 +715,80 @@ describe('GTFS stop times parser', () => {
|
|
|
509
715
|
0,
|
|
510
716
|
),
|
|
511
717
|
]);
|
|
718
|
+
assert.deepEqual(
|
|
719
|
+
result.tripsMapping,
|
|
720
|
+
new Map([['tripA', { routeId: 0, tripRouteIndex: 0 }]]),
|
|
721
|
+
);
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
it('should create trip continuations mapping correctly', async () => {
|
|
725
|
+
const mockedStream = new Readable();
|
|
726
|
+
mockedStream.push(
|
|
727
|
+
'trip_id,arrival_time,departure_time,stop_id,stop_sequence,pickup_type,drop_off_type\n',
|
|
728
|
+
);
|
|
729
|
+
mockedStream.push('"trip1","08:00:00","08:05:00","stop1","1","0","0"\n');
|
|
730
|
+
mockedStream.push('"trip1","08:10:00","08:15:00","stop2","2","0","0"\n');
|
|
731
|
+
mockedStream.push('"trip2","09:00:00","09:05:00","stop3","1","0","0"\n');
|
|
732
|
+
mockedStream.push(null);
|
|
733
|
+
|
|
734
|
+
const validTripIds: GtfsTripIdsMap = new Map([
|
|
735
|
+
['trip1', 'routeA'],
|
|
736
|
+
['trip2', 'routeB'],
|
|
737
|
+
]);
|
|
738
|
+
const validStopIds: Set<StopId> = new Set([0, 1, 2]);
|
|
739
|
+
const stopsMap: GtfsStopsMap = new Map([
|
|
740
|
+
[
|
|
741
|
+
'stop1',
|
|
742
|
+
{
|
|
743
|
+
id: 0,
|
|
744
|
+
sourceStopId: 'stop1',
|
|
745
|
+
name: 'Stop 1',
|
|
746
|
+
children: [],
|
|
747
|
+
locationType: 'SIMPLE_STOP_OR_PLATFORM',
|
|
748
|
+
},
|
|
749
|
+
],
|
|
750
|
+
[
|
|
751
|
+
'stop2',
|
|
752
|
+
{
|
|
753
|
+
id: 1,
|
|
754
|
+
sourceStopId: 'stop2',
|
|
755
|
+
name: 'Stop 2',
|
|
756
|
+
children: [],
|
|
757
|
+
locationType: 'SIMPLE_STOP_OR_PLATFORM',
|
|
758
|
+
},
|
|
759
|
+
],
|
|
760
|
+
[
|
|
761
|
+
'stop3',
|
|
762
|
+
{
|
|
763
|
+
id: 2,
|
|
764
|
+
sourceStopId: 'stop3',
|
|
765
|
+
name: 'Stop 3',
|
|
766
|
+
children: [],
|
|
767
|
+
locationType: 'SIMPLE_STOP_OR_PLATFORM',
|
|
768
|
+
},
|
|
769
|
+
],
|
|
770
|
+
]);
|
|
771
|
+
|
|
772
|
+
const result = await parseStopTimes(
|
|
773
|
+
mockedStream,
|
|
774
|
+
stopsMap,
|
|
775
|
+
validTripIds,
|
|
776
|
+
validStopIds,
|
|
777
|
+
);
|
|
778
|
+
|
|
779
|
+
assert.deepEqual(
|
|
780
|
+
result.tripsMapping,
|
|
781
|
+
new Map([
|
|
782
|
+
['trip1', { routeId: 0, tripRouteIndex: 0 }],
|
|
783
|
+
['trip2', { routeId: 1, tripRouteIndex: 0 }],
|
|
784
|
+
]),
|
|
785
|
+
);
|
|
786
|
+
assert.deepEqual(
|
|
787
|
+
result.serviceRoutesMap,
|
|
788
|
+
new Map([
|
|
789
|
+
['routeA', 0],
|
|
790
|
+
['routeB', 1],
|
|
791
|
+
]),
|
|
792
|
+
);
|
|
512
793
|
});
|
|
513
794
|
});
|
package/src/gtfs/parser.ts
CHANGED
|
@@ -9,7 +9,12 @@ import { standardProfile } from './profiles/standard.js';
|
|
|
9
9
|
import { indexRoutes, parseRoutes } from './routes.js';
|
|
10
10
|
import { parseCalendar, parseCalendarDates, ServiceIds } from './services.js';
|
|
11
11
|
import { parseStops } from './stops.js';
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
buildTripContinuations,
|
|
14
|
+
GtfsTripContinuation,
|
|
15
|
+
parseTransfers,
|
|
16
|
+
TransfersMap,
|
|
17
|
+
} from './transfers.js';
|
|
13
18
|
import {
|
|
14
19
|
buildStopsAdjacencyStructure,
|
|
15
20
|
parseStopTimes,
|
|
@@ -107,22 +112,28 @@ export class GtfsParser {
|
|
|
107
112
|
`${trips.size} valid trips. (${(tripsEnd - tripsStart).toFixed(2)}ms)`,
|
|
108
113
|
);
|
|
109
114
|
|
|
110
|
-
let transfers = new Map()
|
|
115
|
+
let transfers: TransfersMap = new Map();
|
|
116
|
+
let tripContinuationsMap: GtfsTripContinuation[] = [];
|
|
111
117
|
if (entries[TRANSFERS_FILE]) {
|
|
112
118
|
log.info(`Parsing ${TRANSFERS_FILE}`);
|
|
113
119
|
const transfersStart = performance.now();
|
|
114
120
|
const transfersStream = await zip.stream(TRANSFERS_FILE);
|
|
115
|
-
|
|
121
|
+
const {
|
|
122
|
+
transfers: parsedTransfers,
|
|
123
|
+
tripContinuations: parsedTripContinuations,
|
|
124
|
+
} = await parseTransfers(transfersStream, parsedStops);
|
|
125
|
+
transfers = parsedTransfers;
|
|
126
|
+
tripContinuationsMap = parsedTripContinuations;
|
|
116
127
|
const transfersEnd = performance.now();
|
|
117
128
|
log.info(
|
|
118
|
-
`${transfers.size} valid transfers. (${(transfersEnd - transfersStart).toFixed(2)}ms)`,
|
|
129
|
+
`${transfers.size} valid transfers and ${tripContinuationsMap.length} trip continuations. (${(transfersEnd - transfersStart).toFixed(2)}ms)`,
|
|
119
130
|
);
|
|
120
131
|
}
|
|
121
132
|
|
|
122
133
|
log.info(`Parsing ${STOP_TIMES_FILE}`);
|
|
123
134
|
const stopTimesStart = performance.now();
|
|
124
135
|
const stopTimesStream = await zip.stream(STOP_TIMES_FILE);
|
|
125
|
-
const { routes, serviceRoutesMap } = await parseStopTimes(
|
|
136
|
+
const { routes, serviceRoutesMap, tripsMapping } = await parseStopTimes(
|
|
126
137
|
stopTimesStream,
|
|
127
138
|
parsedStops,
|
|
128
139
|
trips,
|
|
@@ -149,10 +160,29 @@ export class GtfsParser {
|
|
|
149
160
|
);
|
|
150
161
|
await zip.close();
|
|
151
162
|
|
|
163
|
+
// temporary timetable for building continuations
|
|
152
164
|
const timetable = new Timetable(stopsAdjacency, routes, serviceRoutes);
|
|
153
165
|
|
|
166
|
+
log.info('Building in-seat trip continuations');
|
|
167
|
+
const tripContinuationsStart = performance.now();
|
|
168
|
+
const tripContinuations = buildTripContinuations(
|
|
169
|
+
tripsMapping,
|
|
170
|
+
tripContinuationsMap,
|
|
171
|
+
timetable,
|
|
172
|
+
activeStopIds,
|
|
173
|
+
);
|
|
174
|
+
const tripContinuationsEnd = performance.now();
|
|
175
|
+
log.info(
|
|
176
|
+
`${tripContinuations.size} in-seat trip continuations origins created. (${(tripContinuationsEnd - tripContinuationsStart).toFixed(2)}ms)`,
|
|
177
|
+
);
|
|
154
178
|
log.info('Parsing complete.');
|
|
155
|
-
|
|
179
|
+
|
|
180
|
+
return new Timetable(
|
|
181
|
+
stopsAdjacency,
|
|
182
|
+
routes,
|
|
183
|
+
serviceRoutes,
|
|
184
|
+
tripContinuations,
|
|
185
|
+
);
|
|
156
186
|
}
|
|
157
187
|
|
|
158
188
|
/**
|