minotor 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cspell.json +14 -1
- package/.gitattributes +3 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +3 -0
- package/.github/workflows/minotor.yml +17 -1
- package/CHANGELOG.md +3 -9
- package/README.md +47 -17
- package/dist/__e2e__/router.test.d.ts +1 -0
- package/dist/cli/perf.d.ts +28 -0
- package/dist/cli/utils.d.ts +6 -2
- package/dist/cli.mjs +1967 -823
- package/dist/cli.mjs.map +1 -1
- package/dist/gtfs/trips.d.ts +1 -0
- package/dist/gtfs/utils.d.ts +1 -1
- package/dist/parser.cjs.js +1030 -627
- package/dist/parser.cjs.js.map +1 -1
- package/dist/parser.d.ts +4 -2
- package/dist/parser.esm.js +1030 -627
- package/dist/parser.esm.js.map +1 -1
- package/dist/router.cjs.js +1 -1
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +10 -5
- package/dist/router.esm.js +1 -1
- package/dist/router.esm.js.map +1 -1
- package/dist/router.umd.js +1 -1
- package/dist/router.umd.js.map +1 -1
- package/dist/routing/__tests__/result.test.d.ts +1 -0
- package/dist/routing/query.d.ts +27 -6
- package/dist/routing/result.d.ts +1 -1
- package/dist/routing/route.d.ts +47 -2
- package/dist/routing/router.d.ts +15 -1
- package/dist/stops/stopsIndex.d.ts +3 -3
- package/dist/timetable/__tests__/route.test.d.ts +1 -0
- package/dist/timetable/__tests__/time.test.d.ts +1 -0
- package/dist/timetable/io.d.ts +7 -1
- package/dist/timetable/proto/timetable.d.ts +1 -1
- package/dist/timetable/route.d.ts +155 -0
- package/dist/timetable/time.d.ts +21 -0
- package/dist/timetable/timetable.d.ts +41 -61
- package/package.json +36 -35
- package/src/__e2e__/benchmark.json +22 -0
- package/src/__e2e__/router.test.ts +209 -0
- package/src/__e2e__/timetable/stops.bin +3 -0
- package/src/__e2e__/timetable/timetable.bin +3 -0
- package/src/cli/minotor.ts +51 -1
- package/src/cli/perf.ts +136 -0
- package/src/cli/repl.ts +26 -13
- package/src/cli/utils.ts +6 -28
- package/src/gtfs/__tests__/parser.test.ts +12 -15
- package/src/gtfs/__tests__/services.test.ts +1 -0
- package/src/gtfs/__tests__/transfers.test.ts +0 -1
- package/src/gtfs/__tests__/trips.test.ts +67 -74
- package/src/gtfs/profiles/ch.ts +1 -1
- package/src/gtfs/routes.ts +4 -4
- package/src/gtfs/services.ts +15 -2
- package/src/gtfs/stops.ts +7 -3
- package/src/gtfs/transfers.ts +6 -3
- package/src/gtfs/trips.ts +33 -16
- package/src/gtfs/utils.ts +13 -2
- package/src/parser.ts +4 -2
- package/src/router.ts +17 -11
- package/src/routing/__tests__/result.test.ts +392 -0
- package/src/routing/__tests__/router.test.ts +94 -137
- package/src/routing/query.ts +28 -7
- package/src/routing/result.ts +10 -5
- package/src/routing/route.ts +95 -9
- package/src/routing/router.ts +82 -66
- package/src/stops/__tests__/io.test.ts +1 -1
- package/src/stops/__tests__/stopFinder.test.ts +1 -1
- package/src/stops/proto/stops.ts +4 -4
- package/src/stops/stopsIndex.ts +3 -3
- package/src/timetable/__tests__/io.test.ts +16 -23
- package/src/timetable/__tests__/route.test.ts +317 -0
- package/src/timetable/__tests__/time.test.ts +494 -0
- package/src/timetable/__tests__/timetable.test.ts +64 -75
- package/src/timetable/io.ts +32 -26
- package/src/timetable/proto/timetable.proto +1 -1
- package/src/timetable/proto/timetable.ts +13 -13
- package/src/timetable/route.ts +347 -0
- package/src/timetable/time.ts +40 -8
- package/src/timetable/timetable.ts +74 -165
- package/tsconfig.build.json +1 -1
package/dist/parser.esm.js
CHANGED
|
@@ -37,7 +37,7 @@ function __values(o) {
|
|
|
37
37
|
if (m) return m.call(o);
|
|
38
38
|
if (o && typeof o.length === "number") return {
|
|
39
39
|
next: function () {
|
|
40
|
-
if (o && i >= o.length) o =
|
|
40
|
+
if (o && i >= o.length) o = void 0;
|
|
41
41
|
return { value: o && o[i++], done: !o };
|
|
42
42
|
}
|
|
43
43
|
};
|
|
@@ -825,12 +825,13 @@ class SystemZone extends Zone {
|
|
|
825
825
|
}
|
|
826
826
|
}
|
|
827
827
|
|
|
828
|
-
|
|
829
|
-
function makeDTF(
|
|
830
|
-
|
|
831
|
-
|
|
828
|
+
const dtfCache = new Map();
|
|
829
|
+
function makeDTF(zoneName) {
|
|
830
|
+
let dtf = dtfCache.get(zoneName);
|
|
831
|
+
if (dtf === undefined) {
|
|
832
|
+
dtf = new Intl.DateTimeFormat("en-US", {
|
|
832
833
|
hour12: false,
|
|
833
|
-
timeZone:
|
|
834
|
+
timeZone: zoneName,
|
|
834
835
|
year: "numeric",
|
|
835
836
|
month: "2-digit",
|
|
836
837
|
day: "2-digit",
|
|
@@ -839,8 +840,9 @@ function makeDTF(zone) {
|
|
|
839
840
|
second: "2-digit",
|
|
840
841
|
era: "short",
|
|
841
842
|
});
|
|
843
|
+
dtfCache.set(zoneName, dtf);
|
|
842
844
|
}
|
|
843
|
-
return
|
|
845
|
+
return dtf;
|
|
844
846
|
}
|
|
845
847
|
|
|
846
848
|
const typeToPos = {
|
|
@@ -876,7 +878,7 @@ function partsOffset(dtf, date) {
|
|
|
876
878
|
return filled;
|
|
877
879
|
}
|
|
878
880
|
|
|
879
|
-
|
|
881
|
+
const ianaZoneCache = new Map();
|
|
880
882
|
/**
|
|
881
883
|
* A zone identified by an IANA identifier, like America/New_York
|
|
882
884
|
* @implements {Zone}
|
|
@@ -887,10 +889,11 @@ class IANAZone extends Zone {
|
|
|
887
889
|
* @return {IANAZone}
|
|
888
890
|
*/
|
|
889
891
|
static create(name) {
|
|
890
|
-
|
|
891
|
-
|
|
892
|
+
let zone = ianaZoneCache.get(name);
|
|
893
|
+
if (zone === undefined) {
|
|
894
|
+
ianaZoneCache.set(name, (zone = new IANAZone(name)));
|
|
892
895
|
}
|
|
893
|
-
return
|
|
896
|
+
return zone;
|
|
894
897
|
}
|
|
895
898
|
|
|
896
899
|
/**
|
|
@@ -898,8 +901,8 @@ class IANAZone extends Zone {
|
|
|
898
901
|
* @return {void}
|
|
899
902
|
*/
|
|
900
903
|
static resetCache() {
|
|
901
|
-
ianaZoneCache
|
|
902
|
-
dtfCache
|
|
904
|
+
ianaZoneCache.clear();
|
|
905
|
+
dtfCache.clear();
|
|
903
906
|
}
|
|
904
907
|
|
|
905
908
|
/**
|
|
@@ -1002,6 +1005,7 @@ class IANAZone extends Zone {
|
|
|
1002
1005
|
* @return {number}
|
|
1003
1006
|
*/
|
|
1004
1007
|
offset(ts) {
|
|
1008
|
+
if (!this.valid) return NaN;
|
|
1005
1009
|
const date = new Date(ts);
|
|
1006
1010
|
|
|
1007
1011
|
if (isNaN(date)) return NaN;
|
|
@@ -1067,36 +1071,36 @@ function getCachedLF(locString, opts = {}) {
|
|
|
1067
1071
|
return dtf;
|
|
1068
1072
|
}
|
|
1069
1073
|
|
|
1070
|
-
|
|
1074
|
+
const intlDTCache = new Map();
|
|
1071
1075
|
function getCachedDTF(locString, opts = {}) {
|
|
1072
1076
|
const key = JSON.stringify([locString, opts]);
|
|
1073
|
-
let dtf = intlDTCache
|
|
1074
|
-
if (
|
|
1077
|
+
let dtf = intlDTCache.get(key);
|
|
1078
|
+
if (dtf === undefined) {
|
|
1075
1079
|
dtf = new Intl.DateTimeFormat(locString, opts);
|
|
1076
|
-
intlDTCache
|
|
1080
|
+
intlDTCache.set(key, dtf);
|
|
1077
1081
|
}
|
|
1078
1082
|
return dtf;
|
|
1079
1083
|
}
|
|
1080
1084
|
|
|
1081
|
-
|
|
1085
|
+
const intlNumCache = new Map();
|
|
1082
1086
|
function getCachedINF(locString, opts = {}) {
|
|
1083
1087
|
const key = JSON.stringify([locString, opts]);
|
|
1084
|
-
let inf = intlNumCache
|
|
1085
|
-
if (
|
|
1088
|
+
let inf = intlNumCache.get(key);
|
|
1089
|
+
if (inf === undefined) {
|
|
1086
1090
|
inf = new Intl.NumberFormat(locString, opts);
|
|
1087
|
-
intlNumCache
|
|
1091
|
+
intlNumCache.set(key, inf);
|
|
1088
1092
|
}
|
|
1089
1093
|
return inf;
|
|
1090
1094
|
}
|
|
1091
1095
|
|
|
1092
|
-
|
|
1096
|
+
const intlRelCache = new Map();
|
|
1093
1097
|
function getCachedRTF(locString, opts = {}) {
|
|
1094
1098
|
const { base, ...cacheKeyOpts } = opts; // exclude `base` from the options
|
|
1095
1099
|
const key = JSON.stringify([locString, cacheKeyOpts]);
|
|
1096
|
-
let inf = intlRelCache
|
|
1097
|
-
if (
|
|
1100
|
+
let inf = intlRelCache.get(key);
|
|
1101
|
+
if (inf === undefined) {
|
|
1098
1102
|
inf = new Intl.RelativeTimeFormat(locString, opts);
|
|
1099
|
-
intlRelCache
|
|
1103
|
+
intlRelCache.set(key, inf);
|
|
1100
1104
|
}
|
|
1101
1105
|
return inf;
|
|
1102
1106
|
}
|
|
@@ -1111,14 +1115,28 @@ function systemLocale() {
|
|
|
1111
1115
|
}
|
|
1112
1116
|
}
|
|
1113
1117
|
|
|
1114
|
-
|
|
1118
|
+
const intlResolvedOptionsCache = new Map();
|
|
1119
|
+
function getCachedIntResolvedOptions(locString) {
|
|
1120
|
+
let opts = intlResolvedOptionsCache.get(locString);
|
|
1121
|
+
if (opts === undefined) {
|
|
1122
|
+
opts = new Intl.DateTimeFormat(locString).resolvedOptions();
|
|
1123
|
+
intlResolvedOptionsCache.set(locString, opts);
|
|
1124
|
+
}
|
|
1125
|
+
return opts;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
const weekInfoCache = new Map();
|
|
1115
1129
|
function getCachedWeekInfo(locString) {
|
|
1116
|
-
let data = weekInfoCache
|
|
1130
|
+
let data = weekInfoCache.get(locString);
|
|
1117
1131
|
if (!data) {
|
|
1118
1132
|
const locale = new Intl.Locale(locString);
|
|
1119
1133
|
// browsers currently implement this as a property, but spec says it should be a getter function
|
|
1120
1134
|
data = "getWeekInfo" in locale ? locale.getWeekInfo() : locale.weekInfo;
|
|
1121
|
-
|
|
1135
|
+
// minimalDays was removed from WeekInfo: https://github.com/tc39/proposal-intl-locale-info/issues/86
|
|
1136
|
+
if (!("minimalDays" in data)) {
|
|
1137
|
+
data = { ...fallbackWeekSettings, ...data };
|
|
1138
|
+
}
|
|
1139
|
+
weekInfoCache.set(locString, data);
|
|
1122
1140
|
}
|
|
1123
1141
|
return data;
|
|
1124
1142
|
}
|
|
@@ -1217,7 +1235,7 @@ function supportsFastNumbers(loc) {
|
|
|
1217
1235
|
loc.numberingSystem === "latn" ||
|
|
1218
1236
|
!loc.locale ||
|
|
1219
1237
|
loc.locale.startsWith("en") ||
|
|
1220
|
-
|
|
1238
|
+
getCachedIntResolvedOptions(loc.locale).numberingSystem === "latn"
|
|
1221
1239
|
);
|
|
1222
1240
|
}
|
|
1223
1241
|
}
|
|
@@ -1376,7 +1394,6 @@ const fallbackWeekSettings = {
|
|
|
1376
1394
|
/**
|
|
1377
1395
|
* @private
|
|
1378
1396
|
*/
|
|
1379
|
-
|
|
1380
1397
|
class Locale {
|
|
1381
1398
|
static fromOpts(opts) {
|
|
1382
1399
|
return Locale.create(
|
|
@@ -1400,9 +1417,11 @@ class Locale {
|
|
|
1400
1417
|
|
|
1401
1418
|
static resetCache() {
|
|
1402
1419
|
sysLocaleCache = null;
|
|
1403
|
-
intlDTCache
|
|
1404
|
-
intlNumCache
|
|
1405
|
-
intlRelCache
|
|
1420
|
+
intlDTCache.clear();
|
|
1421
|
+
intlNumCache.clear();
|
|
1422
|
+
intlRelCache.clear();
|
|
1423
|
+
intlResolvedOptionsCache.clear();
|
|
1424
|
+
weekInfoCache.clear();
|
|
1406
1425
|
}
|
|
1407
1426
|
|
|
1408
1427
|
static fromObject({ locale, numberingSystem, outputCalendar, weekSettings } = {}) {
|
|
@@ -1467,10 +1486,18 @@ class Locale {
|
|
|
1467
1486
|
|
|
1468
1487
|
months(length, format = false) {
|
|
1469
1488
|
return listStuff(this, length, months, () => {
|
|
1489
|
+
// Workaround for "ja" locale: formatToParts does not label all parts of the month
|
|
1490
|
+
// as "month" and for this locale there is no difference between "format" and "non-format".
|
|
1491
|
+
// As such, just use format() instead of formatToParts() and take the whole string
|
|
1492
|
+
const monthSpecialCase = this.intl === "ja" || this.intl.startsWith("ja-");
|
|
1493
|
+
format &= !monthSpecialCase;
|
|
1470
1494
|
const intl = format ? { month: length, day: "numeric" } : { month: length },
|
|
1471
1495
|
formatStr = format ? "format" : "standalone";
|
|
1472
1496
|
if (!this.monthsCache[formatStr][length]) {
|
|
1473
|
-
|
|
1497
|
+
const mapper = !monthSpecialCase
|
|
1498
|
+
? (dt) => this.extract(dt, intl, "month")
|
|
1499
|
+
: (dt) => this.dtFormatter(dt, intl).format();
|
|
1500
|
+
this.monthsCache[formatStr][length] = mapMonths(mapper);
|
|
1474
1501
|
}
|
|
1475
1502
|
return this.monthsCache[formatStr][length];
|
|
1476
1503
|
});
|
|
@@ -1556,7 +1583,7 @@ class Locale {
|
|
|
1556
1583
|
return (
|
|
1557
1584
|
this.locale === "en" ||
|
|
1558
1585
|
this.locale.toLowerCase() === "en-us" ||
|
|
1559
|
-
|
|
1586
|
+
getCachedIntResolvedOptions(this.intl).locale.startsWith("en-us")
|
|
1560
1587
|
);
|
|
1561
1588
|
}
|
|
1562
1589
|
|
|
@@ -1895,22 +1922,26 @@ function parseDigits(str) {
|
|
|
1895
1922
|
}
|
|
1896
1923
|
|
|
1897
1924
|
// cache of {numberingSystem: {append: regex}}
|
|
1898
|
-
|
|
1925
|
+
const digitRegexCache = new Map();
|
|
1899
1926
|
function resetDigitRegexCache() {
|
|
1900
|
-
digitRegexCache
|
|
1927
|
+
digitRegexCache.clear();
|
|
1901
1928
|
}
|
|
1902
1929
|
|
|
1903
1930
|
function digitRegex({ numberingSystem }, append = "") {
|
|
1904
1931
|
const ns = numberingSystem || "latn";
|
|
1905
1932
|
|
|
1906
|
-
|
|
1907
|
-
|
|
1933
|
+
let appendCache = digitRegexCache.get(ns);
|
|
1934
|
+
if (appendCache === undefined) {
|
|
1935
|
+
appendCache = new Map();
|
|
1936
|
+
digitRegexCache.set(ns, appendCache);
|
|
1908
1937
|
}
|
|
1909
|
-
|
|
1910
|
-
|
|
1938
|
+
let regex = appendCache.get(append);
|
|
1939
|
+
if (regex === undefined) {
|
|
1940
|
+
regex = new RegExp(`${numberingSystems[ns]}${append}`);
|
|
1941
|
+
appendCache.set(append, regex);
|
|
1911
1942
|
}
|
|
1912
1943
|
|
|
1913
|
-
return
|
|
1944
|
+
return regex;
|
|
1914
1945
|
}
|
|
1915
1946
|
|
|
1916
1947
|
let now = () => Date.now(),
|
|
@@ -2452,10 +2483,24 @@ function parseMillis(fraction) {
|
|
|
2452
2483
|
}
|
|
2453
2484
|
}
|
|
2454
2485
|
|
|
2455
|
-
function roundTo(number, digits,
|
|
2456
|
-
const factor = 10 ** digits
|
|
2457
|
-
|
|
2458
|
-
|
|
2486
|
+
function roundTo(number, digits, rounding = "round") {
|
|
2487
|
+
const factor = 10 ** digits;
|
|
2488
|
+
switch (rounding) {
|
|
2489
|
+
case "expand":
|
|
2490
|
+
return number > 0
|
|
2491
|
+
? Math.ceil(number * factor) / factor
|
|
2492
|
+
: Math.floor(number * factor) / factor;
|
|
2493
|
+
case "trunc":
|
|
2494
|
+
return Math.trunc(number * factor) / factor;
|
|
2495
|
+
case "round":
|
|
2496
|
+
return Math.round(number * factor) / factor;
|
|
2497
|
+
case "floor":
|
|
2498
|
+
return Math.floor(number * factor) / factor;
|
|
2499
|
+
case "ceil":
|
|
2500
|
+
return Math.ceil(number * factor) / factor;
|
|
2501
|
+
default:
|
|
2502
|
+
throw new RangeError(`Value rounding ${rounding} is out of range`);
|
|
2503
|
+
}
|
|
2459
2504
|
}
|
|
2460
2505
|
|
|
2461
2506
|
// DATE BASICS
|
|
@@ -2563,7 +2608,7 @@ function signedOffset(offHourStr, offMinuteStr) {
|
|
|
2563
2608
|
|
|
2564
2609
|
function asNumber(value) {
|
|
2565
2610
|
const numericValue = Number(value);
|
|
2566
|
-
if (typeof value === "boolean" || value === "" || Number.
|
|
2611
|
+
if (typeof value === "boolean" || value === "" || !Number.isFinite(numericValue))
|
|
2567
2612
|
throw new InvalidArgumentError(`Invalid unit value ${value}`);
|
|
2568
2613
|
return numericValue;
|
|
2569
2614
|
}
|
|
@@ -2822,8 +2867,12 @@ class Formatter {
|
|
|
2822
2867
|
for (let i = 0; i < fmt.length; i++) {
|
|
2823
2868
|
const c = fmt.charAt(i);
|
|
2824
2869
|
if (c === "'") {
|
|
2825
|
-
|
|
2826
|
-
|
|
2870
|
+
// turn '' into a literal signal quote instead of just skipping the empty literal
|
|
2871
|
+
if (currentFull.length > 0 || bracketed) {
|
|
2872
|
+
splits.push({
|
|
2873
|
+
literal: bracketed || /^\s+$/.test(currentFull),
|
|
2874
|
+
val: currentFull === "" ? "'" : currentFull,
|
|
2875
|
+
});
|
|
2827
2876
|
}
|
|
2828
2877
|
current = null;
|
|
2829
2878
|
currentFull = "";
|
|
@@ -2887,7 +2936,7 @@ class Formatter {
|
|
|
2887
2936
|
return this.dtFormatter(dt, opts).resolvedOptions();
|
|
2888
2937
|
}
|
|
2889
2938
|
|
|
2890
|
-
num(n, p = 0) {
|
|
2939
|
+
num(n, p = 0, signDisplay = undefined) {
|
|
2891
2940
|
// we get some perf out of doing this here, annoyingly
|
|
2892
2941
|
if (this.opts.forceSimple) {
|
|
2893
2942
|
return padStart(n, p);
|
|
@@ -2898,6 +2947,9 @@ class Formatter {
|
|
|
2898
2947
|
if (p > 0) {
|
|
2899
2948
|
opts.padTo = p;
|
|
2900
2949
|
}
|
|
2950
|
+
if (signDisplay) {
|
|
2951
|
+
opts.signDisplay = signDisplay;
|
|
2952
|
+
}
|
|
2901
2953
|
|
|
2902
2954
|
return this.loc.numberFormatter(opts).format(n);
|
|
2903
2955
|
}
|
|
@@ -3133,32 +3185,44 @@ class Formatter {
|
|
|
3133
3185
|
}
|
|
3134
3186
|
|
|
3135
3187
|
formatDurationFromString(dur, fmt) {
|
|
3188
|
+
const invertLargest = this.opts.signMode === "negativeLargestOnly" ? -1 : 1;
|
|
3136
3189
|
const tokenToField = (token) => {
|
|
3137
3190
|
switch (token[0]) {
|
|
3138
3191
|
case "S":
|
|
3139
|
-
return "
|
|
3192
|
+
return "milliseconds";
|
|
3140
3193
|
case "s":
|
|
3141
|
-
return "
|
|
3194
|
+
return "seconds";
|
|
3142
3195
|
case "m":
|
|
3143
|
-
return "
|
|
3196
|
+
return "minutes";
|
|
3144
3197
|
case "h":
|
|
3145
|
-
return "
|
|
3198
|
+
return "hours";
|
|
3146
3199
|
case "d":
|
|
3147
|
-
return "
|
|
3200
|
+
return "days";
|
|
3148
3201
|
case "w":
|
|
3149
|
-
return "
|
|
3202
|
+
return "weeks";
|
|
3150
3203
|
case "M":
|
|
3151
|
-
return "
|
|
3204
|
+
return "months";
|
|
3152
3205
|
case "y":
|
|
3153
|
-
return "
|
|
3206
|
+
return "years";
|
|
3154
3207
|
default:
|
|
3155
3208
|
return null;
|
|
3156
3209
|
}
|
|
3157
3210
|
},
|
|
3158
|
-
tokenToString = (lildur) => (token) => {
|
|
3211
|
+
tokenToString = (lildur, info) => (token) => {
|
|
3159
3212
|
const mapped = tokenToField(token);
|
|
3160
3213
|
if (mapped) {
|
|
3161
|
-
|
|
3214
|
+
const inversionFactor =
|
|
3215
|
+
info.isNegativeDuration && mapped !== info.largestUnit ? invertLargest : 1;
|
|
3216
|
+
let signDisplay;
|
|
3217
|
+
if (this.opts.signMode === "negativeLargestOnly" && mapped !== info.largestUnit) {
|
|
3218
|
+
signDisplay = "never";
|
|
3219
|
+
} else if (this.opts.signMode === "all") {
|
|
3220
|
+
signDisplay = "always";
|
|
3221
|
+
} else {
|
|
3222
|
+
// "auto" and "negative" are the same, but "auto" has better support
|
|
3223
|
+
signDisplay = "auto";
|
|
3224
|
+
}
|
|
3225
|
+
return this.num(lildur.get(mapped) * inversionFactor, token.length, signDisplay);
|
|
3162
3226
|
} else {
|
|
3163
3227
|
return token;
|
|
3164
3228
|
}
|
|
@@ -3168,8 +3232,14 @@ class Formatter {
|
|
|
3168
3232
|
(found, { literal, val }) => (literal ? found : found.concat(val)),
|
|
3169
3233
|
[]
|
|
3170
3234
|
),
|
|
3171
|
-
collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t))
|
|
3172
|
-
|
|
3235
|
+
collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t)),
|
|
3236
|
+
durationInfo = {
|
|
3237
|
+
isNegativeDuration: collapsed < 0,
|
|
3238
|
+
// this relies on "collapsed" being based on "shiftTo", which builds up the object
|
|
3239
|
+
// in order
|
|
3240
|
+
largestUnit: Object.keys(collapsed.values)[0],
|
|
3241
|
+
};
|
|
3242
|
+
return stringifyTokens(tokens, tokenToString(collapsed, durationInfo));
|
|
3173
3243
|
}
|
|
3174
3244
|
}
|
|
3175
3245
|
|
|
@@ -3230,11 +3300,11 @@ function simpleParse(...keys) {
|
|
|
3230
3300
|
}
|
|
3231
3301
|
|
|
3232
3302
|
// ISO and SQL parsing
|
|
3233
|
-
const offsetRegex = /(?:(
|
|
3303
|
+
const offsetRegex = /(?:([Zz])|([+-]\d\d)(?::?(\d\d))?)/;
|
|
3234
3304
|
const isoExtendedZone = `(?:${offsetRegex.source}?(?:\\[(${ianaRegex.source})\\])?)?`;
|
|
3235
3305
|
const isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/;
|
|
3236
3306
|
const isoTimeRegex = RegExp(`${isoTimeBaseRegex.source}${isoExtendedZone}`);
|
|
3237
|
-
const isoTimeExtensionRegex = RegExp(`(?:
|
|
3307
|
+
const isoTimeExtensionRegex = RegExp(`(?:[Tt]${isoTimeRegex.source})?`);
|
|
3238
3308
|
const isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/;
|
|
3239
3309
|
const isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/;
|
|
3240
3310
|
const isoOrdinalRegex = /(\d{4})-?(\d{3})/;
|
|
@@ -3949,9 +4019,13 @@ let Duration$1 = class Duration {
|
|
|
3949
4019
|
* @param {string} fmt - the format string
|
|
3950
4020
|
* @param {Object} opts - options
|
|
3951
4021
|
* @param {boolean} [opts.floor=true] - floor numerical values
|
|
4022
|
+
* @param {'negative'|'all'|'negativeLargestOnly'} [opts.signMode=negative] - How to handle signs
|
|
3952
4023
|
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("y d s") //=> "1 6 2"
|
|
3953
4024
|
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("yy dd sss") //=> "01 06 002"
|
|
3954
4025
|
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("M S") //=> "12 518402000"
|
|
4026
|
+
* @example Duration.fromObject({ days: 6, seconds: 2 }).toFormat("d s", { signMode: "all" }) //=> "+6 +2"
|
|
4027
|
+
* @example Duration.fromObject({ days: -6, seconds: -2 }).toFormat("d s", { signMode: "all" }) //=> "-6 -2"
|
|
4028
|
+
* @example Duration.fromObject({ days: -6, seconds: -2 }).toFormat("d s", { signMode: "negativeLargestOnly" }) //=> "-6 2"
|
|
3955
4029
|
* @return {string}
|
|
3956
4030
|
*/
|
|
3957
4031
|
toFormat(fmt, opts = {}) {
|
|
@@ -3971,21 +4045,25 @@ let Duration$1 = class Duration {
|
|
|
3971
4045
|
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options
|
|
3972
4046
|
* @param {Object} opts - Formatting options. Accepts the same keys as the options parameter of the native `Intl.NumberFormat` constructor, as well as `listStyle`.
|
|
3973
4047
|
* @param {string} [opts.listStyle='narrow'] - How to format the merged list. Corresponds to the `style` property of the options parameter of the native `Intl.ListFormat` constructor.
|
|
4048
|
+
* @param {boolean} [opts.showZeros=true] - Show all units previously used by the duration even if they are zero
|
|
3974
4049
|
* @example
|
|
3975
4050
|
* ```js
|
|
3976
|
-
* var dur = Duration.fromObject({
|
|
3977
|
-
* dur.toHuman() //=> '1
|
|
3978
|
-
* dur.toHuman({ listStyle: "long" }) //=> '1
|
|
3979
|
-
* dur.toHuman({ unitDisplay: "short" }) //=> '1
|
|
4051
|
+
* var dur = Duration.fromObject({ months: 1, weeks: 0, hours: 5, minutes: 6 })
|
|
4052
|
+
* dur.toHuman() //=> '1 month, 0 weeks, 5 hours, 6 minutes'
|
|
4053
|
+
* dur.toHuman({ listStyle: "long" }) //=> '1 month, 0 weeks, 5 hours, and 6 minutes'
|
|
4054
|
+
* dur.toHuman({ unitDisplay: "short" }) //=> '1 mth, 0 wks, 5 hr, 6 min'
|
|
4055
|
+
* dur.toHuman({ showZeros: false }) //=> '1 month, 5 hours, 6 minutes'
|
|
3980
4056
|
* ```
|
|
3981
4057
|
*/
|
|
3982
4058
|
toHuman(opts = {}) {
|
|
3983
4059
|
if (!this.isValid) return INVALID$2;
|
|
3984
4060
|
|
|
4061
|
+
const showZeros = opts.showZeros !== false;
|
|
4062
|
+
|
|
3985
4063
|
const l = orderedUnits$1
|
|
3986
4064
|
.map((unit) => {
|
|
3987
4065
|
const val = this.values[unit];
|
|
3988
|
-
if (isUndefined(val)) {
|
|
4066
|
+
if (isUndefined(val) || (val === 0 && !showZeros)) {
|
|
3989
4067
|
return null;
|
|
3990
4068
|
}
|
|
3991
4069
|
return this.loc
|
|
@@ -4345,6 +4423,17 @@ let Duration$1 = class Duration {
|
|
|
4345
4423
|
return clone$1(this, { values: negated }, true);
|
|
4346
4424
|
}
|
|
4347
4425
|
|
|
4426
|
+
/**
|
|
4427
|
+
* Removes all units with values equal to 0 from this Duration.
|
|
4428
|
+
* @example Duration.fromObject({ years: 2, days: 0, hours: 0, minutes: 0 }).removeZeros().toObject() //=> { years: 2 }
|
|
4429
|
+
* @return {Duration}
|
|
4430
|
+
*/
|
|
4431
|
+
removeZeros() {
|
|
4432
|
+
if (!this.isValid) return this;
|
|
4433
|
+
const vals = removeZeroes(this.values);
|
|
4434
|
+
return clone$1(this, { values: vals }, true);
|
|
4435
|
+
}
|
|
4436
|
+
|
|
4348
4437
|
/**
|
|
4349
4438
|
* Get the years.
|
|
4350
4439
|
* @type {number}
|
|
@@ -4655,13 +4744,22 @@ class Interval {
|
|
|
4655
4744
|
}
|
|
4656
4745
|
|
|
4657
4746
|
/**
|
|
4658
|
-
* Returns the end of the Interval
|
|
4747
|
+
* Returns the end of the Interval. This is the first instant which is not part of the interval
|
|
4748
|
+
* (Interval is half-open).
|
|
4659
4749
|
* @type {DateTime}
|
|
4660
4750
|
*/
|
|
4661
4751
|
get end() {
|
|
4662
4752
|
return this.isValid ? this.e : null;
|
|
4663
4753
|
}
|
|
4664
4754
|
|
|
4755
|
+
/**
|
|
4756
|
+
* Returns the last DateTime included in the interval (since end is not part of the interval)
|
|
4757
|
+
* @type {DateTime}
|
|
4758
|
+
*/
|
|
4759
|
+
get lastDateTime() {
|
|
4760
|
+
return this.isValid ? (this.e ? this.e.minus(1) : null) : null;
|
|
4761
|
+
}
|
|
4762
|
+
|
|
4665
4763
|
/**
|
|
4666
4764
|
* Returns whether this Interval's end is at least its start, meaning that the Interval isn't 'backwards'.
|
|
4667
4765
|
* @type {boolean}
|
|
@@ -4926,8 +5024,11 @@ class Interval {
|
|
|
4926
5024
|
}
|
|
4927
5025
|
|
|
4928
5026
|
/**
|
|
4929
|
-
* Merge an array of Intervals into
|
|
5027
|
+
* Merge an array of Intervals into an equivalent minimal set of Intervals.
|
|
4930
5028
|
* Combines overlapping and adjacent Intervals.
|
|
5029
|
+
* The resulting array will contain the Intervals in ascending order, that is, starting with the earliest Interval
|
|
5030
|
+
* and ending with the latest.
|
|
5031
|
+
*
|
|
4931
5032
|
* @param {Array} intervals
|
|
4932
5033
|
* @return {Array}
|
|
4933
5034
|
*/
|
|
@@ -6075,21 +6176,22 @@ function toTechFormat(dt, format, allowZ = true) {
|
|
|
6075
6176
|
: null;
|
|
6076
6177
|
}
|
|
6077
6178
|
|
|
6078
|
-
function toISODate(o, extended) {
|
|
6179
|
+
function toISODate(o, extended, precision) {
|
|
6079
6180
|
const longFormat = o.c.year > 9999 || o.c.year < 0;
|
|
6080
6181
|
let c = "";
|
|
6081
6182
|
if (longFormat && o.c.year >= 0) c += "+";
|
|
6082
6183
|
c += padStart(o.c.year, longFormat ? 6 : 4);
|
|
6083
|
-
|
|
6184
|
+
if (precision === "year") return c;
|
|
6084
6185
|
if (extended) {
|
|
6085
6186
|
c += "-";
|
|
6086
6187
|
c += padStart(o.c.month);
|
|
6188
|
+
if (precision === "month") return c;
|
|
6087
6189
|
c += "-";
|
|
6088
|
-
c += padStart(o.c.day);
|
|
6089
6190
|
} else {
|
|
6090
6191
|
c += padStart(o.c.month);
|
|
6091
|
-
|
|
6192
|
+
if (precision === "month") return c;
|
|
6092
6193
|
}
|
|
6194
|
+
c += padStart(o.c.day);
|
|
6093
6195
|
return c;
|
|
6094
6196
|
}
|
|
6095
6197
|
|
|
@@ -6099,26 +6201,39 @@ function toISOTime(
|
|
|
6099
6201
|
suppressSeconds,
|
|
6100
6202
|
suppressMilliseconds,
|
|
6101
6203
|
includeOffset,
|
|
6102
|
-
extendedZone
|
|
6204
|
+
extendedZone,
|
|
6205
|
+
precision
|
|
6103
6206
|
) {
|
|
6104
|
-
let
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6207
|
+
let showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0,
|
|
6208
|
+
c = "";
|
|
6209
|
+
switch (precision) {
|
|
6210
|
+
case "day":
|
|
6211
|
+
case "month":
|
|
6212
|
+
case "year":
|
|
6213
|
+
break;
|
|
6214
|
+
default:
|
|
6215
|
+
c += padStart(o.c.hour);
|
|
6216
|
+
if (precision === "hour") break;
|
|
6217
|
+
if (extended) {
|
|
6218
|
+
c += ":";
|
|
6219
|
+
c += padStart(o.c.minute);
|
|
6220
|
+
if (precision === "minute") break;
|
|
6221
|
+
if (showSeconds) {
|
|
6222
|
+
c += ":";
|
|
6223
|
+
c += padStart(o.c.second);
|
|
6224
|
+
}
|
|
6225
|
+
} else {
|
|
6226
|
+
c += padStart(o.c.minute);
|
|
6227
|
+
if (precision === "minute") break;
|
|
6228
|
+
if (showSeconds) {
|
|
6229
|
+
c += padStart(o.c.second);
|
|
6230
|
+
}
|
|
6231
|
+
}
|
|
6232
|
+
if (precision === "second") break;
|
|
6233
|
+
if (showSeconds && (!suppressMilliseconds || o.c.millisecond !== 0)) {
|
|
6234
|
+
c += ".";
|
|
6235
|
+
c += padStart(o.c.millisecond, 3);
|
|
6236
|
+
}
|
|
6122
6237
|
}
|
|
6123
6238
|
|
|
6124
6239
|
if (includeOffset) {
|
|
@@ -6250,15 +6365,27 @@ function normalizeUnitWithLocalWeeks(unit) {
|
|
|
6250
6365
|
// This is safe for quickDT (used by local() and utc()) because we don't fill in
|
|
6251
6366
|
// higher-order units from tsNow (as we do in fromObject, this requires that
|
|
6252
6367
|
// offset is calculated from tsNow).
|
|
6368
|
+
/**
|
|
6369
|
+
* @param {Zone} zone
|
|
6370
|
+
* @return {number}
|
|
6371
|
+
*/
|
|
6253
6372
|
function guessOffsetForZone(zone) {
|
|
6254
|
-
if (
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
}
|
|
6373
|
+
if (zoneOffsetTs === undefined) {
|
|
6374
|
+
zoneOffsetTs = Settings.now();
|
|
6375
|
+
}
|
|
6258
6376
|
|
|
6259
|
-
|
|
6377
|
+
// Do not cache anything but IANA zones, because it is not safe to do so.
|
|
6378
|
+
// Guessing an offset which is not present in the zone can cause wrong results from fixOffset
|
|
6379
|
+
if (zone.type !== "iana") {
|
|
6380
|
+
return zone.offset(zoneOffsetTs);
|
|
6260
6381
|
}
|
|
6261
|
-
|
|
6382
|
+
const zoneName = zone.name;
|
|
6383
|
+
let offsetGuess = zoneOffsetGuessCache.get(zoneName);
|
|
6384
|
+
if (offsetGuess === undefined) {
|
|
6385
|
+
offsetGuess = zone.offset(zoneOffsetTs);
|
|
6386
|
+
zoneOffsetGuessCache.set(zoneName, offsetGuess);
|
|
6387
|
+
}
|
|
6388
|
+
return offsetGuess;
|
|
6262
6389
|
}
|
|
6263
6390
|
|
|
6264
6391
|
// this is a dumbed down version of fromObject() that runs about 60% faster
|
|
@@ -6298,8 +6425,9 @@ function quickDT(obj, opts) {
|
|
|
6298
6425
|
|
|
6299
6426
|
function diffRelative(start, end, opts) {
|
|
6300
6427
|
const round = isUndefined(opts.round) ? true : opts.round,
|
|
6428
|
+
rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding,
|
|
6301
6429
|
format = (c, unit) => {
|
|
6302
|
-
c = roundTo(c, round || opts.calendary ? 0 : 2,
|
|
6430
|
+
c = roundTo(c, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
|
|
6303
6431
|
const formatter = end.loc.clone(opts).relFormatter(opts);
|
|
6304
6432
|
return formatter.format(c, unit);
|
|
6305
6433
|
},
|
|
@@ -6348,7 +6476,7 @@ let zoneOffsetTs;
|
|
|
6348
6476
|
* This optimizes quickDT via guessOffsetForZone to avoid repeated calls of
|
|
6349
6477
|
* zone.offset().
|
|
6350
6478
|
*/
|
|
6351
|
-
|
|
6479
|
+
const zoneOffsetGuessCache = new Map();
|
|
6352
6480
|
|
|
6353
6481
|
/**
|
|
6354
6482
|
* A DateTime is an immutable data structure representing a specific date and time and accompanying methods. It contains class and instance methods for creating, parsing, interrogating, transforming, and formatting them.
|
|
@@ -6552,7 +6680,7 @@ class DateTime {
|
|
|
6552
6680
|
throw new InvalidArgumentError(
|
|
6553
6681
|
`fromMillis requires a numerical input, but received a ${typeof milliseconds} with value ${milliseconds}`
|
|
6554
6682
|
);
|
|
6555
|
-
} else if (milliseconds < -
|
|
6683
|
+
} else if (milliseconds < -MAX_DATE || milliseconds > MAX_DATE) {
|
|
6556
6684
|
// this isn't perfect because we can still end up out of range because of additional shifting, but it's a start
|
|
6557
6685
|
return DateTime.invalid("Timestamp out of range");
|
|
6558
6686
|
} else {
|
|
@@ -6913,7 +7041,7 @@ class DateTime {
|
|
|
6913
7041
|
|
|
6914
7042
|
static resetCache() {
|
|
6915
7043
|
zoneOffsetTs = undefined;
|
|
6916
|
-
zoneOffsetGuessCache
|
|
7044
|
+
zoneOffsetGuessCache.clear();
|
|
6917
7045
|
}
|
|
6918
7046
|
|
|
6919
7047
|
// INFO
|
|
@@ -7678,11 +7806,14 @@ class DateTime {
|
|
|
7678
7806
|
* @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
|
|
7679
7807
|
* @param {boolean} [opts.extendedZone=false] - add the time zone format extension
|
|
7680
7808
|
* @param {string} [opts.format='extended'] - choose between the basic and extended format
|
|
7809
|
+
* @param {string} [opts.precision='milliseconds'] - truncate output to desired presicion: 'years', 'months', 'days', 'hours', 'minutes', 'seconds' or 'milliseconds'. When precision and suppressSeconds or suppressMilliseconds are used together, precision sets the maximum unit shown in the output, however seconds or milliseconds will still be suppressed if they are 0.
|
|
7681
7810
|
* @example DateTime.utc(1983, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z'
|
|
7682
7811
|
* @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00'
|
|
7683
7812
|
* @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335'
|
|
7684
7813
|
* @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400'
|
|
7685
|
-
* @
|
|
7814
|
+
* @example DateTime.now().toISO({ precision: 'day' }) //=> '2017-04-22Z'
|
|
7815
|
+
* @example DateTime.now().toISO({ precision: 'minute' }) //=> '2017-04-22T20:47Z'
|
|
7816
|
+
* @return {string|null}
|
|
7686
7817
|
*/
|
|
7687
7818
|
toISO({
|
|
7688
7819
|
format = "extended",
|
|
@@ -7690,16 +7821,26 @@ class DateTime {
|
|
|
7690
7821
|
suppressMilliseconds = false,
|
|
7691
7822
|
includeOffset = true,
|
|
7692
7823
|
extendedZone = false,
|
|
7824
|
+
precision = "milliseconds",
|
|
7693
7825
|
} = {}) {
|
|
7694
7826
|
if (!this.isValid) {
|
|
7695
7827
|
return null;
|
|
7696
7828
|
}
|
|
7697
7829
|
|
|
7830
|
+
precision = normalizeUnit(precision);
|
|
7698
7831
|
const ext = format === "extended";
|
|
7699
7832
|
|
|
7700
|
-
let c = toISODate(this, ext);
|
|
7701
|
-
c += "T";
|
|
7702
|
-
c += toISOTime(
|
|
7833
|
+
let c = toISODate(this, ext, precision);
|
|
7834
|
+
if (orderedUnits.indexOf(precision) >= 3) c += "T";
|
|
7835
|
+
c += toISOTime(
|
|
7836
|
+
this,
|
|
7837
|
+
ext,
|
|
7838
|
+
suppressSeconds,
|
|
7839
|
+
suppressMilliseconds,
|
|
7840
|
+
includeOffset,
|
|
7841
|
+
extendedZone,
|
|
7842
|
+
precision
|
|
7843
|
+
);
|
|
7703
7844
|
return c;
|
|
7704
7845
|
}
|
|
7705
7846
|
|
|
@@ -7707,16 +7848,17 @@ class DateTime {
|
|
|
7707
7848
|
* Returns an ISO 8601-compliant string representation of this DateTime's date component
|
|
7708
7849
|
* @param {Object} opts - options
|
|
7709
7850
|
* @param {string} [opts.format='extended'] - choose between the basic and extended format
|
|
7851
|
+
* @param {string} [opts.precision='day'] - truncate output to desired precision: 'years', 'months', or 'days'.
|
|
7710
7852
|
* @example DateTime.utc(1982, 5, 25).toISODate() //=> '1982-05-25'
|
|
7711
7853
|
* @example DateTime.utc(1982, 5, 25).toISODate({ format: 'basic' }) //=> '19820525'
|
|
7712
|
-
* @
|
|
7854
|
+
* @example DateTime.utc(1982, 5, 25).toISODate({ precision: 'month' }) //=> '1982-05'
|
|
7855
|
+
* @return {string|null}
|
|
7713
7856
|
*/
|
|
7714
|
-
toISODate({ format = "extended" } = {}) {
|
|
7857
|
+
toISODate({ format = "extended", precision = "day" } = {}) {
|
|
7715
7858
|
if (!this.isValid) {
|
|
7716
7859
|
return null;
|
|
7717
7860
|
}
|
|
7718
|
-
|
|
7719
|
-
return toISODate(this, format === "extended");
|
|
7861
|
+
return toISODate(this, format === "extended", normalizeUnit(precision));
|
|
7720
7862
|
}
|
|
7721
7863
|
|
|
7722
7864
|
/**
|
|
@@ -7737,10 +7879,12 @@ class DateTime {
|
|
|
7737
7879
|
* @param {boolean} [opts.extendedZone=true] - add the time zone format extension
|
|
7738
7880
|
* @param {boolean} [opts.includePrefix=false] - include the `T` prefix
|
|
7739
7881
|
* @param {string} [opts.format='extended'] - choose between the basic and extended format
|
|
7882
|
+
* @param {string} [opts.precision='milliseconds'] - truncate output to desired presicion: 'hours', 'minutes', 'seconds' or 'milliseconds'. When precision and suppressSeconds or suppressMilliseconds are used together, precision sets the maximum unit shown in the output, however seconds or milliseconds will still be suppressed if they are 0.
|
|
7740
7883
|
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime() //=> '07:34:19.361Z'
|
|
7741
7884
|
* @example DateTime.utc().set({ hour: 7, minute: 34, seconds: 0, milliseconds: 0 }).toISOTime({ suppressSeconds: true }) //=> '07:34Z'
|
|
7742
7885
|
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ format: 'basic' }) //=> '073419.361Z'
|
|
7743
7886
|
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ includePrefix: true }) //=> 'T07:34:19.361Z'
|
|
7887
|
+
* @example DateTime.utc().set({ hour: 7, minute: 34, second: 56 }).toISOTime({ precision: 'minute' }) //=> '07:34Z'
|
|
7744
7888
|
* @return {string}
|
|
7745
7889
|
*/
|
|
7746
7890
|
toISOTime({
|
|
@@ -7750,12 +7894,14 @@ class DateTime {
|
|
|
7750
7894
|
includePrefix = false,
|
|
7751
7895
|
extendedZone = false,
|
|
7752
7896
|
format = "extended",
|
|
7897
|
+
precision = "milliseconds",
|
|
7753
7898
|
} = {}) {
|
|
7754
7899
|
if (!this.isValid) {
|
|
7755
7900
|
return null;
|
|
7756
7901
|
}
|
|
7757
7902
|
|
|
7758
|
-
|
|
7903
|
+
precision = normalizeUnit(precision);
|
|
7904
|
+
let c = includePrefix && orderedUnits.indexOf(precision) >= 3 ? "T" : "";
|
|
7759
7905
|
return (
|
|
7760
7906
|
c +
|
|
7761
7907
|
toISOTime(
|
|
@@ -7764,7 +7910,8 @@ class DateTime {
|
|
|
7764
7910
|
suppressSeconds,
|
|
7765
7911
|
suppressMilliseconds,
|
|
7766
7912
|
includeOffset,
|
|
7767
|
-
extendedZone
|
|
7913
|
+
extendedZone,
|
|
7914
|
+
precision
|
|
7768
7915
|
)
|
|
7769
7916
|
);
|
|
7770
7917
|
}
|
|
@@ -7794,7 +7941,7 @@ class DateTime {
|
|
|
7794
7941
|
/**
|
|
7795
7942
|
* Returns a string representation of this DateTime appropriate for use in SQL Date
|
|
7796
7943
|
* @example DateTime.utc(2014, 7, 13).toSQLDate() //=> '2014-07-13'
|
|
7797
|
-
* @return {string}
|
|
7944
|
+
* @return {string|null}
|
|
7798
7945
|
*/
|
|
7799
7946
|
toSQLDate() {
|
|
7800
7947
|
if (!this.isValid) {
|
|
@@ -7889,7 +8036,7 @@ class DateTime {
|
|
|
7889
8036
|
}
|
|
7890
8037
|
|
|
7891
8038
|
/**
|
|
7892
|
-
* Returns the epoch seconds of this DateTime.
|
|
8039
|
+
* Returns the epoch seconds (including milliseconds in the fractional part) of this DateTime.
|
|
7893
8040
|
* @return {number}
|
|
7894
8041
|
*/
|
|
7895
8042
|
toSeconds() {
|
|
@@ -7996,7 +8143,7 @@ class DateTime {
|
|
|
7996
8143
|
/**
|
|
7997
8144
|
* Return an Interval spanning between this DateTime and another DateTime
|
|
7998
8145
|
* @param {DateTime} otherDateTime - the other end point of the Interval
|
|
7999
|
-
* @return {Interval}
|
|
8146
|
+
* @return {Interval|DateTime}
|
|
8000
8147
|
*/
|
|
8001
8148
|
until(otherDateTime) {
|
|
8002
8149
|
return this.isValid ? Interval.fromDateTimes(this, otherDateTime) : this;
|
|
@@ -8042,12 +8189,13 @@ class DateTime {
|
|
|
8042
8189
|
|
|
8043
8190
|
/**
|
|
8044
8191
|
* Returns a string representation of a this time relative to now, such as "in two days". Can only internationalize if your
|
|
8045
|
-
* platform supports Intl.RelativeTimeFormat. Rounds
|
|
8192
|
+
* platform supports Intl.RelativeTimeFormat. Rounds towards zero by default.
|
|
8046
8193
|
* @param {Object} options - options that affect the output
|
|
8047
8194
|
* @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
|
|
8048
8195
|
* @param {string} [options.style="long"] - the style of units, must be "long", "short", or "narrow"
|
|
8049
8196
|
* @param {string|string[]} options.unit - use a specific unit or array of units; if omitted, or an array, the method will pick the best unit. Use an array or one of "years", "quarters", "months", "weeks", "days", "hours", "minutes", or "seconds"
|
|
8050
8197
|
* @param {boolean} [options.round=true] - whether to round the numbers in the output.
|
|
8198
|
+
* @param {string} [options.rounding="trunc"] - rounding method to use when rounding the numbers in the output. Can be "trunc" (toward zero), "expand" (away from zero), "round", "floor", or "ceil".
|
|
8051
8199
|
* @param {number} [options.padding=0] - padding in milliseconds. This allows you to round up the result if it fits inside the threshold. Don't use in combination with {round: false} because the decimal output will include the padding.
|
|
8052
8200
|
* @param {string} options.locale - override the locale of this DateTime
|
|
8053
8201
|
* @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this
|
|
@@ -10435,7 +10583,7 @@ class BinaryReader {
|
|
|
10435
10583
|
// ignore
|
|
10436
10584
|
}
|
|
10437
10585
|
break;
|
|
10438
|
-
// @ts-
|
|
10586
|
+
// @ts-ignore TS7029: Fallthrough case in switch -- ignore instead of expect-error for compiler settings without noFallthroughCasesInSwitch: true
|
|
10439
10587
|
case WireType.Bit64:
|
|
10440
10588
|
this.pos += 4;
|
|
10441
10589
|
case WireType.Bit32:
|
|
@@ -10716,7 +10864,6 @@ function around(index, lng, lat, maxResults = Infinity, maxDistance = Infinity,
|
|
|
10716
10864
|
left: 0, // left index in the kd-tree array
|
|
10717
10865
|
right: index.ids.length - 1, // right index
|
|
10718
10866
|
axis: 0, // 0 for longitude axis and 1 for latitude axis
|
|
10719
|
-
dist: 0, // will hold the lower bound of children's distances to the query point
|
|
10720
10867
|
minLng: -180, // bounding box of the node
|
|
10721
10868
|
minLat: -90,
|
|
10722
10869
|
maxLng: 180,
|
|
@@ -11184,7 +11331,7 @@ function sqDist(ax, ay, bx, by) {
|
|
|
11184
11331
|
return dx * dx + dy * dy;
|
|
11185
11332
|
}
|
|
11186
11333
|
|
|
11187
|
-
const xt="ENTRIES",B="KEYS",G="VALUES",g="";class V{set;_type;_path;constructor(e,n){const o=e._tree,s=Array.from(o.keys());this.set=e,this._type=n,this._path=s.length>0?[{node:o,keys:s}]:[];}next(){const e=this.dive();return this.backtrack(),e}dive(){if(this._path.length===0)return {done:true,value:undefined};const{node:e,keys:n}=z(this._path);if(z(n)===g)return {done:false,value:this.result()};const o=e.get(z(n));return this._path.push({node:o,keys:Array.from(o.keys())}),this.dive()}backtrack(){if(this._path.length===0)return;const e=z(this._path).keys;e.pop(),!(e.length>0)&&(this._path.pop(),this.backtrack());}key(){return this.set._prefix+this._path.map(({keys:e})=>z(e)).filter(e=>e!==g).join("")}value(){return z(this._path).node.get(g)}result(){switch(this._type){case G:return this.value();case B:return this.key();default:return [this.key(),this.value()]}}[Symbol.iterator](){return this}}const z=t=>t[t.length-1],zt=(t,e,n)=>{const o=new Map;if(typeof e!="string")return o;const s=e.length+1,r=s+n,i=new Uint8Array(r*s).fill(n+1);for(let c=0;c<s;++c)i[c]=c;for(let c=1;c<r;++c)i[c*s]=c;return K(t,e,n,o,i,1,s,""),o},K=(t,e,n,o,s,r,i,c)=>{const u=r*i;t:for(const d of t.keys())if(d===g){const a=s[u-1];a<=n&&o.set(c,[t.get(d),a]);}else {let a=r;for(let h=0;h<d.length;++h,++a){const f=d[h],_=i*a,p=_-i;let l=s[_];const m=Math.max(0,a-n-1),y=Math.min(i-1,a+n);for(let w=m;w<y;++w){const C=f!==e[w],O=s[p+w]+ +C,b=s[p+w+1]+1,x=s[_+w]+1,S=s[_+w+1]=Math.min(O,b,x);S<l&&(l=S);}if(l>n)continue t}K(t.get(d),e,n,o,s,a,i,c+d);}};class I{_tree;_prefix;_size=undefined;constructor(e=new Map,n=""){this._tree=e,this._prefix=n;}atPrefix(e){if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");const[n,o]=v(this._tree,e.slice(this._prefix.length));if(n===undefined){const[s,r]=L(o);for(const i of s.keys())if(i!==g&&i.startsWith(r)){const c=new Map;return c.set(i.slice(r.length),s.get(i)),new I(c,e)}}return new I(n,e)}clear(){this._size=undefined,this._tree.clear();}delete(e){return this._size=undefined,St(this._tree,e)}entries(){return new V(this,xt)}forEach(e){for(const[n,o]of this)e(n,o,this);}fuzzyGet(e,n){return zt(this._tree,e,n)}get(e){const n=T(this._tree,e);return n!==undefined?n.get(g):undefined}has(e){return T(this._tree,e)?.has(g)??false}keys(){return new V(this,B)}set(e,n){if(typeof e!="string")throw new Error("key must be a string");return this._size=undefined,M(this._tree,e).set(g,n),this}get size(){if(this._size)return this._size;this._size=0;const e=this.entries();for(;!e.next().done;)this._size+=1;return this._size}update(e,n){if(typeof e!="string")throw new Error("key must be a string");this._size=undefined;const o=M(this._tree,e);return o.set(g,n(o.get(g))),this}fetch(e,n){if(typeof e!="string")throw new Error("key must be a string");this._size=undefined;const o=M(this._tree,e);let s=o.get(g);return s===undefined&&o.set(g,s=n()),s}values(){return new V(this,G)}[Symbol.iterator](){return this.entries()}static from(e){const n=new I;for(const[o,s]of e)n.set(o,s);return n}static fromObject(e){return I.from(Object.entries(e))}}const v=(t,e,n=[])=>{if(e.length===0||t==null)return [t,n];for(const o of t.keys())if(o!==g&&e.startsWith(o))return n.push([t,o]),v(t.get(o),e.slice(o.length),n);return n.push([t,e]),v(undefined,"",n)},T=(t,e)=>{if(e.length===0||!t)return t;for(const n of t.keys())if(n!==g&&e.startsWith(n))return T(t.get(n),e.slice(n.length))},M=(t,e)=>{const n=e.length;t:for(let o=0;t&&o<n;){for(const r of t.keys())if(r!==g&&e[o]===r[0]){const i=Math.min(n-o,r.length);let c=1;for(;c<i&&e[o+c]===r[c];)++c;const u=t.get(r);if(c===r.length)t=u;else {const d=new Map;d.set(r.slice(c),u),t.set(e.slice(o,o+c),d),t.delete(r),t=d;}o+=c;continue t}const s=new Map;return t.set(e.slice(o),s),s}return t},St=(t,e)=>{const[n,o]=v(t,e);if(n!==undefined){if(n.delete(g),n.size===0)Q(o);else if(n.size===1){const[s,r]=n.entries().next().value;Y(o,s,r);}}},Q=t=>{if(t.length===0)return;const[e,n]=L(t);if(e.delete(n),e.size===0)Q(t.slice(0,-1));else if(e.size===1){const[o,s]=e.entries().next().value;o!==g&&Y(t.slice(0,-1),o,s);}},Y=(t,e,n)=>{if(t.length===0)return;const[o,s]=L(t);o.set(s+e,n),o.delete(s);},L=t=>t[t.length-1],Z=(t,e)=>t._idToShortId.has(e),vt=/[\n\r\p{Z}\p{P}]+/u,D="or",H="and",Ft="and_not",kt=(t,e)=>{t.includes(e)||t.push(e);},tt=(t,e)=>{for(const n of e)t.includes(n)||t.push(n);},et=({score:t},{score:e})=>e-t,nt=()=>new Map,E=(t,e)=>Object.prototype.hasOwnProperty.call(t,e)?t[e]:undefined,ot={[D]:(t,e)=>{for(const n of e.keys()){const o=t.get(n);if(o==null)t.set(n,e.get(n));else {const{score:s,terms:r,match:i}=e.get(n);o.score=o.score+s,o.match=Object.assign(o.match,i),tt(o.terms,r);}}return t},[H]:(t,e)=>{const n=new Map;for(const o of e.keys()){const s=t.get(o);if(s==null)continue;const{score:r,terms:i,match:c}=e.get(o);tt(s.terms,i),n.set(o,{score:s.score+r,terms:s.terms,match:Object.assign(s.match,c)});}return n},[Ft]:(t,e)=>{for(const n of e.keys())t.delete(n);return t}},Ct=(t,e,n,o,s,r)=>{const{k:i,b:c,d:u}=r;return Math.log(1+(n-e+.5)/(e+.5))*(u+t*(i+1)/(t+i*(1-c+c*o/s)))},Ot=t=>(e,n,o)=>({term:e,fuzzy:typeof t.fuzzy=="function"?t.fuzzy(e,n,o):t.fuzzy??false,prefix:typeof t.prefix=="function"?t.prefix(e,n,o):t.prefix===true,termBoost:typeof t.boostTerm=="function"?t.boostTerm(e,n,o):1}),st=(t,e,n,o)=>{for(const s of Object.keys(t._fieldIds))if(t._fieldIds[s]===n){t._options.logger("warn",`SlimSearch: document with ID ${t._documentIds.get(e)} has changed before removal: term "${o}" was not present in field "${s}". Removing a document after it has changed can corrupt the index!`,"version_conflict");return}},it=(t,e,n,o)=>{const s=t._index.fetch(o,nt);let r=s.get(e);if(r==null)r=new Map,r.set(n,1),s.set(e,r);else {const i=r.get(n);r.set(n,(i??0)+1);}},A=(t,e,n,o)=>{if(!t._index.has(o)){st(t,n,e,o);return}const s=t._index.fetch(o,nt),r=s.get(e),i=r?.get(n);!r||typeof i>"u"?st(t,n,e,o):i<=1?r.size<=1?s.delete(e):r.delete(n):r.set(n,i-1),t._index.get(o).size===0&&t._index.delete(o);},Vt=(t,e,n,o,s)=>{let r=t._fieldLength.get(e);r==null&&t._fieldLength.set(e,r=[]),r[n]=s;const i=(t._avgFieldLength[n]||0)*o+s;t._avgFieldLength[n]=i/(o+1);},Tt=(t,e)=>{const n=t._nextId;return t._idToShortId.set(e,n),t._documentIds.set(n,e),t._documentCount+=1,t._nextId+=1,n},Mt=(t,e,n)=>{const{storeFields:o,extractField:s}=t._options;if(o?.length===0)return;let r=t._storedFields.get(e);r===undefined&&t._storedFields.set(e,r={});for(const i of o){const c=s(n,i);c!=null&&(r[i]=c);}},j=(t,e)=>{const{extractField:n,tokenize:o,processTerm:s,fields:r,idField:i}=t._options,c=n(e,i);if(c==null)throw new Error(`SlimSearch: document does not have ID field "${i}"`);if(Z(t,c))throw new Error(`SlimSearch: duplicate ID ${c}`);const u=Tt(t,c);Mt(t,u,e);for(const d of r){const a=n(e,d);if(a==null)continue;const h=o(a.toString(),d),f=t._fieldIds[d],_=new Set(h).size;Vt(t,u,f,t._documentCount-1,_);for(const p of h){const l=s(p,d);if(Array.isArray(l))for(const m of l)it(t,f,u,m);else l&&it(t,f,u,l);}}},q=(t,e)=>{for(const n of e)j(t,n);},Dt={k:1.2,b:.7,d:.5},$={idField:"id",extractField:(t,e)=>t[e],tokenize:t=>t.split(vt),processTerm:t=>t.toLowerCase(),fields:undefined,searchOptions:undefined,storeFields:[],logger:(t,e)=>{console?.[t]?.(e);},autoVacuum:true},rt={combineWith:D,prefix:false,fuzzy:false,maxFuzzy:6,boost:{},weights:{fuzzy:.45,prefix:.375},bm25:Dt},Et={combineWith:H,prefix:(t,e,n)=>e===n.length-1},N={batchSize:1e3,batchWait:10},W={minDirtFactor:.1,minDirtCount:20},P={...N,...W},R=Symbol("*"),jt=(t,e)=>{const n=new Map,o={...t._options.searchOptions,...e};for(const[s,r]of t._documentIds){const i=o.boostDocument?o.boostDocument(r,"",t._storedFields.get(s)):1;n.set(s,{score:i,terms:[],match:{}});}return n},ct=(t,e=D)=>{if(t.length===0)return new Map;const n=e.toLowerCase();if(!(n in ot))throw new Error(`Invalid combination operator: ${e}`);return t.reduce(ot[n])},J=(t,e,n,o,s,r,i,c,u,d=new Map)=>{if(r==null)return d;for(const a of Object.keys(i)){const h=i[a],f=t._fieldIds[a],_=r.get(f);if(_==null)continue;let p=_.size;const l=t._avgFieldLength[f];for(const m of _.keys()){if(!t._documentIds.has(m)){A(t,f,m,n),p-=1;continue}const y=c?c(t._documentIds.get(m),n,t._storedFields.get(m)):1;if(!y)continue;const w=_.get(m),C=t._fieldLength.get(m)[f],O=Ct(w,p,t._documentCount,C,l,u),b=o*s*h*y*O,x=d.get(m);if(x){x.score+=b,kt(x.terms,e);const S=E(x.match,n);S?S.push(a):x.match[n]=[a];}else d.set(m,{score:b,terms:[e],match:{[n]:[a]}});}}return d},qt=(t,e,n)=>{const o={...t._options.searchOptions,...n},s=(o.fields??t._options.fields).reduce((l,m)=>({...l,[m]:E(o.boost,m)||1}),{}),{boostDocument:r,weights:i,maxFuzzy:c,bm25:u}=o,{fuzzy:d,prefix:a}={...rt.weights,...i},h=t._index.get(e.term),f=J(t,e.term,e.term,1,e.termBoost,h,s,r,u);let _,p;if(e.prefix&&(_=t._index.atPrefix(e.term)),e.fuzzy){const l=e.fuzzy===true?.2:e.fuzzy,m=l<1?Math.min(c,Math.round(e.term.length*l)):l;m&&(p=t._index.fuzzyGet(e.term,m));}if(_)for(const[l,m]of _){const y=l.length-e.term.length;if(!y)continue;p?.delete(l);const w=a*l.length/(l.length+.3*y);J(t,e.term,l,w,e.termBoost,m,s,r,u,f);}if(p)for(const l of p.keys()){const[m,y]=p.get(l);if(!y)continue;const w=d*l.length/(l.length+y);J(t,e.term,l,w,e.termBoost,m,s,r,u,f);}return f},ut=(t,e,n={})=>{if(e===R)return jt(t,n);if(typeof e!="string"){const a={...n,...e,queries:undefined},h=e.queries.map(f=>ut(t,f,a));return ct(h,a.combineWith)}const{tokenize:o,processTerm:s,searchOptions:r}=t._options,i={tokenize:o,processTerm:s,...r,...n},{tokenize:c,processTerm:u}=i,d=c(e).flatMap(a=>u(a)).filter(a=>!!a).map(Ot(i)).map(a=>qt(t,a,i));return ct(d,i.combineWith)},dt=(t,e,n={})=>{const{searchOptions:o}=t._options,s={...o,...n},r=ut(t,e,n),i=[];for(const[c,{score:u,terms:d,match:a}]of r){const h=d.length||1,f={id:t._documentIds.get(c),score:u*h,terms:Object.keys(a),queryTerms:d,match:a};Object.assign(f,t._storedFields.get(c)),(s.filter==null||s.filter(f))&&i.push(f);}return e===R&&s.boostDocument==null||i.sort(et),i};class Nt{_options;_index;_documentCount;_documentIds;_idToShortId;_fieldIds;_fieldLength;_avgFieldLength;_nextId;_storedFields;_dirtCount;_currentVacuum;_enqueuedVacuum;_enqueuedVacuumConditions;constructor(e){if(!e?.fields)throw new Error('SlimSearch: option "fields" must be provided');const n=e.autoVacuum==null||e.autoVacuum===true?P:e.autoVacuum;this._options={...$,...e,autoVacuum:n,searchOptions:{...rt,...e.searchOptions},autoSuggestOptions:{...Et,...e.autoSuggestOptions}},this._index=new I,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldIds={},this._fieldLength=new Map,this._avgFieldLength=[],this._nextId=0,this._storedFields=new Map,this._dirtCount=0,this._currentVacuum=null,this._enqueuedVacuum=null,this._enqueuedVacuumConditions=W,this.addFields(this._options.fields);}get isVacuuming(){return this._currentVacuum!=null}get dirtCount(){return this._dirtCount}get dirtFactor(){return this._dirtCount/(1+this._documentCount+this._dirtCount)}get documentCount(){return this._documentCount}get termCount(){return this._index.size}toJSON(){const e=[];for(const[n,o]of this._index){const s={};for(const[r,i]of o)s[r]=Object.fromEntries(i);e.push([n,s]);}return {documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:e,version:2}}addFields(e){for(let n=0;n<e.length;n++)this._fieldIds[e[n]]=n;}}const lt=t=>new Nt(t);
|
|
11334
|
+
const xt="ENTRIES",B="KEYS",G="VALUES",g="";class V{set;_type;_path;constructor(e,n){const o=e._tree,s=Array.from(o.keys());this.set=e,this._type=n,this._path=s.length>0?[{node:o,keys:s}]:[];}next(){const e=this.dive();return this.backtrack(),e}dive(){if(this._path.length===0)return {done:true,value:void 0};const{node:e,keys:n}=z(this._path);if(z(n)===g)return {done:false,value:this.result()};const o=e.get(z(n));return this._path.push({node:o,keys:Array.from(o.keys())}),this.dive()}backtrack(){if(this._path.length===0)return;const e=z(this._path).keys;e.pop(),!(e.length>0)&&(this._path.pop(),this.backtrack());}key(){return this.set._prefix+this._path.map(({keys:e})=>z(e)).filter(e=>e!==g).join("")}value(){return z(this._path).node.get(g)}result(){switch(this._type){case G:return this.value();case B:return this.key();default:return [this.key(),this.value()]}}[Symbol.iterator](){return this}}const z=t=>t[t.length-1],zt=(t,e,n)=>{const o=new Map;if(typeof e!="string")return o;const s=e.length+1,r=s+n,i=new Uint8Array(r*s).fill(n+1);for(let c=0;c<s;++c)i[c]=c;for(let c=1;c<r;++c)i[c*s]=c;return K(t,e,n,o,i,1,s,""),o},K=(t,e,n,o,s,r,i,c)=>{const u=r*i;t:for(const d of t.keys())if(d===g){const a=s[u-1];a<=n&&o.set(c,[t.get(d),a]);}else {let a=r;for(let h=0;h<d.length;++h,++a){const f=d[h],_=i*a,p=_-i;let l=s[_];const m=Math.max(0,a-n-1),y=Math.min(i-1,a+n);for(let w=m;w<y;++w){const C=f!==e[w],O=s[p+w]+ +C,b=s[p+w+1]+1,x=s[_+w]+1,S=s[_+w+1]=Math.min(O,b,x);S<l&&(l=S);}if(l>n)continue t}K(t.get(d),e,n,o,s,a,i,c+d);}};class I{_tree;_prefix;_size=void 0;constructor(e=new Map,n=""){this._tree=e,this._prefix=n;}atPrefix(e){if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");const[n,o]=v(this._tree,e.slice(this._prefix.length));if(n===void 0){const[s,r]=L(o);for(const i of s.keys())if(i!==g&&i.startsWith(r)){const c=new Map;return c.set(i.slice(r.length),s.get(i)),new I(c,e)}}return new I(n,e)}clear(){this._size=void 0,this._tree.clear();}delete(e){return this._size=void 0,St(this._tree,e)}entries(){return new V(this,xt)}forEach(e){for(const[n,o]of this)e(n,o,this);}fuzzyGet(e,n){return zt(this._tree,e,n)}get(e){const n=T(this._tree,e);return n!==void 0?n.get(g):void 0}has(e){return T(this._tree,e)?.has(g)??false}keys(){return new V(this,B)}set(e,n){if(typeof e!="string")throw new Error("key must be a string");return this._size=void 0,M(this._tree,e).set(g,n),this}get size(){if(this._size)return this._size;this._size=0;const e=this.entries();for(;!e.next().done;)this._size+=1;return this._size}update(e,n){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;const o=M(this._tree,e);return o.set(g,n(o.get(g))),this}fetch(e,n){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;const o=M(this._tree,e);let s=o.get(g);return s===void 0&&o.set(g,s=n()),s}values(){return new V(this,G)}[Symbol.iterator](){return this.entries()}static from(e){const n=new I;for(const[o,s]of e)n.set(o,s);return n}static fromObject(e){return I.from(Object.entries(e))}}const v=(t,e,n=[])=>{if(e.length===0||t==null)return [t,n];for(const o of t.keys())if(o!==g&&e.startsWith(o))return n.push([t,o]),v(t.get(o),e.slice(o.length),n);return n.push([t,e]),v(void 0,"",n)},T=(t,e)=>{if(e.length===0||!t)return t;for(const n of t.keys())if(n!==g&&e.startsWith(n))return T(t.get(n),e.slice(n.length))},M=(t,e)=>{const n=e.length;t:for(let o=0;t&&o<n;){for(const r of t.keys())if(r!==g&&e[o]===r[0]){const i=Math.min(n-o,r.length);let c=1;for(;c<i&&e[o+c]===r[c];)++c;const u=t.get(r);if(c===r.length)t=u;else {const d=new Map;d.set(r.slice(c),u),t.set(e.slice(o,o+c),d),t.delete(r),t=d;}o+=c;continue t}const s=new Map;return t.set(e.slice(o),s),s}return t},St=(t,e)=>{const[n,o]=v(t,e);if(n!==void 0){if(n.delete(g),n.size===0)Q(o);else if(n.size===1){const[s,r]=n.entries().next().value;Y(o,s,r);}}},Q=t=>{if(t.length===0)return;const[e,n]=L(t);if(e.delete(n),e.size===0)Q(t.slice(0,-1));else if(e.size===1){const[o,s]=e.entries().next().value;o!==g&&Y(t.slice(0,-1),o,s);}},Y=(t,e,n)=>{if(t.length===0)return;const[o,s]=L(t);o.set(s+e,n),o.delete(s);},L=t=>t[t.length-1],Z=(t,e)=>t._idToShortId.has(e),vt=/[\n\r\p{Z}\p{P}]+/u,D="or",H="and",Ft="and_not",kt=(t,e)=>{t.includes(e)||t.push(e);},tt=(t,e)=>{for(const n of e)t.includes(n)||t.push(n);},et=({score:t},{score:e})=>e-t,nt=()=>new Map,E=(t,e)=>Object.prototype.hasOwnProperty.call(t,e)?t[e]:void 0,ot={[D]:(t,e)=>{for(const n of e.keys()){const o=t.get(n);if(o==null)t.set(n,e.get(n));else {const{score:s,terms:r,match:i}=e.get(n);o.score=o.score+s,o.match=Object.assign(o.match,i),tt(o.terms,r);}}return t},[H]:(t,e)=>{const n=new Map;for(const o of e.keys()){const s=t.get(o);if(s==null)continue;const{score:r,terms:i,match:c}=e.get(o);tt(s.terms,i),n.set(o,{score:s.score+r,terms:s.terms,match:Object.assign(s.match,c)});}return n},[Ft]:(t,e)=>{for(const n of e.keys())t.delete(n);return t}},Ct=(t,e,n,o,s,r)=>{const{k:i,b:c,d:u}=r;return Math.log(1+(n-e+.5)/(e+.5))*(u+t*(i+1)/(t+i*(1-c+c*o/s)))},Ot=t=>(e,n,o)=>({term:e,fuzzy:typeof t.fuzzy=="function"?t.fuzzy(e,n,o):t.fuzzy??false,prefix:typeof t.prefix=="function"?t.prefix(e,n,o):t.prefix===true,termBoost:typeof t.boostTerm=="function"?t.boostTerm(e,n,o):1}),st=(t,e,n,o)=>{for(const s of Object.keys(t._fieldIds))if(t._fieldIds[s]===n){t._options.logger("warn",`SlimSearch: document with ID ${t._documentIds.get(e)} has changed before removal: term "${o}" was not present in field "${s}". Removing a document after it has changed can corrupt the index!`,"version_conflict");return}},it=(t,e,n,o)=>{const s=t._index.fetch(o,nt);let r=s.get(e);if(r==null)r=new Map,r.set(n,1),s.set(e,r);else {const i=r.get(n);r.set(n,(i??0)+1);}},A=(t,e,n,o)=>{if(!t._index.has(o)){st(t,n,e,o);return}const s=t._index.fetch(o,nt),r=s.get(e),i=r?.get(n);!r||typeof i>"u"?st(t,n,e,o):i<=1?r.size<=1?s.delete(e):r.delete(n):r.set(n,i-1),t._index.get(o).size===0&&t._index.delete(o);},Vt=(t,e,n,o,s)=>{let r=t._fieldLength.get(e);r==null&&t._fieldLength.set(e,r=[]),r[n]=s;const i=(t._avgFieldLength[n]||0)*o+s;t._avgFieldLength[n]=i/(o+1);},Tt=(t,e)=>{const n=t._nextId;return t._idToShortId.set(e,n),t._documentIds.set(n,e),t._documentCount+=1,t._nextId+=1,n},Mt=(t,e,n)=>{const{storeFields:o,extractField:s}=t._options;if(o?.length===0)return;let r=t._storedFields.get(e);r===void 0&&t._storedFields.set(e,r={});for(const i of o){const c=s(n,i);c!=null&&(r[i]=c);}},j=(t,e)=>{const{extractField:n,tokenize:o,processTerm:s,fields:r,idField:i}=t._options,c=n(e,i);if(c==null)throw new Error(`SlimSearch: document does not have ID field "${i}"`);if(Z(t,c))throw new Error(`SlimSearch: duplicate ID ${c}`);const u=Tt(t,c);Mt(t,u,e);for(const d of r){const a=n(e,d);if(a==null)continue;const h=o(a.toString(),d),f=t._fieldIds[d],_=new Set(h).size;Vt(t,u,f,t._documentCount-1,_);for(const p of h){const l=s(p,d);if(Array.isArray(l))for(const m of l)it(t,f,u,m);else l&&it(t,f,u,l);}}},q=(t,e)=>{for(const n of e)j(t,n);},Dt={k:1.2,b:.7,d:.5},$={idField:"id",extractField:(t,e)=>t[e],tokenize:t=>t.split(vt),processTerm:t=>t.toLowerCase(),fields:void 0,searchOptions:void 0,storeFields:[],logger:(t,e)=>{console?.[t]?.(e);},autoVacuum:true},rt={combineWith:D,prefix:false,fuzzy:false,maxFuzzy:6,boost:{},weights:{fuzzy:.45,prefix:.375},bm25:Dt},Et={combineWith:H,prefix:(t,e,n)=>e===n.length-1},N={batchSize:1e3,batchWait:10},W={minDirtFactor:.1,minDirtCount:20},P={...N,...W},R=Symbol("*"),jt=(t,e)=>{const n=new Map,o={...t._options.searchOptions,...e};for(const[s,r]of t._documentIds){const i=o.boostDocument?o.boostDocument(r,"",t._storedFields.get(s)):1;n.set(s,{score:i,terms:[],match:{}});}return n},ct=(t,e=D)=>{if(t.length===0)return new Map;const n=e.toLowerCase();if(!(n in ot))throw new Error(`Invalid combination operator: ${e}`);return t.reduce(ot[n])},J=(t,e,n,o,s,r,i,c,u,d=new Map)=>{if(r==null)return d;for(const a of Object.keys(i)){const h=i[a],f=t._fieldIds[a],_=r.get(f);if(_==null)continue;let p=_.size;const l=t._avgFieldLength[f];for(const m of _.keys()){if(!t._documentIds.has(m)){A(t,f,m,n),p-=1;continue}const y=c?c(t._documentIds.get(m),n,t._storedFields.get(m)):1;if(!y)continue;const w=_.get(m),C=t._fieldLength.get(m)[f],O=Ct(w,p,t._documentCount,C,l,u),b=o*s*h*y*O,x=d.get(m);if(x){x.score+=b,kt(x.terms,e);const S=E(x.match,n);S?S.push(a):x.match[n]=[a];}else d.set(m,{score:b,terms:[e],match:{[n]:[a]}});}}return d},qt=(t,e,n)=>{const o={...t._options.searchOptions,...n},s=(o.fields??t._options.fields).reduce((l,m)=>({...l,[m]:E(o.boost,m)||1}),{}),{boostDocument:r,weights:i,maxFuzzy:c,bm25:u}=o,{fuzzy:d,prefix:a}={...rt.weights,...i},h=t._index.get(e.term),f=J(t,e.term,e.term,1,e.termBoost,h,s,r,u);let _,p;if(e.prefix&&(_=t._index.atPrefix(e.term)),e.fuzzy){const l=e.fuzzy===true?.2:e.fuzzy,m=l<1?Math.min(c,Math.round(e.term.length*l)):l;m&&(p=t._index.fuzzyGet(e.term,m));}if(_)for(const[l,m]of _){const y=l.length-e.term.length;if(!y)continue;p?.delete(l);const w=a*l.length/(l.length+.3*y);J(t,e.term,l,w,e.termBoost,m,s,r,u,f);}if(p)for(const l of p.keys()){const[m,y]=p.get(l);if(!y)continue;const w=d*l.length/(l.length+y);J(t,e.term,l,w,e.termBoost,m,s,r,u,f);}return f},ut=(t,e,n={})=>{if(e===R)return jt(t,n);if(typeof e!="string"){const a={...n,...e,queries:void 0},h=e.queries.map(f=>ut(t,f,a));return ct(h,a.combineWith)}const{tokenize:o,processTerm:s,searchOptions:r}=t._options,i={tokenize:o,processTerm:s,...r,...n},{tokenize:c,processTerm:u}=i,d=c(e).flatMap(a=>u(a)).filter(a=>!!a).map(Ot(i)).map(a=>qt(t,a,i));return ct(d,i.combineWith)},dt=(t,e,n={})=>{const{searchOptions:o}=t._options,s={...o,...n},r=ut(t,e,n),i=[];for(const[c,{score:u,terms:d,match:a}]of r){const h=d.length||1,f={id:t._documentIds.get(c),score:u*h,terms:Object.keys(a),queryTerms:d,match:a};Object.assign(f,t._storedFields.get(c)),(s.filter==null||s.filter(f))&&i.push(f);}return e===R&&s.boostDocument==null||i.sort(et),i};class Nt{_options;_index;_documentCount;_documentIds;_idToShortId;_fieldIds;_fieldLength;_avgFieldLength;_nextId;_storedFields;_dirtCount;_currentVacuum;_enqueuedVacuum;_enqueuedVacuumConditions;constructor(e){if(!e?.fields)throw new Error('SlimSearch: option "fields" must be provided');const n=e.autoVacuum==null||e.autoVacuum===true?P:e.autoVacuum;this._options={...$,...e,autoVacuum:n,searchOptions:{...rt,...e.searchOptions},autoSuggestOptions:{...Et,...e.autoSuggestOptions}},this._index=new I,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldIds={},this._fieldLength=new Map,this._avgFieldLength=[],this._nextId=0,this._storedFields=new Map,this._dirtCount=0,this._currentVacuum=null,this._enqueuedVacuum=null,this._enqueuedVacuumConditions=W,this.addFields(this._options.fields);}get isVacuuming(){return this._currentVacuum!=null}get dirtCount(){return this._dirtCount}get dirtFactor(){return this._dirtCount/(1+this._documentCount+this._dirtCount)}get documentCount(){return this._documentCount}get termCount(){return this._index.size}toJSON(){const e=[];for(const[n,o]of this._index){const s={};for(const[r,i]of o)s[r]=Object.fromEntries(i);e.push([n,s]);}return {documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:e,version:2}}addFields(e){for(let n=0;n<e.length;n++)this._fieldIds[e[n]]=n;}}const lt=t=>new Nt(t);
|
|
11188
11335
|
|
|
11189
11336
|
/**
|
|
11190
11337
|
* Generates a list of accent variants for a given term.
|
|
@@ -11226,7 +11373,7 @@ const generateAccentVariants = (term) => {
|
|
|
11226
11373
|
|
|
11227
11374
|
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
11228
11375
|
// versions:
|
|
11229
|
-
// protoc-gen-ts_proto v2.
|
|
11376
|
+
// protoc-gen-ts_proto v2.7.7
|
|
11230
11377
|
// protoc v4.23.4
|
|
11231
11378
|
// source: src/stops/proto/stops.proto
|
|
11232
11379
|
/* eslint-disable */
|
|
@@ -11323,7 +11470,7 @@ const Stop = {
|
|
|
11323
11470
|
},
|
|
11324
11471
|
decode(input, length) {
|
|
11325
11472
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
11326
|
-
|
|
11473
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
11327
11474
|
const message = createBaseStop();
|
|
11328
11475
|
while (reader.pos < end) {
|
|
11329
11476
|
const tag = reader.uint32();
|
|
@@ -11405,7 +11552,7 @@ const Stop = {
|
|
|
11405
11552
|
sourceStopId: isSet$1(object.sourceStopId) ? globalThis.String(object.sourceStopId) : "",
|
|
11406
11553
|
lat: isSet$1(object.lat) ? globalThis.Number(object.lat) : undefined,
|
|
11407
11554
|
lon: isSet$1(object.lon) ? globalThis.Number(object.lon) : undefined,
|
|
11408
|
-
children: globalThis.Array.isArray(object === null || object ===
|
|
11555
|
+
children: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.children) ? object.children.map((e) => globalThis.Number(e)) : [],
|
|
11409
11556
|
parent: isSet$1(object.parent) ? globalThis.Number(object.parent) : undefined,
|
|
11410
11557
|
locationType: isSet$1(object.locationType) ? locationTypeFromJSON(object.locationType) : 0,
|
|
11411
11558
|
platform: isSet$1(object.platform) ? globalThis.String(object.platform) : undefined,
|
|
@@ -11426,7 +11573,7 @@ const Stop = {
|
|
|
11426
11573
|
if (message.lon !== undefined) {
|
|
11427
11574
|
obj.lon = message.lon;
|
|
11428
11575
|
}
|
|
11429
|
-
if ((_a = message.children) === null || _a ===
|
|
11576
|
+
if ((_a = message.children) === null || _a === void 0 ? void 0 : _a.length) {
|
|
11430
11577
|
obj.children = message.children.map((e) => Math.round(e));
|
|
11431
11578
|
}
|
|
11432
11579
|
if (message.parent !== undefined) {
|
|
@@ -11441,19 +11588,19 @@ const Stop = {
|
|
|
11441
11588
|
return obj;
|
|
11442
11589
|
},
|
|
11443
11590
|
create(base) {
|
|
11444
|
-
return Stop.fromPartial(base !== null && base !==
|
|
11591
|
+
return Stop.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
11445
11592
|
},
|
|
11446
11593
|
fromPartial(object) {
|
|
11447
11594
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
11448
11595
|
const message = createBaseStop();
|
|
11449
|
-
message.name = (_a = object.name) !== null && _a !==
|
|
11450
|
-
message.sourceStopId = (_b = object.sourceStopId) !== null && _b !==
|
|
11451
|
-
message.lat = (_c = object.lat) !== null && _c !==
|
|
11452
|
-
message.lon = (_d = object.lon) !== null && _d !==
|
|
11453
|
-
message.children = ((_e = object.children) === null || _e ===
|
|
11454
|
-
message.parent = (_f = object.parent) !== null && _f !==
|
|
11455
|
-
message.locationType = (_g = object.locationType) !== null && _g !==
|
|
11456
|
-
message.platform = (_h = object.platform) !== null && _h !==
|
|
11596
|
+
message.name = (_a = object.name) !== null && _a !== void 0 ? _a : "";
|
|
11597
|
+
message.sourceStopId = (_b = object.sourceStopId) !== null && _b !== void 0 ? _b : "";
|
|
11598
|
+
message.lat = (_c = object.lat) !== null && _c !== void 0 ? _c : undefined;
|
|
11599
|
+
message.lon = (_d = object.lon) !== null && _d !== void 0 ? _d : undefined;
|
|
11600
|
+
message.children = ((_e = object.children) === null || _e === void 0 ? void 0 : _e.map((e) => e)) || [];
|
|
11601
|
+
message.parent = (_f = object.parent) !== null && _f !== void 0 ? _f : undefined;
|
|
11602
|
+
message.locationType = (_g = object.locationType) !== null && _g !== void 0 ? _g : 0;
|
|
11603
|
+
message.platform = (_h = object.platform) !== null && _h !== void 0 ? _h : undefined;
|
|
11457
11604
|
return message;
|
|
11458
11605
|
},
|
|
11459
11606
|
};
|
|
@@ -11472,7 +11619,7 @@ const StopsMap = {
|
|
|
11472
11619
|
},
|
|
11473
11620
|
decode(input, length) {
|
|
11474
11621
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
11475
|
-
|
|
11622
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
11476
11623
|
const message = createBaseStopsMap();
|
|
11477
11624
|
while (reader.pos < end) {
|
|
11478
11625
|
const tag = reader.uint32();
|
|
@@ -11530,13 +11677,13 @@ const StopsMap = {
|
|
|
11530
11677
|
return obj;
|
|
11531
11678
|
},
|
|
11532
11679
|
create(base) {
|
|
11533
|
-
return StopsMap.fromPartial(base !== null && base !==
|
|
11680
|
+
return StopsMap.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
11534
11681
|
},
|
|
11535
11682
|
fromPartial(object) {
|
|
11536
11683
|
var _a, _b;
|
|
11537
11684
|
const message = createBaseStopsMap();
|
|
11538
|
-
message.version = (_a = object.version) !== null && _a !==
|
|
11539
|
-
message.stops = Object.entries((_b = object.stops) !== null && _b !==
|
|
11685
|
+
message.version = (_a = object.version) !== null && _a !== void 0 ? _a : "";
|
|
11686
|
+
message.stops = Object.entries((_b = object.stops) !== null && _b !== void 0 ? _b : {}).reduce((acc, [key, value]) => {
|
|
11540
11687
|
if (value !== undefined) {
|
|
11541
11688
|
acc[globalThis.Number(key)] = Stop.fromPartial(value);
|
|
11542
11689
|
}
|
|
@@ -11560,7 +11707,7 @@ const StopsMap_StopsEntry = {
|
|
|
11560
11707
|
},
|
|
11561
11708
|
decode(input, length) {
|
|
11562
11709
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
11563
|
-
|
|
11710
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
11564
11711
|
const message = createBaseStopsMap_StopsEntry();
|
|
11565
11712
|
while (reader.pos < end) {
|
|
11566
11713
|
const tag = reader.uint32();
|
|
@@ -11604,12 +11751,12 @@ const StopsMap_StopsEntry = {
|
|
|
11604
11751
|
return obj;
|
|
11605
11752
|
},
|
|
11606
11753
|
create(base) {
|
|
11607
|
-
return StopsMap_StopsEntry.fromPartial(base !== null && base !==
|
|
11754
|
+
return StopsMap_StopsEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
11608
11755
|
},
|
|
11609
11756
|
fromPartial(object) {
|
|
11610
11757
|
var _a;
|
|
11611
11758
|
const message = createBaseStopsMap_StopsEntry();
|
|
11612
|
-
message.key = (_a = object.key) !== null && _a !==
|
|
11759
|
+
message.key = (_a = object.key) !== null && _a !== void 0 ? _a : 0;
|
|
11613
11760
|
message.value = (object.value !== undefined && object.value !== null) ? Stop.fromPartial(object.value) : undefined;
|
|
11614
11761
|
return message;
|
|
11615
11762
|
},
|
|
@@ -11720,7 +11867,7 @@ class StopsIndex {
|
|
|
11720
11867
|
});
|
|
11721
11868
|
const stopsSet = new Map();
|
|
11722
11869
|
for (const [id, stop] of stopsMap.entries()) {
|
|
11723
|
-
const effectiveStopId = (_a = stop.parent) !== null && _a !==
|
|
11870
|
+
const effectiveStopId = (_a = stop.parent) !== null && _a !== void 0 ? _a : id;
|
|
11724
11871
|
if (!stopsSet.has(effectiveStopId)) {
|
|
11725
11872
|
stopsSet.set(effectiveStopId, {
|
|
11726
11873
|
id: effectiveStopId,
|
|
@@ -11751,8 +11898,8 @@ class StopsIndex {
|
|
|
11751
11898
|
/**
|
|
11752
11899
|
* Deserializes a binary representation of the stops.
|
|
11753
11900
|
*
|
|
11754
|
-
* @param
|
|
11755
|
-
* @returns
|
|
11901
|
+
* @param data - The binary data to deserialize.
|
|
11902
|
+
* @returns The deserialized StopFinder.
|
|
11756
11903
|
*/
|
|
11757
11904
|
static fromData(data) {
|
|
11758
11905
|
const reader = new BinaryReader(data);
|
|
@@ -11762,7 +11909,7 @@ class StopsIndex {
|
|
|
11762
11909
|
/**
|
|
11763
11910
|
* Serializes the stops into a binary protobuf.
|
|
11764
11911
|
*
|
|
11765
|
-
* @returns
|
|
11912
|
+
* @returns The serialized binary data.
|
|
11766
11913
|
*/
|
|
11767
11914
|
serialize() {
|
|
11768
11915
|
const protoStopsMap = serializeStopsMap(this.stopsMap);
|
|
@@ -11841,7 +11988,7 @@ class StopsIndex {
|
|
|
11841
11988
|
return [];
|
|
11842
11989
|
}
|
|
11843
11990
|
const equivalentStops = stop.parent
|
|
11844
|
-
? ((_b = (_a = this.stopsMap.get(stop.parent)) === null || _a ===
|
|
11991
|
+
? ((_b = (_a = this.stopsMap.get(stop.parent)) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : [])
|
|
11845
11992
|
: stop.children;
|
|
11846
11993
|
return Array.from(new Set([id, ...equivalentStops])).map((stopId) => this.stopsMap.get(stopId));
|
|
11847
11994
|
}
|
|
@@ -11930,7 +12077,7 @@ class Duration {
|
|
|
11930
12077
|
|
|
11931
12078
|
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
11932
12079
|
// versions:
|
|
11933
|
-
// protoc-gen-ts_proto v2.
|
|
12080
|
+
// protoc-gen-ts_proto v2.7.7
|
|
11934
12081
|
// protoc v4.23.4
|
|
11935
12082
|
// source: src/timetable/proto/timetable.proto
|
|
11936
12083
|
/* eslint-disable */
|
|
@@ -12064,7 +12211,7 @@ function createBaseRoute() {
|
|
|
12064
12211
|
serviceRouteId: "",
|
|
12065
12212
|
};
|
|
12066
12213
|
}
|
|
12067
|
-
const Route = {
|
|
12214
|
+
const Route$1 = {
|
|
12068
12215
|
encode(message, writer = new BinaryWriter()) {
|
|
12069
12216
|
if (message.stopTimes.length !== 0) {
|
|
12070
12217
|
writer.uint32(10).bytes(message.stopTimes);
|
|
@@ -12082,7 +12229,7 @@ const Route = {
|
|
|
12082
12229
|
},
|
|
12083
12230
|
decode(input, length) {
|
|
12084
12231
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12085
|
-
|
|
12232
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12086
12233
|
const message = createBaseRoute();
|
|
12087
12234
|
while (reader.pos < end) {
|
|
12088
12235
|
const tag = reader.uint32();
|
|
@@ -12150,15 +12297,15 @@ const Route = {
|
|
|
12150
12297
|
return obj;
|
|
12151
12298
|
},
|
|
12152
12299
|
create(base) {
|
|
12153
|
-
return Route.fromPartial(base !== null && base !==
|
|
12300
|
+
return Route$1.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12154
12301
|
},
|
|
12155
12302
|
fromPartial(object) {
|
|
12156
12303
|
var _a, _b, _c, _d;
|
|
12157
12304
|
const message = createBaseRoute();
|
|
12158
|
-
message.stopTimes = (_a = object.stopTimes) !== null && _a !==
|
|
12159
|
-
message.pickUpDropOffTypes = (_b = object.pickUpDropOffTypes) !== null && _b !==
|
|
12160
|
-
message.stops = (_c = object.stops) !== null && _c !==
|
|
12161
|
-
message.serviceRouteId = (_d = object.serviceRouteId) !== null && _d !==
|
|
12305
|
+
message.stopTimes = (_a = object.stopTimes) !== null && _a !== void 0 ? _a : new Uint8Array(0);
|
|
12306
|
+
message.pickUpDropOffTypes = (_b = object.pickUpDropOffTypes) !== null && _b !== void 0 ? _b : new Uint8Array(0);
|
|
12307
|
+
message.stops = (_c = object.stops) !== null && _c !== void 0 ? _c : new Uint8Array(0);
|
|
12308
|
+
message.serviceRouteId = (_d = object.serviceRouteId) !== null && _d !== void 0 ? _d : "";
|
|
12162
12309
|
return message;
|
|
12163
12310
|
},
|
|
12164
12311
|
};
|
|
@@ -12174,7 +12321,7 @@ const RoutesAdjacency = {
|
|
|
12174
12321
|
},
|
|
12175
12322
|
decode(input, length) {
|
|
12176
12323
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12177
|
-
|
|
12324
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12178
12325
|
const message = createBaseRoutesAdjacency();
|
|
12179
12326
|
while (reader.pos < end) {
|
|
12180
12327
|
const tag = reader.uint32();
|
|
@@ -12201,7 +12348,7 @@ const RoutesAdjacency = {
|
|
|
12201
12348
|
return {
|
|
12202
12349
|
routes: isObject(object.routes)
|
|
12203
12350
|
? Object.entries(object.routes).reduce((acc, [key, value]) => {
|
|
12204
|
-
acc[key] = Route.fromJSON(value);
|
|
12351
|
+
acc[key] = Route$1.fromJSON(value);
|
|
12205
12352
|
return acc;
|
|
12206
12353
|
}, {})
|
|
12207
12354
|
: {},
|
|
@@ -12214,21 +12361,21 @@ const RoutesAdjacency = {
|
|
|
12214
12361
|
if (entries.length > 0) {
|
|
12215
12362
|
obj.routes = {};
|
|
12216
12363
|
entries.forEach(([k, v]) => {
|
|
12217
|
-
obj.routes[k] = Route.toJSON(v);
|
|
12364
|
+
obj.routes[k] = Route$1.toJSON(v);
|
|
12218
12365
|
});
|
|
12219
12366
|
}
|
|
12220
12367
|
}
|
|
12221
12368
|
return obj;
|
|
12222
12369
|
},
|
|
12223
12370
|
create(base) {
|
|
12224
|
-
return RoutesAdjacency.fromPartial(base !== null && base !==
|
|
12371
|
+
return RoutesAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12225
12372
|
},
|
|
12226
12373
|
fromPartial(object) {
|
|
12227
12374
|
var _a;
|
|
12228
12375
|
const message = createBaseRoutesAdjacency();
|
|
12229
|
-
message.routes = Object.entries((_a = object.routes) !== null && _a !==
|
|
12376
|
+
message.routes = Object.entries((_a = object.routes) !== null && _a !== void 0 ? _a : {}).reduce((acc, [key, value]) => {
|
|
12230
12377
|
if (value !== undefined) {
|
|
12231
|
-
acc[key] = Route.fromPartial(value);
|
|
12378
|
+
acc[key] = Route$1.fromPartial(value);
|
|
12232
12379
|
}
|
|
12233
12380
|
return acc;
|
|
12234
12381
|
}, {});
|
|
@@ -12244,13 +12391,13 @@ const RoutesAdjacency_RoutesEntry = {
|
|
|
12244
12391
|
writer.uint32(10).string(message.key);
|
|
12245
12392
|
}
|
|
12246
12393
|
if (message.value !== undefined) {
|
|
12247
|
-
Route.encode(message.value, writer.uint32(18).fork()).join();
|
|
12394
|
+
Route$1.encode(message.value, writer.uint32(18).fork()).join();
|
|
12248
12395
|
}
|
|
12249
12396
|
return writer;
|
|
12250
12397
|
},
|
|
12251
12398
|
decode(input, length) {
|
|
12252
12399
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12253
|
-
|
|
12400
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12254
12401
|
const message = createBaseRoutesAdjacency_RoutesEntry();
|
|
12255
12402
|
while (reader.pos < end) {
|
|
12256
12403
|
const tag = reader.uint32();
|
|
@@ -12266,7 +12413,7 @@ const RoutesAdjacency_RoutesEntry = {
|
|
|
12266
12413
|
if (tag !== 18) {
|
|
12267
12414
|
break;
|
|
12268
12415
|
}
|
|
12269
|
-
message.value = Route.decode(reader, reader.uint32());
|
|
12416
|
+
message.value = Route$1.decode(reader, reader.uint32());
|
|
12270
12417
|
continue;
|
|
12271
12418
|
}
|
|
12272
12419
|
}
|
|
@@ -12280,7 +12427,7 @@ const RoutesAdjacency_RoutesEntry = {
|
|
|
12280
12427
|
fromJSON(object) {
|
|
12281
12428
|
return {
|
|
12282
12429
|
key: isSet(object.key) ? globalThis.String(object.key) : "",
|
|
12283
|
-
value: isSet(object.value) ? Route.fromJSON(object.value) : undefined,
|
|
12430
|
+
value: isSet(object.value) ? Route$1.fromJSON(object.value) : undefined,
|
|
12284
12431
|
};
|
|
12285
12432
|
},
|
|
12286
12433
|
toJSON(message) {
|
|
@@ -12289,18 +12436,18 @@ const RoutesAdjacency_RoutesEntry = {
|
|
|
12289
12436
|
obj.key = message.key;
|
|
12290
12437
|
}
|
|
12291
12438
|
if (message.value !== undefined) {
|
|
12292
|
-
obj.value = Route.toJSON(message.value);
|
|
12439
|
+
obj.value = Route$1.toJSON(message.value);
|
|
12293
12440
|
}
|
|
12294
12441
|
return obj;
|
|
12295
12442
|
},
|
|
12296
12443
|
create(base) {
|
|
12297
|
-
return RoutesAdjacency_RoutesEntry.fromPartial(base !== null && base !==
|
|
12444
|
+
return RoutesAdjacency_RoutesEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12298
12445
|
},
|
|
12299
12446
|
fromPartial(object) {
|
|
12300
12447
|
var _a;
|
|
12301
12448
|
const message = createBaseRoutesAdjacency_RoutesEntry();
|
|
12302
|
-
message.key = (_a = object.key) !== null && _a !==
|
|
12303
|
-
message.value = (object.value !== undefined && object.value !== null) ? Route.fromPartial(object.value) : undefined;
|
|
12449
|
+
message.key = (_a = object.key) !== null && _a !== void 0 ? _a : "";
|
|
12450
|
+
message.value = (object.value !== undefined && object.value !== null) ? Route$1.fromPartial(object.value) : undefined;
|
|
12304
12451
|
return message;
|
|
12305
12452
|
},
|
|
12306
12453
|
};
|
|
@@ -12322,7 +12469,7 @@ const Transfer = {
|
|
|
12322
12469
|
},
|
|
12323
12470
|
decode(input, length) {
|
|
12324
12471
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12325
|
-
|
|
12472
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12326
12473
|
const message = createBaseTransfer();
|
|
12327
12474
|
while (reader.pos < end) {
|
|
12328
12475
|
const tag = reader.uint32();
|
|
@@ -12377,14 +12524,14 @@ const Transfer = {
|
|
|
12377
12524
|
return obj;
|
|
12378
12525
|
},
|
|
12379
12526
|
create(base) {
|
|
12380
|
-
return Transfer.fromPartial(base !== null && base !==
|
|
12527
|
+
return Transfer.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12381
12528
|
},
|
|
12382
12529
|
fromPartial(object) {
|
|
12383
12530
|
var _a, _b, _c;
|
|
12384
12531
|
const message = createBaseTransfer();
|
|
12385
|
-
message.destination = (_a = object.destination) !== null && _a !==
|
|
12386
|
-
message.type = (_b = object.type) !== null && _b !==
|
|
12387
|
-
message.minTransferTime = (_c = object.minTransferTime) !== null && _c !==
|
|
12532
|
+
message.destination = (_a = object.destination) !== null && _a !== void 0 ? _a : 0;
|
|
12533
|
+
message.type = (_b = object.type) !== null && _b !== void 0 ? _b : 0;
|
|
12534
|
+
message.minTransferTime = (_c = object.minTransferTime) !== null && _c !== void 0 ? _c : undefined;
|
|
12388
12535
|
return message;
|
|
12389
12536
|
},
|
|
12390
12537
|
};
|
|
@@ -12400,7 +12547,7 @@ const StopsAdjacency = {
|
|
|
12400
12547
|
},
|
|
12401
12548
|
decode(input, length) {
|
|
12402
12549
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12403
|
-
|
|
12550
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12404
12551
|
const message = createBaseStopsAdjacency();
|
|
12405
12552
|
while (reader.pos < end) {
|
|
12406
12553
|
const tag = reader.uint32();
|
|
@@ -12447,12 +12594,12 @@ const StopsAdjacency = {
|
|
|
12447
12594
|
return obj;
|
|
12448
12595
|
},
|
|
12449
12596
|
create(base) {
|
|
12450
|
-
return StopsAdjacency.fromPartial(base !== null && base !==
|
|
12597
|
+
return StopsAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12451
12598
|
},
|
|
12452
12599
|
fromPartial(object) {
|
|
12453
12600
|
var _a;
|
|
12454
12601
|
const message = createBaseStopsAdjacency();
|
|
12455
|
-
message.stops = Object.entries((_a = object.stops) !== null && _a !==
|
|
12602
|
+
message.stops = Object.entries((_a = object.stops) !== null && _a !== void 0 ? _a : {}).reduce((acc, [key, value]) => {
|
|
12456
12603
|
if (value !== undefined) {
|
|
12457
12604
|
acc[key] = StopsAdjacency_StopAdjacency.fromPartial(value);
|
|
12458
12605
|
}
|
|
@@ -12476,7 +12623,7 @@ const StopsAdjacency_StopAdjacency = {
|
|
|
12476
12623
|
},
|
|
12477
12624
|
decode(input, length) {
|
|
12478
12625
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12479
|
-
|
|
12626
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12480
12627
|
const message = createBaseStopsAdjacency_StopAdjacency();
|
|
12481
12628
|
while (reader.pos < end) {
|
|
12482
12629
|
const tag = reader.uint32();
|
|
@@ -12505,31 +12652,31 @@ const StopsAdjacency_StopAdjacency = {
|
|
|
12505
12652
|
},
|
|
12506
12653
|
fromJSON(object) {
|
|
12507
12654
|
return {
|
|
12508
|
-
transfers: globalThis.Array.isArray(object === null || object ===
|
|
12655
|
+
transfers: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.transfers)
|
|
12509
12656
|
? object.transfers.map((e) => Transfer.fromJSON(e))
|
|
12510
12657
|
: [],
|
|
12511
|
-
routes: globalThis.Array.isArray(object === null || object ===
|
|
12658
|
+
routes: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.routes) ? object.routes.map((e) => globalThis.String(e)) : [],
|
|
12512
12659
|
};
|
|
12513
12660
|
},
|
|
12514
12661
|
toJSON(message) {
|
|
12515
12662
|
var _a, _b;
|
|
12516
12663
|
const obj = {};
|
|
12517
|
-
if ((_a = message.transfers) === null || _a ===
|
|
12664
|
+
if ((_a = message.transfers) === null || _a === void 0 ? void 0 : _a.length) {
|
|
12518
12665
|
obj.transfers = message.transfers.map((e) => Transfer.toJSON(e));
|
|
12519
12666
|
}
|
|
12520
|
-
if ((_b = message.routes) === null || _b ===
|
|
12667
|
+
if ((_b = message.routes) === null || _b === void 0 ? void 0 : _b.length) {
|
|
12521
12668
|
obj.routes = message.routes;
|
|
12522
12669
|
}
|
|
12523
12670
|
return obj;
|
|
12524
12671
|
},
|
|
12525
12672
|
create(base) {
|
|
12526
|
-
return StopsAdjacency_StopAdjacency.fromPartial(base !== null && base !==
|
|
12673
|
+
return StopsAdjacency_StopAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12527
12674
|
},
|
|
12528
12675
|
fromPartial(object) {
|
|
12529
12676
|
var _a, _b;
|
|
12530
12677
|
const message = createBaseStopsAdjacency_StopAdjacency();
|
|
12531
|
-
message.transfers = ((_a = object.transfers) === null || _a ===
|
|
12532
|
-
message.routes = ((_b = object.routes) === null || _b ===
|
|
12678
|
+
message.transfers = ((_a = object.transfers) === null || _a === void 0 ? void 0 : _a.map((e) => Transfer.fromPartial(e))) || [];
|
|
12679
|
+
message.routes = ((_b = object.routes) === null || _b === void 0 ? void 0 : _b.map((e) => e)) || [];
|
|
12533
12680
|
return message;
|
|
12534
12681
|
},
|
|
12535
12682
|
};
|
|
@@ -12548,7 +12695,7 @@ const StopsAdjacency_StopsEntry = {
|
|
|
12548
12695
|
},
|
|
12549
12696
|
decode(input, length) {
|
|
12550
12697
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12551
|
-
|
|
12698
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12552
12699
|
const message = createBaseStopsAdjacency_StopsEntry();
|
|
12553
12700
|
while (reader.pos < end) {
|
|
12554
12701
|
const tag = reader.uint32();
|
|
@@ -12592,12 +12739,12 @@ const StopsAdjacency_StopsEntry = {
|
|
|
12592
12739
|
return obj;
|
|
12593
12740
|
},
|
|
12594
12741
|
create(base) {
|
|
12595
|
-
return StopsAdjacency_StopsEntry.fromPartial(base !== null && base !==
|
|
12742
|
+
return StopsAdjacency_StopsEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12596
12743
|
},
|
|
12597
12744
|
fromPartial(object) {
|
|
12598
12745
|
var _a;
|
|
12599
12746
|
const message = createBaseStopsAdjacency_StopsEntry();
|
|
12600
|
-
message.key = (_a = object.key) !== null && _a !==
|
|
12747
|
+
message.key = (_a = object.key) !== null && _a !== void 0 ? _a : "";
|
|
12601
12748
|
message.value = (object.value !== undefined && object.value !== null)
|
|
12602
12749
|
? StopsAdjacency_StopAdjacency.fromPartial(object.value)
|
|
12603
12750
|
: undefined;
|
|
@@ -12619,7 +12766,7 @@ const ServiceRoute = {
|
|
|
12619
12766
|
},
|
|
12620
12767
|
decode(input, length) {
|
|
12621
12768
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12622
|
-
|
|
12769
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12623
12770
|
const message = createBaseServiceRoute();
|
|
12624
12771
|
while (reader.pos < end) {
|
|
12625
12772
|
const tag = reader.uint32();
|
|
@@ -12663,13 +12810,13 @@ const ServiceRoute = {
|
|
|
12663
12810
|
return obj;
|
|
12664
12811
|
},
|
|
12665
12812
|
create(base) {
|
|
12666
|
-
return ServiceRoute.fromPartial(base !== null && base !==
|
|
12813
|
+
return ServiceRoute.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12667
12814
|
},
|
|
12668
12815
|
fromPartial(object) {
|
|
12669
12816
|
var _a, _b;
|
|
12670
12817
|
const message = createBaseServiceRoute();
|
|
12671
|
-
message.type = (_a = object.type) !== null && _a !==
|
|
12672
|
-
message.name = (_b = object.name) !== null && _b !==
|
|
12818
|
+
message.type = (_a = object.type) !== null && _a !== void 0 ? _a : 0;
|
|
12819
|
+
message.name = (_b = object.name) !== null && _b !== void 0 ? _b : "";
|
|
12673
12820
|
return message;
|
|
12674
12821
|
},
|
|
12675
12822
|
};
|
|
@@ -12685,7 +12832,7 @@ const ServiceRoutesMap = {
|
|
|
12685
12832
|
},
|
|
12686
12833
|
decode(input, length) {
|
|
12687
12834
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12688
|
-
|
|
12835
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12689
12836
|
const message = createBaseServiceRoutesMap();
|
|
12690
12837
|
while (reader.pos < end) {
|
|
12691
12838
|
const tag = reader.uint32();
|
|
@@ -12732,12 +12879,12 @@ const ServiceRoutesMap = {
|
|
|
12732
12879
|
return obj;
|
|
12733
12880
|
},
|
|
12734
12881
|
create(base) {
|
|
12735
|
-
return ServiceRoutesMap.fromPartial(base !== null && base !==
|
|
12882
|
+
return ServiceRoutesMap.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12736
12883
|
},
|
|
12737
12884
|
fromPartial(object) {
|
|
12738
12885
|
var _a;
|
|
12739
12886
|
const message = createBaseServiceRoutesMap();
|
|
12740
|
-
message.routes = Object.entries((_a = object.routes) !== null && _a !==
|
|
12887
|
+
message.routes = Object.entries((_a = object.routes) !== null && _a !== void 0 ? _a : {}).reduce((acc, [key, value]) => {
|
|
12741
12888
|
if (value !== undefined) {
|
|
12742
12889
|
acc[key] = ServiceRoute.fromPartial(value);
|
|
12743
12890
|
}
|
|
@@ -12761,7 +12908,7 @@ const ServiceRoutesMap_RoutesEntry = {
|
|
|
12761
12908
|
},
|
|
12762
12909
|
decode(input, length) {
|
|
12763
12910
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12764
|
-
|
|
12911
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12765
12912
|
const message = createBaseServiceRoutesMap_RoutesEntry();
|
|
12766
12913
|
while (reader.pos < end) {
|
|
12767
12914
|
const tag = reader.uint32();
|
|
@@ -12805,12 +12952,12 @@ const ServiceRoutesMap_RoutesEntry = {
|
|
|
12805
12952
|
return obj;
|
|
12806
12953
|
},
|
|
12807
12954
|
create(base) {
|
|
12808
|
-
return ServiceRoutesMap_RoutesEntry.fromPartial(base !== null && base !==
|
|
12955
|
+
return ServiceRoutesMap_RoutesEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12809
12956
|
},
|
|
12810
12957
|
fromPartial(object) {
|
|
12811
12958
|
var _a;
|
|
12812
12959
|
const message = createBaseServiceRoutesMap_RoutesEntry();
|
|
12813
|
-
message.key = (_a = object.key) !== null && _a !==
|
|
12960
|
+
message.key = (_a = object.key) !== null && _a !== void 0 ? _a : "";
|
|
12814
12961
|
message.value = (object.value !== undefined && object.value !== null)
|
|
12815
12962
|
? ServiceRoute.fromPartial(object.value)
|
|
12816
12963
|
: undefined;
|
|
@@ -12838,7 +12985,7 @@ const Timetable$1 = {
|
|
|
12838
12985
|
},
|
|
12839
12986
|
decode(input, length) {
|
|
12840
12987
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12841
|
-
|
|
12988
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12842
12989
|
const message = createBaseTimetable();
|
|
12843
12990
|
while (reader.pos < end) {
|
|
12844
12991
|
const tag = reader.uint32();
|
|
@@ -12904,12 +13051,12 @@ const Timetable$1 = {
|
|
|
12904
13051
|
return obj;
|
|
12905
13052
|
},
|
|
12906
13053
|
create(base) {
|
|
12907
|
-
return Timetable$1.fromPartial(base !== null && base !==
|
|
13054
|
+
return Timetable$1.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12908
13055
|
},
|
|
12909
13056
|
fromPartial(object) {
|
|
12910
13057
|
var _a;
|
|
12911
13058
|
const message = createBaseTimetable();
|
|
12912
|
-
message.version = (_a = object.version) !== null && _a !==
|
|
13059
|
+
message.version = (_a = object.version) !== null && _a !== void 0 ? _a : "";
|
|
12913
13060
|
message.stopsAdjacency = (object.stopsAdjacency !== undefined && object.stopsAdjacency !== null)
|
|
12914
13061
|
? StopsAdjacency.fromPartial(object.stopsAdjacency)
|
|
12915
13062
|
: undefined;
|
|
@@ -12954,119 +13101,555 @@ function isSet(value) {
|
|
|
12954
13101
|
return value !== null && value !== undefined;
|
|
12955
13102
|
}
|
|
12956
13103
|
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
|
|
12962
|
-
|
|
12963
|
-
|
|
12964
|
-
|
|
12965
|
-
|
|
12966
|
-
|
|
13104
|
+
/**
|
|
13105
|
+
* A class representing a time as minutes since midnight.
|
|
13106
|
+
*/
|
|
13107
|
+
class Time {
|
|
13108
|
+
/**
|
|
13109
|
+
* Gets the infinity time as a Time instance.
|
|
13110
|
+
* This represents a time that is conceptually beyond any real possible time.
|
|
13111
|
+
*
|
|
13112
|
+
* @returns A Time instance representing an "infinity" time.
|
|
13113
|
+
*/
|
|
13114
|
+
static infinity() {
|
|
13115
|
+
return new Time(Number.MAX_SAFE_INTEGER);
|
|
12967
13116
|
}
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
12971
|
-
|
|
12972
|
-
|
|
12973
|
-
|
|
13117
|
+
/**
|
|
13118
|
+
* Gets the midnight time as a Time instance.
|
|
13119
|
+
*
|
|
13120
|
+
* @returns A Time instance representing midnight.
|
|
13121
|
+
*/
|
|
13122
|
+
static origin() {
|
|
13123
|
+
return new Time(0);
|
|
12974
13124
|
}
|
|
12975
|
-
|
|
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');
|
|
13125
|
+
constructor(minutes) {
|
|
13126
|
+
this.minutesSinceMidnight = minutes;
|
|
12980
13127
|
}
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
|
|
13128
|
+
/**
|
|
13129
|
+
* Creates a Time instance from the number of minutes since midnight.
|
|
13130
|
+
*
|
|
13131
|
+
* @param minutes - The number of minutes since midnight.
|
|
13132
|
+
* @returns A Time instance representing the specified time.
|
|
13133
|
+
*/
|
|
13134
|
+
static fromMinutes(minutes) {
|
|
13135
|
+
return new Time(minutes);
|
|
12984
13136
|
}
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
13137
|
+
/**
|
|
13138
|
+
* Creates a Time instance from hours, minutes, and seconds.
|
|
13139
|
+
* Rounds to the closest minute as times are represented in minutes from midnight.
|
|
13140
|
+
*
|
|
13141
|
+
* @param hours - The hours component of the time.
|
|
13142
|
+
* @param minutes - The minutes component of the time.
|
|
13143
|
+
* @param seconds - The seconds component of the time.
|
|
13144
|
+
* @returns A Time instance representing the specified time.
|
|
13145
|
+
*/
|
|
13146
|
+
static fromHMS(hours, minutes, seconds) {
|
|
13147
|
+
if (hours < 0 ||
|
|
13148
|
+
minutes < 0 ||
|
|
13149
|
+
seconds < 0 ||
|
|
13150
|
+
minutes >= 60 ||
|
|
13151
|
+
seconds >= 60) {
|
|
13152
|
+
throw new Error('Invalid time. Ensure hours, minutes, and seconds are valid values.');
|
|
13153
|
+
}
|
|
13154
|
+
const totalSeconds = seconds + 60 * minutes + 3600 * hours;
|
|
13155
|
+
const roundedMinutes = Math.round(totalSeconds / 60);
|
|
13156
|
+
return new Time(roundedMinutes);
|
|
12990
13157
|
}
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
|
|
12995
|
-
|
|
13158
|
+
/**
|
|
13159
|
+
* Creates a Time instance from hours, minutes.
|
|
13160
|
+
*
|
|
13161
|
+
* @param hours - The hours component of the time.
|
|
13162
|
+
* @param minutes - The minutes component of the time.
|
|
13163
|
+
* @returns A Time instance representing the specified time.
|
|
13164
|
+
*/
|
|
13165
|
+
static fromHM(hours, minutes) {
|
|
13166
|
+
if (hours < 0 || minutes < 0 || minutes >= 60) {
|
|
13167
|
+
throw new Error('Invalid time. Ensure hours and minutes are valid values.');
|
|
13168
|
+
}
|
|
13169
|
+
return new Time(minutes + hours * 60);
|
|
12996
13170
|
}
|
|
12997
|
-
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13171
|
+
/**
|
|
13172
|
+
* Parses a JavaScript Date object and creates a Time instance.
|
|
13173
|
+
*
|
|
13174
|
+
* @param date - A JavaScript Date object representing the time.
|
|
13175
|
+
* @returns A Time instance representing the parsed time.
|
|
13176
|
+
*/
|
|
13177
|
+
static fromDate(date) {
|
|
13178
|
+
const hours = date.getHours();
|
|
13179
|
+
const minutes = date.getMinutes();
|
|
13180
|
+
const seconds = date.getSeconds();
|
|
13181
|
+
return Time.fromHMS(hours, minutes, seconds);
|
|
13003
13182
|
}
|
|
13004
|
-
|
|
13005
|
-
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13183
|
+
/**
|
|
13184
|
+
* Parses a time string in the format "HH:MM:SS" or "HH:MM" and creates a Time instance.
|
|
13185
|
+
*
|
|
13186
|
+
* @param timeStr - A string representing the time in "HH:MM:SS" or "HH:MM" format.
|
|
13187
|
+
* @returns A Time instance representing the parsed time.
|
|
13188
|
+
*/
|
|
13189
|
+
static fromString(timeStr) {
|
|
13190
|
+
const [hoursStr, minutesStr, secondsStr] = timeStr.split(':');
|
|
13191
|
+
if (hoursStr === undefined ||
|
|
13192
|
+
minutesStr === undefined ||
|
|
13193
|
+
hoursStr.trim() === '' ||
|
|
13194
|
+
minutesStr.trim() === '' ||
|
|
13195
|
+
isNaN(Number(hoursStr)) ||
|
|
13196
|
+
isNaN(Number(minutesStr)) ||
|
|
13197
|
+
(secondsStr !== undefined &&
|
|
13198
|
+
(secondsStr.trim() === '' || isNaN(Number(secondsStr))))) {
|
|
13199
|
+
throw new Error('Input string must be in the format "HH:MM:SS" or "HH:MM".');
|
|
13200
|
+
}
|
|
13201
|
+
const hours = parseInt(hoursStr, 10);
|
|
13202
|
+
const minutes = parseInt(minutesStr, 10);
|
|
13203
|
+
const seconds = secondsStr !== undefined ? parseInt(secondsStr, 10) : 0;
|
|
13204
|
+
return Time.fromHMS(hours, minutes, seconds);
|
|
13009
13205
|
}
|
|
13010
|
-
|
|
13011
|
-
|
|
13012
|
-
|
|
13206
|
+
/**
|
|
13207
|
+
* Converts the Time instance to a string in "HH:MM:SS" format.
|
|
13208
|
+
*
|
|
13209
|
+
* @returns A string representing the time.
|
|
13210
|
+
*/
|
|
13211
|
+
toString() {
|
|
13212
|
+
let hours = Math.floor(this.minutesSinceMidnight / 60);
|
|
13213
|
+
const minutes = Math.floor(this.minutesSinceMidnight % 60);
|
|
13214
|
+
if (hours >= 24) {
|
|
13215
|
+
hours = hours % 24;
|
|
13216
|
+
}
|
|
13217
|
+
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
13013
13218
|
}
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13219
|
+
/**
|
|
13220
|
+
* Converts the Time instance to the total number of minutes since midnight, rounded to the closest minute.
|
|
13221
|
+
*
|
|
13222
|
+
* @returns The time in minutes since midnight.
|
|
13223
|
+
*/
|
|
13224
|
+
toMinutes() {
|
|
13225
|
+
return this.minutesSinceMidnight;
|
|
13019
13226
|
}
|
|
13020
|
-
|
|
13021
|
-
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
const
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13227
|
+
/**
|
|
13228
|
+
* Adds a Duration to the current Time instance and returns a new Time instance.
|
|
13229
|
+
*
|
|
13230
|
+
* @param duration - A Duration instance representing the duration to add.
|
|
13231
|
+
* @returns A new Time instance with the added duration.
|
|
13232
|
+
*/
|
|
13233
|
+
plus(duration) {
|
|
13234
|
+
const totalSeconds = this.minutesSinceMidnight * 60 + duration.toSeconds();
|
|
13235
|
+
return new Time(Math.round(totalSeconds / 60));
|
|
13236
|
+
}
|
|
13237
|
+
/**
|
|
13238
|
+
* Subtracts a Duration from the current Time instance and returns a new Time instance.
|
|
13239
|
+
*
|
|
13240
|
+
* @param duration - A Duration instance representing the duration to subtract.
|
|
13241
|
+
* @returns A new Time instance with the subtracted duration.
|
|
13242
|
+
*/
|
|
13243
|
+
minus(duration) {
|
|
13244
|
+
let totalSeconds = this.minutesSinceMidnight * 60 - duration.toSeconds();
|
|
13245
|
+
if (totalSeconds < 0) {
|
|
13246
|
+
totalSeconds += 24 * 3600; // Adjust for negative time to loop back to previous day
|
|
13247
|
+
}
|
|
13248
|
+
return new Time(Math.round(totalSeconds / 60));
|
|
13249
|
+
}
|
|
13250
|
+
/**
|
|
13251
|
+
* Subtracts another Time instance from the current Time instance and returns the Duration.
|
|
13252
|
+
*
|
|
13253
|
+
* @param otherTime - A Time instance representing the time to subtract.
|
|
13254
|
+
* @returns A Duration instance representing the time difference.
|
|
13255
|
+
*/
|
|
13256
|
+
diff(otherTime) {
|
|
13257
|
+
const totalMinutes = this.minutesSinceMidnight - otherTime.toMinutes();
|
|
13258
|
+
return Duration.fromSeconds(Math.abs(totalMinutes * 60));
|
|
13259
|
+
}
|
|
13260
|
+
/**
|
|
13261
|
+
* Computes the maximum Time instance among the provided Time instances.
|
|
13262
|
+
*
|
|
13263
|
+
* @param times - An array of Time instances to compare.
|
|
13264
|
+
* @returns A Time instance representing the maximum time.
|
|
13265
|
+
*/
|
|
13266
|
+
static max(...times) {
|
|
13267
|
+
if (times.length === 0) {
|
|
13268
|
+
throw new Error('At least one Time instance is required.');
|
|
13269
|
+
}
|
|
13270
|
+
return times.reduce((maxTime, currentTime) => {
|
|
13271
|
+
return currentTime.isAfter(maxTime) ? currentTime : maxTime;
|
|
13272
|
+
});
|
|
13273
|
+
}
|
|
13274
|
+
/**
|
|
13275
|
+
* Computes the minimum Time instance among the provided Time instances.
|
|
13276
|
+
*
|
|
13277
|
+
* @param times - An array of Time instances to compare.
|
|
13278
|
+
* @returns A Time instance representing the minimum time.
|
|
13279
|
+
*/
|
|
13280
|
+
static min(...times) {
|
|
13281
|
+
if (times.length === 0) {
|
|
13282
|
+
throw new Error('At least one Time instance is required.');
|
|
13283
|
+
}
|
|
13284
|
+
return times.reduce((minTime, currentTime) => {
|
|
13285
|
+
return currentTime.isBefore(minTime) ? currentTime : minTime;
|
|
13286
|
+
});
|
|
13287
|
+
}
|
|
13288
|
+
/**
|
|
13289
|
+
* Determines if the current Time instance is after another Time instance.
|
|
13290
|
+
*
|
|
13291
|
+
* @param otherTime - A Time instance to compare against.
|
|
13292
|
+
* @returns True if the current Time instance is after the other Time instance, otherwise false.
|
|
13293
|
+
*/
|
|
13294
|
+
isAfter(otherTime) {
|
|
13295
|
+
return this.minutesSinceMidnight > otherTime.toMinutes();
|
|
13296
|
+
}
|
|
13297
|
+
/**
|
|
13298
|
+
* Determines if the current Time instance is before another Time instance.
|
|
13299
|
+
*
|
|
13300
|
+
* @param otherTime - A Time instance to compare against.
|
|
13301
|
+
* @returns True if the current Time instance is before the other Time instance, otherwise false.
|
|
13302
|
+
*/
|
|
13303
|
+
isBefore(otherTime) {
|
|
13304
|
+
return this.minutesSinceMidnight < otherTime.toMinutes();
|
|
13305
|
+
}
|
|
13306
|
+
/**
|
|
13307
|
+
* Determines if the current Time instance is equal to another Time instance.
|
|
13308
|
+
*
|
|
13309
|
+
* @param otherTime - A Time instance to compare against.
|
|
13310
|
+
* @returns True if the current Time instance is equal to the other Time instance, otherwise false.
|
|
13311
|
+
*/
|
|
13312
|
+
equals(otherTime) {
|
|
13313
|
+
return this.minutesSinceMidnight === otherTime.toMinutes();
|
|
13314
|
+
}
|
|
13315
|
+
}
|
|
13316
|
+
|
|
13317
|
+
const REGULAR = 0;
|
|
13318
|
+
const NOT_AVAILABLE = 1;
|
|
13319
|
+
const MUST_PHONE_AGENCY = 2;
|
|
13320
|
+
const MUST_COORDINATE_WITH_DRIVER = 3;
|
|
13321
|
+
const pickUpDropOffTypeMap = [
|
|
13322
|
+
'REGULAR',
|
|
13323
|
+
'NOT_AVAILABLE',
|
|
13324
|
+
'MUST_PHONE_AGENCY',
|
|
13325
|
+
'MUST_COORDINATE_WITH_DRIVER',
|
|
13326
|
+
];
|
|
13327
|
+
/**
|
|
13328
|
+
* Converts a numerical representation of a pick-up/drop-off type
|
|
13329
|
+
* into its corresponding string representation.
|
|
13330
|
+
*
|
|
13331
|
+
* @param numericalType - The numerical value representing the pick-up/drop-off type.
|
|
13332
|
+
* @returns The corresponding PickUpDropOffType as a string.
|
|
13333
|
+
* @throws An error if the numerical type is invalid.
|
|
13334
|
+
*/
|
|
13335
|
+
const toPickupDropOffType = (numericalType) => {
|
|
13336
|
+
const type = pickUpDropOffTypeMap[numericalType];
|
|
13337
|
+
if (!type) {
|
|
13338
|
+
throw new Error(`Invalid pickup/drop-off type ${numericalType}`);
|
|
13339
|
+
}
|
|
13340
|
+
return type;
|
|
13341
|
+
};
|
|
13342
|
+
/**
|
|
13343
|
+
* A route identifies all trips of a given service route sharing the same list of stops.
|
|
13344
|
+
*/
|
|
13345
|
+
class Route {
|
|
13346
|
+
constructor(stopTimes, pickUpDropOffTypes, stops, serviceRouteId) {
|
|
13347
|
+
this.stopTimes = stopTimes;
|
|
13348
|
+
this.pickUpDropOffTypes = pickUpDropOffTypes;
|
|
13349
|
+
this.stops = stops;
|
|
13350
|
+
this.serviceRouteId = serviceRouteId;
|
|
13351
|
+
this.nbStops = stops.length;
|
|
13352
|
+
this.nbTrips = this.stopTimes.length / (this.stops.length * 2);
|
|
13353
|
+
this.stopIndices = new Map();
|
|
13354
|
+
for (let i = 0; i < stops.length; i++) {
|
|
13355
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13356
|
+
this.stopIndices.set(stops[i], i);
|
|
13357
|
+
}
|
|
13358
|
+
}
|
|
13359
|
+
/**
|
|
13360
|
+
* Serializes the Route into binary arrays.
|
|
13361
|
+
*
|
|
13362
|
+
* @returns The serialized binary data.
|
|
13363
|
+
*/
|
|
13364
|
+
serialize() {
|
|
13365
|
+
return {
|
|
13366
|
+
stopTimes: this.stopTimes,
|
|
13367
|
+
pickUpDropOffTypes: this.pickUpDropOffTypes,
|
|
13368
|
+
stops: this.stops,
|
|
13369
|
+
serviceRouteId: this.serviceRouteId,
|
|
13370
|
+
};
|
|
13371
|
+
}
|
|
13372
|
+
/**
|
|
13373
|
+
* Checks if stop A is before stop B in the route.
|
|
13374
|
+
*
|
|
13375
|
+
* @param stopA - The StopId of the first stop.
|
|
13376
|
+
* @param stopB - The StopId of the second stop.
|
|
13377
|
+
* @returns True if stop A is before stop B, false otherwise.
|
|
13378
|
+
*/
|
|
13379
|
+
isBefore(stopA, stopB) {
|
|
13380
|
+
const stopAIndex = this.stopIndices.get(stopA);
|
|
13381
|
+
if (stopAIndex === undefined) {
|
|
13382
|
+
throw new Error(`Stop index ${stopAIndex} not found in route ${this.serviceRouteId}`);
|
|
13383
|
+
}
|
|
13384
|
+
const stopBIndex = this.stopIndices.get(stopB);
|
|
13385
|
+
if (stopBIndex === undefined) {
|
|
13386
|
+
throw new Error(`Stop index ${stopBIndex} not found in route ${this.serviceRouteId}`);
|
|
13387
|
+
}
|
|
13388
|
+
return stopAIndex < stopBIndex;
|
|
13389
|
+
}
|
|
13390
|
+
/**
|
|
13391
|
+
* Retrieves the number of stops in the route.
|
|
13392
|
+
*
|
|
13393
|
+
* @returns The total number of stops in the route.
|
|
13394
|
+
*/
|
|
13395
|
+
getNbStops() {
|
|
13396
|
+
return this.nbStops;
|
|
13397
|
+
}
|
|
13398
|
+
/**
|
|
13399
|
+
* Finds the ServiceRouteId of the route. It corresponds the identifier
|
|
13400
|
+
* of the service shown to the end user as a route.
|
|
13401
|
+
*
|
|
13402
|
+
* @returns The ServiceRouteId of the route.
|
|
13403
|
+
*/
|
|
13404
|
+
serviceRoute() {
|
|
13405
|
+
return this.serviceRouteId;
|
|
13406
|
+
}
|
|
13407
|
+
/**
|
|
13408
|
+
* Retrieves the arrival time at a specific stop for a given trip.
|
|
13409
|
+
*
|
|
13410
|
+
* @param stopId - The identifier of the stop.
|
|
13411
|
+
* @param tripIndex - The index of the trip.
|
|
13412
|
+
* @returns The arrival time at the specified stop and trip as a Time object.
|
|
13413
|
+
*/
|
|
13414
|
+
arrivalAt(stopId, tripIndex) {
|
|
13415
|
+
const arrivalIndex = (tripIndex * this.stops.length + this.stopIndex(stopId)) * 2;
|
|
13416
|
+
const arrival = this.stopTimes[arrivalIndex];
|
|
13417
|
+
if (arrival === undefined) {
|
|
13418
|
+
throw new Error(`Arrival time not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13419
|
+
}
|
|
13420
|
+
return Time.fromMinutes(arrival);
|
|
13421
|
+
}
|
|
13422
|
+
/**
|
|
13423
|
+
* Retrieves the departure time at a specific stop for a given trip.
|
|
13424
|
+
*
|
|
13425
|
+
* @param stopId - The identifier of the stop.
|
|
13426
|
+
* @param tripIndex - The index of the trip.
|
|
13427
|
+
* @returns The departure time at the specified stop and trip as a Time object.
|
|
13428
|
+
*/
|
|
13429
|
+
departureFrom(stopId, tripIndex) {
|
|
13430
|
+
const departureIndex = (tripIndex * this.stops.length + this.stopIndex(stopId)) * 2 + 1;
|
|
13431
|
+
const departure = this.stopTimes[departureIndex];
|
|
13432
|
+
if (departure === undefined) {
|
|
13433
|
+
throw new Error(`Departure time not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13434
|
+
}
|
|
13435
|
+
return Time.fromMinutes(departure);
|
|
13436
|
+
}
|
|
13437
|
+
/**
|
|
13438
|
+
* Retrieves the pick-up type for a specific stop and trip.
|
|
13439
|
+
*
|
|
13440
|
+
* @param stopId - The identifier of the stop.
|
|
13441
|
+
* @param tripIndex - The index of the trip.
|
|
13442
|
+
* @returns The pick-up type at the specified stop and trip.
|
|
13443
|
+
*/
|
|
13444
|
+
pickUpTypeFrom(stopId, tripIndex) {
|
|
13445
|
+
const pickUpIndex = (tripIndex * this.stops.length + this.stopIndex(stopId)) * 2;
|
|
13446
|
+
const pickUpValue = this.pickUpDropOffTypes[pickUpIndex];
|
|
13447
|
+
if (pickUpValue === undefined) {
|
|
13448
|
+
throw new Error(`Pick up type not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13449
|
+
}
|
|
13450
|
+
return toPickupDropOffType(pickUpValue);
|
|
13451
|
+
}
|
|
13452
|
+
/**
|
|
13453
|
+
* Retrieves the drop-off type for a specific stop and trip.
|
|
13454
|
+
*
|
|
13455
|
+
* @param stopId - The identifier of the stop.
|
|
13456
|
+
* @param tripIndex - The index of the trip.
|
|
13457
|
+
* @returns The drop-off type at the specified stop and trip.
|
|
13458
|
+
*/
|
|
13459
|
+
dropOffTypeAt(stopId, tripIndex) {
|
|
13460
|
+
const dropOffIndex = (tripIndex * this.stops.length + this.stopIndex(stopId)) * 2 + 1;
|
|
13461
|
+
const dropOffValue = this.pickUpDropOffTypes[dropOffIndex];
|
|
13462
|
+
if (dropOffValue === undefined) {
|
|
13463
|
+
throw new Error(`Drop off type not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13464
|
+
}
|
|
13465
|
+
return toPickupDropOffType(dropOffValue);
|
|
13466
|
+
}
|
|
13467
|
+
/**
|
|
13468
|
+
* Iterates over the stops in the route, starting from an optional specified stop.
|
|
13469
|
+
* If no start stop is provided, the iteration begins from the first stop in the route.
|
|
13470
|
+
*
|
|
13471
|
+
* @param [startStopId] - (Optional) The StopId of the stop to start the iteration from.
|
|
13472
|
+
* @returns An IterableIterator of StopIds, starting from the specified stop or the first stop.
|
|
13473
|
+
* @throws An error if the specified start stop is not found in the route.
|
|
13474
|
+
*/
|
|
13475
|
+
stopsIterator(startStopId) {
|
|
13476
|
+
const startIndex = startStopId !== undefined ? this.stopIndices.get(startStopId) : 0;
|
|
13477
|
+
if (startIndex === undefined) {
|
|
13478
|
+
throw new Error(`Start stop ${startStopId} not found in route ${this.serviceRouteId}`);
|
|
13479
|
+
}
|
|
13480
|
+
function* generator(stops, startIndex) {
|
|
13481
|
+
for (let i = startIndex; i < stops.length; i++) {
|
|
13482
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13483
|
+
yield stops[i];
|
|
13484
|
+
}
|
|
13485
|
+
}
|
|
13486
|
+
return generator(this.stops, startIndex);
|
|
13487
|
+
}
|
|
13488
|
+
/**
|
|
13489
|
+
* Finds the earliest trip that can be taken from a specific stop on a given route,
|
|
13490
|
+
* optionally constrained by a latest trip index and a time before which the trip
|
|
13491
|
+
* should not depart.
|
|
13492
|
+
* *
|
|
13493
|
+
* @param stopId - The StopId of the stop where the trip should be found.
|
|
13494
|
+
* @param [after=Time.origin()] - The earliest time after which the trip should depart.
|
|
13495
|
+
* If not provided, searches all available trips.
|
|
13496
|
+
* @param [beforeTrip] - (Optional) The index of the trip before which the search should be constrained.
|
|
13497
|
+
* If not provided, searches all available trips.
|
|
13498
|
+
* @returns The index of the earliest trip meeting the criteria, or undefined if no such trip is found.
|
|
13499
|
+
*/
|
|
13500
|
+
findEarliestTrip(stopId, after = Time.origin(), beforeTrip) {
|
|
13501
|
+
const maxTripIndex = beforeTrip !== undefined
|
|
13502
|
+
? Math.min(beforeTrip - 1, this.nbTrips - 1)
|
|
13503
|
+
: this.nbTrips - 1;
|
|
13504
|
+
if (maxTripIndex < 0) {
|
|
13505
|
+
return undefined;
|
|
13506
|
+
}
|
|
13507
|
+
let earliestTripIndex;
|
|
13508
|
+
let lowTrip = 0;
|
|
13509
|
+
let highTrip = maxTripIndex;
|
|
13510
|
+
while (lowTrip <= highTrip) {
|
|
13511
|
+
const midTrip = Math.floor((lowTrip + highTrip) / 2);
|
|
13512
|
+
const departure = this.departureFrom(stopId, midTrip);
|
|
13513
|
+
const pickUpType = this.pickUpTypeFrom(stopId, midTrip);
|
|
13514
|
+
if ((departure.isAfter(after) || departure.equals(after)) &&
|
|
13515
|
+
pickUpType !== 'NOT_AVAILABLE') {
|
|
13516
|
+
earliestTripIndex = midTrip;
|
|
13517
|
+
highTrip = midTrip - 1;
|
|
13518
|
+
}
|
|
13519
|
+
else {
|
|
13520
|
+
lowTrip = midTrip + 1;
|
|
13521
|
+
}
|
|
13522
|
+
}
|
|
13523
|
+
return earliestTripIndex;
|
|
13524
|
+
}
|
|
13525
|
+
/**
|
|
13526
|
+
* Retrieves the index of a stop within the route.
|
|
13527
|
+
* @param stopId The StopId of the stop to locate in the route.
|
|
13528
|
+
* @returns The index of the stop in the route.
|
|
13529
|
+
*/
|
|
13530
|
+
stopIndex(stopId) {
|
|
13531
|
+
const stopIndex = this.stopIndices.get(stopId);
|
|
13532
|
+
if (stopIndex === undefined) {
|
|
13533
|
+
throw new Error(`Stop index for ${stopId} not found in route ${this.serviceRouteId}`);
|
|
13534
|
+
}
|
|
13535
|
+
return stopIndex;
|
|
13536
|
+
}
|
|
13537
|
+
}
|
|
13538
|
+
|
|
13539
|
+
const isLittleEndian = (() => {
|
|
13540
|
+
const buffer = new ArrayBuffer(4);
|
|
13541
|
+
const view = new DataView(buffer);
|
|
13542
|
+
view.setUint32(0, 0x12345678);
|
|
13543
|
+
return new Uint8Array(buffer)[0] === 0x78;
|
|
13544
|
+
})();
|
|
13545
|
+
const STANDARD_ENDIANNESS = true; // true = little-endian
|
|
13546
|
+
const uint32ArrayToBytes = (array) => {
|
|
13547
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
13548
|
+
return new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
13549
|
+
}
|
|
13550
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13551
|
+
const result = new Uint8Array(array.length * 4);
|
|
13552
|
+
const view = new DataView(result.buffer);
|
|
13553
|
+
for (let i = 0; i < array.length; i++) {
|
|
13554
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13555
|
+
view.setUint32(i * 4, array[i], STANDARD_ENDIANNESS);
|
|
13556
|
+
}
|
|
13557
|
+
return result;
|
|
13558
|
+
};
|
|
13559
|
+
const bytesToUint32Array = (bytes) => {
|
|
13560
|
+
if (bytes.byteLength % 4 !== 0) {
|
|
13561
|
+
throw new Error('Byte array length must be a multiple of 4 to convert to Uint32Array');
|
|
13562
|
+
}
|
|
13563
|
+
// If system endianness matches our standard, we can create a view directly
|
|
13564
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
13565
|
+
return new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4);
|
|
13566
|
+
}
|
|
13567
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13568
|
+
const result = new Uint32Array(bytes.byteLength / 4);
|
|
13569
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13570
|
+
for (let i = 0; i < result.length; i++) {
|
|
13571
|
+
result[i] = view.getUint32(i * 4, STANDARD_ENDIANNESS);
|
|
13572
|
+
}
|
|
13573
|
+
return result;
|
|
13574
|
+
};
|
|
13575
|
+
const uint16ArrayToBytes = (array) => {
|
|
13576
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
13577
|
+
return new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
13578
|
+
}
|
|
13579
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13580
|
+
const result = new Uint8Array(array.length * 2);
|
|
13581
|
+
const view = new DataView(result.buffer);
|
|
13582
|
+
for (let i = 0; i < array.length; i++) {
|
|
13583
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13584
|
+
view.setUint16(i * 2, array[i], STANDARD_ENDIANNESS);
|
|
13585
|
+
}
|
|
13586
|
+
return result;
|
|
13587
|
+
};
|
|
13588
|
+
const bytesToUint16Array = (bytes) => {
|
|
13589
|
+
if (bytes.byteLength % 2 !== 0) {
|
|
13590
|
+
throw new Error('Byte array length must be a multiple of 2 to convert to Uint16Array');
|
|
13591
|
+
}
|
|
13592
|
+
// If system endianness matches our standard, we can create a view directly
|
|
13593
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
13594
|
+
return new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2);
|
|
13595
|
+
}
|
|
13596
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13597
|
+
const result = new Uint16Array(bytes.byteLength / 2);
|
|
13598
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13599
|
+
for (let i = 0; i < result.length; i++) {
|
|
13600
|
+
result[i] = view.getUint16(i * 2, STANDARD_ENDIANNESS);
|
|
13601
|
+
}
|
|
13602
|
+
return result;
|
|
13603
|
+
};
|
|
13604
|
+
const serializeStopsAdjacency = (stopsAdjacency) => {
|
|
13605
|
+
const protoStopsAdjacency = {
|
|
13606
|
+
stops: {},
|
|
13607
|
+
};
|
|
13608
|
+
stopsAdjacency.forEach((value, key) => {
|
|
13609
|
+
protoStopsAdjacency.stops[key] = {
|
|
13610
|
+
transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: serializeTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
|
|
13611
|
+
minTransferTime: transfer.minTransferTime.toSeconds(),
|
|
13612
|
+
})))),
|
|
13613
|
+
routes: value.routes,
|
|
13614
|
+
};
|
|
13615
|
+
});
|
|
13616
|
+
return protoStopsAdjacency;
|
|
13617
|
+
};
|
|
13618
|
+
const serializeRoutesAdjacency = (routesAdjacency) => {
|
|
13619
|
+
const protoRoutesAdjacency = {
|
|
13620
|
+
routes: {},
|
|
13621
|
+
};
|
|
13622
|
+
routesAdjacency.forEach((route, key) => {
|
|
13623
|
+
const routeData = route.serialize();
|
|
13624
|
+
protoRoutesAdjacency.routes[key] = {
|
|
13625
|
+
stopTimes: uint16ArrayToBytes(routeData.stopTimes),
|
|
13626
|
+
pickUpDropOffTypes: routeData.pickUpDropOffTypes,
|
|
13627
|
+
stops: uint32ArrayToBytes(routeData.stops),
|
|
13628
|
+
serviceRouteId: routeData.serviceRouteId,
|
|
13629
|
+
};
|
|
13630
|
+
});
|
|
13631
|
+
return protoRoutesAdjacency;
|
|
13632
|
+
};
|
|
13633
|
+
const serializeServiceRoutesMap = (serviceRoutesMap) => {
|
|
13634
|
+
const protoServiceRoutesMap = {
|
|
13635
|
+
routes: {},
|
|
13636
|
+
};
|
|
13637
|
+
serviceRoutesMap.forEach((value, key) => {
|
|
13638
|
+
protoServiceRoutesMap.routes[key] = {
|
|
13639
|
+
type: serializeRouteType(value.type),
|
|
13640
|
+
name: value.name,
|
|
13641
|
+
};
|
|
13642
|
+
});
|
|
13643
|
+
return protoServiceRoutesMap;
|
|
13644
|
+
};
|
|
13645
|
+
const deserializeStopsAdjacency = (protoStopsAdjacency) => {
|
|
13646
|
+
const stopsAdjacency = new Map();
|
|
13647
|
+
Object.entries(protoStopsAdjacency.stops).forEach(([keyStr, value]) => {
|
|
13648
|
+
const key = parseInt(keyStr, 10);
|
|
13649
|
+
stopsAdjacency.set(key, {
|
|
13650
|
+
transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: parseTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
|
|
13651
|
+
minTransferTime: Duration.fromSeconds(transfer.minTransferTime),
|
|
13652
|
+
})))),
|
|
13070
13653
|
routes: value.routes,
|
|
13071
13654
|
});
|
|
13072
13655
|
});
|
|
@@ -13076,18 +13659,7 @@ const deserializeRoutesAdjacency = (protoRoutesAdjacency) => {
|
|
|
13076
13659
|
const routesAdjacency = new Map();
|
|
13077
13660
|
Object.entries(protoRoutesAdjacency.routes).forEach(([key, value]) => {
|
|
13078
13661
|
const stops = bytesToUint32Array(value.stops);
|
|
13079
|
-
|
|
13080
|
-
for (let i = 0; i < stops.length; i++) {
|
|
13081
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13082
|
-
indices.set(stops[i], i);
|
|
13083
|
-
}
|
|
13084
|
-
routesAdjacency.set(key, {
|
|
13085
|
-
stopTimes: bytesToUint16Array(value.stopTimes),
|
|
13086
|
-
pickUpDropOffTypes: value.pickUpDropOffTypes,
|
|
13087
|
-
stops: stops,
|
|
13088
|
-
stopIndices: indices,
|
|
13089
|
-
serviceRouteId: value.serviceRouteId,
|
|
13090
|
-
});
|
|
13662
|
+
routesAdjacency.set(key, new Route(bytesToUint16Array(value.stopTimes), value.pickUpDropOffTypes, stops, value.serviceRouteId));
|
|
13091
13663
|
});
|
|
13092
13664
|
return routesAdjacency;
|
|
13093
13665
|
};
|
|
@@ -13179,195 +13751,7 @@ const serializeRouteType = (type) => {
|
|
|
13179
13751
|
}
|
|
13180
13752
|
};
|
|
13181
13753
|
|
|
13182
|
-
|
|
13183
|
-
* A class representing a time as minutes since midnight.
|
|
13184
|
-
*/
|
|
13185
|
-
class Time {
|
|
13186
|
-
/**
|
|
13187
|
-
* Gets the infinity time as a Time instance.
|
|
13188
|
-
* This represents a time that is conceptually beyond any real possible time.
|
|
13189
|
-
*
|
|
13190
|
-
* @returns A Time instance representing an "infinity" time.
|
|
13191
|
-
*/
|
|
13192
|
-
static infinity() {
|
|
13193
|
-
return new Time(Number.MAX_SAFE_INTEGER);
|
|
13194
|
-
}
|
|
13195
|
-
/**
|
|
13196
|
-
* Gets the midnight time as a Time instance.
|
|
13197
|
-
*
|
|
13198
|
-
* @returns A Time instance representing midnight.
|
|
13199
|
-
*/
|
|
13200
|
-
static origin() {
|
|
13201
|
-
return new Time(0);
|
|
13202
|
-
}
|
|
13203
|
-
constructor(minutes) {
|
|
13204
|
-
this.minutesSinceMidnight = minutes;
|
|
13205
|
-
}
|
|
13206
|
-
/**
|
|
13207
|
-
* Creates a Time instance from the number of minutes since midnight.
|
|
13208
|
-
*
|
|
13209
|
-
* @param minutes - The number of minutes since midnight.
|
|
13210
|
-
* @returns A Time instance representing the specified time.
|
|
13211
|
-
*/
|
|
13212
|
-
static fromMinutes(minutes) {
|
|
13213
|
-
return new Time(minutes);
|
|
13214
|
-
}
|
|
13215
|
-
/**
|
|
13216
|
-
* Creates a Time instance from hours, minutes, and seconds.
|
|
13217
|
-
* Rounds to the closest minute as times are represented in minutes from midnight.
|
|
13218
|
-
*
|
|
13219
|
-
* @param hours - The hours component of the time.
|
|
13220
|
-
* @param minutes - The minutes component of the time.
|
|
13221
|
-
* @param seconds - The seconds component of the time.
|
|
13222
|
-
* @returns A Time instance representing the specified time.
|
|
13223
|
-
*/
|
|
13224
|
-
static fromHMS(hours, minutes, seconds) {
|
|
13225
|
-
if (hours < 0 ||
|
|
13226
|
-
minutes < 0 ||
|
|
13227
|
-
seconds < 0 ||
|
|
13228
|
-
minutes >= 60 ||
|
|
13229
|
-
seconds >= 60) {
|
|
13230
|
-
throw new Error('Invalid time. Ensure hours, minutes, and seconds are valid values.');
|
|
13231
|
-
}
|
|
13232
|
-
const totalSeconds = seconds + 60 * minutes + 3600 * hours;
|
|
13233
|
-
const roundedMinutes = Math.round(totalSeconds / 60);
|
|
13234
|
-
return new Time(roundedMinutes);
|
|
13235
|
-
}
|
|
13236
|
-
/**
|
|
13237
|
-
* Creates a Time instance from hours, minutes.
|
|
13238
|
-
*
|
|
13239
|
-
* @param hours - The hours component of the time.
|
|
13240
|
-
* @param minutes - The minutes component of the time.
|
|
13241
|
-
* @returns A Time instance representing the specified time.
|
|
13242
|
-
*/
|
|
13243
|
-
static fromHM(hours, minutes) {
|
|
13244
|
-
if (hours < 0 || minutes < 0 || minutes >= 60) {
|
|
13245
|
-
throw new Error('Invalid time. Ensure hours and minutes are valid values.');
|
|
13246
|
-
}
|
|
13247
|
-
return new Time(minutes + hours * 60);
|
|
13248
|
-
}
|
|
13249
|
-
/**
|
|
13250
|
-
* Parses a JavaScript Date object and creates a Time instance.
|
|
13251
|
-
*
|
|
13252
|
-
* @param date - A JavaScript Date object representing the time.
|
|
13253
|
-
* @returns A Time instance representing the parsed time.
|
|
13254
|
-
*/
|
|
13255
|
-
static fromDate(date) {
|
|
13256
|
-
const hours = date.getHours();
|
|
13257
|
-
const minutes = date.getMinutes();
|
|
13258
|
-
const seconds = date.getSeconds();
|
|
13259
|
-
return Time.fromHMS(hours, minutes, seconds);
|
|
13260
|
-
}
|
|
13261
|
-
/**
|
|
13262
|
-
* Parses a time string in the format "HH:MM:SS" or "HH:MM" and creates a Time instance.
|
|
13263
|
-
*
|
|
13264
|
-
* @param timeStr - A string representing the time in "HH:MM:SS" or "HH:MM" format.
|
|
13265
|
-
* @returns A Time instance representing the parsed time.
|
|
13266
|
-
*/
|
|
13267
|
-
static fromString(timeStr) {
|
|
13268
|
-
const [hoursStr, minutesStr, secondsStr] = timeStr.split(':');
|
|
13269
|
-
if (hoursStr === undefined ||
|
|
13270
|
-
minutesStr === undefined ||
|
|
13271
|
-
isNaN(Number(hoursStr)) ||
|
|
13272
|
-
isNaN(Number(minutesStr)) ||
|
|
13273
|
-
(secondsStr !== undefined && isNaN(Number(secondsStr)))) {
|
|
13274
|
-
throw new Error('Input string must be in the format "HH:MM:SS" or "HH:MM".');
|
|
13275
|
-
}
|
|
13276
|
-
const hours = parseInt(hoursStr, 10);
|
|
13277
|
-
const minutes = parseInt(minutesStr, 10);
|
|
13278
|
-
const seconds = secondsStr !== undefined ? parseInt(secondsStr, 10) : 0;
|
|
13279
|
-
return Time.fromHMS(hours, minutes, seconds);
|
|
13280
|
-
}
|
|
13281
|
-
/**
|
|
13282
|
-
* Converts the Time instance to a string in "HH:MM:SS" format.
|
|
13283
|
-
*
|
|
13284
|
-
* @returns A string representing the time.
|
|
13285
|
-
*/
|
|
13286
|
-
toString() {
|
|
13287
|
-
const hours = Math.floor(this.minutesSinceMidnight / 60);
|
|
13288
|
-
const minutes = Math.floor(this.minutesSinceMidnight % 60);
|
|
13289
|
-
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
13290
|
-
}
|
|
13291
|
-
/**
|
|
13292
|
-
* Converts the Time instance to the total number of minutes since midnight, rounded to the closest minute.
|
|
13293
|
-
*
|
|
13294
|
-
* @returns The time in minutes since midnight.
|
|
13295
|
-
*/
|
|
13296
|
-
toMinutes() {
|
|
13297
|
-
return this.minutesSinceMidnight;
|
|
13298
|
-
}
|
|
13299
|
-
/**
|
|
13300
|
-
* Adds a Duration to the current Time instance and returns a new Time instance.
|
|
13301
|
-
*
|
|
13302
|
-
* @param duration - A Duration instance representing the duration to add.
|
|
13303
|
-
* @returns A new Time instance with the added duration.
|
|
13304
|
-
*/
|
|
13305
|
-
plus(duration) {
|
|
13306
|
-
const totalSeconds = this.minutesSinceMidnight * 60 + duration.toSeconds();
|
|
13307
|
-
return new Time(Math.round(totalSeconds / 60));
|
|
13308
|
-
}
|
|
13309
|
-
/**
|
|
13310
|
-
* Subtracts a Duration from the current Time instance and returns a new Time instance.
|
|
13311
|
-
*
|
|
13312
|
-
* @param duration - A Duration instance representing the duration to subtract.
|
|
13313
|
-
* @returns A new Time instance with the subtracted duration.
|
|
13314
|
-
*/
|
|
13315
|
-
minus(duration) {
|
|
13316
|
-
let totalSeconds = this.minutesSinceMidnight * 60 - duration.toSeconds();
|
|
13317
|
-
if (totalSeconds < 0) {
|
|
13318
|
-
totalSeconds += 24 * 3600; // Adjust for negative time to loop back to previous day
|
|
13319
|
-
}
|
|
13320
|
-
return new Time(Math.round(totalSeconds / 60));
|
|
13321
|
-
}
|
|
13322
|
-
/**
|
|
13323
|
-
* Subtracts another Time instance from the current Time instance and returns the Duration.
|
|
13324
|
-
*
|
|
13325
|
-
* @param otherTime - A Time instance representing the time to subtract.
|
|
13326
|
-
* @returns A Duration instance representing the time difference.
|
|
13327
|
-
*/
|
|
13328
|
-
diff(otherTime) {
|
|
13329
|
-
const totalMinutes = this.minutesSinceMidnight - otherTime.toMinutes();
|
|
13330
|
-
return Duration.fromSeconds(Math.abs(totalMinutes * 60));
|
|
13331
|
-
}
|
|
13332
|
-
/**
|
|
13333
|
-
* Computes the maximum Time instance among the provided Time instances.
|
|
13334
|
-
*
|
|
13335
|
-
* @param times - An array of Time instances to compare.
|
|
13336
|
-
* @returns A Time instance representing the maximum time.
|
|
13337
|
-
*/
|
|
13338
|
-
static max(...times) {
|
|
13339
|
-
if (times.length === 0) {
|
|
13340
|
-
throw new Error('At least one Time instance is required.');
|
|
13341
|
-
}
|
|
13342
|
-
return times.reduce((maxTime, currentTime) => {
|
|
13343
|
-
return currentTime.toMinutes() > maxTime.toMinutes()
|
|
13344
|
-
? currentTime
|
|
13345
|
-
: maxTime;
|
|
13346
|
-
});
|
|
13347
|
-
}
|
|
13348
|
-
/**
|
|
13349
|
-
* Computes the minimum Time instance among the provided Time instances.
|
|
13350
|
-
*
|
|
13351
|
-
* @param times - An array of Time instances to compare.
|
|
13352
|
-
* @returns A Time instance representing the minimum time.
|
|
13353
|
-
*/
|
|
13354
|
-
static min(...times) {
|
|
13355
|
-
if (times.length === 0) {
|
|
13356
|
-
throw new Error('At least one Time instance is required.');
|
|
13357
|
-
}
|
|
13358
|
-
return times.reduce((minTime, currentTime) => {
|
|
13359
|
-
return currentTime.toMinutes() < minTime.toMinutes()
|
|
13360
|
-
? currentTime
|
|
13361
|
-
: minTime;
|
|
13362
|
-
});
|
|
13363
|
-
}
|
|
13364
|
-
}
|
|
13365
|
-
|
|
13366
|
-
const REGULAR = 0;
|
|
13367
|
-
const NOT_AVAILABLE = 1;
|
|
13368
|
-
const MUST_PHONE_AGENCY = 2;
|
|
13369
|
-
const MUST_COORDINATE_WITH_DRIVER = 3;
|
|
13370
|
-
const ALL_TRANSPORT_MODES = [
|
|
13754
|
+
const ALL_TRANSPORT_MODES = new Set([
|
|
13371
13755
|
'TRAM',
|
|
13372
13756
|
'SUBWAY',
|
|
13373
13757
|
'RAIL',
|
|
@@ -13378,11 +13762,10 @@ const ALL_TRANSPORT_MODES = [
|
|
|
13378
13762
|
'FUNICULAR',
|
|
13379
13763
|
'TROLLEYBUS',
|
|
13380
13764
|
'MONORAIL',
|
|
13381
|
-
];
|
|
13765
|
+
]);
|
|
13382
13766
|
const CURRENT_VERSION = '0.0.3';
|
|
13383
13767
|
/**
|
|
13384
|
-
* The internal transit timetable format
|
|
13385
|
-
* reuses some GTFS concepts for the sake of simplicity for now.
|
|
13768
|
+
* The internal transit timetable format.
|
|
13386
13769
|
*/
|
|
13387
13770
|
class Timetable {
|
|
13388
13771
|
constructor(stopsAdjacency, routesAdjacency, routes) {
|
|
@@ -13391,9 +13774,9 @@ class Timetable {
|
|
|
13391
13774
|
this.routes = routes;
|
|
13392
13775
|
}
|
|
13393
13776
|
/**
|
|
13394
|
-
* Serializes the Timetable into a binary
|
|
13777
|
+
* Serializes the Timetable into a binary array.
|
|
13395
13778
|
*
|
|
13396
|
-
* @returns
|
|
13779
|
+
* @returns The serialized binary data.
|
|
13397
13780
|
*/
|
|
13398
13781
|
serialize() {
|
|
13399
13782
|
const protoTimetable = {
|
|
@@ -13409,8 +13792,8 @@ class Timetable {
|
|
|
13409
13792
|
/**
|
|
13410
13793
|
* Deserializes a binary protobuf into a Timetable object.
|
|
13411
13794
|
*
|
|
13412
|
-
* @param
|
|
13413
|
-
* @returns
|
|
13795
|
+
* @param data - The binary data to deserialize.
|
|
13796
|
+
* @returns The deserialized Timetable object.
|
|
13414
13797
|
*/
|
|
13415
13798
|
static fromData(data) {
|
|
13416
13799
|
const reader = new BinaryReader(data);
|
|
@@ -13426,108 +13809,89 @@ class Timetable {
|
|
|
13426
13809
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13427
13810
|
deserializeServiceRoutesMap(protoTimetable.routes));
|
|
13428
13811
|
}
|
|
13429
|
-
|
|
13430
|
-
|
|
13431
|
-
|
|
13432
|
-
|
|
13433
|
-
|
|
13434
|
-
|
|
13435
|
-
|
|
13812
|
+
/**
|
|
13813
|
+
* Retrieves the route associated with the given route ID.
|
|
13814
|
+
*
|
|
13815
|
+
* @param routeId - The ID of the route to be retrieved.
|
|
13816
|
+
* @returns The route corresponding to the provided ID,
|
|
13817
|
+
* or undefined if no such route exists.
|
|
13818
|
+
*/
|
|
13436
13819
|
getRoute(routeId) {
|
|
13437
13820
|
return this.routesAdjacency.get(routeId);
|
|
13438
13821
|
}
|
|
13822
|
+
/**
|
|
13823
|
+
* Retrieves all transfer options available at the specified stop.
|
|
13824
|
+
*
|
|
13825
|
+
* @param stopId - The ID of the stop to get transfers for.
|
|
13826
|
+
* @returns An array of transfer options available at the stop.
|
|
13827
|
+
*/
|
|
13439
13828
|
getTransfers(stopId) {
|
|
13440
13829
|
var _a, _b;
|
|
13441
|
-
return (_b = (_a = this.stopsAdjacency.get(stopId)) === null || _a ===
|
|
13830
|
+
return (_b = (_a = this.stopsAdjacency.get(stopId)) === null || _a === void 0 ? void 0 : _a.transfers) !== null && _b !== void 0 ? _b : [];
|
|
13831
|
+
}
|
|
13832
|
+
/**
|
|
13833
|
+
* Retrieves the service route associated with the given route.
|
|
13834
|
+
* A service route refers to a collection of trips that are displayed
|
|
13835
|
+
* to riders as a single service.
|
|
13836
|
+
*
|
|
13837
|
+
* @param route - The route for which the service route is to be retrieved.
|
|
13838
|
+
* @returns The service route corresponding to the provided route.
|
|
13839
|
+
*/
|
|
13840
|
+
getServiceRoute(route) {
|
|
13841
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13842
|
+
return this.routes.get(route.serviceRoute());
|
|
13843
|
+
}
|
|
13844
|
+
/**
|
|
13845
|
+
* Finds all routes passing through a stop.
|
|
13846
|
+
*
|
|
13847
|
+
* @param stopId - The ID of the stop to find routes for.
|
|
13848
|
+
* @returns An array of routes passing through the specified stop.
|
|
13849
|
+
*/
|
|
13850
|
+
routesPassingThrough(stopId) {
|
|
13851
|
+
const stopData = this.stopsAdjacency.get(stopId);
|
|
13852
|
+
if (!stopData) {
|
|
13853
|
+
return [];
|
|
13854
|
+
}
|
|
13855
|
+
const routes = [];
|
|
13856
|
+
for (const routeId of stopData.routes) {
|
|
13857
|
+
const route = this.routesAdjacency.get(routeId);
|
|
13858
|
+
if (route) {
|
|
13859
|
+
routes.push(route);
|
|
13860
|
+
}
|
|
13861
|
+
}
|
|
13862
|
+
return routes;
|
|
13442
13863
|
}
|
|
13443
13864
|
/**
|
|
13444
13865
|
* Finds routes that are reachable from a set of stop IDs.
|
|
13445
13866
|
* Also identifies the first stop available to hop on each route among
|
|
13446
13867
|
* the input stops.
|
|
13868
|
+
*
|
|
13869
|
+
* @param fromStops - The set of stop IDs to find reachable routes from.
|
|
13870
|
+
* @param transportModes - The set of transport modes to consider for reachable routes.
|
|
13871
|
+
* @returns A map of reachable routes to the first stop available to hop on each route.
|
|
13447
13872
|
*/
|
|
13448
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
13449
13873
|
findReachableRoutes(fromStops, transportModes = ALL_TRANSPORT_MODES) {
|
|
13450
|
-
var _a;
|
|
13451
13874
|
const reachableRoutes = new Map();
|
|
13452
|
-
for (const
|
|
13453
|
-
const validRoutes = (
|
|
13454
|
-
|
|
13455
|
-
|
|
13456
|
-
if (!serviceRoute) {
|
|
13457
|
-
return false;
|
|
13458
|
-
}
|
|
13459
|
-
return transportModes.includes(serviceRoute.type);
|
|
13875
|
+
for (const originStop of fromStops) {
|
|
13876
|
+
const validRoutes = this.routesPassingThrough(originStop).filter((route) => {
|
|
13877
|
+
const serviceRoute = this.getServiceRoute(route);
|
|
13878
|
+
return transportModes.has(serviceRoute.type);
|
|
13460
13879
|
});
|
|
13461
|
-
for (const
|
|
13462
|
-
const hopOnStop = reachableRoutes.get(
|
|
13880
|
+
for (const route of validRoutes) {
|
|
13881
|
+
const hopOnStop = reachableRoutes.get(route);
|
|
13463
13882
|
if (hopOnStop) {
|
|
13464
|
-
|
|
13465
|
-
const routeStopIndices = this.routesAdjacency.get(routeId).stopIndices;
|
|
13466
|
-
const stopIndex = routeStopIndices.get(stop);
|
|
13467
|
-
const hopOnStopIndex = routeStopIndices.get(hopOnStop);
|
|
13468
|
-
if (stopIndex < hopOnStopIndex) {
|
|
13883
|
+
if (route.isBefore(originStop, hopOnStop)) {
|
|
13469
13884
|
// if the current stop is before the existing hop on stop, replace it
|
|
13470
|
-
reachableRoutes.set(
|
|
13885
|
+
reachableRoutes.set(route, originStop);
|
|
13471
13886
|
}
|
|
13472
13887
|
}
|
|
13473
13888
|
else {
|
|
13474
|
-
reachableRoutes.set(
|
|
13889
|
+
reachableRoutes.set(route, originStop);
|
|
13475
13890
|
}
|
|
13476
13891
|
}
|
|
13477
13892
|
}
|
|
13478
13893
|
return reachableRoutes;
|
|
13479
13894
|
}
|
|
13480
|
-
getServiceRouteFromRouteId(routeId) {
|
|
13481
|
-
const route = this.routesAdjacency.get(routeId);
|
|
13482
|
-
if (!route) {
|
|
13483
|
-
console.warn(`Route ${routeId} not found.`);
|
|
13484
|
-
return undefined;
|
|
13485
|
-
}
|
|
13486
|
-
return this.routes.get(route.serviceRouteId);
|
|
13487
|
-
}
|
|
13488
|
-
getServiceRoute(serviceRouteId) {
|
|
13489
|
-
return this.routes.get(serviceRouteId);
|
|
13490
|
-
}
|
|
13491
|
-
/**
|
|
13492
|
-
* Finds the earliest trip that can be taken from a specific stop on a given route,
|
|
13493
|
-
* optionally constrained by a latest trip index and a time before which the trip
|
|
13494
|
-
* should not depart.
|
|
13495
|
-
*/
|
|
13496
|
-
findEarliestTrip(route, stopId, beforeTrip, after = Time.origin()) {
|
|
13497
|
-
const stopIndex = route.stopIndices.get(stopId);
|
|
13498
|
-
const stopsNumber = route.stops.length;
|
|
13499
|
-
if (beforeTrip === undefined) {
|
|
13500
|
-
for (let tripIndex = 0; tripIndex < route.stopTimes.length / stopsNumber; tripIndex++) {
|
|
13501
|
-
const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
|
|
13502
|
-
const departure = route.stopTimes[stopTimeIndex * 2 + 1];
|
|
13503
|
-
const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
|
|
13504
|
-
if (departure >= after.toMinutes() && pickUpType !== NOT_AVAILABLE) {
|
|
13505
|
-
return tripIndex;
|
|
13506
|
-
}
|
|
13507
|
-
}
|
|
13508
|
-
return undefined;
|
|
13509
|
-
}
|
|
13510
|
-
else {
|
|
13511
|
-
let earliestTripIndex;
|
|
13512
|
-
let earliestDeparture;
|
|
13513
|
-
for (let tripIndex = beforeTrip; // ?? route.stopTimes.length / stopsNumber - 1;
|
|
13514
|
-
tripIndex >= 0; tripIndex--) {
|
|
13515
|
-
const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
|
|
13516
|
-
const departure = route.stopTimes[stopTimeIndex * 2 + 1];
|
|
13517
|
-
const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
|
|
13518
|
-
if (departure < after.toMinutes()) {
|
|
13519
|
-
break;
|
|
13520
|
-
}
|
|
13521
|
-
if (pickUpType !== NOT_AVAILABLE &&
|
|
13522
|
-
(earliestDeparture === undefined ||
|
|
13523
|
-
departure < earliestDeparture.toMinutes())) {
|
|
13524
|
-
earliestTripIndex = tripIndex;
|
|
13525
|
-
earliestDeparture = Time.fromMinutes(departure);
|
|
13526
|
-
}
|
|
13527
|
-
}
|
|
13528
|
-
return earliestTripIndex;
|
|
13529
|
-
}
|
|
13530
|
-
}
|
|
13531
13895
|
}
|
|
13532
13896
|
|
|
13533
13897
|
const standardProfile = {
|
|
@@ -13844,7 +14208,7 @@ const normalize_options = function (opts) {
|
|
|
13844
14208
|
);
|
|
13845
14209
|
}
|
|
13846
14210
|
// Normalize option `columns`
|
|
13847
|
-
options.cast_first_line_to_header =
|
|
14211
|
+
options.cast_first_line_to_header = undefined;
|
|
13848
14212
|
if (options.columns === true) {
|
|
13849
14213
|
// Fields in the first line are converted as-is to columns
|
|
13850
14214
|
options.cast_first_line_to_header = undefined;
|
|
@@ -14376,7 +14740,7 @@ const normalize_options = function (opts) {
|
|
|
14376
14740
|
// Normalize option `to`
|
|
14377
14741
|
if (options.to === undefined || options.to === null) {
|
|
14378
14742
|
options.to = -1;
|
|
14379
|
-
} else {
|
|
14743
|
+
} else if (options.to !== -1) {
|
|
14380
14744
|
if (typeof options.to === "string" && /\d+/.test(options.to)) {
|
|
14381
14745
|
options.to = parseInt(options.to);
|
|
14382
14746
|
}
|
|
@@ -14395,7 +14759,7 @@ const normalize_options = function (opts) {
|
|
|
14395
14759
|
// Normalize option `to_line`
|
|
14396
14760
|
if (options.to_line === undefined || options.to_line === null) {
|
|
14397
14761
|
options.to_line = -1;
|
|
14398
|
-
} else {
|
|
14762
|
+
} else if (options.to_line !== -1) {
|
|
14399
14763
|
if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) {
|
|
14400
14764
|
options.to_line = parseInt(options.to_line);
|
|
14401
14765
|
}
|
|
@@ -14526,10 +14890,14 @@ const transform = function (original_options = {}) {
|
|
|
14526
14890
|
this.state.bufBytesStart += bomLength;
|
|
14527
14891
|
buf = buf.slice(bomLength);
|
|
14528
14892
|
// Renormalize original options with the new encoding
|
|
14529
|
-
|
|
14893
|
+
const options = normalize_options({
|
|
14530
14894
|
...this.original_options,
|
|
14531
14895
|
encoding: encoding,
|
|
14532
14896
|
});
|
|
14897
|
+
// Properties are merged with the existing options instance
|
|
14898
|
+
for (const key in options) {
|
|
14899
|
+
this.options[key] = options[key];
|
|
14900
|
+
}
|
|
14533
14901
|
// Options will re-evaluate the Buffer with the new encoding
|
|
14534
14902
|
({ comment, escape, quote } = this.options);
|
|
14535
14903
|
break;
|
|
@@ -15272,10 +15640,14 @@ const transform = function (original_options = {}) {
|
|
|
15272
15640
|
if (skip_records_with_error) {
|
|
15273
15641
|
this.state.recordHasError = true;
|
|
15274
15642
|
if (this.options.on_skip !== undefined) {
|
|
15275
|
-
|
|
15276
|
-
|
|
15277
|
-
|
|
15278
|
-
|
|
15643
|
+
try {
|
|
15644
|
+
this.options.on_skip(
|
|
15645
|
+
err,
|
|
15646
|
+
raw ? this.state.rawBuffer.toString(encoding) : undefined,
|
|
15647
|
+
);
|
|
15648
|
+
} catch (err) {
|
|
15649
|
+
return err;
|
|
15650
|
+
}
|
|
15279
15651
|
}
|
|
15280
15652
|
// this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined);
|
|
15281
15653
|
return undefined;
|
|
@@ -15472,11 +15844,17 @@ const hashIds = (ids) => {
|
|
|
15472
15844
|
* @param stream The CSV stream.
|
|
15473
15845
|
* @returns A parser from the csv-parse library.
|
|
15474
15846
|
*/
|
|
15475
|
-
const parseCsv = (stream) => {
|
|
15847
|
+
const parseCsv = (stream, numericColumns = []) => {
|
|
15476
15848
|
return stream.pipe(parse({
|
|
15477
15849
|
delimiter: ',',
|
|
15478
15850
|
columns: true,
|
|
15479
|
-
cast:
|
|
15851
|
+
cast: (value, context) => {
|
|
15852
|
+
if (typeof context.column === 'string' &&
|
|
15853
|
+
numericColumns.includes(context.column)) {
|
|
15854
|
+
return Number(value);
|
|
15855
|
+
}
|
|
15856
|
+
return value;
|
|
15857
|
+
},
|
|
15480
15858
|
bom: true,
|
|
15481
15859
|
ignore_last_delimiters: true,
|
|
15482
15860
|
relax_column_count: true,
|
|
@@ -15490,11 +15868,11 @@ const parseCsv = (stream) => {
|
|
|
15490
15868
|
* @param profile A configuration object defining the specificities of the GTFS feed.
|
|
15491
15869
|
* @returns A map of all the valid routes.
|
|
15492
15870
|
*/
|
|
15493
|
-
const parseRoutes = (routesStream_1, ...args_1) => __awaiter(
|
|
15871
|
+
const parseRoutes = (routesStream_1, ...args_1) => __awaiter(void 0, [routesStream_1, ...args_1], void 0, function* (routesStream, profile = standardProfile) {
|
|
15494
15872
|
var _a, e_1, _b, _c;
|
|
15495
15873
|
const routes = new Map();
|
|
15496
15874
|
try {
|
|
15497
|
-
for (var _d = true, _e = __asyncValues(parseCsv(routesStream)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15875
|
+
for (var _d = true, _e = __asyncValues(parseCsv(routesStream, ['route_type'])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15498
15876
|
_c = _f.value;
|
|
15499
15877
|
_d = false;
|
|
15500
15878
|
const rawLine = _c;
|
|
@@ -15505,7 +15883,7 @@ const parseRoutes = (routesStream_1, ...args_1) => __awaiter(undefined, [routesS
|
|
|
15505
15883
|
continue;
|
|
15506
15884
|
}
|
|
15507
15885
|
routes.set(line.route_id, {
|
|
15508
|
-
name: line.route_short_name
|
|
15886
|
+
name: line.route_short_name,
|
|
15509
15887
|
type: routeType,
|
|
15510
15888
|
});
|
|
15511
15889
|
}
|
|
@@ -15558,13 +15936,23 @@ const weekdays = {
|
|
|
15558
15936
|
* @param date The active date.
|
|
15559
15937
|
* @param calendarStream A readable stream for the GTFS calendar.txt file.
|
|
15560
15938
|
*/
|
|
15561
|
-
const parseCalendar = (calendarStream, serviceIds, date) => __awaiter(
|
|
15939
|
+
const parseCalendar = (calendarStream, serviceIds, date) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15562
15940
|
var _a, e_1, _b, _c;
|
|
15563
15941
|
const activeDate = toGtfsDate(date);
|
|
15564
15942
|
const weekday = date.weekday;
|
|
15565
15943
|
const weekdayIndex = weekdays[weekday];
|
|
15566
15944
|
try {
|
|
15567
|
-
for (var _d = true, _e = __asyncValues(parseCsv(calendarStream
|
|
15945
|
+
for (var _d = true, _e = __asyncValues(parseCsv(calendarStream, [
|
|
15946
|
+
'monday',
|
|
15947
|
+
'tuesday',
|
|
15948
|
+
'wednesday',
|
|
15949
|
+
'thursday',
|
|
15950
|
+
'friday',
|
|
15951
|
+
'saturday',
|
|
15952
|
+
'sunday',
|
|
15953
|
+
'start_date',
|
|
15954
|
+
'end_date',
|
|
15955
|
+
])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15568
15956
|
_c = _f.value;
|
|
15569
15957
|
_d = false;
|
|
15570
15958
|
const rawLine = _c;
|
|
@@ -15595,11 +15983,14 @@ const parseCalendar = (calendarStream, serviceIds, date) => __awaiter(undefined,
|
|
|
15595
15983
|
* @param date The active date, in the format "YYYYMMDD".
|
|
15596
15984
|
* @param calendarDatesStream A readable stream for the GTFS calendar_dates.txt file.
|
|
15597
15985
|
*/
|
|
15598
|
-
const parseCalendarDates = (calendarDatesStream, serviceIds, date) => __awaiter(
|
|
15986
|
+
const parseCalendarDates = (calendarDatesStream, serviceIds, date) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15599
15987
|
var _a, e_2, _b, _c;
|
|
15600
15988
|
const activeDate = toGtfsDate(date);
|
|
15601
15989
|
try {
|
|
15602
|
-
for (var _d = true, _e = __asyncValues(parseCsv(calendarDatesStream
|
|
15990
|
+
for (var _d = true, _e = __asyncValues(parseCsv(calendarDatesStream, [
|
|
15991
|
+
'date',
|
|
15992
|
+
'exception_type',
|
|
15993
|
+
])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15603
15994
|
_c = _f.value;
|
|
15604
15995
|
_d = false;
|
|
15605
15996
|
const rawLine = _c;
|
|
@@ -15632,17 +16023,21 @@ const parseCalendarDates = (calendarDatesStream, serviceIds, date) => __awaiter(
|
|
|
15632
16023
|
* @param stopsStream The readable stream containing the stops data.
|
|
15633
16024
|
* @return A mapping of stop IDs to corresponding stop details.
|
|
15634
16025
|
*/
|
|
15635
|
-
const parseStops = (stopsStream, platformParser) => __awaiter(
|
|
16026
|
+
const parseStops = (stopsStream, platformParser) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15636
16027
|
var _a, e_1, _b, _c;
|
|
15637
16028
|
const parsedStops = new Map();
|
|
15638
16029
|
let i = 0;
|
|
15639
16030
|
try {
|
|
15640
|
-
for (var _d = true, _e = __asyncValues(parseCsv(stopsStream
|
|
16031
|
+
for (var _d = true, _e = __asyncValues(parseCsv(stopsStream, [
|
|
16032
|
+
'stop_lat',
|
|
16033
|
+
'stop_lon',
|
|
16034
|
+
'location_type',
|
|
16035
|
+
])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15641
16036
|
_c = _f.value;
|
|
15642
16037
|
_d = false;
|
|
15643
16038
|
const rawLine = _c;
|
|
15644
16039
|
const line = rawLine;
|
|
15645
|
-
const stop = Object.assign({ id: i, sourceStopId: line.stop_id
|
|
16040
|
+
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
|
|
15646
16041
|
? parseGtfsLocationType(line.location_type)
|
|
15647
16042
|
: 'SIMPLE_STOP_OR_PLATFORM', children: [] }, (line.parent_station && { parentSourceId: line.parent_station }));
|
|
15648
16043
|
if (platformParser) {
|
|
@@ -15656,7 +16051,7 @@ const parseStops = (stopsStream, platformParser) => __awaiter(undefined, undefin
|
|
|
15656
16051
|
console.info(`Could not parse platform for stop ${line.stop_id}.`);
|
|
15657
16052
|
}
|
|
15658
16053
|
}
|
|
15659
|
-
parsedStops.set(line.stop_id
|
|
16054
|
+
parsedStops.set(line.stop_id, stop);
|
|
15660
16055
|
i = i + 1;
|
|
15661
16056
|
}
|
|
15662
16057
|
}
|
|
@@ -15733,11 +16128,14 @@ const parseGtfsLocationType = (gtfsLocationType) => {
|
|
|
15733
16128
|
* @param stopsStream The readable stream containing the stops data.
|
|
15734
16129
|
* @return A mapping of stop IDs to corresponding stop details.
|
|
15735
16130
|
*/
|
|
15736
|
-
const parseTransfers = (transfersStream, stopsMap) => __awaiter(
|
|
16131
|
+
const parseTransfers = (transfersStream, stopsMap) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15737
16132
|
var _a, e_1, _b, _c;
|
|
15738
16133
|
const transfers = new Map();
|
|
15739
16134
|
try {
|
|
15740
|
-
for (var _d = true, _e = __asyncValues(parseCsv(transfersStream
|
|
16135
|
+
for (var _d = true, _e = __asyncValues(parseCsv(transfersStream, [
|
|
16136
|
+
'transfer_type',
|
|
16137
|
+
'min_transfer_time',
|
|
16138
|
+
])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15741
16139
|
_c = _f.value;
|
|
15742
16140
|
_d = false;
|
|
15743
16141
|
const rawLine = _c;
|
|
@@ -15762,9 +16160,9 @@ const parseTransfers = (transfersStream, stopsMap) => __awaiter(undefined, undef
|
|
|
15762
16160
|
console.info(`Missing minimum transfer time between ${transferEntry.from_stop_id} and ${transferEntry.to_stop_id}.`);
|
|
15763
16161
|
}
|
|
15764
16162
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15765
|
-
const fromStop = stopsMap.get(transferEntry.from_stop_id
|
|
16163
|
+
const fromStop = stopsMap.get(transferEntry.from_stop_id);
|
|
15766
16164
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15767
|
-
const toStop = stopsMap.get(transferEntry.to_stop_id
|
|
16165
|
+
const toStop = stopsMap.get(transferEntry.to_stop_id);
|
|
15768
16166
|
const transfer = Object.assign({ destination: toStop.id, type: parseGtfsTransferType(transferEntry.transfer_type) }, (transferEntry.min_transfer_time && {
|
|
15769
16167
|
minTransferTime: Duration.fromSeconds(transferEntry.min_transfer_time),
|
|
15770
16168
|
}));
|
|
@@ -15804,11 +16202,11 @@ const parseGtfsTransferType = (gtfsTransferType) => {
|
|
|
15804
16202
|
* @param routeIds A mapping of route IDs to route details.
|
|
15805
16203
|
* @returns A mapping of trip IDs to corresponding route IDs.
|
|
15806
16204
|
*/
|
|
15807
|
-
const parseTrips = (tripsStream, serviceIds, routeIds) => __awaiter(
|
|
16205
|
+
const parseTrips = (tripsStream, serviceIds, routeIds) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15808
16206
|
var _a, e_1, _b, _c;
|
|
15809
16207
|
const trips = new Map();
|
|
15810
16208
|
try {
|
|
15811
|
-
for (var _d = true, _e = __asyncValues(parseCsv(tripsStream)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
16209
|
+
for (var _d = true, _e = __asyncValues(parseCsv(tripsStream, ['stop_sequence'])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15812
16210
|
_c = _f.value;
|
|
15813
16211
|
_d = false;
|
|
15814
16212
|
const rawLine = _c;
|
|
@@ -15838,11 +16236,14 @@ const buildStopsAdjacencyStructure = (validStops, routes, transfersMap) => {
|
|
|
15838
16236
|
const stopsAdjacency = new Map();
|
|
15839
16237
|
for (const routeId of routes.keys()) {
|
|
15840
16238
|
const route = routes.get(routeId);
|
|
15841
|
-
|
|
16239
|
+
if (!route) {
|
|
16240
|
+
throw new Error(`Route ${routeId} not found`);
|
|
16241
|
+
}
|
|
16242
|
+
for (const stop of route.stopsIterator()) {
|
|
15842
16243
|
if (!stopsAdjacency.get(stop) && validStops.has(stop)) {
|
|
15843
16244
|
stopsAdjacency.set(stop, { routes: [], transfers: [] });
|
|
15844
16245
|
}
|
|
15845
|
-
(_a = stopsAdjacency.get(stop)) === null || _a ===
|
|
16246
|
+
(_a = stopsAdjacency.get(stop)) === null || _a === void 0 ? void 0 : _a.routes.push(routeId);
|
|
15846
16247
|
}
|
|
15847
16248
|
}
|
|
15848
16249
|
for (const [stop, transfers] of transfersMap) {
|
|
@@ -15866,7 +16267,7 @@ const buildStopsAdjacencyStructure = (validStops, routes, transfersMap) => {
|
|
|
15866
16267
|
* @param validStopIds A set of valid stop IDs.
|
|
15867
16268
|
* @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.
|
|
15868
16269
|
*/
|
|
15869
|
-
const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) => __awaiter(
|
|
16270
|
+
const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15870
16271
|
var _a, e_2, _b, _c;
|
|
15871
16272
|
var _d, _e;
|
|
15872
16273
|
/**
|
|
@@ -15904,7 +16305,6 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
15904
16305
|
route = {
|
|
15905
16306
|
serviceRouteId: gtfsRouteId,
|
|
15906
16307
|
stops: stopsArray,
|
|
15907
|
-
stopIndices: new Map(stops.map((stop, i) => [stop, i])),
|
|
15908
16308
|
stopTimes: stopTimesArray,
|
|
15909
16309
|
pickUpDropOffTypes: pickUpDropOffTypesArray,
|
|
15910
16310
|
};
|
|
@@ -15969,7 +16369,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
15969
16369
|
let dropOffTypes = [];
|
|
15970
16370
|
let currentTripId = undefined;
|
|
15971
16371
|
try {
|
|
15972
|
-
for (var _f = true, _g = __asyncValues(parseCsv(stopTimesStream)), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
|
|
16372
|
+
for (var _f = true, _g = __asyncValues(parseCsv(stopTimesStream, ['stop_sequence'])), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
|
|
15973
16373
|
_c = _h.value;
|
|
15974
16374
|
_f = false;
|
|
15975
16375
|
const rawLine = _c;
|
|
@@ -15990,7 +16390,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
15990
16390
|
}
|
|
15991
16391
|
currentTripId = line.trip_id;
|
|
15992
16392
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15993
|
-
stops.push(stopsMap.get(line.stop_id
|
|
16393
|
+
stops.push(stopsMap.get(line.stop_id).id);
|
|
15994
16394
|
const departure = (_d = line.departure_time) !== null && _d !== void 0 ? _d : line.arrival_time;
|
|
15995
16395
|
const arrival = (_e = line.arrival_time) !== null && _e !== void 0 ? _e : line.departure_time;
|
|
15996
16396
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -16012,12 +16412,15 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
16012
16412
|
if (currentTripId) {
|
|
16013
16413
|
addTrip(currentTripId);
|
|
16014
16414
|
}
|
|
16015
|
-
|
|
16415
|
+
const routesAdjacency = new Map();
|
|
16416
|
+
for (const [routeId, routeData] of routes) {
|
|
16417
|
+
routesAdjacency.set(routeId, new Route(routeData.stopTimes, routeData.pickUpDropOffTypes, routeData.stops, routeData.serviceRouteId));
|
|
16418
|
+
}
|
|
16419
|
+
return routesAdjacency;
|
|
16016
16420
|
});
|
|
16017
16421
|
const parsePickupDropOffType = (gtfsType) => {
|
|
16018
16422
|
switch (gtfsType) {
|
|
16019
16423
|
default:
|
|
16020
|
-
console.warn(`Unknown pickup/drop-off type ${gtfsType}`);
|
|
16021
16424
|
return REGULAR;
|
|
16022
16425
|
case 0:
|
|
16023
16426
|
return REGULAR;
|
|
@@ -16052,7 +16455,7 @@ class GtfsParser {
|
|
|
16052
16455
|
* @returns An object containing the timetable and stops map.
|
|
16053
16456
|
*/
|
|
16054
16457
|
parse(date) {
|
|
16055
|
-
return __awaiter(this,
|
|
16458
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16056
16459
|
const zip = new StreamZip.async({ file: this.path });
|
|
16057
16460
|
const entries = yield zip.entries();
|
|
16058
16461
|
const datetime = DateTime.fromJSDate(date);
|
|
@@ -16113,7 +16516,7 @@ class GtfsParser {
|
|
|
16113
16516
|
* @returns An object containing the timetable and stops map.
|
|
16114
16517
|
*/
|
|
16115
16518
|
parseStops() {
|
|
16116
|
-
return __awaiter(this,
|
|
16519
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16117
16520
|
const zip = new StreamZip.async({ file: this.path });
|
|
16118
16521
|
log.info(`Parsing ${STOPS_FILE}`);
|
|
16119
16522
|
const stopsStream = yield zip.stream(STOPS_FILE);
|
|
@@ -16131,7 +16534,7 @@ class GtfsParser {
|
|
|
16131
16534
|
* @returns The platform corresponding to this stop.
|
|
16132
16535
|
*/
|
|
16133
16536
|
const platformParser = (stopEntry) => {
|
|
16134
|
-
const stopId =
|
|
16537
|
+
const stopId = stopEntry.stop_id;
|
|
16135
16538
|
const stopParts = stopId.split(':');
|
|
16136
16539
|
if (stopParts.length > 2) {
|
|
16137
16540
|
return stopParts[2];
|