minotor 1.0.7 → 2.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 (60) hide show
  1. package/CHANGELOG.md +9 -3
  2. package/README.md +3 -2
  3. package/dist/cli.mjs +604 -531
  4. package/dist/cli.mjs.map +1 -1
  5. package/dist/gtfs/stops.d.ts +19 -5
  6. package/dist/gtfs/transfers.d.ts +5 -4
  7. package/dist/gtfs/trips.d.ts +7 -5
  8. package/dist/gtfs/utils.d.ts +7 -8
  9. package/dist/parser.cjs.js +569 -501
  10. package/dist/parser.cjs.js.map +1 -1
  11. package/dist/parser.esm.js +569 -501
  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.d.ts +3 -3
  16. package/dist/router.esm.js +1 -1
  17. package/dist/router.esm.js.map +1 -1
  18. package/dist/router.umd.js +1 -1
  19. package/dist/router.umd.js.map +1 -1
  20. package/dist/routing/__tests__/route.test.d.ts +1 -0
  21. package/dist/routing/query.d.ts +7 -7
  22. package/dist/routing/result.d.ts +3 -3
  23. package/dist/routing/route.d.ts +1 -0
  24. package/dist/stops/proto/stops.d.ts +5 -4
  25. package/dist/stops/stops.d.ts +10 -1
  26. package/dist/stops/stopsIndex.d.ts +21 -4
  27. package/dist/timetable/proto/timetable.d.ts +21 -18
  28. package/dist/timetable/timetable.d.ts +38 -14
  29. package/package.json +4 -3
  30. package/src/cli/repl.ts +13 -10
  31. package/src/gtfs/__tests__/parser.test.ts +50 -579
  32. package/src/gtfs/__tests__/stops.test.ts +181 -112
  33. package/src/gtfs/__tests__/transfers.test.ts +170 -12
  34. package/src/gtfs/__tests__/trips.test.ts +212 -141
  35. package/src/gtfs/__tests__/utils.test.ts +4 -4
  36. package/src/gtfs/parser.ts +22 -13
  37. package/src/gtfs/stops.ts +63 -28
  38. package/src/gtfs/transfers.ts +14 -6
  39. package/src/gtfs/trips.ts +110 -47
  40. package/src/gtfs/utils.ts +11 -11
  41. package/src/router.ts +2 -4
  42. package/src/routing/__tests__/route.test.ts +112 -0
  43. package/src/routing/__tests__/router.test.ts +234 -244
  44. package/src/routing/query.ts +7 -7
  45. package/src/routing/result.ts +9 -6
  46. package/src/routing/route.ts +11 -0
  47. package/src/routing/router.ts +26 -24
  48. package/src/stops/__tests__/io.test.ts +9 -8
  49. package/src/stops/__tests__/stopFinder.test.ts +45 -36
  50. package/src/stops/io.ts +8 -5
  51. package/src/stops/proto/stops.proto +8 -7
  52. package/src/stops/proto/stops.ts +68 -38
  53. package/src/stops/stops.ts +13 -1
  54. package/src/stops/stopsIndex.ts +50 -7
  55. package/src/timetable/__tests__/io.test.ts +40 -49
  56. package/src/timetable/__tests__/timetable.test.ts +50 -58
  57. package/src/timetable/io.ts +69 -56
  58. package/src/timetable/proto/timetable.proto +22 -17
  59. package/src/timetable/proto/timetable.ts +94 -184
  60. package/src/timetable/timetable.ts +62 -29
@@ -9664,7 +9664,6 @@ var StreamZip = /*@__PURE__*/getDefaultExportFromCjs(node_stream_zipExports);
9664
9664
  // of the input file used when generating it. This code is not
9665
9665
  // standalone and requires a support library to be linked with it. This
9666
9666
  // support library is itself covered by the above license.
9667
- /* eslint-disable prefer-const,@typescript-eslint/restrict-plus-operands */
9668
9667
  /**
9669
9668
  * Read a 64 bit varint as two JS numbers.
9670
9669
  *
@@ -9947,7 +9946,7 @@ function varint32read() {
9947
9946
  return result >>> 0;
9948
9947
  }
9949
9948
 
9950
- // Copyright 2021-2024 Buf Technologies, Inc.
9949
+ // Copyright 2021-2025 Buf Technologies, Inc.
9951
9950
  //
9952
9951
  // Licensed under the Apache License, Version 2.0 (the "License");
9953
9952
  // you may not use this file except in compliance with the License.
@@ -9976,7 +9975,10 @@ function makeInt64Support() {
9976
9975
  typeof process.env != "object" ||
9977
9976
  process.env.BUF_BIGINT_DISABLE !== "1");
9978
9977
  if (ok) {
9979
- const MIN = BigInt("-9223372036854775808"), MAX = BigInt("9223372036854775807"), UMIN = BigInt("0"), UMAX = BigInt("18446744073709551615");
9978
+ const MIN = BigInt("-9223372036854775808");
9979
+ const MAX = BigInt("9223372036854775807");
9980
+ const UMIN = BigInt("0");
9981
+ const UMAX = BigInt("18446744073709551615");
9980
9982
  return {
9981
9983
  zero: BigInt(0),
9982
9984
  supported: true,
@@ -10070,7 +10072,7 @@ function assertUInt64String(value) {
10070
10072
  }
10071
10073
  }
10072
10074
 
10073
- // Copyright 2021-2024 Buf Technologies, Inc.
10075
+ // Copyright 2021-2025 Buf Technologies, Inc.
10074
10076
  //
10075
10077
  // Licensed under the Apache License, Version 2.0 (the "License");
10076
10078
  // you may not use this file except in compliance with the License.
@@ -10100,7 +10102,7 @@ function getTextEncoding() {
10100
10102
  encodeURIComponent(text);
10101
10103
  return true;
10102
10104
  }
10103
- catch (e) {
10105
+ catch (_) {
10104
10106
  return false;
10105
10107
  }
10106
10108
  },
@@ -10109,7 +10111,7 @@ function getTextEncoding() {
10109
10111
  return globalThis[symbol];
10110
10112
  }
10111
10113
 
10112
- // Copyright 2021-2024 Buf Technologies, Inc.
10114
+ // Copyright 2021-2025 Buf Technologies, Inc.
10113
10115
  //
10114
10116
  // Licensed under the Apache License, Version 2.0 (the "License");
10115
10117
  // you may not use this file except in compliance with the License.
@@ -10122,7 +10124,6 @@ function getTextEncoding() {
10122
10124
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10123
10125
  // See the License for the specific language governing permissions and
10124
10126
  // limitations under the License.
10125
- /* eslint-disable prefer-const,no-case-declarations,@typescript-eslint/restrict-plus-operands */
10126
10127
  /**
10127
10128
  * Protobuf binary format wire types.
10128
10129
  *
@@ -10383,7 +10384,7 @@ class BinaryWriter {
10383
10384
  * Write a `sint64` value, a signed, zig-zag-encoded 64-bit varint.
10384
10385
  */
