@opentripplanner/core-utils 14.3.1 → 14.3.3
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/README.md +1 -0
- package/esm/itinerary.js +13 -16
- package/esm/itinerary.js.map +1 -1
- package/lib/index.js +36 -23
- package/lib/index.js.map +1 -1
- package/lib/itinerary.d.ts +6 -8
- package/lib/itinerary.d.ts.map +1 -1
- package/lib/itinerary.js +620 -540
- package/lib/itinerary.js.map +1 -1
- package/lib/map.js +51 -38
- package/lib/map.js.map +1 -1
- package/lib/query-gen.js +141 -128
- package/lib/query-gen.js.map +1 -1
- package/lib/route.js +261 -225
- package/lib/route.js.map +1 -1
- package/lib/storage.js +31 -22
- package/lib/storage.js.map +1 -1
- package/lib/suspense.js +17 -5
- package/lib/suspense.js.map +1 -1
- package/lib/time.js +58 -33
- package/lib/time.js.map +1 -1
- package/lib/ui.js +39 -31
- package/lib/ui.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/itinerary.ts +34 -21
- package/src/itinerary.ts +21 -17
- package/tsconfig.tsbuildinfo +1 -1
package/lib/route.js
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.alphabeticShortNameComparator = alphabeticShortNameComparator;
|
|
8
|
+
exports.getMostReadableTextColor = getMostReadableTextColor;
|
|
9
|
+
exports.getRouteSortOrderValue = getRouteSortOrderValue;
|
|
10
|
+
exports.getTransitOperatorFromFeedIdAndAgencyId = getTransitOperatorFromFeedIdAndAgencyId;
|
|
11
|
+
exports.getTransitOperatorFromLeg = getTransitOperatorFromLeg;
|
|
12
|
+
exports.getTransitOperatorFromOtpRoute = getTransitOperatorFromOtpRoute;
|
|
13
|
+
exports.makeMultiCriteriaSort = makeMultiCriteriaSort;
|
|
14
|
+
exports.makeNumericValueComparator = makeNumericValueComparator;
|
|
15
|
+
exports.makeRouteComparator = makeRouteComparator;
|
|
16
|
+
exports.makeStringValueComparator = makeStringValueComparator;
|
|
17
|
+
exports.makeTransitOperatorComparator = makeTransitOperatorComparator;
|
|
18
|
+
exports.routeTypeComparator = routeTypeComparator;
|
|
19
|
+
var _chromaJs = _interopRequireDefault(require("chroma-js"));
|
|
2
20
|
/**
|
|
3
21
|
* Returns the transit operator (if an exact match is found) from the transit
|
|
4
22
|
* operators config value. It is critical to use both the feedId and agencyId in
|
|
@@ -11,10 +29,10 @@ import chroma from "chroma-js";
|
|
|
11
29
|
* @return {object} The transitOperator if a match was found or null if no match
|
|
12
30
|
* was found
|
|
13
31
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
transitOperator.agencyId === agencyId) || null);
|
|
32
|
+
function getTransitOperatorFromFeedIdAndAgencyId(feedId, agencyId, transitOperators) {
|
|
33
|
+
return transitOperators.find(transitOperator => transitOperator.feedId === feedId && transitOperator.agencyId === agencyId) || null;
|
|
17
34
|
}
|
|
35
|
+
|
|
18
36
|
/**
|
|
19
37
|
* Looks up an operator from the provided leg.
|
|
20
38
|
*
|
|
@@ -23,12 +41,12 @@ export function getTransitOperatorFromFeedIdAndAgencyId(feedId, agencyId, transi
|
|
|
23
41
|
* @param {object} transitOperators transitOperators from config.
|
|
24
42
|
* @return {object} the operator if one was found or null if no match was found
|
|
25
43
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return getTransitOperatorFromFeedIdAndAgencyId(feedId, leg.agencyId, transitOperators);
|
|
44
|
+
function getTransitOperatorFromLeg(leg, transitOperators) {
|
|
45
|
+
if (!leg.routeId || !leg.agencyId) return null;
|
|
46
|
+
const feedId = leg.routeId.split(":")[0];
|
|
47
|
+
return getTransitOperatorFromFeedIdAndAgencyId(feedId, leg.agencyId, transitOperators);
|
|
31
48
|
}
|
|
49
|
+
|
|
32
50
|
/**
|
|
33
51
|
* Looks up an operator from the provided configuration given an OTP route.
|
|
34
52
|
* NOTE: this assumes the use of the OTP Route model or a modified OTP
|
|
@@ -39,34 +57,34 @@ export function getTransitOperatorFromLeg(leg, transitOperators) {
|
|
|
39
57
|
* @param {array} transitOperators transitOperators from config
|
|
40
58
|
* @return {object} the operator if one was found or null if no match was found
|
|
41
59
|
*/
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
return getTransitOperatorFromFeedIdAndAgencyId(feedId, agencyId, transitOperators);
|
|
60
|
+
function getTransitOperatorFromOtpRoute(route, transitOperators) {
|
|
61
|
+
if (!route.id) return null;
|
|
62
|
+
const feedId = route.id.split(":")[0];
|
|
63
|
+
let agencyId;
|
|
64
|
+
if (route.agency) {
|
|
65
|
+
// This is returned in OTP2
|
|
66
|
+
agencyId = route.agency.id;
|
|
67
|
+
} else if (route.agencyId) {
|
|
68
|
+
// This is returned in OTP1
|
|
69
|
+
agencyId = route.agencyId;
|
|
70
|
+
} else {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
return getTransitOperatorFromFeedIdAndAgencyId(feedId, agencyId, transitOperators);
|
|
59
74
|
}
|
|
75
|
+
|
|
60
76
|
// The functions below are for enhanced route sorting functions for the route
|
|
61
77
|
// viewer on OTP-react-redux.
|
|
62
78
|
// They address route ordering issues discussed in
|
|
63
79
|
// https://github.com/opentripplanner/otp-react-redux/pull/123 and
|
|
64
80
|
// https://github.com/opentripplanner/otp-react-redux/pull/124.
|
|
81
|
+
|
|
65
82
|
/**
|
|
66
83
|
* A large comparator value that can safely be used in mathematical sort
|
|
67
84
|
* comparisons to place things at the end of lists
|
|
68
85
|
*/
|
|
69
86
|
const END_OF_LIST_COMPARATOR_VALUE = 999999999999;
|
|
87
|
+
|
|
70
88
|
/**
|
|
71
89
|
* Returns a transit operator comparator value given a route and an optional
|
|
72
90
|
* transitOperators config value. This function will do its best to handle all
|
|
@@ -81,169 +99,180 @@ const END_OF_LIST_COMPARATOR_VALUE = 999999999999;
|
|
|
81
99
|
* returned.
|
|
82
100
|
*/
|
|
83
101
|
function getTransitOperatorComparatorValue(route, transitOperators) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
? transitOperator.order
|
|
105
|
-
: END_OF_LIST_COMPARATOR_VALUE;
|
|
102
|
+
// if the transitOperators is undefined or has zero length, use the route's
|
|
103
|
+
// agency name as the comparator value
|
|
104
|
+
if (!transitOperators || transitOperators.length === 0) {
|
|
105
|
+
// OTP2 Route
|
|
106
|
+
if (route.agency) return route.agency.name;
|
|
107
|
+
// OTP1 Route
|
|
108
|
+
if (route.agencyName) return route.agencyName;
|
|
109
|
+
// shouldn't happen as agency names will be defined
|
|
110
|
+
return "zzz";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// find operator associated with route
|
|
114
|
+
const transitOperator = getTransitOperatorFromOtpRoute(route, transitOperators);
|
|
115
|
+
|
|
116
|
+
// if transit operator not found, return infinity
|
|
117
|
+
if (!transitOperator) return END_OF_LIST_COMPARATOR_VALUE;
|
|
118
|
+
|
|
119
|
+
// return the transit operator's sort value or END_OF_LIST_COMPARATOR_VALUE if
|
|
120
|
+
// the sort value is not a number
|
|
121
|
+
return typeof transitOperator.order === "number" ? transitOperator.order : END_OF_LIST_COMPARATOR_VALUE;
|
|
106
122
|
}
|
|
123
|
+
|
|
107
124
|
/**
|
|
108
125
|
* Calculates the sort comparator value given two routes based off of the
|
|
109
126
|
* route's agency and provided transitOperators config data.
|
|
110
127
|
*/
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return aVal - bVal;
|
|
127
|
-
};
|
|
128
|
+
function makeTransitOperatorComparator(transitOperators) {
|
|
129
|
+
return (a, b) => {
|
|
130
|
+
const aVal = getTransitOperatorComparatorValue(a, transitOperators);
|
|
131
|
+
const bVal = getTransitOperatorComparatorValue(b, transitOperators);
|
|
132
|
+
if (typeof aVal === "string") {
|
|
133
|
+
// happens when transitOperators is undefined. Both aVal are guaranteed to
|
|
134
|
+
// be strings. Make a string comparison.
|
|
135
|
+
if (aVal < bVal) return -1;
|
|
136
|
+
if (aVal > bVal) return 1;
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
// @ts-expect-error transitOperators are defined and therefore a numeric value is guaranteed
|
|
140
|
+
// to be returned
|
|
141
|
+
return aVal - bVal;
|
|
142
|
+
};
|
|
128
143
|
}
|
|
144
|
+
|
|
129
145
|
/**
|
|
130
146
|
* Gets the desired sort values according to an optional getter function. If the
|
|
131
147
|
* getter function is not defined, the original sort values are returned.
|
|
132
148
|
*/
|
|
133
149
|
function getSortValues(getterFn, a, b) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
150
|
+
let aVal;
|
|
151
|
+
let bVal;
|
|
152
|
+
if (typeof getterFn === "function") {
|
|
153
|
+
aVal = getterFn(a);
|
|
154
|
+
bVal = getterFn(b);
|
|
155
|
+
} else {
|
|
156
|
+
aVal = a;
|
|
157
|
+
bVal = b;
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
aVal,
|
|
161
|
+
bVal
|
|
162
|
+
};
|
|
145
163
|
}
|
|
164
|
+
|
|
146
165
|
// Lookup for the sort values associated with various OTP modes.
|
|
147
166
|
// Note: JSDoc format not used to avoid bug in documentationjs.
|
|
148
167
|
// https://github.com/documentationjs/documentation/issues/372
|
|
149
168
|
const modeComparatorValue = {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
169
|
+
SUBWAY: 1,
|
|
170
|
+
TRAM: 2,
|
|
171
|
+
TROLLEYBUS: 9,
|
|
172
|
+
RAIL: 3,
|
|
173
|
+
GONDOLA: 4,
|
|
174
|
+
FERRY: 5,
|
|
175
|
+
CABLE_CAR: 6,
|
|
176
|
+
FUNICULAR: 7,
|
|
177
|
+
BUS: 8
|
|
159
178
|
};
|
|
179
|
+
|
|
160
180
|
// Lookup that maps route types to the OTP mode sort values.
|
|
161
181
|
// Note: JSDoc format not used to avoid bug in documentationjs.
|
|
162
182
|
// https://github.com/documentationjs/documentation/issues/372
|
|
163
183
|
const routeTypeComparatorValue = {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
0: modeComparatorValue.TRAM,
|
|
185
|
+
// - Tram, Streetcar, Light rail.
|
|
186
|
+
1: modeComparatorValue.SUBWAY,
|
|
187
|
+
// - Subway, Metro.
|
|
188
|
+
2: modeComparatorValue.RAIL,
|
|
189
|
+
// - Rail. Used for intercity or long-distance travel.
|
|
190
|
+
3: modeComparatorValue.BUS,
|
|
191
|
+
// - Bus.
|
|
192
|
+
4: modeComparatorValue.FERRY,
|
|
193
|
+
// - Ferry.
|
|
194
|
+
5: modeComparatorValue.CABLE_CAR,
|
|
195
|
+
// - Cable tram.
|
|
196
|
+
6: modeComparatorValue.GONDOLA,
|
|
197
|
+
// - Gondola, etc.
|
|
198
|
+
7: modeComparatorValue.FUNICULAR,
|
|
199
|
+
// - Funicular.
|
|
200
|
+
// TODO: 11 and 12 are not a part of OTP as of 2019-02-14, but for now just
|
|
201
|
+
// associate them with bus/rail.
|
|
202
|
+
11: modeComparatorValue.BUS,
|
|
203
|
+
// - Trolleybus.
|
|
204
|
+
12: modeComparatorValue.RAIL,
|
|
205
|
+
// - Monorail.
|
|
206
|
+
13: modeComparatorValue.TROLLEYBUS
|
|
177
207
|
};
|
|
208
|
+
|
|
178
209
|
// Gets a comparator value for a given route's type (OTP mode).
|
|
179
210
|
// Note: JSDoc format not used to avoid bug in documentationjs.
|
|
180
211
|
// ttps://github.com/documentationjs/documentation/issues/372
|
|
181
212
|
function getRouteTypeComparatorValue(route) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return END_OF_LIST_COMPARATOR_VALUE;
|
|
213
|
+
// For some strange reason, the short route response in OTP returns the
|
|
214
|
+
// string-based modes, but the long route response returns the
|
|
215
|
+
// integer route type. This attempts to account for both of those cases.
|
|
216
|
+
if (!route) throw new Error(`Route is undefined. ${route}`);
|
|
217
|
+
if (typeof modeComparatorValue[route.mode] !== "undefined") {
|
|
218
|
+
return modeComparatorValue[route.mode];
|
|
219
|
+
}
|
|
220
|
+
if (typeof routeTypeComparatorValue[route.type] !== "undefined") {
|
|
221
|
+
return routeTypeComparatorValue[route.type];
|
|
222
|
+
}
|
|
223
|
+
// Default the comparator value to a large number (placing the route at the
|
|
224
|
+
// end of the list).
|
|
225
|
+
// eslint-disable-next-line no-console
|
|
226
|
+
console.warn("no mode/route type found for route", route);
|
|
227
|
+
return END_OF_LIST_COMPARATOR_VALUE;
|
|
198
228
|
}
|
|
229
|
+
|
|
199
230
|
/**
|
|
200
231
|
* Calculates the sort comparator value given two routes based off of route type
|
|
201
232
|
* (OTP mode).
|
|
202
233
|
*/
|
|
203
|
-
|
|
204
|
-
|
|
234
|
+
function routeTypeComparator(a, b) {
|
|
235
|
+
return getRouteTypeComparatorValue(a) - getRouteTypeComparatorValue(b);
|
|
205
236
|
}
|
|
237
|
+
|
|
206
238
|
/**
|
|
207
239
|
* Determines whether a value is a string that starts with an alphabetic
|
|
208
240
|
* ascii character.
|
|
209
241
|
*/
|
|
210
242
|
function startsWithAlphabeticCharacter(val) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return false;
|
|
243
|
+
if (typeof val === "string" && val.length > 0) {
|
|
244
|
+
const firstCharCode = val.charCodeAt(0);
|
|
245
|
+
return firstCharCode >= 65 && firstCharCode <= 90 || firstCharCode >= 97 && firstCharCode <= 122;
|
|
246
|
+
}
|
|
247
|
+
return false;
|
|
217
248
|
}
|
|
249
|
+
|
|
218
250
|
/**
|
|
219
251
|
* Sorts routes based off of whether the shortName begins with an alphabetic
|
|
220
252
|
* character. Routes with shortn that do start with an alphabetic character will
|
|
221
253
|
* be prioritized over those that don't.
|
|
222
254
|
*/
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return 0;
|
|
229
|
-
}
|
|
230
|
-
// a does start with an alphabetic character, but b does not. Prioritize a
|
|
231
|
-
if (aStartsWithAlphabeticCharacter)
|
|
232
|
-
return -1;
|
|
233
|
-
// b does start with an alphabetic character, but a does not. Prioritize b
|
|
234
|
-
if (bStartsWithAlphabeticCharacter)
|
|
235
|
-
return 1;
|
|
236
|
-
// neither route has a shortName that starts with an alphabetic character.
|
|
237
|
-
// Return equivalence
|
|
255
|
+
function alphabeticShortNameComparator(a, b) {
|
|
256
|
+
const aStartsWithAlphabeticCharacter = startsWithAlphabeticCharacter(a.shortName);
|
|
257
|
+
const bStartsWithAlphabeticCharacter = startsWithAlphabeticCharacter(b.shortName);
|
|
258
|
+
if (aStartsWithAlphabeticCharacter && bStartsWithAlphabeticCharacter) {
|
|
259
|
+
// both start with an alphabetic character, return equivalence
|
|
238
260
|
return 0;
|
|
261
|
+
}
|
|
262
|
+
// a does start with an alphabetic character, but b does not. Prioritize a
|
|
263
|
+
if (aStartsWithAlphabeticCharacter) return -1;
|
|
264
|
+
// b does start with an alphabetic character, but a does not. Prioritize b
|
|
265
|
+
if (bStartsWithAlphabeticCharacter) return 1;
|
|
266
|
+
// neither route has a shortName that starts with an alphabetic character.
|
|
267
|
+
// Return equivalence
|
|
268
|
+
return 0;
|
|
239
269
|
}
|
|
240
|
-
const isNullOrNaN =
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
return typeof val !== "number";
|
|
270
|
+
const isNullOrNaN = val => {
|
|
271
|
+
// isNaN(null) returns false so we have to check for null explicitly.
|
|
272
|
+
// Note: Using the global version of isNaN (the Number version behaves differently.
|
|
273
|
+
// eslint-disable-next-line no-restricted-globals
|
|
274
|
+
if (typeof val === null || isNaN(val)) return true;
|
|
275
|
+
return typeof val !== "number";
|
|
247
276
|
};
|
|
248
277
|
/**
|
|
249
278
|
* Checks whether an appropriate comparison of numeric values can be made for
|
|
@@ -264,24 +293,29 @@ const isNullOrNaN = (val) => {
|
|
|
264
293
|
* @param {function} [objGetterFn] An optional function to obtain the
|
|
265
294
|
* comparison value from the comparator function arguments
|
|
266
295
|
*/
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
296
|
+
function makeNumericValueComparator(objGetterFn) {
|
|
297
|
+
return (a, b) => {
|
|
298
|
+
const {
|
|
299
|
+
aVal,
|
|
300
|
+
bVal
|
|
301
|
+
} = getSortValues(objGetterFn, a, b);
|
|
302
|
+
|
|
303
|
+
// if both values aren't valid numbers, use the next sort criteria
|
|
304
|
+
if (isNullOrNaN(aVal) && isNullOrNaN(bVal)) {
|
|
305
|
+
return 0;
|
|
306
|
+
}
|
|
307
|
+
// b is a valid number, b gets priority
|
|
308
|
+
if (isNullOrNaN(aVal)) return 1;
|
|
309
|
+
|
|
310
|
+
// a is a valid number, a gets priority
|
|
311
|
+
if (isNullOrNaN(bVal)) return -1;
|
|
312
|
+
|
|
313
|
+
// a and b are valid numbers, return the sort value
|
|
314
|
+
// @ts-expect-error We know from the checks above that both aVal and bVal are valid numbers.
|
|
315
|
+
return aVal - bVal;
|
|
316
|
+
};
|
|
284
317
|
}
|
|
318
|
+
|
|
285
319
|
/**
|
|
286
320
|
* Create a comparator function that compares string values. The comparison
|
|
287
321
|
* values feed to the sort comparator function are assumed to be objects that
|
|
@@ -292,26 +326,25 @@ export function makeNumericValueComparator(objGetterFn) {
|
|
|
292
326
|
* @param {function} [objGetterFn] An optional function to obtain the
|
|
293
327
|
* comparison value from the comparator function arguments
|
|
294
328
|
*/
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
return 0;
|
|
313
|
-
};
|
|
329
|
+
function makeStringValueComparator(objGetterFn) {
|
|
330
|
+
return (a, b) => {
|
|
331
|
+
const {
|
|
332
|
+
aVal,
|
|
333
|
+
bVal
|
|
334
|
+
} = getSortValues(objGetterFn, a, b);
|
|
335
|
+
// both a and b are uncomparable strings, return equivalent value
|
|
336
|
+
if (!aVal && !bVal) return 0;
|
|
337
|
+
// a is not a comparable string, b gets priority
|
|
338
|
+
if (!aVal) return 1;
|
|
339
|
+
// b is not a comparable string, a gets priority
|
|
340
|
+
if (!bVal) return -1;
|
|
341
|
+
// a and b are comparable strings, return the sort value
|
|
342
|
+
if (aVal < bVal) return -1;
|
|
343
|
+
if (aVal > bVal) return 1;
|
|
344
|
+
return 0;
|
|
345
|
+
};
|
|
314
346
|
}
|
|
347
|
+
|
|
315
348
|
/**
|
|
316
349
|
* OTP1 sets the routeSortOrder to -999 by default. If we're encountering that value in OTP1,
|
|
317
350
|
* assume that it actually means that the route sortOrder is not set in the GTFS. If we encounter
|
|
@@ -321,14 +354,17 @@ export function makeStringValueComparator(objGetterFn) {
|
|
|
321
354
|
* Also see https://github.com/opentripplanner/otp-react-redux/issues/122
|
|
322
355
|
* This was updated in OTP2 TO be empty by default. https://docs.opentripplanner.org/en/v2.3.0/OTP2-MigrationGuide/#:~:text=the%20Alerts-,Changes%20to%20the%20Index%20API,-Error%20handling%20is
|
|
323
356
|
*/
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
return
|
|
357
|
+
function getRouteSortOrderValue(route) {
|
|
358
|
+
const isOTP1 = !!route.agencyId;
|
|
359
|
+
const {
|
|
360
|
+
sortOrder
|
|
361
|
+
} = route;
|
|
362
|
+
if (isOTP1 && sortOrder === -999 || sortOrder === undefined) {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
return sortOrder;
|
|
331
366
|
}
|
|
367
|
+
|
|
332
368
|
/**
|
|
333
369
|
* Create a multi-criteria sort comparator function composed of other sort
|
|
334
370
|
* comparator functions. Each comparator function will be ran in the order given
|
|
@@ -336,19 +372,20 @@ export function getRouteSortOrderValue(route) {
|
|
|
336
372
|
* returned. If all comparison functions return equivalence, then the values
|
|
337
373
|
* are assumed to be equivalent.
|
|
338
374
|
*/
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
375
|
+
function makeMultiCriteriaSort(...criteria) {
|
|
376
|
+
return (a, b) => {
|
|
377
|
+
for (let i = 0; i < criteria.length; i++) {
|
|
378
|
+
const curCriteriaComparatorValue = criteria[i](a, b);
|
|
379
|
+
// if the comparison objects are not equivalent, return the value obtained
|
|
380
|
+
// in this current criteria comparison
|
|
381
|
+
if (curCriteriaComparatorValue !== 0) {
|
|
382
|
+
return curCriteriaComparatorValue;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return 0;
|
|
386
|
+
};
|
|
351
387
|
}
|
|
388
|
+
|
|
352
389
|
/**
|
|
353
390
|
* Creates a sort comparator function to compares routes for the purposes of
|
|
354
391
|
* sorting and displaying in a user interface. This takes in a single optional
|
|
@@ -380,9 +417,10 @@ export function makeMultiCriteriaSort(...criteria) {
|
|
|
380
417
|
* those with shortNames.
|
|
381
418
|
* 7. longName as string.
|
|
382
419
|
*/
|
|
383
|
-
|
|
384
|
-
|
|
420
|
+
function makeRouteComparator(transitOperators) {
|
|
421
|
+
return makeMultiCriteriaSort(makeTransitOperatorComparator(transitOperators), makeNumericValueComparator(obj => getRouteSortOrderValue(obj)), routeTypeComparator, alphabeticShortNameComparator, makeNumericValueComparator(obj => parseInt(obj.shortName, 10)), makeStringValueComparator(obj => obj.shortName), makeStringValueComparator(obj => obj.longName));
|
|
385
422
|
}
|
|
423
|
+
|
|
386
424
|
/**
|
|
387
425
|
* Tests if a pair of colors is readable. If it is, that readable color is returned.
|
|
388
426
|
* If it is not, a more appropriate alternative is returned.
|
|
@@ -396,29 +434,27 @@ export function makeRouteComparator(transitOperators) {
|
|
|
396
434
|
* @param backgroundColor A hex string, usually the "routeColor"
|
|
397
435
|
* @param proposedTextColor A hex string, usually the "routeTextColor"
|
|
398
436
|
*/
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
// When generating colors, white is preferred.
|
|
422
|
-
return chroma(backgroundColor).luminance() < 0.4 ? "#ffffff" : "#000000";
|
|
437
|
+
function getMostReadableTextColor(backgroundColor, proposedTextColor) {
|
|
438
|
+
// Sometimes input will defy the method signature. Therefore we need extra fallbacks
|
|
439
|
+
if (!backgroundColor) backgroundColor = "#333333";
|
|
440
|
+
if (!proposedTextColor) proposedTextColor = "#ffffff";
|
|
441
|
+
if (!backgroundColor.startsWith("#")) {
|
|
442
|
+
backgroundColor = `#${backgroundColor}`;
|
|
443
|
+
}
|
|
444
|
+
if (!proposedTextColor.startsWith("#")) {
|
|
445
|
+
proposedTextColor = `#${proposedTextColor}`;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Check if proposed color is readable
|
|
449
|
+
// Luminance thresholds have been selected based on actual transit agency colors
|
|
450
|
+
const fgLuminance = (0, _chromaJs.default)(proposedTextColor).luminance();
|
|
451
|
+
const bgLuminance = (0, _chromaJs.default)(backgroundColor).luminance();
|
|
452
|
+
if (bgLuminance + fgLuminance < 1.41 && bgLuminance + fgLuminance > 0.25 && Math.abs(bgLuminance - fgLuminance) > 0.2) {
|
|
453
|
+
return proposedTextColor;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Return black or white based on luminance of background color
|
|
457
|
+
// When generating colors, white is preferred.
|
|
458
|
+
return (0, _chromaJs.default)(backgroundColor).luminance() < 0.4 ? "#ffffff" : "#000000";
|
|
423
459
|
}
|
|
424
460
|
//# sourceMappingURL=route.js.map
|