@opentripplanner/core-utils 4.4.1 → 4.7.0

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/src/map.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import moment from "moment";
2
2
 
3
- import { getPlaceName, isTransit, toSentenceCase } from "./itinerary";
3
+ import { getPlaceName, isTransit, isFlex, toSentenceCase } from "./itinerary";
4
4
 
5
5
  export function latlngToString(latlng) {
6
6
  return (
@@ -181,9 +181,16 @@ export function itineraryToTransitive(itin, companies, getRouteLabel) {
181
181
  });
182
182
  streetEdgeId++;
183
183
  }
184
+
184
185
  if (isTransit(leg.mode)) {
186
+ // Flex routes sometimes have the same from and to IDs, but
187
+ // these stops still need to be rendered separately!
188
+ if (leg.from.stopId === leg.to.stopId) {
189
+ leg.to.stopId = `${leg.to.stopId}_flexed_to`;
190
+ }
185
191
  // determine if we have valid inter-stop geometry
186
192
  const hasInterStopGeometry = !!leg.interStopGeometry;
193
+ const hasLegGeometry = !!leg.legGeometry?.points;
187
194
  const hasIntermediateStopGeometry =
188
195
  hasInterStopGeometry &&
189
196
  leg.intermediateStops &&
@@ -208,7 +215,13 @@ export function itineraryToTransitive(itin, companies, getRouteLabel) {
208
215
  pattern.stops.push({ stop_id: leg.from.stopId });
209
216
 
210
217
  // add intermediate stops to stops dictionary and pattern object
211
- if (leg.intermediateStops) {
218
+ // If there is no intermediateStopGeometry, do not add the intermediate stops
219
+ // as it will be straight lines instead of the nice legGeometry (but only if
220
+ // the legGeometry exists).
221
+ if (
222
+ leg.intermediateStops &&
223
+ (hasIntermediateStopGeometry || !hasLegGeometry)
224
+ ) {
212
225
  leg.intermediateStops.forEach((stop, i) => {
213
226
  stops[stop.stopId] = {
214
227
  stop_id: stop.stopId,
@@ -234,7 +247,8 @@ export function itineraryToTransitive(itin, companies, getRouteLabel) {
234
247
  pattern.stops.push({
235
248
  stop_id: leg.to.stopId,
236
249
  geometry:
237
- hasInterStopGeometry &&
250
+ // Some legs don't have intermediateStopGeometry, but do have valid legGeometry
251
+ (hasInterStopGeometry || hasLegGeometry) &&
238
252
  (hasIntermediateStopGeometry
239
253
  ? leg.interStopGeometry[leg.interStopGeometry.length - 1].points
240
254
  : leg.legGeometry.points)
@@ -260,12 +274,13 @@ export function itineraryToTransitive(itin, companies, getRouteLabel) {
260
274
 
261
275
  // add the pattern reference to the journey object
262
276
  journey.segments.push({
277
+ arc: isFlex(leg),
263
278
  type: "TRANSIT",
264
279
  patterns: [
265
280
  {
266
281
  pattern_id: ptnId,
267
282
  from_stop_index: 0,
268
- to_stop_index: leg.intermediateStops
283
+ to_stop_index: hasIntermediateStopGeometry
269
284
  ? leg.intermediateStops.length + 2 - 1
270
285
  : 1
271
286
  }
package/src/query.js CHANGED
@@ -163,13 +163,32 @@ function isParamApplicable(paramInfo, query, config) {
163
163
  return true;
164
164
  }
165
165
 
166
+ /**
167
+ * Helper method which replaces OTP flex modes with single FLEX mode that's
168
+ * more useful and easier to work with.
169
+ */
170
+ export function reduceOtpFlexModes(modes) {
171
+ return modes.reduce((prev, cur) => {
172
+ const newModes = prev;
173
+ // Add the current mode if it is not a flex mode
174
+ if (!cur.includes("FLEX")) {
175
+ newModes.push(cur);
176
+ // If it is a flex mode, do not add it but rather add the custom flex mode
177
+ // if not already present
178
+ } else if (!newModes.includes("FLEX")) {
179
+ newModes.push("FLEX");
180
+ }
181
+ return newModes;
182
+ }, []);
183
+ }
184
+
166
185
  /**
167
186
  * Determines whether the specified query differs from the default query, i.e.,
168
187
  * whether the user has modified any trip options (including mode) from their
169
188
  * default values.
170
189
  */
171
190
  export function isNotDefaultQuery(query, config) {
172
- const activeModes = query.mode.split(",").sort();
191
+ const activeModes = reduceOtpFlexModes(query.mode.split(",").sort());
173
192
  if (
174
193
  activeModes.length !== 2 ||
175
194
  activeModes[0] !== "TRANSIT" ||
@@ -444,5 +463,12 @@ export function getRoutingParams(config, currentQuery, ignoreRealtimeUpdates) {
444
463
  params.mode += ",WALK";
445
464
  }
446
465
 
466
+ // Replace FLEX placeholder with OTP flex modes
467
+ if (params.mode) {
468
+ // Ensure query is in reduced format to avoid replacing twice
469
+ const mode = reduceOtpFlexModes(params.mode.split(",")).join(",");
470
+ params.mode = mode.replace("FLEX", "FLEX_EGRESS,FLEX_ACCESS,FLEX_DIRECT");
471
+ }
472
+
447
473
  return params;
448
474
  }
package/src/types.js CHANGED
@@ -246,7 +246,7 @@ export const legType = PropTypes.shape({
246
246
  duration: PropTypes.number.isRequired,
247
247
  endTime: PropTypes.number.isRequired,
248
248
  from: placeType.isRequired,
249
- hailedCar: PropTypes.bool.isRequired,
249
+ hailedCar: PropTypes.bool,
250
250
  headsign: PropTypes.string,
251
251
  interlineWithPreviousLeg: PropTypes.bool.isRequired,
252
252
  intermediateStops: PropTypes.arrayOf(placeType).isRequired,