minotor 6.0.0 → 7.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 +3 -3
- package/dist/cli.mjs +94 -77
- package/dist/cli.mjs.map +1 -1
- package/dist/parser.cjs.js +75 -70
- package/dist/parser.cjs.js.map +1 -1
- package/dist/parser.esm.js +75 -70
- package/dist/parser.esm.js.map +1 -1
- package/dist/router.cjs.js +1 -1
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.esm.js +1 -1
- package/dist/router.esm.js.map +1 -1
- package/dist/router.umd.js +1 -1
- package/dist/router.umd.js.map +1 -1
- package/dist/timetable/route.d.ts +2 -11
- package/dist/timetable/timetable.d.ts +1 -1
- package/package.json +1 -1
- package/src/__e2e__/timetable/timetable.bin +1 -1
- package/src/gtfs/trips.ts +10 -4
- package/src/routing/router.ts +19 -7
- package/src/stops/stopsIndex.ts +24 -22
- package/src/timetable/__tests__/route.test.ts +0 -19
- package/src/timetable/io.ts +39 -19
- package/src/timetable/proto/timetable.proto +2 -2
- package/src/timetable/proto/timetable.ts +6 -6
- package/src/timetable/route.ts +2 -32
- package/src/timetable/timetable.ts +9 -4
|
@@ -44,7 +44,7 @@ export declare class Route {
|
|
|
44
44
|
* A binary array of stopIds in the route.
|
|
45
45
|
* [stop1, stop2, stop3,...]
|
|
46
46
|
*/
|
|
47
|
-
|
|
47
|
+
readonly stops: Uint32Array;
|
|
48
48
|
/**
|
|
49
49
|
* A reverse mapping of each stop with their index in the route:
|
|
50
50
|
* {
|
|
@@ -126,15 +126,6 @@ export declare class Route {
|
|
|
126
126
|
* @returns The drop-off type at the specified stop and trip.
|
|
127
127
|
*/
|
|
128
128
|
dropOffTypeAt(stopId: StopId, tripIndex: TripIndex): PickUpDropOffType;
|
|
129
|
-
/**
|
|
130
|
-
* Iterates over the stops in the route, starting from an optional specified stop.
|
|
131
|
-
* If no start stop is provided, the iteration begins from the first stop in the route.
|
|
132
|
-
*
|
|
133
|
-
* @param [startStopId] - (Optional) The StopId of the stop to start the iteration from.
|
|
134
|
-
* @returns An IterableIterator of StopIds, starting from the specified stop or the first stop.
|
|
135
|
-
* @throws An error if the specified start stop is not found in the route.
|
|
136
|
-
*/
|
|
137
|
-
stopsIterator(startStopId?: StopId): IterableIterator<StopId>;
|
|
138
129
|
/**
|
|
139
130
|
* Finds the earliest trip that can be taken from a specific stop on a given route,
|
|
140
131
|
* optionally constrained by a latest trip index and a time before which the trip
|
|
@@ -153,5 +144,5 @@ export declare class Route {
|
|
|
153
144
|
* @param stopId The StopId of the stop to locate in the route.
|
|
154
145
|
* @returns The index of the stop in the route.
|
|
155
146
|
*/
|
|
156
|
-
|
|
147
|
+
stopIndex(stopId: StopId): number;
|
|
157
148
|
}
|
|
@@ -20,7 +20,7 @@ export type ServiceRoute = {
|
|
|
20
20
|
};
|
|
21
21
|
export type ServiceRouteInfo = Omit<ServiceRoute, 'routes'>;
|
|
22
22
|
export declare const ALL_TRANSPORT_MODES: Set<RouteType>;
|
|
23
|
-
export declare const CURRENT_VERSION = "0.0.
|
|
23
|
+
export declare const CURRENT_VERSION = "0.0.7";
|
|
24
24
|
/**
|
|
25
25
|
* The internal transit timetable format.
|
|
26
26
|
*/
|
package/package.json
CHANGED
package/src/gtfs/trips.ts
CHANGED
|
@@ -204,8 +204,12 @@ export const buildStopsAdjacencyStructure = (
|
|
|
204
204
|
for (let i = 0; i < nbStops; i++) {
|
|
205
205
|
stopsAdjacency[i] = { routes: [], transfers: [] };
|
|
206
206
|
}
|
|
207
|
-
routes.
|
|
208
|
-
|
|
207
|
+
for (let index = 0; index < routes.length; index++) {
|
|
208
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
209
|
+
const route = routes[index]!;
|
|
210
|
+
for (let j = 0; j < route.getNbStops(); j++) {
|
|
211
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
212
|
+
const stop = route.stops[j]!;
|
|
209
213
|
if (activeStops.has(stop)) {
|
|
210
214
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
211
215
|
stopsAdjacency[stop]!.routes.push(index);
|
|
@@ -218,9 +222,11 @@ export const buildStopsAdjacencyStructure = (
|
|
|
218
222
|
);
|
|
219
223
|
}
|
|
220
224
|
serviceRoute.routes.push(index);
|
|
221
|
-
}
|
|
225
|
+
}
|
|
222
226
|
for (const [stop, transfers] of transfersMap) {
|
|
223
|
-
for (
|
|
227
|
+
for (let i = 0; i < transfers.length; i++) {
|
|
228
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
229
|
+
const transfer = transfers[i]!;
|
|
224
230
|
if (activeStops.has(stop) || activeStops.has(transfer.destination)) {
|
|
225
231
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
226
232
|
stopsAdjacency[stop]!.transfers.push(transfer);
|
package/src/routing/router.ts
CHANGED
|
@@ -56,7 +56,9 @@ export class Router {
|
|
|
56
56
|
): void {
|
|
57
57
|
const { options } = query;
|
|
58
58
|
const newlyMarkedStops: Set<StopId> = new Set();
|
|
59
|
-
|
|
59
|
+
const markedStopsArray = Array.from(markedStops);
|
|
60
|
+
for (let i = 0; i < markedStopsArray.length; i++) {
|
|
61
|
+
const stop = markedStopsArray[i]!;
|
|
60
62
|
const currentArrival = arrivalsAtCurrentRound.get(stop);
|
|
61
63
|
if (!currentArrival) continue;
|
|
62
64
|
// Skip transfers if the last leg was also a transfer
|
|
@@ -65,7 +67,9 @@ export class Router {
|
|
|
65
67
|
continue;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
const transfers = this.timetable.getTransfers(stop);
|
|
71
|
+
for (let j = 0; j < transfers.length; j++) {
|
|
72
|
+
const transfer = transfers[j]!;
|
|
69
73
|
let transferTime: Duration;
|
|
70
74
|
if (transfer.minTransferTime) {
|
|
71
75
|
transferTime = transfer.minTransferTime;
|
|
@@ -100,7 +104,9 @@ export class Router {
|
|
|
100
104
|
}
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
|
-
|
|
107
|
+
const newlyMarkedStopsArray = Array.from(newlyMarkedStops);
|
|
108
|
+
for (let i = 0; i < newlyMarkedStopsArray.length; i++) {
|
|
109
|
+
const newStop = newlyMarkedStopsArray[i]!;
|
|
104
110
|
markedStops.add(newStop);
|
|
105
111
|
}
|
|
106
112
|
}
|
|
@@ -117,7 +123,8 @@ export class Router {
|
|
|
117
123
|
destinations: Stop[],
|
|
118
124
|
): Time {
|
|
119
125
|
let earliestArrivalAtAnyDestination = UNREACHED;
|
|
120
|
-
for (
|
|
126
|
+
for (let i = 0; i < destinations.length; i++) {
|
|
127
|
+
const destination = destinations[i]!;
|
|
121
128
|
const arrival =
|
|
122
129
|
earliestArrivals.get(destination.id)?.arrival ?? UNREACHED;
|
|
123
130
|
earliestArrivalAtAnyDestination = Time.min(
|
|
@@ -149,7 +156,8 @@ export class Router {
|
|
|
149
156
|
// Stops that have been improved at round k-1
|
|
150
157
|
const markedStops = new Set<StopId>();
|
|
151
158
|
|
|
152
|
-
for (
|
|
159
|
+
for (let i = 0; i < origins.length; i++) {
|
|
160
|
+
const originStop = origins[i]!;
|
|
153
161
|
markedStops.add(originStop.id);
|
|
154
162
|
earliestArrivals.set(originStop.id, {
|
|
155
163
|
arrival: departureTime,
|
|
@@ -183,9 +191,13 @@ export class Router {
|
|
|
183
191
|
);
|
|
184
192
|
markedStops.clear();
|
|
185
193
|
// for each route that can be reached with at least round - 1 trips
|
|
186
|
-
|
|
194
|
+
const reachableRoutesArray = Array.from(reachableRoutes.entries());
|
|
195
|
+
for (let i = 0; i < reachableRoutesArray.length; i++) {
|
|
196
|
+
const [route, hopOnStop] = reachableRoutesArray[i]!;
|
|
187
197
|
let currentTrip: CurrentTrip | undefined = undefined;
|
|
188
|
-
|
|
198
|
+
const startIndex = route.stopIndex(hopOnStop);
|
|
199
|
+
for (let j = startIndex; j < route.getNbStops(); j++) {
|
|
200
|
+
const currentStop = route.stops[j]!;
|
|
189
201
|
// If we're currently on a trip,
|
|
190
202
|
// check if arrival at the stop improves the earliest arrival time
|
|
191
203
|
if (currentTrip !== undefined) {
|
package/src/stops/stopsIndex.ts
CHANGED
|
@@ -25,17 +25,14 @@ export class StopsIndex {
|
|
|
25
25
|
constructor(stops: Stop[]) {
|
|
26
26
|
this.stops = stops;
|
|
27
27
|
this.sourceStopsMap = new Map<SourceStopId, StopId>();
|
|
28
|
-
stops.forEach((stop, id) => {
|
|
29
|
-
this.sourceStopsMap.set(stop.sourceStopId, id);
|
|
30
|
-
});
|
|
31
|
-
this.textIndex = createIndex({
|
|
32
|
-
fields: ['name'],
|
|
33
|
-
storeFields: ['id'],
|
|
34
|
-
searchOptions: { prefix: true, fuzzy: 0.2 },
|
|
35
|
-
processTerm: generateAccentVariants,
|
|
36
|
-
});
|
|
37
28
|
const stopsSet = new Map<StopId, { id: StopId; name: string }>();
|
|
38
|
-
|
|
29
|
+
this.stopPoints = [];
|
|
30
|
+
for (let id = 0; id < stops.length; id++) {
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
32
|
+
const stop = stops[id]!;
|
|
33
|
+
|
|
34
|
+
this.sourceStopsMap.set(stop.sourceStopId, id);
|
|
35
|
+
|
|
39
36
|
const effectiveStopId = stop.parent ?? id;
|
|
40
37
|
if (!stopsSet.has(effectiveStopId)) {
|
|
41
38
|
stopsSet.set(effectiveStopId, {
|
|
@@ -44,22 +41,27 @@ export class StopsIndex {
|
|
|
44
41
|
name: stop.parent ? this.stops[stop.parent]!.name : stop.name,
|
|
45
42
|
});
|
|
46
43
|
}
|
|
44
|
+
|
|
45
|
+
if (stop.lat && stop.lon) {
|
|
46
|
+
this.stopPoints.push({
|
|
47
|
+
id: id,
|
|
48
|
+
lat: stop.lat,
|
|
49
|
+
lon: stop.lon,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
this.textIndex = createIndex({
|
|
54
|
+
fields: ['name'],
|
|
55
|
+
storeFields: ['id'],
|
|
56
|
+
searchOptions: { prefix: true, fuzzy: 0.2 },
|
|
57
|
+
processTerm: generateAccentVariants,
|
|
47
58
|
});
|
|
48
59
|
const stopsArray = Array.from(stopsSet.values());
|
|
49
60
|
addAll(this.textIndex, stopsArray);
|
|
50
|
-
|
|
51
|
-
this.stopPoints = this.stops
|
|
52
|
-
.filter((stop) => {
|
|
53
|
-
if (stop.lat && stop.lon) return true;
|
|
54
|
-
return false;
|
|
55
|
-
})
|
|
56
|
-
.map((stop, id) => ({
|
|
57
|
-
id: id,
|
|
58
|
-
lat: stop.lat as number,
|
|
59
|
-
lon: stop.lon as number,
|
|
60
|
-
}));
|
|
61
61
|
this.geoIndex = new KDTree(this.stopPoints.length);
|
|
62
|
-
for (
|
|
62
|
+
for (let i = 0; i < this.stopPoints.length; i++) {
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
64
|
+
const { lat, lon } = this.stopPoints[i]!;
|
|
63
65
|
this.geoIndex.add(lon, lat);
|
|
64
66
|
}
|
|
65
67
|
this.geoIndex.finish();
|
|
@@ -249,25 +249,6 @@ describe('Route', () => {
|
|
|
249
249
|
});
|
|
250
250
|
});
|
|
251
251
|
|
|
252
|
-
describe('stopsIterator', () => {
|
|
253
|
-
it('should iterate over all stops when no start stop is provided', () => {
|
|
254
|
-
const stopsList = Array.from(route.stopsIterator());
|
|
255
|
-
assert.deepStrictEqual(stopsList, [1001, 1002]);
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it('should iterate from specified start stop', () => {
|
|
259
|
-
const stopsList = Array.from(route.stopsIterator(1002));
|
|
260
|
-
assert.deepStrictEqual(stopsList, [1002]);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it('should throw error for invalid start stop ID', () => {
|
|
264
|
-
assert.throws(
|
|
265
|
-
() => Array.from(route.stopsIterator(9999)),
|
|
266
|
-
/Start stop 9999 not found in route 0/,
|
|
267
|
-
);
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
|
|
271
252
|
describe('findEarliestTrip', () => {
|
|
272
253
|
it('should find earliest trip without time constraint', () => {
|
|
273
254
|
const tripIndex = route.findEarliestTrip(1001);
|
package/src/timetable/io.ts
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
RouteType as ProtoRouteType,
|
|
5
5
|
ServiceRoute as ProtoServiceRoute,
|
|
6
6
|
StopAdjacency as ProtoStopAdjacency,
|
|
7
|
-
Transfer as ProtoTransfer,
|
|
8
7
|
TransferType as ProtoTransferType,
|
|
9
8
|
} from './proto/timetable.js';
|
|
10
9
|
import { Route } from './route.js';
|
|
@@ -171,20 +170,33 @@ export const serializeServiceRoutesMap = (
|
|
|
171
170
|
export const deserializeStopsAdjacency = (
|
|
172
171
|
protoStopsAdjacency: ProtoStopAdjacency[],
|
|
173
172
|
): StopAdjacency[] => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
173
|
+
const result: StopAdjacency[] = [];
|
|
174
|
+
|
|
175
|
+
for (let i = 0; i < protoStopsAdjacency.length; i++) {
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
177
|
+
const value = protoStopsAdjacency[i]!;
|
|
178
|
+
const transfers: Transfer[] = [];
|
|
179
|
+
|
|
180
|
+
for (let j = 0; j < value.transfers.length; j++) {
|
|
181
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
182
|
+
const transfer = value.transfers[j]!;
|
|
183
|
+
const newTransfer: Transfer = {
|
|
184
|
+
destination: transfer.destination,
|
|
185
|
+
type: parseTransferType(transfer.type),
|
|
186
|
+
...(transfer.minTransferTime !== undefined && {
|
|
187
|
+
minTransferTime: Duration.fromSeconds(transfer.minTransferTime),
|
|
183
188
|
}),
|
|
184
|
-
|
|
189
|
+
};
|
|
190
|
+
transfers.push(newTransfer);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
result.push({
|
|
194
|
+
transfers: transfers,
|
|
185
195
|
routes: value.routes,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return result;
|
|
188
200
|
};
|
|
189
201
|
|
|
190
202
|
export const deserializeRoutesAdjacency = (
|
|
@@ -192,7 +204,9 @@ export const deserializeRoutesAdjacency = (
|
|
|
192
204
|
): Route[] => {
|
|
193
205
|
const routesAdjacency: Route[] = [];
|
|
194
206
|
|
|
195
|
-
protoRoutesAdjacency.
|
|
207
|
+
for (let i = 0; i < protoRoutesAdjacency.length; i++) {
|
|
208
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
209
|
+
const value = protoRoutesAdjacency[i]!;
|
|
196
210
|
const stops = bytesToUint32Array(value.stops);
|
|
197
211
|
routesAdjacency.push(
|
|
198
212
|
new Route(
|
|
@@ -202,7 +216,7 @@ export const deserializeRoutesAdjacency = (
|
|
|
202
216
|
value.serviceRouteId,
|
|
203
217
|
),
|
|
204
218
|
);
|
|
205
|
-
}
|
|
219
|
+
}
|
|
206
220
|
|
|
207
221
|
return routesAdjacency;
|
|
208
222
|
};
|
|
@@ -210,13 +224,19 @@ export const deserializeRoutesAdjacency = (
|
|
|
210
224
|
export const deserializeServiceRoutesMap = (
|
|
211
225
|
protoServiceRoutes: ProtoServiceRoute[],
|
|
212
226
|
): ServiceRoute[] => {
|
|
213
|
-
|
|
214
|
-
|
|
227
|
+
const result: ServiceRoute[] = [];
|
|
228
|
+
|
|
229
|
+
for (let i = 0; i < protoServiceRoutes.length; i++) {
|
|
230
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
231
|
+
const value = protoServiceRoutes[i]!;
|
|
232
|
+
result.push({
|
|
215
233
|
type: parseRouteType(value.type),
|
|
216
234
|
name: value.name,
|
|
217
235
|
routes: value.routes,
|
|
218
|
-
};
|
|
219
|
-
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return result;
|
|
220
240
|
};
|
|
221
241
|
|
|
222
242
|
const parseTransferType = (type: ProtoTransferType): TransferType => {
|
|
@@ -42,7 +42,7 @@ message Transfer {
|
|
|
42
42
|
|
|
43
43
|
message StopAdjacency {
|
|
44
44
|
repeated Transfer transfers = 1;
|
|
45
|
-
repeated
|
|
45
|
+
repeated uint32 routes = 2;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
enum RouteType {
|
|
@@ -61,7 +61,7 @@ enum RouteType {
|
|
|
61
61
|
message ServiceRoute {
|
|
62
62
|
RouteType type = 1;
|
|
63
63
|
string name = 2;
|
|
64
|
-
repeated
|
|
64
|
+
repeated uint32 routes = 3;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
message Timetable {
|
|
@@ -402,7 +402,7 @@ export const StopAdjacency: MessageFns<StopAdjacency> = {
|
|
|
402
402
|
}
|
|
403
403
|
writer.uint32(18).fork();
|
|
404
404
|
for (const v of message.routes) {
|
|
405
|
-
writer.
|
|
405
|
+
writer.uint32(v);
|
|
406
406
|
}
|
|
407
407
|
writer.join();
|
|
408
408
|
return writer;
|
|
@@ -425,7 +425,7 @@ export const StopAdjacency: MessageFns<StopAdjacency> = {
|
|
|
425
425
|
}
|
|
426
426
|
case 2: {
|
|
427
427
|
if (tag === 16) {
|
|
428
|
-
message.routes.push(reader.
|
|
428
|
+
message.routes.push(reader.uint32());
|
|
429
429
|
|
|
430
430
|
continue;
|
|
431
431
|
}
|
|
@@ -433,7 +433,7 @@ export const StopAdjacency: MessageFns<StopAdjacency> = {
|
|
|
433
433
|
if (tag === 18) {
|
|
434
434
|
const end2 = reader.uint32() + reader.pos;
|
|
435
435
|
while (reader.pos < end2) {
|
|
436
|
-
message.routes.push(reader.
|
|
436
|
+
message.routes.push(reader.uint32());
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
continue;
|
|
@@ -495,7 +495,7 @@ export const ServiceRoute: MessageFns<ServiceRoute> = {
|
|
|
495
495
|
}
|
|
496
496
|
writer.uint32(26).fork();
|
|
497
497
|
for (const v of message.routes) {
|
|
498
|
-
writer.
|
|
498
|
+
writer.uint32(v);
|
|
499
499
|
}
|
|
500
500
|
writer.join();
|
|
501
501
|
return writer;
|
|
@@ -526,7 +526,7 @@ export const ServiceRoute: MessageFns<ServiceRoute> = {
|
|
|
526
526
|
}
|
|
527
527
|
case 3: {
|
|
528
528
|
if (tag === 24) {
|
|
529
|
-
message.routes.push(reader.
|
|
529
|
+
message.routes.push(reader.uint32());
|
|
530
530
|
|
|
531
531
|
continue;
|
|
532
532
|
}
|
|
@@ -534,7 +534,7 @@ export const ServiceRoute: MessageFns<ServiceRoute> = {
|
|
|
534
534
|
if (tag === 26) {
|
|
535
535
|
const end2 = reader.uint32() + reader.pos;
|
|
536
536
|
while (reader.pos < end2) {
|
|
537
|
-
message.routes.push(reader.
|
|
537
|
+
message.routes.push(reader.uint32());
|
|
538
538
|
}
|
|
539
539
|
|
|
540
540
|
continue;
|
package/src/timetable/route.ts
CHANGED
|
@@ -81,7 +81,7 @@ export class Route {
|
|
|
81
81
|
* A binary array of stopIds in the route.
|
|
82
82
|
* [stop1, stop2, stop3,...]
|
|
83
83
|
*/
|
|
84
|
-
|
|
84
|
+
public readonly stops: Uint32Array;
|
|
85
85
|
/**
|
|
86
86
|
* A reverse mapping of each stop with their index in the route:
|
|
87
87
|
* {
|
|
@@ -269,36 +269,6 @@ export class Route {
|
|
|
269
269
|
return toPickupDropOffType(dropOffValue);
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
/**
|
|
273
|
-
* Iterates over the stops in the route, starting from an optional specified stop.
|
|
274
|
-
* If no start stop is provided, the iteration begins from the first stop in the route.
|
|
275
|
-
*
|
|
276
|
-
* @param [startStopId] - (Optional) The StopId of the stop to start the iteration from.
|
|
277
|
-
* @returns An IterableIterator of StopIds, starting from the specified stop or the first stop.
|
|
278
|
-
* @throws An error if the specified start stop is not found in the route.
|
|
279
|
-
*/
|
|
280
|
-
stopsIterator(startStopId?: StopId): IterableIterator<StopId> {
|
|
281
|
-
const startIndex =
|
|
282
|
-
startStopId !== undefined ? this.stopIndices.get(startStopId) : 0;
|
|
283
|
-
if (startIndex === undefined) {
|
|
284
|
-
throw new Error(
|
|
285
|
-
`Start stop ${startStopId} not found in route ${this.serviceRouteId}`,
|
|
286
|
-
);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function* generator(
|
|
290
|
-
stops: Uint32Array,
|
|
291
|
-
startIndex: number,
|
|
292
|
-
): IterableIterator<StopId> {
|
|
293
|
-
for (let i = startIndex; i < stops.length; i++) {
|
|
294
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
295
|
-
yield stops[i]!;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return generator(this.stops, startIndex);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
272
|
/**
|
|
303
273
|
* Finds the earliest trip that can be taken from a specific stop on a given route,
|
|
304
274
|
* optionally constrained by a latest trip index and a time before which the trip
|
|
@@ -349,7 +319,7 @@ export class Route {
|
|
|
349
319
|
* @param stopId The StopId of the stop to locate in the route.
|
|
350
320
|
* @returns The index of the stop in the route.
|
|
351
321
|
*/
|
|
352
|
-
|
|
322
|
+
public stopIndex(stopId: StopId): number {
|
|
353
323
|
const stopIndex = this.stopIndices.get(stopId);
|
|
354
324
|
if (stopIndex === undefined) {
|
|
355
325
|
throw new Error(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
1
2
|
import { BinaryReader, BinaryWriter } from '@bufbuild/protobuf/wire';
|
|
2
3
|
|
|
3
4
|
import { StopId } from '../stops/stops.js';
|
|
@@ -67,7 +68,7 @@ export const ALL_TRANSPORT_MODES: Set<RouteType> = new Set([
|
|
|
67
68
|
'MONORAIL',
|
|
68
69
|
]);
|
|
69
70
|
|
|
70
|
-
export const CURRENT_VERSION = '0.0.
|
|
71
|
+
export const CURRENT_VERSION = '0.0.7';
|
|
71
72
|
|
|
72
73
|
/**
|
|
73
74
|
* The internal transit timetable format.
|
|
@@ -200,7 +201,8 @@ export class Timetable {
|
|
|
200
201
|
return [];
|
|
201
202
|
}
|
|
202
203
|
const routes: Route[] = [];
|
|
203
|
-
for (
|
|
204
|
+
for (let i = 0; i < stopData.routes.length; i++) {
|
|
205
|
+
const routeId = stopData.routes[i]!;
|
|
204
206
|
const route = this.routesAdjacency[routeId];
|
|
205
207
|
if (route) {
|
|
206
208
|
routes.push(route);
|
|
@@ -223,14 +225,17 @@ export class Timetable {
|
|
|
223
225
|
transportModes: Set<RouteType> = ALL_TRANSPORT_MODES,
|
|
224
226
|
): Map<Route, StopId> {
|
|
225
227
|
const reachableRoutes = new Map<Route, StopId>();
|
|
226
|
-
|
|
228
|
+
const fromStopsArray = Array.from(fromStops);
|
|
229
|
+
for (let i = 0; i < fromStopsArray.length; i++) {
|
|
230
|
+
const originStop = fromStopsArray[i]!;
|
|
227
231
|
const validRoutes = this.routesPassingThrough(originStop).filter(
|
|
228
232
|
(route) => {
|
|
229
233
|
const serviceRoute = this.getServiceRouteInfo(route);
|
|
230
234
|
return transportModes.has(serviceRoute.type);
|
|
231
235
|
},
|
|
232
236
|
);
|
|
233
|
-
for (
|
|
237
|
+
for (let j = 0; j < validRoutes.length; j++) {
|
|
238
|
+
const route = validRoutes[j]!;
|
|
234
239
|
const hopOnStop = reachableRoutes.get(route);
|
|
235
240
|
if (hopOnStop) {
|
|
236
241
|
if (route.isBefore(originStop, hopOnStop)) {
|