10385
10386
  sint64(value) {
10386
- let tc = protoInt64.enc(value),
10387
+ const tc = protoInt64.enc(value),
10387
10388
  // zigzag encode
10388
10389
  sign = tc.hi >> 31, lo = (tc.lo << 1) ^ sign, hi = ((tc.hi << 1) | (tc.lo >>> 31)) ^ sign;
10389
10390
  varint64write(lo, hi, this.buf);
@@ -10393,7 +10394,7 @@ class BinaryWriter {
10393
10394
  * Write a `uint64` value, an unsigned 64-bit varint.
10394
10395
  */
10395
10396
  uint64(value) {
10396
- let tc = protoInt64.uEnc(value);
10397
+ const tc = protoInt64.uEnc(value);
10397
10398
  varint64write(tc.lo, tc.hi, this.buf);
10398
10399
  return this;
10399
10400
  }
@@ -10434,11 +10435,9 @@ class BinaryReader {
10434
10435
  // ignore
10435
10436
  }
10436
10437
  break;
10437
- // eslint-disable-next-line
10438
10438
  // @ts-expect-error TS7029: Fallthrough case in switch
10439
10439
  case WireType.Bit64:
10440
10440
  this.pos += 4;
10441
- // eslint-disable-next-line no-fallthrough
10442
10441
  case WireType.Bit32:
10443
10442
  this.pos += 4;
10444
10443
  break;
@@ -10519,12 +10518,14 @@ class BinaryReader {
10519
10518
  * Read a `fixed32` field, an unsigned, fixed-length 32-bit integer.
10520
10519
  */
10521
10520
  fixed32() {
10521
+ // biome-ignore lint/suspicious/noAssignInExpressions: no
10522
10522
  return this.view.getUint32((this.pos += 4) - 4, true);
10523
10523
  }
10524
10524
  /**
10525
10525
  * Read a `sfixed32` field, a signed, fixed-length 32-bit integer.
10526
10526
  */
10527
10527
  sfixed32() {
10528
+ // biome-ignore lint/suspicious/noAssignInExpressions: no
10528
10529
  return this.view.getInt32((this.pos += 4) - 4, true);
10529
10530
  }
10530
10531
  /**
@@ -10543,12 +10544,14 @@ class BinaryReader {
10543
10544
  * Read a `float` field, 32-bit floating point number.
10544
10545
  */
10545
10546
  float() {
10547
+ // biome-ignore lint/suspicious/noAssignInExpressions: no
10546
10548
  return this.view.getFloat32((this.pos += 4) - 4, true);
10547
10549
  }
10548
10550
  /**
10549
10551
  * Read a `double` field, a 64-bit floating point number.
10550
10552
  */
10551
10553
  double() {
10554
+ // biome-ignore lint/suspicious/noAssignInExpressions: no
10552
10555
  return this.view.getFloat64((this.pos += 8) - 8, true);
10553
10556
  }
10554
10557
  /**
@@ -10604,7 +10607,7 @@ function assertFloat32(arg) {
10604
10607
  if (typeof arg == "string") {
10605
10608
  const o = arg;
10606
10609
  arg = Number(arg);
10607
- if (isNaN(arg) && o !== "NaN") {
10610
+ if (Number.isNaN(arg) && o !== "NaN") {
10608
10611
  throw new Error("invalid float32: " + o);
10609
10612
  }
10610
10613
  }
@@ -11279,6 +11282,7 @@ function locationTypeToJSON(object) {
11279
11282
  function createBaseStop() {
11280
11283
  return {
11281
11284
  name: "",
11285
+ sourceStopId: "",
11282
11286
  lat: undefined,
11283
11287
  lon: undefined,
11284
11288
  children: [],
@@ -11292,23 +11296,28 @@ const Stop = {
11292
11296
  if (message.name !== "") {
11293
11297
  writer.uint32(10).string(message.name);
11294
11298
  }
11299
+ if (message.sourceStopId !== "") {
11300
+ writer.uint32(18).string(message.sourceStopId);
11301
+ }
11295
11302
  if (message.lat !== undefined) {
11296
- writer.uint32(17).double(message.lat);
11303
+ writer.uint32(25).double(message.lat);
11297
11304
  }
11298
11305
  if (message.lon !== undefined) {
11299
- writer.uint32(25).double(message.lon);
11306
+ writer.uint32(33).double(message.lon);
11300
11307
  }
11308
+ writer.uint32(42).fork();
11301
11309
  for (const v of message.children) {
11302
- writer.uint32(34).string(v);
11310
+ writer.uint32(v);
11303
11311
  }
11312
+ writer.join();
11304
11313
  if (message.parent !== undefined) {
11305
- writer.uint32(42).string(message.parent);
11314
+ writer.uint32(48).uint32(message.parent);
11306
11315
  }
11307
11316
  if (message.locationType !== 0) {
11308
- writer.uint32(48).int32(message.locationType);
11317
+ writer.uint32(56).int32(message.locationType);
11309
11318
  }
11310
11319
  if (message.platform !== undefined) {
11311
- writer.uint32(58).string(message.platform);
11320
+ writer.uint32(66).string(message.platform);
11312
11321
  }
11313
11322
  return writer;
11314
11323
  },
@@ -11327,42 +11336,56 @@ const Stop = {
11327
11336
  continue;
11328
11337
  }
11329
11338
  case 2: {
11330
- if (tag !== 17) {
11339
+ if (tag !== 18) {
11331
11340
  break;
11332
11341
  }
11333
- message.lat = reader.double();
11342
+ message.sourceStopId = reader.string();
11334
11343
  continue;
11335
11344
  }
11336
11345
  case 3: {
11337
11346
  if (tag !== 25) {
11338
11347
  break;
11339
11348
  }
11340
- message.lon = reader.double();
11349
+ message.lat = reader.double();
11341
11350
  continue;
11342
11351
  }
11343
11352
  case 4: {
11344
- if (tag !== 34) {
11353
+ if (tag !== 33) {
11345
11354
  break;
11346
11355
  }
11347
- message.children.push(reader.string());
11356
+ message.lon = reader.double();
11348
11357
  continue;
11349
11358
  }
11350
11359
  case 5: {
11351
- if (tag !== 42) {
11352
- break;
11360
+ if (tag === 40) {
11361
+ message.children.push(reader.uint32());
11362
+ continue;
11353
11363
  }
11354
- message.parent = reader.string();
11355
- continue;
11364
+ if (tag === 42) {
11365
+ const end2 = reader.uint32() + reader.pos;
11366
+ while (reader.pos < end2) {
11367
+ message.children.push(reader.uint32());
11368
+ }
11369
+ continue;
11370
+ }
11371
+ break;
11356
11372
  }
11357
11373
  case 6: {
11358
11374
  if (tag !== 48) {
11359
11375
  break;
11360
11376
  }
11361
- message.locationType = reader.int32();
11377
+ message.parent = reader.uint32();
11362
11378
  continue;
11363
11379
  }
11364
11380
  case 7: {
11365
- if (tag !== 58) {
11381
+ if (tag !== 56) {
11382
+ break;
11383
+ }
11384
+ message.locationType = reader.int32();
11385
+ continue;
11386
+ }
11387
+ case 8: {
11388
+ if (tag !== 66) {
11366
11389
  break;
11367
11390
  }
11368
11391
  message.platform = reader.string();
@@ -11379,10 +11402,11 @@ const Stop = {
11379
11402
  fromJSON(object) {
11380
11403
  return {
11381
11404
  name: isSet$1(object.name) ? globalThis.String(object.name) : "",
11405
+ sourceStopId: isSet$1(object.sourceStopId) ? globalThis.String(object.sourceStopId) : "",
11382
11406
  lat: isSet$1(object.lat) ? globalThis.Number(object.lat) : undefined,
11383
11407
  lon: isSet$1(object.lon) ? globalThis.Number(object.lon) : undefined,
11384
- children: globalThis.Array.isArray(object === null || object === undefined ? undefined : object.children) ? object.children.map((e) => globalThis.String(e)) : [],
11385
- parent: isSet$1(object.parent) ? globalThis.String(object.parent) : undefined,
11408
+ children: globalThis.Array.isArray(object === null || object === undefined ? undefined : object.children) ? object.children.map((e) => globalThis.Number(e)) : [],
11409
+ parent: isSet$1(object.parent) ? globalThis.Number(object.parent) : undefined,
11386
11410
  locationType: isSet$1(object.locationType) ? locationTypeFromJSON(object.locationType) : 0,
11387
11411
  platform: isSet$1(object.platform) ? globalThis.String(object.platform) : undefined,
11388
11412
  };
@@ -11393,6 +11417,9 @@ const Stop = {
11393
11417
  if (message.name !== "") {
11394
11418
  obj.name = message.name;
11395
11419
  }
11420
+ if (message.sourceStopId !== "") {
11421
+ obj.sourceStopId = message.sourceStopId;
11422
+ }
11396
11423
  if (message.lat !== undefined) {
11397
11424
  obj.lat = message.lat;
11398
11425
  }
@@ -11400,10 +11427,10 @@ const Stop = {
11400
11427
  obj.lon = message.lon;
11401
11428
  }
11402
11429
  if ((_a = message.children) === null || _a === undefined ? undefined : _a.length) {
11403
- obj.children = message.children;
11430
+ obj.children = message.children.map((e) => Math.round(e));
11404
11431
  }
11405
11432
  if (message.parent !== undefined) {
11406
- obj.parent = message.parent;
11433
+ obj.parent = Math.round(message.parent);
11407
11434
  }
11408
11435
  if (message.locationType !== 0) {
11409
11436
  obj.locationType = locationTypeToJSON(message.locationType);
@@ -11417,15 +11444,16 @@ const Stop = {
11417
11444
  return Stop.fromPartial(base !== null && base !== undefined ? base : {});
11418
11445
  },
11419
11446
  fromPartial(object) {
11420
- var _a, _b, _c, _d, _e, _f, _g;
11447
+ var _a, _b, _c, _d, _e, _f, _g, _h;
11421
11448
  const message = createBaseStop();
11422
11449
  message.name = (_a = object.name) !== null && _a !== undefined ? _a : "";
11423
- message.lat = (_b = object.lat) !== null && _b !== undefined ? _b : undefined;
11424
- message.lon = (_c = object.lon) !== null && _c !== undefined ? _c : undefined;
11425
- message.children = ((_d = object.children) === null || _d === undefined ? undefined : _d.map((e) => e)) || [];
11426
- message.parent = (_e = object.parent) !== null && _e !== undefined ? _e : undefined;
11427
- message.locationType = (_f = object.locationType) !== null && _f !== undefined ? _f : 0;
11428
- message.platform = (_g = object.platform) !== null && _g !== undefined ? _g : undefined;
11450
+ message.sourceStopId = (_b = object.sourceStopId) !== null && _b !== undefined ? _b : "";
11451
+ message.lat = (_c = object.lat) !== null && _c !== undefined ? _c : undefined;
11452
+ message.lon = (_d = object.lon) !== null && _d !== undefined ? _d : undefined;
11453
+ message.children = ((_e = object.children) === null || _e === undefined ? undefined : _e.map((e) => e)) || [];
11454
+ message.parent = (_f = object.parent) !== null && _f !== undefined ? _f : undefined;
11455
+ message.locationType = (_g = object.locationType) !== null && _g !== undefined ? _g : 0;
11456
+ message.platform = (_h = object.platform) !== null && _h !== undefined ? _h : undefined;
11429
11457
  return message;
11430
11458
  },
11431
11459
  };
@@ -11479,7 +11507,7 @@ const StopsMap = {
11479
11507
  version: isSet$1(object.version) ? globalThis.String(object.version) : "",
11480
11508
  stops: isObject$1(object.stops)
11481
11509
  ? Object.entries(object.stops).reduce((acc, [key, value]) => {
11482
- acc[key] = Stop.fromJSON(value);
11510
+ acc[globalThis.Number(key)] = Stop.fromJSON(value);
11483
11511
  return acc;
11484
11512
  }, {})
11485
11513
  : {},
@@ -11510,7 +11538,7 @@ const StopsMap = {
11510
11538
  message.version = (_a = object.version) !== null && _a !== undefined ? _a : "";
11511
11539
  message.stops = Object.entries((_b = object.stops) !== null && _b !== undefined ? _b : {}).reduce((acc, [key, value]) => {
11512
11540
  if (value !== undefined) {
11513
- acc[key] = Stop.fromPartial(value);
11541
+ acc[globalThis.Number(key)] = Stop.fromPartial(value);
11514
11542
  }
11515
11543
  return acc;
11516
11544
  }, {});
@@ -11518,12 +11546,12 @@ const StopsMap = {
11518
11546
  },
11519
11547
  };
11520
11548
  function createBaseStopsMap_StopsEntry() {
11521
- return { key: "", value: undefined };
11549
+ return { key: 0, value: undefined };
11522
11550
  }
11523
11551
  const StopsMap_StopsEntry = {
11524
11552
  encode(message, writer = new BinaryWriter()) {
11525
- if (message.key !== "") {
11526
- writer.uint32(10).string(message.key);
11553
+ if (message.key !== 0) {
11554
+ writer.uint32(8).uint32(message.key);
11527
11555
  }
11528
11556
  if (message.value !== undefined) {
11529
11557
  Stop.encode(message.value, writer.uint32(18).fork()).join();
@@ -11538,10 +11566,10 @@ const StopsMap_StopsEntry = {
11538
11566
  const tag = reader.uint32();
11539
11567
  switch (tag >>> 3) {
11540
11568
  case 1: {
11541
- if (tag !== 10) {
11569
+ if (tag !== 8) {
11542
11570
  break;
11543
11571
  }
11544
- message.key = reader.string();
11572
+ message.key = reader.uint32();
11545
11573
  continue;
11546
11574
  }
11547
11575
  case 2: {
@@ -11561,14 +11589,14 @@ const StopsMap_StopsEntry = {
11561
11589
  },
11562
11590
  fromJSON(object) {
11563
11591
  return {
11564
- key: isSet$1(object.key) ? globalThis.String(object.key) : "",
11592
+ key: isSet$1(object.key) ? globalThis.Number(object.key) : 0,
11565
11593
  value: isSet$1(object.value) ? Stop.fromJSON(object.value) : undefined,
11566
11594
  };
11567
11595
  },
11568
11596
  toJSON(message) {
11569
11597
  const obj = {};
11570
- if (message.key !== "") {
11571
- obj.key = message.key;
11598
+ if (message.key !== 0) {
11599
+ obj.key = Math.round(message.key);
11572
11600
  }
11573
11601
  if (message.value !== undefined) {
11574
11602
  obj.value = Stop.toJSON(message.value);
@@ -11581,7 +11609,7 @@ const StopsMap_StopsEntry = {
11581
11609
  fromPartial(object) {
11582
11610
  var _a;
11583
11611
  const message = createBaseStopsMap_StopsEntry();
11584
- message.key = (_a = object.key) !== null && _a !== undefined ? _a : "";
11612
+ message.key = (_a = object.key) !== null && _a !== undefined ? _a : 0;
11585
11613
  message.value = (object.value !== undefined && object.value !== null) ? Stop.fromPartial(object.value) : undefined;
11586
11614
  return message;
11587
11615
  },
@@ -11593,10 +11621,11 @@ function isSet$1(value) {
11593
11621
  return value !== null && value !== undefined;
11594
11622
  }
11595
11623
 
11596
- const CURRENT_VERSION$1 = '0.0.1';
11624
+ const CURRENT_VERSION$1 = '0.0.2';
11597
11625
  const serializeStop = (stop) => {
11598
11626
  return {
11599
11627
  name: stop.name,
11628
+ sourceStopId: stop.sourceStopId,
11600
11629
  lat: stop.lat,
11601
11630
  lon: stop.lon,
11602
11631
  children: stop.children,
@@ -11618,6 +11647,7 @@ const serializeStopsMap = (stopsMap) => {
11618
11647
  const deserializeStop = (stopId, protoStop) => {
11619
11648
  return {
11620
11649
  id: stopId,
11650
+ sourceStopId: protoStop.sourceStopId,
11621
11651
  name: protoStop.name,
11622
11652
  lat: protoStop.lat,
11623
11653
  lon: protoStop.lon,
@@ -11633,7 +11663,8 @@ const deserializeStopsMap = (protoStopsMap) => {
11633
11663
  }
11634
11664
  const stopsMap = new Map();
11635
11665
  Object.entries(protoStopsMap.stops).forEach(([key, value]) => {
11636
- stopsMap.set(key, deserializeStop(key, value));
11666
+ const intKey = parseInt(key, 10);
11667
+ stopsMap.set(intKey, deserializeStop(intKey, value));
11637
11668
  });
11638
11669
  return stopsMap;
11639
11670
  };
@@ -11677,6 +11708,10 @@ class StopsIndex {
11677
11708
  constructor(stopsMap) {
11678
11709
  var _a;
11679
11710
  this.stopsMap = stopsMap;
11711
+ this.sourceStopsMap = new Map();
11712
+ for (const [id, stop] of stopsMap.entries()) {
11713
+ this.sourceStopsMap.set(stop.sourceStopId, id);
11714
+ }
11680
11715
  this.textIndex = lt({
11681
11716
  fields: ['name'],
11682
11717
  storeFields: ['id'],
@@ -11735,6 +11770,14 @@ class StopsIndex {
11735
11770
  StopsMap.encode(protoStopsMap, writer);
11736
11771
  return writer.finish();
11737
11772
  }
11773
+ /**
11774
+ * Returns the number of stops in the index.
11775
+ *
11776
+ * @returns The total number of stops.
11777
+ */
11778
+ size() {
11779
+ return this.stopsMap.size;
11780
+ }
11738
11781
  /**
11739
11782
  * Finds stops by their name using a text search.
11740
11783
  *
@@ -11763,16 +11806,36 @@ class StopsIndex {
11763
11806
  return nearestStops;
11764
11807
  }
11765
11808
  /**
11766
- * Finds a stop by its ID.
11809
+ * Finds a stop by its internal ID.
11767
11810
  *
11768
- * @param id - The ID of the stop to search for.
11811
+ * @param id - The internal ID of the stop to search for.
11769
11812
  * @returns The Stop object that matches the specified ID, or undefined if not found.
11770
11813
  */
11771
11814
  findStopById(id) {
11772
11815
  return this.stopsMap.get(id);
11773
11816
  }
11774
- equivalentStops(id) {
11817
+ /**
11818
+ * Finds a stop by its ID in the transit data source (e.g. GTFS).
11819
+ *
11820
+ * @param id - The source ID of the stop to search for.
11821
+ * @returns The Stop object that matches the specified ID, or undefined if not found.
11822
+ */
11823
+ findStopBySourceStopId(sourceStopId) {
11824
+ const stopId = this.sourceStopsMap.get(sourceStopId);
11825
+ if (stopId === undefined) {
11826
+ return;
11827
+ }
11828
+ return this.findStopById(stopId);
11829
+ }
11830
+ /**
11831
+ * Find ids of all sibling stops.
11832
+ */
11833
+ equivalentStops(sourceId) {
11775
11834
  var _a, _b;
11835
+ const id = this.sourceStopsMap.get(sourceId);
11836
+ if (id === undefined) {
11837
+ return [];
11838
+ }
11776
11839
  const stop = this.stopsMap.get(id);
11777
11840
  if (!stop) {
11778
11841
  return [];
@@ -11780,7 +11843,7 @@ class StopsIndex {
11780
11843
  const equivalentStops = stop.parent
11781
11844
  ? ((_b = (_a = this.stopsMap.get(stop.parent)) === null || _a === undefined ? undefined : _a.children) !== null && _b !== undefined ? _b : [])
11782
11845
  : stop.children;
11783
- return Array.from(new Set([id, ...equivalentStops]));
11846
+ return Array.from(new Set([id, ...equivalentStops])).map((stopId) => this.stopsMap.get(stopId));
11784
11847
  }
11785
11848
  }
11786
11849
 
@@ -11871,43 +11934,6 @@ class Duration {
11871
11934
  // protoc v4.23.4
11872
11935
  // source: src/timetable/proto/timetable.proto
11873
11936
  /* eslint-disable */
11874
- var PickUpDropOffType;
11875
- (function (PickUpDropOffType) {
11876
- PickUpDropOffType[PickUpDropOffType["NOT_AVAILABLE"] = 0] = "NOT_AVAILABLE";
11877
- PickUpDropOffType[PickUpDropOffType["MUST_PHONE_AGENCY"] = 1] = "MUST_PHONE_AGENCY";
11878
- PickUpDropOffType[PickUpDropOffType["MUST_COORDINATE_WITH_DRIVER"] = 2] = "MUST_COORDINATE_WITH_DRIVER";
11879
- PickUpDropOffType[PickUpDropOffType["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
11880
- })(PickUpDropOffType || (PickUpDropOffType = {}));
11881
- function pickUpDropOffTypeFromJSON(object) {
11882
- switch (object) {
11883
- case 0:
11884
- case "NOT_AVAILABLE":
11885
- return PickUpDropOffType.NOT_AVAILABLE;
11886
- case 1:
11887
- case "MUST_PHONE_AGENCY":
11888
- return PickUpDropOffType.MUST_PHONE_AGENCY;
11889
- case 2:
11890
- case "MUST_COORDINATE_WITH_DRIVER":
11891
- return PickUpDropOffType.MUST_COORDINATE_WITH_DRIVER;
11892
- case -1:
11893
- case "UNRECOGNIZED":
11894
- default:
11895
- return PickUpDropOffType.UNRECOGNIZED;
11896
- }
11897
- }
11898
- function pickUpDropOffTypeToJSON(object) {
11899
- switch (object) {
11900
- case PickUpDropOffType.NOT_AVAILABLE:
11901
- return "NOT_AVAILABLE";
11902
- case PickUpDropOffType.MUST_PHONE_AGENCY:
11903
- return "MUST_PHONE_AGENCY";
11904
- case PickUpDropOffType.MUST_COORDINATE_WITH_DRIVER:
11905
- return "MUST_COORDINATE_WITH_DRIVER";
11906
- case PickUpDropOffType.UNRECOGNIZED:
11907
- default:
11908
- return "UNRECOGNIZED";
11909
- }
11910
- }
11911
11937
  var TransferType;
11912
11938
  (function (TransferType) {
11913
11939
  TransferType[TransferType["RECOMMENDED_TRANSFER_POINT"] = 0] = "RECOMMENDED_TRANSFER_POINT";
@@ -12030,118 +12056,27 @@ function routeTypeToJSON(object) {
12030
12056
  return "UNRECOGNIZED";
12031
12057
  }
12032
12058
  }
12033
- function createBaseStopTimes() {
12034
- return { arrival: 0, departure: 0, pickUpType: undefined, dropOffType: undefined };
12035
- }
12036
- const StopTimes = {
12037
- encode(message, writer = new BinaryWriter()) {
12038
- if (message.arrival !== 0) {
12039
- writer.uint32(8).int32(message.arrival);
12040
- }
12041
- if (message.departure !== 0) {
12042
- writer.uint32(16).int32(message.departure);
12043
- }
12044
- if (message.pickUpType !== undefined) {
12045
- writer.uint32(24).int32(message.pickUpType);
12046
- }
12047
- if (message.dropOffType !== undefined) {
12048
- writer.uint32(32).int32(message.dropOffType);
12049
- }
12050
- return writer;
12051
- },
12052
- decode(input, length) {
12053
- const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
12054
- let end = length === undefined ? reader.len : reader.pos + length;
12055
- const message = createBaseStopTimes();
12056
- while (reader.pos < end) {
12057
- const tag = reader.uint32();
12058
- switch (tag >>> 3) {
12059
- case 1: {
12060
- if (tag !== 8) {
12061
- break;
12062
- }
12063
- message.arrival = reader.int32();
12064
- continue;
12065
- }
12066
- case 2: {
12067
- if (tag !== 16) {
12068
- break;
12069
- }
12070
- message.departure = reader.int32();
12071
- continue;
12072
- }
12073
- case 3: {
12074
- if (tag !== 24) {
12075
- break;
12076
- }
12077
- message.pickUpType = reader.int32();
12078
- continue;
12079
- }
12080
- case 4: {
12081
- if (tag !== 32) {
12082
- break;
12083
- }
12084
- message.dropOffType = reader.int32();
12085
- continue;
12086
- }
12087
- }
12088
- if ((tag & 7) === 4 || tag === 0) {
12089
- break;
12090
- }
12091
- reader.skip(tag & 7);
12092
- }
12093
- return message;
12094
- },
12095
- fromJSON(object) {
12096
- return {
12097
- arrival: isSet(object.arrival) ? globalThis.Number(object.arrival) : 0,
12098
- departure: isSet(object.departure) ? globalThis.Number(object.departure) : 0,
12099
- pickUpType: isSet(object.pickUpType) ? pickUpDropOffTypeFromJSON(object.pickUpType) : undefined,
12100
- dropOffType: isSet(object.dropOffType) ? pickUpDropOffTypeFromJSON(object.dropOffType) : undefined,
12101
- };
12102
- },
12103
- toJSON(message) {
12104
- const obj = {};
12105
- if (message.arrival !== 0) {
12106
- obj.arrival = Math.round(message.arrival);
12107
- }
12108
- if (message.departure !== 0) {
12109
- obj.departure = Math.round(message.departure);
12110
- }
12111
- if (message.pickUpType !== undefined) {
12112
- obj.pickUpType = pickUpDropOffTypeToJSON(message.pickUpType);
12113
- }
12114
- if (message.dropOffType !== undefined) {
12115
- obj.dropOffType = pickUpDropOffTypeToJSON(message.dropOffType);
12116
- }
12117
- return obj;
12118
- },
12119
- create(base) {
12120
- return StopTimes.fromPartial(base !== null && base !== undefined ? base : {});
12121
- },
12122
- fromPartial(object) {
12123
- var _a, _b, _c, _d;
12124
- const message = createBaseStopTimes();
12125
- message.arrival = (_a = object.arrival) !== null && _a !== undefined ? _a : 0;
12126
- message.departure = (_b = object.departure) !== null && _b !== undefined ? _b : 0;
12127
- message.pickUpType = (_c = object.pickUpType) !== null && _c !== undefined ? _c : undefined;
12128
- message.dropOffType = (_d = object.dropOffType) !== null && _d !== undefined ? _d : undefined;
12129
- return message;
12130
- },
12131
- };
12132
12059
  function createBaseRoute() {
12133
- return { stopTimes: [], stops: [], serviceRouteId: "" };
12060
+ return {
12061
+ stopTimes: new Uint8Array(0),
12062
+ pickUpDropOffTypes: new Uint8Array(0),
12063
+ stops: new Uint8Array(0),
12064
+ serviceRouteId: "",
12065
+ };
12134
12066
  }
12135
12067
  const Route = {
12136
12068
  encode(message, writer = new BinaryWriter()) {
12137
- for (const v of message.stopTimes) {
12138
- StopTimes.encode(v, writer.uint32(10).fork()).join();
12069
+ if (message.stopTimes.length !== 0) {
12070
+ writer.uint32(10).bytes(message.stopTimes);
12139
12071
  }
12140
- for (const v of message.stops) {
12141
- writer.uint32(18).string(v);
12072
+ if (message.pickUpDropOffTypes.length !== 0) {
12073
+ writer.uint32(18).bytes(message.pickUpDropOffTypes);
12074
+ }
12075
+ if (message.stops.length !== 0) {
12076
+ writer.uint32(26).bytes(message.stops);
12142
12077
  }
12143
12078
  if (message.serviceRouteId !== "") {
12144
- writer.uint32(26).string(message.serviceRouteId);
12079
+ writer.uint32(34).string(message.serviceRouteId);
12145
12080
  }
12146
12081
  return writer;
12147
12082
  },
@@ -12156,20 +12091,27 @@ const Route = {
12156
12091
  if (tag !== 10) {
12157
12092
  break;
12158
12093
  }
12159
- message.stopTimes.push(StopTimes.decode(reader, reader.uint32()));
12094
+ message.stopTimes = reader.bytes();
12160
12095
  continue;
12161
12096
  }
12162
12097
  case 2: {
12163
12098
  if (tag !== 18) {
12164
12099
  break;
12165
12100
  }
12166
- message.stops.push(reader.string());
12101
+ message.pickUpDropOffTypes = reader.bytes();
12167
12102
  continue;
12168
12103
  }
12169
12104
  case 3: {
12170
12105
  if (tag !== 26) {
12171
12106
  break;
12172
12107
  }
12108
+ message.stops = reader.bytes();
12109
+ continue;
12110
+ }
12111
+ case 4: {
12112
+ if (tag !== 34) {
12113
+ break;
12114
+ }
12173
12115
  message.serviceRouteId = reader.string();
12174
12116
  continue;
12175
12117
  }
@@ -12183,21 +12125,24 @@ const Route = {
12183
12125
  },
12184
12126
  fromJSON(object) {
12185
12127
  return {
12186
- stopTimes: globalThis.Array.isArray(object === null || object === undefined ? undefined : object.stopTimes)
12187
- ? object.stopTimes.map((e) => StopTimes.fromJSON(e))
12188
- : [],
12189
- stops: globalThis.Array.isArray(object === null || object === undefined ? undefined : object.stops) ? object.stops.map((e) => globalThis.String(e)) : [],
12128
+ stopTimes: isSet(object.stopTimes) ? bytesFromBase64(object.stopTimes) : new Uint8Array(0),
12129
+ pickUpDropOffTypes: isSet(object.pickUpDropOffTypes)
12130
+ ? bytesFromBase64(object.pickUpDropOffTypes)
12131
+ : new Uint8Array(0),
12132
+ stops: isSet(object.stops) ? bytesFromBase64(object.stops) : new Uint8Array(0),
12190
12133
  serviceRouteId: isSet(object.serviceRouteId) ? globalThis.String(object.serviceRouteId) : "",
12191
12134
  };
12192
12135
  },
12193
12136
  toJSON(message) {
12194
- var _a, _b;
12195
12137
  const obj = {};
12196
- if ((_a = message.stopTimes) === null || _a === undefined ? undefined : _a.length) {
12197
- obj.stopTimes = message.stopTimes.map((e) => StopTimes.toJSON(e));
12138
+ if (message.stopTimes.length !== 0) {
12139
+ obj.stopTimes = base64FromBytes(message.stopTimes);
12140
+ }
12141
+ if (message.pickUpDropOffTypes.length !== 0) {
12142
+ obj.pickUpDropOffTypes = base64FromBytes(message.pickUpDropOffTypes);
12198
12143
  }
12199
- if ((_b = message.stops) === null || _b === undefined ? undefined : _b.length) {
12200
- obj.stops = message.stops;
12144
+ if (message.stops.length !== 0) {
12145
+ obj.stops = base64FromBytes(message.stops);
12201
12146
  }
12202
12147
  if (message.serviceRouteId !== "") {
12203
12148
  obj.serviceRouteId = message.serviceRouteId;
@@ -12208,11 +12153,12 @@ const Route = {
12208
12153
  return Route.fromPartial(base !== null && base !== undefined ? base : {});
12209
12154
  },
12210
12155
  fromPartial(object) {
12211
- var _a, _b, _c;
12156
+ var _a, _b, _c, _d;
12212
12157
  const message = createBaseRoute();
12213
- message.stopTimes = ((_a = object.stopTimes) === null || _a === undefined ? undefined : _a.map((e) => StopTimes.fromPartial(e))) || [];
12214
- message.stops = ((_b = object.stops) === null || _b === undefined ? undefined : _b.map((e) => e)) || [];
12215
- message.serviceRouteId = (_c = object.serviceRouteId) !== null && _c !== undefined ? _c : "";
12158
+ message.stopTimes = (_a = object.stopTimes) !== null && _a !== undefined ? _a : new Uint8Array(0);
12159
+ message.pickUpDropOffTypes = (_b = object.pickUpDropOffTypes) !== null && _b !== undefined ? _b : new Uint8Array(0);
12160
+ message.stops = (_c = object.stops) !== null && _c !== undefined ? _c : new Uint8Array(0);
12161
+ message.serviceRouteId = (_d = object.serviceRouteId) !== null && _d !== undefined ? _d : "";
12216
12162
  return message;
12217
12163
  },
12218
12164
  };
@@ -12359,12 +12305,12 @@ const RoutesAdjacency_RoutesEntry = {
12359
12305
  },
12360
12306
  };
12361
12307
  function createBaseTransfer() {
12362
- return { destination: "", type: 0, minTransferTime: undefined };
12308
+ return { destination: 0, type: 0, minTransferTime: undefined };
12363
12309
  }
12364
12310
  const Transfer = {
12365
12311
  encode(message, writer = new BinaryWriter()) {
12366
- if (message.destination !== "") {
12367
- writer.uint32(10).string(message.destination);
12312
+ if (message.destination !== 0) {
12313
+ writer.uint32(8).uint32(message.destination);
12368
12314
  }
12369
12315
  if (message.type !== 0) {
12370
12316
  writer.uint32(16).int32(message.type);
@@ -12382,10 +12328,10 @@ const Transfer = {
12382
12328
  const tag = reader.uint32();
12383
12329
  switch (tag >>> 3) {
12384
12330
  case 1: {
12385
- if (tag !== 10) {
12331
+ if (tag !== 8) {
12386
12332
  break;
12387
12333
  }
12388
- message.destination = reader.string();
12334
+ message.destination = reader.uint32();
12389
12335
  continue;
12390
12336
  }
12391
12337
  case 2: {
@@ -12412,15 +12358,15 @@ const Transfer = {
12412
12358
  },
12413
12359
  fromJSON(object) {
12414
12360
  return {
12415
- destination: isSet(object.destination) ? globalThis.String(object.destination) : "",
12361
+ destination: isSet(object.destination) ? globalThis.Number(object.destination) : 0,
12416
12362
  type: isSet(object.type) ? transferTypeFromJSON(object.type) : 0,
12417
12363
  minTransferTime: isSet(object.minTransferTime) ? globalThis.Number(object.minTransferTime) : undefined,
12418
12364
  };
12419
12365
  },
12420
12366
  toJSON(message) {
12421
12367
  const obj = {};
12422
- if (message.destination !== "") {
12423
- obj.destination = message.destination;
12368
+ if (message.destination !== 0) {
12369
+ obj.destination = Math.round(message.destination);
12424
12370
  }
12425
12371
  if (message.type !== 0) {
12426
12372
  obj.type = transferTypeToJSON(message.type);
@@ -12436,7 +12382,7 @@ const Transfer = {
12436
12382
  fromPartial(object) {
12437
12383
  var _a, _b, _c;
12438
12384
  const message = createBaseTransfer();
12439
- message.destination = (_a = object.destination) !== null && _a !== undefined ? _a : "";
12385
+ message.destination = (_a = object.destination) !== null && _a !== undefined ? _a : 0;
12440
12386
  message.type = (_b = object.type) !== null && _b !== undefined ? _b : 0;
12441
12387
  message.minTransferTime = (_c = object.minTransferTime) !== null && _c !== undefined ? _c : undefined;
12442
12388
  return message;
@@ -12976,6 +12922,31 @@ const Timetable$1 = {
12976
12922
  return message;
12977
12923
  },
12978
12924
  };
12925
+ function bytesFromBase64(b64) {
12926
+ if (globalThis.Buffer) {
12927
+ return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
12928
+ }
12929
+ else {
12930
+ const bin = globalThis.atob(b64);
12931
+ const arr = new Uint8Array(bin.length);
12932
+ for (let i = 0; i < bin.length; ++i) {
12933
+ arr[i] = bin.charCodeAt(i);
12934
+ }
12935
+ return arr;
12936
+ }
12937
+ }
12938
+ function base64FromBytes(arr) {
12939
+ if (globalThis.Buffer) {
12940
+ return globalThis.Buffer.from(arr).toString("base64");
12941
+ }
12942
+ else {
12943
+ const bin = [];
12944
+ arr.forEach((byte) => {
12945
+ bin.push(globalThis.String.fromCharCode(byte));
12946
+ });
12947
+ return globalThis.btoa(bin.join(""));
12948
+ }
12949
+ }
12979
12950
  function isObject(value) {
12980
12951
  return typeof value === "object" && value !== null;
12981
12952
  }
@@ -12983,6 +12954,202 @@ function isSet(value) {
12983
12954
  return value !== null && value !== undefined;
12984
12955
  }
12985
12956
 
12957
+ const isLittleEndian = (() => {
12958
+ const buffer = new ArrayBuffer(4);
12959
+ const view = new DataView(buffer);
12960
+ view.setUint32(0, 0x12345678);
12961
+ return new Uint8Array(buffer)[0] === 0x78;
12962
+ })();
12963
+ const STANDARD_ENDIANNESS = true; // true = little-endian
12964
+ function uint32ArrayToBytes(array) {
12965
+ if (isLittleEndian === STANDARD_ENDIANNESS) {
12966
+ return new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
12967
+ }
12968
+ // If endianness doesn't match, we need to swap byte order
12969
+ const result = new Uint8Array(array.length * 4);
12970
+ const view = new DataView(result.buffer);
12971
+ for (let i = 0; i < array.length; i++) {
12972
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
12973
+ view.setUint32(i * 4, array[i], STANDARD_ENDIANNESS);
12974
+ }
12975
+ return result;
12976
+ }
12977
+ function bytesToUint32Array(bytes) {
12978
+ if (bytes.byteLength % 4 !== 0) {
12979
+ throw new Error('Byte array length must be a multiple of 4 to convert to Uint32Array');
12980
+ }
12981
+ // If system endianness matches our standard, we can create a view directly
12982
+ if (isLittleEndian === STANDARD_ENDIANNESS) {
12983
+ return new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4);
12984
+ }
12985
+ // If endianness doesn't match, we need to swap byte order
12986
+ const result = new Uint32Array(bytes.byteLength / 4);
12987
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
12988
+ for (let i = 0; i < result.length; i++) {
12989
+ result[i] = view.getUint32(i * 4, STANDARD_ENDIANNESS);
12990
+ }
12991
+ return result;
12992
+ }
12993
+ const serializeStopsAdjacency = (stopsAdjacency) => {
12994
+ const protoStopsAdjacency = {
12995
+ stops: {},
12996
+ };
12997
+ stopsAdjacency.forEach((value, key) => {
12998
+ protoStopsAdjacency.stops[key] = {
12999
+ transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: serializeTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
13000
+ minTransferTime: transfer.minTransferTime.toSeconds(),
13001
+ })))),
13002
+ routes: value.routes,
13003
+ };
13004
+ });
13005
+ return protoStopsAdjacency;
13006
+ };
13007
+ const serializeRoutesAdjacency = (routesAdjacency) => {
13008
+ const protoRoutesAdjacency = {
13009
+ routes: {},
13010
+ };
13011
+ routesAdjacency.forEach((value, key) => {
13012
+ protoRoutesAdjacency.routes[key] = {
13013
+ stopTimes: uint32ArrayToBytes(value.stopTimes),
13014
+ pickUpDropOffTypes: value.pickUpDropOffTypes,
13015
+ stops: uint32ArrayToBytes(value.stops),
13016
+ serviceRouteId: value.serviceRouteId,
13017
+ };
13018
+ });
13019
+ return protoRoutesAdjacency;
13020
+ };
13021
+ const serializeServiceRoutesMap = (serviceRoutesMap) => {
13022
+ const protoServiceRoutesMap = {
13023
+ routes: {},
13024
+ };
13025
+ serviceRoutesMap.forEach((value, key) => {
13026
+ protoServiceRoutesMap.routes[key] = {
13027
+ type: serializeRouteType(value.type),
13028
+ name: value.name,
13029
+ };
13030
+ });
13031
+ return protoServiceRoutesMap;
13032
+ };
13033
+ const deserializeStopsAdjacency = (protoStopsAdjacency) => {
13034
+ const stopsAdjacency = new Map();
13035
+ Object.entries(protoStopsAdjacency.stops).forEach(([keyStr, value]) => {
13036
+ const key = parseInt(keyStr, 10);
13037
+ stopsAdjacency.set(key, {
13038
+ transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: parseTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
13039
+ minTransferTime: Duration.fromSeconds(transfer.minTransferTime),
13040
+ })))),
13041
+ routes: value.routes,
13042
+ });
13043
+ });
13044
+ return stopsAdjacency;
13045
+ };
13046
+ const deserializeRoutesAdjacency = (protoRoutesAdjacency) => {
13047
+ const routesAdjacency = new Map();
13048
+ Object.entries(protoRoutesAdjacency.routes).forEach(([key, value]) => {
13049
+ const stops = bytesToUint32Array(value.stops);
13050
+ const indices = new Map();
13051
+ for (let i = 0; i < stops.length; i++) {
13052
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
13053
+ indices.set(stops[i], i);
13054
+ }
13055
+ routesAdjacency.set(key, {
13056
+ stopTimes: bytesToUint32Array(value.stopTimes),
13057
+ pickUpDropOffTypes: value.pickUpDropOffTypes,
13058
+ stops: stops,
13059
+ stopIndices: indices,
13060
+ serviceRouteId: value.serviceRouteId,
13061
+ });
13062
+ });
13063
+ return routesAdjacency;
13064
+ };
13065
+ const deserializeServiceRoutesMap = (protoServiceRoutesMap) => {
13066
+ const serviceRoutesMap = new Map();
13067
+ Object.entries(protoServiceRoutesMap.routes).forEach(([key, value]) => {
13068
+ serviceRoutesMap.set(key, {
13069
+ type: parseRouteType(value.type),
13070
+ name: value.name,
13071
+ });
13072
+ });
13073
+ return serviceRoutesMap;
13074
+ };
13075
+ const parseTransferType = (type) => {
13076
+ switch (type) {
13077
+ case TransferType.RECOMMENDED_TRANSFER_POINT:
13078
+ return 'RECOMMENDED';
13079
+ case TransferType.TIMED_TRANSFER:
13080
+ return 'GUARANTEED';
13081
+ case TransferType.REQUIRES_MINIMAL_TIME:
13082
+ return 'REQUIRES_MINIMAL_TIME';
13083
+ case TransferType.IN_SEAT_TRANSFER:
13084
+ return 'IN_SEAT';
13085
+ case TransferType.UNRECOGNIZED:
13086
+ throw new Error('Unrecognized protobuf transfer type.');
13087
+ }
13088
+ };
13089
+ const serializeTransferType = (type) => {
13090
+ switch (type) {
13091
+ case 'RECOMMENDED':
13092
+ return TransferType.RECOMMENDED_TRANSFER_POINT;
13093
+ case 'GUARANTEED':
13094
+ return TransferType.TIMED_TRANSFER;
13095
+ case 'REQUIRES_MINIMAL_TIME':
13096
+ return TransferType.REQUIRES_MINIMAL_TIME;
13097
+ case 'IN_SEAT':
13098
+ return TransferType.IN_SEAT_TRANSFER;
13099
+ }
13100
+ };
13101
+ const parseRouteType = (type) => {
13102
+ switch (type) {
13103
+ case RouteType.TRAM:
13104
+ return 'TRAM';
13105
+ case RouteType.SUBWAY:
13106
+ return 'SUBWAY';
13107
+ case RouteType.RAIL:
13108
+ return 'RAIL';
13109
+ case RouteType.BUS:
13110
+ return 'BUS';
13111
+ case RouteType.FERRY:
13112
+ return 'FERRY';
13113
+ case RouteType.CABLE_TRAM:
13114
+ return 'CABLE_TRAM';
13115
+ case RouteType.AERIAL_LIFT:
13116
+ return 'AERIAL_LIFT';
13117
+ case RouteType.FUNICULAR:
13118
+ return 'FUNICULAR';
13119
+ case RouteType.TROLLEYBUS:
13120
+ return 'TROLLEYBUS';
13121
+ case RouteType.MONORAIL:
13122
+ return 'MONORAIL';
13123
+ case RouteType.UNRECOGNIZED:
13124
+ default:
13125
+ throw new Error('Unrecognized protobuf route type.');
13126
+ }
13127
+ };
13128
+ const serializeRouteType = (type) => {
13129
+ switch (type) {
13130
+ case 'TRAM':
13131
+ return RouteType.TRAM;
13132
+ case 'SUBWAY':
13133
+ return RouteType.SUBWAY;
13134
+ case 'RAIL':
13135
+ return RouteType.RAIL;
13136
+ case 'BUS':
13137
+ return RouteType.BUS;
13138
+ case 'FERRY':
13139
+ return RouteType.FERRY;
13140
+ case 'CABLE_TRAM':
13141
+ return RouteType.CABLE_TRAM;
13142
+ case 'AERIAL_LIFT':
13143
+ return RouteType.AERIAL_LIFT;
13144
+ case 'FUNICULAR':
13145
+ return RouteType.FUNICULAR;
13146
+ case 'TROLLEYBUS':
13147
+ return RouteType.TROLLEYBUS;
13148
+ case 'MONORAIL':
13149
+ return RouteType.MONORAIL;
13150
+ }
13151
+ };
13152
+
12986
13153
  /**
12987
13154
  * A class representing a time in hours, minutes, and seconds.
12988
13155
  */
@@ -13154,195 +13321,10 @@ class Time {
13154
13321
  }
13155
13322
  }
13156
13323
 
13157
- const serializeStopsAdjacency = (stopsAdjacency) => {
13158
- const protoStopsAdjacency = {
13159
- stops: {},
13160
- };
13161
- stopsAdjacency.forEach((value, key) => {
13162
- protoStopsAdjacency.stops[key] = {
13163
- transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: serializeTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
13164
- minTransferTime: transfer.minTransferTime.toSeconds(),
13165
- })))),
13166
- routes: value.routes,
13167
- };
13168
- });
13169
- return protoStopsAdjacency;
13170
- };
13171
- const serializeRoutesAdjacency = (routesAdjacency) => {
13172
- const protoRoutesAdjacency = {
13173
- routes: {},
13174
- };
13175
- routesAdjacency.forEach((value, key) => {
13176
- protoRoutesAdjacency.routes[key] = {
13177
- stopTimes: value.stopTimes.map((stopTimes) => ({
13178
- arrival: stopTimes.arrival.toSeconds(),
13179
- departure: stopTimes.departure.toSeconds(),
13180
- pickUpType: serializePickUpDropOffType(stopTimes.pickUpType),
13181
- dropOffType: serializePickUpDropOffType(stopTimes.dropOffType),
13182
- })),
13183
- stops: value.stops,
13184
- serviceRouteId: value.serviceRouteId,
13185
- };
13186
- });
13187
- return protoRoutesAdjacency;
13188
- };
13189
- const serializeServiceRoutesMap = (serviceRoutesMap) => {
13190
- const protoServiceRoutesMap = {
13191
- routes: {},
13192
- };
13193
- serviceRoutesMap.forEach((value, key) => {
13194
- protoServiceRoutesMap.routes[key] = {
13195
- type: serializeRouteType(value.type),
13196
- name: value.name,
13197
- };
13198
- });
13199
- return protoServiceRoutesMap;
13200
- };
13201
- const deserializeStopsAdjacency = (protoStopsAdjacency) => {
13202
- const stopsAdjacency = new Map();
13203
- Object.entries(protoStopsAdjacency.stops).forEach(([key, value]) => {
13204
- stopsAdjacency.set(key, {
13205
- transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: parseTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
13206
- minTransferTime: Duration.fromSeconds(transfer.minTransferTime),
13207
- })))),
13208
- routes: value.routes,
13209
- });
13210
- });
13211
- return stopsAdjacency;
13212
- };
13213
- const deserializeRoutesAdjacency = (protoRoutesAdjacency) => {
13214
- const routesAdjacency = new Map();
13215
- Object.entries(protoRoutesAdjacency.routes).forEach(([key, value]) => {
13216
- routesAdjacency.set(key, {
13217
- stopTimes: value.stopTimes.map((stopTimes) => ({
13218
- arrival: Time.fromSeconds(stopTimes.arrival),
13219
- departure: Time.fromSeconds(stopTimes.departure),
13220
- pickUpType: stopTimes.pickUpType !== undefined
13221
- ? parsePickUpDropOffType(stopTimes.pickUpType)
13222
- : 'REGULAR',
13223
- dropOffType: stopTimes.dropOffType !== undefined
13224
- ? parsePickUpDropOffType(stopTimes.dropOffType)
13225
- : 'REGULAR',
13226
- })),
13227
- stops: value.stops,
13228
- stopIndices: new Map(value.stops.map((stop, index) => [stop, index])),
13229
- serviceRouteId: value.serviceRouteId,
13230
- });
13231
- });
13232
- return routesAdjacency;
13233
- };
13234
- const deserializeServiceRoutesMap = (protoServiceRoutesMap) => {
13235
- const serviceRoutesMap = new Map();
13236
- Object.entries(protoServiceRoutesMap.routes).forEach(([key, value]) => {
13237
- serviceRoutesMap.set(key, {
13238
- type: parseRouteType(value.type),
13239
- name: value.name,
13240
- });
13241
- });
13242
- return serviceRoutesMap;
13243
- };
13244
- const parseTransferType = (type) => {
13245
- switch (type) {
13246
- case TransferType.RECOMMENDED_TRANSFER_POINT:
13247
- return 'RECOMMENDED';
13248
- case TransferType.TIMED_TRANSFER:
13249
- return 'GUARANTEED';
13250
- case TransferType.REQUIRES_MINIMAL_TIME:
13251
- return 'REQUIRES_MINIMAL_TIME';
13252
- case TransferType.IN_SEAT_TRANSFER:
13253
- return 'IN_SEAT';
13254
- case TransferType.UNRECOGNIZED:
13255
- throw new Error('Unrecognized protobuf transfer type.');
13256
- }
13257
- };
13258
- const serializeTransferType = (type) => {
13259
- switch (type) {
13260
- case 'RECOMMENDED':
13261
- return TransferType.RECOMMENDED_TRANSFER_POINT;
13262
- case 'GUARANTEED':
13263
- return TransferType.TIMED_TRANSFER;
13264
- case 'REQUIRES_MINIMAL_TIME':
13265
- return TransferType.REQUIRES_MINIMAL_TIME;
13266
- case 'IN_SEAT':
13267
- return TransferType.IN_SEAT_TRANSFER;
13268
- }
13269
- };
13270
- const parseRouteType = (type) => {
13271
- switch (type) {
13272
- case RouteType.TRAM:
13273
- return 'TRAM';
13274
- case RouteType.SUBWAY:
13275
- return 'SUBWAY';
13276
- case RouteType.RAIL:
13277
- return 'RAIL';
13278
- case RouteType.BUS:
13279
- return 'BUS';
13280
- case RouteType.FERRY:
13281
- return 'FERRY';
13282
- case RouteType.CABLE_TRAM:
13283
- return 'CABLE_TRAM';
13284
- case RouteType.AERIAL_LIFT:
13285
- return 'AERIAL_LIFT';
13286
- case RouteType.FUNICULAR:
13287
- return 'FUNICULAR';
13288
- case RouteType.TROLLEYBUS:
13289
- return 'TROLLEYBUS';
13290
- case RouteType.MONORAIL:
13291
- return 'MONORAIL';
13292
- case RouteType.UNRECOGNIZED:
13293
- default:
13294
- throw new Error('Unrecognized protobuf route type.');
13295
- }
13296
- };
13297
- const serializeRouteType = (type) => {
13298
- switch (type) {
13299
- case 'TRAM':
13300
- return RouteType.TRAM;
13301
- case 'SUBWAY':
13302
- return RouteType.SUBWAY;
13303
- case 'RAIL':
13304
- return RouteType.RAIL;
13305
- case 'BUS':
13306
- return RouteType.BUS;
13307
- case 'FERRY':
13308
- return RouteType.FERRY;
13309
- case 'CABLE_TRAM':
13310
- return RouteType.CABLE_TRAM;
13311
- case 'AERIAL_LIFT':
13312
- return RouteType.AERIAL_LIFT;
13313
- case 'FUNICULAR':
13314
- return RouteType.FUNICULAR;
13315
- case 'TROLLEYBUS':
13316
- return RouteType.TROLLEYBUS;
13317
- case 'MONORAIL':
13318
- return RouteType.MONORAIL;
13319
- }
13320
- };
13321
- const parsePickUpDropOffType = (type) => {
13322
- switch (type) {
13323
- case PickUpDropOffType.MUST_PHONE_AGENCY:
13324
- return 'MUST_PHONE_AGENCY';
13325
- case PickUpDropOffType.MUST_COORDINATE_WITH_DRIVER:
13326
- return 'MUST_COORDINATE_WITH_DRIVER';
13327
- case PickUpDropOffType.NOT_AVAILABLE:
13328
- return 'NOT_AVAILABLE';
13329
- default:
13330
- return 'REGULAR';
13331
- }
13332
- };
13333
- const serializePickUpDropOffType = (type) => {
13334
- switch (type) {
13335
- case 'REGULAR':
13336
- return undefined;
13337
- case 'NOT_AVAILABLE':
13338
- return PickUpDropOffType.NOT_AVAILABLE;
13339
- case 'MUST_COORDINATE_WITH_DRIVER':
13340
- return PickUpDropOffType.MUST_COORDINATE_WITH_DRIVER;
13341
- case 'MUST_PHONE_AGENCY':
13342
- return PickUpDropOffType.MUST_PHONE_AGENCY;
13343
- }
13344
- };
13345
-
13324
+ const REGULAR = 0;
13325
+ const NOT_AVAILABLE = 1;
13326
+ const MUST_PHONE_AGENCY = 2;
13327
+ const MUST_COORDINATE_WITH_DRIVER = 3;
13346
13328
  const ALL_TRANSPORT_MODES = [
13347
13329
  'TRAM',
13348
13330
  'SUBWAY',
@@ -13355,7 +13337,7 @@ const ALL_TRANSPORT_MODES = [
13355
13337
  'TROLLEYBUS',
13356
13338
  'MONORAIL',
13357
13339
  ];
13358
- const CURRENT_VERSION = '0.0.1';
13340
+ const CURRENT_VERSION = '0.0.2';
13359
13341
  /**
13360
13342
  * The internal transit timetable format
13361
13343
  * reuses some GTFS concepts for the sake of simplicity for now.
@@ -13402,6 +13384,13 @@ class Timetable {
13402
13384
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
13403
13385
  deserializeServiceRoutesMap(protoTimetable.routes));
13404
13386
  }
13387
+ getRoutesThroughStop(stopId) {
13388
+ const stopAdjacency = this.stopsAdjacency.get(stopId);
13389
+ if (!stopAdjacency) {
13390
+ return [];
13391
+ }
13392
+ return stopAdjacency.routes;
13393
+ }
13405
13394
  getRoute(routeId) {
13406
13395
  return this.routesAdjacency.get(routeId);
13407
13396
  }
@@ -13468,9 +13457,9 @@ class Timetable {
13468
13457
  if (beforeTrip === undefined) {
13469
13458
  for (let tripIndex = 0; tripIndex < route.stopTimes.length / stopsNumber; tripIndex++) {
13470
13459
  const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
13471
- const stopTime = route.stopTimes[stopTimeIndex];
13472
- if (stopTime.departure >= after &&
13473
- stopTime.pickUpType !== 'NOT_AVAILABLE') {
13460
+ const departure = route.stopTimes[stopTimeIndex * 2 + 1];
13461
+ const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
13462
+ if (departure >= after.toSeconds() && pickUpType !== NOT_AVAILABLE) {
13474
13463
  return tripIndex;
13475
13464
  }
13476
13465
  }
@@ -13482,15 +13471,16 @@ class Timetable {
13482
13471
  for (let tripIndex = beforeTrip; // ?? route.stopTimes.length / stopsNumber - 1;
13483
13472
  tripIndex >= 0; tripIndex--) {
13484
13473
  const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
13485
- const stopTime = route.stopTimes[stopTimeIndex];
13486
- if (stopTime.departure < after) {
13474
+ const departure = route.stopTimes[stopTimeIndex * 2 + 1];
13475
+ const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
13476
+ if (departure < after.toSeconds()) {
13487
13477
  break;
13488
13478
  }
13489
- if (stopTime.pickUpType !== 'NOT_AVAILABLE' &&
13479
+ if (pickUpType !== NOT_AVAILABLE &&
13490
13480
  (earliestDeparture === undefined ||
13491
- stopTime.departure < earliestDeparture)) {
13481
+ departure < earliestDeparture.toSeconds())) {
13492
13482
  earliestTripIndex = tripIndex;
13493
- earliestDeparture = stopTime.departure;
13483
+ earliestDeparture = Time.fromSeconds(departure);
13494
13484
  }
13495
13485
  }
13496
13486
  return earliestTripIndex;
@@ -15416,23 +15406,23 @@ const parse = function () {
15416
15406
  };
15417
15407
 
15418
15408
  /**
15419
- * Generates a simple hash from a string.
15409
+ * Generates a simple hash from an array of numeric IDs.
15420
15410
  *
15421
- * This function computes a hash for a given string by iterating over each
15422
- * character and applying bitwise operations to accumulate a hash value.
15423
- * The final hash is then converted to a base-36 string and padded to
15424
- * ensure a minimum length of 6 characters.
15411
+ * This function computes a hash for a given array of numbers by iterating over each
15412
+ * ID and applying bitwise operations to accumulate a hash value.
15413
+ * The final hash is then converted to a base-36 string.
15425
15414
  *
15426
- * @param str - The input string to hash.
15427
- * @returns A hashed string representation of the input.
15415
+ * @param ids - The array of numeric IDs to hash.
15416
+ * @returns A hashed string representation of the input array.
15428
15417
  */
15429
- const hash = (str) => {
15418
+ const hashIds = (ids) => {
15430
15419
  let hash = 0;
15431
- for (let i = 0; i < str.length; i++) {
15432
- hash = (hash << 5) - hash + str.charCodeAt(i);
15420
+ for (let i = 0; i < ids.length; i++) {
15421
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15422
+ hash = (hash << 5) - hash + ids[i];
15433
15423
  hash &= hash;
15434
15424
  }
15435
- return (hash >>> 0).toString(36).padStart(6, '0');
15425
+ return (hash >>> 0).toString(36);
15436
15426
  };
15437
15427
  /**
15438
15428
  * Parses a CSV stream with a sensible configuration for GTFS feeds.
@@ -15600,18 +15590,19 @@ const parseCalendarDates = (calendarDatesStream, serviceIds, date) => __awaiter(
15600
15590
  * @param stopsStream The readable stream containing the stops data.
15601
15591
  * @return A mapping of stop IDs to corresponding stop details.
15602
15592
  */
15603
- const parseStops = (stopsStream, platformParser, validStops) => __awaiter(undefined, undefined, undefined, function* () {
15593
+ const parseStops = (stopsStream, platformParser) => __awaiter(undefined, undefined, undefined, function* () {
15604
15594
  var _a, e_1, _b, _c;
15605
- const stops = new Map();
15595
+ const parsedStops = new Map();
15596
+ let i = 0;
15606
15597
  try {
15607
15598
  for (var _d = true, _e = __asyncValues(parseCsv(stopsStream)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
15608
15599
  _c = _f.value;
15609
15600
  _d = false;
15610
15601
  const rawLine = _c;
15611
15602
  const line = rawLine;
15612
- const stop = Object.assign({ id: line.stop_id, name: line.stop_name, lat: line.stop_lat, lon: line.stop_lon, locationType: line.location_type
15603
+ 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
15613
15604
  ? parseGtfsLocationType(line.location_type)
15614
- : 'SIMPLE_STOP_OR_PLATFORM', children: [] }, (line.parent_station && { parent: line.parent_station }));
15605
+ : 'SIMPLE_STOP_OR_PLATFORM', children: [] }, (line.parent_station && { parentSourceId: line.parent_station }));
15615
15606
  if (platformParser) {
15616
15607
  try {
15617
15608
  const platform = platformParser(line);
@@ -15623,7 +15614,8 @@ const parseStops = (stopsStream, platformParser, validStops) => __awaiter(undefi
15623
15614
  console.info(`Could not parse platform for stop ${line.stop_id}.`);
15624
15615
  }
15625
15616
  }
15626
- stops.set(line.stop_id, stop);
15617
+ parsedStops.set(line.stop_id + '', stop);
15618
+ i = i + 1;
15627
15619
  }
15628
15620
  }
15629
15621
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
@@ -15633,29 +15625,50 @@ const parseStops = (stopsStream, platformParser, validStops) => __awaiter(undefi
15633
15625
  }
15634
15626
  finally { if (e_1) throw e_1.error; }
15635
15627
  }
15636
- for (const [stopId, stop] of stops) {
15637
- if (stop.parent) {
15638
- const parentStop = stops.get(stop.parent);
15628
+ for (const [sourceStopId, stop] of parsedStops) {
15629
+ if (stop.parentSourceId) {
15630
+ const parentStop = parsedStops.get(stop.parentSourceId);
15639
15631
  if (!parentStop) {
15640
- console.warn(`Cannot find parent stop ${stop.parent} of ${stopId}`);
15632
+ console.warn(`Cannot find parent stop ${stop.parentSourceId} of ${sourceStopId}`);
15641
15633
  continue;
15642
15634
  }
15643
- parentStop.children.push(stopId);
15635
+ stop.parent = parentStop.id;
15636
+ parentStop.children.push(stop.id);
15644
15637
  }
15645
15638
  }
15646
- if (validStops) {
15647
- // Remove all stops which don't have at least one valid stopId as a child,
15648
- // a parent or as its own.
15649
- for (const [stopId, stop] of stops) {
15650
- if (!validStops.has(stopId) &&
15651
- (!stop.parent || !validStops.has(stop.parent)) &&
15652
- !stop.children.some((childId) => validStops.has(childId))) {
15653
- stops.delete(stopId);
15654
- }
15639
+ return parsedStops;
15640
+ });
15641
+ /**
15642
+ * Builds the final stop map indexed by internal IDs.
15643
+ * Excludes all stops that do not have at least one valid stopId
15644
+ * as a child, a parent, or being valid itself.
15645
+ *
15646
+ * @param parsedStops - The map of parsed stops.
15647
+ * @param validStops - A set of valid stop IDs.
15648
+ * @returns A map of stops indexed by internal IDs.
15649
+ */
15650
+ const indexStops = (parsedStops, validStops) => {
15651
+ const stops = new Map();
15652
+ for (const [, stop] of parsedStops) {
15653
+ if (!validStops ||
15654
+ validStops.has(stop.id) ||
15655
+ (stop.parent && validStops.has(stop.parent)) ||
15656
+ stop.children.some((childId) => validStops.has(childId))) {
15657
+ stops.set(stop.id, {
15658
+ id: stop.id,
15659
+ sourceStopId: stop.sourceStopId,
15660
+ name: stop.name,
15661
+ lat: stop.lat,
15662
+ lon: stop.lon,
15663
+ locationType: stop.locationType,
15664
+ platform: stop.platform,
15665
+ children: stop.children.filter((childId) => !validStops || validStops.has(childId)),
15666
+ parent: stop.parent,
15667
+ });
15655
15668
  }
15656
15669
  }
15657
15670
  return stops;
15658
- });
15671
+ };
15659
15672
  const parseGtfsLocationType = (gtfsLocationType) => {
15660
15673
  switch (gtfsLocationType) {
15661
15674
  case 0:
@@ -15678,7 +15691,7 @@ const parseGtfsLocationType = (gtfsLocationType) => {
15678
15691
  * @param stopsStream The readable stream containing the stops data.
15679
15692
  * @return A mapping of stop IDs to corresponding stop details.
15680
15693
  */
15681
- const parseTransfers = (transfersStream) => __awaiter(undefined, undefined, undefined, function* () {
15694
+ const parseTransfers = (transfersStream, stopsMap) => __awaiter(undefined, undefined, undefined, function* () {
15682
15695
  var _a, e_1, _b, _c;
15683
15696
  const transfers = new Map();
15684
15697
  try {
@@ -15706,12 +15719,16 @@ const parseTransfers = (transfersStream) => __awaiter(undefined, undefined, unde
15706
15719
  if (transferEntry.transfer_type === 2 && !transferEntry.min_transfer_time) {
15707
15720
  console.info(`Missing minimum transfer time between ${transferEntry.from_stop_id} and ${transferEntry.to_stop_id}.`);
15708
15721
  }
15709
- const transfer = Object.assign({ destination: transferEntry.to_stop_id, type: parseGtfsTransferType(transferEntry.transfer_type) }, (transferEntry.min_transfer_time && {
15722
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15723
+ const fromStop = stopsMap.get(transferEntry.from_stop_id + '');
15724
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15725
+ const toStop = stopsMap.get(transferEntry.to_stop_id + '');
15726
+ const transfer = Object.assign({ destination: toStop.id, type: parseGtfsTransferType(transferEntry.transfer_type) }, (transferEntry.min_transfer_time && {
15710
15727
  minTransferTime: Duration.fromSeconds(transferEntry.min_transfer_time),
15711
15728
  }));
15712
- const fromStopTransfers = transfers.get(transferEntry.from_stop_id) || [];
15729
+ const fromStopTransfers = transfers.get(fromStop.id) || [];
15713
15730
  fromStopTransfers.push(transfer);
15714
- transfers.set(transferEntry.from_stop_id, fromStopTransfers);
15731
+ transfers.set(fromStop.id, fromStopTransfers);
15715
15732
  }
15716
15733
  }
15717
15734
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
@@ -15802,28 +15819,52 @@ const buildStopsAdjacencyStructure = (validStops, routes, transfersMap) => {
15802
15819
  * Parses the stop_times.txt data from a GTFS feed.
15803
15820
  *
15804
15821
  * @param stopTimesStream The readable stream containing the stop times data.
15822
+ * @param stopsMap A map of parsed stops from the GTFS feed.
15805
15823
  * @param validTripIds A map of valid trip IDs to corresponding route IDs.
15806
- * @param validStopIds A map of valid stop IDs.
15807
- * @returns A mapping of route IDs to route details. The routes return corresponds to the set of trips from GTFS that share the same stop list.
15824
+ * @param validStopIds A set of valid stop IDs.
15825
+ * @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.
15808
15826
  */
15809
- const parseStopTimes = (stopTimesStream, validTripIds, validStopIds) => __awaiter(undefined, undefined, undefined, function* () {
15827
+ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) => __awaiter(undefined, undefined, undefined, function* () {
15810
15828
  var _a, e_2, _b, _c;
15811
15829
  var _d, _e;
15830
+ /**
15831
+ * Inserts a trip at the right place in the routes adjacency structure.
15832
+ */
15812
15833
  const addTrip = (currentTripId) => {
15813
15834
  const gtfsRouteId = validTripIds.get(currentTripId);
15814
15835
  if (!gtfsRouteId) {
15815
15836
  stops = [];
15816
- stopTimes = [];
15837
+ arrivalTimes = [];
15838
+ departureTimes = [];
15839
+ pickUpTypes = [];
15840
+ dropOffTypes = [];
15817
15841
  return;
15818
15842
  }
15819
- const routeId = `${gtfsRouteId}_${hash(stops.join('$'))}`;
15843
+ const routeId = `${gtfsRouteId}_${hashIds(stops)}`;
15820
15844
  let route = routes.get(routeId);
15821
15845
  if (!route) {
15846
+ const stopsCount = stops.length;
15847
+ const stopsArray = new Uint32Array(stops);
15848
+ const stopTimesArray = new Uint32Array(stopsCount * 2);
15849
+ for (let i = 0; i < stopsCount; i++) {
15850
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15851
+ stopTimesArray[i * 2] = arrivalTimes[i];
15852
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15853
+ stopTimesArray[i * 2 + 1] = departureTimes[i];
15854
+ }
15855
+ const pickUpDropOffTypesArray = new Uint8Array(stopsCount * 2);
15856
+ for (let i = 0; i < stopsCount; i++) {
15857
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15858
+ pickUpDropOffTypesArray[i * 2] = pickUpTypes[i];
15859
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15860
+ pickUpDropOffTypesArray[i * 2 + 1] = dropOffTypes[i];
15861
+ }
15822
15862
  route = {
15823
15863
  serviceRouteId: gtfsRouteId,
15824
- stops: [...stops],
15864
+ stops: stopsArray,
15825
15865
  stopIndices: new Map(stops.map((stop, i) => [stop, i])),
15826
- stopTimes: [...stopTimes],
15866
+ stopTimes: stopTimesArray,
15867
+ pickUpDropOffTypes: pickUpDropOffTypesArray,
15827
15868
  };
15828
15869
  routes.set(routeId, route);
15829
15870
  for (const stop of stops) {
@@ -15831,31 +15872,59 @@ const parseStopTimes = (stopTimesStream, validTripIds, validStopIds) => __awaite
15831
15872
  }
15832
15873
  }
15833
15874
  else {
15834
- const tripFirstStop = stopTimes[0];
15835
- if (!tripFirstStop) {
15875
+ const tripFirstStopDeparture = departureTimes[0];
15876
+ if (tripFirstStopDeparture === undefined) {
15836
15877
  throw new Error(`Empty trip ${currentTripId}`);
15837
15878
  }
15838
- // insert the stopTimes at the right position
15839
- let stopTimesIndex = 0;
15840
- for (let i = 0; i < route.stopTimes.length; i += stops.length) {
15841
- const currentDeparture = route.stopTimes[i];
15842
- if (currentDeparture &&
15843
- tripFirstStop.departure > currentDeparture.departure) {
15844
- stopTimesIndex = i + stops.length;
15879
+ // Find the correct position to insert the new trip
15880
+ const stopsCount = stops.length;
15881
+ let insertPosition = 0;
15882
+ const existingTripsCount = route.stopTimes.length / (stopsCount * 2);
15883
+ for (let tripIndex = 0; tripIndex < existingTripsCount; tripIndex++) {
15884
+ const currentDeparture = route.stopTimes[tripIndex * stopsCount * 2 + 1];
15885
+ if (currentDeparture && tripFirstStopDeparture > currentDeparture) {
15886
+ insertPosition = (tripIndex + 1) * stopsCount;
15845
15887
  }
15846
15888
  else {
15847
15889
  break;
15848
15890
  }
15849
15891
  }
15850
- route.stopTimes.splice(stopTimesIndex, 0, ...stopTimes);
15892
+ // insert data for the new trip at the right place
15893
+ const newStopTimesLength = route.stopTimes.length + stopsCount * 2;
15894
+ const newStopTimes = new Uint32Array(newStopTimesLength);
15895
+ const newPickUpDropOffTypes = new Uint8Array(newStopTimesLength);
15896
+ newStopTimes.set(route.stopTimes.slice(0, insertPosition * 2), 0);
15897
+ newPickUpDropOffTypes.set(route.pickUpDropOffTypes.slice(0, insertPosition * 2), 0);
15898
+ for (let i = 0; i < stopsCount; i++) {
15899
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15900
+ newStopTimes[(insertPosition + i) * 2] = arrivalTimes[i];
15901
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15902
+ newStopTimes[(insertPosition + i) * 2 + 1] = departureTimes[i];
15903
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15904
+ newPickUpDropOffTypes[(insertPosition + i) * 2] = pickUpTypes[i];
15905
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15906
+ newPickUpDropOffTypes[(insertPosition + i) * 2 + 1] = dropOffTypes[i];
15907
+ }
15908
+ const afterInsertionSlice = route.stopTimes.slice(insertPosition * 2);
15909
+ newStopTimes.set(afterInsertionSlice, (insertPosition + stopsCount) * 2);
15910
+ const afterInsertionTypesSlice = route.pickUpDropOffTypes.slice(insertPosition * 2);
15911
+ newPickUpDropOffTypes.set(afterInsertionTypesSlice, (insertPosition + stopsCount) * 2);
15912
+ route.stopTimes = newStopTimes;
15913
+ route.pickUpDropOffTypes = newPickUpDropOffTypes;
15851
15914
  }
15852
15915
  stops = [];
15853
- stopTimes = [];
15916
+ arrivalTimes = [];
15917
+ departureTimes = [];
15918
+ pickUpTypes = [];
15919
+ dropOffTypes = [];
15854
15920
  };
15855
15921
  const routes = new Map();
15856
15922
  let previousSeq = 0;
15857
15923
  let stops = [];
15858
- let stopTimes = [];
15924
+ let arrivalTimes = [];
15925
+ let departureTimes = [];
15926
+ let pickUpTypes = [];
15927
+ let dropOffTypes = [];
15859
15928
  let currentTripId = undefined;
15860
15929
  try {
15861
15930
  for (var _f = true, _g = __asyncValues(parseCsv(stopTimesStream)), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
@@ -15874,24 +15943,20 @@ const parseStopTimes = (stopTimesStream, validTripIds, validStopIds) => __awaite
15874
15943
  if (line.pickup_type === 1 && line.drop_off_type === 1) {
15875
15944
  continue;
15876
15945
  }
15877
- if (currentTripId &&
15878
- line.trip_id !== currentTripId &&
15879
- stops.length > 0 &&
15880
- stopTimes.length > 0) {
15946
+ if (currentTripId && line.trip_id !== currentTripId && stops.length > 0) {
15881
15947
  addTrip(currentTripId);
15882
15948
  }
15883
15949
  currentTripId = line.trip_id;
15884
- stops.push(line.stop_id);
15950
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15951
+ stops.push(stopsMap.get(line.stop_id + '').id);
15885
15952
  const departure = (_d = line.departure_time) !== null && _d !== void 0 ? _d : line.arrival_time;
15886
15953
  const arrival = (_e = line.arrival_time) !== null && _e !== void 0 ? _e : line.departure_time;
15887
- stopTimes.push({
15888
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15889
- departure: toTime(departure),
15890
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15891
- arrival: toTime(arrival),
15892
- pickUpType: parsePickupDropOffType(line.pickup_type),
15893
- dropOffType: parsePickupDropOffType(line.drop_off_type),
15894
- });
15954
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15955
+ arrivalTimes.push(toTime(arrival).toSeconds());
15956
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
15957
+ departureTimes.push(toTime(departure).toSeconds());
15958
+ pickUpTypes.push(parsePickupDropOffType(line.pickup_type));
15959
+ dropOffTypes.push(parsePickupDropOffType(line.drop_off_type));
15895
15960
  previousSeq = line.stop_sequence;
15896
15961
  }
15897
15962
  }
@@ -15911,15 +15976,15 @@ const parsePickupDropOffType = (gtfsType) => {
15911
15976
  switch (gtfsType) {
15912
15977
  default:
15913
15978
  console.warn(`Unknown pickup/drop-off type ${gtfsType}`);
15914
- return 'REGULAR';
15979
+ return REGULAR;
15915
15980
  case 0:
15916
- return 'REGULAR';
15981
+ return REGULAR;
15917
15982
  case 1:
15918
- return 'NOT_AVAILABLE';
15983
+ return NOT_AVAILABLE;
15919
15984
  case 2:
15920
- return 'MUST_PHONE_AGENCY';
15985
+ return MUST_PHONE_AGENCY;
15921
15986
  case 3:
15922
- return 'MUST_COORDINATE_WITH_DRIVER';
15987
+ return MUST_COORDINATE_WITH_DRIVER;
15923
15988
  }
15924
15989
  };
15925
15990
 
@@ -15951,6 +16016,10 @@ class GtfsParser {
15951
16016
  const datetime = DateTime.fromJSDate(date);
15952
16017
  const validServiceIds = new Set();
15953
16018
  const validStopIds = new Set();
16019
+ log.info(`Parsing ${STOPS_FILE}`);
16020
+ const stopsStream = yield zip.stream(STOPS_FILE);
16021
+ const parsedStops = yield parseStops(stopsStream, this.profile.platformParser);
16022
+ log.info(`${parsedStops.size} parsed stops.`);
15954
16023
  if (entries[CALENDAR_FILE]) {
15955
16024
  log.info(`Parsing ${CALENDAR_FILE}`);
15956
16025
  const calendarStream = yield zip.stream(CALENDAR_FILE);
@@ -15975,18 +16044,17 @@ class GtfsParser {
15975
16044
  if (entries[TRANSFERS_FILE]) {
15976
16045
  log.info(`Parsing ${TRANSFERS_FILE}`);
15977
16046
  const transfersStream = yield zip.stream(TRANSFERS_FILE);
15978
- transfers = yield parseTransfers(transfersStream);
16047
+ transfers = yield parseTransfers(transfersStream, parsedStops);
15979
16048
  log.info(`${transfers.size} valid transfers.`);
15980
16049
  }
15981
16050
  log.info(`Parsing ${STOP_TIMES_FILE}`);
15982
16051
  const stopTimesStream = yield zip.stream(STOP_TIMES_FILE);
15983
- const routesAdjacency = yield parseStopTimes(stopTimesStream, trips, validStopIds);
16052
+ const routesAdjacency = yield parseStopTimes(stopTimesStream, parsedStops, trips, validStopIds);
15984
16053
  const stopsAdjacency = buildStopsAdjacencyStructure(validStopIds, routesAdjacency, transfers);
15985
16054
  log.info(`${routesAdjacency.size} valid unique routes.`);
15986
- log.info(`Parsing ${STOPS_FILE}`);
15987
- const stopsStream = yield zip.stream(STOPS_FILE);
15988
- const stops = yield parseStops(stopsStream, this.profile.platformParser, validStopIds);
15989
- log.info(`${stops.size} valid stops.`);
16055
+ log.info(`Removing unused stops.`);
16056
+ const stops = indexStops(parsedStops, validStopIds);
16057
+ log.info(`${stops.size} used stop stops, ${parsedStops.size - stops.size} unused.`);
15990
16058
  yield zip.close();
15991
16059
  const timetable = new Timetable(stopsAdjacency, routesAdjacency, validGtfsRoutes);
15992
16060
  log.info(`Building stops index.`);
@@ -16007,8 +16075,8 @@ class GtfsParser {
16007
16075
  const zip = new StreamZip.async({ file: this.path });
16008
16076
  log.info(`Parsing ${STOPS_FILE}`);
16009
16077
  const stopsStream = yield zip.stream(STOPS_FILE);
16010
- const stops = yield parseStops(stopsStream, this.profile.platformParser);
16011
- log.info(`${stops.size} valid stops.`);
16078
+ const stops = indexStops(yield parseStops(stopsStream, this.profile.platformParser));
16079
+ log.info(`${stops.size} parsed stops.`);
16012
16080
  yield zip.close();
16013
16081
  return new StopsIndex(stops);
16014
16082
  });