minotor 5.0.1 → 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.
Files changed (58) hide show
  1. package/CHANGELOG.md +8 -3
  2. package/dist/cli.mjs +282 -654
  3. package/dist/cli.mjs.map +1 -1
  4. package/dist/gtfs/parser.d.ts +4 -10
  5. package/dist/gtfs/routes.d.ts +16 -2
  6. package/dist/gtfs/stops.d.ts +3 -13
  7. package/dist/gtfs/transfers.d.ts +2 -2
  8. package/dist/gtfs/trips.d.ts +12 -8
  9. package/dist/parser.cjs.js +257 -644
  10. package/dist/parser.cjs.js.map +1 -1
  11. package/dist/parser.esm.js +257 -644
  12. package/dist/parser.esm.js.map +1 -1
  13. package/dist/router.cjs.js +1 -1
  14. package/dist/router.cjs.js.map +1 -1
  15. package/dist/router.esm.js +1 -1
  16. package/dist/router.esm.js.map +1 -1
  17. package/dist/router.umd.js +1 -1
  18. package/dist/router.umd.js.map +1 -1
  19. package/dist/stops/io.d.ts +3 -3
  20. package/dist/stops/proto/stops.d.ts +1 -8
  21. package/dist/stops/stops.d.ts +0 -4
  22. package/dist/stops/stopsIndex.d.ts +3 -3
  23. package/dist/timetable/io.d.ts +6 -6
  24. package/dist/timetable/proto/timetable.d.ts +5 -27
  25. package/dist/timetable/route.d.ts +2 -11
  26. package/dist/timetable/timetable.d.ts +17 -9
  27. package/package.json +1 -1
  28. package/src/__e2e__/timetable/stops.bin +2 -2
  29. package/src/__e2e__/timetable/timetable.bin +2 -2
  30. package/src/cli/minotor.ts +3 -4
  31. package/src/gtfs/__tests__/parser.test.ts +5 -6
  32. package/src/gtfs/__tests__/routes.test.ts +0 -3
  33. package/src/gtfs/__tests__/stops.test.ts +1 -124
  34. package/src/gtfs/__tests__/transfers.test.ts +7 -7
  35. package/src/gtfs/__tests__/trips.test.ts +74 -45
  36. package/src/gtfs/parser.ts +32 -49
  37. package/src/gtfs/routes.ts +43 -5
  38. package/src/gtfs/stops.ts +2 -44
  39. package/src/gtfs/transfers.ts +2 -2
  40. package/src/gtfs/trips.ts +66 -43
  41. package/src/routing/__tests__/result.test.ts +48 -48
  42. package/src/routing/__tests__/router.test.ts +279 -363
  43. package/src/routing/router.ts +22 -8
  44. package/src/stops/__tests__/io.test.ts +25 -31
  45. package/src/stops/__tests__/stopFinder.test.ts +82 -103
  46. package/src/stops/io.ts +8 -17
  47. package/src/stops/proto/stops.proto +3 -3
  48. package/src/stops/proto/stops.ts +16 -120
  49. package/src/stops/stops.ts +0 -4
  50. package/src/stops/stopsIndex.ts +37 -41
  51. package/src/timetable/__tests__/io.test.ts +44 -54
  52. package/src/timetable/__tests__/route.test.ts +10 -29
  53. package/src/timetable/__tests__/timetable.test.ts +29 -37
  54. package/src/timetable/io.ts +66 -74
  55. package/src/timetable/proto/timetable.proto +7 -14
  56. package/src/timetable/proto/timetable.ts +49 -391
  57. package/src/timetable/route.ts +2 -32
  58. package/src/timetable/timetable.ts +51 -31
package/dist/cli.mjs CHANGED
@@ -15771,10 +15771,10 @@ const Stop = {
15771
15771
  writer.uint32(18).string(message.sourceStopId);
15772
15772
  }
15773
15773
  if (message.lat !== undefined) {
15774
- writer.uint32(25).double(message.lat);
15774
+ writer.uint32(29).float(message.lat);
15775
15775
  }
15776
15776
  if (message.lon !== undefined) {
15777
- writer.uint32(33).double(message.lon);
15777
+ writer.uint32(37).float(message.lon);
15778
15778
  }
15779
15779
  writer.uint32(42).fork();
