@opentripplanner/core-utils 5.0.3-alpha.1 → 7.0.0-alpha.1
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/esm/itinerary.js +74 -11
- package/esm/itinerary.js.map +1 -1
- package/esm/map.js +20 -239
- package/esm/map.js.map +1 -1
- package/esm/query.js +14 -11
- package/esm/query.js.map +1 -1
- package/esm/time.js +5 -56
- package/esm/time.js.map +1 -1
- package/lib/itinerary.d.ts +14 -7
- package/lib/itinerary.d.ts.map +1 -1
- package/lib/itinerary.js +79 -65
- package/lib/itinerary.js.map +1 -1
- package/lib/map.d.ts +4 -13
- package/lib/map.d.ts.map +1 -1
- package/lib/map.js +18 -251
- package/lib/map.js.map +1 -1
- package/lib/query.js +11 -15
- package/lib/query.js.map +1 -1
- package/lib/time.d.ts +1 -16
- package/lib/time.d.ts.map +1 -1
- package/lib/time.js +4 -72
- package/lib/time.js.map +1 -1
- package/package.json +4 -5
- package/src/__tests__/__snapshots__/itinerary.js.snap +2 -38
- package/src/__tests__/__snapshots__/time.js.snap +7 -13
- package/src/__tests__/itinerary.js +6 -29
- package/src/__tests__/time.js +7 -27
- package/src/itinerary.ts +72 -27
- package/src/map.ts +19 -287
- package/src/query.js +19 -16
- package/src/time.ts +11 -76
- package/tsconfig.tsbuildinfo +1381 -1288
- package/esm/deprecated-with-types.js +0 -47
- package/esm/deprecated-with-types.js.map +0 -1
- package/esm/deprecated.js +0 -325
- package/esm/deprecated.js.map +0 -1
- package/lib/deprecated-with-types.d.ts +0 -23
- package/lib/deprecated-with-types.d.ts.map +0 -1
- package/lib/deprecated-with-types.js +0 -61
- package/lib/deprecated-with-types.js.map +0 -1
- package/lib/deprecated.js +0 -355
- package/lib/deprecated.js.map +0 -1
- package/src/__tests__/__mocks__/multi-currency-itinerary.json +0 -1728
- package/src/deprecated-with-types.ts +0 -62
- package/src/deprecated.js +0 -334
package/src/itinerary.ts
CHANGED
|
@@ -7,33 +7,37 @@ import {
|
|
|
7
7
|
Itinerary,
|
|
8
8
|
LatLngArray,
|
|
9
9
|
Leg,
|
|
10
|
-
|
|
10
|
+
Money,
|
|
11
|
+
Step,
|
|
12
|
+
TncFare
|
|
11
13
|
} from "@opentripplanner/types";
|
|
12
14
|
import turfAlong from "@turf/along";
|
|
13
15
|
|
|
16
|
+
/*
|
|
14
17
|
import {
|
|
15
|
-
calculateFares,
|
|
16
|
-
getLegModeLabel,
|
|
17
|
-
getModeForPlace,
|
|
18
|
-
getPlaceName,
|
|
19
|
-
getStepDirection,
|
|
20
|
-
getStepInstructions,
|
|
21
|
-
getStepStreetName,
|
|
22
|
-
getTimeZoneOffset,
|
|
23
|
-
getTransitFare
|
|
18
|
+
// calculateFares,
|
|
19
|
+
// getLegModeLabel,
|
|
20
|
+
// getModeForPlace,
|
|
21
|
+
// getPlaceName,
|
|
22
|
+
// getStepDirection,
|
|
23
|
+
// getStepInstructions,
|
|
24
|
+
// getStepStreetName,
|
|
25
|
+
// getTimeZoneOffset,
|
|
26
|
+
// getTransitFare
|
|
24
27
|
} from "./deprecated";
|
|
25
28
|
|
|
26
29
|
export {
|
|
27
|
-
calculateFares,
|
|
28
|
-
getLegModeLabel,
|
|
29
|
-
getModeForPlace,
|
|
30
|
-
getPlaceName,
|
|
31
|
-
getStepDirection,
|
|
32
|
-
getStepInstructions,
|
|
33
|
-
getStepStreetName,
|
|
34
|
-
getTimeZoneOffset,
|
|
35
|
-
getTransitFare
|
|
30
|
+
// calculateFares,
|
|
31
|
+
// getLegModeLabel,
|
|
32
|
+
// getModeForPlace,
|
|
33
|
+
// getPlaceName,
|
|
34
|
+
// getStepDirection,
|
|
35
|
+
// getStepInstructions,
|
|
36
|
+
// getStepStreetName,
|
|
37
|
+
// getTimeZoneOffset,
|
|
38
|
+
// getTransitFare
|
|
36
39
|
};
|
|
40
|
+
*/
|
|
37
41
|
|
|
38
42
|
// All OTP transit modes
|
|
39
43
|
export const transitModes = [
|
|
@@ -445,12 +449,53 @@ export function calculatePhysicalActivity(
|
|
|
445
449
|
};
|
|
446
450
|
}
|
|
447
451
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
452
|
+
/**
|
|
453
|
+
* For an itinerary, calculates the TNC fares and returns an object with
|
|
454
|
+
* these values and currency info.
|
|
455
|
+
* It is assumed that the same currency is used for all TNC legs.
|
|
456
|
+
*/
|
|
457
|
+
export function calculateTncFares(itinerary: Itinerary): TncFare {
|
|
458
|
+
let minTNCFare = 0;
|
|
459
|
+
let maxTNCFare = 0;
|
|
460
|
+
let currencyCode;
|
|
461
|
+
itinerary.legs.forEach(({ hailedCar, mode, tncData }) => {
|
|
462
|
+
if (mode === "CAR" && hailedCar && tncData) {
|
|
463
|
+
const { currency, maxCost, minCost } = tncData;
|
|
464
|
+
minTNCFare += minCost;
|
|
465
|
+
maxTNCFare += maxCost;
|
|
466
|
+
// Assumes a single currency for entire itinerary.
|
|
467
|
+
currencyCode = currency;
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
return {
|
|
472
|
+
currencyCode,
|
|
473
|
+
maxTNCFare,
|
|
474
|
+
minTNCFare
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* For a given fare component (either total fare or component parts), returns
|
|
480
|
+
* an object with the fare value (in cents).
|
|
481
|
+
*/
|
|
482
|
+
export function getTransitFare(
|
|
483
|
+
fareComponent: Money
|
|
484
|
+
): {
|
|
485
|
+
currencyCode: string;
|
|
486
|
+
transitFare: number;
|
|
487
|
+
} {
|
|
488
|
+
// Default values (if fare component is not valid).
|
|
489
|
+
let transitFare = 0;
|
|
490
|
+
let currencyCode = "USD";
|
|
491
|
+
if (fareComponent) {
|
|
492
|
+
// Assign values without declaration.
|
|
493
|
+
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#assignment_without_declaration
|
|
494
|
+
({ currencyCode } = fareComponent.currency);
|
|
495
|
+
transitFare = fareComponent.cents;
|
|
496
|
+
}
|
|
497
|
+
return {
|
|
498
|
+
currencyCode,
|
|
499
|
+
transitFare
|
|
500
|
+
};
|
|
456
501
|
}
|
package/src/map.ts
CHANGED
|
@@ -1,28 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
Itinerary,
|
|
4
|
-
LatLngArray,
|
|
5
|
-
Leg,
|
|
6
|
-
Location,
|
|
7
|
-
TransitiveData,
|
|
8
|
-
UserPosition
|
|
9
|
-
} from "@opentripplanner/types";
|
|
10
|
-
import {
|
|
11
|
-
getPlaceName,
|
|
12
|
-
isAccessMode,
|
|
13
|
-
isFlex,
|
|
14
|
-
isTransit,
|
|
15
|
-
toSentenceCase
|
|
16
|
-
} from "./itinerary";
|
|
1
|
+
import { LatLngArray, Location, UserPosition } from "@opentripplanner/types";
|
|
2
|
+
import { toSentenceCase } from "./itinerary";
|
|
17
3
|
|
|
4
|
+
/*
|
|
18
5
|
import {
|
|
19
|
-
coordsToString,
|
|
20
|
-
getDetailText
|
|
21
|
-
latlngToString,
|
|
22
|
-
logDeprecationWarning
|
|
6
|
+
// coordsToString,
|
|
7
|
+
// getDetailText //,
|
|
8
|
+
// latlngToString,
|
|
9
|
+
// logDeprecationWarning
|
|
23
10
|
} from "./deprecated";
|
|
24
11
|
|
|
25
|
-
export { coordsToString, getDetailText, latlngToString };
|
|
12
|
+
export { coordsToString, getDetailText , latlngToString };
|
|
13
|
+
*/
|
|
26
14
|
|
|
27
15
|
export function currentPositionToLocation(
|
|
28
16
|
currentPosition: UserPosition
|
|
@@ -40,6 +28,12 @@ export function currentPositionToLocation(
|
|
|
40
28
|
};
|
|
41
29
|
}
|
|
42
30
|
|
|
31
|
+
// TRICKY: It is used in query.js and in the context of
|
|
32
|
+
// otp-rr actions where the intl context is not available.
|
|
33
|
+
export function coordsToString(coords: number[]): string {
|
|
34
|
+
return coords.length && coords.map(c => (+c).toFixed(5)).join(", ");
|
|
35
|
+
}
|
|
36
|
+
|
|
43
37
|
export function stringToCoords(str: string): number[] {
|
|
44
38
|
return (str && str.split(",").map(c => +c)) || [];
|
|
45
39
|
}
|
|
@@ -54,23 +48,10 @@ export function constructLocation(latlng: {
|
|
|
54
48
|
};
|
|
55
49
|
}
|
|
56
50
|
|
|
57
|
-
export function formatStoredPlaceName(
|
|
58
|
-
location
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (withDetails) {
|
|
62
|
-
logDeprecationWarning("the formatStoredPlaceName withDetails parameter");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
let displayName =
|
|
66
|
-
location.type === "home" || location.type === "work"
|
|
67
|
-
? toSentenceCase(location.type)
|
|
68
|
-
: location.name;
|
|
69
|
-
if (withDetails) {
|
|
70
|
-
const detailText = getDetailText(location);
|
|
71
|
-
if (detailText) displayName += ` (${detailText})`;
|
|
72
|
-
}
|
|
73
|
-
return displayName;
|
|
51
|
+
export function formatStoredPlaceName(location: Location): string {
|
|
52
|
+
return location.type === "home" || location.type === "work"
|
|
53
|
+
? toSentenceCase(location.type)
|
|
54
|
+
: location.name;
|
|
74
55
|
}
|
|
75
56
|
|
|
76
57
|
export function matchLatLon(location1: Location, location2: Location): boolean {
|
|
@@ -78,255 +59,6 @@ export function matchLatLon(location1: Location, location2: Location): boolean {
|
|
|
78
59
|
return location1.lat === location2.lat && location1.lon === location2.lon;
|
|
79
60
|
}
|
|
80
61
|
|
|
81
|
-
/**
|
|
82
|
-
* Converts an OTP itinerary object to a transtive.js itinerary object.
|
|
83
|
-
* @param {*} itin Required OTP itinerary (see @opentripplanner/core-utils/types#itineraryType) to convert.
|
|
84
|
-
* @param {*} companies Optional list of companies, used for labeling vehicle rental locations.
|
|
85
|
-
* @param {*} getRouteLabel Optional function that takes an itinerary leg (see @opentripplanner/core-utils/types#legType)
|
|
86
|
-
* and returns a string representing the route label to display for that leg.
|
|
87
|
-
* @returns An itinerary in the transitive.js format.
|
|
88
|
-
*/
|
|
89
|
-
export function itineraryToTransitive(
|
|
90
|
-
itin: Itinerary,
|
|
91
|
-
companies: Company[],
|
|
92
|
-
getRouteLabel: (leg: Leg) => string,
|
|
93
|
-
disableFlexArc: boolean
|
|
94
|
-
): TransitiveData {
|
|
95
|
-
const tdata = {
|
|
96
|
-
journeys: [],
|
|
97
|
-
streetEdges: [],
|
|
98
|
-
places: [],
|
|
99
|
-
patterns: [],
|
|
100
|
-
routes: [],
|
|
101
|
-
stops: []
|
|
102
|
-
};
|
|
103
|
-
const routes = {};
|
|
104
|
-
const stops = {};
|
|
105
|
-
let streetEdgeId = 0;
|
|
106
|
-
let patternId = 0;
|
|
107
|
-
|
|
108
|
-
const journey = {
|
|
109
|
-
journey_id: "itin",
|
|
110
|
-
// This string is not shown in the UI
|
|
111
|
-
journey_name: "Iterarary-derived Journey",
|
|
112
|
-
segments: []
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// add 'from' and 'to' places to the tdata places array
|
|
116
|
-
tdata.places.push({
|
|
117
|
-
place_id: "from",
|
|
118
|
-
place_lat: itin.legs[0].from.lat,
|
|
119
|
-
place_lon: itin.legs[0].from.lon
|
|
120
|
-
});
|
|
121
|
-
tdata.places.push({
|
|
122
|
-
place_id: "to",
|
|
123
|
-
place_lat: itin.legs[itin.legs.length - 1].to.lat,
|
|
124
|
-
place_lon: itin.legs[itin.legs.length - 1].to.lon
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
itin.legs.forEach((leg, idx) => {
|
|
128
|
-
if (isAccessMode(leg.mode)) {
|
|
129
|
-
let fromPlaceId: string;
|
|
130
|
-
if (leg.from.bikeShareId) {
|
|
131
|
-
fromPlaceId = `bicycle_rent_station_${leg.from.bikeShareId}`;
|
|
132
|
-
if (
|
|
133
|
-
// OTP2 Scooter case
|
|
134
|
-
leg.mode === "SCOOTER"
|
|
135
|
-
) {
|
|
136
|
-
fromPlaceId = `escooter_rent_station_${leg.from.bikeShareId}`;
|
|
137
|
-
}
|
|
138
|
-
} else if (leg.from.vertexType === "VEHICLERENTAL") {
|
|
139
|
-
// OTP1 Scooter case
|
|
140
|
-
fromPlaceId = `escooter_rent_station_${leg.from.name}`;
|
|
141
|
-
} else if (
|
|
142
|
-
leg.mode === "CAR" &&
|
|
143
|
-
idx > 0 &&
|
|
144
|
-
itin.legs[idx - 1].mode === "WALK"
|
|
145
|
-
) {
|
|
146
|
-
// create a special place ID for car legs preceded by walking legs
|
|
147
|
-
fromPlaceId = `itin_car_${streetEdgeId}_from`;
|
|
148
|
-
} else if (!fromPlaceId) {
|
|
149
|
-
fromPlaceId = `itin_street_${streetEdgeId}_from`;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
let toPlaceId;
|
|
153
|
-
if (leg.to.bikeShareId) {
|
|
154
|
-
toPlaceId = `bicycle_rent_station_${leg.to.bikeShareId}`;
|
|
155
|
-
// OTP2 scooter case
|
|
156
|
-
// Need to check next leg since this is a "to" place "
|
|
157
|
-
if (leg.mode === "SCOOTER" || itin.legs?.[idx + 1].mode === "SCOOTER") {
|
|
158
|
-
toPlaceId = `escooter_rent_station_${leg.to.bikeShareId}`;
|
|
159
|
-
}
|
|
160
|
-
} else if (leg.to.vertexType === "VEHICLERENTAL") {
|
|
161
|
-
toPlaceId = `escooter_rent_station_${leg.to.name}`;
|
|
162
|
-
} else if (
|
|
163
|
-
leg.mode === "CAR" &&
|
|
164
|
-
idx < itin.legs.length - 1 &&
|
|
165
|
-
itin.legs[idx + 1].mode === "WALK"
|
|
166
|
-
) {
|
|
167
|
-
// create a special place ID for car legs followed by walking legs
|
|
168
|
-
toPlaceId = `itin_car_${streetEdgeId}_to`;
|
|
169
|
-
} else if (!toPlaceId) {
|
|
170
|
-
toPlaceId = `itin_street_${streetEdgeId}_to`;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const segment = {
|
|
174
|
-
arc: false,
|
|
175
|
-
type: leg.mode,
|
|
176
|
-
streetEdges: [streetEdgeId],
|
|
177
|
-
from: { type: "PLACE", place_id: fromPlaceId },
|
|
178
|
-
to: { type: "PLACE", place_id: toPlaceId }
|
|
179
|
-
};
|
|
180
|
-
// For TNC segments, draw using an arc
|
|
181
|
-
if (leg.mode === "CAR" && leg.hailedCar) segment.arc = true;
|
|
182
|
-
journey.segments.push(segment);
|
|
183
|
-
|
|
184
|
-
tdata.streetEdges.push({
|
|
185
|
-
edge_id: streetEdgeId,
|
|
186
|
-
geometry: leg.legGeometry
|
|
187
|
-
});
|
|
188
|
-
tdata.places.push({
|
|
189
|
-
place_id: fromPlaceId,
|
|
190
|
-
// Do not label the from place in addition to the to place. Otherwise,
|
|
191
|
-
// in some cases (bike rental station) the label for a single place will
|
|
192
|
-
// appear twice on the rendered transitive view.
|
|
193
|
-
// See https://github.com/conveyal/trimet-mod-otp/issues/152
|
|
194
|
-
// place_name: leg.from.name,
|
|
195
|
-
place_lat: leg.from.lat,
|
|
196
|
-
place_lon: leg.from.lon
|
|
197
|
-
});
|
|
198
|
-
tdata.places.push({
|
|
199
|
-
place_id: toPlaceId,
|
|
200
|
-
// This string is not shown in the UI
|
|
201
|
-
place_name: getPlaceName(leg.to, companies),
|
|
202
|
-
place_lat: leg.to.lat,
|
|
203
|
-
place_lon: leg.to.lon
|
|
204
|
-
});
|
|
205
|
-
streetEdgeId++;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (isTransit(leg.mode)) {
|
|
209
|
-
// Flex routes sometimes have the same from and to IDs, but
|
|
210
|
-
// these stops still need to be rendered separately!
|
|
211
|
-
if (leg.from.stopId === leg.to.stopId) {
|
|
212
|
-
leg.to.stopId = `${leg.to.stopId}_flexed_to`;
|
|
213
|
-
}
|
|
214
|
-
// determine if we have valid inter-stop geometry
|
|
215
|
-
const hasInterStopGeometry = !!leg.interStopGeometry;
|
|
216
|
-
const hasLegGeometry = !!leg.legGeometry?.points;
|
|
217
|
-
const hasIntermediateStopGeometry =
|
|
218
|
-
hasInterStopGeometry &&
|
|
219
|
-
leg.intermediateStops &&
|
|
220
|
-
leg.interStopGeometry.length === leg.intermediateStops.length + 1;
|
|
221
|
-
|
|
222
|
-
// create leg-specific pattern
|
|
223
|
-
const ptnId = `ptn_${patternId}`;
|
|
224
|
-
const pattern = {
|
|
225
|
-
pattern_id: ptnId,
|
|
226
|
-
// This string is not shown in the UI
|
|
227
|
-
pattern_name: `Pattern ${patternId}`,
|
|
228
|
-
route_id: leg.routeId,
|
|
229
|
-
stops: []
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
// add 'from' stop to stops dictionary and pattern object
|
|
233
|
-
stops[leg.from.stopId] = {
|
|
234
|
-
stop_id: leg.from.stopId,
|
|
235
|
-
stop_name: leg.from.name,
|
|
236
|
-
stop_lat: leg.from.lat,
|
|
237
|
-
stop_lon: leg.from.lon
|
|
238
|
-
};
|
|
239
|
-
pattern.stops.push({ stop_id: leg.from.stopId });
|
|
240
|
-
|
|
241
|
-
// add intermediate stops to stops dictionary and pattern object
|
|
242
|
-
// If there is no intermediateStopGeometry, do not add the intermediate stops
|
|
243
|
-
// as it will be straight lines instead of the nice legGeometry (but only if
|
|
244
|
-
// the legGeometry exists).
|
|
245
|
-
if (
|
|
246
|
-
leg.intermediateStops &&
|
|
247
|
-
(hasIntermediateStopGeometry || !hasLegGeometry)
|
|
248
|
-
) {
|
|
249
|
-
leg.intermediateStops.forEach((stop, i) => {
|
|
250
|
-
stops[stop.stopId] = {
|
|
251
|
-
stop_id: stop.stopId,
|
|
252
|
-
stop_name: stop.name,
|
|
253
|
-
stop_lat: stop.lat,
|
|
254
|
-
stop_lon: stop.lon
|
|
255
|
-
};
|
|
256
|
-
pattern.stops.push({
|
|
257
|
-
stop_id: stop.stopId,
|
|
258
|
-
geometry:
|
|
259
|
-
hasIntermediateStopGeometry && leg.interStopGeometry[i].points
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// add 'to' stop to stops dictionary and pattern object
|
|
265
|
-
stops[leg.to.stopId] = {
|
|
266
|
-
stop_id: leg.to.stopId,
|
|
267
|
-
stop_name: leg.to.name,
|
|
268
|
-
stop_lat: leg.to.lat,
|
|
269
|
-
stop_lon: leg.to.lon
|
|
270
|
-
};
|
|
271
|
-
pattern.stops.push({
|
|
272
|
-
stop_id: leg.to.stopId,
|
|
273
|
-
geometry:
|
|
274
|
-
// Some legs don't have intermediateStopGeometry, but do have valid legGeometry
|
|
275
|
-
(hasInterStopGeometry || hasLegGeometry) &&
|
|
276
|
-
(hasIntermediateStopGeometry
|
|
277
|
-
? leg.interStopGeometry[leg.interStopGeometry.length - 1].points
|
|
278
|
-
: leg.legGeometry.points)
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// add route to the route dictionary
|
|
282
|
-
// with a custom route label if specified.
|
|
283
|
-
const routeLabel =
|
|
284
|
-
typeof getRouteLabel === "function"
|
|
285
|
-
? getRouteLabel(leg)
|
|
286
|
-
: leg.routeShortName;
|
|
287
|
-
routes[leg.routeId] = {
|
|
288
|
-
agency_id: leg.agencyId,
|
|
289
|
-
route_id: leg.routeId,
|
|
290
|
-
route_short_name: routeLabel || "",
|
|
291
|
-
route_long_name: leg.routeLongName || "",
|
|
292
|
-
route_type: leg.routeType,
|
|
293
|
-
route_color: leg.routeColor
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
// add the pattern to the tdata patterns array
|
|
297
|
-
tdata.patterns.push(pattern);
|
|
298
|
-
|
|
299
|
-
// add the pattern reference to the journey object
|
|
300
|
-
journey.segments.push({
|
|
301
|
-
arc:
|
|
302
|
-
typeof disableFlexArc === "undefined" ? isFlex(leg) : !disableFlexArc,
|
|
303
|
-
type: "TRANSIT",
|
|
304
|
-
patterns: [
|
|
305
|
-
{
|
|
306
|
-
pattern_id: ptnId,
|
|
307
|
-
from_stop_index: 0,
|
|
308
|
-
to_stop_index: hasIntermediateStopGeometry
|
|
309
|
-
? leg.intermediateStops.length + 2 - 1
|
|
310
|
-
: 1
|
|
311
|
-
}
|
|
312
|
-
]
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
patternId++;
|
|
316
|
-
}
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
// add the routes and stops to the tdata arrays
|
|
320
|
-
tdata.routes.push(...Object.values(routes));
|
|
321
|
-
tdata.stops.push(...Object.values(stops));
|
|
322
|
-
|
|
323
|
-
// add the journey to the tdata journeys array
|
|
324
|
-
tdata.journeys.push(journey);
|
|
325
|
-
|
|
326
|
-
// console.log('derived tdata', tdata);
|
|
327
|
-
return tdata;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
62
|
type TransitivePlaceRaw = {
|
|
331
63
|
place_id: string;
|
|
332
64
|
};
|
package/src/query.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { format, isMatch, parse } from "date-fns";
|
|
2
2
|
import getGeocoder from "@opentripplanner/geocoder/lib";
|
|
3
3
|
import qs from "qs";
|
|
4
4
|
|
|
5
5
|
import { getTransitModes, hasCar, isAccessMode } from "./itinerary";
|
|
6
|
-
import { stringToCoords } from "./map";
|
|
6
|
+
import { coordsToString, stringToCoords } from "./map";
|
|
7
7
|
import queryParams from "./query-params";
|
|
8
8
|
import {
|
|
9
9
|
getCurrentTime,
|
|
10
10
|
getCurrentDate,
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
OTP_API_TIME_FORMAT,
|
|
12
|
+
OTP_API_DATE_FORMAT_DATE_FNS
|
|
13
13
|
} from "./time";
|
|
14
14
|
|
|
15
|
-
import { coordsToString, summarizeQuery } from "./deprecated";
|
|
15
|
+
// import { coordsToString, summarizeQuery } from "./deprecated";
|
|
16
16
|
|
|
17
|
-
export { summarizeQuery };
|
|
17
|
+
// export { summarizeQuery };
|
|
18
18
|
|
|
19
19
|
/* The list of default parameters considered in the settings panel */
|
|
20
20
|
|
|
@@ -315,9 +315,15 @@ export function planParamsToQuery(params) {
|
|
|
315
315
|
break;
|
|
316
316
|
case "time":
|
|
317
317
|
{
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
318
|
+
// Match one of the supported time formats
|
|
319
|
+
const matchedTimeFormat = TIME_FORMATS.find(timeFormat =>
|
|
320
|
+
isMatch(params.time, timeFormat)
|
|
321
|
+
);
|
|
322
|
+
query.time = matchedTimeFormat
|
|
323
|
+
? format(
|
|
324
|
+
parse(params.time, matchedTimeFormat, new Date()),
|
|
325
|
+
OTP_API_TIME_FORMAT
|
|
326
|
+
)
|
|
321
327
|
: getCurrentTime();
|
|
322
328
|
}
|
|
323
329
|
break;
|
|
@@ -421,8 +427,8 @@ export function getRoutingParams(config, currentQuery, ignoreRealtimeUpdates) {
|
|
|
421
427
|
}
|
|
422
428
|
|
|
423
429
|
// check date/time validity; ignore both if either is invalid
|
|
424
|
-
const dateValid =
|
|
425
|
-
const timeValid =
|
|
430
|
+
const dateValid = isMatch(params.date, OTP_API_DATE_FORMAT_DATE_FNS);
|
|
431
|
+
const timeValid = isMatch(params.time, OTP_API_TIME_FORMAT);
|
|
426
432
|
|
|
427
433
|
if (!dateValid || !timeValid) {
|
|
428
434
|
delete params.time;
|
|
@@ -447,11 +453,8 @@ export function getRoutingParams(config, currentQuery, ignoreRealtimeUpdates) {
|
|
|
447
453
|
// Additional processing specific to PROFILE mode
|
|
448
454
|
} else {
|
|
449
455
|
// check start and end time validity; ignore both if either is invalid
|
|
450
|
-
const startTimeValid =
|
|
451
|
-
|
|
452
|
-
OTP_API_TIME_FORMAT
|
|
453
|
-
).isValid();
|
|
454
|
-
const endTimeValid = moment(params.endTime, OTP_API_TIME_FORMAT).isValid();
|
|
456
|
+
const startTimeValid = isMatch(params.startTime, OTP_API_TIME_FORMAT);
|
|
457
|
+
const endTimeValid = isMatch(params.endTime, OTP_API_TIME_FORMAT);
|
|
455
458
|
|
|
456
459
|
if (!startTimeValid || !endTimeValid) {
|
|
457
460
|
delete params.startTimeValid;
|
package/src/time.ts
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
1
|
import { Config } from "@opentripplanner/types";
|
|
2
|
-
import {
|
|
3
|
-
startOfDay,
|
|
4
|
-
add,
|
|
5
|
-
format,
|
|
6
|
-
formatDuration as dateFnsFormatDuration
|
|
7
|
-
} from "date-fns";
|
|
2
|
+
import { startOfDay, add, format } from "date-fns";
|
|
8
3
|
import { utcToZonedTime } from "date-fns-tz";
|
|
9
4
|
|
|
10
|
-
/* eslint-disable import/no-cycle */
|
|
11
|
-
import {
|
|
12
|
-
formatTime,
|
|
13
|
-
formatDurationWithSeconds,
|
|
14
|
-
formatDuration
|
|
15
|
-
} from "./deprecated-with-types";
|
|
16
|
-
|
|
17
|
-
export { formatTime, formatDuration, formatDurationWithSeconds };
|
|
18
|
-
|
|
19
5
|
// special constants for making sure the following date format is always sent to
|
|
20
6
|
// OTP regardless of whatever the user has configured as the display format
|
|
21
7
|
export const OTP_API_DATE_FORMAT = "YYYY-MM-DD";
|
|
@@ -24,73 +10,22 @@ export const OTP_API_DATE_FORMAT = "YYYY-MM-DD";
|
|
|
24
10
|
export const OTP_API_DATE_FORMAT_DATE_FNS = "yyyy-MM-dd";
|
|
25
11
|
export const OTP_API_TIME_FORMAT = "HH:mm";
|
|
26
12
|
|
|
27
|
-
/**
|
|
28
|
-
* To ease the transition away from moment.js, this method uses date-fns to format durations
|
|
29
|
-
* the way moment.js did.
|
|
30
|
-
* @param {number} seconds The number of seconds to format
|
|
31
|
-
* @param {boolean} showSeconds Whether to render seconds or not
|
|
32
|
-
* @param {boolean} localize If true, will create output like moment.js using date-fns locale.
|
|
33
|
-
* Otherwise, uses date-fns default
|
|
34
|
-
* @returns Formatted duration
|
|
35
|
-
*/
|
|
36
|
-
export function formatDurationLikeMoment(
|
|
37
|
-
seconds: number,
|
|
38
|
-
showSeconds: boolean,
|
|
39
|
-
localize: { enabled: boolean; code: string } = {
|
|
40
|
-
enabled: true,
|
|
41
|
-
code: "en-US"
|
|
42
|
-
}
|
|
43
|
-
): string {
|
|
44
|
-
// date-fns doesn't do this automatically
|
|
45
|
-
if ((!showSeconds && seconds < 60) || seconds === 0) {
|
|
46
|
-
return "0 min";
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const hours = Math.floor(seconds / 3600);
|
|
50
|
-
const minutes = Math.floor((seconds - hours * 3600) / 60);
|
|
51
|
-
const secondsLeftOver = showSeconds
|
|
52
|
-
? seconds - hours * 3600 - minutes * 60
|
|
53
|
-
: 0;
|
|
54
|
-
const specLookup = {
|
|
55
|
-
xHours: "hr",
|
|
56
|
-
xMinutes: "min",
|
|
57
|
-
xSeconds: "sec"
|
|
58
|
-
};
|
|
59
|
-
const locale = localize
|
|
60
|
-
? {
|
|
61
|
-
// Maintain backwards compatibility when called with localize=true
|
|
62
|
-
code: localize?.code || "en-US",
|
|
63
|
-
formatDistance: (spec, val) => {
|
|
64
|
-
return `${val} ${specLookup[spec]}`;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
: undefined;
|
|
68
|
-
|
|
69
|
-
return dateFnsFormatDuration(
|
|
70
|
-
{
|
|
71
|
-
hours,
|
|
72
|
-
minutes,
|
|
73
|
-
seconds: secondsLeftOver
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
format: ["hours", "minutes", "seconds"],
|
|
77
|
-
locale
|
|
78
|
-
}
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
13
|
/**
|
|
83
14
|
* Breaks up a duration in seconds into hours, minutes, and seconds.
|
|
84
15
|
* @param {number} seconds The number of seconds to break up
|
|
85
16
|
* @returns an object with fields with the corresponding, hours, minutes, seconds.
|
|
86
17
|
*/
|
|
87
|
-
export function toHoursMinutesSeconds(
|
|
88
|
-
|
|
89
|
-
|
|
18
|
+
export function toHoursMinutesSeconds(
|
|
19
|
+
seconds: number
|
|
20
|
+
): {
|
|
21
|
+
hours: number;
|
|
22
|
+
minutes: number;
|
|
23
|
+
seconds: number;
|
|
24
|
+
} {
|
|
90
25
|
return {
|
|
91
|
-
hours,
|
|
92
|
-
minutes,
|
|
93
|
-
seconds: seconds
|
|
26
|
+
hours: Math.floor(seconds / 3600),
|
|
27
|
+
minutes: Math.floor(seconds / 60) % 60,
|
|
28
|
+
seconds: seconds % 60
|
|
94
29
|
};
|
|
95
30
|
}
|
|
96
31
|
|