minotor 5.0.0 → 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 (59) hide show
  1. package/CHANGELOG.md +3 -4
  2. package/dist/cli.mjs +212 -632
  3. package/dist/cli.mjs.map +1 -1
  4. package/dist/gtfs/parser.d.ts +4 -13
  5. package/dist/gtfs/routes.d.ts +16 -2
  6. package/dist/gtfs/stops.d.ts +3 -14
  7. package/dist/gtfs/transfers.d.ts +2 -2
  8. package/dist/gtfs/trips.d.ts +12 -8
  9. package/dist/parser.cjs.js +206 -629
  10. package/dist/parser.cjs.js.map +1 -1
  11. package/dist/parser.esm.js +206 -629
  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 +7 -137
  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 +34 -57
  36. package/src/gtfs/profiles/__tests__/ch.test.ts +0 -28
  37. package/src/gtfs/profiles/ch.ts +1 -18
  38. package/src/gtfs/profiles/standard.ts +0 -9
  39. package/src/gtfs/routes.ts +43 -5
  40. package/src/gtfs/stops.ts +4 -56
  41. package/src/gtfs/transfers.ts +2 -2
  42. package/src/gtfs/trips.ts +57 -40
  43. package/src/routing/__tests__/result.test.ts +48 -48
  44. package/src/routing/__tests__/router.test.ts +279 -363
  45. package/src/routing/router.ts +3 -1
  46. package/src/stops/__tests__/io.test.ts +25 -31
  47. package/src/stops/__tests__/stopFinder.test.ts +82 -103
  48. package/src/stops/io.ts +8 -17
  49. package/src/stops/proto/stops.proto +3 -3
  50. package/src/stops/proto/stops.ts +16 -120
  51. package/src/stops/stops.ts +0 -4
  52. package/src/stops/stopsIndex.ts +20 -26
  53. package/src/timetable/__tests__/io.test.ts +44 -54
  54. package/src/timetable/__tests__/route.test.ts +11 -11
  55. package/src/timetable/__tests__/timetable.test.ts +29 -37
  56. package/src/timetable/io.ts +38 -66
  57. package/src/timetable/proto/timetable.proto +6 -13
  58. package/src/timetable/proto/timetable.ts +43 -385
  59. 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
  }
@@ -18151,12 +17764,6 @@ const standardProfile = {
18151
17764
  return undefined;
18152
17765
  }
18153
17766
  },
18154
- platformParser: (stopEntry) => {
18155
- if (stopEntry.platform_code) {
18156
- return stopEntry.platform_code;
18157
- }
18158
- return undefined;
18159
- },
18160
17767
  };
18161
17768
 
