@opentripplanner/core-utils 9.0.0-alpha.2 → 9.0.0-alpha.20

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.
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.extractAdditionalModes = extractAdditionalModes;
7
+ exports.generateCombinations = generateCombinations;
8
+ exports.generateOtp2Query = generateOtp2Query;
9
+ exports.TRANSIT_SUBMODES_AND_TRANSIT = exports.TRANSIT_SUBMODES = exports.SIMPLIFICATIONS = void 0;
10
+
11
+ var _graphql = require("graphql");
12
+
13
+ var PlanQuery = { kind: "Document", definitions: [{ kind: "OperationDefinition", operation: "query", name: { kind: "Name", value: "PlanQuery" }, variableDefinitions: [{ kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "fromPlace" } }, type: { kind: "NonNullType", type: { kind: "NamedType", name: { kind: "Name", value: "String" } } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "toPlace" } }, type: { kind: "NonNullType", type: { kind: "NamedType", name: { kind: "Name", value: "String" } } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "modes" } }, type: { kind: "ListType", type: { kind: "NamedType", name: { kind: "Name", value: "TransportMode" } } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "time" } }, type: { kind: "NamedType", name: { kind: "Name", value: "String" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "date" } }, type: { kind: "NamedType", name: { kind: "Name", value: "String" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "wheelchair" } }, type: { kind: "NamedType", name: { kind: "Name", value: "Boolean" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "bikeReluctance" } }, type: { kind: "NamedType", name: { kind: "Name", value: "Float" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "carReluctance" } }, type: { kind: "NamedType", name: { kind: "Name", value: "Float" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "walkReluctance" } }, type: { kind: "NamedType", name: { kind: "Name", value: "Float" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "arriveBy" } }, type: { kind: "NamedType", name: { kind: "Name", value: "Boolean" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "intermediatePlaces" } }, type: { kind: "ListType", type: { kind: "NamedType", name: { kind: "Name", value: "InputCoordinates" } } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "preferred" } }, type: { kind: "NamedType", name: { kind: "Name", value: "InputPreferred" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "unpreferred" } }, type: { kind: "NamedType", name: { kind: "Name", value: "InputUnpreferred" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "banned" } }, type: { kind: "NamedType", name: { kind: "Name", value: "InputBanned" } }, directives: [] }, { kind: "VariableDefinition", variable: { kind: "Variable", name: { kind: "Name", value: "numItineraries" } }, type: { kind: "NamedType", name: { kind: "Name", value: "Int" } }, directives: [] }], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "plan" }, arguments: [{ kind: "Argument", name: { kind: "Name", value: "fromPlace" }, value: { kind: "Variable", name: { kind: "Name", value: "fromPlace" } } }, { kind: "Argument", name: { kind: "Name", value: "toPlace" }, value: { kind: "Variable", name: { kind: "Name", value: "toPlace" } } }, { kind: "Argument", name: { kind: "Name", value: "transportModes" }, value: { kind: "Variable", name: { kind: "Name", value: "modes" } } }, { kind: "Argument", name: { kind: "Name", value: "locale" }, value: { kind: "StringValue", value: "en", block: false } }, { kind: "Argument", name: { kind: "Name", value: "time" }, value: { kind: "Variable", name: { kind: "Name", value: "time" } } }, { kind: "Argument", name: { kind: "Name", value: "date" }, value: { kind: "Variable", name: { kind: "Name", value: "date" } } }, { kind: "Argument", name: { kind: "Name", value: "wheelchair" }, value: { kind: "Variable", name: { kind: "Name", value: "wheelchair" } } }, { kind: "Argument", name: { kind: "Name", value: "bikeReluctance" }, value: { kind: "Variable", name: { kind: "Name", value: "bikeReluctance" } } }, { kind: "Argument", name: { kind: "Name", value: "carReluctance" }, value: { kind: "Variable", name: { kind: "Name", value: "carReluctance" } } }, { kind: "Argument", name: { kind: "Name", value: "walkReluctance" }, value: { kind: "Variable", name: { kind: "Name", value: "walkReluctance" } } }, { kind: "Argument", name: { kind: "Name", value: "arriveBy" }, value: { kind: "Variable", name: { kind: "Name", value: "arriveBy" } } }, { kind: "Argument", name: { kind: "Name", value: "intermediatePlaces" }, value: { kind: "Variable", name: { kind: "Name", value: "intermediatePlaces" } } }, { kind: "Argument", name: { kind: "Name", value: "preferred" }, value: { kind: "Variable", name: { kind: "Name", value: "preferred" } } }, { kind: "Argument", name: { kind: "Name", value: "unpreferred" }, value: { kind: "Variable", name: { kind: "Name", value: "unpreferred" } } }, { kind: "Argument", name: { kind: "Name", value: "banned" }, value: { kind: "Variable", name: { kind: "Name", value: "banned" } } }, { kind: "Argument", name: { kind: "Name", value: "numItineraries" }, value: { kind: "Variable", name: { kind: "Name", value: "numItineraries" } } }], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "routingErrors" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "code" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "inputField" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "description" }, arguments: [], directives: [] }] } }, { kind: "Field", name: { kind: "Name", value: "itineraries" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "duration" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "endTime" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "startTime" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "waitingTime" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "walkTime" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "legs" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "pickupType" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "dropoffType" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "pickupBookingInfo" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "earliestBookingTime" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "daysPrior" }, arguments: [], directives: [] }] } }] } }, { kind: "Field", name: { kind: "Name", value: "rentedBike" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "interlineWithPreviousLeg" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "departureDelay" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "arrivalDelay" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "distance" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "duration" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "endTime" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "mode" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "realTime" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "realtimeState" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "startTime" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "transitLeg" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "trip" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "id" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "gtfsId" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "tripHeadsign" }, arguments: [], directives: [] }] } }, { kind: "Field", name: { kind: "Name", value: "agency" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "name" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "id" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "timezone" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "url" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alerts" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "alertHeaderText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertDescriptionText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertUrl" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "effectiveStartDate" }, arguments: [], directives: [] }] } }] } }, { kind: "Field", name: { kind: "Name", value: "legGeometry" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "length" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "points" }, arguments: [], directives: [] }] } }, { kind: "Field", name: { kind: "Name", value: "intermediateStops" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "lat" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "lon" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "name" }, arguments: [], directives: [] }, { kind: "Field", alias: { kind: "Name", value: "stopCode" }, name: { kind: "Name", value: "code" }, arguments: [], directives: [] }, { kind: "Field", alias: { kind: "Name", value: "stopId" }, name: { kind: "Name", value: "id" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "locationType" }, arguments: [], directives: [] }] } }, { kind: "Field", name: { kind: "Name", value: "route" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "shortName" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "longName" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "color" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "textColor" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "id" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "type" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alerts" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "alertHeaderText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertDescriptionText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertUrl" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "effectiveStartDate" }, arguments: [], directives: [] }] } }] } }, { kind: "Field", name: { kind: "Name", value: "from" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "lat" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "lon" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "name" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "vertexType" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "rentalVehicle" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "network" }, arguments: [], directives: [] }] } }, { kind: "Field", name: { kind: "Name", value: "stop" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "id" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "code" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "gtfsId" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alerts" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "alertHeaderText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertDescriptionText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertUrl" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "effectiveStartDate" }, arguments: [], directives: [] }] } }] } }] } }, { kind: "Field", name: { kind: "Name", value: "to" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "lat" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "lon" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "name" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "vertexType" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "rentalVehicle" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "network" }, arguments: [], directives: [] }] } }, { kind: "Field", name: { kind: "Name", value: "stop" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "id" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "code" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "gtfsId" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alerts" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "alertHeaderText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertDescriptionText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertUrl" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "effectiveStartDate" }, arguments: [], directives: [] }] } }] } }] } }, { kind: "Field", name: { kind: "Name", value: "steps" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "distance" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "lat" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "lon" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "relativeDirection" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "absoluteDirection" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "stayOn" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "streetName" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "area" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alerts" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "alertHeaderText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertDescriptionText" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "alertUrl" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "effectiveStartDate" }, arguments: [], directives: [] }] } }, { kind: "Field", name: { kind: "Name", value: "elevationProfile" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "distance" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "elevation" }, arguments: [], directives: [] }] } }] } }] } }] } }] } }] } }], loc: { start: 0, end: 3460, source: { body: "query PlanQuery(\n $fromPlace: String!\n $toPlace: String!\n $modes: [TransportMode]\n $time: String\n $date: String\n $wheelchair: Boolean\n $bikeReluctance: Float\n $carReluctance: Float\n $walkReluctance: Float\n $arriveBy: Boolean\n $intermediatePlaces: [InputCoordinates]\n $preferred: InputPreferred\n $unpreferred: InputUnpreferred\n $banned: InputBanned\n $numItineraries: Int\n) {\n plan(\n fromPlace: $fromPlace\n toPlace: $toPlace\n transportModes: $modes\n # Currently only supporting EN locale, used for times and text\n locale: \"en\"\n time: $time\n date: $date\n wheelchair: $wheelchair\n bikeReluctance: $bikeReluctance\n carReluctance: $carReluctance\n walkReluctance: $walkReluctance\n arriveBy: $arriveBy\n intermediatePlaces: $intermediatePlaces\n preferred: $preferred\n unpreferred: $unpreferred\n banned: $banned\n numItineraries: $numItineraries\n ) {\n routingErrors {\n code\n inputField\n description\n }\n itineraries {\n duration\n endTime\n startTime\n waitingTime\n walkTime\n legs {\n pickupType\n dropoffType\n pickupBookingInfo {\n earliestBookingTime {\n daysPrior\n }\n }\n rentedBike\n interlineWithPreviousLeg\n departureDelay\n arrivalDelay\n distance\n duration\n endTime\n mode\n realTime\n realtimeState\n startTime\n transitLeg\n trip {\n id\n gtfsId\n tripHeadsign\n }\n agency {\n name\n id\n timezone\n url\n alerts {\n alertHeaderText\n alertDescriptionText\n alertUrl\n effectiveStartDate\n }\n }\n legGeometry {\n length\n points\n }\n intermediateStops {\n lat\n lon\n name\n stopCode: code\n stopId: id\n locationType\n }\n route {\n shortName\n longName\n color\n textColor\n id\n type\n alerts {\n alertHeaderText\n alertDescriptionText\n alertUrl\n effectiveStartDate\n }\n }\n from {\n lat\n lon\n name\n vertexType\n rentalVehicle {\n network\n }\n stop {\n id\n code\n gtfsId\n alerts {\n alertHeaderText\n alertDescriptionText\n alertUrl\n effectiveStartDate\n }\n }\n }\n to {\n lat\n lon\n name\n vertexType\n rentalVehicle {\n network\n }\n stop {\n id\n code\n gtfsId\n alerts {\n alertHeaderText\n alertDescriptionText\n alertUrl\n effectiveStartDate\n }\n }\n }\n steps {\n distance\n lat\n lon\n relativeDirection\n absoluteDirection\n stayOn\n streetName\n area\n alerts {\n alertHeaderText\n alertDescriptionText\n alertUrl\n effectiveStartDate\n }\n elevationProfile {\n distance\n elevation\n }\n }\n }\n }\n }\n}\n", name: "GraphQL request", locationOffset: { line: 1, column: 1 } } } };
14
+
15
+ /**
16
+ * Mode Settings can contain additional modes to add to the query,
17
+ * this function extracts those additional modes from the settings
18
+ * and returns them in an array.
19
+ * @param modeSettings List of mode settings with values populated
20
+ * @returns Additional transport modes to add to query
21
+ */
22
+ function extractAdditionalModes(modeSettings, enabledModes) {
23
+ return modeSettings.reduce((prev, cur) => {
24
+ // First, ensure that the mode associated with this setting is even enabled
25
+ if (!enabledModes.map(m => m.mode).includes(cur.applicableMode)) {
26
+ return prev;
27
+ } // In checkboxes, mode must be enabled and have a transport mode in it
28
+
29
+
30
+ if (cur.type === "CHECKBOX" && cur.addTransportMode && cur.value) {
31
+ return [...prev, cur.addTransportMode];
32
+ }
33
+
34
+ if (cur.type === "DROPDOWN") {
35
+ const transportMode = cur.options.find(o => o.value === cur.value).addTransportMode;
36
+
37
+ if (transportMode) {
38
+ return [...prev, transportMode];
39
+ }
40
+ }
41
+
42
+ return prev;
43
+ }, []);
44
+ }
45
+ /**
46
+ * Generates every possible mathematical subset of the input TransportModes.
47
+ * Uses code from:
48
+ * https://stackoverflow.com/questions/5752002/find-all-possible-subset-combos-in-an-array
49
+ * @param array Array of input transport modes
50
+ * @returns 2D array representing every possible subset of transport modes from input
51
+ */
52
+
53
+
54
+ function combinations(array) {
55
+ if (!array) return [];
56
+ return (// eslint-disable-next-line no-bitwise
57
+ new Array(1 << array.length).fill(null) // eslint-disable-next-line no-bitwise
58
+ .map((e1, i) => array.filter((e2, j) => i & 1 << j))
59
+ );
60
+ }
61
+ /**
62
+ * This constant maps all the transport mode to a broader mode type,
63
+ * which is used to determine the valid combinations of modes used in query generation.
64
+ */
65
+
66
+
67
+ const SIMPLIFICATIONS = {
68
+ AIRPLANE: "TRANSIT",
69
+ BICYCLE: "PERSONAL",
70
+ BUS: "TRANSIT",
71
+ CABLE_CAR: "TRANSIT",
72
+ CAR: "CAR",
73
+ FERRY: "TRANSIT",
74
+ FLEX: "SHARED",
75
+ // TODO: this allows FLEX+WALK. Is this reasonable?
76
+ FUNICULAR: "TRANSIT",
77
+ GONDOLA: "TRANSIT",
78
+ RAIL: "TRANSIT",
79
+ SCOOTER: "PERSONAL",
80
+ SUBWAY: "TRANSIT",
81
+ TRAM: "TRANSIT",
82
+ TRANSIT: "TRANSIT",
83
+ WALK: "WALK"
84
+ }; // Inclusion of "TRANSIT" alone automatically implies "WALK" in OTP
85
+
86
+ exports.SIMPLIFICATIONS = SIMPLIFICATIONS;
87
+ const VALID_COMBOS = [["WALK"], ["PERSONAL"], ["TRANSIT", "SHARED"], ["WALK", "SHARED"], ["TRANSIT"], ["TRANSIT", "PERSONAL"], ["TRANSIT", "CAR"]];
88
+ const BANNED_TOGETHER = ["SCOOTER", "BICYCLE"];
89
+ const TRANSIT_SUBMODES = Object.keys(SIMPLIFICATIONS).filter(mode => SIMPLIFICATIONS[mode] === "TRANSIT" && mode !== "TRANSIT");
90
+ exports.TRANSIT_SUBMODES = TRANSIT_SUBMODES;
91
+ const TRANSIT_SUBMODES_AND_TRANSIT = Object.keys(SIMPLIFICATIONS).filter(mode => SIMPLIFICATIONS[mode] === "TRANSIT");
92
+ exports.TRANSIT_SUBMODES_AND_TRANSIT = TRANSIT_SUBMODES_AND_TRANSIT;
93
+
94
+ function isCombinationValid(combo, queryTransitSubmodes) {
95
+ if (combo.length === 0) return false; // All current qualifiers currently simplify to "SHARED"
96
+
97
+ const simplifiedModes = Array.from(new Set(combo.map(c => c.qualifier ? "SHARED" : SIMPLIFICATIONS[c.mode]))); // Ensure that if we have one transit mode, then we include ALL transit modes
98
+
99
+ if (simplifiedModes.includes("TRANSIT")) {
100
+ // Don't allow TRANSIT along with any other submodes
101
+ if (queryTransitSubmodes.length && combo.find(c => c.mode === "TRANSIT")) {
102
+ return false;
103
+ }
104
+
105
+ if (combo.reduce((prev, cur) => {
106
+ if (queryTransitSubmodes.includes(cur.mode)) {
107
+ return prev - 1;
108
+ }
109
+
110
+ return prev;
111
+ }, queryTransitSubmodes.length) !== 0) {
112
+ return false;
113
+ } // Continue to the other checks
114
+
115
+ } // OTP doesn't support multiple non-walk modes
116
+
117
+
118
+ if (BANNED_TOGETHER.every(m => combo.find(c => c.mode === m))) return false;
119
+ return !!VALID_COMBOS.find(vc => simplifiedModes.every(m => vc.includes(m)) && vc.every(m => simplifiedModes.includes(m)));
120
+ }
121
+ /**
122
+ * Generates a list of queries for OTP to get a comprehensive
123
+ * set of results based on the modes input.
124
+ * @param params OTP Query Params
125
+ * @returns Set of parameters to generate queries
126
+ */
127
+
128
+
129
+ function generateCombinations(params) {
130
+ const completeModeList = [...extractAdditionalModes(params.modeSettings, params.modes), ...params.modes]; // List of the transit *submodes* that are included in the input params
131
+
132
+ const queryTransitSubmodes = completeModeList.filter(mode => TRANSIT_SUBMODES.includes(mode.mode)).map(mode => mode.mode);
133
+ return combinations(completeModeList).filter(combo => isCombinationValid(combo, queryTransitSubmodes)).map(combo => ({ ...params,
134
+ modes: combo
135
+ }));
136
+ }
137
+
138
+ function generateOtp2Query({
139
+ arriveBy,
140
+ banned,
141
+ date,
142
+ from,
143
+ modes,
144
+ modeSettings,
145
+ numItineraries,
146
+ preferred,
147
+ time,
148
+ to
149
+ }) {
150
+ // This extracts the values from the mode settings to key value pairs
151
+ const modeSettingValues = modeSettings.reduce((prev, cur) => {
152
+ if (cur.type === "SLIDER" && cur.inverseKey) {
153
+ prev[cur.inverseKey] = cur.high - cur.value + cur.low;
154
+ }
155
+
156
+ prev[cur.key] = cur.value;
157
+ return prev;
158
+ }, {});
159
+ const {
160
+ bikeReluctance,
161
+ carReluctance,
162
+ walkReluctance,
163
+ wheelchair
164
+ } = modeSettingValues;
165
+ return {
166
+ query: (0, _graphql.print)(PlanQuery),
167
+ variables: {
168
+ arriveBy,
169
+ banned,
170
+ bikeReluctance,
171
+ carReluctance,
172
+ date,
173
+ fromPlace: `${from.name}::${from.lat},${from.lon}}`,
174
+ modes,
175
+ numItineraries,
176
+ preferred,
177
+ time,
178
+ toPlace: `${to.name}::${to.lat},${to.lon}}`,
179
+ walkReluctance,
180
+ wheelchair
181
+ }
182
+ };
183
+ }
184
+ //# sourceMappingURL=query-gen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/query-gen.ts"],"names":["extractAdditionalModes","modeSettings","enabledModes","reduce","prev","cur","map","m","mode","includes","applicableMode","type","addTransportMode","value","transportMode","options","find","o","combinations","array","Array","length","fill","e1","i","filter","e2","j","SIMPLIFICATIONS","AIRPLANE","BICYCLE","BUS","CABLE_CAR","CAR","FERRY","FLEX","FUNICULAR","GONDOLA","RAIL","SCOOTER","SUBWAY","TRAM","TRANSIT","WALK","VALID_COMBOS","BANNED_TOGETHER","TRANSIT_SUBMODES","Object","keys","TRANSIT_SUBMODES_AND_TRANSIT","isCombinationValid","combo","queryTransitSubmodes","simplifiedModes","from","Set","c","qualifier","every","vc","generateCombinations","params","completeModeList","modes","generateOtp2Query","arriveBy","banned","date","numItineraries","preferred","time","to","modeSettingValues","inverseKey","high","low","key","bikeReluctance","carReluctance","walkReluctance","wheelchair","query","PlanQuery","variables","fromPlace","name","lat","lon","toPlace"],"mappings":"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","sourcesContent":["import { LonLatOutput } from \"@conveyal/lonlat\";\nimport { print } from \"graphql\";\nimport {\n ModeSetting,\n ModeSettingValues,\n TransportMode\n} from \"@opentripplanner/types\";\n\nimport PlanQuery from \"./planQuery.graphql\";\n\ntype InputBanned = {\n routes?: string;\n agencies?: string;\n trips?: string;\n stops?: string;\n stopsHard?: string;\n};\n\ntype InputPreferred = {\n routes?: string;\n agencies?: string;\n unpreferredCost?: string;\n};\n\ntype OTPQueryParams = {\n arriveBy: boolean;\n date?: string;\n from: LonLatOutput & { name?: string };\n modes: TransportMode[];\n modeSettings: ModeSetting[];\n time?: string;\n numItineraries?: number;\n to: LonLatOutput & { name?: string };\n banned?: InputBanned;\n preferred?: InputPreferred;\n};\n\ntype GraphQLQuery = {\n query: string;\n variables: Record<string, unknown>;\n};\n\n/**\n * Mode Settings can contain additional modes to add to the query,\n * this function extracts those additional modes from the settings\n * and returns them in an array.\n * @param modeSettings List of mode settings with values populated\n * @returns Additional transport modes to add to query\n */\nexport function extractAdditionalModes(\n modeSettings: ModeSetting[],\n enabledModes: TransportMode[]\n): TransportMode[] {\n return modeSettings.reduce<TransportMode[]>((prev, cur) => {\n // First, ensure that the mode associated with this setting is even enabled\n if (!enabledModes.map(m => m.mode).includes(cur.applicableMode)) {\n return prev;\n }\n\n // In checkboxes, mode must be enabled and have a transport mode in it\n if (cur.type === \"CHECKBOX\" && cur.addTransportMode && cur.value) {\n return [...prev, cur.addTransportMode];\n }\n if (cur.type === \"DROPDOWN\") {\n const transportMode = cur.options.find(o => o.value === cur.value)\n .addTransportMode;\n if (transportMode) {\n return [...prev, transportMode];\n }\n }\n return prev;\n }, []);\n}\n\n/**\n * Generates every possible mathematical subset of the input TransportModes.\n * Uses code from:\n * https://stackoverflow.com/questions/5752002/find-all-possible-subset-combos-in-an-array\n * @param array Array of input transport modes\n * @returns 2D array representing every possible subset of transport modes from input\n */\nfunction combinations(array: TransportMode[]): TransportMode[][] {\n if (!array) return [];\n return (\n // eslint-disable-next-line no-bitwise\n new Array(1 << array.length)\n .fill(null)\n // eslint-disable-next-line no-bitwise\n .map((e1, i) => array.filter((e2, j) => i & (1 << j)))\n );\n}\n\n/**\n * This constant maps all the transport mode to a broader mode type,\n * which is used to determine the valid combinations of modes used in query generation.\n */\nexport const SIMPLIFICATIONS = {\n AIRPLANE: \"TRANSIT\",\n BICYCLE: \"PERSONAL\",\n BUS: \"TRANSIT\",\n CABLE_CAR: \"TRANSIT\",\n CAR: \"CAR\",\n FERRY: \"TRANSIT\",\n FLEX: \"SHARED\", // TODO: this allows FLEX+WALK. Is this reasonable?\n FUNICULAR: \"TRANSIT\",\n GONDOLA: \"TRANSIT\",\n RAIL: \"TRANSIT\",\n SCOOTER: \"PERSONAL\",\n SUBWAY: \"TRANSIT\",\n TRAM: \"TRANSIT\",\n TRANSIT: \"TRANSIT\",\n WALK: \"WALK\"\n};\n\n// Inclusion of \"TRANSIT\" alone automatically implies \"WALK\" in OTP\nconst VALID_COMBOS = [\n [\"WALK\"],\n [\"PERSONAL\"],\n [\"TRANSIT\", \"SHARED\"],\n [\"WALK\", \"SHARED\"],\n [\"TRANSIT\"],\n [\"TRANSIT\", \"PERSONAL\"],\n [\"TRANSIT\", \"CAR\"]\n];\n\nconst BANNED_TOGETHER = [\"SCOOTER\", \"BICYCLE\"];\n\nexport const TRANSIT_SUBMODES = Object.keys(SIMPLIFICATIONS).filter(\n mode => SIMPLIFICATIONS[mode] === \"TRANSIT\" && mode !== \"TRANSIT\"\n);\nexport const TRANSIT_SUBMODES_AND_TRANSIT = Object.keys(SIMPLIFICATIONS).filter(\n mode => SIMPLIFICATIONS[mode] === \"TRANSIT\"\n);\n\nfunction isCombinationValid(\n combo: TransportMode[],\n queryTransitSubmodes: string[]\n): boolean {\n if (combo.length === 0) return false;\n\n // All current qualifiers currently simplify to \"SHARED\"\n const simplifiedModes = Array.from(\n new Set(combo.map(c => (c.qualifier ? \"SHARED\" : SIMPLIFICATIONS[c.mode])))\n );\n\n // Ensure that if we have one transit mode, then we include ALL transit modes\n if (simplifiedModes.includes(\"TRANSIT\")) {\n // Don't allow TRANSIT along with any other submodes\n if (queryTransitSubmodes.length && combo.find(c => c.mode === \"TRANSIT\")) {\n return false;\n }\n\n if (\n combo.reduce((prev, cur) => {\n if (queryTransitSubmodes.includes(cur.mode)) {\n return prev - 1;\n }\n return prev;\n }, queryTransitSubmodes.length) !== 0\n ) {\n return false;\n }\n // Continue to the other checks\n }\n\n // OTP doesn't support multiple non-walk modes\n if (BANNED_TOGETHER.every(m => combo.find(c => c.mode === m))) return false;\n\n return !!VALID_COMBOS.find(\n vc =>\n simplifiedModes.every(m => vc.includes(m)) &&\n vc.every(m => simplifiedModes.includes(m))\n );\n}\n\n/**\n * Generates a list of queries for OTP to get a comprehensive\n * set of results based on the modes input.\n * @param params OTP Query Params\n * @returns Set of parameters to generate queries\n */\nexport function generateCombinations(params: OTPQueryParams): OTPQueryParams[] {\n const completeModeList = [\n ...extractAdditionalModes(params.modeSettings, params.modes),\n ...params.modes\n ];\n\n // List of the transit *submodes* that are included in the input params\n const queryTransitSubmodes = completeModeList\n .filter(mode => TRANSIT_SUBMODES.includes(mode.mode))\n .map(mode => mode.mode);\n\n return combinations(completeModeList)\n .filter(combo => isCombinationValid(combo, queryTransitSubmodes))\n .map(combo => ({ ...params, modes: combo }));\n}\n\nexport function generateOtp2Query({\n arriveBy,\n banned,\n date,\n from,\n modes,\n modeSettings,\n numItineraries,\n preferred,\n time,\n to\n}: OTPQueryParams): GraphQLQuery {\n // This extracts the values from the mode settings to key value pairs\n const modeSettingValues = modeSettings.reduce((prev, cur) => {\n if (cur.type === \"SLIDER\" && cur.inverseKey) {\n prev[cur.inverseKey] = cur.high - cur.value + cur.low;\n }\n prev[cur.key] = cur.value;\n return prev;\n }, {}) as ModeSettingValues;\n\n const {\n bikeReluctance,\n carReluctance,\n walkReluctance,\n wheelchair\n } = modeSettingValues;\n\n return {\n query: print(PlanQuery),\n variables: {\n arriveBy,\n banned,\n bikeReluctance,\n carReluctance,\n date,\n fromPlace: `${from.name}::${from.lat},${from.lon}}`,\n modes,\n numItineraries,\n preferred,\n time,\n toPlace: `${to.name}::${to.lat},${to.lon}}`,\n walkReluctance,\n wheelchair\n }\n };\n}\n"],"file":"query-gen.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentripplanner/core-utils",
3
- "version": "9.0.0-alpha.2",
3
+ "version": "9.0.0-alpha.20",
4
4
  "description": "Core functionality that is shared among numerous UI components",
5
5
  "engines": {
6
6
  "node": ">=13"
@@ -12,14 +12,16 @@
12
12
  "license": "MIT",
13
13
  "private": false,
14
14
  "dependencies": {
15
+ "@conveyal/lonlat": "^1.4.1",
15
16
  "@mapbox/polyline": "^1.1.0",
16
- "@opentripplanner/geocoder": "^1.3.2",
17
+ "@opentripplanner/geocoder": "^1.4.0",
17
18
  "@styled-icons/foundation": "^10.34.0",
18
19
  "@turf/along": "^6.0.1",
19
20
  "bowser": "^2.7.0",
20
21
  "chroma-js": "^2.4.2",
21
22
  "date-fns": "^2.28.0",
22
23
  "date-fns-tz": "^1.2.2",
24
+ "graphql": "^16.6.0",
23
25
  "lodash.clonedeep": "^4.5.0",
24
26
  "lodash.isequal": "^4.5.0",
25
27
  "qs": "^6.9.1"
@@ -29,7 +31,7 @@
29
31
  "tsc": "tsc"
30
32
  },
31
33
  "devDependencies": {
32
- "@types/chroma-js": "^2.1.4",
33
- "@opentripplanner/types": "^4.0.2"
34
+ "@opentripplanner/types": "^5.0.0",
35
+ "@types/chroma-js": "^2.1.4"
34
36
  }
35
37
  }
@@ -0,0 +1,283 @@
1
+ import { ModeSetting, TransportMode } from "@opentripplanner/types";
2
+
3
+ import { reduceOtpFlexModes } from "../query";
4
+ import queryParams, { getCustomQueryParams } from "../query-params";
5
+ import { extractAdditionalModes, generateCombinations } from "../query-gen";
6
+
7
+ const customWalkDistanceOptions = [
8
+ {
9
+ text: "200 m",
10
+ value: 200
11
+ },
12
+ {
13
+ text: "500 m",
14
+ value: 500
15
+ }
16
+ ];
17
+
18
+ function modeStrToTransportMode(m): TransportMode {
19
+ const splitVals = m.split("_");
20
+ return {
21
+ mode: splitVals[0],
22
+ qualifier: splitVals?.[1] || null
23
+ };
24
+ }
25
+
26
+ const mockLatLon = {
27
+ lat: 1,
28
+ lon: 2
29
+ };
30
+
31
+ function expectModes(modes: string[], expectedModes: string[][]) {
32
+ const generatedModesList = generateCombinations({
33
+ from: mockLatLon,
34
+ modes: modes.map(modeStrToTransportMode),
35
+ modeSettings: [],
36
+ to: mockLatLon
37
+ });
38
+ const expandedExpectedModesList = expectedModes.map(em => ({
39
+ from: mockLatLon,
40
+ modes: em.map(modeStrToTransportMode),
41
+ modeSettings: [],
42
+ to: mockLatLon
43
+ }));
44
+ return it(
45
+ modes.join(" "),
46
+ () =>
47
+ expect(generatedModesList.length === expandedExpectedModesList.length) &&
48
+ expect(new Set(generatedModesList)).toEqual(
49
+ new Set(expandedExpectedModesList)
50
+ )
51
+ );
52
+ }
53
+
54
+ describe("extract-modes", () => {
55
+ const mode = {
56
+ mode: "UNICYCLE"
57
+ };
58
+
59
+ const testTransportMode: TransportMode = {
60
+ mode: "testMode"
61
+ };
62
+
63
+ const checkboxModeSetting: ModeSetting = {
64
+ addTransportMode: mode,
65
+ applicableMode: testTransportMode.mode,
66
+ icon: null,
67
+ key: "test",
68
+ label: "test",
69
+ type: "CHECKBOX",
70
+ value: true
71
+ };
72
+
73
+ const dropdownModeSetting: ModeSetting = {
74
+ applicableMode: testTransportMode.mode,
75
+ key: "test",
76
+ label: "test",
77
+ options: [{ text: "testOption", value: "1", addTransportMode: mode }],
78
+ type: "DROPDOWN",
79
+ value: "1"
80
+ };
81
+
82
+ it("determines whether a checkbox setting is extracted correctly", () => {
83
+ expect(
84
+ extractAdditionalModes([checkboxModeSetting], [testTransportMode])
85
+ ).toEqual([mode]);
86
+ });
87
+ it("determines whether a dropdown setting is extracted correctly", () => {
88
+ expect(
89
+ extractAdditionalModes([dropdownModeSetting], [testTransportMode])
90
+ ).toEqual([mode]);
91
+ });
92
+ it("determines whether a checkbox setting set to false is ignored", () => {
93
+ expect(
94
+ extractAdditionalModes(
95
+ [{ ...checkboxModeSetting, value: false }],
96
+ [testTransportMode]
97
+ )
98
+ ).toEqual([]);
99
+ });
100
+ it("determines whether a checkbox setting with no modes is ignored", () => {
101
+ expect(extractAdditionalModes([{ ...checkboxModeSetting }], [])).toEqual(
102
+ []
103
+ );
104
+ });
105
+ });
106
+
107
+ describe("query-gen", () => {
108
+ describe("generateCombinations", () => {
109
+ expectModes(["WALK"], [["WALK"]]);
110
+ expectModes(["WALK", "TRANSIT"], [["WALK"], ["TRANSIT"]]);
111
+ expectModes(
112
+ ["WALK", "TRANSIT", "BICYCLE"],
113
+ [["WALK"], ["TRANSIT"], ["BICYCLE"], ["TRANSIT", "BICYCLE"]]
114
+ );
115
+ expectModes(
116
+ ["WALK", "TRANSIT", "CAR"],
117
+ [["WALK"], ["TRANSIT"], ["TRANSIT", "CAR"]]
118
+ );
119
+ expectModes(["TRANSIT", "CAR"], [["TRANSIT"], ["TRANSIT", "CAR"]]);
120
+ expectModes(["CAR"], []);
121
+ expectModes(
122
+ ["WALK", "TRANSIT", "BICYCLE", "CAR"],
123
+ [
124
+ ["WALK"],
125
+ ["TRANSIT"],
126
+ ["TRANSIT", "BICYCLE"],
127
+ ["BICYCLE"],
128
+ ["TRANSIT", "CAR"]
129
+ ]
130
+ );
131
+ expectModes(
132
+ ["BICYCLE_RENT", "TRANSIT", "WALK"],
133
+ [
134
+ ["TRANSIT"],
135
+ ["BICYCLE_RENT", "TRANSIT"],
136
+ ["BICYCLE_RENT", "WALK"],
137
+ ["WALK"]
138
+ ]
139
+ );
140
+ expectModes(
141
+ ["BICYCLE_RENT", "BICYCLE", "TRANSIT", "WALK"],
142
+ [
143
+ ["TRANSIT"],
144
+ ["BICYCLE_RENT", "TRANSIT"],
145
+ ["BICYCLE", "TRANSIT"],
146
+ ["BICYCLE_RENT", "WALK"],
147
+ ["BICYCLE"],
148
+ ["WALK"]
149
+ ]
150
+ );
151
+ expectModes(
152
+ ["BICYCLE_RENT", "BICYCLE", "WALK"],
153
+ [["BICYCLE_RENT", "WALK"], ["BICYCLE"], ["WALK"]]
154
+ );
155
+ expectModes(
156
+ ["SCOOTER_RENT", "BICYCLE_RENT", "TRANSIT", "WALK"],
157
+ [
158
+ ["TRANSIT"],
159
+ ["BICYCLE_RENT", "TRANSIT"],
160
+ ["BICYCLE_RENT", "WALK"],
161
+ ["SCOOTER_RENT", "TRANSIT"],
162
+ ["SCOOTER_RENT", "WALK"],
163
+ ["WALK"]
164
+ ]
165
+ );
166
+ expectModes(
167
+ ["FLEX", "TRANSIT", "WALK"],
168
+ [["TRANSIT"], ["FLEX", "TRANSIT"], ["FLEX", "WALK"], ["WALK"]]
169
+ );
170
+ expectModes(
171
+ ["FLEX", "SCOOTER_RENT", "TRANSIT", "WALK"],
172
+ [
173
+ ["TRANSIT"],
174
+ ["FLEX", "TRANSIT"],
175
+ ["WALK"],
176
+ ["FLEX", "WALK"],
177
+ ["FLEX", "SCOOTER_RENT", "WALK"], // Is this sensible?
178
+ ["FLEX", "SCOOTER_RENT", "TRANSIT"],
179
+ ["SCOOTER_RENT", "WALK"],
180
+ ["SCOOTER_RENT", "TRANSIT"]
181
+ ]
182
+ );
183
+ expectModes(
184
+ ["FLEX", "SCOOTER_RENT", "TRANSIT"],
185
+ [
186
+ ["TRANSIT"],
187
+ ["FLEX", "TRANSIT"],
188
+ ["FLEX", "SCOOTER_RENT", "TRANSIT"],
189
+ ["SCOOTER_RENT", "TRANSIT"]
190
+ ]
191
+ );
192
+ expectModes(
193
+ // Transit is required to enable other transit submodes
194
+ ["BUS", "RAIL", "GONDOLA", "TRAM", "TRANSIT"],
195
+ [["BUS", "RAIL", "GONDOLA", "TRAM"]]
196
+ );
197
+ expectModes(
198
+ // Transit is required to enable other transit submodes
199
+ ["TRANSIT"],
200
+ [["TRANSIT"]]
201
+ );
202
+ });
203
+ });
204
+
205
+ describe("query-params", () => {
206
+ describe("getCustomQueryParams", () => {
207
+ it("should return the original unmodified queryParams if no customizations", () => {
208
+ expect(getCustomQueryParams()).toEqual(queryParams);
209
+ });
210
+
211
+ it("should return queryParams with customizations", () => {
212
+ const customizations = {
213
+ maxWalkDistance: {
214
+ label: "Max Walk Distance In Meters",
215
+ options: customWalkDistanceOptions
216
+ }
217
+ };
218
+ expect(getCustomQueryParams(customizations)).toMatchSnapshot();
219
+ });
220
+
221
+ it("should ignore unknown query params", () => {
222
+ const customizations = {
223
+ unknownQueryParameter: {
224
+ label: "Unknown query parameter",
225
+ options: customWalkDistanceOptions
226
+ }
227
+ };
228
+ expect(getCustomQueryParams(customizations)).toEqual(queryParams);
229
+ });
230
+ });
231
+ });
232
+
233
+ describe("flex-reducer", () => {
234
+ it("should not touch a query that doesn't include flex modes", () => {
235
+ expect(reduceOtpFlexModes(["WALK", "TRANSIT", "BIKE"])).toStrictEqual([
236
+ "WALK",
237
+ "TRANSIT",
238
+ "BIKE"
239
+ ]);
240
+ });
241
+ it("should modify a query that includes some flex modes", () => {
242
+ expect(
243
+ reduceOtpFlexModes(["WALK", "TRANSIT", "BIKE", "FLEX_DIRECT"])
244
+ ).toStrictEqual(["WALK", "TRANSIT", "BIKE", "FLEX"]);
245
+ });
246
+ it("should modify a query that includes all flex modes", () => {
247
+ expect(
248
+ reduceOtpFlexModes([
249
+ "WALK",
250
+ "TRANSIT",
251
+ "BIKE",
252
+ "FLEX_DIRECT",
253
+ "FLEX_ACCESS",
254
+ "FLEX_EGRESS"
255
+ ])
256
+ ).toStrictEqual(["WALK", "TRANSIT", "BIKE", "FLEX"]);
257
+ expect(
258
+ reduceOtpFlexModes([
259
+ "FLEX_DIRECT",
260
+ "BIKE",
261
+ "FLEX_ACCESS",
262
+ "WALK",
263
+ "FLEX_EGRESS",
264
+ "TRANSIT"
265
+ ])
266
+ ).toStrictEqual(["FLEX", "BIKE", "WALK", "TRANSIT"]);
267
+ });
268
+ it("should modify a query that includes only flex modes", () => {
269
+ expect(
270
+ reduceOtpFlexModes(["FLEX_DIRECT", "FLEX_ACCESS", "FLEX_EGRESS"])
271
+ ).toStrictEqual(["FLEX"]);
272
+ });
273
+ it("should modify a query that includes duplicate flex modes", () => {
274
+ expect(
275
+ reduceOtpFlexModes([
276
+ "FLEX_DIRECT",
277
+ "FLEX_DIRECT",
278
+ "FLEX_ACCESS",
279
+ "FLEX_EGRESS"
280
+ ])
281
+ ).toStrictEqual(["FLEX"]);
282
+ });
283
+ });
@@ -50,7 +50,7 @@ export const RouteColorTester = (): JSX.Element => {
50
50
  </>
51
51
  );
52
52
  };
53
- // Disable color contrast checking for the uncorrected color pairs
53
+ // Disable color contrast checking for the uncorrected color pairs.
54
54
  RouteColorTester.parameters = {
55
55
  a11y: { config: { rules: [{ id: "color-contrast", reviewOnFail: true }] } },
56
56
  storyshots: { disable: true }
@@ -0,0 +1,7 @@
1
+ declare module "*.graphql" {
2
+ import { DocumentNode } from "graphql";
3
+
4
+ const Schema: DocumentNode;
5
+
6
+ export = Schema;
7
+ }
package/src/index.ts CHANGED
@@ -7,12 +7,14 @@ import * as route from "./route";
7
7
  import * as storage from "./storage";
8
8
  import * as time from "./time";
9
9
  import * as ui from "./ui";
10
+ import * as queryGen from "./query-gen";
10
11
 
11
12
  const core = {
12
13
  itinerary,
13
14
  map,
14
15
  profile,
15
16
  query,
17
+ queryGen,
16
18
  queryParams,
17
19
  route,
18
20
  storage,