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.cjs.js
CHANGED
|
@@ -39,7 +39,7 @@ function __values(o) {
|
|
|
39
39
|
if (m) return m.call(o);
|
|
40
40
|
if (o && typeof o.length === "number") return {
|
|
41
41
|
next: function () {
|
|
42
|
-
if (o && i >= o.length) o =
|
|
42
|
+
if (o && i >= o.length) o = void 0;
|
|
43
43
|
return { value: o && o[i++], done: !o };
|
|
44
44
|
}
|
|
45
45
|
};
|
|
@@ -827,12 +827,13 @@ class SystemZone extends Zone {
|
|
|
827
827
|
}
|
|
828
828
|
}
|
|
829
829
|
|
|
830
|
-
|
|
831
|
-
function makeDTF(
|
|
832
|
-
|
|
833
|
-
|
|
830
|
+
const dtfCache = new Map();
|
|
831
|
+
function makeDTF(zoneName) {
|
|
832
|
+
let dtf = dtfCache.get(zoneName);
|
|
833
|
+
if (dtf === undefined) {
|
|
834
|
+
dtf = new Intl.DateTimeFormat("en-US", {
|
|
834
835
|
hour12: false,
|
|
835
|
-
timeZone:
|
|
836
|
+
timeZone: zoneName,
|
|
836
837
|
year: "numeric",
|
|
837
838
|
month: "2-digit",
|
|
838
839
|
day: "2-digit",
|
|
@@ -841,8 +842,9 @@ function makeDTF(zone) {
|
|
|
841
842
|
second: "2-digit",
|
|
842
843
|
era: "short",
|
|
843
844
|
});
|
|
845
|
+
dtfCache.set(zoneName, dtf);
|
|
844
846
|
}
|
|
845
|
-
return
|
|
847
|
+
return dtf;
|
|
846
848
|
}
|
|
847
849
|
|
|
848
850
|
const typeToPos = {
|
|
@@ -878,7 +880,7 @@ function partsOffset(dtf, date) {
|
|
|
878
880
|
return filled;
|
|
879
881
|
}
|
|
880
882
|
|
|
881
|
-
|
|
883
|
+
const ianaZoneCache = new Map();
|
|
882
884
|
/**
|
|
883
885
|
* A zone identified by an IANA identifier, like America/New_York
|
|
884
886
|
* @implements {Zone}
|
|
@@ -889,10 +891,11 @@ class IANAZone extends Zone {
|
|
|
889
891
|
* @return {IANAZone}
|
|
890
892
|
*/
|
|
891
893
|
static create(name) {
|
|
892
|
-
|
|
893
|
-
|
|
894
|
+
let zone = ianaZoneCache.get(name);
|
|
895
|
+
if (zone === undefined) {
|
|
896
|
+
ianaZoneCache.set(name, (zone = new IANAZone(name)));
|
|
894
897
|
}
|
|
895
|
-
return
|
|
898
|
+
return zone;
|
|
896
899
|
}
|
|
897
900
|
|
|
898
901
|
/**
|
|
@@ -900,8 +903,8 @@ class IANAZone extends Zone {
|
|
|
900
903
|
* @return {void}
|
|
901
904
|
*/
|
|
902
905
|
static resetCache() {
|
|
903
|
-
ianaZoneCache
|
|
904
|
-
dtfCache
|
|
906
|
+
ianaZoneCache.clear();
|
|
907
|
+
dtfCache.clear();
|
|
905
908
|
}
|
|
906
909
|
|
|
907
910
|
/**
|
|
@@ -1004,6 +1007,7 @@ class IANAZone extends Zone {
|
|
|
1004
1007
|
* @return {number}
|
|
1005
1008
|
*/
|
|
1006
1009
|
offset(ts) {
|
|
1010
|
+
if (!this.valid) return NaN;
|
|
1007
1011
|
const date = new Date(ts);
|
|
1008
1012
|
|
|
1009
1013
|
if (isNaN(date)) return NaN;
|
|
@@ -1069,36 +1073,36 @@ function getCachedLF(locString, opts = {}) {
|
|
|
1069
1073
|
return dtf;
|
|
1070
1074
|
}
|
|
1071
1075
|
|
|
1072
|
-
|
|
1076
|
+
const intlDTCache = new Map();
|
|
1073
1077
|
function getCachedDTF(locString, opts = {}) {
|
|
1074
1078
|
const key = JSON.stringify([locString, opts]);
|
|
1075
|
-
let dtf = intlDTCache
|
|
1076
|
-
if (
|
|
1079
|
+
let dtf = intlDTCache.get(key);
|
|
1080
|
+
if (dtf === undefined) {
|
|
1077
1081
|
dtf = new Intl.DateTimeFormat(locString, opts);
|
|
1078
|
-
intlDTCache
|
|
1082
|
+
intlDTCache.set(key, dtf);
|
|
1079
1083
|
}
|
|
1080
1084
|
return dtf;
|
|
1081
1085
|
}
|
|
1082
1086
|
|
|
1083
|
-
|
|
1087
|
+
const intlNumCache = new Map();
|
|
1084
1088
|
function getCachedINF(locString, opts = {}) {
|
|
1085
1089
|
const key = JSON.stringify([locString, opts]);
|
|
1086
|
-
let inf = intlNumCache
|
|
1087
|
-
if (
|
|
1090
|
+
let inf = intlNumCache.get(key);
|
|
1091
|
+
if (inf === undefined) {
|
|
1088
1092
|
inf = new Intl.NumberFormat(locString, opts);
|
|
1089
|
-
intlNumCache
|
|
1093
|
+
intlNumCache.set(key, inf);
|
|
1090
1094
|
}
|
|
1091
1095
|
return inf;
|
|
1092
1096
|
}
|
|
1093
1097
|
|
|
1094
|
-
|
|
1098
|
+
const intlRelCache = new Map();
|
|
1095
1099
|
function getCachedRTF(locString, opts = {}) {
|
|
1096
1100
|
const { base, ...cacheKeyOpts } = opts; // exclude `base` from the options
|
|
1097
1101
|
const key = JSON.stringify([locString, cacheKeyOpts]);
|
|
1098
|
-
let inf = intlRelCache
|
|
1099
|
-
if (
|
|
1102
|
+
let inf = intlRelCache.get(key);
|
|
1103
|
+
if (inf === undefined) {
|
|
1100
1104
|
inf = new Intl.RelativeTimeFormat(locString, opts);
|
|
1101
|
-
intlRelCache
|
|
1105
|
+
intlRelCache.set(key, inf);
|
|
1102
1106
|
}
|
|
1103
1107
|
return inf;
|
|
1104
1108
|
}
|
|
@@ -1113,14 +1117,28 @@ function systemLocale() {
|
|
|
1113
1117
|
}
|
|
1114
1118
|
}
|
|
1115
1119
|
|
|
1116
|
-
|
|
1120
|
+
const intlResolvedOptionsCache = new Map();
|
|
1121
|
+
function getCachedIntResolvedOptions(locString) {
|
|
1122
|
+
let opts = intlResolvedOptionsCache.get(locString);
|
|
1123
|
+
if (opts === undefined) {
|
|
1124
|
+
opts = new Intl.DateTimeFormat(locString).resolvedOptions();
|
|
1125
|
+
intlResolvedOptionsCache.set(locString, opts);
|
|
1126
|
+
}
|
|
1127
|
+
return opts;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
const weekInfoCache = new Map();
|
|
1117
1131
|
function getCachedWeekInfo(locString) {
|
|
1118
|
-
let data = weekInfoCache
|
|
1132
|
+
let data = weekInfoCache.get(locString);
|
|
1119
1133
|
if (!data) {
|
|
1120
1134
|
const locale = new Intl.Locale(locString);
|
|
1121
1135
|
// browsers currently implement this as a property, but spec says it should be a getter function
|
|
1122
1136
|
data = "getWeekInfo" in locale ? locale.getWeekInfo() : locale.weekInfo;
|
|
1123
|
-
|
|
1137
|
+
// minimalDays was removed from WeekInfo: https://github.com/tc39/proposal-intl-locale-info/issues/86
|
|
1138
|
+
if (!("minimalDays" in data)) {
|
|
1139
|
+
data = { ...fallbackWeekSettings, ...data };
|
|
1140
|
+
}
|
|
1141
|
+
weekInfoCache.set(locString, data);
|
|
1124
1142
|
}
|
|
1125
1143
|
return data;
|
|
1126
1144
|
}
|
|
@@ -1219,7 +1237,7 @@ function supportsFastNumbers(loc) {
|
|
|
1219
1237
|
loc.numberingSystem === "latn" ||
|
|
1220
1238
|
!loc.locale ||
|
|
1221
1239
|
loc.locale.startsWith("en") ||
|
|
1222
|
-
|
|
1240
|
+
getCachedIntResolvedOptions(loc.locale).numberingSystem === "latn"
|
|
1223
1241
|
);
|
|
1224
1242
|
}
|
|
1225
1243
|
}
|
|
@@ -1378,7 +1396,6 @@ const fallbackWeekSettings = {
|
|
|
1378
1396
|
/**
|
|
1379
1397
|
* @private
|
|
1380
1398
|
*/
|
|
1381
|
-
|
|
1382
1399
|
class Locale {
|
|
1383
1400
|
static fromOpts(opts) {
|
|
1384
1401
|
return Locale.create(
|
|
@@ -1402,9 +1419,11 @@ class Locale {
|
|
|
1402
1419
|
|
|
1403
1420
|
static resetCache() {
|
|
1404
1421
|
sysLocaleCache = null;
|
|
1405
|
-
intlDTCache
|
|
1406
|
-
intlNumCache
|
|
1407
|
-
intlRelCache
|
|
1422
|
+
intlDTCache.clear();
|
|
1423
|
+
intlNumCache.clear();
|
|
1424
|
+
intlRelCache.clear();
|
|
1425
|
+
intlResolvedOptionsCache.clear();
|
|
1426
|
+
weekInfoCache.clear();
|
|
1408
1427
|
}
|
|
1409
1428
|
|
|
1410
1429
|
static fromObject({ locale, numberingSystem, outputCalendar, weekSettings } = {}) {
|
|
@@ -1469,10 +1488,18 @@ class Locale {
|
|
|
1469
1488
|
|
|
1470
1489
|
months(length, format = false) {
|
|
1471
1490
|
return listStuff(this, length, months, () => {
|
|
1491
|
+
// Workaround for "ja" locale: formatToParts does not label all parts of the month
|
|
1492
|
+
// as "month" and for this locale there is no difference between "format" and "non-format".
|
|
1493
|
+
// As such, just use format() instead of formatToParts() and take the whole string
|
|
1494
|
+
const monthSpecialCase = this.intl === "ja" || this.intl.startsWith("ja-");
|
|
1495
|
+
format &= !monthSpecialCase;
|
|
1472
1496
|
const intl = format ? { month: length, day: "numeric" } : { month: length },
|
|
1473
1497
|
formatStr = format ? "format" : "standalone";
|
|
1474
1498
|
if (!this.monthsCache[formatStr][length]) {
|
|
1475
|
-
|
|
1499
|
+
const mapper = !monthSpecialCase
|
|
1500
|
+
? (dt) => this.extract(dt, intl, "month")
|
|
1501
|
+
: (dt) => this.dtFormatter(dt, intl).format();
|
|
1502
|
+
this.monthsCache[formatStr][length] = mapMonths(mapper);
|
|
1476
1503
|
}
|
|
1477
1504
|
return this.monthsCache[formatStr][length];
|
|
1478
1505
|
});
|
|
@@ -1558,7 +1585,7 @@ class Locale {
|
|
|
1558
1585
|
return (
|
|
1559
1586
|
this.locale === "en" ||
|
|
1560
1587
|
this.locale.toLowerCase() === "en-us" ||
|
|
1561
|
-
|
|
1588
|
+
getCachedIntResolvedOptions(this.intl).locale.startsWith("en-us")
|
|
1562
1589
|
);
|
|
1563
1590
|
}
|
|
1564
1591
|
|
|
@@ -1897,22 +1924,26 @@ function parseDigits(str) {
|
|
|
1897
1924
|
}
|
|
1898
1925
|
|
|
1899
1926
|
// cache of {numberingSystem: {append: regex}}
|
|
1900
|
-
|
|
1927
|
+
const digitRegexCache = new Map();
|
|
1901
1928
|
function resetDigitRegexCache() {
|
|
1902
|
-
digitRegexCache
|
|
1929
|
+
digitRegexCache.clear();
|
|
1903
1930
|
}
|
|
1904
1931
|
|
|
1905
1932
|
function digitRegex({ numberingSystem }, append = "") {
|
|
1906
1933
|
const ns = numberingSystem || "latn";
|
|
1907
1934
|
|
|
1908
|
-
|
|
1909
|
-
|
|
1935
|
+
let appendCache = digitRegexCache.get(ns);
|
|
1936
|
+
if (appendCache === undefined) {
|
|
1937
|
+
appendCache = new Map();
|
|
1938
|
+
digitRegexCache.set(ns, appendCache);
|
|
1910
1939
|
}
|
|
1911
|
-
|
|
1912
|
-
|
|
1940
|
+
let regex = appendCache.get(append);
|
|
1941
|
+
if (regex === undefined) {
|
|
1942
|
+
regex = new RegExp(`${numberingSystems[ns]}${append}`);
|
|
1943
|
+
appendCache.set(append, regex);
|
|
1913
1944
|
}
|
|
1914
1945
|
|
|
1915
|
-
return
|
|
1946
|
+
return regex;
|
|
1916
1947
|
}
|
|
1917
1948
|
|
|
1918
1949
|
let now = () => Date.now(),
|
|
@@ -2454,10 +2485,24 @@ function parseMillis(fraction) {
|
|
|
2454
2485
|
}
|
|
2455
2486
|
}
|
|
2456
2487
|
|
|
2457
|
-
function roundTo(number, digits,
|
|
2458
|
-
const factor = 10 ** digits
|
|
2459
|
-
|
|
2460
|
-
|
|
2488
|
+
function roundTo(number, digits, rounding = "round") {
|
|
2489
|
+
const factor = 10 ** digits;
|
|
2490
|
+
switch (rounding) {
|
|
2491
|
+
case "expand":
|
|
2492
|
+
return number > 0
|
|
2493
|
+
? Math.ceil(number * factor) / factor
|
|
2494
|
+
: Math.floor(number * factor) / factor;
|
|
2495
|
+
case "trunc":
|
|
2496
|
+
return Math.trunc(number * factor) / factor;
|
|
2497
|
+
case "round":
|
|
2498
|
+
return Math.round(number * factor) / factor;
|
|
2499
|
+
case "floor":
|
|
2500
|
+
return Math.floor(number * factor) / factor;
|
|
2501
|
+
case "ceil":
|
|
2502
|
+
return Math.ceil(number * factor) / factor;
|
|
2503
|
+
default:
|
|
2504
|
+
throw new RangeError(`Value rounding ${rounding} is out of range`);
|
|
2505
|
+
}
|
|
2461
2506
|
}
|
|
2462
2507
|
|
|
2463
2508
|
// DATE BASICS
|
|
@@ -2565,7 +2610,7 @@ function signedOffset(offHourStr, offMinuteStr) {
|
|
|
2565
2610
|
|
|
2566
2611
|
function asNumber(value) {
|
|
2567
2612
|
const numericValue = Number(value);
|
|
2568
|
-
if (typeof value === "boolean" || value === "" || Number.
|
|
2613
|
+
if (typeof value === "boolean" || value === "" || !Number.isFinite(numericValue))
|
|
2569
2614
|
throw new InvalidArgumentError(`Invalid unit value ${value}`);
|
|
2570
2615
|
return numericValue;
|
|
2571
2616
|
}
|
|
@@ -2824,8 +2869,12 @@ class Formatter {
|
|
|
2824
2869
|
for (let i = 0; i < fmt.length; i++) {
|
|
2825
2870
|
const c = fmt.charAt(i);
|
|
2826
2871
|
if (c === "'") {
|
|
2827
|
-
|
|
2828
|
-
|
|
2872
|
+
// turn '' into a literal signal quote instead of just skipping the empty literal
|
|
2873
|
+
if (currentFull.length > 0 || bracketed) {
|
|
2874
|
+
splits.push({
|
|
2875
|
+
literal: bracketed || /^\s+$/.test(currentFull),
|
|
2876
|
+
val: currentFull === "" ? "'" : currentFull,
|
|
2877
|
+
});
|
|
2829
2878
|
}
|
|
2830
2879
|
current = null;
|
|
2831
2880
|
currentFull = "";
|
|
@@ -2889,7 +2938,7 @@ class Formatter {
|
|
|
2889
2938
|
return this.dtFormatter(dt, opts).resolvedOptions();
|
|
2890
2939
|
}
|
|
2891
2940
|
|
|
2892
|
-
num(n, p = 0) {
|
|
2941
|
+
num(n, p = 0, signDisplay = undefined) {
|
|
2893
2942
|
// we get some perf out of doing this here, annoyingly
|
|
2894
2943
|
if (this.opts.forceSimple) {
|
|
2895
2944
|
return padStart(n, p);
|
|
@@ -2900,6 +2949,9 @@ class Formatter {
|
|
|
2900
2949
|
if (p > 0) {
|
|
2901
2950
|
opts.padTo = p;
|
|
2902
2951
|
}
|
|
2952
|
+
if (signDisplay) {
|
|
2953
|
+
opts.signDisplay = signDisplay;
|
|
2954
|
+
}
|
|
2903
2955
|
|
|
2904
2956
|
return this.loc.numberFormatter(opts).format(n);
|
|
2905
2957
|
}
|
|
@@ -3135,32 +3187,44 @@ class Formatter {
|
|
|
3135
3187
|
}
|
|
3136
3188
|
|
|
3137
3189
|
formatDurationFromString(dur, fmt) {
|
|
3190
|
+
const invertLargest = this.opts.signMode === "negativeLargestOnly" ? -1 : 1;
|
|
3138
3191
|
const tokenToField = (token) => {
|
|
3139
3192
|
switch (token[0]) {
|
|
3140
3193
|
case "S":
|
|
3141
|
-
return "
|
|
3194
|
+
return "milliseconds";
|
|
3142
3195
|
case "s":
|
|
3143
|
-
return "
|
|
3196
|
+
return "seconds";
|
|
3144
3197
|
case "m":
|
|
3145
|
-
return "
|
|
3198
|
+
return "minutes";
|
|
3146
3199
|
case "h":
|
|
3147
|
-
return "
|
|
3200
|
+
return "hours";
|
|
3148
3201
|
case "d":
|
|
3149
|
-
return "
|
|
3202
|
+
return "days";
|
|
3150
3203
|
case "w":
|
|
3151
|
-
return "
|
|
3204
|
+
return "weeks";
|
|
3152
3205
|
case "M":
|
|
3153
|
-
return "
|
|
3206
|
+
return "months";
|
|
3154
3207
|
case "y":
|
|
3155
|
-
return "
|
|
3208
|
+
return "years";
|
|
3156
3209
|
default:
|
|
3157
3210
|
return null;
|
|
3158
3211
|
}
|
|
3159
3212
|
},
|
|
3160
|
-
tokenToString = (lildur) => (token) => {
|
|
3213
|
+
tokenToString = (lildur, info) => (token) => {
|
|
3161
3214
|
const mapped = tokenToField(token);
|
|
3162
3215
|
if (mapped) {
|
|
3163
|
-
|
|
3216
|
+
const inversionFactor =
|
|
3217
|
+
info.isNegativeDuration && mapped !== info.largestUnit ? invertLargest : 1;
|
|
3218
|
+
let signDisplay;
|
|
3219
|
+
if (this.opts.signMode === "negativeLargestOnly" && mapped !== info.largestUnit) {
|
|
3220
|
+
signDisplay = "never";
|
|
3221
|
+
} else if (this.opts.signMode === "all") {
|
|
3222
|
+
signDisplay = "always";
|
|
3223
|
+
} else {
|
|
3224
|
+
// "auto" and "negative" are the same, but "auto" has better support
|
|
3225
|
+
signDisplay = "auto";
|
|
3226
|
+
}
|
|
3227
|
+
return this.num(lildur.get(mapped) * inversionFactor, token.length, signDisplay);
|
|
3164
3228
|
} else {
|
|
3165
3229
|
return token;
|
|
3166
3230
|
}
|
|
@@ -3170,8 +3234,14 @@ class Formatter {
|
|
|
3170
3234
|
(found, { literal, val }) => (literal ? found : found.concat(val)),
|
|
3171
3235
|
[]
|
|
3172
3236
|
),
|
|
3173
|
-
collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t))
|
|
3174
|
-
|
|
3237
|
+
collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t)),
|
|
3238
|
+
durationInfo = {
|
|
3239
|
+
isNegativeDuration: collapsed < 0,
|
|
3240
|
+
// this relies on "collapsed" being based on "shiftTo", which builds up the object
|
|
3241
|
+
// in order
|
|
3242
|
+
largestUnit: Object.keys(collapsed.values)[0],
|
|
3243
|
+
};
|
|
3244
|
+
return stringifyTokens(tokens, tokenToString(collapsed, durationInfo));
|
|
3175
3245
|
}
|
|
3176
3246
|
}
|
|
3177
3247
|
|
|
@@ -3232,11 +3302,11 @@ function simpleParse(...keys) {
|
|
|
3232
3302
|
}
|
|
3233
3303
|
|
|
3234
3304
|
// ISO and SQL parsing
|
|
3235
|
-
const offsetRegex = /(?:(
|
|
3305
|
+
const offsetRegex = /(?:([Zz])|([+-]\d\d)(?::?(\d\d))?)/;
|
|
3236
3306
|
const isoExtendedZone = `(?:${offsetRegex.source}?(?:\\[(${ianaRegex.source})\\])?)?`;
|
|
3237
3307
|
const isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/;
|
|
3238
3308
|
const isoTimeRegex = RegExp(`${isoTimeBaseRegex.source}${isoExtendedZone}`);
|
|
3239
|
-
const isoTimeExtensionRegex = RegExp(`(?:
|
|
3309
|
+
const isoTimeExtensionRegex = RegExp(`(?:[Tt]${isoTimeRegex.source})?`);
|
|
3240
3310
|
const isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/;
|
|
3241
3311
|
const isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/;
|
|
3242
3312
|
const isoOrdinalRegex = /(\d{4})-?(\d{3})/;
|
|
@@ -3951,9 +4021,13 @@ let Duration$1 = class Duration {
|
|
|
3951
4021
|
* @param {string} fmt - the format string
|
|
3952
4022
|
* @param {Object} opts - options
|
|
3953
4023
|
* @param {boolean} [opts.floor=true] - floor numerical values
|
|
4024
|
+
* @param {'negative'|'all'|'negativeLargestOnly'} [opts.signMode=negative] - How to handle signs
|
|
3954
4025
|
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("y d s") //=> "1 6 2"
|
|
3955
4026
|
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("yy dd sss") //=> "01 06 002"
|
|
3956
4027
|
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("M S") //=> "12 518402000"
|
|
4028
|
+
* @example Duration.fromObject({ days: 6, seconds: 2 }).toFormat("d s", { signMode: "all" }) //=> "+6 +2"
|
|
4029
|
+
* @example Duration.fromObject({ days: -6, seconds: -2 }).toFormat("d s", { signMode: "all" }) //=> "-6 -2"
|
|
4030
|
+
* @example Duration.fromObject({ days: -6, seconds: -2 }).toFormat("d s", { signMode: "negativeLargestOnly" }) //=> "-6 2"
|
|
3957
4031
|
* @return {string}
|
|
3958
4032
|
*/
|
|
3959
4033
|
toFormat(fmt, opts = {}) {
|
|
@@ -3973,21 +4047,25 @@ let Duration$1 = class Duration {
|
|
|
3973
4047
|
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options
|
|
3974
4048
|
* @param {Object} opts - Formatting options. Accepts the same keys as the options parameter of the native `Intl.NumberFormat` constructor, as well as `listStyle`.
|
|
3975
4049
|
* @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.
|
|
4050
|
+
* @param {boolean} [opts.showZeros=true] - Show all units previously used by the duration even if they are zero
|
|
3976
4051
|
* @example
|
|
3977
4052
|
* ```js
|
|
3978
|
-
* var dur = Duration.fromObject({
|
|
3979
|
-
* dur.toHuman() //=> '1
|
|
3980
|
-
* dur.toHuman({ listStyle: "long" }) //=> '1
|
|
3981
|
-
* dur.toHuman({ unitDisplay: "short" }) //=> '1
|
|
4053
|
+
* var dur = Duration.fromObject({ months: 1, weeks: 0, hours: 5, minutes: 6 })
|
|
4054
|
+
* dur.toHuman() //=> '1 month, 0 weeks, 5 hours, 6 minutes'
|
|
4055
|
+
* dur.toHuman({ listStyle: "long" }) //=> '1 month, 0 weeks, 5 hours, and 6 minutes'
|
|
4056
|
+
* dur.toHuman({ unitDisplay: "short" }) //=> '1 mth, 0 wks, 5 hr, 6 min'
|
|
4057
|
+
* dur.toHuman({ showZeros: false }) //=> '1 month, 5 hours, 6 minutes'
|
|
3982
4058
|
* ```
|
|
3983
4059
|
*/
|
|
3984
4060
|
toHuman(opts = {}) {
|
|
3985
4061
|
if (!this.isValid) return INVALID$2;
|
|
3986
4062
|
|
|
4063
|
+
const showZeros = opts.showZeros !== false;
|
|
4064
|
+
|
|
3987
4065
|
const l = orderedUnits$1
|
|
3988
4066
|
.map((unit) => {
|
|
3989
4067
|
const val = this.values[unit];
|
|
3990
|
-
if (isUndefined(val)) {
|
|
4068
|
+
if (isUndefined(val) || (val === 0 && !showZeros)) {
|
|
3991
4069
|
return null;
|
|
3992
4070
|
}
|
|
3993
4071
|
return this.loc
|
|
@@ -4347,6 +4425,17 @@ let Duration$1 = class Duration {
|
|
|
4347
4425
|
return clone$1(this, { values: negated }, true);
|
|
4348
4426
|
}
|
|
4349
4427
|
|
|
4428
|
+
/**
|
|
4429
|
+
* Removes all units with values equal to 0 from this Duration.
|
|
4430
|
+
* @example Duration.fromObject({ years: 2, days: 0, hours: 0, minutes: 0 }).removeZeros().toObject() //=> { years: 2 }
|
|
4431
|
+
* @return {Duration}
|
|
4432
|
+
*/
|
|
4433
|
+
removeZeros() {
|
|
4434
|
+
if (!this.isValid) return this;
|
|
4435
|
+
const vals = removeZeroes(this.values);
|
|
4436
|
+
return clone$1(this, { values: vals }, true);
|
|
4437
|
+
}
|
|
4438
|
+
|
|
4350
4439
|
/**
|
|
4351
4440
|
* Get the years.
|
|
4352
4441
|
* @type {number}
|
|
@@ -4657,13 +4746,22 @@ class Interval {
|
|
|
4657
4746
|
}
|
|
4658
4747
|
|
|
4659
4748
|
/**
|
|
4660
|
-
* Returns the end of the Interval
|
|
4749
|
+
* Returns the end of the Interval. This is the first instant which is not part of the interval
|
|
4750
|
+
* (Interval is half-open).
|
|
4661
4751
|
* @type {DateTime}
|
|
4662
4752
|
*/
|
|
4663
4753
|
get end() {
|
|
4664
4754
|
return this.isValid ? this.e : null;
|
|
4665
4755
|
}
|
|
4666
4756
|
|
|
4757
|
+
/**
|
|
4758
|
+
* Returns the last DateTime included in the interval (since end is not part of the interval)
|
|
4759
|
+
* @type {DateTime}
|
|
4760
|
+
*/
|
|
4761
|
+
get lastDateTime() {
|
|
4762
|
+
return this.isValid ? (this.e ? this.e.minus(1) : null) : null;
|
|
4763
|
+
}
|
|
4764
|
+
|
|
4667
4765
|
/**
|
|
4668
4766
|
* Returns whether this Interval's end is at least its start, meaning that the Interval isn't 'backwards'.
|
|
4669
4767
|
* @type {boolean}
|
|
@@ -4928,8 +5026,11 @@ class Interval {
|
|
|
4928
5026
|
}
|
|
4929
5027
|
|
|
4930
5028
|
/**
|
|
4931
|
-
* Merge an array of Intervals into
|
|
5029
|
+
* Merge an array of Intervals into an equivalent minimal set of Intervals.
|
|
4932
5030
|
* Combines overlapping and adjacent Intervals.
|
|
5031
|
+
* The resulting array will contain the Intervals in ascending order, that is, starting with the earliest Interval
|
|
5032
|
+
* and ending with the latest.
|
|
5033
|
+
*
|
|
4933
5034
|
* @param {Array} intervals
|
|
4934
5035
|
* @return {Array}
|
|
4935
5036
|
*/
|
|
@@ -6077,21 +6178,22 @@ function toTechFormat(dt, format, allowZ = true) {
|
|
|
6077
6178
|
: null;
|
|
6078
6179
|
}
|
|
6079
6180
|
|
|
6080
|
-
function toISODate(o, extended) {
|
|
6181
|
+
function toISODate(o, extended, precision) {
|
|
6081
6182
|
const longFormat = o.c.year > 9999 || o.c.year < 0;
|
|
6082
6183
|
let c = "";
|
|
6083
6184
|
if (longFormat && o.c.year >= 0) c += "+";
|
|
6084
6185
|
c += padStart(o.c.year, longFormat ? 6 : 4);
|
|
6085
|
-
|
|
6186
|
+
if (precision === "year") return c;
|
|
6086
6187
|
if (extended) {
|
|
6087
6188
|
c += "-";
|
|
6088
6189
|
c += padStart(o.c.month);
|
|
6190
|
+
if (precision === "month") return c;
|
|
6089
6191
|
c += "-";
|
|
6090
|
-
c += padStart(o.c.day);
|
|
6091
6192
|
} else {
|
|
6092
6193
|
c += padStart(o.c.month);
|
|
6093
|
-
|
|
6194
|
+
if (precision === "month") return c;
|
|
6094
6195
|
}
|
|
6196
|
+
c += padStart(o.c.day);
|
|
6095
6197
|
return c;
|
|
6096
6198
|
}
|
|
6097
6199
|
|
|
@@ -6101,26 +6203,39 @@ function toISOTime(
|
|
|
6101
6203
|
suppressSeconds,
|
|
6102
6204
|
suppressMilliseconds,
|
|
6103
6205
|
includeOffset,
|
|
6104
|
-
extendedZone
|
|
6206
|
+
extendedZone,
|
|
6207
|
+
precision
|
|
6105
6208
|
) {
|
|
6106
|
-
let
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6209
|
+
let showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0,
|
|
6210
|
+
c = "";
|
|
6211
|
+
switch (precision) {
|
|
6212
|
+
case "day":
|
|
6213
|
+
case "month":
|
|
6214
|
+
case "year":
|
|
6215
|
+
break;
|
|
6216
|
+
default:
|
|
6217
|
+
c += padStart(o.c.hour);
|
|
6218
|
+
if (precision === "hour") break;
|
|
6219
|
+
if (extended) {
|
|
6220
|
+
c += ":";
|
|
6221
|
+
c += padStart(o.c.minute);
|
|
6222
|
+
if (precision === "minute") break;
|
|
6223
|
+
if (showSeconds) {
|
|
6224
|
+
c += ":";
|
|
6225
|
+
c += padStart(o.c.second);
|
|
6226
|
+
}
|
|
6227
|
+
} else {
|
|
6228
|
+
c += padStart(o.c.minute);
|
|
6229
|
+
if (precision === "minute") break;
|
|
6230
|
+
if (showSeconds) {
|
|
6231
|
+
c += padStart(o.c.second);
|
|
6232
|
+
}
|
|
6233
|
+
}
|
|
6234
|
+
if (precision === "second") break;
|
|
6235
|
+
if (showSeconds && (!suppressMilliseconds || o.c.millisecond !== 0)) {
|
|
6236
|
+
c += ".";
|
|
6237
|
+
c += padStart(o.c.millisecond, 3);
|
|
6238
|
+
}
|
|
6124
6239
|
}
|
|
6125
6240
|
|
|
6126
6241
|
if (includeOffset) {
|
|
@@ -6252,15 +6367,27 @@ function normalizeUnitWithLocalWeeks(unit) {
|
|
|
6252
6367
|
// This is safe for quickDT (used by local() and utc()) because we don't fill in
|
|
6253
6368
|
// higher-order units from tsNow (as we do in fromObject, this requires that
|
|
6254
6369
|
// offset is calculated from tsNow).
|
|
6370
|
+
/**
|
|
6371
|
+
* @param {Zone} zone
|
|
6372
|
+
* @return {number}
|
|
6373
|
+
*/
|
|
6255
6374
|
function guessOffsetForZone(zone) {
|
|
6256
|
-
if (
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
}
|
|
6375
|
+
if (zoneOffsetTs === undefined) {
|
|
6376
|
+
zoneOffsetTs = Settings.now();
|
|
6377
|
+
}
|
|
6260
6378
|
|
|
6261
|
-
|
|
6379
|
+
// Do not cache anything but IANA zones, because it is not safe to do so.
|
|
6380
|
+
// Guessing an offset which is not present in the zone can cause wrong results from fixOffset
|
|
6381
|
+
if (zone.type !== "iana") {
|
|
6382
|
+
return zone.offset(zoneOffsetTs);
|
|
6262
6383
|
}
|
|
6263
|
-
|
|
6384
|
+
const zoneName = zone.name;
|
|
6385
|
+
let offsetGuess = zoneOffsetGuessCache.get(zoneName);
|
|
6386
|
+
if (offsetGuess === undefined) {
|
|
6387
|
+
offsetGuess = zone.offset(zoneOffsetTs);
|
|
6388
|
+
zoneOffsetGuessCache.set(zoneName, offsetGuess);
|
|
6389
|
+
}
|
|
6390
|
+
return offsetGuess;
|
|
6264
6391
|
}
|
|
6265
6392
|
|
|
6266
6393
|
// this is a dumbed down version of fromObject() that runs about 60% faster
|
|
@@ -6300,8 +6427,9 @@ function quickDT(obj, opts) {
|
|
|
6300
6427
|
|
|
6301
6428
|
function diffRelative(start, end, opts) {
|
|
6302
6429
|
const round = isUndefined(opts.round) ? true : opts.round,
|
|
6430
|
+
rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding,
|
|
6303
6431
|
format = (c, unit) => {
|
|
6304
|
-
c = roundTo(c, round || opts.calendary ? 0 : 2,
|
|
6432
|
+
c = roundTo(c, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
|
|
6305
6433
|
const formatter = end.loc.clone(opts).relFormatter(opts);
|
|
6306
6434
|
return formatter.format(c, unit);
|
|
6307
6435
|
},
|
|
@@ -6350,7 +6478,7 @@ let zoneOffsetTs;
|
|
|
6350
6478
|
* This optimizes quickDT via guessOffsetForZone to avoid repeated calls of
|
|
6351
6479
|
* zone.offset().
|
|
6352
6480
|
*/
|
|
6353
|
-
|
|
6481
|
+
const zoneOffsetGuessCache = new Map();
|
|
6354
6482
|
|
|
6355
6483
|
/**
|
|
6356
6484
|
* 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.
|
|
@@ -6554,7 +6682,7 @@ class DateTime {
|
|
|
6554
6682
|
throw new InvalidArgumentError(
|
|
6555
6683
|
`fromMillis requires a numerical input, but received a ${typeof milliseconds} with value ${milliseconds}`
|
|
6556
6684
|
);
|
|
6557
|
-
} else if (milliseconds < -
|
|
6685
|
+
} else if (milliseconds < -MAX_DATE || milliseconds > MAX_DATE) {
|
|
6558
6686
|
// this isn't perfect because we can still end up out of range because of additional shifting, but it's a start
|
|
6559
6687
|
return DateTime.invalid("Timestamp out of range");
|
|
6560
6688
|
} else {
|
|
@@ -6915,7 +7043,7 @@ class DateTime {
|
|
|
6915
7043
|
|
|
6916
7044
|
static resetCache() {
|
|
6917
7045
|
zoneOffsetTs = undefined;
|
|
6918
|
-
zoneOffsetGuessCache
|
|
7046
|
+
zoneOffsetGuessCache.clear();
|
|
6919
7047
|
}
|
|
6920
7048
|
|
|
6921
7049
|
// INFO
|
|
@@ -7680,11 +7808,14 @@ class DateTime {
|
|
|
7680
7808
|
* @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
|
|
7681
7809
|
* @param {boolean} [opts.extendedZone=false] - add the time zone format extension
|
|
7682
7810
|
* @param {string} [opts.format='extended'] - choose between the basic and extended format
|
|
7811
|
+
* @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.
|
|
7683
7812
|
* @example DateTime.utc(1983, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z'
|
|
7684
7813
|
* @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00'
|
|
7685
7814
|
* @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335'
|
|
7686
7815
|
* @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400'
|
|
7687
|
-
* @
|
|
7816
|
+
* @example DateTime.now().toISO({ precision: 'day' }) //=> '2017-04-22Z'
|
|
7817
|
+
* @example DateTime.now().toISO({ precision: 'minute' }) //=> '2017-04-22T20:47Z'
|
|
7818
|
+
* @return {string|null}
|
|
7688
7819
|
*/
|
|
7689
7820
|
toISO({
|
|
7690
7821
|
format = "extended",
|
|
@@ -7692,16 +7823,26 @@ class DateTime {
|
|
|
7692
7823
|
suppressMilliseconds = false,
|
|
7693
7824
|
includeOffset = true,
|
|
7694
7825
|
extendedZone = false,
|
|
7826
|
+
precision = "milliseconds",
|
|
7695
7827
|
} = {}) {
|
|
7696
7828
|
if (!this.isValid) {
|
|
7697
7829
|
return null;
|
|
7698
7830
|
}
|
|
7699
7831
|
|
|
7832
|
+
precision = normalizeUnit(precision);
|
|
7700
7833
|
const ext = format === "extended";
|
|
7701
7834
|
|
|
7702
|
-
let c = toISODate(this, ext);
|
|
7703
|
-
c += "T";
|
|
7704
|
-
c += toISOTime(
|
|
7835
|
+
let c = toISODate(this, ext, precision);
|
|
7836
|
+
if (orderedUnits.indexOf(precision) >= 3) c += "T";
|
|
7837
|
+
c += toISOTime(
|
|
7838
|
+
this,
|
|
7839
|
+
ext,
|
|
7840
|
+
suppressSeconds,
|
|
7841
|
+
suppressMilliseconds,
|
|
7842
|
+
includeOffset,
|
|
7843
|
+
extendedZone,
|
|
7844
|
+
precision
|
|
7845
|
+
);
|
|
7705
7846
|
return c;
|
|
7706
7847
|
}
|
|
7707
7848
|
|
|
@@ -7709,16 +7850,17 @@ class DateTime {
|
|
|
7709
7850
|
* Returns an ISO 8601-compliant string representation of this DateTime's date component
|
|
7710
7851
|
* @param {Object} opts - options
|
|
7711
7852
|
* @param {string} [opts.format='extended'] - choose between the basic and extended format
|
|
7853
|
+
* @param {string} [opts.precision='day'] - truncate output to desired precision: 'years', 'months', or 'days'.
|
|
7712
7854
|
* @example DateTime.utc(1982, 5, 25).toISODate() //=> '1982-05-25'
|
|
7713
7855
|
* @example DateTime.utc(1982, 5, 25).toISODate({ format: 'basic' }) //=> '19820525'
|
|
7714
|
-
* @
|
|
7856
|
+
* @example DateTime.utc(1982, 5, 25).toISODate({ precision: 'month' }) //=> '1982-05'
|
|
7857
|
+
* @return {string|null}
|
|
7715
7858
|
*/
|
|
7716
|
-
toISODate({ format = "extended" } = {}) {
|
|
7859
|
+
toISODate({ format = "extended", precision = "day" } = {}) {
|
|
7717
7860
|
if (!this.isValid) {
|
|
7718
7861
|
return null;
|
|
7719
7862
|
}
|
|
7720
|
-
|
|
7721
|
-
return toISODate(this, format === "extended");
|
|
7863
|
+
return toISODate(this, format === "extended", normalizeUnit(precision));
|
|
7722
7864
|
}
|
|
7723
7865
|
|
|
7724
7866
|
/**
|
|
@@ -7739,10 +7881,12 @@ class DateTime {
|
|
|
7739
7881
|
* @param {boolean} [opts.extendedZone=true] - add the time zone format extension
|
|
7740
7882
|
* @param {boolean} [opts.includePrefix=false] - include the `T` prefix
|
|
7741
7883
|
* @param {string} [opts.format='extended'] - choose between the basic and extended format
|
|
7884
|
+
* @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.
|
|
7742
7885
|
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime() //=> '07:34:19.361Z'
|
|
7743
7886
|
* @example DateTime.utc().set({ hour: 7, minute: 34, seconds: 0, milliseconds: 0 }).toISOTime({ suppressSeconds: true }) //=> '07:34Z'
|
|
7744
7887
|
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ format: 'basic' }) //=> '073419.361Z'
|
|
7745
7888
|
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ includePrefix: true }) //=> 'T07:34:19.361Z'
|
|
7889
|
+
* @example DateTime.utc().set({ hour: 7, minute: 34, second: 56 }).toISOTime({ precision: 'minute' }) //=> '07:34Z'
|
|
7746
7890
|
* @return {string}
|
|
7747
7891
|
*/
|
|
7748
7892
|
toISOTime({
|
|
@@ -7752,12 +7896,14 @@ class DateTime {
|
|
|
7752
7896
|
includePrefix = false,
|
|
7753
7897
|
extendedZone = false,
|
|
7754
7898
|
format = "extended",
|
|
7899
|
+
precision = "milliseconds",
|
|
7755
7900
|
} = {}) {
|
|
7756
7901
|
if (!this.isValid) {
|
|
7757
7902
|
return null;
|
|
7758
7903
|
}
|
|
7759
7904
|
|
|
7760
|
-
|
|
7905
|
+
precision = normalizeUnit(precision);
|
|
7906
|
+
let c = includePrefix && orderedUnits.indexOf(precision) >= 3 ? "T" : "";
|
|
7761
7907
|
return (
|
|
7762
7908
|
c +
|
|
7763
7909
|
toISOTime(
|
|
@@ -7766,7 +7912,8 @@ class DateTime {
|
|
|
7766
7912
|
suppressSeconds,
|
|
7767
7913
|
suppressMilliseconds,
|
|
7768
7914
|
includeOffset,
|
|
7769
|
-
extendedZone
|
|
7915
|
+
extendedZone,
|
|
7916
|
+
precision
|
|
7770
7917
|
)
|
|
7771
7918
|
);
|
|
7772
7919
|
}
|
|
@@ -7796,7 +7943,7 @@ class DateTime {
|
|
|
7796
7943
|
/**
|
|
7797
7944
|
* Returns a string representation of this DateTime appropriate for use in SQL Date
|
|
7798
7945
|
* @example DateTime.utc(2014, 7, 13).toSQLDate() //=> '2014-07-13'
|
|
7799
|
-
* @return {string}
|
|
7946
|
+
* @return {string|null}
|
|
7800
7947
|
*/
|
|
7801
7948
|
toSQLDate() {
|
|
7802
7949
|
if (!this.isValid) {
|
|
@@ -7891,7 +8038,7 @@ class DateTime {
|
|
|
7891
8038
|
}
|
|
7892
8039
|
|
|
7893
8040
|
/**
|
|
7894
|
-
* Returns the epoch seconds of this DateTime.
|
|
8041
|
+
* Returns the epoch seconds (including milliseconds in the fractional part) of this DateTime.
|
|
7895
8042
|
* @return {number}
|
|
7896
8043
|
*/
|
|
7897
8044
|
toSeconds() {
|
|
@@ -7998,7 +8145,7 @@ class DateTime {
|
|
|
7998
8145
|
/**
|
|
7999
8146
|
* Return an Interval spanning between this DateTime and another DateTime
|
|
8000
8147
|
* @param {DateTime} otherDateTime - the other end point of the Interval
|
|
8001
|
-
* @return {Interval}
|
|
8148
|
+
* @return {Interval|DateTime}
|
|
8002
8149
|
*/
|
|
8003
8150
|
until(otherDateTime) {
|
|
8004
8151
|
return this.isValid ? Interval.fromDateTimes(this, otherDateTime) : this;
|
|
@@ -8044,12 +8191,13 @@ class DateTime {
|
|
|
8044
8191
|
|
|
8045
8192
|
/**
|
|
8046
8193
|
* Returns a string representation of a this time relative to now, such as "in two days". Can only internationalize if your
|
|
8047
|
-
* platform supports Intl.RelativeTimeFormat. Rounds
|
|
8194
|
+
* platform supports Intl.RelativeTimeFormat. Rounds towards zero by default.
|
|
8048
8195
|
* @param {Object} options - options that affect the output
|
|
8049
8196
|
* @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
|
|
8050
8197
|
* @param {string} [options.style="long"] - the style of units, must be "long", "short", or "narrow"
|
|
8051
8198
|
* @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"
|
|
8052
8199
|
* @param {boolean} [options.round=true] - whether to round the numbers in the output.
|
|
8200
|
+
* @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".
|
|
8053
8201
|
* @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.
|
|
8054
8202
|
* @param {string} options.locale - override the locale of this DateTime
|
|
8055
8203
|
* @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this
|
|
@@ -10437,7 +10585,7 @@ class BinaryReader {
|
|
|
10437
10585
|
// ignore
|
|
10438
10586
|
}
|
|
10439
10587
|
break;
|
|
10440
|
-
// @ts-
|
|
10588
|
+
// @ts-ignore TS7029: Fallthrough case in switch -- ignore instead of expect-error for compiler settings without noFallthroughCasesInSwitch: true
|
|
10441
10589
|
case WireType.Bit64:
|
|
10442
10590
|
this.pos += 4;
|
|
10443
10591
|
case WireType.Bit32:
|
|
@@ -10718,7 +10866,6 @@ function around(index, lng, lat, maxResults = Infinity, maxDistance = Infinity,
|
|
|
10718
10866
|
left: 0, // left index in the kd-tree array
|
|
10719
10867
|
right: index.ids.length - 1, // right index
|
|
10720
10868
|
axis: 0, // 0 for longitude axis and 1 for latitude axis
|
|
10721
|
-
dist: 0, // will hold the lower bound of children's distances to the query point
|
|
10722
10869
|
minLng: -180, // bounding box of the node
|
|
10723
10870
|
minLat: -90,
|
|
10724
10871
|
maxLng: 180,
|
|
@@ -11186,7 +11333,7 @@ function sqDist(ax, ay, bx, by) {
|
|
|
11186
11333
|
return dx * dx + dy * dy;
|
|
11187
11334
|
}
|
|
11188
11335
|
|
|
11189
|
-
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);
|
|
11336
|
+
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);
|
|
11190
11337
|
|
|
11191
11338
|
/**
|
|
11192
11339
|
* Generates a list of accent variants for a given term.
|
|
@@ -11228,7 +11375,7 @@ const generateAccentVariants = (term) => {
|
|
|
11228
11375
|
|
|
11229
11376
|
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
11230
11377
|
// versions:
|
|
11231
|
-
// protoc-gen-ts_proto v2.
|
|
11378
|
+
// protoc-gen-ts_proto v2.7.7
|
|
11232
11379
|
// protoc v4.23.4
|
|
11233
11380
|
// source: src/stops/proto/stops.proto
|
|
11234
11381
|
/* eslint-disable */
|
|
@@ -11325,7 +11472,7 @@ const Stop = {
|
|
|
11325
11472
|
},
|
|
11326
11473
|
decode(input, length) {
|
|
11327
11474
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
11328
|
-
|
|
11475
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
11329
11476
|
const message = createBaseStop();
|
|
11330
11477
|
while (reader.pos < end) {
|
|
11331
11478
|
const tag = reader.uint32();
|
|
@@ -11407,7 +11554,7 @@ const Stop = {
|
|
|
11407
11554
|
sourceStopId: isSet$1(object.sourceStopId) ? globalThis.String(object.sourceStopId) : "",
|
|
11408
11555
|
lat: isSet$1(object.lat) ? globalThis.Number(object.lat) : undefined,
|
|
11409
11556
|
lon: isSet$1(object.lon) ? globalThis.Number(object.lon) : undefined,
|
|
11410
|
-
children: globalThis.Array.isArray(object === null || object ===
|
|
11557
|
+
children: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.children) ? object.children.map((e) => globalThis.Number(e)) : [],
|
|
11411
11558
|
parent: isSet$1(object.parent) ? globalThis.Number(object.parent) : undefined,
|
|
11412
11559
|
locationType: isSet$1(object.locationType) ? locationTypeFromJSON(object.locationType) : 0,
|
|
11413
11560
|
platform: isSet$1(object.platform) ? globalThis.String(object.platform) : undefined,
|
|
@@ -11428,7 +11575,7 @@ const Stop = {
|
|
|
11428
11575
|
if (message.lon !== undefined) {
|
|
11429
11576
|
obj.lon = message.lon;
|
|
11430
11577
|
}
|
|
11431
|
-
if ((_a = message.children) === null || _a ===
|
|
11578
|
+
if ((_a = message.children) === null || _a === void 0 ? void 0 : _a.length) {
|
|
11432
11579
|
obj.children = message.children.map((e) => Math.round(e));
|
|
11433
11580
|
}
|
|
11434
11581
|
if (message.parent !== undefined) {
|
|
@@ -11443,19 +11590,19 @@ const Stop = {
|
|
|
11443
11590
|
return obj;
|
|
11444
11591
|
},
|
|
11445
11592
|
create(base) {
|
|
11446
|
-
return Stop.fromPartial(base !== null && base !==
|
|
11593
|
+
return Stop.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
11447
11594
|
},
|
|
11448
11595
|
fromPartial(object) {
|
|
11449
11596
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
11450
11597
|
const message = createBaseStop();
|
|
11451
|
-
message.name = (_a = object.name) !== null && _a !==
|
|
11452
|
-
message.sourceStopId = (_b = object.sourceStopId) !== null && _b !==
|
|
11453
|
-
message.lat = (_c = object.lat) !== null && _c !==
|
|
11454
|
-
message.lon = (_d = object.lon) !== null && _d !==
|
|
11455
|
-
message.children = ((_e = object.children) === null || _e ===
|
|
11456
|
-
message.parent = (_f = object.parent) !== null && _f !==
|
|
11457
|
-
message.locationType = (_g = object.locationType) !== null && _g !==
|
|
11458
|
-
message.platform = (_h = object.platform) !== null && _h !==
|
|
11598
|
+
message.name = (_a = object.name) !== null && _a !== void 0 ? _a : "";
|
|
11599
|
+
message.sourceStopId = (_b = object.sourceStopId) !== null && _b !== void 0 ? _b : "";
|
|
11600
|
+
message.lat = (_c = object.lat) !== null && _c !== void 0 ? _c : undefined;
|
|
11601
|
+
message.lon = (_d = object.lon) !== null && _d !== void 0 ? _d : undefined;
|
|
11602
|
+
message.children = ((_e = object.children) === null || _e === void 0 ? void 0 : _e.map((e) => e)) || [];
|
|
11603
|
+
message.parent = (_f = object.parent) !== null && _f !== void 0 ? _f : undefined;
|
|
11604
|
+
message.locationType = (_g = object.locationType) !== null && _g !== void 0 ? _g : 0;
|
|
11605
|
+
message.platform = (_h = object.platform) !== null && _h !== void 0 ? _h : undefined;
|
|
11459
11606
|
return message;
|
|
11460
11607
|
},
|
|
11461
11608
|
};
|
|
@@ -11474,7 +11621,7 @@ const StopsMap = {
|
|
|
11474
11621
|
},
|
|
11475
11622
|
decode(input, length) {
|
|
11476
11623
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
11477
|
-
|
|
11624
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
11478
11625
|
const message = createBaseStopsMap();
|
|
11479
11626
|
while (reader.pos < end) {
|
|
11480
11627
|
const tag = reader.uint32();
|
|
@@ -11532,13 +11679,13 @@ const StopsMap = {
|
|
|
11532
11679
|
return obj;
|
|
11533
11680
|
},
|
|
11534
11681
|
create(base) {
|
|
11535
|
-
return StopsMap.fromPartial(base !== null && base !==
|
|
11682
|
+
return StopsMap.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
11536
11683
|
},
|
|
11537
11684
|
fromPartial(object) {
|
|
11538
11685
|
var _a, _b;
|
|
11539
11686
|
const message = createBaseStopsMap();
|
|
11540
|
-
message.version = (_a = object.version) !== null && _a !==
|
|
11541
|
-
message.stops = Object.entries((_b = object.stops) !== null && _b !==
|
|
11687
|
+
message.version = (_a = object.version) !== null && _a !== void 0 ? _a : "";
|
|
11688
|
+
message.stops = Object.entries((_b = object.stops) !== null && _b !== void 0 ? _b : {}).reduce((acc, [key, value]) => {
|
|
11542
11689
|
if (value !== undefined) {
|
|
11543
11690
|
acc[globalThis.Number(key)] = Stop.fromPartial(value);
|
|
11544
11691
|
}
|
|
@@ -11562,7 +11709,7 @@ const StopsMap_StopsEntry = {
|
|
|
11562
11709
|
},
|
|
11563
11710
|
decode(input, length) {
|
|
11564
11711
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
11565
|
-
|
|
11712
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
11566
11713
|
const message = createBaseStopsMap_StopsEntry();
|
|
11567
11714
|
while (reader.pos < end) {
|
|
11568
11715
|
const tag = reader.uint32();
|
|
@@ -11606,12 +11753,12 @@ const StopsMap_StopsEntry = {
|
|
|
11606
11753
|
return obj;
|
|
11607
11754
|
},
|
|
11608
11755
|
create(base) {
|
|
11609
|
-
return StopsMap_StopsEntry.fromPartial(base !== null && base !==
|
|
11756
|
+
return StopsMap_StopsEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
11610
11757
|
},
|
|
11611
11758
|
fromPartial(object) {
|
|
11612
11759
|
var _a;
|
|
11613
11760
|
const message = createBaseStopsMap_StopsEntry();
|
|
11614
|
-
message.key = (_a = object.key) !== null && _a !==
|
|
11761
|
+
message.key = (_a = object.key) !== null && _a !== void 0 ? _a : 0;
|
|
11615
11762
|
message.value = (object.value !== undefined && object.value !== null) ? Stop.fromPartial(object.value) : undefined;
|
|
11616
11763
|
return message;
|
|
11617
11764
|
},
|
|
@@ -11722,7 +11869,7 @@ class StopsIndex {
|
|
|
11722
11869
|
});
|
|
11723
11870
|
const stopsSet = new Map();
|
|
11724
11871
|
for (const [id, stop] of stopsMap.entries()) {
|
|
11725
|
-
const effectiveStopId = (_a = stop.parent) !== null && _a !==
|
|
11872
|
+
const effectiveStopId = (_a = stop.parent) !== null && _a !== void 0 ? _a : id;
|
|
11726
11873
|
if (!stopsSet.has(effectiveStopId)) {
|
|
11727
11874
|
stopsSet.set(effectiveStopId, {
|
|
11728
11875
|
id: effectiveStopId,
|
|
@@ -11753,8 +11900,8 @@ class StopsIndex {
|
|
|
11753
11900
|
/**
|
|
11754
11901
|
* Deserializes a binary representation of the stops.
|
|
11755
11902
|
*
|
|
11756
|
-
* @param
|
|
11757
|
-
* @returns
|
|
11903
|
+
* @param data - The binary data to deserialize.
|
|
11904
|
+
* @returns The deserialized StopFinder.
|
|
11758
11905
|
*/
|
|
11759
11906
|
static fromData(data) {
|
|
11760
11907
|
const reader = new BinaryReader(data);
|
|
@@ -11764,7 +11911,7 @@ class StopsIndex {
|
|
|
11764
11911
|
/**
|
|
11765
11912
|
* Serializes the stops into a binary protobuf.
|
|
11766
11913
|
*
|
|
11767
|
-
* @returns
|
|
11914
|
+
* @returns The serialized binary data.
|
|
11768
11915
|
*/
|
|
11769
11916
|
serialize() {
|
|
11770
11917
|
const protoStopsMap = serializeStopsMap(this.stopsMap);
|
|
@@ -11843,7 +11990,7 @@ class StopsIndex {
|
|
|
11843
11990
|
return [];
|
|
11844
11991
|
}
|
|
11845
11992
|
const equivalentStops = stop.parent
|
|
11846
|
-
? ((_b = (_a = this.stopsMap.get(stop.parent)) === null || _a ===
|
|
11993
|
+
? ((_b = (_a = this.stopsMap.get(stop.parent)) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : [])
|
|
11847
11994
|
: stop.children;
|
|
11848
11995
|
return Array.from(new Set([id, ...equivalentStops])).map((stopId) => this.stopsMap.get(stopId));
|
|
11849
11996
|
}
|
|
@@ -11932,7 +12079,7 @@ class Duration {
|
|
|
11932
12079
|
|
|
11933
12080
|
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
11934
12081
|
// versions:
|
|
11935
|
-
// protoc-gen-ts_proto v2.
|
|
12082
|
+
// protoc-gen-ts_proto v2.7.7
|
|
11936
12083
|
// protoc v4.23.4
|
|
11937
12084
|
// source: src/timetable/proto/timetable.proto
|
|
11938
12085
|
/* eslint-disable */
|
|
@@ -12066,7 +12213,7 @@ function createBaseRoute() {
|
|
|
12066
12213
|
serviceRouteId: "",
|
|
12067
12214
|
};
|
|
12068
12215
|
}
|
|
12069
|
-
const Route = {
|
|
12216
|
+
const Route$1 = {
|
|
12070
12217
|
encode(message, writer = new BinaryWriter()) {
|
|
12071
12218
|
if (message.stopTimes.length !== 0) {
|
|
12072
12219
|
writer.uint32(10).bytes(message.stopTimes);
|
|
@@ -12084,7 +12231,7 @@ const Route = {
|
|
|
12084
12231
|
},
|
|
12085
12232
|
decode(input, length) {
|
|
12086
12233
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12087
|
-
|
|
12234
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12088
12235
|
const message = createBaseRoute();
|
|
12089
12236
|
while (reader.pos < end) {
|
|
12090
12237
|
const tag = reader.uint32();
|
|
@@ -12152,15 +12299,15 @@ const Route = {
|
|
|
12152
12299
|
return obj;
|
|
12153
12300
|
},
|
|
12154
12301
|
create(base) {
|
|
12155
|
-
return Route.fromPartial(base !== null && base !==
|
|
12302
|
+
return Route$1.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12156
12303
|
},
|
|
12157
12304
|
fromPartial(object) {
|
|
12158
12305
|
var _a, _b, _c, _d;
|
|
12159
12306
|
const message = createBaseRoute();
|
|
12160
|
-
message.stopTimes = (_a = object.stopTimes) !== null && _a !==
|
|
12161
|
-
message.pickUpDropOffTypes = (_b = object.pickUpDropOffTypes) !== null && _b !==
|
|
12162
|
-
message.stops = (_c = object.stops) !== null && _c !==
|
|
12163
|
-
message.serviceRouteId = (_d = object.serviceRouteId) !== null && _d !==
|
|
12307
|
+
message.stopTimes = (_a = object.stopTimes) !== null && _a !== void 0 ? _a : new Uint8Array(0);
|
|
12308
|
+
message.pickUpDropOffTypes = (_b = object.pickUpDropOffTypes) !== null && _b !== void 0 ? _b : new Uint8Array(0);
|
|
12309
|
+
message.stops = (_c = object.stops) !== null && _c !== void 0 ? _c : new Uint8Array(0);
|
|
12310
|
+
message.serviceRouteId = (_d = object.serviceRouteId) !== null && _d !== void 0 ? _d : "";
|
|
12164
12311
|
return message;
|
|
12165
12312
|
},
|
|
12166
12313
|
};
|
|
@@ -12176,7 +12323,7 @@ const RoutesAdjacency = {
|
|
|
12176
12323
|
},
|
|
12177
12324
|
decode(input, length) {
|
|
12178
12325
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12179
|
-
|
|
12326
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12180
12327
|
const message = createBaseRoutesAdjacency();
|
|
12181
12328
|
while (reader.pos < end) {
|
|
12182
12329
|
const tag = reader.uint32();
|
|
@@ -12203,7 +12350,7 @@ const RoutesAdjacency = {
|
|
|
12203
12350
|
return {
|
|
12204
12351
|
routes: isObject(object.routes)
|
|
12205
12352
|
? Object.entries(object.routes).reduce((acc, [key, value]) => {
|
|
12206
|
-
acc[key] = Route.fromJSON(value);
|
|
12353
|
+
acc[key] = Route$1.fromJSON(value);
|
|
12207
12354
|
return acc;
|
|
12208
12355
|
}, {})
|
|
12209
12356
|
: {},
|
|
@@ -12216,21 +12363,21 @@ const RoutesAdjacency = {
|
|
|
12216
12363
|
if (entries.length > 0) {
|
|
12217
12364
|
obj.routes = {};
|
|
12218
12365
|
entries.forEach(([k, v]) => {
|
|
12219
|
-
obj.routes[k] = Route.toJSON(v);
|
|
12366
|
+
obj.routes[k] = Route$1.toJSON(v);
|
|
12220
12367
|
});
|
|
12221
12368
|
}
|
|
12222
12369
|
}
|
|
12223
12370
|
return obj;
|
|
12224
12371
|
},
|
|
12225
12372
|
create(base) {
|
|
12226
|
-
return RoutesAdjacency.fromPartial(base !== null && base !==
|
|
12373
|
+
return RoutesAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12227
12374
|
},
|
|
12228
12375
|
fromPartial(object) {
|
|
12229
12376
|
var _a;
|
|
12230
12377
|
const message = createBaseRoutesAdjacency();
|
|
12231
|
-
message.routes = Object.entries((_a = object.routes) !== null && _a !==
|
|
12378
|
+
message.routes = Object.entries((_a = object.routes) !== null && _a !== void 0 ? _a : {}).reduce((acc, [key, value]) => {
|
|
12232
12379
|
if (value !== undefined) {
|
|
12233
|
-
acc[key] = Route.fromPartial(value);
|
|
12380
|
+
acc[key] = Route$1.fromPartial(value);
|
|
12234
12381
|
}
|
|
12235
12382
|
return acc;
|
|
12236
12383
|
}, {});
|
|
@@ -12246,13 +12393,13 @@ const RoutesAdjacency_RoutesEntry = {
|
|
|
12246
12393
|
writer.uint32(10).string(message.key);
|
|
12247
12394
|
}
|
|
12248
12395
|
if (message.value !== undefined) {
|
|
12249
|
-
Route.encode(message.value, writer.uint32(18).fork()).join();
|
|
12396
|
+
Route$1.encode(message.value, writer.uint32(18).fork()).join();
|
|
12250
12397
|
}
|
|
12251
12398
|
return writer;
|
|
12252
12399
|
},
|
|
12253
12400
|
decode(input, length) {
|
|
12254
12401
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12255
|
-
|
|
12402
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12256
12403
|
const message = createBaseRoutesAdjacency_RoutesEntry();
|
|
12257
12404
|
while (reader.pos < end) {
|
|
12258
12405
|
const tag = reader.uint32();
|
|
@@ -12268,7 +12415,7 @@ const RoutesAdjacency_RoutesEntry = {
|
|
|
12268
12415
|
if (tag !== 18) {
|
|
12269
12416
|
break;
|
|
12270
12417
|
}
|
|
12271
|
-
message.value = Route.decode(reader, reader.uint32());
|
|
12418
|
+
message.value = Route$1.decode(reader, reader.uint32());
|
|
12272
12419
|
continue;
|
|
12273
12420
|
}
|
|
12274
12421
|
}
|
|
@@ -12282,7 +12429,7 @@ const RoutesAdjacency_RoutesEntry = {
|
|
|
12282
12429
|
fromJSON(object) {
|
|
12283
12430
|
return {
|
|
12284
12431
|
key: isSet(object.key) ? globalThis.String(object.key) : "",
|
|
12285
|
-
value: isSet(object.value) ? Route.fromJSON(object.value) : undefined,
|
|
12432
|
+
value: isSet(object.value) ? Route$1.fromJSON(object.value) : undefined,
|
|
12286
12433
|
};
|
|
12287
12434
|
},
|
|
12288
12435
|
toJSON(message) {
|
|
@@ -12291,18 +12438,18 @@ const RoutesAdjacency_RoutesEntry = {
|
|
|
12291
12438
|
obj.key = message.key;
|
|
12292
12439
|
}
|
|
12293
12440
|
if (message.value !== undefined) {
|
|
12294
|
-
obj.value = Route.toJSON(message.value);
|
|
12441
|
+
obj.value = Route$1.toJSON(message.value);
|
|
12295
12442
|
}
|
|
12296
12443
|
return obj;
|
|
12297
12444
|
},
|
|
12298
12445
|
create(base) {
|
|
12299
|
-
return RoutesAdjacency_RoutesEntry.fromPartial(base !== null && base !==
|
|
12446
|
+
return RoutesAdjacency_RoutesEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12300
12447
|
},
|
|
12301
12448
|
fromPartial(object) {
|
|
12302
12449
|
var _a;
|
|
12303
12450
|
const message = createBaseRoutesAdjacency_RoutesEntry();
|
|
12304
|
-
message.key = (_a = object.key) !== null && _a !==
|
|
12305
|
-
message.value = (object.value !== undefined && object.value !== null) ? Route.fromPartial(object.value) : undefined;
|
|
12451
|
+
message.key = (_a = object.key) !== null && _a !== void 0 ? _a : "";
|
|
12452
|
+
message.value = (object.value !== undefined && object.value !== null) ? Route$1.fromPartial(object.value) : undefined;
|
|
12306
12453
|
return message;
|
|
12307
12454
|
},
|
|
12308
12455
|
};
|
|
@@ -12324,7 +12471,7 @@ const Transfer = {
|
|
|
12324
12471
|
},
|
|
12325
12472
|
decode(input, length) {
|
|
12326
12473
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12327
|
-
|
|
12474
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12328
12475
|
const message = createBaseTransfer();
|
|
12329
12476
|
while (reader.pos < end) {
|
|
12330
12477
|
const tag = reader.uint32();
|
|
@@ -12379,14 +12526,14 @@ const Transfer = {
|
|
|
12379
12526
|
return obj;
|
|
12380
12527
|
},
|
|
12381
12528
|
create(base) {
|
|
12382
|
-
return Transfer.fromPartial(base !== null && base !==
|
|
12529
|
+
return Transfer.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12383
12530
|
},
|
|
12384
12531
|
fromPartial(object) {
|
|
12385
12532
|
var _a, _b, _c;
|
|
12386
12533
|
const message = createBaseTransfer();
|
|
12387
|
-
message.destination = (_a = object.destination) !== null && _a !==
|
|
12388
|
-
message.type = (_b = object.type) !== null && _b !==
|
|
12389
|
-
message.minTransferTime = (_c = object.minTransferTime) !== null && _c !==
|
|
12534
|
+
message.destination = (_a = object.destination) !== null && _a !== void 0 ? _a : 0;
|
|
12535
|
+
message.type = (_b = object.type) !== null && _b !== void 0 ? _b : 0;
|
|
12536
|
+
message.minTransferTime = (_c = object.minTransferTime) !== null && _c !== void 0 ? _c : undefined;
|
|
12390
12537
|
return message;
|
|
12391
12538
|
},
|
|
12392
12539
|
};
|
|
@@ -12402,7 +12549,7 @@ const StopsAdjacency = {
|
|
|
12402
12549
|
},
|
|
12403
12550
|
decode(input, length) {
|
|
12404
12551
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12405
|
-
|
|
12552
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12406
12553
|
const message = createBaseStopsAdjacency();
|
|
12407
12554
|
while (reader.pos < end) {
|
|
12408
12555
|
const tag = reader.uint32();
|
|
@@ -12449,12 +12596,12 @@ const StopsAdjacency = {
|
|
|
12449
12596
|
return obj;
|
|
12450
12597
|
},
|
|
12451
12598
|
create(base) {
|
|
12452
|
-
return StopsAdjacency.fromPartial(base !== null && base !==
|
|
12599
|
+
return StopsAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12453
12600
|
},
|
|
12454
12601
|
fromPartial(object) {
|
|
12455
12602
|
var _a;
|
|
12456
12603
|
const message = createBaseStopsAdjacency();
|
|
12457
|
-
message.stops = Object.entries((_a = object.stops) !== null && _a !==
|
|
12604
|
+
message.stops = Object.entries((_a = object.stops) !== null && _a !== void 0 ? _a : {}).reduce((acc, [key, value]) => {
|
|
12458
12605
|
if (value !== undefined) {
|
|
12459
12606
|
acc[key] = StopsAdjacency_StopAdjacency.fromPartial(value);
|
|
12460
12607
|
}
|
|
@@ -12478,7 +12625,7 @@ const StopsAdjacency_StopAdjacency = {
|
|
|
12478
12625
|
},
|
|
12479
12626
|
decode(input, length) {
|
|
12480
12627
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12481
|
-
|
|
12628
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12482
12629
|
const message = createBaseStopsAdjacency_StopAdjacency();
|
|
12483
12630
|
while (reader.pos < end) {
|
|
12484
12631
|
const tag = reader.uint32();
|
|
@@ -12507,31 +12654,31 @@ const StopsAdjacency_StopAdjacency = {
|
|
|
12507
12654
|
},
|
|
12508
12655
|
fromJSON(object) {
|
|
12509
12656
|
return {
|
|
12510
|
-
transfers: globalThis.Array.isArray(object === null || object ===
|
|
12657
|
+
transfers: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.transfers)
|
|
12511
12658
|
? object.transfers.map((e) => Transfer.fromJSON(e))
|
|
12512
12659
|
: [],
|
|
12513
|
-
routes: globalThis.Array.isArray(object === null || object ===
|
|
12660
|
+
routes: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.routes) ? object.routes.map((e) => globalThis.String(e)) : [],
|
|
12514
12661
|
};
|
|
12515
12662
|
},
|
|
12516
12663
|
toJSON(message) {
|
|
12517
12664
|
var _a, _b;
|
|
12518
12665
|
const obj = {};
|
|
12519
|
-
if ((_a = message.transfers) === null || _a ===
|
|
12666
|
+
if ((_a = message.transfers) === null || _a === void 0 ? void 0 : _a.length) {
|
|
12520
12667
|
obj.transfers = message.transfers.map((e) => Transfer.toJSON(e));
|
|
12521
12668
|
}
|
|
12522
|
-
if ((_b = message.routes) === null || _b ===
|
|
12669
|
+
if ((_b = message.routes) === null || _b === void 0 ? void 0 : _b.length) {
|
|
12523
12670
|
obj.routes = message.routes;
|
|
12524
12671
|
}
|
|
12525
12672
|
return obj;
|
|
12526
12673
|
},
|
|
12527
12674
|
create(base) {
|
|
12528
|
-
return StopsAdjacency_StopAdjacency.fromPartial(base !== null && base !==
|
|
12675
|
+
return StopsAdjacency_StopAdjacency.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12529
12676
|
},
|
|
12530
12677
|
fromPartial(object) {
|
|
12531
12678
|
var _a, _b;
|
|
12532
12679
|
const message = createBaseStopsAdjacency_StopAdjacency();
|
|
12533
|
-
message.transfers = ((_a = object.transfers) === null || _a ===
|
|
12534
|
-
message.routes = ((_b = object.routes) === null || _b ===
|
|
12680
|
+
message.transfers = ((_a = object.transfers) === null || _a === void 0 ? void 0 : _a.map((e) => Transfer.fromPartial(e))) || [];
|
|
12681
|
+
message.routes = ((_b = object.routes) === null || _b === void 0 ? void 0 : _b.map((e) => e)) || [];
|
|
12535
12682
|
return message;
|
|
12536
12683
|
},
|
|
12537
12684
|
};
|
|
@@ -12550,7 +12697,7 @@ const StopsAdjacency_StopsEntry = {
|
|
|
12550
12697
|
},
|
|
12551
12698
|
decode(input, length) {
|
|
12552
12699
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12553
|
-
|
|
12700
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12554
12701
|
const message = createBaseStopsAdjacency_StopsEntry();
|
|
12555
12702
|
while (reader.pos < end) {
|
|
12556
12703
|
const tag = reader.uint32();
|
|
@@ -12594,12 +12741,12 @@ const StopsAdjacency_StopsEntry = {
|
|
|
12594
12741
|
return obj;
|
|
12595
12742
|
},
|
|
12596
12743
|
create(base) {
|
|
12597
|
-
return StopsAdjacency_StopsEntry.fromPartial(base !== null && base !==
|
|
12744
|
+
return StopsAdjacency_StopsEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12598
12745
|
},
|
|
12599
12746
|
fromPartial(object) {
|
|
12600
12747
|
var _a;
|
|
12601
12748
|
const message = createBaseStopsAdjacency_StopsEntry();
|
|
12602
|
-
message.key = (_a = object.key) !== null && _a !==
|
|
12749
|
+
message.key = (_a = object.key) !== null && _a !== void 0 ? _a : "";
|
|
12603
12750
|
message.value = (object.value !== undefined && object.value !== null)
|
|
12604
12751
|
? StopsAdjacency_StopAdjacency.fromPartial(object.value)
|
|
12605
12752
|
: undefined;
|
|
@@ -12621,7 +12768,7 @@ const ServiceRoute = {
|
|
|
12621
12768
|
},
|
|
12622
12769
|
decode(input, length) {
|
|
12623
12770
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12624
|
-
|
|
12771
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12625
12772
|
const message = createBaseServiceRoute();
|
|
12626
12773
|
while (reader.pos < end) {
|
|
12627
12774
|
const tag = reader.uint32();
|
|
@@ -12665,13 +12812,13 @@ const ServiceRoute = {
|
|
|
12665
12812
|
return obj;
|
|
12666
12813
|
},
|
|
12667
12814
|
create(base) {
|
|
12668
|
-
return ServiceRoute.fromPartial(base !== null && base !==
|
|
12815
|
+
return ServiceRoute.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12669
12816
|
},
|
|
12670
12817
|
fromPartial(object) {
|
|
12671
12818
|
var _a, _b;
|
|
12672
12819
|
const message = createBaseServiceRoute();
|
|
12673
|
-
message.type = (_a = object.type) !== null && _a !==
|
|
12674
|
-
message.name = (_b = object.name) !== null && _b !==
|
|
12820
|
+
message.type = (_a = object.type) !== null && _a !== void 0 ? _a : 0;
|
|
12821
|
+
message.name = (_b = object.name) !== null && _b !== void 0 ? _b : "";
|
|
12675
12822
|
return message;
|
|
12676
12823
|
},
|
|
12677
12824
|
};
|
|
@@ -12687,7 +12834,7 @@ const ServiceRoutesMap = {
|
|
|
12687
12834
|
},
|
|
12688
12835
|
decode(input, length) {
|
|
12689
12836
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12690
|
-
|
|
12837
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12691
12838
|
const message = createBaseServiceRoutesMap();
|
|
12692
12839
|
while (reader.pos < end) {
|
|
12693
12840
|
const tag = reader.uint32();
|
|
@@ -12734,12 +12881,12 @@ const ServiceRoutesMap = {
|
|
|
12734
12881
|
return obj;
|
|
12735
12882
|
},
|
|
12736
12883
|
create(base) {
|
|
12737
|
-
return ServiceRoutesMap.fromPartial(base !== null && base !==
|
|
12884
|
+
return ServiceRoutesMap.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12738
12885
|
},
|
|
12739
12886
|
fromPartial(object) {
|
|
12740
12887
|
var _a;
|
|
12741
12888
|
const message = createBaseServiceRoutesMap();
|
|
12742
|
-
message.routes = Object.entries((_a = object.routes) !== null && _a !==
|
|
12889
|
+
message.routes = Object.entries((_a = object.routes) !== null && _a !== void 0 ? _a : {}).reduce((acc, [key, value]) => {
|
|
12743
12890
|
if (value !== undefined) {
|
|
12744
12891
|
acc[key] = ServiceRoute.fromPartial(value);
|
|
12745
12892
|
}
|
|
@@ -12763,7 +12910,7 @@ const ServiceRoutesMap_RoutesEntry = {
|
|
|
12763
12910
|
},
|
|
12764
12911
|
decode(input, length) {
|
|
12765
12912
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12766
|
-
|
|
12913
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12767
12914
|
const message = createBaseServiceRoutesMap_RoutesEntry();
|
|
12768
12915
|
while (reader.pos < end) {
|
|
12769
12916
|
const tag = reader.uint32();
|
|
@@ -12807,12 +12954,12 @@ const ServiceRoutesMap_RoutesEntry = {
|
|
|
12807
12954
|
return obj;
|
|
12808
12955
|
},
|
|
12809
12956
|
create(base) {
|
|
12810
|
-
return ServiceRoutesMap_RoutesEntry.fromPartial(base !== null && base !==
|
|
12957
|
+
return ServiceRoutesMap_RoutesEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12811
12958
|
},
|
|
12812
12959
|
fromPartial(object) {
|
|
12813
12960
|
var _a;
|
|
12814
12961
|
const message = createBaseServiceRoutesMap_RoutesEntry();
|
|
12815
|
-
message.key = (_a = object.key) !== null && _a !==
|
|
12962
|
+
message.key = (_a = object.key) !== null && _a !== void 0 ? _a : "";
|
|
12816
12963
|
message.value = (object.value !== undefined && object.value !== null)
|
|
12817
12964
|
? ServiceRoute.fromPartial(object.value)
|
|
12818
12965
|
: undefined;
|
|
@@ -12840,7 +12987,7 @@ const Timetable$1 = {
|
|
|
12840
12987
|
},
|
|
12841
12988
|
decode(input, length) {
|
|
12842
12989
|
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
|
12843
|
-
|
|
12990
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
12844
12991
|
const message = createBaseTimetable();
|
|
12845
12992
|
while (reader.pos < end) {
|
|
12846
12993
|
const tag = reader.uint32();
|
|
@@ -12906,12 +13053,12 @@ const Timetable$1 = {
|
|
|
12906
13053
|
return obj;
|
|
12907
13054
|
},
|
|
12908
13055
|
create(base) {
|
|
12909
|
-
return Timetable$1.fromPartial(base !== null && base !==
|
|
13056
|
+
return Timetable$1.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
12910
13057
|
},
|
|
12911
13058
|
fromPartial(object) {
|
|
12912
13059
|
var _a;
|
|
12913
13060
|
const message = createBaseTimetable();
|
|
12914
|
-
message.version = (_a = object.version) !== null && _a !==
|
|
13061
|
+
message.version = (_a = object.version) !== null && _a !== void 0 ? _a : "";
|
|
12915
13062
|
message.stopsAdjacency = (object.stopsAdjacency !== undefined && object.stopsAdjacency !== null)
|
|
12916
13063
|
? StopsAdjacency.fromPartial(object.stopsAdjacency)
|
|
12917
13064
|
: undefined;
|
|
@@ -12956,119 +13103,555 @@ function isSet(value) {
|
|
|
12956
13103
|
return value !== null && value !== undefined;
|
|
12957
13104
|
}
|
|
12958
13105
|
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
|
|
12962
|
-
|
|
12963
|
-
|
|
12964
|
-
|
|
12965
|
-
|
|
12966
|
-
|
|
12967
|
-
|
|
12968
|
-
|
|
13106
|
+
/**
|
|
13107
|
+
* A class representing a time as minutes since midnight.
|
|
13108
|
+
*/
|
|
13109
|
+
class Time {
|
|
13110
|
+
/**
|
|
13111
|
+
* Gets the infinity time as a Time instance.
|
|
13112
|
+
* This represents a time that is conceptually beyond any real possible time.
|
|
13113
|
+
*
|
|
13114
|
+
* @returns A Time instance representing an "infinity" time.
|
|
13115
|
+
*/
|
|
13116
|
+
static infinity() {
|
|
13117
|
+
return new Time(Number.MAX_SAFE_INTEGER);
|
|
12969
13118
|
}
|
|
12970
|
-
|
|
12971
|
-
|
|
12972
|
-
|
|
12973
|
-
|
|
12974
|
-
|
|
12975
|
-
|
|
13119
|
+
/**
|
|
13120
|
+
* Gets the midnight time as a Time instance.
|
|
13121
|
+
*
|
|
13122
|
+
* @returns A Time instance representing midnight.
|
|
13123
|
+
*/
|
|
13124
|
+
static origin() {
|
|
13125
|
+
return new Time(0);
|
|
12976
13126
|
}
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
function bytesToUint32Array(bytes) {
|
|
12980
|
-
if (bytes.byteLength % 4 !== 0) {
|
|
12981
|
-
throw new Error('Byte array length must be a multiple of 4 to convert to Uint32Array');
|
|
13127
|
+
constructor(minutes) {
|
|
13128
|
+
this.minutesSinceMidnight = minutes;
|
|
12982
13129
|
}
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
13130
|
+
/**
|
|
13131
|
+
* Creates a Time instance from the number of minutes since midnight.
|
|
13132
|
+
*
|
|
13133
|
+
* @param minutes - The number of minutes since midnight.
|
|
13134
|
+
* @returns A Time instance representing the specified time.
|
|
13135
|
+
*/
|
|
13136
|
+
static fromMinutes(minutes) {
|
|
13137
|
+
return new Time(minutes);
|
|
12986
13138
|
}
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
13139
|
+
/**
|
|
13140
|
+
* Creates a Time instance from hours, minutes, and seconds.
|
|
13141
|
+
* Rounds to the closest minute as times are represented in minutes from midnight.
|
|
13142
|
+
*
|
|
13143
|
+
* @param hours - The hours component of the time.
|
|
13144
|
+
* @param minutes - The minutes component of the time.
|
|
13145
|
+
* @param seconds - The seconds component of the time.
|
|
13146
|
+
* @returns A Time instance representing the specified time.
|
|
13147
|
+
*/
|
|
13148
|
+
static fromHMS(hours, minutes, seconds) {
|
|
13149
|
+
if (hours < 0 ||
|
|
13150
|
+
minutes < 0 ||
|
|
13151
|
+
seconds < 0 ||
|
|
13152
|
+
minutes >= 60 ||
|
|
13153
|
+
seconds >= 60) {
|
|
13154
|
+
throw new Error('Invalid time. Ensure hours, minutes, and seconds are valid values.');
|
|
13155
|
+
}
|
|
13156
|
+
const totalSeconds = seconds + 60 * minutes + 3600 * hours;
|
|
13157
|
+
const roundedMinutes = Math.round(totalSeconds / 60);
|
|
13158
|
+
return new Time(roundedMinutes);
|
|
12992
13159
|
}
|
|
12993
|
-
|
|
12994
|
-
|
|
12995
|
-
|
|
12996
|
-
|
|
12997
|
-
|
|
13160
|
+
/**
|
|
13161
|
+
* Creates a Time instance from hours, minutes.
|
|
13162
|
+
*
|
|
13163
|
+
* @param hours - The hours component of the time.
|
|
13164
|
+
* @param minutes - The minutes component of the time.
|
|
13165
|
+
* @returns A Time instance representing the specified time.
|
|
13166
|
+
*/
|
|
13167
|
+
static fromHM(hours, minutes) {
|
|
13168
|
+
if (hours < 0 || minutes < 0 || minutes >= 60) {
|
|
13169
|
+
throw new Error('Invalid time. Ensure hours and minutes are valid values.');
|
|
13170
|
+
}
|
|
13171
|
+
return new Time(minutes + hours * 60);
|
|
12998
13172
|
}
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
|
|
13004
|
-
|
|
13173
|
+
/**
|
|
13174
|
+
* Parses a JavaScript Date object and creates a Time instance.
|
|
13175
|
+
*
|
|
13176
|
+
* @param date - A JavaScript Date object representing the time.
|
|
13177
|
+
* @returns A Time instance representing the parsed time.
|
|
13178
|
+
*/
|
|
13179
|
+
static fromDate(date) {
|
|
13180
|
+
const hours = date.getHours();
|
|
13181
|
+
const minutes = date.getMinutes();
|
|
13182
|
+
const seconds = date.getSeconds();
|
|
13183
|
+
return Time.fromHMS(hours, minutes, seconds);
|
|
13005
13184
|
}
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13185
|
+
/**
|
|
13186
|
+
* Parses a time string in the format "HH:MM:SS" or "HH:MM" and creates a Time instance.
|
|
13187
|
+
*
|
|
13188
|
+
* @param timeStr - A string representing the time in "HH:MM:SS" or "HH:MM" format.
|
|
13189
|
+
* @returns A Time instance representing the parsed time.
|
|
13190
|
+
*/
|
|
13191
|
+
static fromString(timeStr) {
|
|
13192
|
+
const [hoursStr, minutesStr, secondsStr] = timeStr.split(':');
|
|
13193
|
+
if (hoursStr === undefined ||
|
|
13194
|
+
minutesStr === undefined ||
|
|
13195
|
+
hoursStr.trim() === '' ||
|
|
13196
|
+
minutesStr.trim() === '' ||
|
|
13197
|
+
isNaN(Number(hoursStr)) ||
|
|
13198
|
+
isNaN(Number(minutesStr)) ||
|
|
13199
|
+
(secondsStr !== undefined &&
|
|
13200
|
+
(secondsStr.trim() === '' || isNaN(Number(secondsStr))))) {
|
|
13201
|
+
throw new Error('Input string must be in the format "HH:MM:SS" or "HH:MM".');
|
|
13202
|
+
}
|
|
13203
|
+
const hours = parseInt(hoursStr, 10);
|
|
13204
|
+
const minutes = parseInt(minutesStr, 10);
|
|
13205
|
+
const seconds = secondsStr !== undefined ? parseInt(secondsStr, 10) : 0;
|
|
13206
|
+
return Time.fromHMS(hours, minutes, seconds);
|
|
13011
13207
|
}
|
|
13012
|
-
|
|
13013
|
-
|
|
13014
|
-
|
|
13208
|
+
/**
|
|
13209
|
+
* Converts the Time instance to a string in "HH:MM:SS" format.
|
|
13210
|
+
*
|
|
13211
|
+
* @returns A string representing the time.
|
|
13212
|
+
*/
|
|
13213
|
+
toString() {
|
|
13214
|
+
let hours = Math.floor(this.minutesSinceMidnight / 60);
|
|
13215
|
+
const minutes = Math.floor(this.minutesSinceMidnight % 60);
|
|
13216
|
+
if (hours >= 24) {
|
|
13217
|
+
hours = hours % 24;
|
|
13218
|
+
}
|
|
13219
|
+
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
13015
13220
|
}
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
13020
|
-
|
|
13221
|
+
/**
|
|
13222
|
+
* Converts the Time instance to the total number of minutes since midnight, rounded to the closest minute.
|
|
13223
|
+
*
|
|
13224
|
+
* @returns The time in minutes since midnight.
|
|
13225
|
+
*/
|
|
13226
|
+
toMinutes() {
|
|
13227
|
+
return this.minutesSinceMidnight;
|
|
13021
13228
|
}
|
|
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
|
-
|
|
13051
|
-
|
|
13052
|
-
const
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
|
|
13229
|
+
/**
|
|
13230
|
+
* Adds a Duration to the current Time instance and returns a new Time instance.
|
|
13231
|
+
*
|
|
13232
|
+
* @param duration - A Duration instance representing the duration to add.
|
|
13233
|
+
* @returns A new Time instance with the added duration.
|
|
13234
|
+
*/
|
|
13235
|
+
plus(duration) {
|
|
13236
|
+
const totalSeconds = this.minutesSinceMidnight * 60 + duration.toSeconds();
|
|
13237
|
+
return new Time(Math.round(totalSeconds / 60));
|
|
13238
|
+
}
|
|
13239
|
+
/**
|
|
13240
|
+
* Subtracts a Duration from the current Time instance and returns a new Time instance.
|
|
13241
|
+
*
|
|
13242
|
+
* @param duration - A Duration instance representing the duration to subtract.
|
|
13243
|
+
* @returns A new Time instance with the subtracted duration.
|
|
13244
|
+
*/
|
|
13245
|
+
minus(duration) {
|
|
13246
|
+
let totalSeconds = this.minutesSinceMidnight * 60 - duration.toSeconds();
|
|
13247
|
+
if (totalSeconds < 0) {
|
|
13248
|
+
totalSeconds += 24 * 3600; // Adjust for negative time to loop back to previous day
|
|
13249
|
+
}
|
|
13250
|
+
return new Time(Math.round(totalSeconds / 60));
|
|
13251
|
+
}
|
|
13252
|
+
/**
|
|
13253
|
+
* Subtracts another Time instance from the current Time instance and returns the Duration.
|
|
13254
|
+
*
|
|
13255
|
+
* @param otherTime - A Time instance representing the time to subtract.
|
|
13256
|
+
* @returns A Duration instance representing the time difference.
|
|
13257
|
+
*/
|
|
13258
|
+
diff(otherTime) {
|
|
13259
|
+
const totalMinutes = this.minutesSinceMidnight - otherTime.toMinutes();
|
|
13260
|
+
return Duration.fromSeconds(Math.abs(totalMinutes * 60));
|
|
13261
|
+
}
|
|
13262
|
+
/**
|
|
13263
|
+
* Computes the maximum Time instance among the provided Time instances.
|
|
13264
|
+
*
|
|
13265
|
+
* @param times - An array of Time instances to compare.
|
|
13266
|
+
* @returns A Time instance representing the maximum time.
|
|
13267
|
+
*/
|
|
13268
|
+
static max(...times) {
|
|
13269
|
+
if (times.length === 0) {
|
|
13270
|
+
throw new Error('At least one Time instance is required.');
|
|
13271
|
+
}
|
|
13272
|
+
return times.reduce((maxTime, currentTime) => {
|
|
13273
|
+
return currentTime.isAfter(maxTime) ? currentTime : maxTime;
|
|
13274
|
+
});
|
|
13275
|
+
}
|
|
13276
|
+
/**
|
|
13277
|
+
* Computes the minimum Time instance among the provided Time instances.
|
|
13278
|
+
*
|
|
13279
|
+
* @param times - An array of Time instances to compare.
|
|
13280
|
+
* @returns A Time instance representing the minimum time.
|
|
13281
|
+
*/
|
|
13282
|
+
static min(...times) {
|
|
13283
|
+
if (times.length === 0) {
|
|
13284
|
+
throw new Error('At least one Time instance is required.');
|
|
13285
|
+
}
|
|
13286
|
+
return times.reduce((minTime, currentTime) => {
|
|
13287
|
+
return currentTime.isBefore(minTime) ? currentTime : minTime;
|
|
13288
|
+
});
|
|
13289
|
+
}
|
|
13290
|
+
/**
|
|
13291
|
+
* Determines if the current Time instance is after another Time instance.
|
|
13292
|
+
*
|
|
13293
|
+
* @param otherTime - A Time instance to compare against.
|
|
13294
|
+
* @returns True if the current Time instance is after the other Time instance, otherwise false.
|
|
13295
|
+
*/
|
|
13296
|
+
isAfter(otherTime) {
|
|
13297
|
+
return this.minutesSinceMidnight > otherTime.toMinutes();
|
|
13298
|
+
}
|
|
13299
|
+
/**
|
|
13300
|
+
* Determines if the current Time instance is before another Time instance.
|
|
13301
|
+
*
|
|
13302
|
+
* @param otherTime - A Time instance to compare against.
|
|
13303
|
+
* @returns True if the current Time instance is before the other Time instance, otherwise false.
|
|
13304
|
+
*/
|
|
13305
|
+
isBefore(otherTime) {
|
|
13306
|
+
return this.minutesSinceMidnight < otherTime.toMinutes();
|
|
13307
|
+
}
|
|
13308
|
+
/**
|
|
13309
|
+
* Determines if the current Time instance is equal to another Time instance.
|
|
13310
|
+
*
|
|
13311
|
+
* @param otherTime - A Time instance to compare against.
|
|
13312
|
+
* @returns True if the current Time instance is equal to the other Time instance, otherwise false.
|
|
13313
|
+
*/
|
|
13314
|
+
equals(otherTime) {
|
|
13315
|
+
return this.minutesSinceMidnight === otherTime.toMinutes();
|
|
13316
|
+
}
|
|
13317
|
+
}
|
|
13318
|
+
|
|
13319
|
+
const REGULAR = 0;
|
|
13320
|
+
const NOT_AVAILABLE = 1;
|
|
13321
|
+
const MUST_PHONE_AGENCY = 2;
|
|
13322
|
+
const MUST_COORDINATE_WITH_DRIVER = 3;
|
|
13323
|
+
const pickUpDropOffTypeMap = [
|
|
13324
|
+
'REGULAR',
|
|
13325
|
+
'NOT_AVAILABLE',
|
|
13326
|
+
'MUST_PHONE_AGENCY',
|
|
13327
|
+
'MUST_COORDINATE_WITH_DRIVER',
|
|
13328
|
+
];
|
|
13329
|
+
/**
|
|
13330
|
+
* Converts a numerical representation of a pick-up/drop-off type
|
|
13331
|
+
* into its corresponding string representation.
|
|
13332
|
+
*
|
|
13333
|
+
* @param numericalType - The numerical value representing the pick-up/drop-off type.
|
|
13334
|
+
* @returns The corresponding PickUpDropOffType as a string.
|
|
13335
|
+
* @throws An error if the numerical type is invalid.
|
|
13336
|
+
*/
|
|
13337
|
+
const toPickupDropOffType = (numericalType) => {
|
|
13338
|
+
const type = pickUpDropOffTypeMap[numericalType];
|
|
13339
|
+
if (!type) {
|
|
13340
|
+
throw new Error(`Invalid pickup/drop-off type ${numericalType}`);
|
|
13341
|
+
}
|
|
13342
|
+
return type;
|
|
13343
|
+
};
|
|
13344
|
+
/**
|
|
13345
|
+
* A route identifies all trips of a given service route sharing the same list of stops.
|
|
13346
|
+
*/
|
|
13347
|
+
class Route {
|
|
13348
|
+
constructor(stopTimes, pickUpDropOffTypes, stops, serviceRouteId) {
|
|
13349
|
+
this.stopTimes = stopTimes;
|
|
13350
|
+
this.pickUpDropOffTypes = pickUpDropOffTypes;
|
|
13351
|
+
this.stops = stops;
|
|
13352
|
+
this.serviceRouteId = serviceRouteId;
|
|
13353
|
+
this.nbStops = stops.length;
|
|
13354
|
+
this.nbTrips = this.stopTimes.length / (this.stops.length * 2);
|
|
13355
|
+
this.stopIndices = new Map();
|
|
13356
|
+
for (let i = 0; i < stops.length; i++) {
|
|
13357
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13358
|
+
this.stopIndices.set(stops[i], i);
|
|
13359
|
+
}
|
|
13360
|
+
}
|
|
13361
|
+
/**
|
|
13362
|
+
* Serializes the Route into binary arrays.
|
|
13363
|
+
*
|
|
13364
|
+
* @returns The serialized binary data.
|
|
13365
|
+
*/
|
|
13366
|
+
serialize() {
|
|
13367
|
+
return {
|
|
13368
|
+
stopTimes: this.stopTimes,
|
|
13369
|
+
pickUpDropOffTypes: this.pickUpDropOffTypes,
|
|
13370
|
+
stops: this.stops,
|
|
13371
|
+
serviceRouteId: this.serviceRouteId,
|
|
13372
|
+
};
|
|
13373
|
+
}
|
|
13374
|
+
/**
|
|
13375
|
+
* Checks if stop A is before stop B in the route.
|
|
13376
|
+
*
|
|
13377
|
+
* @param stopA - The StopId of the first stop.
|
|
13378
|
+
* @param stopB - The StopId of the second stop.
|
|
13379
|
+
* @returns True if stop A is before stop B, false otherwise.
|
|
13380
|
+
*/
|
|
13381
|
+
isBefore(stopA, stopB) {
|
|
13382
|
+
const stopAIndex = this.stopIndices.get(stopA);
|
|
13383
|
+
if (stopAIndex === undefined) {
|
|
13384
|
+
throw new Error(`Stop index ${stopAIndex} not found in route ${this.serviceRouteId}`);
|
|
13385
|
+
}
|
|
13386
|
+
const stopBIndex = this.stopIndices.get(stopB);
|
|
13387
|
+
if (stopBIndex === undefined) {
|
|
13388
|
+
throw new Error(`Stop index ${stopBIndex} not found in route ${this.serviceRouteId}`);
|
|
13389
|
+
}
|
|
13390
|
+
return stopAIndex < stopBIndex;
|
|
13391
|
+
}
|
|
13392
|
+
/**
|
|
13393
|
+
* Retrieves the number of stops in the route.
|
|
13394
|
+
*
|
|
13395
|
+
* @returns The total number of stops in the route.
|
|
13396
|
+
*/
|
|
13397
|
+
getNbStops() {
|
|
13398
|
+
return this.nbStops;
|
|
13399
|
+
}
|
|
13400
|
+
/**
|
|
13401
|
+
* Finds the ServiceRouteId of the route. It corresponds the identifier
|
|
13402
|
+
* of the service shown to the end user as a route.
|
|
13403
|
+
*
|
|
13404
|
+
* @returns The ServiceRouteId of the route.
|
|
13405
|
+
*/
|
|
13406
|
+
serviceRoute() {
|
|
13407
|
+
return this.serviceRouteId;
|
|
13408
|
+
}
|
|
13409
|
+
/**
|
|
13410
|
+
* Retrieves the arrival time at a specific stop for a given trip.
|
|
13411
|
+
*
|
|
13412
|
+
* @param stopId - The identifier of the stop.
|
|
13413
|
+
* @param tripIndex - The index of the trip.
|
|
13414
|
+
* @returns The arrival time at the specified stop and trip as a Time object.
|
|
13415
|
+
*/
|
|
13416
|
+
arrivalAt(stopId, tripIndex) {
|
|
13417
|
+
const arrivalIndex = (tripIndex * this.stops.length + this.stopIndex(stopId)) * 2;
|
|
13418
|
+
const arrival = this.stopTimes[arrivalIndex];
|
|
13419
|
+
if (arrival === undefined) {
|
|
13420
|
+
throw new Error(`Arrival time not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13421
|
+
}
|
|
13422
|
+
return Time.fromMinutes(arrival);
|
|
13423
|
+
}
|
|
13424
|
+
/**
|
|
13425
|
+
* Retrieves the departure time at a specific stop for a given trip.
|
|
13426
|
+
*
|
|
13427
|
+
* @param stopId - The identifier of the stop.
|
|
13428
|
+
* @param tripIndex - The index of the trip.
|
|
13429
|
+
* @returns The departure time at the specified stop and trip as a Time object.
|
|
13430
|
+
*/
|
|
13431
|
+
departureFrom(stopId, tripIndex) {
|
|
13432
|
+
const departureIndex = (tripIndex * this.stops.length + this.stopIndex(stopId)) * 2 + 1;
|
|
13433
|
+
const departure = this.stopTimes[departureIndex];
|
|
13434
|
+
if (departure === undefined) {
|
|
13435
|
+
throw new Error(`Departure time not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13436
|
+
}
|
|
13437
|
+
return Time.fromMinutes(departure);
|
|
13438
|
+
}
|
|
13439
|
+
/**
|
|
13440
|
+
* Retrieves the pick-up type for a specific stop and trip.
|
|
13441
|
+
*
|
|
13442
|
+
* @param stopId - The identifier of the stop.
|
|
13443
|
+
* @param tripIndex - The index of the trip.
|
|
13444
|
+
* @returns The pick-up type at the specified stop and trip.
|
|
13445
|
+
*/
|
|
13446
|
+
pickUpTypeFrom(stopId, tripIndex) {
|
|
13447
|
+
const pickUpIndex = (tripIndex * this.stops.length + this.stopIndex(stopId)) * 2;
|
|
13448
|
+
const pickUpValue = this.pickUpDropOffTypes[pickUpIndex];
|
|
13449
|
+
if (pickUpValue === undefined) {
|
|
13450
|
+
throw new Error(`Pick up type not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13451
|
+
}
|
|
13452
|
+
return toPickupDropOffType(pickUpValue);
|
|
13453
|
+
}
|
|
13454
|
+
/**
|
|
13455
|
+
* Retrieves the drop-off type for a specific stop and trip.
|
|
13456
|
+
*
|
|
13457
|
+
* @param stopId - The identifier of the stop.
|
|
13458
|
+
* @param tripIndex - The index of the trip.
|
|
13459
|
+
* @returns The drop-off type at the specified stop and trip.
|
|
13460
|
+
*/
|
|
13461
|
+
dropOffTypeAt(stopId, tripIndex) {
|
|
13462
|
+
const dropOffIndex = (tripIndex * this.stops.length + this.stopIndex(stopId)) * 2 + 1;
|
|
13463
|
+
const dropOffValue = this.pickUpDropOffTypes[dropOffIndex];
|
|
13464
|
+
if (dropOffValue === undefined) {
|
|
13465
|
+
throw new Error(`Drop off type not found for stop ${stopId} at trip index ${tripIndex} in route ${this.serviceRouteId}`);
|
|
13466
|
+
}
|
|
13467
|
+
return toPickupDropOffType(dropOffValue);
|
|
13468
|
+
}
|
|
13469
|
+
/**
|
|
13470
|
+
* Iterates over the stops in the route, starting from an optional specified stop.
|
|
13471
|
+
* If no start stop is provided, the iteration begins from the first stop in the route.
|
|
13472
|
+
*
|
|
13473
|
+
* @param [startStopId] - (Optional) The StopId of the stop to start the iteration from.
|
|
13474
|
+
* @returns An IterableIterator of StopIds, starting from the specified stop or the first stop.
|
|
13475
|
+
* @throws An error if the specified start stop is not found in the route.
|
|
13476
|
+
*/
|
|
13477
|
+
stopsIterator(startStopId) {
|
|
13478
|
+
const startIndex = startStopId !== undefined ? this.stopIndices.get(startStopId) : 0;
|
|
13479
|
+
if (startIndex === undefined) {
|
|
13480
|
+
throw new Error(`Start stop ${startStopId} not found in route ${this.serviceRouteId}`);
|
|
13481
|
+
}
|
|
13482
|
+
function* generator(stops, startIndex) {
|
|
13483
|
+
for (let i = startIndex; i < stops.length; i++) {
|
|
13484
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13485
|
+
yield stops[i];
|
|
13486
|
+
}
|
|
13487
|
+
}
|
|
13488
|
+
return generator(this.stops, startIndex);
|
|
13489
|
+
}
|
|
13490
|
+
/**
|
|
13491
|
+
* Finds the earliest trip that can be taken from a specific stop on a given route,
|
|
13492
|
+
* optionally constrained by a latest trip index and a time before which the trip
|
|
13493
|
+
* should not depart.
|
|
13494
|
+
* *
|
|
13495
|
+
* @param stopId - The StopId of the stop where the trip should be found.
|
|
13496
|
+
* @param [after=Time.origin()] - The earliest time after which the trip should depart.
|
|
13497
|
+
* If not provided, searches all available trips.
|
|
13498
|
+
* @param [beforeTrip] - (Optional) The index of the trip before which the search should be constrained.
|
|
13499
|
+
* If not provided, searches all available trips.
|
|
13500
|
+
* @returns The index of the earliest trip meeting the criteria, or undefined if no such trip is found.
|
|
13501
|
+
*/
|
|
13502
|
+
findEarliestTrip(stopId, after = Time.origin(), beforeTrip) {
|
|
13503
|
+
const maxTripIndex = beforeTrip !== undefined
|
|
13504
|
+
? Math.min(beforeTrip - 1, this.nbTrips - 1)
|
|
13505
|
+
: this.nbTrips - 1;
|
|
13506
|
+
if (maxTripIndex < 0) {
|
|
13507
|
+
return undefined;
|
|
13508
|
+
}
|
|
13509
|
+
let earliestTripIndex;
|
|
13510
|
+
let lowTrip = 0;
|
|
13511
|
+
let highTrip = maxTripIndex;
|
|
13512
|
+
while (lowTrip <= highTrip) {
|
|
13513
|
+
const midTrip = Math.floor((lowTrip + highTrip) / 2);
|
|
13514
|
+
const departure = this.departureFrom(stopId, midTrip);
|
|
13515
|
+
const pickUpType = this.pickUpTypeFrom(stopId, midTrip);
|
|
13516
|
+
if ((departure.isAfter(after) || departure.equals(after)) &&
|
|
13517
|
+
pickUpType !== 'NOT_AVAILABLE') {
|
|
13518
|
+
earliestTripIndex = midTrip;
|
|
13519
|
+
highTrip = midTrip - 1;
|
|
13520
|
+
}
|
|
13521
|
+
else {
|
|
13522
|
+
lowTrip = midTrip + 1;
|
|
13523
|
+
}
|
|
13524
|
+
}
|
|
13525
|
+
return earliestTripIndex;
|
|
13526
|
+
}
|
|
13527
|
+
/**
|
|
13528
|
+
* Retrieves the index of a stop within the route.
|
|
13529
|
+
* @param stopId The StopId of the stop to locate in the route.
|
|
13530
|
+
* @returns The index of the stop in the route.
|
|
13531
|
+
*/
|
|
13532
|
+
stopIndex(stopId) {
|
|
13533
|
+
const stopIndex = this.stopIndices.get(stopId);
|
|
13534
|
+
if (stopIndex === undefined) {
|
|
13535
|
+
throw new Error(`Stop index for ${stopId} not found in route ${this.serviceRouteId}`);
|
|
13536
|
+
}
|
|
13537
|
+
return stopIndex;
|
|
13538
|
+
}
|
|
13539
|
+
}
|
|
13540
|
+
|
|
13541
|
+
const isLittleEndian = (() => {
|
|
13542
|
+
const buffer = new ArrayBuffer(4);
|
|
13543
|
+
const view = new DataView(buffer);
|
|
13544
|
+
view.setUint32(0, 0x12345678);
|
|
13545
|
+
return new Uint8Array(buffer)[0] === 0x78;
|
|
13546
|
+
})();
|
|
13547
|
+
const STANDARD_ENDIANNESS = true; // true = little-endian
|
|
13548
|
+
const uint32ArrayToBytes = (array) => {
|
|
13549
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
13550
|
+
return new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
13551
|
+
}
|
|
13552
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13553
|
+
const result = new Uint8Array(array.length * 4);
|
|
13554
|
+
const view = new DataView(result.buffer);
|
|
13555
|
+
for (let i = 0; i < array.length; i++) {
|
|
13556
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13557
|
+
view.setUint32(i * 4, array[i], STANDARD_ENDIANNESS);
|
|
13558
|
+
}
|
|
13559
|
+
return result;
|
|
13560
|
+
};
|
|
13561
|
+
const bytesToUint32Array = (bytes) => {
|
|
13562
|
+
if (bytes.byteLength % 4 !== 0) {
|
|
13563
|
+
throw new Error('Byte array length must be a multiple of 4 to convert to Uint32Array');
|
|
13564
|
+
}
|
|
13565
|
+
// If system endianness matches our standard, we can create a view directly
|
|
13566
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
13567
|
+
return new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4);
|
|
13568
|
+
}
|
|
13569
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13570
|
+
const result = new Uint32Array(bytes.byteLength / 4);
|
|
13571
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13572
|
+
for (let i = 0; i < result.length; i++) {
|
|
13573
|
+
result[i] = view.getUint32(i * 4, STANDARD_ENDIANNESS);
|
|
13574
|
+
}
|
|
13575
|
+
return result;
|
|
13576
|
+
};
|
|
13577
|
+
const uint16ArrayToBytes = (array) => {
|
|
13578
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
13579
|
+
return new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
13580
|
+
}
|
|
13581
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13582
|
+
const result = new Uint8Array(array.length * 2);
|
|
13583
|
+
const view = new DataView(result.buffer);
|
|
13584
|
+
for (let i = 0; i < array.length; i++) {
|
|
13585
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13586
|
+
view.setUint16(i * 2, array[i], STANDARD_ENDIANNESS);
|
|
13587
|
+
}
|
|
13588
|
+
return result;
|
|
13589
|
+
};
|
|
13590
|
+
const bytesToUint16Array = (bytes) => {
|
|
13591
|
+
if (bytes.byteLength % 2 !== 0) {
|
|
13592
|
+
throw new Error('Byte array length must be a multiple of 2 to convert to Uint16Array');
|
|
13593
|
+
}
|
|
13594
|
+
// If system endianness matches our standard, we can create a view directly
|
|
13595
|
+
if (isLittleEndian === STANDARD_ENDIANNESS) {
|
|
13596
|
+
return new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2);
|
|
13597
|
+
}
|
|
13598
|
+
// If endianness doesn't match, we need to swap byte order
|
|
13599
|
+
const result = new Uint16Array(bytes.byteLength / 2);
|
|
13600
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13601
|
+
for (let i = 0; i < result.length; i++) {
|
|
13602
|
+
result[i] = view.getUint16(i * 2, STANDARD_ENDIANNESS);
|
|
13603
|
+
}
|
|
13604
|
+
return result;
|
|
13605
|
+
};
|
|
13606
|
+
const serializeStopsAdjacency = (stopsAdjacency) => {
|
|
13607
|
+
const protoStopsAdjacency = {
|
|
13608
|
+
stops: {},
|
|
13609
|
+
};
|
|
13610
|
+
stopsAdjacency.forEach((value, key) => {
|
|
13611
|
+
protoStopsAdjacency.stops[key] = {
|
|
13612
|
+
transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: serializeTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
|
|
13613
|
+
minTransferTime: transfer.minTransferTime.toSeconds(),
|
|
13614
|
+
})))),
|
|
13615
|
+
routes: value.routes,
|
|
13616
|
+
};
|
|
13617
|
+
});
|
|
13618
|
+
return protoStopsAdjacency;
|
|
13619
|
+
};
|
|
13620
|
+
const serializeRoutesAdjacency = (routesAdjacency) => {
|
|
13621
|
+
const protoRoutesAdjacency = {
|
|
13622
|
+
routes: {},
|
|
13623
|
+
};
|
|
13624
|
+
routesAdjacency.forEach((route, key) => {
|
|
13625
|
+
const routeData = route.serialize();
|
|
13626
|
+
protoRoutesAdjacency.routes[key] = {
|
|
13627
|
+
stopTimes: uint16ArrayToBytes(routeData.stopTimes),
|
|
13628
|
+
pickUpDropOffTypes: routeData.pickUpDropOffTypes,
|
|
13629
|
+
stops: uint32ArrayToBytes(routeData.stops),
|
|
13630
|
+
serviceRouteId: routeData.serviceRouteId,
|
|
13631
|
+
};
|
|
13632
|
+
});
|
|
13633
|
+
return protoRoutesAdjacency;
|
|
13634
|
+
};
|
|
13635
|
+
const serializeServiceRoutesMap = (serviceRoutesMap) => {
|
|
13636
|
+
const protoServiceRoutesMap = {
|
|
13637
|
+
routes: {},
|
|
13638
|
+
};
|
|
13639
|
+
serviceRoutesMap.forEach((value, key) => {
|
|
13640
|
+
protoServiceRoutesMap.routes[key] = {
|
|
13641
|
+
type: serializeRouteType(value.type),
|
|
13642
|
+
name: value.name,
|
|
13643
|
+
};
|
|
13644
|
+
});
|
|
13645
|
+
return protoServiceRoutesMap;
|
|
13646
|
+
};
|
|
13647
|
+
const deserializeStopsAdjacency = (protoStopsAdjacency) => {
|
|
13648
|
+
const stopsAdjacency = new Map();
|
|
13649
|
+
Object.entries(protoStopsAdjacency.stops).forEach(([keyStr, value]) => {
|
|
13650
|
+
const key = parseInt(keyStr, 10);
|
|
13651
|
+
stopsAdjacency.set(key, {
|
|
13652
|
+
transfers: value.transfers.map((transfer) => (Object.assign({ destination: transfer.destination, type: parseTransferType(transfer.type) }, (transfer.minTransferTime !== undefined && {
|
|
13653
|
+
minTransferTime: Duration.fromSeconds(transfer.minTransferTime),
|
|
13654
|
+
})))),
|
|
13072
13655
|
routes: value.routes,
|
|
13073
13656
|
});
|
|
13074
13657
|
});
|
|
@@ -13078,18 +13661,7 @@ const deserializeRoutesAdjacency = (protoRoutesAdjacency) => {
|
|
|
13078
13661
|
const routesAdjacency = new Map();
|
|
13079
13662
|
Object.entries(protoRoutesAdjacency.routes).forEach(([key, value]) => {
|
|
13080
13663
|
const stops = bytesToUint32Array(value.stops);
|
|
13081
|
-
|
|
13082
|
-
for (let i = 0; i < stops.length; i++) {
|
|
13083
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13084
|
-
indices.set(stops[i], i);
|
|
13085
|
-
}
|
|
13086
|
-
routesAdjacency.set(key, {
|
|
13087
|
-
stopTimes: bytesToUint16Array(value.stopTimes),
|
|
13088
|
-
pickUpDropOffTypes: value.pickUpDropOffTypes,
|
|
13089
|
-
stops: stops,
|
|
13090
|
-
stopIndices: indices,
|
|
13091
|
-
serviceRouteId: value.serviceRouteId,
|
|
13092
|
-
});
|
|
13664
|
+
routesAdjacency.set(key, new Route(bytesToUint16Array(value.stopTimes), value.pickUpDropOffTypes, stops, value.serviceRouteId));
|
|
13093
13665
|
});
|
|
13094
13666
|
return routesAdjacency;
|
|
13095
13667
|
};
|
|
@@ -13181,195 +13753,7 @@ const serializeRouteType = (type) => {
|
|
|
13181
13753
|
}
|
|
13182
13754
|
};
|
|
13183
13755
|
|
|
13184
|
-
|
|
13185
|
-
* A class representing a time as minutes since midnight.
|
|
13186
|
-
*/
|
|
13187
|
-
class Time {
|
|
13188
|
-
/**
|
|
13189
|
-
* Gets the infinity time as a Time instance.
|
|
13190
|
-
* This represents a time that is conceptually beyond any real possible time.
|
|
13191
|
-
*
|
|
13192
|
-
* @returns A Time instance representing an "infinity" time.
|
|
13193
|
-
*/
|
|
13194
|
-
static infinity() {
|
|
13195
|
-
return new Time(Number.MAX_SAFE_INTEGER);
|
|
13196
|
-
}
|
|
13197
|
-
/**
|
|
13198
|
-
* Gets the midnight time as a Time instance.
|
|
13199
|
-
*
|
|
13200
|
-
* @returns A Time instance representing midnight.
|
|
13201
|
-
*/
|
|
13202
|
-
static origin() {
|
|
13203
|
-
return new Time(0);
|
|
13204
|
-
}
|
|
13205
|
-
constructor(minutes) {
|
|
13206
|
-
this.minutesSinceMidnight = minutes;
|
|
13207
|
-
}
|
|
13208
|
-
/**
|
|
13209
|
-
* Creates a Time instance from the number of minutes since midnight.
|
|
13210
|
-
*
|
|
13211
|
-
* @param minutes - The number of minutes since midnight.
|
|
13212
|
-
* @returns A Time instance representing the specified time.
|
|
13213
|
-
*/
|
|
13214
|
-
static fromMinutes(minutes) {
|
|
13215
|
-
return new Time(minutes);
|
|
13216
|
-
}
|
|
13217
|
-
/**
|
|
13218
|
-
* Creates a Time instance from hours, minutes, and seconds.
|
|
13219
|
-
* Rounds to the closest minute as times are represented in minutes from midnight.
|
|
13220
|
-
*
|
|
13221
|
-
* @param hours - The hours component of the time.
|
|
13222
|
-
* @param minutes - The minutes component of the time.
|
|
13223
|
-
* @param seconds - The seconds component of the time.
|
|
13224
|
-
* @returns A Time instance representing the specified time.
|
|
13225
|
-
*/
|
|
13226
|
-
static fromHMS(hours, minutes, seconds) {
|
|
13227
|
-
if (hours < 0 ||
|
|
13228
|
-
minutes < 0 ||
|
|
13229
|
-
seconds < 0 ||
|
|
13230
|
-
minutes >= 60 ||
|
|
13231
|
-
seconds >= 60) {
|
|
13232
|
-
throw new Error('Invalid time. Ensure hours, minutes, and seconds are valid values.');
|
|
13233
|
-
}
|
|
13234
|
-
const totalSeconds = seconds + 60 * minutes + 3600 * hours;
|
|
13235
|
-
const roundedMinutes = Math.round(totalSeconds / 60);
|
|
13236
|
-
return new Time(roundedMinutes);
|
|
13237
|
-
}
|
|
13238
|
-
/**
|
|
13239
|
-
* Creates a Time instance from hours, minutes.
|
|
13240
|
-
*
|
|
13241
|
-
* @param hours - The hours component of the time.
|
|
13242
|
-
* @param minutes - The minutes component of the time.
|
|
13243
|
-
* @returns A Time instance representing the specified time.
|
|
13244
|
-
*/
|
|
13245
|
-
static fromHM(hours, minutes) {
|
|
13246
|
-
if (hours < 0 || minutes < 0 || minutes >= 60) {
|
|
13247
|
-
throw new Error('Invalid time. Ensure hours and minutes are valid values.');
|
|
13248
|
-
}
|
|
13249
|
-
return new Time(minutes + hours * 60);
|
|
13250
|
-
}
|
|
13251
|
-
/**
|
|
13252
|
-
* Parses a JavaScript Date object and creates a Time instance.
|
|
13253
|
-
*
|
|
13254
|
-
* @param date - A JavaScript Date object representing the time.
|
|
13255
|
-
* @returns A Time instance representing the parsed time.
|
|
13256
|
-
*/
|
|
13257
|
-
static fromDate(date) {
|
|
13258
|
-
const hours = date.getHours();
|
|
13259
|
-
const minutes = date.getMinutes();
|
|
13260
|
-
const seconds = date.getSeconds();
|
|
13261
|
-
return Time.fromHMS(hours, minutes, seconds);
|
|
13262
|
-
}
|
|
13263
|
-
/**
|
|
13264
|
-
* Parses a time string in the format "HH:MM:SS" or "HH:MM" and creates a Time instance.
|
|
13265
|
-
*
|
|
13266
|
-
* @param timeStr - A string representing the time in "HH:MM:SS" or "HH:MM" format.
|
|
13267
|
-
* @returns A Time instance representing the parsed time.
|
|
13268
|
-
*/
|
|
13269
|
-
static fromString(timeStr) {
|
|
13270
|
-
const [hoursStr, minutesStr, secondsStr] = timeStr.split(':');
|
|
13271
|
-
if (hoursStr === undefined ||
|
|
13272
|
-
minutesStr === undefined ||
|
|
13273
|
-
isNaN(Number(hoursStr)) ||
|
|
13274
|
-
isNaN(Number(minutesStr)) ||
|
|
13275
|
-
(secondsStr !== undefined && isNaN(Number(secondsStr)))) {
|
|
13276
|
-
throw new Error('Input string must be in the format "HH:MM:SS" or "HH:MM".');
|
|
13277
|
-
}
|
|
13278
|
-
const hours = parseInt(hoursStr, 10);
|
|
13279
|
-
const minutes = parseInt(minutesStr, 10);
|
|
13280
|
-
const seconds = secondsStr !== undefined ? parseInt(secondsStr, 10) : 0;
|
|
13281
|
-
return Time.fromHMS(hours, minutes, seconds);
|
|
13282
|
-
}
|
|
13283
|
-
/**
|
|
13284
|
-
* Converts the Time instance to a string in "HH:MM:SS" format.
|
|
13285
|
-
*
|
|
13286
|
-
* @returns A string representing the time.
|
|
13287
|
-
*/
|
|
13288
|
-
toString() {
|
|
13289
|
-
const hours = Math.floor(this.minutesSinceMidnight / 60);
|
|
13290
|
-
const minutes = Math.floor(this.minutesSinceMidnight % 60);
|
|
13291
|
-
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
13292
|
-
}
|
|
13293
|
-
/**
|
|
13294
|
-
* Converts the Time instance to the total number of minutes since midnight, rounded to the closest minute.
|
|
13295
|
-
*
|
|
13296
|
-
* @returns The time in minutes since midnight.
|
|
13297
|
-
*/
|
|
13298
|
-
toMinutes() {
|
|
13299
|
-
return this.minutesSinceMidnight;
|
|
13300
|
-
}
|
|
13301
|
-
/**
|
|
13302
|
-
* Adds a Duration to the current Time instance and returns a new Time instance.
|
|
13303
|
-
*
|
|
13304
|
-
* @param duration - A Duration instance representing the duration to add.
|
|
13305
|
-
* @returns A new Time instance with the added duration.
|
|
13306
|
-
*/
|
|
13307
|
-
plus(duration) {
|
|
13308
|
-
const totalSeconds = this.minutesSinceMidnight * 60 + duration.toSeconds();
|
|
13309
|
-
return new Time(Math.round(totalSeconds / 60));
|
|
13310
|
-
}
|
|
13311
|
-
/**
|
|
13312
|
-
* Subtracts a Duration from the current Time instance and returns a new Time instance.
|
|
13313
|
-
*
|
|
13314
|
-
* @param duration - A Duration instance representing the duration to subtract.
|
|
13315
|
-
* @returns A new Time instance with the subtracted duration.
|
|
13316
|
-
*/
|
|
13317
|
-
minus(duration) {
|
|
13318
|
-
let totalSeconds = this.minutesSinceMidnight * 60 - duration.toSeconds();
|
|
13319
|
-
if (totalSeconds < 0) {
|
|
13320
|
-
totalSeconds += 24 * 3600; // Adjust for negative time to loop back to previous day
|
|
13321
|
-
}
|
|
13322
|
-
return new Time(Math.round(totalSeconds / 60));
|
|
13323
|
-
}
|
|
13324
|
-
/**
|
|
13325
|
-
* Subtracts another Time instance from the current Time instance and returns the Duration.
|
|
13326
|
-
*
|
|
13327
|
-
* @param otherTime - A Time instance representing the time to subtract.
|
|
13328
|
-
* @returns A Duration instance representing the time difference.
|
|
13329
|
-
*/
|
|
13330
|
-
diff(otherTime) {
|
|
13331
|
-
const totalMinutes = this.minutesSinceMidnight - otherTime.toMinutes();
|
|
13332
|
-
return Duration.fromSeconds(Math.abs(totalMinutes * 60));
|
|
13333
|
-
}
|
|
13334
|
-
/**
|
|
13335
|
-
* Computes the maximum Time instance among the provided Time instances.
|
|
13336
|
-
*
|
|
13337
|
-
* @param times - An array of Time instances to compare.
|
|
13338
|
-
* @returns A Time instance representing the maximum time.
|
|
13339
|
-
*/
|
|
13340
|
-
static max(...times) {
|
|
13341
|
-
if (times.length === 0) {
|
|
13342
|
-
throw new Error('At least one Time instance is required.');
|
|
13343
|
-
}
|
|
13344
|
-
return times.reduce((maxTime, currentTime) => {
|
|
13345
|
-
return currentTime.toMinutes() > maxTime.toMinutes()
|
|
13346
|
-
? currentTime
|
|
13347
|
-
: maxTime;
|
|
13348
|
-
});
|
|
13349
|
-
}
|
|
13350
|
-
/**
|
|
13351
|
-
* Computes the minimum Time instance among the provided Time instances.
|
|
13352
|
-
*
|
|
13353
|
-
* @param times - An array of Time instances to compare.
|
|
13354
|
-
* @returns A Time instance representing the minimum time.
|
|
13355
|
-
*/
|
|
13356
|
-
static min(...times) {
|
|
13357
|
-
if (times.length === 0) {
|
|
13358
|
-
throw new Error('At least one Time instance is required.');
|
|
13359
|
-
}
|
|
13360
|
-
return times.reduce((minTime, currentTime) => {
|
|
13361
|
-
return currentTime.toMinutes() < minTime.toMinutes()
|
|
13362
|
-
? currentTime
|
|
13363
|
-
: minTime;
|
|
13364
|
-
});
|
|
13365
|
-
}
|
|
13366
|
-
}
|
|
13367
|
-
|
|
13368
|
-
const REGULAR = 0;
|
|
13369
|
-
const NOT_AVAILABLE = 1;
|
|
13370
|
-
const MUST_PHONE_AGENCY = 2;
|
|
13371
|
-
const MUST_COORDINATE_WITH_DRIVER = 3;
|
|
13372
|
-
const ALL_TRANSPORT_MODES = [
|
|
13756
|
+
const ALL_TRANSPORT_MODES = new Set([
|
|
13373
13757
|
'TRAM',
|
|
13374
13758
|
'SUBWAY',
|
|
13375
13759
|
'RAIL',
|
|
@@ -13380,11 +13764,10 @@ const ALL_TRANSPORT_MODES = [
|
|
|
13380
13764
|
'FUNICULAR',
|
|
13381
13765
|
'TROLLEYBUS',
|
|
13382
13766
|
'MONORAIL',
|
|
13383
|
-
];
|
|
13767
|
+
]);
|
|
13384
13768
|
const CURRENT_VERSION = '0.0.3';
|
|
13385
13769
|
/**
|
|
13386
|
-
* The internal transit timetable format
|
|
13387
|
-
* reuses some GTFS concepts for the sake of simplicity for now.
|
|
13770
|
+
* The internal transit timetable format.
|
|
13388
13771
|
*/
|
|
13389
13772
|
class Timetable {
|
|
13390
13773
|
constructor(stopsAdjacency, routesAdjacency, routes) {
|
|
@@ -13393,9 +13776,9 @@ class Timetable {
|
|
|
13393
13776
|
this.routes = routes;
|
|
13394
13777
|
}
|
|
13395
13778
|
/**
|
|
13396
|
-
* Serializes the Timetable into a binary
|
|
13779
|
+
* Serializes the Timetable into a binary array.
|
|
13397
13780
|
*
|
|
13398
|
-
* @returns
|
|
13781
|
+
* @returns The serialized binary data.
|
|
13399
13782
|
*/
|
|
13400
13783
|
serialize() {
|
|
13401
13784
|
const protoTimetable = {
|
|
@@ -13411,8 +13794,8 @@ class Timetable {
|
|
|
13411
13794
|
/**
|
|
13412
13795
|
* Deserializes a binary protobuf into a Timetable object.
|
|
13413
13796
|
*
|
|
13414
|
-
* @param
|
|
13415
|
-
* @returns
|
|
13797
|
+
* @param data - The binary data to deserialize.
|
|
13798
|
+
* @returns The deserialized Timetable object.
|
|
13416
13799
|
*/
|
|
13417
13800
|
static fromData(data) {
|
|
13418
13801
|
const reader = new BinaryReader(data);
|
|
@@ -13428,108 +13811,89 @@ class Timetable {
|
|
|
13428
13811
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13429
13812
|
deserializeServiceRoutesMap(protoTimetable.routes));
|
|
13430
13813
|
}
|
|
13431
|
-
|
|
13432
|
-
|
|
13433
|
-
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13814
|
+
/**
|
|
13815
|
+
* Retrieves the route associated with the given route ID.
|
|
13816
|
+
*
|
|
13817
|
+
* @param routeId - The ID of the route to be retrieved.
|
|
13818
|
+
* @returns The route corresponding to the provided ID,
|
|
13819
|
+
* or undefined if no such route exists.
|
|
13820
|
+
*/
|
|
13438
13821
|
getRoute(routeId) {
|
|
13439
13822
|
return this.routesAdjacency.get(routeId);
|
|
13440
13823
|
}
|
|
13824
|
+
/**
|
|
13825
|
+
* Retrieves all transfer options available at the specified stop.
|
|
13826
|
+
*
|
|
13827
|
+
* @param stopId - The ID of the stop to get transfers for.
|
|
13828
|
+
* @returns An array of transfer options available at the stop.
|
|
13829
|
+
*/
|
|
13441
13830
|
getTransfers(stopId) {
|
|
13442
13831
|
var _a, _b;
|
|
13443
|
-
return (_b = (_a = this.stopsAdjacency.get(stopId)) === null || _a ===
|
|
13832
|
+
return (_b = (_a = this.stopsAdjacency.get(stopId)) === null || _a === void 0 ? void 0 : _a.transfers) !== null && _b !== void 0 ? _b : [];
|
|
13833
|
+
}
|
|
13834
|
+
/**
|
|
13835
|
+
* Retrieves the service route associated with the given route.
|
|
13836
|
+
* A service route refers to a collection of trips that are displayed
|
|
13837
|
+
* to riders as a single service.
|
|
13838
|
+
*
|
|
13839
|
+
* @param route - The route for which the service route is to be retrieved.
|
|
13840
|
+
* @returns The service route corresponding to the provided route.
|
|
13841
|
+
*/
|
|
13842
|
+
getServiceRoute(route) {
|
|
13843
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
13844
|
+
return this.routes.get(route.serviceRoute());
|
|
13845
|
+
}
|
|
13846
|
+
/**
|
|
13847
|
+
* Finds all routes passing through a stop.
|
|
13848
|
+
*
|
|
13849
|
+
* @param stopId - The ID of the stop to find routes for.
|
|
13850
|
+
* @returns An array of routes passing through the specified stop.
|
|
13851
|
+
*/
|
|
13852
|
+
routesPassingThrough(stopId) {
|
|
13853
|
+
const stopData = this.stopsAdjacency.get(stopId);
|
|
13854
|
+
if (!stopData) {
|
|
13855
|
+
return [];
|
|
13856
|
+
}
|
|
13857
|
+
const routes = [];
|
|
13858
|
+
for (const routeId of stopData.routes) {
|
|
13859
|
+
const route = this.routesAdjacency.get(routeId);
|
|
13860
|
+
if (route) {
|
|
13861
|
+
routes.push(route);
|
|
13862
|
+
}
|
|
13863
|
+
}
|
|
13864
|
+
return routes;
|
|
13444
13865
|
}
|
|
13445
13866
|
/**
|
|
13446
13867
|
* Finds routes that are reachable from a set of stop IDs.
|
|
13447
13868
|
* Also identifies the first stop available to hop on each route among
|
|
13448
13869
|
* the input stops.
|
|
13870
|
+
*
|
|
13871
|
+
* @param fromStops - The set of stop IDs to find reachable routes from.
|
|
13872
|
+
* @param transportModes - The set of transport modes to consider for reachable routes.
|
|
13873
|
+
* @returns A map of reachable routes to the first stop available to hop on each route.
|
|
13449
13874
|
*/
|
|
13450
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
13451
13875
|
findReachableRoutes(fromStops, transportModes = ALL_TRANSPORT_MODES) {
|
|
13452
|
-
var _a;
|
|
13453
13876
|
const reachableRoutes = new Map();
|
|
13454
|
-
for (const
|
|
13455
|
-
const validRoutes = (
|
|
13456
|
-
|
|
13457
|
-
|
|
13458
|
-
if (!serviceRoute) {
|
|
13459
|
-
return false;
|
|
13460
|
-
}
|
|
13461
|
-
return transportModes.includes(serviceRoute.type);
|
|
13877
|
+
for (const originStop of fromStops) {
|
|
13878
|
+
const validRoutes = this.routesPassingThrough(originStop).filter((route) => {
|
|
13879
|
+
const serviceRoute = this.getServiceRoute(route);
|
|
13880
|
+
return transportModes.has(serviceRoute.type);
|
|
13462
13881
|
});
|
|
13463
|
-
for (const
|
|
13464
|
-
const hopOnStop = reachableRoutes.get(
|
|
13882
|
+
for (const route of validRoutes) {
|
|
13883
|
+
const hopOnStop = reachableRoutes.get(route);
|
|
13465
13884
|
if (hopOnStop) {
|
|
13466
|
-
|
|
13467
|
-
const routeStopIndices = this.routesAdjacency.get(routeId).stopIndices;
|
|
13468
|
-
const stopIndex = routeStopIndices.get(stop);
|
|
13469
|
-
const hopOnStopIndex = routeStopIndices.get(hopOnStop);
|
|
13470
|
-
if (stopIndex < hopOnStopIndex) {
|
|
13885
|
+
if (route.isBefore(originStop, hopOnStop)) {
|
|
13471
13886
|
// if the current stop is before the existing hop on stop, replace it
|
|
13472
|
-
reachableRoutes.set(
|
|
13887
|
+
reachableRoutes.set(route, originStop);
|
|
13473
13888
|
}
|
|
13474
13889
|
}
|
|
13475
13890
|
else {
|
|
13476
|
-
reachableRoutes.set(
|
|
13891
|
+
reachableRoutes.set(route, originStop);
|
|
13477
13892
|
}
|
|
13478
13893
|
}
|
|
13479
13894
|
}
|
|
13480
13895
|
return reachableRoutes;
|
|
13481
13896
|
}
|
|
13482
|
-
getServiceRouteFromRouteId(routeId) {
|
|
13483
|
-
const route = this.routesAdjacency.get(routeId);
|
|
13484
|
-
if (!route) {
|
|
13485
|
-
console.warn(`Route ${routeId} not found.`);
|
|
13486
|
-
return undefined;
|
|
13487
|
-
}
|
|
13488
|
-
return this.routes.get(route.serviceRouteId);
|
|
13489
|
-
}
|
|
13490
|
-
getServiceRoute(serviceRouteId) {
|
|
13491
|
-
return this.routes.get(serviceRouteId);
|
|
13492
|
-
}
|
|
13493
|
-
/**
|
|
13494
|
-
* Finds the earliest trip that can be taken from a specific stop on a given route,
|
|
13495
|
-
* optionally constrained by a latest trip index and a time before which the trip
|
|
13496
|
-
* should not depart.
|
|
13497
|
-
*/
|
|
13498
|
-
findEarliestTrip(route, stopId, beforeTrip, after = Time.origin()) {
|
|
13499
|
-
const stopIndex = route.stopIndices.get(stopId);
|
|
13500
|
-
const stopsNumber = route.stops.length;
|
|
13501
|
-
if (beforeTrip === undefined) {
|
|
13502
|
-
for (let tripIndex = 0; tripIndex < route.stopTimes.length / stopsNumber; tripIndex++) {
|
|
13503
|
-
const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
|
|
13504
|
-
const departure = route.stopTimes[stopTimeIndex * 2 + 1];
|
|
13505
|
-
const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
|
|
13506
|
-
if (departure >= after.toMinutes() && pickUpType !== NOT_AVAILABLE) {
|
|
13507
|
-
return tripIndex;
|
|
13508
|
-
}
|
|
13509
|
-
}
|
|
13510
|
-
return undefined;
|
|
13511
|
-
}
|
|
13512
|
-
else {
|
|
13513
|
-
let earliestTripIndex;
|
|
13514
|
-
let earliestDeparture;
|
|
13515
|
-
for (let tripIndex = beforeTrip; // ?? route.stopTimes.length / stopsNumber - 1;
|
|
13516
|
-
tripIndex >= 0; tripIndex--) {
|
|
13517
|
-
const stopTimeIndex = tripIndex * stopsNumber + stopIndex;
|
|
13518
|
-
const departure = route.stopTimes[stopTimeIndex * 2 + 1];
|
|
13519
|
-
const pickUpType = route.pickUpDropOffTypes[stopTimeIndex * 2];
|
|
13520
|
-
if (departure < after.toMinutes()) {
|
|
13521
|
-
break;
|
|
13522
|
-
}
|
|
13523
|
-
if (pickUpType !== NOT_AVAILABLE &&
|
|
13524
|
-
(earliestDeparture === undefined ||
|
|
13525
|
-
departure < earliestDeparture.toMinutes())) {
|
|
13526
|
-
earliestTripIndex = tripIndex;
|
|
13527
|
-
earliestDeparture = Time.fromMinutes(departure);
|
|
13528
|
-
}
|
|
13529
|
-
}
|
|
13530
|
-
return earliestTripIndex;
|
|
13531
|
-
}
|
|
13532
|
-
}
|
|
13533
13897
|
}
|
|
13534
13898
|
|
|
13535
13899
|
const standardProfile = {
|
|
@@ -13846,7 +14210,7 @@ const normalize_options = function (opts) {
|
|
|
13846
14210
|
);
|
|
13847
14211
|
}
|
|
13848
14212
|
// Normalize option `columns`
|
|
13849
|
-
options.cast_first_line_to_header =
|
|
14213
|
+
options.cast_first_line_to_header = undefined;
|
|
13850
14214
|
if (options.columns === true) {
|
|
13851
14215
|
// Fields in the first line are converted as-is to columns
|
|
13852
14216
|
options.cast_first_line_to_header = undefined;
|
|
@@ -14378,7 +14742,7 @@ const normalize_options = function (opts) {
|
|
|
14378
14742
|
// Normalize option `to`
|
|
14379
14743
|
if (options.to === undefined || options.to === null) {
|
|
14380
14744
|
options.to = -1;
|
|
14381
|
-
} else {
|
|
14745
|
+
} else if (options.to !== -1) {
|
|
14382
14746
|
if (typeof options.to === "string" && /\d+/.test(options.to)) {
|
|
14383
14747
|
options.to = parseInt(options.to);
|
|
14384
14748
|
}
|
|
@@ -14397,7 +14761,7 @@ const normalize_options = function (opts) {
|
|
|
14397
14761
|
// Normalize option `to_line`
|
|
14398
14762
|
if (options.to_line === undefined || options.to_line === null) {
|
|
14399
14763
|
options.to_line = -1;
|
|
14400
|
-
} else {
|
|
14764
|
+
} else if (options.to_line !== -1) {
|
|
14401
14765
|
if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) {
|
|
14402
14766
|
options.to_line = parseInt(options.to_line);
|
|
14403
14767
|
}
|
|
@@ -14528,10 +14892,14 @@ const transform = function (original_options = {}) {
|
|
|
14528
14892
|
this.state.bufBytesStart += bomLength;
|
|
14529
14893
|
buf = buf.slice(bomLength);
|
|
14530
14894
|
// Renormalize original options with the new encoding
|
|
14531
|
-
|
|
14895
|
+
const options = normalize_options({
|
|
14532
14896
|
...this.original_options,
|
|
14533
14897
|
encoding: encoding,
|
|
14534
14898
|
});
|
|
14899
|
+
// Properties are merged with the existing options instance
|
|
14900
|
+
for (const key in options) {
|
|
14901
|
+
this.options[key] = options[key];
|
|
14902
|
+
}
|
|
14535
14903
|
// Options will re-evaluate the Buffer with the new encoding
|
|
14536
14904
|
({ comment, escape, quote } = this.options);
|
|
14537
14905
|
break;
|
|
@@ -15274,10 +15642,14 @@ const transform = function (original_options = {}) {
|
|
|
15274
15642
|
if (skip_records_with_error) {
|
|
15275
15643
|
this.state.recordHasError = true;
|
|
15276
15644
|
if (this.options.on_skip !== undefined) {
|
|
15277
|
-
|
|
15278
|
-
|
|
15279
|
-
|
|
15280
|
-
|
|
15645
|
+
try {
|
|
15646
|
+
this.options.on_skip(
|
|
15647
|
+
err,
|
|
15648
|
+
raw ? this.state.rawBuffer.toString(encoding) : undefined,
|
|
15649
|
+
);
|
|
15650
|
+
} catch (err) {
|
|
15651
|
+
return err;
|
|
15652
|
+
}
|
|
15281
15653
|
}
|
|
15282
15654
|
// this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined);
|
|
15283
15655
|
return undefined;
|
|
@@ -15474,11 +15846,17 @@ const hashIds = (ids) => {
|
|
|
15474
15846
|
* @param stream The CSV stream.
|
|
15475
15847
|
* @returns A parser from the csv-parse library.
|
|
15476
15848
|
*/
|
|
15477
|
-
const parseCsv = (stream) => {
|
|
15849
|
+
const parseCsv = (stream, numericColumns = []) => {
|
|
15478
15850
|
return stream.pipe(parse({
|
|
15479
15851
|
delimiter: ',',
|
|
15480
15852
|
columns: true,
|
|
15481
|
-
cast:
|
|
15853
|
+
cast: (value, context) => {
|
|
15854
|
+
if (typeof context.column === 'string' &&
|
|
15855
|
+
numericColumns.includes(context.column)) {
|
|
15856
|
+
return Number(value);
|
|
15857
|
+
}
|
|
15858
|
+
return value;
|
|
15859
|
+
},
|
|
15482
15860
|
bom: true,
|
|
15483
15861
|
ignore_last_delimiters: true,
|
|
15484
15862
|
relax_column_count: true,
|
|
@@ -15492,11 +15870,11 @@ const parseCsv = (stream) => {
|
|
|
15492
15870
|
* @param profile A configuration object defining the specificities of the GTFS feed.
|
|
15493
15871
|
* @returns A map of all the valid routes.
|
|
15494
15872
|
*/
|
|
15495
|
-
const parseRoutes = (routesStream_1, ...args_1) => __awaiter(
|
|
15873
|
+
const parseRoutes = (routesStream_1, ...args_1) => __awaiter(void 0, [routesStream_1, ...args_1], void 0, function* (routesStream, profile = standardProfile) {
|
|
15496
15874
|
var _a, e_1, _b, _c;
|
|
15497
15875
|
const routes = new Map();
|
|
15498
15876
|
try {
|
|
15499
|
-
for (var _d = true, _e = __asyncValues(parseCsv(routesStream)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15877
|
+
for (var _d = true, _e = __asyncValues(parseCsv(routesStream, ['route_type'])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15500
15878
|
_c = _f.value;
|
|
15501
15879
|
_d = false;
|
|
15502
15880
|
const rawLine = _c;
|
|
@@ -15507,7 +15885,7 @@ const parseRoutes = (routesStream_1, ...args_1) => __awaiter(undefined, [routesS
|
|
|
15507
15885
|
continue;
|
|
15508
15886
|
}
|
|
15509
15887
|
routes.set(line.route_id, {
|
|
15510
|
-
name: line.route_short_name
|
|
15888
|
+
name: line.route_short_name,
|
|
15511
15889
|
type: routeType,
|
|
15512
15890
|
});
|
|
15513
15891
|
}
|
|
@@ -15560,13 +15938,23 @@ const weekdays = {
|
|
|
15560
15938
|
* @param date The active date.
|
|
15561
15939
|
* @param calendarStream A readable stream for the GTFS calendar.txt file.
|
|
15562
15940
|
*/
|
|
15563
|
-
const parseCalendar = (calendarStream, serviceIds, date) => __awaiter(
|
|
15941
|
+
const parseCalendar = (calendarStream, serviceIds, date) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15564
15942
|
var _a, e_1, _b, _c;
|
|
15565
15943
|
const activeDate = toGtfsDate(date);
|
|
15566
15944
|
const weekday = date.weekday;
|
|
15567
15945
|
const weekdayIndex = weekdays[weekday];
|
|
15568
15946
|
try {
|
|
15569
|
-
for (var _d = true, _e = __asyncValues(parseCsv(calendarStream
|
|
15947
|
+
for (var _d = true, _e = __asyncValues(parseCsv(calendarStream, [
|
|
15948
|
+
'monday',
|
|
15949
|
+
'tuesday',
|
|
15950
|
+
'wednesday',
|
|
15951
|
+
'thursday',
|
|
15952
|
+
'friday',
|
|
15953
|
+
'saturday',
|
|
15954
|
+
'sunday',
|
|
15955
|
+
'start_date',
|
|
15956
|
+
'end_date',
|
|
15957
|
+
])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15570
15958
|
_c = _f.value;
|
|
15571
15959
|
_d = false;
|
|
15572
15960
|
const rawLine = _c;
|
|
@@ -15597,11 +15985,14 @@ const parseCalendar = (calendarStream, serviceIds, date) => __awaiter(undefined,
|
|
|
15597
15985
|
* @param date The active date, in the format "YYYYMMDD".
|
|
15598
15986
|
* @param calendarDatesStream A readable stream for the GTFS calendar_dates.txt file.
|
|
15599
15987
|
*/
|
|
15600
|
-
const parseCalendarDates = (calendarDatesStream, serviceIds, date) => __awaiter(
|
|
15988
|
+
const parseCalendarDates = (calendarDatesStream, serviceIds, date) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15601
15989
|
var _a, e_2, _b, _c;
|
|
15602
15990
|
const activeDate = toGtfsDate(date);
|
|
15603
15991
|
try {
|
|
15604
|
-
for (var _d = true, _e = __asyncValues(parseCsv(calendarDatesStream
|
|
15992
|
+
for (var _d = true, _e = __asyncValues(parseCsv(calendarDatesStream, [
|
|
15993
|
+
'date',
|
|
15994
|
+
'exception_type',
|
|
15995
|
+
])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15605
15996
|
_c = _f.value;
|
|
15606
15997
|
_d = false;
|
|
15607
15998
|
const rawLine = _c;
|
|
@@ -15634,17 +16025,21 @@ const parseCalendarDates = (calendarDatesStream, serviceIds, date) => __awaiter(
|
|
|
15634
16025
|
* @param stopsStream The readable stream containing the stops data.
|
|
15635
16026
|
* @return A mapping of stop IDs to corresponding stop details.
|
|
15636
16027
|
*/
|
|
15637
|
-
const parseStops = (stopsStream, platformParser) => __awaiter(
|
|
16028
|
+
const parseStops = (stopsStream, platformParser) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15638
16029
|
var _a, e_1, _b, _c;
|
|
15639
16030
|
const parsedStops = new Map();
|
|
15640
16031
|
let i = 0;
|
|
15641
16032
|
try {
|
|
15642
|
-
for (var _d = true, _e = __asyncValues(parseCsv(stopsStream
|
|
16033
|
+
for (var _d = true, _e = __asyncValues(parseCsv(stopsStream, [
|
|
16034
|
+
'stop_lat',
|
|
16035
|
+
'stop_lon',
|
|
16036
|
+
'location_type',
|
|
16037
|
+
])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15643
16038
|
_c = _f.value;
|
|
15644
16039
|
_d = false;
|
|
15645
16040
|
const rawLine = _c;
|
|
15646
16041
|
const line = rawLine;
|
|
15647
|
-
const stop = Object.assign({ id: i, sourceStopId: line.stop_id
|
|
16042
|
+
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
|
|
15648
16043
|
? parseGtfsLocationType(line.location_type)
|
|
15649
16044
|
: 'SIMPLE_STOP_OR_PLATFORM', children: [] }, (line.parent_station && { parentSourceId: line.parent_station }));
|
|
15650
16045
|
if (platformParser) {
|
|
@@ -15658,7 +16053,7 @@ const parseStops = (stopsStream, platformParser) => __awaiter(undefined, undefin
|
|
|
15658
16053
|
console.info(`Could not parse platform for stop ${line.stop_id}.`);
|
|
15659
16054
|
}
|
|
15660
16055
|
}
|
|
15661
|
-
parsedStops.set(line.stop_id
|
|
16056
|
+
parsedStops.set(line.stop_id, stop);
|
|
15662
16057
|
i = i + 1;
|
|
15663
16058
|
}
|
|
15664
16059
|
}
|
|
@@ -15735,11 +16130,14 @@ const parseGtfsLocationType = (gtfsLocationType) => {
|
|
|
15735
16130
|
* @param stopsStream The readable stream containing the stops data.
|
|
15736
16131
|
* @return A mapping of stop IDs to corresponding stop details.
|
|
15737
16132
|
*/
|
|
15738
|
-
const parseTransfers = (transfersStream, stopsMap) => __awaiter(
|
|
16133
|
+
const parseTransfers = (transfersStream, stopsMap) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15739
16134
|
var _a, e_1, _b, _c;
|
|
15740
16135
|
const transfers = new Map();
|
|
15741
16136
|
try {
|
|
15742
|
-
for (var _d = true, _e = __asyncValues(parseCsv(transfersStream
|
|
16137
|
+
for (var _d = true, _e = __asyncValues(parseCsv(transfersStream, [
|
|
16138
|
+
'transfer_type',
|
|
16139
|
+
'min_transfer_time',
|
|
16140
|
+
])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15743
16141
|
_c = _f.value;
|
|
15744
16142
|
_d = false;
|
|
15745
16143
|
const rawLine = _c;
|
|
@@ -15764,9 +16162,9 @@ const parseTransfers = (transfersStream, stopsMap) => __awaiter(undefined, undef
|
|
|
15764
16162
|
console.info(`Missing minimum transfer time between ${transferEntry.from_stop_id} and ${transferEntry.to_stop_id}.`);
|
|
15765
16163
|
}
|
|
15766
16164
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15767
|
-
const fromStop = stopsMap.get(transferEntry.from_stop_id
|
|
16165
|
+
const fromStop = stopsMap.get(transferEntry.from_stop_id);
|
|
15768
16166
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15769
|
-
const toStop = stopsMap.get(transferEntry.to_stop_id
|
|
16167
|
+
const toStop = stopsMap.get(transferEntry.to_stop_id);
|
|
15770
16168
|
const transfer = Object.assign({ destination: toStop.id, type: parseGtfsTransferType(transferEntry.transfer_type) }, (transferEntry.min_transfer_time && {
|
|
15771
16169
|
minTransferTime: Duration.fromSeconds(transferEntry.min_transfer_time),
|
|
15772
16170
|
}));
|
|
@@ -15806,11 +16204,11 @@ const parseGtfsTransferType = (gtfsTransferType) => {
|
|
|
15806
16204
|
* @param routeIds A mapping of route IDs to route details.
|
|
15807
16205
|
* @returns A mapping of trip IDs to corresponding route IDs.
|
|
15808
16206
|
*/
|
|
15809
|
-
const parseTrips = (tripsStream, serviceIds, routeIds) => __awaiter(
|
|
16207
|
+
const parseTrips = (tripsStream, serviceIds, routeIds) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15810
16208
|
var _a, e_1, _b, _c;
|
|
15811
16209
|
const trips = new Map();
|
|
15812
16210
|
try {
|
|
15813
|
-
for (var _d = true, _e = __asyncValues(parseCsv(tripsStream)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
16211
|
+
for (var _d = true, _e = __asyncValues(parseCsv(tripsStream, ['stop_sequence'])), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
15814
16212
|
_c = _f.value;
|
|
15815
16213
|
_d = false;
|
|
15816
16214
|
const rawLine = _c;
|
|
@@ -15840,11 +16238,14 @@ const buildStopsAdjacencyStructure = (validStops, routes, transfersMap) => {
|
|
|
15840
16238
|
const stopsAdjacency = new Map();
|
|
15841
16239
|
for (const routeId of routes.keys()) {
|
|
15842
16240
|
const route = routes.get(routeId);
|
|
15843
|
-
|
|
16241
|
+
if (!route) {
|
|
16242
|
+
throw new Error(`Route ${routeId} not found`);
|
|
16243
|
+
}
|
|
16244
|
+
for (const stop of route.stopsIterator()) {
|
|
15844
16245
|
if (!stopsAdjacency.get(stop) && validStops.has(stop)) {
|
|
15845
16246
|
stopsAdjacency.set(stop, { routes: [], transfers: [] });
|
|
15846
16247
|
}
|
|
15847
|
-
(_a = stopsAdjacency.get(stop)) === null || _a ===
|
|
16248
|
+
(_a = stopsAdjacency.get(stop)) === null || _a === void 0 ? void 0 : _a.routes.push(routeId);
|
|
15848
16249
|
}
|
|
15849
16250
|
}
|
|
15850
16251
|
for (const [stop, transfers] of transfersMap) {
|
|
@@ -15868,7 +16269,7 @@ const buildStopsAdjacencyStructure = (validStops, routes, transfersMap) => {
|
|
|
15868
16269
|
* @param validStopIds A set of valid stop IDs.
|
|
15869
16270
|
* @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.
|
|
15870
16271
|
*/
|
|
15871
|
-
const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) => __awaiter(
|
|
16272
|
+
const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15872
16273
|
var _a, e_2, _b, _c;
|
|
15873
16274
|
var _d, _e;
|
|
15874
16275
|
/**
|
|
@@ -15906,7 +16307,6 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
15906
16307
|
route = {
|
|
15907
16308
|
serviceRouteId: gtfsRouteId,
|
|
15908
16309
|
stops: stopsArray,
|
|
15909
|
-
stopIndices: new Map(stops.map((stop, i) => [stop, i])),
|
|
15910
16310
|
stopTimes: stopTimesArray,
|
|
15911
16311
|
pickUpDropOffTypes: pickUpDropOffTypesArray,
|
|
15912
16312
|
};
|
|
@@ -15971,7 +16371,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
15971
16371
|
let dropOffTypes = [];
|
|
15972
16372
|
let currentTripId = undefined;
|
|
15973
16373
|
try {
|
|
15974
|
-
for (var _f = true, _g = __asyncValues(parseCsv(stopTimesStream)), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
|
|
16374
|
+
for (var _f = true, _g = __asyncValues(parseCsv(stopTimesStream, ['stop_sequence'])), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
|
|
15975
16375
|
_c = _h.value;
|
|
15976
16376
|
_f = false;
|
|
15977
16377
|
const rawLine = _c;
|
|
@@ -15992,7 +16392,7 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
15992
16392
|
}
|
|
15993
16393
|
currentTripId = line.trip_id;
|
|
15994
16394
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
15995
|
-
stops.push(stopsMap.get(line.stop_id
|
|
16395
|
+
stops.push(stopsMap.get(line.stop_id).id);
|
|
15996
16396
|
const departure = (_d = line.departure_time) !== null && _d !== void 0 ? _d : line.arrival_time;
|
|
15997
16397
|
const arrival = (_e = line.arrival_time) !== null && _e !== void 0 ? _e : line.departure_time;
|
|
15998
16398
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -16014,12 +16414,15 @@ const parseStopTimes = (stopTimesStream, stopsMap, validTripIds, validStopIds) =
|
|
|
16014
16414
|
if (currentTripId) {
|
|
16015
16415
|
addTrip(currentTripId);
|
|
16016
16416
|
}
|
|
16017
|
-
|
|
16417
|
+
const routesAdjacency = new Map();
|
|
16418
|
+
for (const [routeId, routeData] of routes) {
|
|
16419
|
+
routesAdjacency.set(routeId, new Route(routeData.stopTimes, routeData.pickUpDropOffTypes, routeData.stops, routeData.serviceRouteId));
|
|
16420
|
+
}
|
|
16421
|
+
return routesAdjacency;
|
|
16018
16422
|
});
|
|
16019
16423
|
const parsePickupDropOffType = (gtfsType) => {
|
|
16020
16424
|
switch (gtfsType) {
|
|
16021
16425
|
default:
|
|
16022
|
-
console.warn(`Unknown pickup/drop-off type ${gtfsType}`);
|
|
16023
16426
|
return REGULAR;
|
|
16024
16427
|
case 0:
|
|
16025
16428
|
return REGULAR;
|
|
@@ -16054,7 +16457,7 @@ class GtfsParser {
|
|
|
16054
16457
|
* @returns An object containing the timetable and stops map.
|
|
16055
16458
|
*/
|
|
16056
16459
|
parse(date) {
|
|
16057
|
-
return __awaiter(this,
|
|
16460
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16058
16461
|
const zip = new StreamZip.async({ file: this.path });
|
|
16059
16462
|
const entries = yield zip.entries();
|
|
16060
16463
|
const datetime = DateTime.fromJSDate(date);
|
|
@@ -16115,7 +16518,7 @@ class GtfsParser {
|
|
|
16115
16518
|
* @returns An object containing the timetable and stops map.
|
|
16116
16519
|
*/
|
|
16117
16520
|
parseStops() {
|
|
16118
|
-
return __awaiter(this,
|
|
16521
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16119
16522
|
const zip = new StreamZip.async({ file: this.path });
|
|
16120
16523
|
log.info(`Parsing ${STOPS_FILE}`);
|
|
16121
16524
|
const stopsStream = yield zip.stream(STOPS_FILE);
|
|
@@ -16133,7 +16536,7 @@ class GtfsParser {
|
|
|
16133
16536
|
* @returns The platform corresponding to this stop.
|
|
16134
16537
|
*/
|
|
16135
16538
|
const platformParser = (stopEntry) => {
|
|
16136
|
-
const stopId =
|
|
16539
|
+
const stopId = stopEntry.stop_id;
|
|
16137
16540
|
const stopParts = stopId.split(':');
|
|
16138
16541
|
if (stopParts.length > 2) {
|
|
16139
16542
|
return stopParts[2];
|