minotor 5.0.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +8 -3
  2. package/dist/cli.mjs +207 -596
  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 +201 -593
  10. package/dist/parser.cjs.js.map +1 -1
  11. package/dist/parser.esm.js +201 -593
  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/timetable.d.ts +17 -9
  26. package/package.json +1 -1
  27. package/src/__e2e__/timetable/stops.bin +2 -2
  28. package/src/__e2e__/timetable/timetable.bin +2 -2
  29. package/src/cli/minotor.ts +3 -4
  30. package/src/gtfs/__tests__/parser.test.ts +5 -6
  31. package/src/gtfs/__tests__/routes.test.ts +0 -3
  32. package/src/gtfs/__tests__/stops.test.ts +1 -124
  33. package/src/gtfs/__tests__/transfers.test.ts +7 -7
  34. package/src/gtfs/__tests__/trips.test.ts +74 -45
  35. package/src/gtfs/parser.ts +32 -49
  36. package/src/gtfs/routes.ts +43 -5
  37. package/src/gtfs/stops.ts +2 -44
  38. package/src/gtfs/transfers.ts +2 -2
  39. package/src/gtfs/trips.ts +57 -40
  40. package/src/routing/__tests__/result.test.ts +48 -48
  41. package/src/routing/__tests__/router.test.ts +279 -363
  42. package/src/routing/router.ts +3 -1
  43. package/src/stops/__tests__/io.test.ts +25 -31
  44. package/src/stops/__tests__/stopFinder.test.ts +82 -103
  45. package/src/stops/io.ts +8 -17
  46. package/src/stops/proto/stops.proto +3 -3
  47. package/src/stops/proto/stops.ts +16 -120
  48. package/src/stops/stops.ts +0 -4
  49. package/src/stops/stopsIndex.ts +20 -26
  50. package/src/timetable/__tests__/io.test.ts +44 -54
  51. package/src/timetable/__tests__/route.test.ts +11 -11
  52. package/src/timetable/__tests__/timetable.test.ts +29 -37
  53. package/src/timetable/io.ts +38 -66
  54. package/src/timetable/proto/timetable.proto +6 -13
  55. package/src/timetable/proto/timetable.ts +43 -385
  56. package/src/timetable/timetable.ts +43 -28
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,13 +16078,12 @@ const serializeLocationType = (locationType) => {
16176
16078
  * to efficiently find stops based on user queries.
16177
16079
  */
16178
16080
  class StopsIndex {
16179
- constructor(stopsMap) {
16180
- var _a;
16181
- this.stopsMap = stopsMap;
16081
+ constructor(stops) {
16082
+ this.stops = stops;
16182
16083
  this.sourceStopsMap = new Map();
16183
- for (const [id, stop] of stopsMap.entries()) {
16084
+ stops.forEach((stop, id) => {
16184
16085
  this.sourceStopsMap.set(stop.sourceStopId, id);
16185
- }
16086
+ });
16186
16087
  this.textIndex = lt({
16187
16088
  fields: ['name'],
16188
16089
  storeFields: ['id'],
@@ -16190,25 +16091,26 @@ class StopsIndex {
16190
16091
  processTerm: generateAccentVariants,
16191
16092
  });
16192
16093
  const stopsSet = new Map();
16193
- for (const [id, stop] of stopsMap.entries()) {
16094
+ stops.forEach((stop, id) => {
16095
+ var _a;
16194
16096
  const effectiveStopId = (_a = stop.parent) !== null && _a !== void 0 ? _a : id;
16195
16097
  if (!stopsSet.has(effectiveStopId)) {
16196
16098
  stopsSet.set(effectiveStopId, {
16197
16099
  id: effectiveStopId,
16198
16100
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
16199
- name: stop.parent ? this.stopsMap.get(stop.parent).name : stop.name,
16101
+ name: stop.parent ? this.stops[stop.parent].name : stop.name,
16200
16102
  });
16201
16103
  }
16202
- }
16104
+ });
16203
16105
  const stopsArray = Array.from(stopsSet.values());
16204
16106
  q(this.textIndex, stopsArray);
16205
- this.stopPoints = Array.from(this.stopsMap.entries())
16206
- .filter(([, stop]) => {
16107
+ this.stopPoints = this.stops
16108
+ .filter((stop) => {
16207
16109
  if (stop.lat && stop.lon)
16208
16110
  return true;
16209
16111
  return false;
16210
16112
  })
16211
- .map(([id, stop]) => ({
16113
+ .map((stop, id) => ({
16212
16114
  id: id,
16213
16115
  lat: stop.lat,
16214
16116
  lon: stop.lon,
@@ -16236,7 +16138,7 @@ class StopsIndex {
16236
16138
  * @returns The serialized binary data.
16237
16139
  */
16238
16140
  serialize() {
16239
- const protoStopsMap = serializeStopsMap(this.stopsMap);
16141
+ const protoStopsMap = serializeStopsMap(this.stops);
16240
16142
  const writer = new BinaryWriter();
16241
16143
  StopsMap.encode(protoStopsMap, writer);
16242
16144
  return writer.finish();
@@ -16247,7 +16149,7 @@ class StopsIndex {
16247
16149
  * @returns The total number of stops.
16248
16150
  */
16249
16151
  size() {
16250
- return this.stopsMap.size;
16152
+ return this.stops.length;
16251
16153
  }
16252
16154
  /**
16253
16155
  * Finds stops by their name using a text search.
@@ -16257,7 +16159,7 @@ class StopsIndex {
16257
16159
  * @returns An array of Stop objects that match the search query.
16258
16160
  */
16259
16161
  findStopsByName(query, maxResults = 5) {
16260
- const results = dt(this.textIndex, query).map((result) => this.stopsMap.get(result.id));
16162
+ const results = dt(this.textIndex, query).map((result) => this.stops[result.id]);
16261
16163
  return results.slice(0, maxResults);
16262
16164
  }
16263
16165
  /**
@@ -16272,7 +16174,7 @@ class StopsIndex {
16272
16174
  findStopsByLocation(lat, lon, maxResults = 5, radius = 0.5) {
16273
16175
  const nearestStops = around(this.geoIndex, lon, lat, maxResults, radius).map((id) => {
16274
16176
  const stopPoint = this.stopPoints[id];
16275
- return this.stopsMap.get(stopPoint.id);
16177
+ return this.stops[stopPoint.id];
16276
16178
  });
16277
16179
  return nearestStops;
16278
16180
  }
@@ -16283,7 +16185,7 @@ class StopsIndex {
16283
16185
  * @returns The Stop object that matches the specified ID, or undefined if not found.
16284
16186
  */
16285
16187
  findStopById(id) {
16286
- return this.stopsMap.get(id);
16188
+ return this.stops[id];
16287
16189
  }
16288
16190
  /**
16289
16191
  * Finds a stop by its ID in the transit data source (e.g. GTFS).
@@ -16307,14 +16209,14 @@ class StopsIndex {
16307
16209
  if (id === undefined) {
16308
16210
  return [];
16309
16211
  }
16310
- const stop = this.stopsMap.get(id);
16212
+ const stop = this.stops[id];
16311
16213
  if (!stop) {
16312
16214
  return [];
16313
16215
  }
16314
16216
  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 : [])
16217
+ ? ((_b = (_a = this.stops[stop.parent]) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : [])
16316
16218
  : stop.children;
16317
- return Array.from(new Set([id, ...equivalentStops])).map((stopId) => this.stopsMap.get(stopId));
16219
+ return Array.from(new Set([id, ...equivalentStops])).map((stopId) => this.stops[stopId]);
16318
16220
  }
16319
16221
  }
16320
16222
 
@@ -16532,7 +16434,7 @@ function createBaseRoute() {
16532
16434
  stopTimes: new Uint8Array(0),
16533
16435
  pickUpDropOffTypes: new Uint8Array(0),
16534
16436
  stops: new Uint8Array(0),
16535
- serviceRouteId: "",
16437
+ serviceRouteId: 0,
16536
16438
  };
16537
16439
  }
16538
16440
  const Route$2 = {
@@ -16546,8 +16448,8 @@ const Route$2 = {
16546
16448
  if (message.stops.length !== 0) {
16547
16449
  writer.uint32(26).bytes(message.stops);
16548
16450
  }
16549
- if (message.serviceRouteId !== "") {
16550
- writer.uint32(34).string(message.serviceRouteId);
16451
+ if (message.serviceRouteId !== 0) {
16452
+ writer.uint32(32).uint32(message.serviceRouteId);
16551
16453
  }
16552
16454
  return writer;
16553
16455
  },
@@ -16580,10 +16482,10 @@ const Route$2 = {
16580
16482
  continue;
16581
16483
  }
16582
16484
  case 4: {
16583
- if (tag !== 34) {
16485
+ if (tag !== 32) {
16584
16486
  break;
16585
16487
  }
16586
- message.serviceRouteId = reader.string();
16488
+ message.serviceRouteId = reader.uint32();
16587
16489
  continue;
16588
16490
  }
16589
16491
  }
@@ -16601,7 +16503,7 @@ const Route$2 = {
16601
16503
  ? bytesFromBase64(object.pickUpDropOffTypes)
16602
16504
  : new Uint8Array(0),
16603
16505
  stops: isSet(object.stops) ? bytesFromBase64(object.stops) : new Uint8Array(0),
16604
- serviceRouteId: isSet(object.serviceRouteId) ? globalThis.String(object.serviceRouteId) : "",
16506
+ serviceRouteId: isSet(object.serviceRouteId) ? globalThis.Number(object.serviceRouteId) : 0,
16605
16507
  };
16606
16508
  },
16607
16509
  toJSON(message) {
@@ -16615,8 +16517,8 @@ const Route$2 = {
16615
16517
  if (message.stops.length !== 0) {
16616
16518
  obj.stops = base64FromBytes(message.stops);
16617
16519
  }
16618
- if (message.serviceRouteId !== "") {
16619
- obj.serviceRouteId = message.serviceRouteId;
16520
+ if (message.serviceRouteId !== 0) {
16521
+ obj.serviceRouteId = Math.round(message.serviceRouteId);
16620
16522
  }
16621
16523
  return obj;
16622
16524
  },
@@ -16629,7 +16531,7 @@ const Route$2 = {
16629
16531
  message.stopTimes = (_a = object.stopTimes) !== null && _a !== void 0 ? _a : new Uint8Array(0);
16630
16532
  message.pickUpDropOffTypes = (_b = object.pickUpDropOffTypes) !== null && _b !== void 0 ? _b : new Uint8Array(0);
16631
16533
  message.stops = (_c = object.stops) !== null && _c !== void 0 ? _c : new Uint8Array(0);
16632
- message.serviceRouteId = (_d = object.serviceRouteId) !== null && _d !== void 0 ? _d : "";
16534
+ message.serviceRouteId = (_d = object.serviceRouteId) !== null && _d !== void 0 ? _d : 0;
16633
16535
  return message;
16634
16536
  },
16635
16537
  };
@@ -16717,83 +16619,10 @@ const Transfer = {
16717
16619
  return message;
16718
16620
  },
16719
16621
  };
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() {
16622
+ function createBaseStopAdjacency() {
16794
16623
  return { transfers: [], routes: [] };
16795
16624
  }
16796
- const StopsAdjacency_StopAdjacency = {
16625
+ const StopAdjacency = {
16797
16626
  encode(message, writer = new BinaryWriter()) {
16798
16627
  for (const v of message.transfers) {
16799
16628
  Transfer.encode(v, writer.uint32(10).fork()).join();
@@ -16808,7 +16637,7 @@ const StopsAdjacency_StopAdjacency = {
16808
16637
  decode(input, length) {
16809
16638
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
16810
16639
  const end = length === undefined ? reader.len : reader.pos + length;
16811
- const message = createBaseStopsAdjacency_StopAdjacency();
16640
+ const message = createBaseStopAdjacency();
16812
16641
  while (reader.pos < end) {
16813
16642
  const tag = reader.uint32();
16814
16643
  switch (tag >>> 3) {
@@ -16861,87 +16690,16 @@ const StopsAdjacency_StopAdjacency = {
16861
16690
  return obj;
16862
16691
  },
16863
16692
  create(base) {
16864
- return StopsAdjacency_StopAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
16693
+ return StopAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
16865
16694
  },
16866
16695
  fromPartial(object) {
16867
16696
  var _a, _b;
16868
- const message = createBaseStopsAdjacency_StopAdjacency();
16697
+ const message = createBaseStopAdjacency();
16869
16698
  message.transfers = ((_a = object.transfers) === null || _a === void 0 ? void 0 : _a.map((e) => Transfer.fromPartial(e))) || [];
16870
16699
  message.routes = ((_b = object.routes) === null || _b === void 0 ? void 0 : _b.map((e) => e)) || [];
16871
16700
  return message;
16872
16701
  },
16873
16702
  };
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
16703
  function createBaseServiceRoute() {
16946
16704
  return { type: 0, name: "", routes: [] };
16947
16705
  }
@@ -17036,166 +16794,22 @@ const ServiceRoute = {
17036
16794
  return message;
17037
16795
  },
17038
16796
  };
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
16797
  function createBaseTimetable() {
17184
- return { version: "", stopsAdjacency: undefined, routesAdjacency: [], routes: undefined };
16798
+ return { version: "", stopsAdjacency: [], routesAdjacency: [], serviceRoutes: [] };
17185
16799
  }
17186
16800
  const Timetable$1 = {
17187
16801
  encode(message, writer = new BinaryWriter()) {
17188
16802
  if (message.version !== "") {
17189
16803
  writer.uint32(10).string(message.version);
17190
16804
  }
17191
- if (message.stopsAdjacency !== undefined) {
17192
- StopsAdjacency.encode(message.stopsAdjacency, writer.uint32(18).fork()).join();
16805
+ for (const v of message.stopsAdjacency) {
16806
+ StopAdjacency.encode(v, writer.uint32(18).fork()).join();
17193
16807
  }
17194
16808
  for (const v of message.routesAdjacency) {
17195
16809
  Route$2.encode(v, writer.uint32(26).fork()).join();
17196
16810
  }
17197
- if (message.routes !== undefined) {
17198
- ServiceRoutesMap.encode(message.routes, writer.uint32(34).fork()).join();
16811
+ for (const v of message.serviceRoutes) {
16812
+ ServiceRoute.encode(v, writer.uint32(34).fork()).join();
17199
16813
  }
17200
16814
  return writer;
17201
16815
  },
@@ -17217,7 +16831,7 @@ const Timetable$1 = {
17217
16831
  if (tag !== 18) {
17218
16832
  break;
17219
16833
  }
17220
- message.stopsAdjacency = StopsAdjacency.decode(reader, reader.uint32());
16834
+ message.stopsAdjacency.push(StopAdjacency.decode(reader, reader.uint32()));
17221
16835
  continue;
17222
16836
  }
17223
16837
  case 3: {
@@ -17231,7 +16845,7 @@ const Timetable$1 = {
17231
16845
  if (tag !== 34) {
17232
16846
  break;
17233
16847
  }
17234
- message.routes = ServiceRoutesMap.decode(reader, reader.uint32());
16848
+ message.serviceRoutes.push(ServiceRoute.decode(reader, reader.uint32()));
17235
16849
  continue;
17236
16850
  }
17237
16851
  }
@@ -17245,27 +16859,31 @@ const Timetable$1 = {
17245
16859
  fromJSON(object) {
17246
16860
  return {
17247
16861
  version: isSet(object.version) ? globalThis.String(object.version) : "",
17248
- stopsAdjacency: isSet(object.stopsAdjacency) ? StopsAdjacency.fromJSON(object.stopsAdjacency) : undefined,
16862
+ stopsAdjacency: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.stopsAdjacency)
16863
+ ? object.stopsAdjacency.map((e) => StopAdjacency.fromJSON(e))
16864
+ : [],
17249
16865
  routesAdjacency: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.routesAdjacency)
17250
16866
  ? object.routesAdjacency.map((e) => Route$2.fromJSON(e))
17251
16867
  : [],
17252
- routes: isSet(object.routes) ? ServiceRoutesMap.fromJSON(object.routes) : undefined,
16868
+ serviceRoutes: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.serviceRoutes)
16869
+ ? object.serviceRoutes.map((e) => ServiceRoute.fromJSON(e))
16870
+ : [],
17253
16871
  };
17254
16872
  },
17255
16873
  toJSON(message) {
17256
- var _a;
16874
+ var _a, _b, _c;
17257
16875
  const obj = {};
17258
16876
  if (message.version !== "") {
17259
16877
  obj.version = message.version;
17260
16878
  }
17261
- if (message.stopsAdjacency !== undefined) {
17262
- obj.stopsAdjacency = StopsAdjacency.toJSON(message.stopsAdjacency);
16879
+ if ((_a = message.stopsAdjacency) === null || _a === void 0 ? void 0 : _a.length) {
16880
+ obj.stopsAdjacency = message.stopsAdjacency.map((e) => StopAdjacency.toJSON(e));
17263
16881
  }
17264
- if ((_a = message.routesAdjacency) === null || _a === void 0 ? void 0 : _a.length) {
16882
+ if ((_b = message.routesAdjacency) === null || _b === void 0 ? void 0 : _b.length) {
17265
16883
  obj.routesAdjacency = message.routesAdjacency.map((e) => Route$2.toJSON(e));
17266
16884
  }
17267
- if (message.routes !== undefined) {
17268
- obj.routes = ServiceRoutesMap.toJSON(message.routes);
16885
+ if ((_c = message.serviceRoutes) === null || _c === void 0 ? void 0 : _c.length) {
16886
+ obj.serviceRoutes = message.serviceRoutes.map((e) => ServiceRoute.toJSON(e));
17269
16887
  }
17270
16888
  return obj;
17271
16889
  },
@@ -17273,16 +16891,12 @@ const Timetable$1 = {
17273
16891
  return Timetable$1.fromPartial(base !== null && base !== void 0 ? base : {});
17274
16892
  },
17275
16893
  fromPartial(object) {
17276
- var _a, _b;
16894
+ var _a, _b, _c, _d;
17277
16895
  const message = createBaseTimetable();
17278
16896
  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;
16897
+ message.stopsAdjacency = ((_b = object.stopsAdjacency) === null || _b === void 0 ? void 0 : _b.map((e) => StopAdjacency.fromPartial(e))) || [];
16898
+ message.routesAdjacency = ((_c = object.routesAdjacency) === null || _c === void 0 ? void 0 : _c.map((e) => Route$2.fromPartial(e))) || [];
16899
+ message.serviceRoutes = ((_d = object.serviceRoutes) === null || _d === void 0 ? void 0 : _d.map((e) => ServiceRoute.fromPartial(e))) || [];
17286
16900
  return message;
17287
16901
  },
17288
16902
  };
@@ -17311,9 +16925,6 @@ function base64FromBytes(arr) {
17311
16925
  return globalThis.btoa(bin.join(""));
17312
16926
  }
17313
16927
  }
17314
- function isObject(value) {
17315
- return typeof value === "object" && value !== null;
17316
- }
17317
16928
  function isSet(value) {
17318
16929
  return value !== null && value !== undefined;
17319
16930
  }
@@ -17829,18 +17440,14 @@ const bytesToUint16Array = (bytes) => {
17829
17440
  return result;
17830
17441
  };
17831
17442
  const serializeStopsAdjacency = (stopsAdjacency) => {
17832
- const protoStopsAdjacency = {
17833
- stops: {},
17834
- };
17835
- stopsAdjacency.forEach((value, key) => {
17836
- protoStopsAdjacency.stops[key] = {
17443
+ return stopsAdjacency.map((value) => {
17444
+ return {
17837
17445
  transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: serializeTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
17838
17446
  minTransferTime: transfer.minTransferTime.toSeconds(),
17839
17447
  })))),
17840
17448
  routes: value.routes,
17841
17449
  };
17842
17450
  });
17843
- return protoStopsAdjacency;
17844
17451
  };
17845
17452
  const serializeRoutesAdjacency = (routesAdjacency) => {
17846
17453
  const protoRoutesAdjacency = [];
@@ -17855,31 +17462,24 @@ const serializeRoutesAdjacency = (routesAdjacency) => {
17855
17462
  });
17856
17463
  return protoRoutesAdjacency;
17857
17464
  };
17858
- const serializeServiceRoutesMap = (serviceRoutesMap) => {
17859
- const protoServiceRoutesMap = {
17860
- routes: {},
17861
- };
17862
- serviceRoutesMap.forEach((value, key) => {
17863
- protoServiceRoutesMap.routes[key] = {
17465
+ const serializeServiceRoutesMap = (serviceRoutes) => {
17466
+ return serviceRoutes.map((value) => {
17467
+ return {
17864
17468
  type: serializeRouteType(value.type),
17865
17469
  name: value.name,
17866
17470
  routes: value.routes,
17867
17471
  };
17868
17472
  });
17869
- return protoServiceRoutesMap;
17870
17473
  };
17871
17474
  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, {
17475
+ return protoStopsAdjacency.map((value) => {
17476
+ return {
17876
17477
  transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: parseTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
17877
17478
  minTransferTime: Duration.fromSeconds(transfer.minTransferTime),
17878
17479
  })))),
17879
17480
  routes: value.routes,
17880
- });
17481
+ };
17881
17482
  });
17882
- return stopsAdjacency;
17883
17483
  };
17884
17484
  const deserializeRoutesAdjacency = (protoRoutesAdjacency) => {
17885
17485
  const routesAdjacency = [];
@@ -17889,16 +17489,14 @@ const deserializeRoutesAdjacency = (protoRoutesAdjacency) => {
17889
17489
  });
17890
17490
  return routesAdjacency;
17891
17491
  };
17892
- const deserializeServiceRoutesMap = (protoServiceRoutesMap) => {
17893
- const serviceRoutesMap = new Map();
17894
- Object.entries(protoServiceRoutesMap.routes).forEach(([key, value]) => {
17895
- serviceRoutesMap.set(key, {
17492
+ const deserializeServiceRoutesMap = (protoServiceRoutes) => {
17493
+ return protoServiceRoutes.map((value) => {
17494
+ return {
17896
17495
  type: parseRouteType(value.type),
17897
17496
  name: value.name,
17898
17497
  routes: value.routes,
17899
- });
17498
+ };
17900
17499
  });
17901
- return serviceRoutesMap;
17902
17500
  };
17903
17501
  const parseTransferType = (type) => {
17904
17502
  switch (type) {
@@ -17990,7 +17588,7 @@ const ALL_TRANSPORT_MODES = new Set([
17990
17588
  'TROLLEYBUS',
17991
17589
  'MONORAIL',
17992
17590
  ]);
17993
- const CURRENT_VERSION = '0.0.5';
17591
+ const CURRENT_VERSION = '0.0.6';
17994
17592
  /**
17995
17593
  * The internal transit timetable format.
17996
17594
  */
@@ -17998,7 +17596,15 @@ class Timetable {
17998
17596
  constructor(stopsAdjacency, routesAdjacency, routes) {
17999
17597
  this.stopsAdjacency = stopsAdjacency;
18000
17598
  this.routesAdjacency = routesAdjacency;
18001
- this.routes = routes;
17599
+ this.serviceRoutes = routes;
17600
+ this.activeStops = new Set();
17601
+ for (let i = 0; i < stopsAdjacency.length; i++) {
17602
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17603
+ const stop = stopsAdjacency[i];
17604
+ if (stop.routes.length > 0 || stop.transfers.length > 0) {
17605
+ this.activeStops.add(i);
17606
+ }
17607
+ }
18002
17608
  }
18003
17609
  /**
18004
17610
  * Serializes the Timetable into a binary array.
@@ -18010,7 +17616,7 @@ class Timetable {
18010
17616
  version: CURRENT_VERSION,
18011
17617
  stopsAdjacency: serializeStopsAdjacency(this.stopsAdjacency),
18012
17618
  routesAdjacency: serializeRoutesAdjacency(this.routesAdjacency),
18013
- routes: serializeServiceRoutesMap(this.routes),
17619
+ serviceRoutes: serializeServiceRoutesMap(this.serviceRoutes),
18014
17620
  };
18015
17621
  const writer = new BinaryWriter();
18016
17622
  Timetable$1.encode(protoTimetable, writer);
@@ -18028,11 +17634,18 @@ class Timetable {
18028
17634
  if (protoTimetable.version !== CURRENT_VERSION) {
18029
17635
  throw new Error(`Unsupported timetable version ${protoTimetable.version}`);
18030
17636
  }
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));
17637
+ return new Timetable(deserializeStopsAdjacency(protoTimetable.stopsAdjacency), deserializeRoutesAdjacency(protoTimetable.routesAdjacency), deserializeServiceRoutesMap(protoTimetable.serviceRoutes));
17638
+ }
17639
+ /**
17640
+ * Checks if the given stop is active on the timetable.
17641
+ * An active stop is a stop reached by a route that is active on the timetable
17642
+ * or by a transfer reachable from an active route.
17643
+ *
17644
+ * @param stopId - The ID of the stop to check.
17645
+ * @returns True if the stop is active, false otherwise.
17646
+ */
17647
+ isActive(stopId) {
17648
+ return this.activeStops.has(stopId);
18036
17649
  }
18037
17650
  /**
18038
17651
  * Retrieves the route associated with the given route ID.
@@ -18052,7 +17665,7 @@ class Timetable {
18052
17665
  */
18053
17666
  getTransfers(stopId) {
18054
17667
  var _a, _b;
18055
- return (_b = (_a = this.stopsAdjacency.get(stopId)) === null || _a === void 0 ? void 0 : _a.transfers) !== null && _b !== void 0 ? _b : [];
17668
+ return (_b = (_a = this.stopsAdjacency[stopId]) === null || _a === void 0 ? void 0 : _a.transfers) !== null && _b !== void 0 ? _b : [];
18056
17669
  }
18057
17670
  /**
18058
17671
  * Retrieves the service route associated with the given route.
@@ -18063,7 +17676,7 @@ class Timetable {
18063
17676
  * @returns The service route corresponding to the provided route.
18064
17677
  */
18065
17678
  getServiceRouteInfo(route) {
18066
- const serviceRoute = this.routes.get(route.serviceRoute());
17679
+ const serviceRoute = this.serviceRoutes[route.serviceRoute()];
18067
17680
  if (!serviceRoute) {
18068
17681
  throw new Error(`Service route not found for route ID: ${route.serviceRoute()}`);
18069
17682
  }
@@ -18078,7 +17691,7 @@ class Timetable {
18078
17691
  * @returns An array of routes passing through the specified stop.
18079
17692
  */
18080
17693
  routesPassingThrough(stopId) {
18081
- const stopData = this.stopsAdjacency.get(stopId);
17694
+ const stopData = this.stopsAdjacency[stopId];
18082
17695
  if (!stopData) {
18083
17696
  return [];
18084
17697
  }
@@ -20109,7 +19722,6 @@ const parseRoutes = (routesStream_1, ...args_1) => __awaiter(void 0, [routesStre
20109
19722
  routes.set(line.route_id, {
20110
19723
  name: line.route_short_name,
20111
19724
  type: routeType,
20112
- routes: [],
20113
19725
  });
20114
19726
  }
20115
19727
  }
@@ -20122,6 +19734,29 @@ const parseRoutes = (routesStream_1, ...args_1) => __awaiter(void 0, [routesStre
20122
19734
  }
20123
19735
  return routes;
20124
19736
  });
19737
+ /**
19738
+ * Creates an array of ServiceRoute objects by combining GTFS route data with service route mappings.
19739
+ *
19740
+ * @param gtfsRoutesMap A map containing GTFS route information indexed by route ID
19741
+ * @param serviceRoutesMap A map linking GTFS route IDs to service route IDs
19742
+ * @returns An array of ServiceRoute objects with route information
19743
+ */
19744
+ const indexRoutes = (gtfsRoutesMap, serviceRoutesMap) => {
19745
+ const serviceRoutes = new Array(serviceRoutesMap.size);
19746
+ for (const [gtfsRouteId, serviceRouteId] of serviceRoutesMap) {
19747
+ const route = gtfsRoutesMap.get(gtfsRouteId);
19748
+ if (route === undefined) {
19749
+ log.warn(`Route ${gtfsRouteId} not found.`);
19750
+ continue;
19751
+ }
19752
+ serviceRoutes[serviceRouteId] = {
19753
+ name: route.name,
19754
+ type: route.type,
19755
+ routes: [],
19756
+ };
19757
+ }
19758
+ return serviceRoutes;
19759
+ };
20125
19760
 
20126
19761
  const toGtfsDate = (date) => {
20127
19762
  return parseInt(date.toFormat('yyyyLLdd'));
@@ -20289,37 +19924,6 @@ const parseStops = (stopsStream) => __awaiter(void 0, void 0, void 0, function*
20289
19924
  }
20290
19925
  return parsedStops;
20291
19926
  });
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
19927
  const parseGtfsLocationType = (gtfsLocationType) => {
20324
19928
  switch (gtfsLocationType) {
20325
19929
  case 0:
@@ -20496,7 +20100,7 @@ const finalizeRouteFromBuilder = (builder) => {
20496
20100
  * @param serviceRoutes A mapping of route IDs to route details.
20497
20101
  * @returns A mapping of trip IDs to corresponding route IDs.
20498
20102
  */
20499
- const parseTrips = (tripsStream, serviceIds, serviceRoutes) => __awaiter(void 0, void 0, void 0, function* () {
20103
+ const parseTrips = (tripsStream, serviceIds, validGtfsRoutes) => __awaiter(void 0, void 0, void 0, function* () {
20500
20104
  var _a, e_1, _b, _c;
20501
20105
  const trips = new Map();
20502
20106
  try {
@@ -20509,7 +20113,7 @@ const parseTrips = (tripsStream, serviceIds, serviceRoutes) => __awaiter(void 0,
20509
20113
  // The trip doesn't correspond to an active service
20510
20114
  continue;
20511
20115
  }
20512
- if (!serviceRoutes.get(line.route_id)) {
20116
+ if (!validGtfsRoutes.has(line.route_id)) {
20513
20117
  // The trip doesn't correspond to a supported route
20514
20118
  continue;
20515
20119
  }
@@ -20525,29 +20129,32 @@ const parseTrips = (tripsStream, serviceIds, serviceRoutes) => __awaiter(void 0,
20525
20129
  }
20526
20130
  return trips;
20527
20131
  });
20528
- const buildStopsAdjacencyStructure = (validStops, serviceRoutes, routes, transfersMap) => {
20529
- const stopsAdjacency = new Map();
20132
+ const buildStopsAdjacencyStructure = (serviceRoutes, routes, transfersMap, nbStops, activeStops) => {
20133
+ // TODO somehow works when it's a map
20134
+ const stopsAdjacency = new Array(nbStops);
20135
+ for (let i = 0; i < nbStops; i++) {
20136
+ stopsAdjacency[i] = { routes: [], transfers: [] };
20137
+ }
20530
20138
  routes.forEach((route, index) => {
20531
- var _a;
20532
20139
  for (const stop of route.stopsIterator()) {
20533
- if (!stopsAdjacency.get(stop) && validStops.has(stop)) {
20534
- stopsAdjacency.set(stop, { routes: [], transfers: [] });
20140
+ if (activeStops.has(stop)) {
20141
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20142
+ stopsAdjacency[stop].routes.push(index);
20535
20143
  }
20536
- (_a = stopsAdjacency.get(stop)) === null || _a === void 0 ? void 0 : _a.routes.push(index);
20537
20144
  }
20538
- const serviceRoute = serviceRoutes.get(route.serviceRoute());
20539
- if (!serviceRoute) {
20145
+ const serviceRoute = serviceRoutes[route.serviceRoute()];
20146
+ if (serviceRoute === undefined) {
20540
20147
  throw new Error(`Service route ${route.serviceRoute()} not found for route ${index}.`);
20541
20148
  }
20542
20149
  serviceRoute.routes.push(index);
20543
20150
  });
20544
20151
  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
- }
20152
+ for (const transfer of transfers) {
20153
+ if (activeStops.has(stop) || activeStops.has(transfer.destination)) {
20154
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20155
+ stopsAdjacency[stop].transfers.push(transfer);
20156
+ activeStops.add(transfer.destination);
20157
+ activeStops.add(stop);
20551
20158
  }
20552
20159
  }
20553
20160
  }
@@ -20558,18 +20165,18 @@ const buildStopsAdjacencyStructure = (validStops, serviceRoutes, routes, transfe
20558
20165
  *
20559
20166
  * @param stopTimesStream The readable stream containing the stop times data.
20560
20167
  * @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.
20168
+ * @param activeTripIds A map of valid trip IDs to corresponding route IDs.
20169
+ * @param activeStopIds A set of valid stop IDs.
20563
20170
  * @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
20171
  */
20565
- const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) => __awaiter(void 0, void 0, void 0, function* () {
20172
+ const parseStopTimes = (stopTimesStream, stopsMap, activeTripIds, activeStopIds) => __awaiter(void 0, void 0, void 0, function* () {
20566
20173
  var _a, e_2, _b, _c;
20567
20174
  var _d, _e;
20568
20175
  /**
20569
20176
  * Adds a trip to the appropriate route builder
20570
20177
  */
20571
20178
  const addTrip = (currentTripId) => {
20572
- const gtfsRouteId = validTripIds.get(currentTripId);
20179
+ const gtfsRouteId = activeTripIds.get(currentTripId);
20573
20180
  if (!gtfsRouteId || stops.length === 0) {
20574
20181
  stops = [];
20575
20182
  arrivalTimes = [];
@@ -20578,7 +20185,6 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20578
20185
  dropOffTypes = [];
20579
20186
  return;
20580
20187
  }
20581
- const routeId = `${gtfsRouteId}_${hashIds(stops)}`;
20582
20188
  const firstDeparture = departureTimes[0];
20583
20189
  if (firstDeparture === undefined) {
20584
20190
  console.warn(`Empty trip ${currentTripId}`);
@@ -20589,24 +20195,31 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20589
20195
  dropOffTypes = [];
20590
20196
  return;
20591
20197
  }
20198
+ const routeId = `${gtfsRouteId}_${hashIds(stops)}`;
20592
20199
  let routeBuilder = routeBuilders.get(routeId);
20593
20200
  if (!routeBuilder) {
20201
+ let serviceRouteId = serviceRoutesMap.get(gtfsRouteId);
20202
+ if (serviceRouteId === undefined) {
20203
+ serviceRouteId = currentServiceRouteId;
20204
+ serviceRoutesMap.set(gtfsRouteId, serviceRouteId);
20205
+ currentServiceRouteId = currentServiceRouteId + 1;
20206
+ }
20594
20207
  routeBuilder = {
20595
- serviceRouteId: gtfsRouteId,
20596
- stops: [...stops],
20208
+ serviceRouteId,
20209
+ stops,
20597
20210
  trips: [],
20598
20211
  };
20599
20212
  routeBuilders.set(routeId, routeBuilder);
20600
20213
  for (const stop of stops) {
20601
- validStopIds.add(stop);
20214
+ activeStopIds.add(stop);
20602
20215
  }
20603
20216
  }
20604
20217
  routeBuilder.trips.push({
20605
20218
  firstDeparture,
20606
- arrivalTimes: [...arrivalTimes],
20607
- departureTimes: [...departureTimes],
20608
- pickUpTypes: [...pickUpTypes],
20609
- dropOffTypes: [...dropOffTypes],
20219
+ arrivalTimes: arrivalTimes,
20220
+ departureTimes: departureTimes,
20221
+ pickUpTypes: pickUpTypes,
20222
+ dropOffTypes: dropOffTypes,
20610
20223
  });
20611
20224
  stops = [];
20612
20225
  arrivalTimes = [];
@@ -20615,6 +20228,9 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20615
20228
  dropOffTypes = [];
20616
20229
  };
20617
20230
  const routeBuilders = new Map();
20231
+ const serviceRoutesMap = new Map();
20232
+ // incrementally generate service route IDs
20233
+ let currentServiceRouteId = 0;
20618
20234
  let previousSeq = 0;
20619
20235
  let stops = [];
20620
20236
  let arrivalTimes = [];
@@ -20677,7 +20293,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20677
20293
  const routeData = finalizeRouteFromBuilder(routeBuilder);
20678
20294
  routesAdjacency.push(new Route$1(routeData.stopTimes, routeData.pickUpDropOffTypes, routeData.stops, routeData.serviceRouteId));
20679
20295
  }
20680
- return routesAdjacency;
20296
+ return { routes: routesAdjacency, serviceRoutesMap };
20681
20297
  });
20682
20298
  const parsePickupDropOffType = (gtfsType) => {
20683
20299
  switch (gtfsType) {
@@ -20711,18 +20327,16 @@ class GtfsParser {
20711
20327
  * Parses a GTFS feed to extract all the data relevant to a given day in a transit-planner friendly format.
20712
20328
  *
20713
20329
  * @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.
20330
+ * @returns The parsed timetable.
20717
20331
  */
20718
- parse(date) {
20332
+ parseTimetable(date) {
20719
20333
  return __awaiter(this, void 0, void 0, function* () {
20720
20334
  log.setLevel('INFO');
20721
20335
  const zip = new StreamZip.async({ file: this.path });
20722
20336
  const entries = yield zip.entries();
20723
20337
  const datetime = DateTime.fromJSDate(date);
20724
- const validServiceIds = new Set();
20725
- const validStopIds = new Set();
20338
+ const activeServiceIds = new Set();
20339
+ const activeStopIds = new Set();
20726
20340
  log.info(`Parsing ${STOPS_FILE}`);
20727
20341
  const stopsStart = performance.now();
20728
20342
  const stopsStream = yield zip.stream(STOPS_FILE);
@@ -20733,17 +20347,17 @@ class GtfsParser {
20733
20347
  log.info(`Parsing ${CALENDAR_FILE}`);
20734
20348
  const calendarStart = performance.now();
20735
20349
  const calendarStream = yield zip.stream(CALENDAR_FILE);
20736
- yield parseCalendar(calendarStream, validServiceIds, datetime);
20350
+ yield parseCalendar(calendarStream, activeServiceIds, datetime);
20737
20351
  const calendarEnd = performance.now();
20738
- log.info(`${validServiceIds.size} valid services. (${(calendarEnd - calendarStart).toFixed(2)}ms)`);
20352
+ log.info(`${activeServiceIds.size} valid services. (${(calendarEnd - calendarStart).toFixed(2)}ms)`);
20739
20353
  }
20740
20354
  if (entries[CALENDAR_DATES_FILE]) {
20741
20355
  log.info(`Parsing ${CALENDAR_DATES_FILE}`);
20742
20356
  const calendarDatesStart = performance.now();
20743
20357
  const calendarDatesStream = yield zip.stream(CALENDAR_DATES_FILE);
20744
- yield parseCalendarDates(calendarDatesStream, validServiceIds, datetime);
20358
+ yield parseCalendarDates(calendarDatesStream, activeServiceIds, datetime);
20745
20359
  const calendarDatesEnd = performance.now();
20746
- log.info(`${validServiceIds.size} valid services. (${(calendarDatesEnd - calendarDatesStart).toFixed(2)}ms)`);
20360
+ log.info(`${activeServiceIds.size} valid services. (${(calendarDatesEnd - calendarDatesStart).toFixed(2)}ms)`);
20747
20361
  }
20748
20362
  log.info(`Parsing ${ROUTES_FILE}`);
20749
20363
  const routesStart = performance.now();
@@ -20754,7 +20368,7 @@ class GtfsParser {
20754
20368
  log.info(`Parsing ${TRIPS_FILE}`);
20755
20369
  const tripsStart = performance.now();
20756
20370
  const tripsStream = yield zip.stream(TRIPS_FILE);
20757
- const trips = yield parseTrips(tripsStream, validServiceIds, validGtfsRoutes);
20371
+ const trips = yield parseTrips(tripsStream, activeServiceIds, validGtfsRoutes);
20758
20372
  const tripsEnd = performance.now();
20759
20373
  log.info(`${trips.size} valid trips. (${(tripsEnd - tripsStart).toFixed(2)}ms)`);
20760
20374
  let transfers = new Map();
@@ -20769,32 +20383,26 @@ class GtfsParser {
20769
20383
  log.info(`Parsing ${STOP_TIMES_FILE}`);
20770
20384
  const stopTimesStart = performance.now();
20771
20385
  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);
20386
+ const { routes, serviceRoutesMap } = yield parseStopTimes(stopTimesStream, parsedStops, trips, activeStopIds);
20387
+ const serviceRoutes = indexRoutes(validGtfsRoutes, serviceRoutesMap);
20774
20388
  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)`);
20389
+ log.info(`${routes.length} valid unique routes. (${(stopTimesEnd - stopTimesStart).toFixed(2)}ms)`);
20390
+ log.info('Building stops adjacency structure');
20391
+ const stopsAdjacencyStart = performance.now();
20392
+ const stopsAdjacency = buildStopsAdjacencyStructure(serviceRoutes, routes, transfers, parsedStops.size, activeStopIds);
20393
+ const stopsAdjacencyEnd = performance.now();
20394
+ log.info(`${stopsAdjacency.length} valid stops in the structure. (${(stopsAdjacencyEnd - stopsAdjacencyStart).toFixed(2)}ms)`);
20781
20395
  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)`);
20396
+ const timetable = new Timetable(stopsAdjacency, routes, serviceRoutes);
20788
20397
  log.info('Parsing complete.');
20789
- return { timetable, stopsIndex };
20398
+ return timetable;
20790
20399
  });
20791
20400
  }
20792
20401
  /**
20793
20402
  * Parses a GTFS feed to extract all stops.
20794
20403
  *
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.
20404
+ * @param activeStops The set of active stop IDs to include in the index.
20405
+ * @returns An index of stops.
20798
20406
  */
20799
20407
  parseStops() {
20800
20408
  return __awaiter(this, void 0, void 0, function* () {
@@ -20802,11 +20410,11 @@ class GtfsParser {
20802
20410
  log.info(`Parsing ${STOPS_FILE}`);
20803
20411
  const stopsStart = performance.now();
20804
20412
  const stopsStream = yield zip.stream(STOPS_FILE);
20805
- const stops = indexStops(yield parseStops(stopsStream));
20413
+ const stops = yield parseStops(stopsStream);
20806
20414
  const stopsEnd = performance.now();
20807
20415
  log.info(`${stops.size} parsed stops. (${(stopsEnd - stopsStart).toFixed(2)}ms)`);
20808
20416
  yield zip.close();
20809
- return new StopsIndex(stops);
20417
+ return new StopsIndex(Array.from(stops.values()));
20810
20418
  });
20811
20419
  }
20812
20420
  }
@@ -21316,6 +20924,8 @@ class Router {
21316
20924
  for (const [route, hopOnStop] of reachableRoutes.entries()) {
21317
20925
  let currentTrip = undefined;
21318
20926
  for (const currentStop of route.stopsIterator(hopOnStop)) {
20927
+ // If we're currently on a trip,
20928
+ // check if arrival at the stop improves the earliest arrival time
21319
20929
  if (currentTrip !== undefined) {
21320
20930
  const currentArrivalTime = route.arrivalAt(currentStop, currentTrip.tripIndex);
21321
20931
  const currentDropOffType = route.dropOffTypeAt(currentStop, currentTrip.tripIndex);
@@ -21344,7 +20954,7 @@ class Router {
21344
20954
  markedStops.add(currentStop);
21345
20955
  }
21346
20956
  }
21347
- // check if we can catch a previous trip at the current stop
20957
+ // check if we can board an earlier trip at the current stop
21348
20958
  // if there was no current trip, find the first one reachable
21349
20959
  const earliestArrivalOnPreviousRound = (_c = arrivalsAtPreviousRound.get(currentStop)) === null || _c === void 0 ? void 0 : _c.arrival;
21350
20960
  if (earliestArrivalOnPreviousRound !== undefined &&
@@ -21669,9 +21279,10 @@ program
21669
21279
  log.setDefaultLevel(log.levels.ERROR);
21670
21280
  }
21671
21281
  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());
21282
+ const stopsIndex = yield parser.parseStops();
21674
21283
  fs.writeFileSync(options.stopsOutputPath, stopsIndex.serialize());
21284
+ const timetable = yield parser.parseTimetable(new Date(options.date));
21285
+ fs.writeFileSync(options.timetableOutputPath, timetable.serialize());
21675
21286
  }));
21676
21287
  program
21677
21288
  .command('parse-stops')