@opentripplanner/core-utils 9.0.0-alpha.1 → 9.0.0-alpha.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/esm/graphql.d.js +2 -0
- package/esm/graphql.d.js.map +1 -0
- package/esm/index.js +2 -0
- package/esm/index.js.map +1 -1
- package/esm/query-gen.js +136 -0
- package/esm/query-gen.js.map +1 -0
- package/esm/state.js +2 -0
- package/esm/state.js.map +1 -0
- package/lib/graphql.d.js +2 -0
- package/lib/graphql.d.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/query-gen.d.ts +31 -0
- package/lib/query-gen.d.ts.map +1 -0
- package/lib/query-gen.js +121 -0
- package/lib/query-gen.js.map +1 -0
- package/lib/state.d.ts +1 -0
- package/lib/state.d.ts.map +1 -0
- package/lib/state.js +2 -0
- package/lib/state.js.map +1 -0
- package/package.json +5 -2
- package/src/__tests__/query-params.js +125 -0
- package/src/graphql.d.ts +7 -0
- package/src/index.ts +2 -0
- package/src/planQuery.graphql +107 -0
- package/src/query-gen.ts +152 -0
- package/src/state.ts +0 -0
- package/tsconfig.json +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { reduceOtpFlexModes } from "../query";
|
|
2
2
|
import queryParams, { getCustomQueryParams } from "../query-params";
|
|
3
|
+
import { generateCombinations } from "../query-gen";
|
|
3
4
|
|
|
4
5
|
const customWalkDistanceOptions = [
|
|
5
6
|
{
|
|
@@ -12,6 +13,130 @@ const customWalkDistanceOptions = [
|
|
|
12
13
|
}
|
|
13
14
|
];
|
|
14
15
|
|
|
16
|
+
function modeStrToTransportMode(m) {
|
|
17
|
+
const splitVals = m.split("_");
|
|
18
|
+
return {
|
|
19
|
+
mode: splitVals[0],
|
|
20
|
+
qualifier: splitVals?.[1] || null
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const mockLatLon = {
|
|
25
|
+
lat: 1,
|
|
26
|
+
lon: 2
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function expectModes(modes, expectedModes) {
|
|
30
|
+
const generatedModesList = generateCombinations({
|
|
31
|
+
modes: modes.map(modeStrToTransportMode),
|
|
32
|
+
to: mockLatLon,
|
|
33
|
+
from: mockLatLon,
|
|
34
|
+
modeSettings: []
|
|
35
|
+
});
|
|
36
|
+
const expandedExpectedModesList = expectedModes.map(em => ({
|
|
37
|
+
modes: em.map(modeStrToTransportMode),
|
|
38
|
+
to: mockLatLon,
|
|
39
|
+
from: mockLatLon,
|
|
40
|
+
modeSettings: []
|
|
41
|
+
}));
|
|
42
|
+
return it(
|
|
43
|
+
modes.join(" "),
|
|
44
|
+
() =>
|
|
45
|
+
expect(generatedModesList.length === expandedExpectedModesList.length) &&
|
|
46
|
+
expect(new Set(generatedModesList)).toEqual(
|
|
47
|
+
new Set(expandedExpectedModesList)
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe("query-gen", () => {
|
|
53
|
+
describe("generateCombinations", () => {
|
|
54
|
+
expectModes(["WALK"], [["WALK"]]);
|
|
55
|
+
expectModes(["WALK", "TRANSIT"], [["WALK"], ["TRANSIT"]]);
|
|
56
|
+
expectModes(
|
|
57
|
+
["WALK", "TRANSIT", "BICYCLE"],
|
|
58
|
+
[["WALK"], ["TRANSIT"], ["BICYCLE"], ["TRANSIT", "BICYCLE"]]
|
|
59
|
+
);
|
|
60
|
+
expectModes(
|
|
61
|
+
["WALK", "TRANSIT", "CAR"],
|
|
62
|
+
[["WALK"], ["TRANSIT"], ["TRANSIT", "CAR"]]
|
|
63
|
+
);
|
|
64
|
+
expectModes(["TRANSIT", "CAR"], [["TRANSIT"], ["TRANSIT", "CAR"]]);
|
|
65
|
+
expectModes(["CAR"], []);
|
|
66
|
+
expectModes(
|
|
67
|
+
["WALK", "TRANSIT", "BICYCLE", "CAR"],
|
|
68
|
+
[
|
|
69
|
+
["WALK"],
|
|
70
|
+
["TRANSIT"],
|
|
71
|
+
["TRANSIT", "BICYCLE"],
|
|
72
|
+
["BICYCLE"],
|
|
73
|
+
["TRANSIT", "CAR"]
|
|
74
|
+
]
|
|
75
|
+
);
|
|
76
|
+
expectModes(
|
|
77
|
+
["BICYCLE_RENT", "TRANSIT", "WALK"],
|
|
78
|
+
[
|
|
79
|
+
["TRANSIT"],
|
|
80
|
+
["BICYCLE_RENT", "TRANSIT"],
|
|
81
|
+
["BICYCLE_RENT", "WALK"],
|
|
82
|
+
["WALK"]
|
|
83
|
+
]
|
|
84
|
+
);
|
|
85
|
+
expectModes(
|
|
86
|
+
["BICYCLE_RENT", "BICYCLE", "TRANSIT", "WALK"],
|
|
87
|
+
[
|
|
88
|
+
["TRANSIT"],
|
|
89
|
+
["BICYCLE_RENT", "TRANSIT"],
|
|
90
|
+
["BICYCLE", "TRANSIT"],
|
|
91
|
+
["BICYCLE_RENT", "WALK"],
|
|
92
|
+
["BICYCLE"],
|
|
93
|
+
["WALK"]
|
|
94
|
+
]
|
|
95
|
+
);
|
|
96
|
+
expectModes(
|
|
97
|
+
["SCOOTER_RENT", "BICYCLE_RENT", "TRANSIT", "WALK"],
|
|
98
|
+
[
|
|
99
|
+
["TRANSIT"],
|
|
100
|
+
["BICYCLE_RENT", "TRANSIT"],
|
|
101
|
+
["BICYCLE_RENT", "WALK"],
|
|
102
|
+
["SCOOTER_RENT", "TRANSIT"],
|
|
103
|
+
["SCOOTER_RENT", "WALK"],
|
|
104
|
+
["WALK"]
|
|
105
|
+
]
|
|
106
|
+
);
|
|
107
|
+
expectModes(
|
|
108
|
+
["FLEX", "TRANSIT", "WALK"],
|
|
109
|
+
[["TRANSIT"], ["FLEX", "TRANSIT"], ["FLEX", "WALK"], ["WALK"]]
|
|
110
|
+
);
|
|
111
|
+
expectModes(
|
|
112
|
+
["FLEX", "SCOOTER_RENT", "TRANSIT", "WALK"],
|
|
113
|
+
[
|
|
114
|
+
["TRANSIT"],
|
|
115
|
+
["FLEX", "TRANSIT"],
|
|
116
|
+
["WALK"],
|
|
117
|
+
["FLEX", "WALK"],
|
|
118
|
+
["FLEX", "SCOOTER_RENT", "WALK"], // Is this sensible?
|
|
119
|
+
["FLEX", "SCOOTER_RENT", "TRANSIT"],
|
|
120
|
+
["SCOOTER_RENT", "WALK"],
|
|
121
|
+
["SCOOTER_RENT", "TRANSIT"]
|
|
122
|
+
]
|
|
123
|
+
);
|
|
124
|
+
expectModes(
|
|
125
|
+
["FLEX", "SCOOTER_RENT", "TRANSIT"],
|
|
126
|
+
[
|
|
127
|
+
["TRANSIT"],
|
|
128
|
+
["FLEX", "TRANSIT"],
|
|
129
|
+
["FLEX", "SCOOTER_RENT", "TRANSIT"],
|
|
130
|
+
["SCOOTER_RENT", "TRANSIT"]
|
|
131
|
+
]
|
|
132
|
+
);
|
|
133
|
+
expectModes(
|
|
134
|
+
["BUS", "RAIL", "GONDOLA", "TRAM"],
|
|
135
|
+
[["BUS", "RAIL", "GONDOLA", "TRAM"]]
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
15
140
|
describe("query-params", () => {
|
|
16
141
|
describe("getCustomQueryParams", () => {
|
|
17
142
|
it("should return the original unmodified queryParams if no customizations", () => {
|
package/src/graphql.d.ts
ADDED
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,
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
query PlanQuery(
|
|
2
|
+
$fromPlace: String!,
|
|
3
|
+
$toPlace: String!,
|
|
4
|
+
$modes: [TransportMode],
|
|
5
|
+
$time: String,
|
|
6
|
+
$date: String,
|
|
7
|
+
$wheelchair: Boolean,
|
|
8
|
+
$bikeReluctance: Float,
|
|
9
|
+
$carReluctance: Float,
|
|
10
|
+
$walkReluctance: Float,
|
|
11
|
+
$arriveBy: Boolean,
|
|
12
|
+
$intermediatePlaces: [InputCoordinates],
|
|
13
|
+
$preferred: InputPreferred,
|
|
14
|
+
$unpreferred: InputUnpreferred,
|
|
15
|
+
$banned: InputBanned,
|
|
16
|
+
) {
|
|
17
|
+
plan(
|
|
18
|
+
fromPlace: $fromPlace
|
|
19
|
+
toPlace: $toPlace
|
|
20
|
+
transportModes: $modes
|
|
21
|
+
locale: "en",
|
|
22
|
+
time: $time,
|
|
23
|
+
date: $date,
|
|
24
|
+
wheelchair: $wheelchair,
|
|
25
|
+
bikeReluctance: $bikeReluctance,
|
|
26
|
+
carReluctance: $carReluctance,
|
|
27
|
+
walkReluctance: $walkReluctance,
|
|
28
|
+
arriveBy: $arriveBy,
|
|
29
|
+
intermediatePlaces: $intermediatePlaces,
|
|
30
|
+
preferred: $preferred,
|
|
31
|
+
unpreferred: $unpreferred,
|
|
32
|
+
banned: $banned,
|
|
33
|
+
) {
|
|
34
|
+
itineraries {
|
|
35
|
+
duration
|
|
36
|
+
endTime
|
|
37
|
+
startTime
|
|
38
|
+
waitingTime
|
|
39
|
+
walkTime
|
|
40
|
+
legs {
|
|
41
|
+
distance
|
|
42
|
+
duration
|
|
43
|
+
endTime
|
|
44
|
+
mode
|
|
45
|
+
realTime
|
|
46
|
+
realtimeState
|
|
47
|
+
startTime
|
|
48
|
+
transitLeg
|
|
49
|
+
agency {
|
|
50
|
+
name
|
|
51
|
+
id
|
|
52
|
+
timezone
|
|
53
|
+
url
|
|
54
|
+
}
|
|
55
|
+
legGeometry {
|
|
56
|
+
length
|
|
57
|
+
points
|
|
58
|
+
}
|
|
59
|
+
intermediateStops {
|
|
60
|
+
lat
|
|
61
|
+
lon
|
|
62
|
+
name
|
|
63
|
+
stopCode: code
|
|
64
|
+
stopId: id
|
|
65
|
+
locationType
|
|
66
|
+
}
|
|
67
|
+
route {
|
|
68
|
+
shortName
|
|
69
|
+
color
|
|
70
|
+
textColor
|
|
71
|
+
id
|
|
72
|
+
type
|
|
73
|
+
}
|
|
74
|
+
from {
|
|
75
|
+
lat
|
|
76
|
+
lon
|
|
77
|
+
name
|
|
78
|
+
vertexType
|
|
79
|
+
stop {
|
|
80
|
+
id
|
|
81
|
+
code
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
to {
|
|
86
|
+
lat
|
|
87
|
+
lon
|
|
88
|
+
name
|
|
89
|
+
vertexType
|
|
90
|
+
stop {
|
|
91
|
+
id
|
|
92
|
+
code
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
steps {
|
|
96
|
+
distance
|
|
97
|
+
lat
|
|
98
|
+
lon
|
|
99
|
+
elevationProfile {
|
|
100
|
+
distance
|
|
101
|
+
elevation
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
package/src/query-gen.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
import { print } from "graphql";
|
|
3
|
+
import {
|
|
4
|
+
ModeSetting,
|
|
5
|
+
ModeSettingValues,
|
|
6
|
+
TransportMode
|
|
7
|
+
} from "@opentripplanner/types";
|
|
8
|
+
import { LonLatOutput } from "@conveyal/lonlat";
|
|
9
|
+
import PlanQuery from "./planQuery.graphql";
|
|
10
|
+
|
|
11
|
+
type OTPQueryParams = {
|
|
12
|
+
to: LonLatOutput;
|
|
13
|
+
from: LonLatOutput;
|
|
14
|
+
modes: Array<TransportMode>;
|
|
15
|
+
modeSettings: ModeSetting[];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generates every possible mathematical subset of the input TransportModes.
|
|
20
|
+
* Uses code from:
|
|
21
|
+
* https://stackoverflow.com/questions/5752002/find-all-possible-subset-combos-in-an-array
|
|
22
|
+
* @param array Array of input transport modes
|
|
23
|
+
* @returns 2D array representing every possible subset of transport modes from input
|
|
24
|
+
*/
|
|
25
|
+
function combinations(array: TransportMode[]): TransportMode[][] {
|
|
26
|
+
if (!array) return [];
|
|
27
|
+
return (
|
|
28
|
+
// eslint-disable-next-line no-bitwise
|
|
29
|
+
new Array(1 << array.length)
|
|
30
|
+
.fill(null)
|
|
31
|
+
// eslint-disable-next-line no-bitwise
|
|
32
|
+
.map((e1, i) => array.filter((e2, j) => i & (1 << j)))
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
export const SIMPLIFICATIONS = {
|
|
36
|
+
AIRPLANE: "TRANSIT",
|
|
37
|
+
BICYCLE: "PERSONAL",
|
|
38
|
+
BUS: "TRANSIT",
|
|
39
|
+
CABLE_CAR: "TRANSIT",
|
|
40
|
+
CAR: "CAR",
|
|
41
|
+
FERRY: "TRANSIT",
|
|
42
|
+
FLEX: "SHARED", // TODO: this allows FLEX+WALK. Is this reasonable?
|
|
43
|
+
FUNICULAR: "TRANSIT",
|
|
44
|
+
GONDOLA: "TRANSIT",
|
|
45
|
+
RAIL: "TRANSIT",
|
|
46
|
+
SCOOTER: "PERSONAL",
|
|
47
|
+
SUBWAY: "TRANSIT",
|
|
48
|
+
TRAM: "TRANSIT",
|
|
49
|
+
TRANSIT: "TRANSIT",
|
|
50
|
+
WALK: "WALK"
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const TRANSIT_SUBMODES = Object.keys(SIMPLIFICATIONS).filter(
|
|
54
|
+
mode => SIMPLIFICATIONS[mode] === "TRANSIT" && mode !== "TRANSIT"
|
|
55
|
+
);
|
|
56
|
+
export const TRANSIT_SUBMODES_AND_TRANSIT = Object.keys(SIMPLIFICATIONS).filter(
|
|
57
|
+
mode => SIMPLIFICATIONS[mode] === "TRANSIT"
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
export function generateCombinations(params: OTPQueryParams): OTPQueryParams[] {
|
|
61
|
+
const VALID_COMBOS = [
|
|
62
|
+
["WALK"],
|
|
63
|
+
["PERSONAL"],
|
|
64
|
+
["TRANSIT", "SHARED"],
|
|
65
|
+
["WALK", "SHARED"],
|
|
66
|
+
["TRANSIT"],
|
|
67
|
+
["TRANSIT", "PERSONAL"],
|
|
68
|
+
["TRANSIT", "CAR"]
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
const BANNED_TOGETHER = ["SCOOTER", "BICYCLE"];
|
|
72
|
+
|
|
73
|
+
// List of the transit submodes that are included in the input params
|
|
74
|
+
const queryTransitSubmodes = params.modes
|
|
75
|
+
.filter(mode => TRANSIT_SUBMODES.includes(mode.mode))
|
|
76
|
+
.map(mode => mode.mode);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
combinations(params.modes)
|
|
80
|
+
.filter(combo => {
|
|
81
|
+
if (combo.length === 0) return false;
|
|
82
|
+
|
|
83
|
+
// All current qualifiers currently simplify to "SHARED"
|
|
84
|
+
const simplifiedModes = Array.from(
|
|
85
|
+
new Set(
|
|
86
|
+
combo.map(c => (c.qualifier ? "SHARED" : SIMPLIFICATIONS[c.mode]))
|
|
87
|
+
)
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Ensure that if we have one transit mode, then we include ALL transit modes
|
|
91
|
+
if (simplifiedModes.includes("TRANSIT")) {
|
|
92
|
+
const flatModes = combo.map(m => m.mode);
|
|
93
|
+
if (
|
|
94
|
+
combo.reduce((prev, cur) => {
|
|
95
|
+
if (queryTransitSubmodes.includes(cur.mode)) {
|
|
96
|
+
return prev - 1;
|
|
97
|
+
}
|
|
98
|
+
return prev;
|
|
99
|
+
}, queryTransitSubmodes.length) !== 0
|
|
100
|
+
) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// OTP doesn't support multiple non-walk modes
|
|
106
|
+
if (BANNED_TOGETHER.every(m => combo.find(c => c.mode === m)))
|
|
107
|
+
return false;
|
|
108
|
+
|
|
109
|
+
return !!VALID_COMBOS.find(
|
|
110
|
+
vc =>
|
|
111
|
+
simplifiedModes.every(m => vc.includes(m)) &&
|
|
112
|
+
vc.every(m => simplifiedModes.includes(m))
|
|
113
|
+
);
|
|
114
|
+
})
|
|
115
|
+
// create new filter that removes subTransit modes from appearing on their own
|
|
116
|
+
// ONLY IF there's multiple of them!
|
|
117
|
+
.map(combo => ({ ...params, modes: combo }))
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// eslint-disable-next-line import/prefer-default-export
|
|
122
|
+
export function generateOtp2Query(params: OTPQueryParams): any {
|
|
123
|
+
const { to, from, modeSettings } = params;
|
|
124
|
+
|
|
125
|
+
// This extracts the values from the mode settings to key value pairs
|
|
126
|
+
const modeSettingValues = modeSettings.reduce((prev, cur) => {
|
|
127
|
+
prev[cur.key] = cur.value;
|
|
128
|
+
return prev;
|
|
129
|
+
}, {}) as ModeSettingValues;
|
|
130
|
+
|
|
131
|
+
const {
|
|
132
|
+
walkReluctance,
|
|
133
|
+
wheelchair,
|
|
134
|
+
bikeReluctance,
|
|
135
|
+
carReluctance,
|
|
136
|
+
allowBikeRental
|
|
137
|
+
} = modeSettingValues;
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
query: print(PlanQuery),
|
|
141
|
+
variables: {
|
|
142
|
+
fromPlace: [from.lat, from.lon].join(","),
|
|
143
|
+
toPlace: [to.lat, to.lon].join(","),
|
|
144
|
+
modes: params.modes,
|
|
145
|
+
allowBikeRental,
|
|
146
|
+
walkReluctance,
|
|
147
|
+
wheelchair,
|
|
148
|
+
bikeReluctance,
|
|
149
|
+
carReluctance
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
package/src/state.ts
ADDED
|
File without changes
|