18162
17769
  const is_object = function (obj) {
@@ -20115,7 +19722,6 @@ const parseRoutes = (routesStream_1, ...args_1) => __awaiter(void 0, [routesStre
20115
19722
  routes.set(line.route_id, {
20116
19723
  name: line.route_short_name,
20117
19724
  type: routeType,
20118
- routes: [],
20119
19725
  });
20120
19726
  }
20121
19727
  }
@@ -20128,6 +19734,29 @@ const parseRoutes = (routesStream_1, ...args_1) => __awaiter(void 0, [routesStre
20128
19734
  }
20129
19735
  return routes;
20130
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
+ };
20131
19760
 
20132
19761
  const toGtfsDate = (date) => {
20133
19762
  return parseInt(date.toFormat('yyyyLLdd'));
@@ -20254,7 +19883,7 @@ const parseCalendarDates = (calendarDatesStream, serviceIds, date) => __awaiter(
20254
19883
  * @param stopsStream The readable stream containing the stops data.
20255
19884
  * @return A mapping of stop IDs to corresponding stop details.
20256
19885
  */
20257
- const parseStops = (stopsStream, platformParser) => __awaiter(void 0, void 0, void 0, function* () {
19886
+ const parseStops = (stopsStream) => __awaiter(void 0, void 0, void 0, function* () {
20258
19887
  var _a, e_1, _b, _c;
20259
19888
  const parsedStops = new Map();
20260
19889
  let i = 0;
@@ -20268,20 +19897,9 @@ const parseStops = (stopsStream, platformParser) => __awaiter(void 0, void 0, vo
20268
19897
  _d = false;
20269
19898
  const rawLine = _c;
20270
19899
  const line = rawLine;
20271
- const stop = Object.assign({ id: i, sourceStopId: line.stop_id, name: line.stop_name, lat: line.stop_lat, lon: line.stop_lon, locationType: line.location_type
19900
+ const stop = Object.assign(Object.assign(Object.assign({ id: i, sourceStopId: line.stop_id, name: line.stop_name, lat: line.stop_lat, lon: line.stop_lon, locationType: line.location_type
20272
19901
  ? parseGtfsLocationType(line.location_type)
20273
- : 'SIMPLE_STOP_OR_PLATFORM', children: [] }, (line.parent_station && { parentSourceId: line.parent_station }));
20274
- if (platformParser) {
20275
- try {
20276
- const platform = platformParser(line);
20277
- if (platform) {
20278
- stop.platform = platform;
20279
- }
20280
- }
20281
- catch (_g) {
20282
- console.info(`Could not parse platform for stop ${line.stop_id}.`);
20283
- }
20284
- }
19902
+ : 'SIMPLE_STOP_OR_PLATFORM' }, (line.platform_code && { platform: line.platform_code })), { children: [] }), (line.parent_station && { parentSourceId: line.parent_station }));
20285
19903
  parsedStops.set(line.stop_id, stop);
20286
19904
  i = i + 1;
20287
19905
  }
@@ -20306,37 +19924,6 @@ const parseStops = (stopsStream, platformParser) => __awaiter(void 0, void 0, vo
20306
19924
  }
20307
19925
  return parsedStops;
20308
19926
  });
20309
- /**
20310
- * Builds the final stop map indexed by internal IDs.
20311
- * Excludes all stops that do not have at least one valid stopId
20312
- * as a child, a parent, or being valid itself.
20313
- *
20314
- * @param parsedStops - The map of parsed stops.
20315
- * @param validStops - A set of valid stop IDs.
20316
- * @returns A map of stops indexed by internal IDs.
20317
- */
20318
- const indexStops = (parsedStops, validStops) => {
20319
- const stops = new Map();
20320
- for (const [, stop] of parsedStops) {
20321
- if (!validStops ||
20322
- validStops.has(stop.id) ||
20323
- (stop.parent && validStops.has(stop.parent)) ||
20324
- stop.children.some((childId) => validStops.has(childId))) {
20325
- stops.set(stop.id, {
20326
- id: stop.id,
20327
- sourceStopId: stop.sourceStopId,
20328
- name: stop.name,
20329
- lat: stop.lat,
20330
- lon: stop.lon,
20331
- locationType: stop.locationType,
20332
- platform: stop.platform,
20333
- children: stop.children.filter((childId) => !validStops || validStops.has(childId)),
20334
- parent: stop.parent,
20335
- });
20336
- }
20337
- }
20338
- return stops;
20339
- };
20340
19927
  const parseGtfsLocationType = (gtfsLocationType) => {
20341
19928
  switch (gtfsLocationType) {
20342
19929
  case 0:
@@ -20513,7 +20100,7 @@ const finalizeRouteFromBuilder = (builder) => {
20513
20100
  * @param serviceRoutes A mapping of route IDs to route details.
20514
20101
  * @returns A mapping of trip IDs to corresponding route IDs.
20515
20102
  */
20516
- 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* () {
20517
20104
  var _a, e_1, _b, _c;
20518
20105
  const trips = new Map();
20519
20106
  try {
@@ -20526,7 +20113,7 @@ const parseTrips = (tripsStream, serviceIds, serviceRoutes) => __awaiter(void 0,
20526
20113
  // The trip doesn't correspond to an active service
20527
20114
  continue;
20528
20115
  }
20529
- if (!serviceRoutes.get(line.route_id)) {
20116
+ if (!validGtfsRoutes.has(line.route_id)) {
20530
20117
  // The trip doesn't correspond to a supported route
20531
20118
  continue;
20532
20119
  }
@@ -20542,29 +20129,32 @@ const parseTrips = (tripsStream, serviceIds, serviceRoutes) => __awaiter(void 0,
20542
20129
  }
20543
20130
  return trips;
20544
20131
  });
20545
- const buildStopsAdjacencyStructure = (validStops, serviceRoutes, routes, transfersMap) => {
20546
- 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
+ }
20547
20138
  routes.forEach((route, index) => {
20548
- var _a;
20549
20139
  for (const stop of route.stopsIterator()) {
20550
- if (!stopsAdjacency.get(stop) && validStops.has(stop)) {
20551
- 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);
20552
20143
  }
20553
- (_a = stopsAdjacency.get(stop)) === null || _a === void 0 ? void 0 : _a.routes.push(index);
20554
20144
  }
20555
- const serviceRoute = serviceRoutes.get(route.serviceRoute());
20556
- if (!serviceRoute) {
20145
+ const serviceRoute = serviceRoutes[route.serviceRoute()];
20146
+ if (serviceRoute === undefined) {
20557
20147
  throw new Error(`Service route ${route.serviceRoute()} not found for route ${index}.`);
20558
20148
  }
20559
20149
  serviceRoute.routes.push(index);
20560
20150
  });
20561
20151
  for (const [stop, transfers] of transfersMap) {
20562
- const s = stopsAdjacency.get(stop);
20563
- if (s) {
20564
- for (const transfer of transfers) {
20565
- if (validStops.has(transfer.destination)) {
20566
- s.transfers.push(transfer);
20567
- }
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);
20568
20158
  }
20569
20159
  }
20570
20160
  }
@@ -20575,18 +20165,18 @@ const buildStopsAdjacencyStructure = (validStops, serviceRoutes, routes, transfe
20575
20165
  *
20576
20166
  * @param stopTimesStream The readable stream containing the stop times data.
20577
20167
  * @param stopsMap A map of parsed stops from the GTFS feed.
20578
- * @param validTripIds A map of valid trip IDs to corresponding route IDs.
20579
- * @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.
20580
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.
20581
20171
  */
20582
- 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* () {
20583
20173
  var _a, e_2, _b, _c;
20584
20174
  var _d, _e;
20585
20175
  /**
20586
20176
  * Adds a trip to the appropriate route builder
20587
20177
  */
20588
20178
  const addTrip = (currentTripId) => {
20589
- const gtfsRouteId = validTripIds.get(currentTripId);
20179
+ const gtfsRouteId = activeTripIds.get(currentTripId);
20590
20180
  if (!gtfsRouteId || stops.length === 0) {
20591
20181
  stops = [];
20592
20182
  arrivalTimes = [];
@@ -20595,7 +20185,6 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20595
20185
  dropOffTypes = [];
20596
20186
  return;
20597
20187
  }
20598
- const routeId = `${gtfsRouteId}_${hashIds(stops)}`;
20599
20188
  const firstDeparture = departureTimes[0];
20600
20189
  if (firstDeparture === undefined) {
20601
20190
  console.warn(`Empty trip ${currentTripId}`);
@@ -20606,24 +20195,31 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20606
20195
  dropOffTypes = [];
20607
20196
  return;
20608
20197
  }
20198
+ const routeId = `${gtfsRouteId}_${hashIds(stops)}`;
20609
20199
  let routeBuilder = routeBuilders.get(routeId);
20610
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
+ }
20611
20207
  routeBuilder = {
20612
- serviceRouteId: gtfsRouteId,
20613
- stops: [...stops],
20208
+ serviceRouteId,
20209
+ stops,
20614
20210
  trips: [],
20615
20211
  };
20616
20212
  routeBuilders.set(routeId, routeBuilder);
20617
20213
  for (const stop of stops) {
20618
- validStopIds.add(stop);
20214
+ activeStopIds.add(stop);
20619
20215
  }
20620
20216
  }
20621
20217
  routeBuilder.trips.push({
20622
20218
  firstDeparture,
20623
- arrivalTimes: [...arrivalTimes],
20624
- departureTimes: [...departureTimes],
20625
- pickUpTypes: [...pickUpTypes],
20626
- dropOffTypes: [...dropOffTypes],
20219
+ arrivalTimes: arrivalTimes,
20220
+ departureTimes: departureTimes,
20221
+ pickUpTypes: pickUpTypes,
20222
+ dropOffTypes: dropOffTypes,
20627
20223
  });
20628
20224
  stops = [];
20629
20225
  arrivalTimes = [];
@@ -20632,6 +20228,9 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20632
20228
  dropOffTypes = [];
20633
20229
  };
20634
20230
  const routeBuilders = new Map();
20231
+ const serviceRoutesMap = new Map();
20232
+ // incrementally generate service route IDs
20233
+ let currentServiceRouteId = 0;
20635
20234
  let previousSeq = 0;
20636
20235
  let stops = [];
20637
20236
  let arrivalTimes = [];
@@ -20694,7 +20293,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
20694
20293
  const routeData = finalizeRouteFromBuilder(routeBuilder);
20695
20294
  routesAdjacency.push(new Route$1(routeData.stopTimes, routeData.pickUpDropOffTypes, routeData.stops, routeData.serviceRouteId));
20696
20295
  }
20697
- return routesAdjacency;
20296
+ return { routes: routesAdjacency, serviceRoutesMap };
20698
20297
  });
20699
20298
  const parsePickupDropOffType = (gtfsType) => {
20700
20299
  switch (gtfsType) {
@@ -20728,39 +20327,37 @@ class GtfsParser {
20728
20327
  * Parses a GTFS feed to extract all the data relevant to a given day in a transit-planner friendly format.
20729
20328
  *
20730
20329
  * @param date The active date.
20731
- * @param gtfsPath A path to the zipped GTFS feed.
20732
- * @param gtfsProfile The GTFS profile configuration.
20733
- * @returns An object containing the timetable and stops map.
20330
+ * @returns The parsed timetable.
20734
20331
  */
20735
- parse(date) {
20332
+ parseTimetable(date) {
20736
20333
  return __awaiter(this, void 0, void 0, function* () {
20737
20334
  log.setLevel('INFO');
20738
20335
  const zip = new StreamZip.async({ file: this.path });
20739
20336
  const entries = yield zip.entries();
20740
20337
  const datetime = DateTime.fromJSDate(date);
20741
- const validServiceIds = new Set();
20742
- const validStopIds = new Set();
20338
+ const activeServiceIds = new Set();
20339
+ const activeStopIds = new Set();
20743
20340
  log.info(`Parsing ${STOPS_FILE}`);
20744
20341
  const stopsStart = performance.now();
20745
20342
  const stopsStream = yield zip.stream(STOPS_FILE);
20746
- const parsedStops = yield parseStops(stopsStream, this.profile.platformParser);
20343
+ const parsedStops = yield parseStops(stopsStream);
20747
20344
  const stopsEnd = performance.now();
20748
20345
  log.info(`${parsedStops.size} parsed stops. (${(stopsEnd - stopsStart).toFixed(2)}ms)`);
20749
20346
  if (entries[CALENDAR_FILE]) {
20750
20347
  log.info(`Parsing ${CALENDAR_FILE}`);
20751
20348
  const calendarStart = performance.now();
20752
20349
  const calendarStream = yield zip.stream(CALENDAR_FILE);
20753
- yield parseCalendar(calendarStream, validServiceIds, datetime);
20350
+ yield parseCalendar(calendarStream, activeServiceIds, datetime);
20754
20351
  const calendarEnd = performance.now();
20755
- log.info(`${validServiceIds.size} valid services. (${(calendarEnd - calendarStart).toFixed(2)}ms)`);
20352
+ log.info(`${activeServiceIds.size} valid services. (${(calendarEnd - calendarStart).toFixed(2)}ms)`);
20756
20353
  }
20757
20354
  if (entries[CALENDAR_DATES_FILE]) {
20758
20355
  log.info(`Parsing ${CALENDAR_DATES_FILE}`);
20759
20356
  const calendarDatesStart = performance.now();
20760
20357
  const calendarDatesStream = yield zip.stream(CALENDAR_DATES_FILE);
20761
- yield parseCalendarDates(calendarDatesStream, validServiceIds, datetime);
20358
+ yield parseCalendarDates(calendarDatesStream, activeServiceIds, datetime);
20762
20359
  const calendarDatesEnd = performance.now();
20763
- log.info(`${validServiceIds.size} valid services. (${(calendarDatesEnd - calendarDatesStart).toFixed(2)}ms)`);
20360
+ log.info(`${activeServiceIds.size} valid services. (${(calendarDatesEnd - calendarDatesStart).toFixed(2)}ms)`);
20764
20361
  }
20765
20362
  log.info(`Parsing ${ROUTES_FILE}`);
20766
20363
  const routesStart = performance.now();
@@ -20771,7 +20368,7 @@ class GtfsParser {
20771
20368
  log.info(`Parsing ${TRIPS_FILE}`);
20772
20369
  const tripsStart = performance.now();
20773
20370
  const tripsStream = yield zip.stream(TRIPS_FILE);
20774
- const trips = yield parseTrips(tripsStream, validServiceIds, validGtfsRoutes);
20371
+ const trips = yield parseTrips(tripsStream, activeServiceIds, validGtfsRoutes);
20775
20372
  const tripsEnd = performance.now();
20776
20373
  log.info(`${trips.size} valid trips. (${(tripsEnd - tripsStart).toFixed(2)}ms)`);
20777
20374
  let transfers = new Map();
@@ -20786,32 +20383,26 @@ class GtfsParser {
20786
20383
  log.info(`Parsing ${STOP_TIMES_FILE}`);
20787
20384
  const stopTimesStart = performance.now();
20788
20385
  const stopTimesStream = yield zip.stream(STOP_TIMES_FILE);
20789
- const routesAdjacency = yield parseStopTimes(stopTimesStream, parsedStops, trips, validStopIds);
20790
- const stopsAdjacency = buildStopsAdjacencyStructure(validStopIds, validGtfsRoutes, routesAdjacency, transfers);
20386
+ const { routes, serviceRoutesMap } = yield parseStopTimes(stopTimesStream, parsedStops, trips, activeStopIds);
20387
+ const serviceRoutes = indexRoutes(validGtfsRoutes, serviceRoutesMap);
20791
20388
  const stopTimesEnd = performance.now();
20792
- log.info(`${routesAdjacency.length} valid unique routes. (${(stopTimesEnd - stopTimesStart).toFixed(2)}ms)`);
20793
- log.info(`Removing unused stops.`);
20794
- const indexStopsStart = performance.now();
20795
- const stops = indexStops(parsedStops, validStopIds);
20796
- const indexStopsEnd = performance.now();
20797
- 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)`);
20798
20395
  yield zip.close();
20799
- const timetable = new Timetable(stopsAdjacency, routesAdjacency, validGtfsRoutes);
20800
- log.info(`Building stops index.`);
20801
- const stopsIndexStart = performance.now();
20802
- const stopsIndex = new StopsIndex(stops);
20803
- const stopsIndexEnd = performance.now();
20804
- log.info(`Stops index built. (${(stopsIndexEnd - stopsIndexStart).toFixed(2)}ms)`);
20396
+ const timetable = new Timetable(stopsAdjacency, routes, serviceRoutes);
20805
20397
  log.info('Parsing complete.');
20806
- return { timetable, stopsIndex };
20398
+ return timetable;
20807
20399
  });
20808
20400
  }
20809
20401
  /**
20810
20402
  * Parses a GTFS feed to extract all stops.
20811
20403
  *
20812
- * @param gtfsPath A path the zipped GTFS feed.
20813
- * @param gtfsProfile The GTFS profile configuration.
20814
- * @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.
20815
20406
  */
20816
20407
  parseStops() {
20817
20408
  return __awaiter(this, void 0, void 0, function* () {
@@ -20819,28 +20410,15 @@ class GtfsParser {
20819
20410
  log.info(`Parsing ${STOPS_FILE}`);
20820
20411
  const stopsStart = performance.now();
20821
20412
  const stopsStream = yield zip.stream(STOPS_FILE);
20822
- const stops = indexStops(yield parseStops(stopsStream, this.profile.platformParser));
20413
+ const stops = yield parseStops(stopsStream);
20823
20414
  const stopsEnd = performance.now();
20824
20415
  log.info(`${stops.size} parsed stops. (${(stopsEnd - stopsStart).toFixed(2)}ms)`);
20825
20416
  yield zip.close();
20826
- return new StopsIndex(stops);
20417
+ return new StopsIndex(Array.from(stops.values()));
20827
20418
  });
20828
20419
  }
20829
20420
  }
20830
20421
 
20831
- /**
20832
- * Parses the platform number from a stop entry.
20833
- * @param stopEntry The stop entry.
20834
- * @returns The platform corresponding to this stop.
20835
- */
20836
- const platformParser = (stopEntry) => {
20837
- const stopId = stopEntry.stop_id;
20838
- const stopParts = stopId.split(':');
20839
- if (stopParts.length > 2) {
20840
- return stopParts[2];
20841
- }
20842
- return undefined;
20843
- };
20844
20422
  /**
20845
20423
  * Parses the SBB extended route type and returns the corresponding basic GTFS route type.
20846
20424
  * @param routeType The SBB route type to parse.
@@ -20867,6 +20445,7 @@ const routeTypeParser = (routeType) => {
20867
20445
  return 'FERRY'; // Boat
20868
20446
  case 900: // Tram
20869
20447
  return 'TRAM'; // Tram
20448
+ case 116: // ??? train TODO figure out what this means
20870
20449
  case 117: // Special train
20871
20450
  case 102: // International train
20872
20451
  case 104: // Car train
@@ -20878,7 +20457,6 @@ const routeTypeParser = (routeType) => {
20878
20457
  case 100: // No guaranteed train
20879
20458
  case 106: // Regional train
20880
20459
  case 109: // Urban train
20881
- case 116: // ??? train TODO figure out what this means
20882
20460
  return 'RAIL'; // Train
20883
20461
  case 1100: // Aircraft
20884
20462
  case 1500: // Taxi
@@ -20888,7 +20466,6 @@ const routeTypeParser = (routeType) => {
20888
20466
  };
20889
20467
  const chGtfsProfile = {
20890
20468
  routeTypeParser,
20891
- platformParser,
20892
20469
  };
20893
20470
 
20894
20471
  class Plotter {
@@ -21347,6 +20924,8 @@ class Router {
21347
20924
  for (const [route, hopOnStop] of reachableRoutes.entries()) {
21348
20925
  let currentTrip = undefined;
21349
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
21350
20929
  if (currentTrip !== undefined) {
21351
20930
  const currentArrivalTime = route.arrivalAt(currentStop, currentTrip.tripIndex);
21352
20931
  const currentDropOffType = route.dropOffTypeAt(currentStop, currentTrip.tripIndex);
@@ -21375,7 +20954,7 @@ class Router {
21375
20954
  markedStops.add(currentStop);
21376
20955
  }
21377
20956
  }
21378
- // 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
21379
20958
  // if there was no current trip, find the first one reachable
21380
20959
  const earliestArrivalOnPreviousRound = (_c = arrivalsAtPreviousRound.get(currentStop)) === null || _c === void 0 ? void 0 : _c.arrival;
21381
20960
  if (earliestArrivalOnPreviousRound !== undefined &&
@@ -21700,9 +21279,10 @@ program
21700
21279
  log.setDefaultLevel(log.levels.ERROR);
21701
21280
  }
21702
21281
  const parser = new GtfsParser(gtfsPath, profiles[options.profileName]);
21703
- const { timetable, stopsIndex } = yield parser.parse(new Date(options.date));
21704
- fs.writeFileSync(options.timetableOutputPath, timetable.serialize());
21282
+ const stopsIndex = yield parser.parseStops();
21705
21283
  fs.writeFileSync(options.stopsOutputPath, stopsIndex.serialize());
21284
+ const timetable = yield parser.parseTimetable(new Date(options.date));
21285
+ fs.writeFileSync(options.timetableOutputPath, timetable.serialize());
21706
21286
  }));
21707
21287
  program
21708
21288
  .command('parse-stops')