hk-bus-eta 3.7.0 → 3.7.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/dist/journeyTime.js +39 -8
- package/dist/journeyTime.js.map +1 -1
- package/esm/journeyTime.js +37 -8
- package/esm/journeyTime.js.map +1 -1
- package/package.json +5 -1
- package/src/journeyTime.ts +96 -46
package/dist/journeyTime.js
CHANGED
|
@@ -10,8 +10,29 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.fetchEstJourneyTime = void 0;
|
|
13
|
+
const date_fns_tz_1 = require("date-fns-tz");
|
|
13
14
|
const __HK_BUS_ETA_JT_CACHE__ = {};
|
|
14
15
|
function fetchEstJourneyTimeBasedOnHistoricalData({ route, startSeq, endSeq, }) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
const requests = [];
|
|
18
|
+
for (let i = startSeq; i < endSeq; ++i) {
|
|
19
|
+
const start = Object.values(route.stops)[0][startSeq];
|
|
20
|
+
const end = Object.values(route.stops)[0][endSeq];
|
|
21
|
+
const day = parseInt((0, date_fns_tz_1.formatInTimeZone)(new Date(), "Asia/Hong_Kong", "i"), 10) - 1;
|
|
22
|
+
const hour = (0, date_fns_tz_1.formatInTimeZone)(new Date(), "Asia/Hong_Kong", "HH");
|
|
23
|
+
requests.push(fetch(`https://raw.githubusercontent.com/HK-Bus-ETA/hk-bus-time-between-stops/refs/heads/pages/times_hourly/${day}/${hour}/${start.slice(0, 2)}.json`)
|
|
24
|
+
.then((r) => r.json())
|
|
25
|
+
.then((r) => {
|
|
26
|
+
if (r[start][end]) {
|
|
27
|
+
return r[start][end];
|
|
28
|
+
}
|
|
29
|
+
throw new Error("not found");
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
return Promise.all(requests).then((seconds) => Math.ceil(seconds.reduce((acc, cur) => acc + cur, 0) / 60));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function fetchEstJourneyTimeBasedOnHistoricalAvgData({ route, startSeq, endSeq, }) {
|
|
15
36
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16
37
|
const requests = [];
|
|
17
38
|
for (let i = startSeq; i < endSeq; ++i) {
|
|
@@ -65,7 +86,7 @@ function fetchEstJourneyTime({ route, stopList, startSeq, endSeq, batchSize = 4,
|
|
|
65
86
|
{
|
|
66
87
|
startSeq: i,
|
|
67
88
|
endSeq: i + 1,
|
|
68
|
-
}
|
|
89
|
+
},
|
|
69
90
|
]);
|
|
70
91
|
if (payloads.length < batchSize && i !== endSeq - 1) {
|
|
71
92
|
// skip fetching until whole batch filled
|
|
@@ -78,8 +99,16 @@ function fetchEstJourneyTime({ route, stopList, startSeq, endSeq, batchSize = 4,
|
|
|
78
99
|
return Promise.resolve(__HK_BUS_ETA_JT_CACHE__[key].s);
|
|
79
100
|
}
|
|
80
101
|
return fetchEstJourneyTimeBasedOnHistoricalData({
|
|
81
|
-
route,
|
|
82
|
-
|
|
102
|
+
route,
|
|
103
|
+
startSeq,
|
|
104
|
+
endSeq,
|
|
105
|
+
})
|
|
106
|
+
.catch(() => fetchEstJourneyTimeBasedOnHistoricalAvgData({
|
|
107
|
+
route,
|
|
108
|
+
startSeq,
|
|
109
|
+
endSeq,
|
|
110
|
+
}))
|
|
111
|
+
.catch(() => fetch("https://tdas-api.hkemobility.gov.hk/tdas/api/route", {
|
|
83
112
|
method: "POST",
|
|
84
113
|
headers: {
|
|
85
114
|
"Content-Type": "application/json",
|
|
@@ -95,21 +124,23 @@ function fetchEstJourneyTime({ route, stopList, startSeq, endSeq, batchSize = 4,
|
|
|
95
124
|
speedStr !== undefined &&
|
|
96
125
|
!isNaN(parseInt(speedStr, 10))) {
|
|
97
126
|
// Set the speed limit as 70 km/h
|
|
98
|
-
return (distM / Math.min(parseInt(speedStr, 10), 70) / 1000) * 60
|
|
127
|
+
return ((distM / Math.min(parseInt(speedStr, 10), 70) / 1000) * 60);
|
|
99
128
|
}
|
|
100
129
|
console.warn("Unable to parse TDAS response for more precise journey time. Falling back.");
|
|
101
|
-
const [hh, mm] = eta
|
|
102
|
-
|
|
130
|
+
const [hh, mm] = eta
|
|
131
|
+
.split(":")
|
|
132
|
+
.map((v) => parseInt(v, 10));
|
|
133
|
+
return hh * 60 + mm;
|
|
103
134
|
})
|
|
104
135
|
.catch(() => {
|
|
105
136
|
// for any error, assume 4 minutes journey time blindly
|
|
106
|
-
return 4
|
|
137
|
+
return 4;
|
|
107
138
|
})
|
|
108
139
|
.then((s) => {
|
|
109
140
|
__HK_BUS_ETA_JT_CACHE__[key] = { s: s * 1.1, ts };
|
|
110
141
|
// margin for car accelerating, decelerating, and passenger picking up and dropping off
|
|
111
142
|
return s * 1.1;
|
|
112
|
-
}))
|
|
143
|
+
}));
|
|
113
144
|
}));
|
|
114
145
|
seconds.forEach((s) => {
|
|
115
146
|
ret += s;
|
package/dist/journeyTime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journeyTime.js","sourceRoot":"","sources":["../src/journeyTime.ts"],"names":[],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"journeyTime.js","sourceRoot":"","sources":["../src/journeyTime.ts"],"names":[],"mappings":"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"}
|
package/esm/journeyTime.js
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
|
+
import { formatInTimeZone } from "date-fns-tz";
|
|
1
2
|
const __HK_BUS_ETA_JT_CACHE__ = {};
|
|
2
3
|
async function fetchEstJourneyTimeBasedOnHistoricalData({ route, startSeq, endSeq, }) {
|
|
4
|
+
const requests = [];
|
|
5
|
+
for (let i = startSeq; i < endSeq; ++i) {
|
|
6
|
+
const start = Object.values(route.stops)[0][startSeq];
|
|
7
|
+
const end = Object.values(route.stops)[0][endSeq];
|
|
8
|
+
const day = parseInt(formatInTimeZone(new Date(), "Asia/Hong_Kong", "i"), 10) - 1;
|
|
9
|
+
const hour = formatInTimeZone(new Date(), "Asia/Hong_Kong", "HH");
|
|
10
|
+
requests.push(fetch(`https://raw.githubusercontent.com/HK-Bus-ETA/hk-bus-time-between-stops/refs/heads/pages/times_hourly/${day}/${hour}/${start.slice(0, 2)}.json`)
|
|
11
|
+
.then((r) => r.json())
|
|
12
|
+
.then((r) => {
|
|
13
|
+
if (r[start][end]) {
|
|
14
|
+
return r[start][end];
|
|
15
|
+
}
|
|
16
|
+
throw new Error("not found");
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
return Promise.all(requests).then((seconds) => Math.ceil(seconds.reduce((acc, cur) => acc + cur, 0) / 60));
|
|
20
|
+
}
|
|
21
|
+
async function fetchEstJourneyTimeBasedOnHistoricalAvgData({ route, startSeq, endSeq, }) {
|
|
3
22
|
const requests = [];
|
|
4
23
|
for (let i = startSeq; i < endSeq; ++i) {
|
|
5
24
|
const start = Object.values(route.stops)[0][startSeq];
|
|
@@ -50,7 +69,7 @@ export async function fetchEstJourneyTime({ route, stopList, startSeq, endSeq, b
|
|
|
50
69
|
{
|
|
51
70
|
startSeq: i,
|
|
52
71
|
endSeq: i + 1,
|
|
53
|
-
}
|
|
72
|
+
},
|
|
54
73
|
]);
|
|
55
74
|
if (payloads.length < batchSize && i !== endSeq - 1) {
|
|
56
75
|
// skip fetching until whole batch filled
|
|
@@ -63,8 +82,16 @@ export async function fetchEstJourneyTime({ route, stopList, startSeq, endSeq, b
|
|
|
63
82
|
return Promise.resolve(__HK_BUS_ETA_JT_CACHE__[key].s);
|
|
64
83
|
}
|
|
65
84
|
return fetchEstJourneyTimeBasedOnHistoricalData({
|
|
66
|
-
route,
|
|
67
|
-
|
|
85
|
+
route,
|
|
86
|
+
startSeq,
|
|
87
|
+
endSeq,
|
|
88
|
+
})
|
|
89
|
+
.catch(() => fetchEstJourneyTimeBasedOnHistoricalAvgData({
|
|
90
|
+
route,
|
|
91
|
+
startSeq,
|
|
92
|
+
endSeq,
|
|
93
|
+
}))
|
|
94
|
+
.catch(() => fetch("https://tdas-api.hkemobility.gov.hk/tdas/api/route", {
|
|
68
95
|
method: "POST",
|
|
69
96
|
headers: {
|
|
70
97
|
"Content-Type": "application/json",
|
|
@@ -80,21 +107,23 @@ export async function fetchEstJourneyTime({ route, stopList, startSeq, endSeq, b
|
|
|
80
107
|
speedStr !== undefined &&
|
|
81
108
|
!isNaN(parseInt(speedStr, 10))) {
|
|
82
109
|
// Set the speed limit as 70 km/h
|
|
83
|
-
return (distM / Math.min(parseInt(speedStr, 10), 70) / 1000) * 60
|
|
110
|
+
return ((distM / Math.min(parseInt(speedStr, 10), 70) / 1000) * 60);
|
|
84
111
|
}
|
|
85
112
|
console.warn("Unable to parse TDAS response for more precise journey time. Falling back.");
|
|
86
|
-
const [hh, mm] = eta
|
|
87
|
-
|
|
113
|
+
const [hh, mm] = eta
|
|
114
|
+
.split(":")
|
|
115
|
+
.map((v) => parseInt(v, 10));
|
|
116
|
+
return hh * 60 + mm;
|
|
88
117
|
})
|
|
89
118
|
.catch(() => {
|
|
90
119
|
// for any error, assume 4 minutes journey time blindly
|
|
91
|
-
return 4
|
|
120
|
+
return 4;
|
|
92
121
|
})
|
|
93
122
|
.then((s) => {
|
|
94
123
|
__HK_BUS_ETA_JT_CACHE__[key] = { s: s * 1.1, ts };
|
|
95
124
|
// margin for car accelerating, decelerating, and passenger picking up and dropping off
|
|
96
125
|
return s * 1.1;
|
|
97
|
-
}))
|
|
126
|
+
}));
|
|
98
127
|
}));
|
|
99
128
|
seconds.forEach((s) => {
|
|
100
129
|
ret += s;
|
package/esm/journeyTime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journeyTime.js","sourceRoot":"","sources":["../src/journeyTime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"journeyTime.js","sourceRoot":"","sources":["../src/journeyTime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hk-bus-eta",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.2",
|
|
4
4
|
"description": "Query the ETA (Estimated Time of Arrival) of HK Bus/Minibus/MTR/Lightrail",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "esm/index.js",
|
|
@@ -49,5 +49,9 @@
|
|
|
49
49
|
"ts-jest": "^29.1.1",
|
|
50
50
|
"ts-node": "^10.9.1",
|
|
51
51
|
"typescript": "^5.2.2"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"date-fns": "^4.1.0",
|
|
55
|
+
"date-fns-tz": "^3.2.0"
|
|
52
56
|
}
|
|
53
57
|
}
|
package/src/journeyTime.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RouteListEntry, StopList } from "./type";
|
|
2
|
+
import { formatInTimeZone } from "date-fns-tz";
|
|
2
3
|
|
|
3
4
|
type JT_CACHE = Record<
|
|
4
5
|
string,
|
|
@@ -19,8 +20,42 @@ async function fetchEstJourneyTimeBasedOnHistoricalData({
|
|
|
19
20
|
startSeq: number;
|
|
20
21
|
endSeq: number;
|
|
21
22
|
}): Promise<number> {
|
|
22
|
-
const requests = []
|
|
23
|
-
for (
|
|
23
|
+
const requests = [];
|
|
24
|
+
for (let i = startSeq; i < endSeq; ++i) {
|
|
25
|
+
const start = Object.values(route.stops)[0][startSeq];
|
|
26
|
+
const end = Object.values(route.stops)[0][endSeq];
|
|
27
|
+
const day =
|
|
28
|
+
parseInt(formatInTimeZone(new Date(), "Asia/Hong_Kong", "i"), 10) - 1;
|
|
29
|
+
const hour = formatInTimeZone(new Date(), "Asia/Hong_Kong", "HH");
|
|
30
|
+
requests.push(
|
|
31
|
+
fetch(
|
|
32
|
+
`https://raw.githubusercontent.com/HK-Bus-ETA/hk-bus-time-between-stops/refs/heads/pages/times_hourly/${day}/${hour}/${start.slice(0, 2)}.json`,
|
|
33
|
+
)
|
|
34
|
+
.then((r) => r.json())
|
|
35
|
+
.then((r) => {
|
|
36
|
+
if (r[start][end]) {
|
|
37
|
+
return r[start][end];
|
|
38
|
+
}
|
|
39
|
+
throw new Error("not found");
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return Promise.all(requests).then((seconds) =>
|
|
44
|
+
Math.ceil(seconds.reduce((acc, cur) => acc + cur, 0) / 60),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function fetchEstJourneyTimeBasedOnHistoricalAvgData({
|
|
49
|
+
route,
|
|
50
|
+
startSeq,
|
|
51
|
+
endSeq,
|
|
52
|
+
}: {
|
|
53
|
+
route: RouteListEntry;
|
|
54
|
+
startSeq: number;
|
|
55
|
+
endSeq: number;
|
|
56
|
+
}): Promise<number> {
|
|
57
|
+
const requests = [];
|
|
58
|
+
for (let i = startSeq; i < endSeq; ++i) {
|
|
24
59
|
const start = Object.values(route.stops)[0][startSeq];
|
|
25
60
|
const end = Object.values(route.stops)[0][endSeq];
|
|
26
61
|
requests.push(
|
|
@@ -32,12 +67,13 @@ async function fetchEstJourneyTimeBasedOnHistoricalData({
|
|
|
32
67
|
if (r[start][end]) {
|
|
33
68
|
return r[start][end];
|
|
34
69
|
}
|
|
35
|
-
throw new Error("not found")
|
|
36
|
-
})
|
|
37
|
-
)
|
|
70
|
+
throw new Error("not found");
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
38
73
|
}
|
|
39
|
-
return Promise.all(requests).then((seconds) =>
|
|
40
|
-
|
|
74
|
+
return Promise.all(requests).then((seconds) =>
|
|
75
|
+
Math.ceil(seconds.reduce((acc, cur) => acc + cur, 0) / 60),
|
|
76
|
+
);
|
|
41
77
|
}
|
|
42
78
|
|
|
43
79
|
/**
|
|
@@ -91,15 +127,15 @@ export async function fetchEstJourneyTime({
|
|
|
91
127
|
}),
|
|
92
128
|
{
|
|
93
129
|
startSeq: i,
|
|
94
|
-
endSeq: i+1,
|
|
95
|
-
}
|
|
130
|
+
endSeq: i + 1,
|
|
131
|
+
},
|
|
96
132
|
]);
|
|
97
133
|
if (payloads.length < batchSize && i !== endSeq - 1) {
|
|
98
134
|
// skip fetching until whole batch filled
|
|
99
135
|
continue;
|
|
100
136
|
}
|
|
101
137
|
const seconds = await Promise.all(
|
|
102
|
-
payloads.map(([key, payload, {startSeq, endSeq}]) => {
|
|
138
|
+
payloads.map(([key, payload, { startSeq, endSeq }]) => {
|
|
103
139
|
// load from cache if it is query within 15 minutes
|
|
104
140
|
if (
|
|
105
141
|
key in __HK_BUS_ETA_JT_CACHE__ &&
|
|
@@ -109,43 +145,57 @@ export async function fetchEstJourneyTime({
|
|
|
109
145
|
}
|
|
110
146
|
|
|
111
147
|
return fetchEstJourneyTimeBasedOnHistoricalData({
|
|
112
|
-
route,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return (distM / Math.min(parseInt(speedStr, 10), 70) / 1000) * 60 * 60;
|
|
132
|
-
}
|
|
133
|
-
console.warn(
|
|
134
|
-
"Unable to parse TDAS response for more precise journey time. Falling back.",
|
|
135
|
-
);
|
|
136
|
-
const [hh, mm] = eta.split(":").map((v: string) => parseInt(v, 10));
|
|
137
|
-
return ( hh * 60 + mm ) * 60;
|
|
138
|
-
})
|
|
139
|
-
.catch(() => {
|
|
140
|
-
// for any error, assume 4 minutes journey time blindly
|
|
141
|
-
return 4 * 60;
|
|
142
|
-
})
|
|
143
|
-
.then((s) => {
|
|
144
|
-
__HK_BUS_ETA_JT_CACHE__[key] = { s: s * 1.1, ts };
|
|
145
|
-
// margin for car accelerating, decelerating, and passenger picking up and dropping off
|
|
146
|
-
return s * 1.1;
|
|
148
|
+
route,
|
|
149
|
+
startSeq,
|
|
150
|
+
endSeq,
|
|
151
|
+
})
|
|
152
|
+
.catch(() =>
|
|
153
|
+
fetchEstJourneyTimeBasedOnHistoricalAvgData({
|
|
154
|
+
route,
|
|
155
|
+
startSeq,
|
|
156
|
+
endSeq,
|
|
157
|
+
}),
|
|
158
|
+
)
|
|
159
|
+
.catch(() =>
|
|
160
|
+
fetch("https://tdas-api.hkemobility.gov.hk/tdas/api/route", {
|
|
161
|
+
method: "POST",
|
|
162
|
+
headers: {
|
|
163
|
+
"Content-Type": "application/json",
|
|
164
|
+
},
|
|
165
|
+
body: payload,
|
|
166
|
+
signal,
|
|
147
167
|
})
|
|
148
|
-
|
|
168
|
+
.then((r) => r.json())
|
|
169
|
+
.then(({ eta, distM, jSpeed }) => {
|
|
170
|
+
const speedStr = /(\d+)公里\/小時/g.exec(jSpeed)?.[1];
|
|
171
|
+
if (
|
|
172
|
+
speedStr !== null &&
|
|
173
|
+
speedStr !== undefined &&
|
|
174
|
+
!isNaN(parseInt(speedStr, 10))
|
|
175
|
+
) {
|
|
176
|
+
// Set the speed limit as 70 km/h
|
|
177
|
+
return (
|
|
178
|
+
(distM / Math.min(parseInt(speedStr, 10), 70) / 1000) * 60
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
console.warn(
|
|
182
|
+
"Unable to parse TDAS response for more precise journey time. Falling back.",
|
|
183
|
+
);
|
|
184
|
+
const [hh, mm] = eta
|
|
185
|
+
.split(":")
|
|
186
|
+
.map((v: string) => parseInt(v, 10));
|
|
187
|
+
return hh * 60 + mm;
|
|
188
|
+
})
|
|
189
|
+
.catch(() => {
|
|
190
|
+
// for any error, assume 4 minutes journey time blindly
|
|
191
|
+
return 4;
|
|
192
|
+
})
|
|
193
|
+
.then((s) => {
|
|
194
|
+
__HK_BUS_ETA_JT_CACHE__[key] = { s: s * 1.1, ts };
|
|
195
|
+
// margin for car accelerating, decelerating, and passenger picking up and dropping off
|
|
196
|
+
return s * 1.1;
|
|
197
|
+
}),
|
|
198
|
+
);
|
|
149
199
|
}),
|
|
150
200
|
);
|
|
151
201
|
seconds.forEach((s) => {
|