minotor 5.0.1 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -3
- package/dist/cli.mjs +207 -596
- package/dist/cli.mjs.map +1 -1
- package/dist/gtfs/parser.d.ts +4 -10
- package/dist/gtfs/routes.d.ts +16 -2
- package/dist/gtfs/stops.d.ts +3 -13
- package/dist/gtfs/transfers.d.ts +2 -2
- package/dist/gtfs/trips.d.ts +12 -8
- package/dist/parser.cjs.js +201 -593
- package/dist/parser.cjs.js.map +1 -1
- package/dist/parser.esm.js +201 -593
- 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/stops/io.d.ts +3 -3
- package/dist/stops/proto/stops.d.ts +1 -8
- package/dist/stops/stops.d.ts +0 -4
- package/dist/stops/stopsIndex.d.ts +3 -3
- package/dist/timetable/io.d.ts +6 -6
- package/dist/timetable/proto/timetable.d.ts +5 -27
- package/dist/timetable/timetable.d.ts +17 -9
- package/package.json +1 -1
- package/src/__e2e__/timetable/stops.bin +2 -2
- package/src/__e2e__/timetable/timetable.bin +2 -2
- package/src/cli/minotor.ts +3 -4
- package/src/gtfs/__tests__/parser.test.ts +5 -6
- package/src/gtfs/__tests__/routes.test.ts +0 -3
- package/src/gtfs/__tests__/stops.test.ts +1 -124
- package/src/gtfs/__tests__/transfers.test.ts +7 -7
- package/src/gtfs/__tests__/trips.test.ts +74 -45
- package/src/gtfs/parser.ts +32 -49
- package/src/gtfs/routes.ts +43 -5
- package/src/gtfs/stops.ts +2 -44
- package/src/gtfs/transfers.ts +2 -2
- package/src/gtfs/trips.ts +57 -40
- package/src/routing/__tests__/result.test.ts +48 -48
- package/src/routing/__tests__/router.test.ts +279 -363
- package/src/routing/router.ts +3 -1
- package/src/stops/__tests__/io.test.ts +25 -31
- package/src/stops/__tests__/stopFinder.test.ts +82 -103
- package/src/stops/io.ts +8 -17
- package/src/stops/proto/stops.proto +3 -3
- package/src/stops/proto/stops.ts +16 -120
- package/src/stops/stops.ts +0 -4
- package/src/stops/stopsIndex.ts +20 -26
- package/src/timetable/__tests__/io.test.ts +44 -54
- package/src/timetable/__tests__/route.test.ts +11 -11
- package/src/timetable/__tests__/timetable.test.ts +29 -37
- package/src/timetable/io.ts +38 -66
- package/src/timetable/proto/timetable.proto +6 -13
- package/src/timetable/proto/timetable.ts +43 -385
- package/src/timetable/timetable.ts +43 -28
package/src/stops/stopsIndex.ts
CHANGED
|
@@ -6,13 +6,7 @@ import { addAll, createIndex, search, SearchResult } from 'slimsearch';
|
|
|
6
6
|
import { generateAccentVariants } from './i18n.js';
|
|
7
7
|
import { deserializeStopsMap, serializeStopsMap } from './io.js';
|
|
8
8
|
import { StopsMap as ProtoStopsMap } from './proto/stops.js';
|
|
9
|
-
import {
|
|
10
|
-
SourceStopId,
|
|
11
|
-
SourceStopsMap,
|
|
12
|
-
Stop,
|
|
13
|
-
StopId,
|
|
14
|
-
StopsMap,
|
|
15
|
-
} from './stops.js';
|
|
9
|
+
import { SourceStopId, SourceStopsMap, Stop, StopId } from './stops.js';
|
|
16
10
|
|
|
17
11
|
type StopPoint = { id: StopId; lat: number; lon: number };
|
|
18
12
|
|
|
@@ -22,18 +16,18 @@ type StopPoint = { id: StopId; lat: number; lon: number };
|
|
|
22
16
|
* to efficiently find stops based on user queries.
|
|
23
17
|
*/
|
|
24
18
|
export class StopsIndex {
|
|
25
|
-
private readonly
|
|
19
|
+
private readonly stops: Stop[];
|
|
26
20
|
private readonly sourceStopsMap: SourceStopsMap;
|
|
27
21
|
private readonly textIndex;
|
|
28
22
|
private readonly geoIndex: KDTree;
|
|
29
23
|
private readonly stopPoints: StopPoint[];
|
|
30
24
|
|
|
31
|
-
constructor(
|
|
32
|
-
this.
|
|
25
|
+
constructor(stops: Stop[]) {
|
|
26
|
+
this.stops = stops;
|
|
33
27
|
this.sourceStopsMap = new Map<SourceStopId, StopId>();
|
|
34
|
-
|
|
28
|
+
stops.forEach((stop, id) => {
|
|
35
29
|
this.sourceStopsMap.set(stop.sourceStopId, id);
|
|
36
|
-
}
|
|
30
|
+
});
|
|
37
31
|
this.textIndex = createIndex({
|
|
38
32
|
fields: ['name'],
|
|
39
33
|
storeFields: ['id'],
|
|
@@ -41,25 +35,25 @@ export class StopsIndex {
|
|
|
41
35
|
processTerm: generateAccentVariants,
|
|
42
36
|
});
|
|
43
37
|
const stopsSet = new Map<StopId, { id: StopId; name: string }>();
|
|
44
|
-
|
|
38
|
+
stops.forEach((stop, id) => {
|
|
45
39
|
const effectiveStopId = stop.parent ?? id;
|
|
46
40
|
if (!stopsSet.has(effectiveStopId)) {
|
|
47
41
|
stopsSet.set(effectiveStopId, {
|
|
48
42
|
id: effectiveStopId,
|
|
49
43
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
50
|
-
name: stop.parent ? this.
|
|
44
|
+
name: stop.parent ? this.stops[stop.parent]!.name : stop.name,
|
|
51
45
|
});
|
|
52
46
|
}
|
|
53
|
-
}
|
|
47
|
+
});
|
|
54
48
|
const stopsArray = Array.from(stopsSet.values());
|
|
55
49
|
addAll(this.textIndex, stopsArray);
|
|
56
50
|
|
|
57
|
-
this.stopPoints =
|
|
58
|
-
.filter((
|
|
51
|
+
this.stopPoints = this.stops
|
|
52
|
+
.filter((stop) => {
|
|
59
53
|
if (stop.lat && stop.lon) return true;
|
|
60
54
|
return false;
|
|
61
55
|
})
|
|
62
|
-
.map((
|
|
56
|
+
.map((stop, id) => ({
|
|
63
57
|
id: id,
|
|
64
58
|
lat: stop.lat as number,
|
|
65
59
|
lon: stop.lon as number,
|
|
@@ -90,7 +84,7 @@ export class StopsIndex {
|
|
|
90
84
|
* @returns The serialized binary data.
|
|
91
85
|
*/
|
|
92
86
|
serialize(): Uint8Array {
|
|
93
|
-
const protoStopsMap: ProtoStopsMap = serializeStopsMap(this.
|
|
87
|
+
const protoStopsMap: ProtoStopsMap = serializeStopsMap(this.stops);
|
|
94
88
|
|
|
95
89
|
const writer = new BinaryWriter();
|
|
96
90
|
ProtoStopsMap.encode(protoStopsMap, writer);
|
|
@@ -103,7 +97,7 @@ export class StopsIndex {
|
|
|
103
97
|
* @returns The total number of stops.
|
|
104
98
|
*/
|
|
105
99
|
size(): number {
|
|
106
|
-
return this.
|
|
100
|
+
return this.stops.length;
|
|
107
101
|
}
|
|
108
102
|
|
|
109
103
|
/**
|
|
@@ -115,7 +109,7 @@ export class StopsIndex {
|
|
|
115
109
|
*/
|
|
116
110
|
findStopsByName(query: string, maxResults = 5): Stop[] {
|
|
117
111
|
const results = search(this.textIndex, query).map(
|
|
118
|
-
(result: SearchResult) => this.
|
|
112
|
+
(result: SearchResult) => this.stops[result.id as number] as Stop,
|
|
119
113
|
);
|
|
120
114
|
return results.slice(0, maxResults);
|
|
121
115
|
}
|
|
@@ -143,7 +137,7 @@ export class StopsIndex {
|
|
|
143
137
|
radius,
|
|
144
138
|
).map((id) => {
|
|
145
139
|
const stopPoint = this.stopPoints[id as number] as StopPoint;
|
|
146
|
-
return this.
|
|
140
|
+
return this.stops[stopPoint.id] as Stop;
|
|
147
141
|
});
|
|
148
142
|
return nearestStops;
|
|
149
143
|
}
|
|
@@ -155,7 +149,7 @@ export class StopsIndex {
|
|
|
155
149
|
* @returns The Stop object that matches the specified ID, or undefined if not found.
|
|
156
150
|
*/
|
|
157
151
|
findStopById(id: StopId): Stop | undefined {
|
|
158
|
-
return this.
|
|
152
|
+
return this.stops[id];
|
|
159
153
|
}
|
|
160
154
|
|
|
161
155
|
/**
|
|
@@ -180,15 +174,15 @@ export class StopsIndex {
|
|
|
180
174
|
if (id === undefined) {
|
|
181
175
|
return [];
|
|
182
176
|
}
|
|
183
|
-
const stop = this.
|
|
177
|
+
const stop = this.stops[id];
|
|
184
178
|
if (!stop) {
|
|
185
179
|
return [];
|
|
186
180
|
}
|
|
187
181
|
const equivalentStops = stop.parent
|
|
188
|
-
? (this.
|
|
182
|
+
? (this.stops[stop.parent]?.children ?? [])
|
|
189
183
|
: stop.children;
|
|
190
184
|
return Array.from(new Set([id, ...equivalentStops])).map(
|
|
191
|
-
(stopId) => this.
|
|
185
|
+
(stopId) => this.stops[stopId] as Stop,
|
|
192
186
|
);
|
|
193
187
|
}
|
|
194
188
|
}
|
|
@@ -12,31 +12,25 @@ import {
|
|
|
12
12
|
} from '../io.js';
|
|
13
13
|
import { REGULAR, Route } from '../route.js';
|
|
14
14
|
import { Time } from '../time.js';
|
|
15
|
-
import {
|
|
15
|
+
import { ServiceRoute, StopAdjacency } from '../timetable.js';
|
|
16
16
|
|
|
17
17
|
describe('Timetable IO', () => {
|
|
18
|
-
const stopsAdjacency:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
routes: [1],
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
]);
|
|
18
|
+
const stopsAdjacency: StopAdjacency[] = [
|
|
19
|
+
{
|
|
20
|
+
transfers: [{ destination: 2, type: 'RECOMMENDED' }],
|
|
21
|
+
routes: [0],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
transfers: [
|
|
25
|
+
{
|
|
26
|
+
destination: 1,
|
|
27
|
+
type: 'GUARANTEED',
|
|
28
|
+
minTransferTime: Duration.fromMinutes(3),
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
routes: [1],
|
|
32
|
+
},
|
|
33
|
+
];
|
|
40
34
|
const routesAdjacency = [
|
|
41
35
|
new Route(
|
|
42
36
|
new Uint16Array([
|
|
@@ -45,7 +39,7 @@ describe('Timetable IO', () => {
|
|
|
45
39
|
]),
|
|
46
40
|
new Uint8Array([REGULAR, REGULAR]),
|
|
47
41
|
new Uint32Array([1, 2]),
|
|
48
|
-
|
|
42
|
+
0,
|
|
49
43
|
),
|
|
50
44
|
new Route(
|
|
51
45
|
new Uint16Array([
|
|
@@ -54,31 +48,29 @@ describe('Timetable IO', () => {
|
|
|
54
48
|
]),
|
|
55
49
|
new Uint8Array([REGULAR, REGULAR]),
|
|
56
50
|
new Uint32Array([2, 1]),
|
|
57
|
-
|
|
51
|
+
1,
|
|
58
52
|
),
|
|
59
53
|
];
|
|
60
|
-
const routes:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
]
|
|
64
|
-
const stopsAdjacencyProto =
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
routes: [1],
|
|
79
|
-
},
|
|
54
|
+
const routes: ServiceRoute[] = [
|
|
55
|
+
{ type: 'RAIL', name: 'Route 1', routes: [0] },
|
|
56
|
+
{ type: 'RAIL', name: 'Route 2', routes: [1] },
|
|
57
|
+
];
|
|
58
|
+
const stopsAdjacencyProto = [
|
|
59
|
+
{
|
|
60
|
+
transfers: [{ destination: 2, type: 0 }],
|
|
61
|
+
routes: [0],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
transfers: [
|
|
65
|
+
{
|
|
66
|
+
destination: 1,
|
|
67
|
+
type: 1,
|
|
68
|
+
minTransferTime: 180,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
routes: [1],
|
|
80
72
|
},
|
|
81
|
-
|
|
73
|
+
];
|
|
82
74
|
|
|
83
75
|
const routesAdjacencyProto = [
|
|
84
76
|
{
|
|
@@ -90,7 +82,7 @@ describe('Timetable IO', () => {
|
|
|
90
82
|
),
|
|
91
83
|
pickUpDropOffTypes: new Uint8Array([REGULAR, REGULAR]),
|
|
92
84
|
stops: new Uint8Array(new Uint32Array([1, 2]).buffer),
|
|
93
|
-
serviceRouteId:
|
|
85
|
+
serviceRouteId: 0,
|
|
94
86
|
},
|
|
95
87
|
{
|
|
96
88
|
stopTimes: new Uint8Array(
|
|
@@ -101,16 +93,14 @@ describe('Timetable IO', () => {
|
|
|
101
93
|
),
|
|
102
94
|
pickUpDropOffTypes: new Uint8Array([REGULAR, REGULAR]),
|
|
103
95
|
stops: new Uint8Array(new Uint32Array([2, 1]).buffer),
|
|
104
|
-
serviceRouteId:
|
|
96
|
+
serviceRouteId: 1,
|
|
105
97
|
},
|
|
106
98
|
];
|
|
107
99
|
|
|
108
|
-
const routesProto =
|
|
109
|
-
routes:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
},
|
|
113
|
-
};
|
|
100
|
+
const routesProto = [
|
|
101
|
+
{ type: 2, name: 'Route 1', routes: [0] },
|
|
102
|
+
{ type: 2, name: 'Route 2', routes: [1] },
|
|
103
|
+
];
|
|
114
104
|
|
|
115
105
|
it('should serialize a stops adjacency matrix to a Uint8Array', () => {
|
|
116
106
|
const serializedData = serializeStopsAdjacency(stopsAdjacency);
|
|
@@ -56,7 +56,7 @@ describe('Route', () => {
|
|
|
56
56
|
);
|
|
57
57
|
|
|
58
58
|
const stops = new Uint32Array([1001, 1002]);
|
|
59
|
-
const serviceRouteId =
|
|
59
|
+
const serviceRouteId = 0;
|
|
60
60
|
|
|
61
61
|
const route = new Route(stopTimes, pickUpDropOffTypes, stops, serviceRouteId);
|
|
62
62
|
|
|
@@ -71,10 +71,10 @@ describe('Route', () => {
|
|
|
71
71
|
new Uint16Array([]),
|
|
72
72
|
new Uint8Array([]),
|
|
73
73
|
new Uint32Array([]),
|
|
74
|
-
|
|
74
|
+
1,
|
|
75
75
|
);
|
|
76
76
|
assert.strictEqual(emptyRoute.getNbStops(), 0);
|
|
77
|
-
assert.strictEqual(emptyRoute.serviceRoute(),
|
|
77
|
+
assert.strictEqual(emptyRoute.serviceRoute(), 1);
|
|
78
78
|
});
|
|
79
79
|
});
|
|
80
80
|
|
|
@@ -104,14 +104,14 @@ describe('Route', () => {
|
|
|
104
104
|
it('should throw error when stopA is not found', () => {
|
|
105
105
|
assert.throws(
|
|
106
106
|
() => route.isBefore(9999, 1002),
|
|
107
|
-
/Stop index undefined not found in route
|
|
107
|
+
/Stop index undefined not found in route 0/,
|
|
108
108
|
);
|
|
109
109
|
});
|
|
110
110
|
|
|
111
111
|
it('should throw error when stopB is not found', () => {
|
|
112
112
|
assert.throws(
|
|
113
113
|
() => route.isBefore(1001, 9999),
|
|
114
|
-
/Stop index undefined not found in route
|
|
114
|
+
/Stop index undefined not found in route 0/,
|
|
115
115
|
);
|
|
116
116
|
});
|
|
117
117
|
});
|
|
@@ -148,7 +148,7 @@ describe('Route', () => {
|
|
|
148
148
|
it('should throw error for invalid stop ID', () => {
|
|
149
149
|
assert.throws(
|
|
150
150
|
() => route.arrivalAt(9999, 0),
|
|
151
|
-
/Stop index for 9999 not found in route
|
|
151
|
+
/Stop index for 9999 not found in route 0/,
|
|
152
152
|
);
|
|
153
153
|
});
|
|
154
154
|
|
|
@@ -180,7 +180,7 @@ describe('Route', () => {
|
|
|
180
180
|
it('should throw error for invalid stop ID', () => {
|
|
181
181
|
assert.throws(
|
|
182
182
|
() => route.departureFrom(9999, 0),
|
|
183
|
-
/Stop index for 9999 not found in route
|
|
183
|
+
/Stop index for 9999 not found in route 0/,
|
|
184
184
|
);
|
|
185
185
|
});
|
|
186
186
|
|
|
@@ -211,7 +211,7 @@ describe('Route', () => {
|
|
|
211
211
|
it('should throw error for invalid stop ID', () => {
|
|
212
212
|
assert.throws(
|
|
213
213
|
() => route.pickUpTypeFrom(9999, 0),
|
|
214
|
-
/Stop index for 9999 not found in route
|
|
214
|
+
/Stop index for 9999 not found in route 0/,
|
|
215
215
|
);
|
|
216
216
|
});
|
|
217
217
|
|
|
@@ -237,7 +237,7 @@ describe('Route', () => {
|
|
|
237
237
|
it('should throw error for invalid stop ID', () => {
|
|
238
238
|
assert.throws(
|
|
239
239
|
() => route.dropOffTypeAt(9999, 0),
|
|
240
|
-
/Stop index for 9999 not found in route
|
|
240
|
+
/Stop index for 9999 not found in route 0/,
|
|
241
241
|
);
|
|
242
242
|
});
|
|
243
243
|
|
|
@@ -263,7 +263,7 @@ describe('Route', () => {
|
|
|
263
263
|
it('should throw error for invalid start stop ID', () => {
|
|
264
264
|
assert.throws(
|
|
265
265
|
() => Array.from(route.stopsIterator(9999)),
|
|
266
|
-
/Start stop 9999 not found in route
|
|
266
|
+
/Start stop 9999 not found in route 0/,
|
|
267
267
|
);
|
|
268
268
|
});
|
|
269
269
|
});
|
|
@@ -318,7 +318,7 @@ describe('Route', () => {
|
|
|
318
318
|
it('should throw error for invalid stop ID', () => {
|
|
319
319
|
assert.throws(
|
|
320
320
|
() => route.findEarliestTrip(9999),
|
|
321
|
-
/Stop index for 9999 not found in route
|
|
321
|
+
/Stop index for 9999 not found in route 0/,
|
|
322
322
|
);
|
|
323
323
|
});
|
|
324
324
|
});
|
|
@@ -7,41 +7,33 @@ import { NOT_AVAILABLE, REGULAR, Route } from '../route.js';
|
|
|
7
7
|
import { Time } from '../time.js';
|
|
8
8
|
import {
|
|
9
9
|
RouteType,
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
ServiceRoute,
|
|
11
|
+
StopAdjacency,
|
|
12
12
|
Timetable,
|
|
13
13
|
} from '../timetable.js';
|
|
14
14
|
|
|
15
15
|
describe('Timetable', () => {
|
|
16
|
-
const stopsAdjacency:
|
|
17
|
-
[
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
[
|
|
38
|
-
3,
|
|
39
|
-
{
|
|
40
|
-
transfers: [],
|
|
41
|
-
routes: [],
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
]);
|
|
16
|
+
const stopsAdjacency: StopAdjacency[] = [
|
|
17
|
+
{ transfers: [], routes: [] },
|
|
18
|
+
{
|
|
19
|
+
transfers: [{ destination: 2, type: 'RECOMMENDED' }],
|
|
20
|
+
routes: [0, 1],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
transfers: [
|
|
24
|
+
{
|
|
25
|
+
destination: 1,
|
|
26
|
+
type: 'GUARANTEED',
|
|
27
|
+
minTransferTime: Duration.fromMinutes(3),
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
routes: [1, 0],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
transfers: [],
|
|
34
|
+
routes: [],
|
|
35
|
+
},
|
|
36
|
+
];
|
|
45
37
|
|
|
46
38
|
const route1 = new Route(
|
|
47
39
|
new Uint16Array([
|
|
@@ -59,7 +51,7 @@ describe('Timetable', () => {
|
|
|
59
51
|
[REGULAR, REGULAR, REGULAR, REGULAR],
|
|
60
52
|
),
|
|
61
53
|
new Uint32Array([1, 2]),
|
|
62
|
-
|
|
54
|
+
0,
|
|
63
55
|
);
|
|
64
56
|
const route2 = new Route(
|
|
65
57
|
new Uint16Array([
|
|
@@ -70,13 +62,13 @@ describe('Timetable', () => {
|
|
|
70
62
|
]),
|
|
71
63
|
encodePickUpDropOffTypes([REGULAR, REGULAR], [REGULAR, REGULAR]),
|
|
72
64
|
new Uint32Array([2, 1]),
|
|
73
|
-
|
|
65
|
+
1,
|
|
74
66
|
);
|
|
75
67
|
const routesAdjacency = [route1, route2];
|
|
76
|
-
const routes:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
]
|
|
68
|
+
const routes: ServiceRoute[] = [
|
|
69
|
+
{ type: 'RAIL', name: 'Route 1', routes: [0] },
|
|
70
|
+
{ type: 'RAIL', name: 'Route 2', routes: [1] },
|
|
71
|
+
];
|
|
80
72
|
|
|
81
73
|
const sampleTimetable: Timetable = new Timetable(
|
|
82
74
|
stopsAdjacency,
|
package/src/timetable/io.ts
CHANGED
|
@@ -2,17 +2,17 @@ import { Duration } from './duration.js';
|
|
|
2
2
|
import {
|
|
3
3
|
Route as ProtoRoute,
|
|
4
4
|
RouteType as ProtoRouteType,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
ServiceRoute as ProtoServiceRoute,
|
|
6
|
+
StopAdjacency as ProtoStopAdjacency,
|
|
7
7
|
Transfer as ProtoTransfer,
|
|
8
8
|
TransferType as ProtoTransferType,
|
|
9
9
|
} from './proto/timetable.js';
|
|
10
|
-
import { Route
|
|
10
|
+
import { Route } from './route.js';
|
|
11
11
|
import {
|
|
12
12
|
RouteType,
|
|
13
|
+
ServiceRoute,
|
|
13
14
|
ServiceRouteId,
|
|
14
|
-
|
|
15
|
-
StopsAdjacency,
|
|
15
|
+
StopAdjacency,
|
|
16
16
|
Transfer,
|
|
17
17
|
TransferType,
|
|
18
18
|
} from './timetable.js';
|
|
@@ -122,28 +122,20 @@ const bytesToUint16Array = (bytes: Uint8Array): Uint16Array => {
|
|
|
122
122
|
};
|
|
123
123
|
|
|
124
124
|
export const serializeStopsAdjacency = (
|
|
125
|
-
stopsAdjacency:
|
|
126
|
-
):
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}),
|
|
140
|
-
})),
|
|
141
|
-
routes: value.routes,
|
|
142
|
-
};
|
|
143
|
-
},
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
return protoStopsAdjacency;
|
|
125
|
+
stopsAdjacency: StopAdjacency[],
|
|
126
|
+
): ProtoStopAdjacency[] => {
|
|
127
|
+
return stopsAdjacency.map((value) => {
|
|
128
|
+
return {
|
|
129
|
+
transfers: value.transfers.map((transfer) => ({
|
|
130
|
+
destination: transfer.destination,
|
|
131
|
+
type: serializeTransferType(transfer.type),
|
|
132
|
+
...(transfer.minTransferTime !== undefined && {
|
|
133
|
+
minTransferTime: transfer.minTransferTime.toSeconds(),
|
|
134
|
+
}),
|
|
135
|
+
})),
|
|
136
|
+
routes: value.routes,
|
|
137
|
+
};
|
|
138
|
+
});
|
|
147
139
|
};
|
|
148
140
|
|
|
149
141
|
export const serializeRoutesAdjacency = (
|
|
@@ -165,36 +157,22 @@ export const serializeRoutesAdjacency = (
|
|
|
165
157
|
};
|
|
166
158
|
|
|
167
159
|
export const serializeServiceRoutesMap = (
|
|
168
|
-
|
|
169
|
-
):
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
key: string,
|
|
178
|
-
) => {
|
|
179
|
-
protoServiceRoutesMap.routes[key] = {
|
|
180
|
-
type: serializeRouteType(value.type),
|
|
181
|
-
name: value.name,
|
|
182
|
-
routes: value.routes,
|
|
183
|
-
};
|
|
184
|
-
},
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
return protoServiceRoutesMap;
|
|
160
|
+
serviceRoutes: ServiceRoute[],
|
|
161
|
+
): ProtoServiceRoute[] => {
|
|
162
|
+
return serviceRoutes.map((value) => {
|
|
163
|
+
return {
|
|
164
|
+
type: serializeRouteType(value.type),
|
|
165
|
+
name: value.name,
|
|
166
|
+
routes: value.routes,
|
|
167
|
+
};
|
|
168
|
+
});
|
|
188
169
|
};
|
|
189
170
|
|
|
190
171
|
export const deserializeStopsAdjacency = (
|
|
191
|
-
protoStopsAdjacency:
|
|
192
|
-
):
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
Object.entries(protoStopsAdjacency.stops).forEach(([keyStr, value]) => {
|
|
196
|
-
const key = parseInt(keyStr, 10);
|
|
197
|
-
stopsAdjacency.set(key, {
|
|
172
|
+
protoStopsAdjacency: ProtoStopAdjacency[],
|
|
173
|
+
): StopAdjacency[] => {
|
|
174
|
+
return protoStopsAdjacency.map((value) => {
|
|
175
|
+
return {
|
|
198
176
|
transfers: value.transfers.map(
|
|
199
177
|
(transfer: ProtoTransfer): Transfer => ({
|
|
200
178
|
destination: transfer.destination,
|
|
@@ -205,10 +183,8 @@ export const deserializeStopsAdjacency = (
|
|
|
205
183
|
}),
|
|
206
184
|
),
|
|
207
185
|
routes: value.routes,
|
|
208
|
-
}
|
|
186
|
+
};
|
|
209
187
|
});
|
|
210
|
-
|
|
211
|
-
return stopsAdjacency;
|
|
212
188
|
};
|
|
213
189
|
|
|
214
190
|
export const deserializeRoutesAdjacency = (
|
|
@@ -232,19 +208,15 @@ export const deserializeRoutesAdjacency = (
|
|
|
232
208
|
};
|
|
233
209
|
|
|
234
210
|
export const deserializeServiceRoutesMap = (
|
|
235
|
-
|
|
236
|
-
):
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
Object.entries(protoServiceRoutesMap.routes).forEach(([key, value]) => {
|
|
240
|
-
serviceRoutesMap.set(key, {
|
|
211
|
+
protoServiceRoutes: ProtoServiceRoute[],
|
|
212
|
+
): ServiceRoute[] => {
|
|
213
|
+
return protoServiceRoutes.map((value) => {
|
|
214
|
+
return {
|
|
241
215
|
type: parseRouteType(value.type),
|
|
242
216
|
name: value.name,
|
|
243
217
|
routes: value.routes,
|
|
244
|
-
}
|
|
218
|
+
};
|
|
245
219
|
});
|
|
246
|
-
|
|
247
|
-
return serviceRoutesMap;
|
|
248
220
|
};
|
|
249
221
|
|
|
250
222
|
const parseTransferType = (type: ProtoTransferType): TransferType => {
|
|
@@ -24,7 +24,7 @@ message Route {
|
|
|
24
24
|
* Format: [stop1, stop2, stop3, etc.]
|
|
25
25
|
*/
|
|
26
26
|
bytes stops = 3;
|
|
27
|
-
|
|
27
|
+
uint32 serviceRouteId = 4;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
enum TransferType {
|
|
@@ -40,12 +40,9 @@ message Transfer {
|
|
|
40
40
|
optional uint32 minTransferTime = 3;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
message
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
repeated int32 routes = 2;
|
|
47
|
-
}
|
|
48
|
-
map<uint32, StopAdjacency> stops = 1;
|
|
43
|
+
message StopAdjacency {
|
|
44
|
+
repeated Transfer transfers = 1;
|
|
45
|
+
repeated int32 routes = 2;
|
|
49
46
|
}
|
|
50
47
|
|
|
51
48
|
enum RouteType {
|
|
@@ -67,13 +64,9 @@ message ServiceRoute {
|
|
|
67
64
|
repeated int32 routes = 3;
|
|
68
65
|
}
|
|
69
66
|
|
|
70
|
-
message ServiceRoutesMap {
|
|
71
|
-
map<string, ServiceRoute> routes = 1;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
67
|
message Timetable {
|
|
75
68
|
string version = 1;
|
|
76
|
-
|
|
69
|
+
repeated StopAdjacency stopsAdjacency = 2;
|
|
77
70
|
repeated Route routesAdjacency = 3;
|
|
78
|
-
|
|
71
|
+
repeated ServiceRoute serviceRoutes = 4;
|
|
79
72
|
}
|