15780
15780
  for (const v of message.children) {
@@ -15814,17 +15814,17 @@ const Stop = {
15814
15814
  continue;
15815
15815
  }
15816
15816
  case 3: {
15817
- if (tag !== 25) {
15817
+ if (tag !== 29) {
15818
15818
  break;
15819
15819
  }
15820
- message.lat = reader.double();
15820
+ message.lat = reader.float();
15821
15821
  continue;
15822
15822
  }
15823
15823
  case 4: {
15824
- if (tag !== 33) {
15824
+ if (tag !== 37) {
15825
15825
  break;
15826
15826
  }
15827
- message.lon = reader.double();
15827
+ message.lon = reader.float();
15828
15828
  continue;
15829
15829
  }
15830
15830
  case 5: {
@@ -15929,16 +15929,16 @@ const Stop = {
15929
15929
  },
15930
15930
  };
15931
15931
  function createBaseStopsMap() {
15932
- return { version: "", stops: {} };
15932
+ return { version: "", stops: [] };
15933
15933
  }
15934
15934
  const StopsMap = {
15935
15935
  encode(message, writer = new BinaryWriter()) {
15936
15936
  if (message.version !== "") {
15937
15937
  writer.uint32(10).string(message.version);
15938
15938
  }
15939
- Object.entries(message.stops).forEach(([key, value]) => {
15940
- StopsMap_StopsEntry.encode({ key: key, value }, writer.uint32(18).fork()).join();
15941
- });
15939
+ for (const v of message.stops) {
15940
+ Stop.encode(v, writer.uint32(18).fork()).join();
15941
+ }
15942
15942
  return writer;
15943
15943
  },
15944
15944
  decode(input, length) {
@@ -15959,10 +15959,7 @@ const StopsMap = {
15959
15959
  if (tag !== 18) {
15960
15960
  break;
15961
15961
  }
15962
- const entry2 = StopsMap_StopsEntry.decode(reader, reader.uint32());
15963
- if (entry2.value !== undefined) {
15964
- message.stops[entry2.key] = entry2.value;
15965
- }
15962
+ message.stops.push(Stop.decode(reader, reader.uint32()));
15966
15963
  continue;
15967
15964
  }
15968
15965
  }
@@ -15976,27 +15973,17 @@ const StopsMap = {
15976
15973
  fromJSON(object) {
15977
15974
  return {
15978
15975
  version: isSet$1(object.version) ? globalThis.String(object.version) : "",
15979
- stops: isObject$1(object.stops)
15980
- ? Object.entries(object.stops).reduce((acc, [key, value]) => {
15981
- acc[globalThis.Number(key)] = Stop.fromJSON(value);
15982
- return acc;
15983
- }, {})
15984
- : {},
15976
+ stops: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.stops) ? object.stops.map((e) => Stop.fromJSON(e)) : [],
15985
15977
  };
15986
15978
  },
15987
15979
  toJSON(message) {
15980
+ var _a;
15988
15981
  const obj = {};
15989
15982
  if (message.version !== "") {
15990
15983
  obj.version = message.version;
15991
15984
  }
15992
- if (message.stops) {
15993
- const entries = Object.entries(message.stops);
15994
- if (entries.length > 0) {
15995
- obj.stops = {};
15996
- entries.forEach(([k, v]) => {
15997
- obj.stops[k] = Stop.toJSON(v);
15998
- });
15999
- }
15985
+ if ((_a = message.stops) === null || _a === void 0 ? void 0 : _a.length) {
15986
+ obj.stops = message.stops.map((e) => Stop.toJSON(e));
16000
15987
  }
16001
15988
  return obj;
16002
15989
  },
@@ -16007,92 +15994,15 @@ const StopsMap = {
16007
15994
  var _a, _b;
16008
15995
  const message = createBaseStopsMap();
16009
15996
  message.version = (_a = object.version) !== null && _a !== void 0 ? _a : "";
16010
- message.stops = Object.entries((_b = object.stops) !== null && _b !== void 0 ? _b : {}).reduce((acc, [key, value]) => {
16011
- if (value !== undefined) {
16012
- acc[globalThis.Number(key)] = Stop.fromPartial(value);
16013
- }
16014
- return acc;
16015
- }, {});
15997
+ message.stops = ((_b = object.stops) === null || _b === void 0 ? void 0 : _b.map((e) => Stop.fromPartial(e))) || [];
16016
15998
  return message;
16017
15999
  },
16018
16000
  };
16019
- function createBaseStopsMap_StopsEntry() {
16020
- return { key: 0, value: undefined };
16021
- }
16022
- const StopsMap_StopsEntry = {
16023
- encode(message, writer = new BinaryWriter()) {
16024
- if (message.key !== 0) {
16025
- writer.uint32(8).uint32(message.key);
16026
- }
16027
- if (message.value !== undefined) {
16028
- Stop.encode(message.value, writer.uint32(18).fork()).join();
16029
- }
16030
- return writer;
16031
- },
16032
- decode(input, length) {
16033
- const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
16034
- const end = length === undefined ? reader.len : reader.pos + length;
16035
- const message = createBaseStopsMap_StopsEntry();
16036
- while (reader.pos < end) {
16037
- const tag = reader.uint32();
16038
- switch (tag >>> 3) {
16039
- case 1: {
16040
- if (tag !== 8) {
16041
- break;
16042
- }
16043
- message.key = reader.uint32();
16044
- continue;
16045
- }
16046
- case 2: {
16047
- if (tag !== 18) {
16048
- break;
16049
- }
16050
- message.value = Stop.decode(reader, reader.uint32());
16051
- continue;
16052
- }
16053
- }
16054
- if ((tag & 7) === 4 || tag === 0) {
16055
- break;
16056
- }
16057
- reader.skip(tag & 7);
16058
- }
16059
- return message;
16060
- },
16061
- fromJSON(object) {
16062
- return {
16063
- key: isSet$1(object.key) ? globalThis.Number(object.key) : 0,
16064
- value: isSet$1(object.value) ? Stop.fromJSON(object.value) : undefined,
16065
- };
16066
- },
16067
- toJSON(message) {
16068
- const obj = {};
16069
- if (message.key !== 0) {
16070
- obj.key = Math.round(message.key);
16071
- }
16072
- if (message.value !== undefined) {
16073
- obj.value = Stop.toJSON(message.value);
16074
- }
16075
- return obj;
16076
- },
16077
- create(base) {
16078
- return StopsMap_StopsEntry.fromPartial(base !== null && base !== void 0 ? base : {});
16079
- },
16080
- fromPartial(object) {
16081
- var _a;
16082
- const message = createBaseStopsMap_StopsEntry();
16083
- message.key = (_a = object.key) !== null && _a !== void 0 ? _a : 0;
16084
- message.value = (object.value !== undefined && object.value !== null) ? Stop.fromPartial(object.value) : undefined;
16085
- return message;
16086
- },
16087
- };
16088
- function isObject$1(value) {
16089
- return typeof value === "object" && value !== null;
16090
- }
16091
16001
  function isSet$1(value) {
16092
16002
  return value !== null && value !== undefined;
16093
16003
  }
16094
16004
 
16095
- const CURRENT_VERSION$1 = '0.0.2';
16005
+ const CURRENT_VERSION$1 = '0.0.3';
16096
16006
  const serializeStop = (stop) => {
16097
16007
  return {
16098
16008
  name: stop.name,
@@ -16105,14 +16015,11 @@ const serializeStop = (stop) => {
16105
16015
  platform: stop.platform,
16106
16016
  };
16107
16017
  };
16108
- const serializeStopsMap = (stopsMap) => {
16018
+ const serializeStopsMap = (stops) => {
16109
16019
  const protoStopsMap = {
16110
16020
  version: CURRENT_VERSION$1,
16111
- stops: {},
16021
+ stops: stops.map((value) => serializeStop(value)),
16112
16022
  };
16113
- stopsMap.forEach((value, key) => {
16114
- protoStopsMap.stops[key] = serializeStop(value);
16115
- });
16116
16023
  return protoStopsMap;
16117
16024
  };
16118
16025
  const deserializeStop = (stopId, protoStop) => {
@@ -16132,12 +16039,7 @@ const deserializeStopsMap = (protoStopsMap) => {
16132
16039
  if (protoStopsMap.version !== CURRENT_VERSION$1) {
16133
16040
  throw new Error(`Unsupported stopMap version ${protoStopsMap.version}`);
16134
16041
  }
16135
- const stopsMap = new Map();
16136
- Object.entries(protoStopsMap.stops).forEach(([key, value]) => {
16137
- const intKey = parseInt(key, 10);
16138
- stopsMap.set(intKey, deserializeStop(intKey, value));
16139
- });
16140
- return stopsMap;
16042
+ return protoStopsMap.stops.map((value, intKey) => deserializeStop(intKey, value));
16141
16043
  };
16142
16044
  const parseProtoLocationType = (protoLocationType) => {
16143
16045
  switch (protoLocationType) {
@@ -16176,45 +16078,44 @@ const serializeLocationType = (locationType) => {
16176
16078
  * to efficiently find stops based on user queries.
16177
16079
  */
16178
16080
  class StopsIndex {
16179
- constructor(stopsMap) {
16081
+ constructor(stops) {
16180
16082
  var _a;
16181
- this.stopsMap = stopsMap;
16083
+ this.stops = stops;
16182
16084
  this.sourceStopsMap = new Map();
16183
- for (const [id, stop] of stopsMap.entries()) {
16184
- this.sourceStopsMap.set(stop.sourceStopId, id);
16185
- }
16186
- this.textIndex = lt({
16187
- fields: ['name'],
16188
- storeFields: ['id'],
16189
- searchOptions: { prefix: true, fuzzy: 0.2 },
16190
- processTerm: generateAccentVariants,
16191
- });
16192
16085
  const stopsSet = new Map();
16193
- for (const [id, stop] of stopsMap.entries()) {
16086
+ this.stopPoints = [];
16087
+ for (let id = 0; id < stops.length; id++) {
16088
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
16089
+ const stop = stops[id];
16090
+ this.sourceStopsMap.set(stop.sourceStopId, id);
16194
16091
  const effectiveStopId = (_a = stop.parent) !== null && _a !== void 0 ? _a : id;
16195
16092
  if (!stopsSet.has(effectiveStopId)) {
16196
16093
  stopsSet.set(effectiveStopId, {
16197
16094
  id: effectiveStopId,
16198
16095
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
16199
- name: stop.parent ? this.stopsMap.get(stop.parent).name : stop.name,
16096
+ name: stop.parent ? this.stops[stop.parent].name : stop.name,
16097
+ });
16098
+ }
16099
+ if (stop.lat && stop.lon) {
16100
+ this.stopPoints.push({
16101
+ id: id,
16102
+ lat: stop.lat,
16103
+ lon: stop.lon,
16200
16104
  });
16201
16105
  }
16202
16106
  }
16107
+ this.textIndex = lt({
16108
+ fields: ['name'],
16109
+ storeFields: ['id'],
16110
+ searchOptions: { prefix: true, fuzzy: 0.2 },
16111
+ processTerm: generateAccentVariants,
16112
+ });
16203
16113
  const stopsArray = Array.from(stopsSet.values());
16204
16114
  q(this.textIndex, stopsArray);
16205
- this.stopPoints = Array.from(this.stopsMap.entries())
16206
- .filter(([, stop]) => {
16207
- if (stop.lat && stop.lon)
16208
- return true;
16209
- return false;
16210
- })
16211
- .map(([id, stop]) => ({
16212
- id: id,
16213
- lat: stop.lat,
16214
- lon: stop.lon,
16215
- }));
16216
16115
  this.geoIndex = new KDBush(this.stopPoints.length);
16217
- for (const { lat, lon } of this.stopPoints) {
16116
+ for (let i = 0; i < this.stopPoints.length; i++) {
16117
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
16118
+ const { lat, lon } = this.stopPoints[i];
16218
16119
  this.geoIndex.add(lon, lat);
16219
16120
  }
16220
16121
  this.geoIndex.finish();
@@ -16236,7 +16137,7 @@ class StopsIndex {
16236
16137
  * @returns The serialized binary data.
16237
16138
  */
16238
16139
  serialize() {
16239
- const protoStopsMap = serializeStopsMap(this.stopsMap);
16140
+ const protoStopsMap = serializeStopsMap(this.stops);
16240
16141
  const writer = new BinaryWriter();
16241
16142
  StopsMap.encode(protoStopsMap, writer);
16242
16143
  return writer.finish();
@@ -16247,7 +16148,7 @@ class StopsIndex {
16247
16148
  * @returns The total number of stops.
16248
16149
  */
16249
16150
  size() {
16250
- return this.stopsMap.size;
16151
+ return this.stops.length;
16251
16152
  }
16252
16153
  /**
16253
16154
  * Finds stops by their name using a text search.
@@ -16257,7 +16158,7 @@ class StopsIndex {
16257
16158
  * @returns An array of Stop objects that match the search query.
16258
16159
  */
16259
16160
  findStopsByName(query, maxResults = 5) {
16260
- const results = dt(this.textIndex, query).map((result) => this.stopsMap.get(result.id));
16161
+ const results = dt(this.textIndex, query).map((result) => this.stops[result.id]);
16261
16162
  return results.slice(0, maxResults);
16262
16163
  }
16263
16164
  /**
@@ -16272,7 +16173,7 @@ class StopsIndex {
16272
16173
  findStopsByLocation(lat, lon, maxResults = 5, radius = 0.5) {
16273
16174
  const nearestStops = around(this.geoIndex, lon, lat, maxResults, radius).map((id) => {
16274
16175
  const stopPoint = this.stopPoints[id];
16275
- return this.stopsMap.get(stopPoint.id);
16176
+ return this.stops[stopPoint.id];
16276
16177
  });
16277
16178
  return nearestStops;
16278
16179
  }
@@ -16283,7 +16184,7 @@ class StopsIndex {
16283
16184
  * @returns The Stop object that matches the specified ID, or undefined if not found.
16284
16185
  */
16285
16186
  findStopById(id) {
16286
- return this.stopsMap.get(id);
16187
+ return this.stops[id];
16287
16188
  }
16288
16189
  /**
16289
16190
  * Finds a stop by its ID in the transit data source (e.g. GTFS).
@@ -16307,14 +16208,14 @@ class StopsIndex {
16307
16208
  if (id === undefined) {
16308
16209
  return [];
16309
16210
  }
16310
- const stop = this.stopsMap.get(id);
16211
+ const stop = this.stops[id];
16311
16212
  if (!stop) {
16312
16213
  return [];
16313
16214
  }
16314
16215
  const equivalentStops = stop.parent
16315
- ? ((_b = (_a = this.stopsMap.get(stop.parent)) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : [])
16216
+ ? ((_b = (_a = this.stops[stop.parent]) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : [])
16316
16217
  : stop.children;
16317
- return Array.from(new Set([id, ...equivalentStops])).map((stopId) => this.stopsMap.get(stopId));
16218
+ return Array.from(new Set([id, ...equivalentStops])).map((stopId) => this.stops[stopId]);
16318
16219
  }
16319
16220
  }
16320
16221
 
@@ -16532,7 +16433,7 @@ function createBaseRoute() {
16532
16433
  stopTimes: new Uint8Array(0),
16533
16434
  pickUpDropOffTypes: new Uint8Array(0),
16534
16435
  stops: new Uint8Array(0),
16535
- serviceRouteId: "",
16436
+ serviceRouteId: 0,
16536
16437
  };
16537
16438
  }
16538
16439
  const Route$2 = {
@@ -16546,8 +16447,8 @@ const Route$2 = {
16546
16447
  if (message.stops.length !== 0) {
16547
16448
  writer.uint32(26).bytes(message.stops);
16548
16449
  }
16549
- if (message.serviceRouteId !== "") {
16550
- writer.uint32(34).string(message.serviceRouteId);
16450
+ if (message.serviceRouteId !== 0) {
16451
+ writer.uint32(32).uint32(message.serviceRouteId);
16551
16452
  }
16552
16453
  return writer;
16553
16454
  },
@@ -16580,10 +16481,10 @@ const Route$2 = {
16580
16481
  continue;
16581
16482
  }
16582
16483
  case 4: {
16583
- if (tag !== 34) {
16484
+ if (tag !== 32) {
16584
16485
  break;
16585
16486
  }
16586
- message.serviceRouteId = reader.string();
16487
+ message.serviceRouteId = reader.uint32();
16587
16488
  continue;
16588
16489
  }
16589
16490
  }
@@ -16601,7 +16502,7 @@ const Route$2 = {
16601
16502
  ? bytesFromBase64(object.pickUpDropOffTypes)
16602
16503
  : new Uint8Array(0),
16603
16504
  stops: isSet(object.stops) ? bytesFromBase64(object.stops) : new Uint8Array(0),
16604
- serviceRouteId: isSet(object.serviceRouteId) ? globalThis.String(object.serviceRouteId) : "",
16505
+ serviceRouteId: isSet(object.serviceRouteId) ? globalThis.Number(object.serviceRouteId) : 0,
16605
16506
  };
16606
16507
  },
16607
16508
  toJSON(message) {
@@ -16615,8 +16516,8 @@ const Route$2 = {
16615
16516
  if (message.stops.length !== 0) {
16616
16517
  obj.stops = base64FromBytes(message.stops);
16617
16518
  }
16618
- if (message.serviceRouteId !== "") {
16619
- obj.serviceRouteId = message.serviceRouteId;
16519
+ if (message.serviceRouteId !== 0) {
16520
+ obj.serviceRouteId = Math.round(message.serviceRouteId);
16620
16521
  }
16621
16522
  return obj;
16622
16523
  },
@@ -16629,7 +16530,7 @@ const Route$2 = {
16629
16530
  message.stopTimes = (_a = object.stopTimes) !== null && _a !== void 0 ? _a : new Uint8Array(0);
16630
16531
  message.pickUpDropOffTypes = (_b = object.pickUpDropOffTypes) !== null && _b !== void 0 ? _b : new Uint8Array(0);
16631
16532
  message.stops = (_c = object.stops) !== null && _c !== void 0 ? _c : new Uint8Array(0);
16632
- message.serviceRouteId = (_d = object.serviceRouteId) !== null && _d !== void 0 ? _d : "";
16533
+ message.serviceRouteId = (_d = object.serviceRouteId) !== null && _d !== void 0 ? _d : 0;
16633
16534
  return message;
16634
16535
  },
16635
16536
  };
@@ -16717,90 +16618,17 @@ const Transfer = {
16717
16618
  return message;
16718
16619
  },
16719
16620
  };
16720
- function createBaseStopsAdjacency() {
16721
- return { stops: {} };
16722
- }
16723
- const StopsAdjacency = {
16724
- encode(message, writer = new BinaryWriter()) {
16725
- Object.entries(message.stops).forEach(([key, value]) => {
16726
- StopsAdjacency_StopsEntry.encode({ key: key, value }, writer.uint32(10).fork()).join();
16727
- });
16728
- return writer;
16729
- },
16730
- decode(input, length) {
16731
- const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
16732
- const end = length === undefined ? reader.len : reader.pos + length;
16733
- const message = createBaseStopsAdjacency();
16734
- while (reader.pos < end) {
16735
- const tag = reader.uint32();
16736
- switch (tag >>> 3) {
16737
- case 1: {
16738
- if (tag !== 10) {
16739
- break;
16740
- }
16741
- const entry1 = StopsAdjacency_StopsEntry.decode(reader, reader.uint32());
16742
- if (entry1.value !== undefined) {
16743
- message.stops[entry1.key] = entry1.value;
16744
- }
16745
- continue;
16746
- }
16747
- }
16748
- if ((tag & 7) === 4 || tag === 0) {
16749
- break;
16750
- }
16751
- reader.skip(tag & 7);
16752
- }
16753
- return message;
16754
- },
16755
- fromJSON(object) {
16756
- return {
16757
- stops: isObject(object.stops)
16758
- ? Object.entries(object.stops).reduce((acc, [key, value]) => {
16759
- acc[globalThis.Number(key)] = StopsAdjacency_StopAdjacency.fromJSON(value);
16760
- return acc;
16761
- }, {})
16762
- : {},
16763
- };
16764
- },
16765
- toJSON(message) {
16766
- const obj = {};
16767
- if (message.stops) {
16768
- const entries = Object.entries(message.stops);
16769
- if (entries.length > 0) {
16770
- obj.stops = {};
16771
- entries.forEach(([k, v]) => {
16772
- obj.stops[k] = StopsAdjacency_StopAdjacency.toJSON(v);
16773
- });
16774
- }
16775
- }
16776
- return obj;
16777
- },
16778
- create(base) {
16779
- return StopsAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
16780
- },
16781
- fromPartial(object) {
16782
- var _a;
16783
- const message = createBaseStopsAdjacency();
16784
- message.stops = Object.entries((_a = object.stops) !== null && _a !== void 0 ? _a : {}).reduce((acc, [key, value]) => {
16785
- if (value !== undefined) {
16786
- acc[globalThis.Number(key)] = StopsAdjacency_StopAdjacency.fromPartial(value);
16787
- }
16788
- return acc;
16789
- }, {});
16790
- return message;
16791
- },
16792
- };
16793
- function createBaseStopsAdjacency_StopAdjacency() {
16621
+ function createBaseStopAdjacency() {
16794
16622
  return { transfers: [], routes: [] };
16795
16623
  }
16796
- const StopsAdjacency_StopAdjacency = {
16624
+ const StopAdjacency = {
16797
16625
  encode(message, writer = new BinaryWriter()) {
16798
16626
  for (const v of message.transfers) {
16799
16627
  Transfer.encode(v, writer.uint32(10).fork()).join();
16800
16628
  }
16801
16629
  writer.uint32(18).fork();
16802
16630
  for (const v of message.routes) {
16803
- writer.int32(v);
16631
+ writer.uint32(v);
16804
16632
  }
16805
16633
  writer.join();
16806
16634
  return writer;
@@ -16808,7 +16636,7 @@ const StopsAdjacency_StopAdjacency = {
16808
16636
  decode(input, length) {
16809
16637
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
16810
16638
  const end = length === undefined ? reader.len : reader.pos + length;
16811
- const message = createBaseStopsAdjacency_StopAdjacency();
16639
+ const message = createBaseStopAdjacency();
16812
16640
  while (reader.pos < end) {
16813
16641
  const tag = reader.uint32();
16814
16642
  switch (tag >>> 3) {
@@ -16821,13 +16649,13 @@ const StopsAdjacency_StopAdjacency = {
16821
16649
  }
16822
16650
  case 2: {
16823
16651
  if (tag === 16) {
16824
- message.routes.push(reader.int32());
16652
+ message.routes.push(reader.uint32());
16825
16653
  continue;
16826
16654
  }
16827
16655
  if (tag === 18) {
16828
16656
  const end2 = reader.uint32() + reader.pos;
16829
16657
  while (reader.pos < end2) {
16830
- message.routes.push(reader.int32());
16658
+ message.routes.push(reader.uint32());
16831
16659
  }
16832
16660
  continue;
16833
16661
  }
@@ -16861,87 +16689,16 @@ const StopsAdjacency_StopAdjacency = {
16861
16689
  return obj;
16862
16690
  },
16863
16691
  create(base) {
16864
- return StopsAdjacency_StopAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
16692
+ return StopAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
16865
16693
  },
16866
16694
  fromPartial(object) {
16867
16695
  var _a, _b;
16868
- const message = createBaseStopsAdjacency_StopAdjacency();
16696
+ const message = createBaseStopAdjacency();
16869
16697
  message.transfers = ((_a = object.transfers) === null || _a === void 0 ? void 0 : _a.map((e) => Transfer.fromPartial(e))) || [];
16870
16698
  message.routes = ((_b = object.routes) === null || _b === void 0 ? void 0 : _b.map((e) => e)) || [];
16871
16699
  return message;
16872
16700
  },
16873
16701
  };
16874
- function createBaseStopsAdjacency_StopsEntry() {
16875
- return { key: 0, value: undefined };
16876
- }
16877
- const StopsAdjacency_StopsEntry = {
16878
- encode(message, writer = new BinaryWriter()) {
16879
- if (message.key !== 0) {
16880
- writer.uint32(8).uint32(message.key);
16881
- }
16882
- if (message.value !== undefined) {
16883
- StopsAdjacency_StopAdjacency.encode(message.value, writer.uint32(18).fork()).join();
16884
- }
16885
- return writer;
16886
- },
16887
- decode(input, length) {
16888
- const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
16889
- const end = length === undefined ? reader.len : reader.pos + length;
16890
- const message = createBaseStopsAdjacency_StopsEntry();
16891
- while (reader.pos < end) {
16892
- const tag = reader.uint32();
16893
- switch (tag >>> 3) {
16894
- case 1: {
16895
- if (tag !== 8) {
16896
- break;
16897
- }
16898
- message.key = reader.uint32();
16899
- continue;
16900
- }
16901
- case 2: {
16902
- if (tag !== 18) {
16903
- break;
16904
- }
16905
- message.value = StopsAdjacency_StopAdjacency.decode(reader, reader.uint32());
16906
- continue;
16907
- }
16908
- }
16909
- if ((tag & 7) === 4 || tag === 0) {
16910
- break;
16911
- }
16912
- reader.skip(tag & 7);
16913
- }
16914
- return message;
16915
- },
16916
- fromJSON(object) {
16917
- return {
16918
- key: isSet(object.key) ? globalThis.Number(object.key) : 0,
16919
- value: isSet(object.value) ? StopsAdjacency_StopAdjacency.fromJSON(object.value) : undefined,
16920
- };
16921
- },
16922
- toJSON(message) {
16923
- const obj = {};
16924
- if (message.key !== 0) {
16925
- obj.key = Math.round(message.key);
16926
- }
16927
- if (message.value !== undefined) {
16928
- obj.value = StopsAdjacency_StopAdjacency.toJSON(message.value);
16929
- }
16930
- return obj;
16931
- },
16932
- create(base) {
16933
- return StopsAdjacency_StopsEntry.fromPartial(base !== null && base !== void 0 ? base : {});
16934
- },
16935
- fromPartial(object) {
16936
- var _a;
16937
- const message = createBaseStopsAdjacency_StopsEntry();
16938
- message.key = (_a = object.key) !== null && _a !== void 0 ? _a : 0;
16939
- message.value = (object.value !== undefined && object.value !== null)
16940
- ? StopsAdjacency_StopAdjacency.fromPartial(object.value)
16941
- : undefined;
16942
- return message;
16943
- },
16944
- };
16945
16702
  function createBaseServiceRoute() {
16946
16703
  return { type: 0, name: "", routes: [] };
16947
16704
  }
@@ -16955,7 +16712,7 @@ const ServiceRoute = {
16955
16712
  }
16956
16713
  writer.uint32(26).fork();
16957
16714
  for (const v of message.routes) {
16958
- writer.int32(v);
16715
+ writer.uint32(v);
16959
16716
  }
16960
16717
  writer.join();
16961
16718
  return writer;
@@ -16983,13 +16740,13 @@ const ServiceRoute = {
16983
16740
  }
16984
16741
  case 3: {
16985
16742
  if (tag === 24) {
16986
- message.routes.push(reader.int32());
16743
+ message.routes.push(reader.uint32());
16987
16744
  continue;
16988
16745
  }
16989
16746
  if (tag === 26) {
16990
16747
  const end2 = reader.uint32() + reader.pos;
16991
16748
  while (reader.pos < end2) {
16992
- message.routes.push(reader.int32());
16749
+ message.routes.push(reader.uint32());
16993
16750
  }
16994
16751
  continue;
16995
16752
  }
@@ -17036,166 +16793,22 @@ const ServiceRoute = {
17036
16793
  return message;
17037
16794
  },
17038
16795
  };
17039
- function createBaseServiceRoutesMap() {
17040
- return { routes: {} };
17041
- }
17042
- const ServiceRoutesMap = {
17043
- encode(message, writer = new BinaryWriter()) {
17044
- Object.entries(message.routes).forEach(([key, value]) => {
17045
- ServiceRoutesMap_RoutesEntry.encode({ key: key, value }, writer.uint32(10).fork()).join();
17046
- });
17047
- return writer;
17048
- },
17049
- decode(input, length) {
17050
- const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
17051
- const end = length === undefined ? reader.len : reader.pos + length;
17052
- const message = createBaseServiceRoutesMap();
17053
- while (reader.pos < end) {
17054
- const tag = reader.uint32();
17055
- switch (tag >>> 3) {
17056
- case 1: {
17057
- if (tag !== 10) {
17058
- break;
17059
- }
17060
- const entry1 = ServiceRoutesMap_RoutesEntry.decode(reader, reader.uint32());
17061
- if (entry1.value !== undefined) {
17062
- message.routes[entry1.key] = entry1.value;
17063
- }
17064
- continue;
17065
- }
17066
- }
17067
- if ((tag & 7) === 4 || tag === 0) {
17068
- break;
17069
- }
17070
- reader.skip(tag & 7);
17071
- }
17072
- return message;
17073
- },
17074
- fromJSON(object) {
17075
- return {
17076
- routes: isObject(object.routes)
17077
- ? Object.entries(object.routes).reduce((acc, [key, value]) => {
17078
- acc[key] = ServiceRoute.fromJSON(value);
17079
- return acc;
17080
- }, {})
17081
- : {},
17082
- };
17083
- },
17084
- toJSON(message) {
17085
- const obj = {};
17086
- if (message.routes) {
17087
- const entries = Object.entries(message.routes);
17088
- if (entries.length > 0) {
17089
- obj.routes = {};
17090
- entries.forEach(([k, v]) => {
17091
- obj.routes[k] = ServiceRoute.toJSON(v);
17092
- });
17093
- }
17094
- }
17095
- return obj;
17096
- },
17097
- create(base) {
17098
- return ServiceRoutesMap.fromPartial(base !== null && base !== void 0 ? base : {});
17099
- },
17100
- fromPartial(object) {
17101
- var _a;
17102
- const message = createBaseServiceRoutesMap();
17103
- message.routes = Object.entries((_a = object.routes) !== null && _a !== void 0 ? _a : {}).reduce((acc, [key, value]) => {
17104
- if (value !== undefined) {
17105
- acc[key] = ServiceRoute.fromPartial(value);
17106
- }
17107
- return acc;
17108
- }, {});
17109
- return message;
17110
- },
17111
- };
17112
- function createBaseServiceRoutesMap_RoutesEntry() {
17113
- return { key: "", value: undefined };
17114
- }
17115
- const ServiceRoutesMap_RoutesEntry = {
17116
- encode(message, writer = new BinaryWriter()) {
17117
- if (message.key !== "") {
17118
- writer.uint32(10).string(message.key);
17119
- }
17120
- if (message.value !== undefined) {
17121
- ServiceRoute.encode(message.value, writer.uint32(18).fork()).join();
17122
- }
17123
- return writer;
17124
- },
17125
- decode(input, length) {
17126
- const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
17127
- const end = length === undefined ? reader.len : reader.pos + length;
17128
- const message = createBaseServiceRoutesMap_RoutesEntry();
17129
- while (reader.pos < end) {
17130
- const tag = reader.uint32();
17131
- switch (tag >>> 3) {
17132
- case 1: {
17133
- if (tag !== 10) {
17134
- break;
17135
- }
17136
- message.key = reader.string();
17137
- continue;
17138
- }
17139
- case 2: {
17140
- if (tag !== 18) {
17141
- break;
17142
- }
17143
- message.value = ServiceRoute.decode(reader, reader.uint32());
17144
- continue;
17145
- }
17146
- }
17147
- if ((tag & 7) === 4 || tag === 0) {
17148
- break;
17149
- }
17150
- reader.skip(tag & 7);
17151
- }
17152
- return message;
17153
- },
17154
- fromJSON(object) {
17155
- return {
17156
- key: isSet(object.key) ? globalThis.String(object.key) : "",
17157
- value: isSet(object.value) ? ServiceRoute.fromJSON(object.value) : undefined,
17158
- };
17159
- },
17160
- toJSON(message) {
17161
- const obj = {};
17162
- if (message.key !== "") {
17163
- obj.key = message.key;
17164
- }
17165
- if (message.value !== undefined) {
17166
- obj.value = ServiceRoute.toJSON(message.value);
17167
- }
17168
- return obj;
17169
- },
17170
- create(base) {
17171
- return ServiceRoutesMap_RoutesEntry.fromPartial(base !== null && base !== void 0 ? base : {});
17172
- },
17173
- fromPartial(object) {
17174
- var _a;
17175
- const message = createBaseServiceRoutesMap_RoutesEntry();
17176
- message.key = (_a = object.key) !== null && _a !== void 0 ? _a : "";
17177
- message.value = (object.value !== undefined && object.value !== null)
17178
- ? ServiceRoute.fromPartial(object.value)
17179
- : undefined;
17180
- return message;
17181
- },
17182
- };
17183
16796
  function createBaseTimetable() {
17184
- return { version: "", stopsAdjacency: undefined, routesAdjacency: [], routes: undefined };
16797
+ return { version: "", stopsAdjacency: [], routesAdjacency: [], serviceRoutes: [] };
17185
16798
  }
17186
16799
  const Timetable$1 = {
17187
16800
  encode(message, writer = new BinaryWriter()) {
17188
16801
  if (message.version !== "") {
17189
16802
  writer.uint32(10).string(message.version);
17190
16803
  }
17191
- if (message.stopsAdjacency !== undefined) {
17192
- StopsAdjacency.encode(message.stopsAdjacency, writer.uint32(18).fork()).join();
16804
+ for (const v of message.stopsAdjacency) {
16805
+ StopAdjacency.encode(v, writer.uint32(18).fork()).join();
17193
16806
  }
17194
16807
  for (const v of message.routesAdjacency) {
17195
16808
  Route$2.encode(v, writer.uint32(26).fork()).join();
17196
16809
  }
17197
- if (message.routes !== undefined) {
17198
- ServiceRoutesMap.encode(message.routes, writer.uint32(34).fork()).join();
16810
+ for (const v of message.serviceRoutes) {
16811
+ ServiceRoute.encode(v, writer.uint32(34).fork()).join();
17199
16812
  }
17200
16813
  return writer;
17201
16814
  },
@@ -17217,7 +16830,7 @@ const Timetable$1 = {
17217
16830
  if (tag !== 18) {
17218
16831
  break;
17219
16832
  }
17220
- message.stopsAdjacency = StopsAdjacency.decode(reader, reader.uint32());
16833
+ message.stopsAdjacency.push(StopAdjacency.decode(reader, reader.uint32()));
17221
16834
  continue;
17222
16835
  }
17223
16836
  case 3: {
@@ -17231,7 +16844,7 @@ const Timetable$1 = {
17231
16844
  if (tag !== 34) {
17232
16845
  break;
17233
16846
  }
17234
- message.routes = ServiceRoutesMap.decode(reader, reader.uint32());
16847
+ message.serviceRoutes.push(ServiceRoute.decode(reader, reader.uint32()));
17235
16848
  continue;
17236
16849
  }
17237
16850
  }
@@ -17245,27 +16858,31 @@ const Timetable$1 = {
17245
16858
  fromJSON(object) {
17246
16859
  return {
17247
16860
  version: isSet(object.version) ? globalThis.String(object.version) : "",
17248
- stopsAdjacency: isSet(object.stopsAdjacency) ? StopsAdjacency.fromJSON(object.stopsAdjacency) : undefined,
16861
+ stopsAdjacency: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.stopsAdjacency)
16862
+ ? object.stopsAdjacency.map((e) => StopAdjacency.fromJSON(e))
16863
+ : [],
17249
16864
  routesAdjacency: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.routesAdjacency)
17250
16865
  ? object.routesAdjacency.map((e) => Route$2.fromJSON(e))
17251
16866
  : [],
17252
- routes: isSet(object.routes) ? ServiceRoutesMap.fromJSON(object.routes) : undefined,
16867
+ serviceRoutes: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.serviceRoutes)
16868
+ ? object.serviceRoutes.map((e) => ServiceRoute.fromJSON(e))
16869
+ : [],
17253
16870
  };
17254
16871
  },
17255
16872
  toJSON(message) {
17256
- var _a;
16873
+ var _a, _b, _c;
17257
16874
  const obj = {};
17258
16875
  if (message.version !== "") {
17259
16876
  obj.version = message.version;
17260
16877
  }
17261
- if (message.stopsAdjacency !== undefined) {
17262
- obj.stopsAdjacency = StopsAdjacency.toJSON(message.stopsAdjacency);
16878
+ if ((_a = message.stopsAdjacency) === null || _a === void 0 ? void 0 : _a.length) {
16879
+ obj.stopsAdjacency = message.stopsAdjacency.map((e) => StopAdjacency.toJSON(e));
17263
16880
  }
17264
- if ((_a = message.routesAdjacency) === null || _a === void 0 ? void 0 : _a.length) {
16881
+ if ((_b = message.routesAdjacency) === null || _b === void 0 ? void 0 : _b.length) {
17265
16882
  obj.routesAdjacency = message.routesAdjacency.map((e) => Route$2.toJSON(e));
17266
16883
  }
17267
- if (message.routes !== undefined) {
17268
- obj.routes = ServiceRoutesMap.toJSON(message.routes);
16884
+ if ((_c = message.serviceRoutes) === null || _c === void 0 ? void 0 : _c.length) {
16885
+ obj.serviceRoutes = message.serviceRoutes.map((e) => ServiceRoute.toJSON(e));
17269
16886
  }
17270
16887
  return obj;
17271
16888
  },
@@ -17273,16 +16890,12 @@ const Timetable$1 = {
17273
16890
  return Timetable$1.fromPartial(base !== null && base !== void 0 ? base : {});
17274
16891
  },
17275
16892
  fromPartial(object) {
17276
- var _a, _b;
16893
+ var _a, _b, _c, _d;
17277
16894
  const message = createBaseTimetable();
17278
16895
  message.version = (_a = object.version) !== null && _a !== void 0 ? _a : "";
17279
- message.stopsAdjacency = (object.stopsAdjacency !== undefined && object.stopsAdjacency !== null)
17280
- ? StopsAdjacency.fromPartial(object.stopsAdjacency)
17281
- : undefined;
17282
- message.routesAdjacency = ((_b = object.routesAdjacency) === null || _b === void 0 ? void 0 : _b.map((e) => Route$2.fromPartial(e))) || [];
17283
- message.routes = (object.routes !== undefined && object.routes !== null)
17284
- ? ServiceRoutesMap.fromPartial(object.routes)
17285
- : undefined;
16896
+ message.stopsAdjacency = ((_b = object.stopsAdjacency) === null || _b === void 0 ? void 0 : _b.map((e) => StopAdjacency.fromPartial(e))) || [];
16897
+ message.routesAdjacency = ((_c = object.routesAdjacency) === null || _c === void 0 ? void 0 : _c.map((e) => Route$2.fromPartial(e))) || [];
16898
+ message.serviceRoutes = ((_d = object.serviceRoutes) === null || _d === void 0 ? void 0 : _d.map((e) => ServiceRoute.fromPartial(e))) || [];
17286
16899
  return message;
17287
16900
  },
17288
16901
  };
@@ -17311,9 +16924,6 @@ function base64FromBytes(arr) {
17311
16924
  return globalThis.btoa(bin.join(""));
17312
16925
  }
17313
16926
  }
17314
- function isObject(value) {
17315
- return typeof value === "object" && value !== null;
17316
- }
17317
16927
  function isSet(value) {
17318
16928
  return value !== null && value !== undefined;
17319
16929
  }
@@ -17691,27 +17301,6 @@ let Route$1 = class Route {
17691
17301
  : byte & 0x03; // Lower 2 bits for first pair
17692
17302
  return toPickupDropOffType(dropOffValue);
17693
17303
  }
17694
- /**
17695
- * Iterates over the stops in the route, starting from an optional specified stop.
17696
- * If no start stop is provided, the iteration begins from the first stop in the route.
17697
- *
17698
- * @param [startStopId] - (Optional) The StopId of the stop to start the iteration from.
17699
- * @returns An IterableIterator of StopIds, starting from the specified stop or the first stop.
17700
- * @throws An error if the specified start stop is not found in the route.
17701
- */
17702
- stopsIterator(startStopId) {
17703
- const startIndex = startStopId !== undefined ? this.stopIndices.get(startStopId) : 0;
17704
- if (startIndex === undefined) {
17705
- throw new Error(`Start stop ${startStopId} not found in route ${this.serviceRouteId}`);
17706
- }
17707
- function* generator(stops, startIndex) {
17708
- for (let i = startIndex; i < stops.length; i++) {
17709
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17710
- yield stops[i];
17711
- }
17712
- }
17713
- return generator(this.stops, startIndex);
17714
- }
17715
17304
  /**
17716
17305
  * Finds the earliest trip that can be taken from a specific stop on a given route,
17717
17306
  * optionally constrained by a latest trip index and a time before which the trip
@@ -17829,18 +17418,14 @@ const bytesToUint16Array = (bytes) => {
17829
17418
  return result;
17830
17419
  };
17831
17420
  const serializeStopsAdjacency = (stopsAdjacency) => {
17832
- const protoStopsAdjacency = {
17833
- stops: {},
17834
- };
17835
- stopsAdjacency.forEach((value, key) => {
17836
- protoStopsAdjacency.stops[key] = {
17421
+ return stopsAdjacency.map((value) => {
17422
+ return {
17837
17423
  transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: serializeTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
17838
17424
  minTransferTime: transfer.minTransferTime.toSeconds(),
17839
17425
  })))),
17840
17426
  routes: value.routes,
17841
17427
  };
17842
17428
  });
17843
- return protoStopsAdjacency;
17844
17429
  };
17845
17430
  const serializeRoutesAdjacency = (routesAdjacency) => {
17846
17431
  const protoRoutesAdjacency = [];
@@ -17855,50 +17440,58 @@ const serializeRoutesAdjacency = (routesAdjacency) => {
17855
17440
  });
17856
17441
  return protoRoutesAdjacency;
17857
17442
  };
17858
- const serializeServiceRoutesMap = (serviceRoutesMap) => {
17859
- const protoServiceRoutesMap = {
17860
- routes: {},
17861
- };
17862
- serviceRoutesMap.forEach((value, key) => {
17863
- protoServiceRoutesMap.routes[key] = {
17443
+ const serializeServiceRoutesMap = (serviceRoutes) => {
17444
+ return serviceRoutes.map((value) => {
17445
+ return {
17864
17446
  type: serializeRouteType(value.type),
17865
17447
  name: value.name,
17866
17448
  routes: value.routes,
17867
17449
  };
17868
17450
  });
17869
- return protoServiceRoutesMap;
17870
17451
  };
17871
17452
  const deserializeStopsAdjacency = (protoStopsAdjacency) => {
17872
- const stopsAdjacency = new Map();
17873
- Object.entries(protoStopsAdjacency.stops).forEach(([keyStr, value]) => {
17874
- const key = parseInt(keyStr, 10);
17875
- stopsAdjacency.set(key, {
17876
- transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: parseTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
17453
+ const result = [];
17454
+ for (let i = 0; i < protoStopsAdjacency.length; i++) {
17455
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17456
+ const value = protoStopsAdjacency[i];
17457
+ const transfers = [];
17458
+ for (let j = 0; j < value.transfers.length; j++) {
17459
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17460
+ const transfer = value.transfers[j];
17461
+ const newTransfer = Object.assign({ destination: transfer.destination, type: parseTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
17877
17462
  minTransferTime: Duration.fromSeconds(transfer.minTransferTime),
17878
- })))),
17463
+ }));
17464
+ transfers.push(newTransfer);
17465
+ }
17466
+ result.push({
17467
+ transfers: transfers,
17879
17468
  routes: value.routes,
17880
17469
  });
17881
- });
17882
- return stopsAdjacency;
17470
+ }
17471
+ return result;
17883
17472
  };
17884
17473
  const deserializeRoutesAdjacency = (protoRoutesAdjacency) => {
17885
17474
  const routesAdjacency = [];
17886
- protoRoutesAdjacency.forEach((value) => {
17475
+ for (let i = 0; i < protoRoutesAdjacency.length; i++) {
17476
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17477
+ const value = protoRoutesAdjacency[i];
17887
17478
  const stops = bytesToUint32Array(value.stops);
17888
17479
  routesAdjacency.push(new Route$1(bytesToUint16Array(value.stopTimes), value.pickUpDropOffTypes, stops, value.serviceRouteId));
17889
- });
17480
+ }
17890
17481
  return routesAdjacency;
17891
17482
  };
17892
- const deserializeServiceRoutesMap = (protoServiceRoutesMap) => {
17893
- const serviceRoutesMap = new Map();
17894
- Object.entries(protoServiceRoutesMap.routes).forEach(([key, value]) => {
17895
- serviceRoutesMap.set(key, {
17483
+ const deserializeServiceRoutesMap = (protoServiceRoutes) => {
17484
+ const result = [];
17485
+ for (let i = 0; i < protoServiceRoutes.length; i++) {
17486
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17487
+ const value = protoServiceRoutes[i];
17488
+ result.push({
17896
17489
  type: parseRouteType(value.type),
17897
17490
  name: value.name,
17898
17491
  routes: value.routes,
17899
17492
  });
17900
- });
17901
- return serviceRoutesMap;
17493
+ }
17494
+ return result;
17902
17495
  };
17903
17496
  const parseTransferType = (type) => {
17904
17497
  switch (type) {
@@ -17990,7 +17583,7 @@ const ALL_TRANSPORT_MODES = new Set([
17990
17583
  'TROLLEYBUS',
17991
17584
  'MONORAIL',
17992
17585
  ]);
17993
- const CURRENT_VERSION = '0.0.5';
17586
+ const CURRENT_VERSION = '0.0.7';
17994
17587
  /**
17995
17588
  * The internal transit timetable format.
17996
17589
  */
@@ -17998,7 +17591,15 @@ class Timetable {
17998
17591
  constructor(stopsAdjacency, routesAdjacency, routes) {
17999
17592
  this.stopsAdjacency = stopsAdjacency;
18000
17593
  this.routesAdjacency = routesAdjacency;
18001
- this.routes = routes;
17594
+ this.serviceRoutes = routes;
17595
+ this.activeStops = new Set();
17596
+ for (let i = 0; i < stopsAdjacency.length; i++) {
17597
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17598
+ const stop = stopsAdjacency[i];
17599
+ if (stop.routes.length > 0 || stop.transfers.length > 0) {
17600
+ this.activeStops.add(i);
17601
+ }
17602
+ }
18002
17603
  }
18003
17604
  /**
18004
17605
  * Serializes the Timetable into a binary array.
@@ -18010,7 +17611,7 @@ class Timetable {
18010
17611
  version: CURRENT_VERSION,
18011
17612
  stopsAdjacency: serializeStopsAdjacency(this.stopsAdjacency),
18012
17613
  routesAdjacency: serializeRoutesAdjacency(this.routesAdjacency),
18013
- routes: serializeServiceRoutesMap(this.routes),
17614
+ serviceRoutes: serializeServiceRoutesMap(this.serviceRoutes),
18014
17615
  };
18015
17616
  const writer = new BinaryWriter();
18016
17617
  Timetable$1.encode(protoTimetable, writer);
@@ -18028,11 +17629,18 @@ class Timetable {
18028
17629
  if (protoTimetable.version !== CURRENT_VERSION) {
18029
17630
  throw new Error(`Unsupported timetable version ${protoTimetable.version}`);
18030
17631
  }
18031
- return new Timetable(
18032
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
18033
- deserializeStopsAdjacency(protoTimetable.stopsAdjacency), deserializeRoutesAdjacency(protoTimetable.routesAdjacency),
18034
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
18035
- deserializeServiceRoutesMap(protoTimetable.routes));
17632
+ return new Timetable(deserializeStopsAdjacency(protoTimetable.stopsAdjacency), deserializeRoutesAdjacency(protoTimetable.routesAdjacency), deserializeServiceRoutesMap(protoTimetable.serviceRoutes));
17633
+ }
17634
+ /**
17635
+ * Checks if the given stop is active on the timetable.
17636
+ * An active stop is a stop reached by a route that is active on the timetable
17637
+ * or by a transfer reachable from an active route.
17638
+ *
17639
+ * @param stopId - The ID of the stop to check.
17640
+ * @returns True if the stop is active, false otherwise.
17641
+ */
17642
+ isActive(stopId) {
17643
+ return this.activeStops.has(stopId);
18036
17644
  }
18037
17645
  /**
18038
17646
  * Retrieves the route associated with the given route ID.
@@ -18052,7 +17660,7 @@ class Timetable {
18052
17660
  */
18053
17661
  getTransfers(stopId) {
18054
17662
  var _a, _b;
18055
- return (_b = (_a = this.stopsAdjacency.get(stopId)) === null || _a === void 0 ? void 0 : _a.transfers) !== null && _b !== void 0 ? _b : [];
17663
+ return (_b = (_a = this.stopsAdjacency[stopId]) === null || _a === void 0 ? void 0 : _a.transfers) !== null && _b !== void 0 ? _b : [];
18056
17664
  }
18057
17665
  /**
18058
17666
  * Retrieves the service route associated with the given route.
@@ -18063,7 +17671,7 @@ class Timetable {
18063
17671
  * @returns The service route corresponding to the provided route.
18064
17672
  */
18065
17673
  getServiceRouteInfo(route) {
18066
- const serviceRoute = this.routes.get(route.serviceRoute());
17674
+ const serviceRoute = this.serviceRoutes[route.serviceRoute()];
18067
17675
  if (!serviceRoute) {
18068
17676
  throw new Error(`Service route not found for route ID: ${route.serviceRoute()}`);
18069
17677
  }
@@ -18078,12 +17686,13 @@ class Timetable {
18078
17686
  * @returns An array of routes passing through the specified stop.
18079
17687
  */
18080
17688
  routesPassingThrough(stopId) {
18081
- const stopData = this.stopsAdjacency.get(stopId);
17689
+ const stopData = this.stopsAdjacency[stopId];
18082
17690
  if (!stopData) {
18083
17691
  return [];
18084
17692
  }
18085
17693
  const routes = [];
18086
- for (const routeId of stopData.routes) {
17694
+ for (let i = 0; i < stopData.routes.length; i++) {
17695
+ const routeId = stopData.routes[i];
18087
17696
  const route = this.routesAdjacency[routeId];
18088
17697
  if (route) {
18089
17698
  routes.push(route);
@@ -18102,12 +17711,15 @@ class Timetable {
18102
17711
  */
18103
17712
  findReachableRoutes(fromStops, transportModes = ALL_TRANSPORT_MODES) {
18104
17713
  const reachableRoutes = new Map();
18105
- for (const originStop of fromStops) {
17714
+ const fromStopsArray = Array.from(fromStops);
17715
+ for (let i = 0; i < fromStopsArray.length; i++) {
17716
+ const originStop = fromStopsArray[i];
18106
17717
  const validRoutes = this.routesPassingThrough(originStop).filter((route) => {
18107
17718
  const serviceRoute = this.getServiceRouteInfo(route);
18108
17719
  return transportModes.has(serviceRoute.type);
18109
17720
  });
18110
- for (const route of validRoutes) {
17721
+ for (let j = 0; j < validRoutes.length; j++) {
17722
+ const route = validRoutes[j];
18111
17723
  const hopOnStop = reachableRoutes.get(route);
18112
17724
  if (hopOnStop) {
18113
17725
  if (route.isBefore(originStop, hopOnStop)) {
@@ -20109,7 +19721,6 @@ const parseRoutes = (routesStream_1, ...args_1) => __awaiter(void 0, [routesStre
20109
19721
  routes.set(line.route_id, {
20110
19722
  name: line.route_short_name,
20111
19723
  type: routeType,
20112
- routes: [],
20113
19724
  });
20114
19725
  }
20115
19726
  }
@@ -20122,6 +19733,29 @@ const parseRoutes = (routesStream_1, ...args_1) => __awaiter(void 0, [routesStre
20122
19733
  }
20123
19734
  return routes;
20124
19735
  });
19736
+ /**
19737
+ * Creates an array of ServiceRoute objects by combining GTFS route data with service route mappings.
19738
+ *
19739
+ * @param gtfsRoutesMap A map containing GTFS route information indexed by route ID
19740
+ * @param serviceRoutesMap A map linking GTFS route IDs to service route IDs
19741
+ * @returns An array of ServiceRoute objects with route information
19742
+ */
19743
+ const indexRoutes = (gtfsRoutesMap, serviceRoutesMap) => {
19744
+ const serviceRoutes = new Array(serviceRoutesMap.size);
19745
+ for (const [gtfsRouteId, serviceRouteId] of serviceRoutesMap) {
19746
+ const route = gtfsRoutesMap.get(gtfsRouteId);
19747
+ if (route === undefined) {
19748
+ log.warn(`Route ${gtfsRouteId} not found.`);
19749
+ continue;
19750
+ }
19751
+ serviceRoutes[serviceRouteId] = {
19752
+ name: route.name,
19753
+ type: route.type,
19754
+ routes: [],
19755
+ };
19756
+ }
19757
+ return serviceRoutes;
19758
+ };
20125
19759
 
20126
19760
  const toGtfsDate = (date) => {
20127
19761
  return parseInt(date.toFormat('yyyyLLdd'));
@@ -20289,37 +19923,6 @@ const parseStops = (stopsStream) => __awaiter(void 0, void 0, void 0, function*
20289
19923
  }
20290
19924
  return parsedStops;
20291
19925
  });
20292
- /**
20293
- * Builds the final stop map indexed by internal IDs.
20294
- * Excludes all stops that do not have at least one valid stopId
20295
- * as a child, a parent, or being valid itself.
20296
- *
20297
- * @param parsedStops - The map of parsed stops.
20298
- * @param validStops - A set of valid stop IDs.
20299
- * @returns A map of stops indexed by internal IDs.
20300
- */
20301
- const indexStops = (parsedStops, validStops) => {
20302
- const stops = new Map();
20303
- for (const [, stop] of parsedStops) {
20304
- if (!validStops ||
20305
- validStops.has(stop.id) ||
20306
- (stop.parent && validStops.has(stop.parent)) ||
20307
- stop.children.some((childId) => validStops.has(childId))) {
20308
- stops.set(stop.id, {
20309
- id: stop.id,
20310
- sourceStopId: stop.sourceStopId,
20311
- name: stop.name,
20312
- lat: stop.lat,
20313
- lon: stop.lon,
20314
- locationType: stop.locationType,
20315
- platform: stop.platform,
20316
- children: stop.children.filter((childId) => !validStops || validStops.has(childId)),
20317
- parent: stop.parent,
20318
- });
20319
- }
20320
- }
20321
- return stops;
20322
- };
20323
19926
  const parseGtfsLocationType = (gtfsLocationType) => {
20324
19927
  switch (gtfsLocationType) {
20325
19928
  case 0:
@@ -20496,7 +20099,7 @@ const finalizeRouteFromBuilder = (builder) => {
20496
20099
  * @param serviceRoutes A mapping of route IDs to route details.
20497
20100
  * @returns A mapping of trip IDs to corresponding route IDs.
20498
20101
  */
20499
- const parseTrips = (tripsStream, serviceIds, serviceRoutes) => __awaiter(void 0, void 0, void 0, function* () {
20102
+ const parseTrips = (tripsStream, serviceIds, validGtfsRoutes) => __awaiter(void 0, void 0, void 0, function* () {
20500
20103
  var _a, e_1, _b, _c;
20501
20104
  const trips = new Map();
20502
20105
  try {
@@ -20509,7 +20112,7 @@ const parseTrips = (tripsStream, serviceIds, serviceRoutes) => __awaiter(void 0,
20509
20112
  // The trip doesn't correspond to an active service
20510
20113
  continue;
20511
20114
  }
20512
- if (!serviceRoutes.get(line.route_id)) {
20115
+ if (!validGtfsRoutes.has(line.route_id)) {
20513
20116
  // The trip doesn't correspond to a supported route
20514
20117
  continue;
20515
20118
  }
@@ -20525,29 +20128,38 @@ const parseTrips = (tripsStream, serviceIds, serviceRoutes) => __awaiter(void 0,
20525
20128
  }
20526
20129
  return trips;
20527
20130
  });
20528
- const buildStopsAdjacencyStructure = (validStops, serviceRoutes, routes, transfersMap) => {
20529
- const stopsAdjacency = new Map();
20530
- routes.forEach((route, index) => {
20531
- var _a;
20532
- for (const stop of route.stopsIterator()) {
20533
- if (!stopsAdjacency.get(stop) && validStops.has(stop)) {
20534
- stopsAdjacency.set(stop, { routes: [], transfers: [] });
20131
+ const buildStopsAdjacencyStructure = (serviceRoutes, routes, transfersMap, nbStops, activeStops) => {
20132
+ // TODO somehow works when it's a map
20133
+ const stopsAdjacency = new Array(nbStops);
20134
+ for (let i = 0; i < nbStops; i++) {
20135
+ stopsAdjacency[i] = { routes: [], transfers: [] };
20136
+ }
20137
+ for (let index = 0; index < routes.length; index++) {
20138
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20139
+ const route = routes[index];
20140
+ for (let j = 0; j < route.getNbStops(); j++) {
20141
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20142
+ const stop = route.stops[j];
20143
+ if (activeStops.has(stop)) {
20144
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20145
+ stopsAdjacency[stop].routes.push(index);
20535
20146
  }
20536
- (_a = stopsAdjacency.get(stop)) === null || _a === void 0 ? void 0 : _a.routes.push(index);
20537
20147
  }
20538
- const serviceRoute = serviceRoutes.get(route.serviceRoute());
20539
- if (!serviceRoute) {
20148
+ const serviceRoute = serviceRoutes[route.serviceRoute()];
20149
+ if (serviceRoute === undefined) {
20540
20150
  throw new Error(`Service route ${route.serviceRoute()} not found for route ${index}.`);
20541
20151
  }
20542
20152
  serviceRoute.routes.push(index);
20543
- });
20153
+ }
20544
20154
  for (const [stop, transfers] of transfersMap) {
20545
- const s = stopsAdjacency.get(stop);
20546
- if (s) {
20547
- for (const transfer of transfers) {
20548
- if (validStops.has(transfer.destination)) {
20549
- s.transfers.push(transfer);
20550
- }
20155
+ for (let i = 0; i < transfers.length; i++) {
20156
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20157
+ const transfer = transfers[i];
20158
+ if (activeStops.has(stop) || activeStops.has(transfer.destination)) {
20159
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20160
+ stopsAdjacency[stop].transfers.push(transfer);
20161
+ activeStops.add(transfer.destination);
20162
+ activeStops.add(stop);
20551
20163
  }
20552
20164
  }
20553
20165
  }
@@ -20558,18 +20170,18 @@ const buildStopsAdjacencyStructure = (validStops, serviceRoutes, routes, transfe
20558
20170
  *
20559
20171
  * @param stopTimesStream The readable stream containing the stop times data.
20560
20172
  * @param stopsMap A map of parsed stops from the GTFS feed.
20561
- * @param validTripIds A map of valid trip IDs to corresponding route IDs.
20562
- * @param validStopIds A set of valid stop IDs.
20173
+ * @param activeTripIds A map of valid trip IDs to corresponding route IDs.
20174
+ * @param activeStopIds A set of valid stop IDs.
20563
20175
  * @returns A mapping of route IDs to route details. The routes returned correspond to the set of trips from GTFS that share the same stop list.
20564
20176
  */
20565
- const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) => __awaiter(void 0, void 0, void 0, function* () {
20177
+ const parseStopTimes = (stopTimesStream, stopsMap, activeTripIds, activeStopIds) => __awaiter(void 0, void 0, void 0, function* () {
20566
20178
  var _a, e_2, _b, _c;
20567
20179
  var _d, _e;
20568
20180
  /**
20569
20181
  * Adds a trip to the appropriate route builder
20570
20182
  */
20571
20183
  const addTrip = (currentTripId) => {
20572
- const gtfsRouteId = validTripIds.get(currentTripId);
20184
+ const gtfsRouteId = activeTripIds.get(currentTripId);
20573
20185
  if (!gtfsRouteId || stops.length === 0) {
20574
20186
  stops = [];
20575
20187
  arrivalTimes = [];
@@ -20578,7 +20190,6 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20578
20190
  dropOffTypes = [];
20579
20191
  return;
20580
20192
  }
20581
- const routeId = `${gtfsRouteId}_${hashIds(stops)}`;
20582
20193
  const firstDeparture = departureTimes[0];
20583
20194
  if (firstDeparture === undefined) {
20584
20195
  console.warn(`Empty trip ${currentTripId}`);
@@ -20589,24 +20200,31 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20589
20200
  dropOffTypes = [];
20590
20201
  return;
20591
20202
  }
20203
+ const routeId = `${gtfsRouteId}_${hashIds(stops)}`;
20592
20204
  let routeBuilder = routeBuilders.get(routeId);
20593
20205
  if (!routeBuilder) {
20206
+ let serviceRouteId = serviceRoutesMap.get(gtfsRouteId);
20207
+ if (serviceRouteId === undefined) {
20208
+ serviceRouteId = currentServiceRouteId;
20209
+ serviceRoutesMap.set(gtfsRouteId, serviceRouteId);
20210
+ currentServiceRouteId = currentServiceRouteId + 1;
20211
+ }
20594
20212
  routeBuilder = {
20595
- serviceRouteId: gtfsRouteId,
20596
- stops: [...stops],
20213
+ serviceRouteId,
20214
+ stops,
20597
20215
  trips: [],
20598
20216
  };
20599
20217
  routeBuilders.set(routeId, routeBuilder);
20600
20218
  for (const stop of stops) {
20601
- validStopIds.add(stop);
20219
+ activeStopIds.add(stop);
20602
20220
  }
20603
20221
  }
20604
20222
  routeBuilder.trips.push({
20605
20223
  firstDeparture,
20606
- arrivalTimes: [...arrivalTimes],
20607
- departureTimes: [...departureTimes],
20608
- pickUpTypes: [...pickUpTypes],
20609
- dropOffTypes: [...dropOffTypes],
20224
+ arrivalTimes: arrivalTimes,
20225
+ departureTimes: departureTimes,
20226
+ pickUpTypes: pickUpTypes,
20227
+ dropOffTypes: dropOffTypes,
20610
20228
  });
20611
20229
  stops = [];
20612
20230
  arrivalTimes = [];
@@ -20615,6 +20233,9 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20615
20233
  dropOffTypes = [];
20616
20234
  };
20617
20235
  const routeBuilders = new Map();
20236
+ const serviceRoutesMap = new Map();
20237
+ // incrementally generate service route IDs
20238
+ let currentServiceRouteId = 0;
20618
20239
  let previousSeq = 0;
20619
20240
  let stops = [];
20620
20241
  let arrivalTimes = [];
@@ -20677,7 +20298,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20677
20298
  const routeData = finalizeRouteFromBuilder(routeBuilder);
20678
20299
  routesAdjacency.push(new Route$1(routeData.stopTimes, routeData.pickUpDropOffTypes, routeData.stops, routeData.serviceRouteId));
20679
20300
  }
20680
- return routesAdjacency;
20301
+ return { routes: routesAdjacency, serviceRoutesMap };
20681
20302
  });
20682
20303
  const parsePickupDropOffType = (gtfsType) => {
20683
20304
  switch (gtfsType) {
@@ -20711,18 +20332,16 @@ class GtfsParser {
20711
20332
  * Parses a GTFS feed to extract all the data relevant to a given day in a transit-planner friendly format.
20712
20333
  *
20713
20334
  * @param date The active date.
20714
- * @param gtfsPath A path to the zipped GTFS feed.
20715
- * @param gtfsProfile The GTFS profile configuration.
20716
- * @returns An object containing the timetable and stops map.
20335
+ * @returns The parsed timetable.
20717
20336
  */
20718
- parse(date) {
20337
+ parseTimetable(date) {
20719
20338
  return __awaiter(this, void 0, void 0, function* () {
20720
20339
  log.setLevel('INFO');
20721
20340
  const zip = new StreamZip.async({ file: this.path });
20722
20341
  const entries = yield zip.entries();
20723
20342
  const datetime = DateTime.fromJSDate(date);
20724
- const validServiceIds = new Set();
20725
- const validStopIds = new Set();
20343
+ const activeServiceIds = new Set();
20344
+ const activeStopIds = new Set();
20726
20345
  log.info(`Parsing ${STOPS_FILE}`);
20727
20346
  const stopsStart = performance.now();
20728
20347
  const stopsStream = yield zip.stream(STOPS_FILE);
@@ -20733,17 +20352,17 @@ class GtfsParser {
20733
20352
  log.info(`Parsing ${CALENDAR_FILE}`);
20734
20353
  const calendarStart = performance.now();
20735
20354
  const calendarStream = yield zip.stream(CALENDAR_FILE);
20736
- yield parseCalendar(calendarStream, validServiceIds, datetime);
20355
+ yield parseCalendar(calendarStream, activeServiceIds, datetime);
20737
20356
  const calendarEnd = performance.now();
20738
- log.info(`${validServiceIds.size} valid services. (${(calendarEnd - calendarStart).toFixed(2)}ms)`);
20357
+ log.info(`${activeServiceIds.size} valid services. (${(calendarEnd - calendarStart).toFixed(2)}ms)`);
20739
20358
  }
20740
20359
  if (entries[CALENDAR_DATES_FILE]) {
20741
20360
  log.info(`Parsing ${CALENDAR_DATES_FILE}`);
20742
20361
  const calendarDatesStart = performance.now();
20743
20362
  const calendarDatesStream = yield zip.stream(CALENDAR_DATES_FILE);
20744
- yield parseCalendarDates(calendarDatesStream, validServiceIds, datetime);
20363
+ yield parseCalendarDates(calendarDatesStream, activeServiceIds, datetime);
20745
20364
  const calendarDatesEnd = performance.now();
20746
- log.info(`${validServiceIds.size} valid services. (${(calendarDatesEnd - calendarDatesStart).toFixed(2)}ms)`);
20365
+ log.info(`${activeServiceIds.size} valid services. (${(calendarDatesEnd - calendarDatesStart).toFixed(2)}ms)`);
20747
20366
  }
20748
20367
  log.info(`Parsing ${ROUTES_FILE}`);
20749
20368
  const routesStart = performance.now();
@@ -20754,7 +20373,7 @@ class GtfsParser {
20754
20373
  log.info(`Parsing ${TRIPS_FILE}`);
20755
20374
  const tripsStart = performance.now();
20756
20375
  const tripsStream = yield zip.stream(TRIPS_FILE);
20757
- const trips = yield parseTrips(tripsStream, validServiceIds, validGtfsRoutes);
20376
+ const trips = yield parseTrips(tripsStream, activeServiceIds, validGtfsRoutes);
20758
20377
  const tripsEnd = performance.now();
20759
20378
  log.info(`${trips.size} valid trips. (${(tripsEnd - tripsStart).toFixed(2)}ms)`);
20760
20379
  let transfers = new Map();
@@ -20769,32 +20388,26 @@ class GtfsParser {
20769
20388
  log.info(`Parsing ${STOP_TIMES_FILE}`);
20770
20389
  const stopTimesStart = performance.now();
20771
20390
  const stopTimesStream = yield zip.stream(STOP_TIMES_FILE);
20772
- const routesAdjacency = yield parseStopTimes(stopTimesStream, parsedStops, trips, validStopIds);
20773
- const stopsAdjacency = buildStopsAdjacencyStructure(validStopIds, validGtfsRoutes, routesAdjacency, transfers);
20391
+ const { routes, serviceRoutesMap } = yield parseStopTimes(stopTimesStream, parsedStops, trips, activeStopIds);
20392
+ const serviceRoutes = indexRoutes(validGtfsRoutes, serviceRoutesMap);
20774
20393
  const stopTimesEnd = performance.now();
20775
- log.info(`${routesAdjacency.length} valid unique routes. (${(stopTimesEnd - stopTimesStart).toFixed(2)}ms)`);
20776
- log.info(`Removing unused stops.`);
20777
- const indexStopsStart = performance.now();
20778
- const stops = indexStops(parsedStops, validStopIds);
20779
- const indexStopsEnd = performance.now();
20780
- log.info(`${stops.size} used stop stops, ${parsedStops.size - stops.size} unused. (${(indexStopsEnd - indexStopsStart).toFixed(2)}ms)`);
20394
+ log.info(`${routes.length} valid unique routes. (${(stopTimesEnd - stopTimesStart).toFixed(2)}ms)`);
20395
+ log.info('Building stops adjacency structure');
20396
+ const stopsAdjacencyStart = performance.now();
20397
+ const stopsAdjacency = buildStopsAdjacencyStructure(serviceRoutes, routes, transfers, parsedStops.size, activeStopIds);
20398
+ const stopsAdjacencyEnd = performance.now();
20399
+ log.info(`${stopsAdjacency.length} valid stops in the structure. (${(stopsAdjacencyEnd - stopsAdjacencyStart).toFixed(2)}ms)`);
20781
20400
  yield zip.close();
20782
- const timetable = new Timetable(stopsAdjacency, routesAdjacency, validGtfsRoutes);
20783
- log.info(`Building stops index.`);
20784
- const stopsIndexStart = performance.now();
20785
- const stopsIndex = new StopsIndex(stops);
20786
- const stopsIndexEnd = performance.now();
20787
- log.info(`Stops index built. (${(stopsIndexEnd - stopsIndexStart).toFixed(2)}ms)`);
20401
+ const timetable = new Timetable(stopsAdjacency, routes, serviceRoutes);
20788
20402
  log.info('Parsing complete.');
20789
- return { timetable, stopsIndex };
20403
+ return timetable;
20790
20404
  });
20791
20405
  }
20792
20406
  /**
20793
20407
  * Parses a GTFS feed to extract all stops.
20794
20408
  *
20795
- * @param gtfsPath A path the zipped GTFS feed.
20796
- * @param gtfsProfile The GTFS profile configuration.
20797
- * @returns An object containing the timetable and stops map.
20409
+ * @param activeStops The set of active stop IDs to include in the index.
20410
+ * @returns An index of stops.
20798
20411
  */
20799
20412
  parseStops() {
20800
20413
  return __awaiter(this, void 0, void 0, function* () {
@@ -20802,11 +20415,11 @@ class GtfsParser {
20802
20415
  log.info(`Parsing ${STOPS_FILE}`);
20803
20416
  const stopsStart = performance.now();
20804
20417
  const stopsStream = yield zip.stream(STOPS_FILE);
20805
- const stops = indexStops(yield parseStops(stopsStream));
20418
+ const stops = yield parseStops(stopsStream);
20806
20419
  const stopsEnd = performance.now();
20807
20420
  log.info(`${stops.size} parsed stops. (${(stopsEnd - stopsStart).toFixed(2)}ms)`);
20808
20421
  yield zip.close();
20809
- return new StopsIndex(stops);
20422
+ return new StopsIndex(Array.from(stops.values()));
20810
20423
  });
20811
20424
  }
20812
20425
  }
@@ -21207,7 +20820,9 @@ class Router {
21207
20820
  var _a, _b;
21208
20821
  const { options } = query;
21209
20822
  const newlyMarkedStops = new Set();
21210
- for (const stop of markedStops) {
20823
+ const markedStopsArray = Array.from(markedStops);
20824
+ for (let i = 0; i < markedStopsArray.length; i++) {
20825
+ const stop = markedStopsArray[i];
21211
20826
  const currentArrival = arrivalsAtCurrentRound.get(stop);
21212
20827
  if (!currentArrival)
21213
20828
  continue;
@@ -21216,7 +20831,9 @@ class Router {
21216
20831
  if (previousLeg && !('route' in previousLeg)) {
21217
20832
  continue;
21218
20833
  }
21219
- for (const transfer of this.timetable.getTransfers(stop)) {
20834
+ const transfers = this.timetable.getTransfers(stop);
20835
+ for (let j = 0; j < transfers.length; j++) {
20836
+ const transfer = transfers[j];
21220
20837
  let transferTime;
21221
20838
  if (transfer.minTransferTime) {
21222
20839
  transferTime = transfer.minTransferTime;
@@ -21251,7 +20868,9 @@ class Router {
21251
20868
  }
21252
20869
  }
21253
20870
  }
21254
- for (const newStop of newlyMarkedStops) {
20871
+ const newlyMarkedStopsArray = Array.from(newlyMarkedStops);
20872
+ for (let i = 0; i < newlyMarkedStopsArray.length; i++) {
20873
+ const newStop = newlyMarkedStopsArray[i];
21255
20874
  markedStops.add(newStop);
21256
20875
  }
21257
20876
  }
@@ -21265,7 +20884,8 @@ class Router {
21265
20884
  earliestArrivalAtAnyStop(earliestArrivals, destinations) {
21266
20885
  var _a, _b;
21267
20886
  let earliestArrivalAtAnyDestination = UNREACHED;
21268
- for (const destination of destinations) {
20887
+ for (let i = 0; i < destinations.length; i++) {
20888
+ const destination = destinations[i];
21269
20889
  const arrival = (_b = (_a = earliestArrivals.get(destination.id)) === null || _a === void 0 ? void 0 : _a.arrival) !== null && _b !== void 0 ? _b : UNREACHED;
21270
20890
  earliestArrivalAtAnyDestination = Time.min(earliestArrivalAtAnyDestination, arrival);
21271
20891
  }
@@ -21289,7 +20909,8 @@ class Router {
21289
20909
  const earliestArrivalsPerRound = [earliestArrivalsWithoutAnyLeg];
21290
20910
  // Stops that have been improved at round k-1
21291
20911
  const markedStops = new Set();
21292
- for (const originStop of origins) {
20912
+ for (let i = 0; i < origins.length; i++) {
20913
+ const originStop = origins[i];
21293
20914
  markedStops.add(originStop.id);
21294
20915
  earliestArrivals.set(originStop.id, {
21295
20916
  arrival: departureTime,
@@ -21313,9 +20934,15 @@ class Router {
21313
20934
  const reachableRoutes = this.timetable.findReachableRoutes(markedStops, options.transportModes);
21314
20935
  markedStops.clear();
21315
20936
  // for each route that can be reached with at least round - 1 trips
21316
- for (const [route, hopOnStop] of reachableRoutes.entries()) {
20937
+ const reachableRoutesArray = Array.from(reachableRoutes.entries());
20938
+ for (let i = 0; i < reachableRoutesArray.length; i++) {
20939
+ const [route, hopOnStop] = reachableRoutesArray[i];
21317
20940
  let currentTrip = undefined;
21318
- for (const currentStop of route.stopsIterator(hopOnStop)) {
20941
+ const startIndex = route.stopIndex(hopOnStop);
20942
+ for (let j = startIndex; j < route.getNbStops(); j++) {
20943
+ const currentStop = route.stops[j];
20944
+ // If we're currently on a trip,
20945
+ // check if arrival at the stop improves the earliest arrival time
21319
20946
  if (currentTrip !== undefined) {
21320
20947
  const currentArrivalTime = route.arrivalAt(currentStop, currentTrip.tripIndex);
21321
20948
  const currentDropOffType = route.dropOffTypeAt(currentStop, currentTrip.tripIndex);
@@ -21344,7 +20971,7 @@ class Router {
21344
20971
  markedStops.add(currentStop);
21345
20972
  }
21346
20973
  }
21347
- // check if we can catch a previous trip at the current stop
20974
+ // check if we can board an earlier trip at the current stop
21348
20975
  // if there was no current trip, find the first one reachable
21349
20976
  const earliestArrivalOnPreviousRound = (_c = arrivalsAtPreviousRound.get(currentStop)) === null || _c === void 0 ? void 0 : _c.arrival;
21350
20977
  if (earliestArrivalOnPreviousRound !== undefined &&
@@ -21669,9 +21296,10 @@ program
21669
21296
  log.setDefaultLevel(log.levels.ERROR);
21670
21297
  }
21671
21298
  const parser = new GtfsParser(gtfsPath, profiles[options.profileName]);
21672
- const { timetable, stopsIndex } = yield parser.parse(new Date(options.date));
21673
- fs.writeFileSync(options.timetableOutputPath, timetable.serialize());
21299
+ const stopsIndex = yield parser.parseStops();
21674
21300
  fs.writeFileSync(options.stopsOutputPath, stopsIndex.serialize());
21301
+ const timetable = yield parser.parseTimetable(new Date(options.date));
21302
+ fs.writeFileSync(options.timetableOutputPath, timetable.serialize());
21675
21303
  }));
21676
21304
  program
21677
21305
  .command('parse-stops')