@wemap/routers 6.2.2 → 7.0.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/assets/biocbon-bergere-rdc-network.osm +163 -0
- package/assets/gare-de-lest-network-pp-bounds.osm +1615 -0
- package/dist/wemap-routers.es.js +1811 -695
- package/dist/wemap-routers.es.js.map +1 -1
- package/index.js +13 -5
- package/package.json +9 -6
- package/src/Constants.js +4 -2
- package/src/ItineraryInfoManager.spec.js +2 -2
- package/src/Utils.js +0 -77
- package/src/model/Itinerary.js +41 -5
- package/src/model/Itinerary.spec.js +91 -0
- package/src/model/Itinerary.type.spec.js +3 -78
- package/src/model/Leg.js +89 -19
- package/src/model/Leg.spec.js +110 -0
- package/src/model/Leg.type.spec.js +48 -0
- package/src/model/LevelChange.js +14 -24
- package/src/model/LevelChange.spec.js +78 -0
- package/src/model/LevelChange.type.spec.js +26 -0
- package/src/model/RouterResponse.js +70 -1
- package/src/model/RouterResponse.spec.js +85 -0
- package/src/model/RouterResponse.type.spec.js +7 -4
- package/src/model/Step.js +45 -6
- package/src/model/Step.spec.js +100 -0
- package/src/model/Step.type.spec.js +52 -0
- package/src/remote/RemoteRouter.js +31 -0
- package/src/remote/RemoteRouterManager.js +84 -0
- package/src/remote/RemoteRouterOptions.js +25 -0
- package/src/remote/RemoteRouterServerUnreachable.js +10 -0
- package/src/remote/RemoteRouterUtils.js +78 -0
- package/src/remote/RoutingModeCorrespondanceNotFound.js +18 -0
- package/src/remote/cityway/CitywayRemoteRouter.js +386 -0
- package/src/{cityway/CitywayUtils.spec.js → remote/cityway/CitywayRemoteRouter.spec.js} +19 -18
- package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.js +143 -0
- package/src/{deutsche-bahn/DeutscheBahnRouterUtils.spec.js → remote/deutsche-bahn/DeutscheBahnRemoteRouter.spec.js} +7 -6
- package/src/remote/idfm/IdfmRemoteRouter.js +432 -0
- package/src/{idfm/IdfmUtils.spec.js → remote/idfm/IdfmRemoteRouter.spec.js} +7 -6
- package/src/remote/idfm/IdfmRemoteRouterTokenError.js +6 -0
- package/src/remote/osrm/OsrmRemoteRouter.js +331 -0
- package/src/{osrm/OsrmUtils.spec.js → remote/osrm/OsrmRemoteRouter.spec.js} +9 -15
- package/src/remote/otp/OtpRemoteRouter.js +222 -0
- package/src/{otp/OtpUtils.spec.js → remote/otp/OtpRemoteRouter.spec.js} +10 -9
- package/src/remote/wemap-meta/WemapMetaRemoteRouter.js +57 -0
- package/src/remote/wemap-meta/WemapMetaRemoteRouter.spec.js +22 -0
- package/src/remote/wemap-meta/WemapMetaRemoteRouterOptions.js +36 -0
- package/src/remote/wemap-meta/WemapMetaRemoteRouterPayload.js +44 -0
- package/src/wemap/WemapRouter.js +6 -0
- package/src/wemap/WemapRouterUtils.js +10 -4
- package/src/wemap/WemapStepsGeneration.js +36 -9
- package/src/wemap-meta/IOMap.js +191 -0
- package/src/wemap-meta/WemapMetaRouter.js +314 -0
- package/src/wemap-meta/WemapMetaRouter.spec.js +119 -0
- package/src/wemap-meta/WemapMetaRouterOptions.js +20 -0
- package/src/cityway/CitywayUtils.js +0 -252
- package/src/deutsche-bahn/DeutscheBahnRouterUtils.js +0 -91
- package/src/idfm/IdfmUtils.js +0 -247
- package/src/osrm/OsrmUtils.js +0 -269
- package/src/otp/OtpUtils.js +0 -150
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-depth */
|
|
2
|
-
/* eslint-disable max-statements */
|
|
3
|
-
import { Coordinates } from '@wemap/geo';
|
|
4
|
-
import Logger from '@wemap/logger';
|
|
5
|
-
|
|
6
|
-
import Itinerary from '../model/Itinerary.js';
|
|
7
|
-
import Leg from '../model/Leg.js';
|
|
8
|
-
import RouterResponse from '../model/RouterResponse.js';
|
|
9
|
-
import Step from '../model/Step.js';
|
|
10
|
-
import { generateStepsMetadata, dateWithTimeZone } from '../Utils.js';
|
|
11
|
-
import Constants from '../Constants.js';
|
|
12
|
-
|
|
13
|
-
const routingModeCorrespondance = new Map();
|
|
14
|
-
routingModeCorrespondance.set('WALK', Constants.ROUTING_MODE.WALK);
|
|
15
|
-
routingModeCorrespondance.set('BICYCLE', Constants.ROUTING_MODE.BIKE);
|
|
16
|
-
routingModeCorrespondance.set('BUS', Constants.ROUTING_MODE.BUS);
|
|
17
|
-
routingModeCorrespondance.set('TRAMWAY', Constants.ROUTING_MODE.TRAM);
|
|
18
|
-
routingModeCorrespondance.set('FUNICULAR', Constants.ROUTING_MODE.FUNICULAR);
|
|
19
|
-
routingModeCorrespondance.set('TRAIN', Constants.ROUTING_MODE.TRAIN);
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {object} json
|
|
23
|
-
* @returns {Coordinates}
|
|
24
|
-
*/
|
|
25
|
-
export function jsonToCoordinates(json) {
|
|
26
|
-
return new Coordinates(json.Lat, json.Long);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {string} jsonDate
|
|
31
|
-
* @returns {number}
|
|
32
|
-
*/
|
|
33
|
-
function jsonDateToTimestamp(jsonDate) {
|
|
34
|
-
const [dateStr, timeStr] = jsonDate.split(' ');
|
|
35
|
-
const [dayStr, monthStr, yearStr] = dateStr.split('/');
|
|
36
|
-
const [hoursStr, minutesStr, secondsStr] = timeStr.split(':');
|
|
37
|
-
|
|
38
|
-
return dateWithTimeZone(
|
|
39
|
-
Number(yearStr),
|
|
40
|
-
Number(monthStr) - 1,
|
|
41
|
-
Number(dayStr),
|
|
42
|
-
Number(hoursStr),
|
|
43
|
-
Number(minutesStr),
|
|
44
|
-
Number(secondsStr)
|
|
45
|
-
).getTime();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @param {string} wktGeometry
|
|
50
|
-
* @returns {Coordinates[]}
|
|
51
|
-
*/
|
|
52
|
-
function parseWKTGeometry(wktGeometry) {
|
|
53
|
-
const tmpCoordsStr = wktGeometry.match(/LINESTRING \((.*)\)/i);
|
|
54
|
-
if (!tmpCoordsStr) {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
return tmpCoordsStr[1].split(',').map(str => {
|
|
58
|
-
const sp = str.trim().split(' ');
|
|
59
|
-
return new Coordinates(Number(sp[1]), Number(sp[0]));
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* @param {string} iso8601Duration
|
|
65
|
-
* @see https://stackoverflow.com/a/29153059/2239938
|
|
66
|
-
*/
|
|
67
|
-
function parseDuration(iso8601Duration) {
|
|
68
|
-
const iso8601DurationRegex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/;
|
|
69
|
-
|
|
70
|
-
var matches = iso8601Duration.match(iso8601DurationRegex);
|
|
71
|
-
|
|
72
|
-
// const sign = typeof matches[1] === 'undefined' ? '+' : '-',
|
|
73
|
-
const years = typeof matches[2] === 'undefined' ? 0 : Number(matches[2]);
|
|
74
|
-
const months = typeof matches[3] === 'undefined' ? 0 : Number(matches[3]);
|
|
75
|
-
const weeks = typeof matches[4] === 'undefined' ? 0 : Number(matches[4]);
|
|
76
|
-
const days = typeof matches[5] === 'undefined' ? 0 : Number(matches[5]);
|
|
77
|
-
const hours = typeof matches[6] === 'undefined' ? 0 : Number(matches[6]);
|
|
78
|
-
const minutes = typeof matches[7] === 'undefined' ? 0 : Number(matches[7]);
|
|
79
|
-
const seconds = typeof matches[8] === 'undefined' ? 0 : Number(matches[8]);
|
|
80
|
-
|
|
81
|
-
return seconds
|
|
82
|
-
+ minutes * 60
|
|
83
|
-
+ hours * 3600
|
|
84
|
-
+ days * 86400
|
|
85
|
-
+ weeks * (86400 * 7)
|
|
86
|
-
+ months * (86400 * 30)
|
|
87
|
-
+ years * (86400 * 365.25);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Generate multi itineraries from Cityway JSON
|
|
92
|
-
* @param {object} json JSON file provided by Cityway.
|
|
93
|
-
* @returns {?RouterResponse}
|
|
94
|
-
* @example https://preprod.api.lia2.cityway.fr/journeyplanner/api/opt/PlanTrips/json?DepartureLatitude=49.51509388236216&DepartureLongitude=0.09341749619366316&ArrivalLatitude=49.5067090188444&ArrivalLongitude=0.1694842115417831&DepartureType=COORDINATES&ArrivalType=COORDINATES
|
|
95
|
-
*/
|
|
96
|
-
export function createRouterResponseFromJson(json) {
|
|
97
|
-
|
|
98
|
-
if (json.StatusCode !== 200 || !json.Data || !json.Data.length) {
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const routerResponse = new RouterResponse();
|
|
103
|
-
routerResponse.routerName = 'cityway';
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// Do not know if it the best approach, but it works...
|
|
107
|
-
const allJsonTrips = json.Data.reduce((acc, dataObj) => {
|
|
108
|
-
acc.push(...dataObj.response.trips.Trip);
|
|
109
|
-
return acc;
|
|
110
|
-
}, []);
|
|
111
|
-
|
|
112
|
-
for (const trip of allJsonTrips) {
|
|
113
|
-
|
|
114
|
-
const itinerary = new Itinerary();
|
|
115
|
-
|
|
116
|
-
itinerary.duration = parseDuration(trip.Duration);
|
|
117
|
-
itinerary.startTime = jsonDateToTimestamp(trip.Departure.Time);
|
|
118
|
-
itinerary.from = jsonToCoordinates(trip.Departure.Site.Position);
|
|
119
|
-
itinerary.endTime = jsonDateToTimestamp(trip.Arrival.Time);
|
|
120
|
-
itinerary.to = jsonToCoordinates(trip.Arrival.Site.Position);
|
|
121
|
-
routerResponse.itineraries.push(itinerary);
|
|
122
|
-
|
|
123
|
-
for (const jsonSection of trip.sections.Section) {
|
|
124
|
-
|
|
125
|
-
const jsonLeg = jsonSection.Leg ? jsonSection.Leg : jsonSection.PTRide;
|
|
126
|
-
|
|
127
|
-
const leg = new Leg();
|
|
128
|
-
|
|
129
|
-
leg.mode = routingModeCorrespondance.get(jsonLeg.TransportMode);
|
|
130
|
-
leg.duration = parseDuration(jsonLeg.Duration);
|
|
131
|
-
leg.startTime = jsonDateToTimestamp(jsonLeg.Departure.Time);
|
|
132
|
-
leg.endTime = jsonDateToTimestamp(jsonLeg.Arrival.Time);
|
|
133
|
-
leg.coords = [];
|
|
134
|
-
|
|
135
|
-
if (leg.mode === Constants.ROUTING_MODE.WALK || leg.mode === Constants.ROUTING_MODE.BIKE) {
|
|
136
|
-
|
|
137
|
-
leg.from = {
|
|
138
|
-
name: jsonLeg.Departure.Site.Name,
|
|
139
|
-
coords: jsonToCoordinates(jsonLeg.Departure.Site.Position)
|
|
140
|
-
};
|
|
141
|
-
leg.to = {
|
|
142
|
-
name: jsonLeg.Arrival.Site.Name,
|
|
143
|
-
coords: jsonToCoordinates(jsonLeg.Arrival.Site.Position)
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
leg.steps = [];
|
|
147
|
-
for (const jsonPathLink of jsonLeg.pathLinks.PathLink) {
|
|
148
|
-
const step = new Step();
|
|
149
|
-
let stepCoords;
|
|
150
|
-
if (jsonPathLink.Geometry) {
|
|
151
|
-
stepCoords = parseWKTGeometry(jsonPathLink.Geometry);
|
|
152
|
-
} else {
|
|
153
|
-
stepCoords = [leg.from.coords, leg.to.coords];
|
|
154
|
-
}
|
|
155
|
-
step.coords = stepCoords[0];
|
|
156
|
-
step._idCoordsInLeg = leg.coords.length;
|
|
157
|
-
stepCoords.forEach((coords, idx) => {
|
|
158
|
-
if (
|
|
159
|
-
idx !== 0
|
|
160
|
-
|| leg.coords.length === 0
|
|
161
|
-
|| !leg.coords[leg.coords.length - 1].equalsTo(coords)
|
|
162
|
-
) {
|
|
163
|
-
leg.coords.push(coords);
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
step.name = jsonPathLink.Departure.Site.Name;
|
|
169
|
-
step.levelChange = null;
|
|
170
|
-
|
|
171
|
-
step.distance = jsonPathLink.Distance;
|
|
172
|
-
|
|
173
|
-
leg.steps.push(step);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
} else if (Constants.PUBLIC_TRANSPORT.includes(leg.mode)) {
|
|
177
|
-
|
|
178
|
-
leg.from = {
|
|
179
|
-
name: jsonLeg.Departure.StopPlace.Name,
|
|
180
|
-
coords: jsonToCoordinates(jsonLeg.Departure.StopPlace.Position)
|
|
181
|
-
};
|
|
182
|
-
leg.to = {
|
|
183
|
-
name: jsonLeg.Arrival.StopPlace.Name,
|
|
184
|
-
coords: jsonToCoordinates(jsonLeg.Arrival.StopPlace.Position)
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
let transportName = jsonLeg.Line.Number;
|
|
188
|
-
if (leg.mode === Constants.ROUTING_MODE.TRAM) {
|
|
189
|
-
// In order to remove the "TRAM " prefix.
|
|
190
|
-
transportName = transportName.substr(5);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
leg.transportInfo = {
|
|
194
|
-
name: transportName,
|
|
195
|
-
routeColor: jsonLeg.Line.Color,
|
|
196
|
-
routeTextColor: jsonLeg.Line.TextColor,
|
|
197
|
-
directionName: jsonLeg.Destination
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
for (const jsonStep of jsonLeg.steps.Step) {
|
|
201
|
-
const stepCoords = parseWKTGeometry(jsonStep.Geometry);
|
|
202
|
-
stepCoords.forEach((coords, idx) => {
|
|
203
|
-
if (
|
|
204
|
-
idx !== 0
|
|
205
|
-
|| leg.coords.length === 0
|
|
206
|
-
|| !leg.coords[leg.coords.length - 1].equalsTo(coords)
|
|
207
|
-
) {
|
|
208
|
-
leg.coords.push(coords);
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const legStep = new Step();
|
|
214
|
-
legStep.coords = leg.coords[0];
|
|
215
|
-
legStep._idCoordsInLeg = 0;
|
|
216
|
-
legStep.name = jsonLeg.Line.Name;
|
|
217
|
-
legStep.levelChange = null;
|
|
218
|
-
legStep.distance = jsonLeg.Distance;
|
|
219
|
-
leg.steps = [legStep];
|
|
220
|
-
} else {
|
|
221
|
-
Logger.warn(`[CitywayParser] Unknown leg mode: ${leg.mode}`);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
leg.distance = leg.coords.reduce((acc, coords, idx, arr) => {
|
|
225
|
-
if (idx === 0) {
|
|
226
|
-
return acc;
|
|
227
|
-
}
|
|
228
|
-
return acc + arr[idx - 1].distanceTo(coords);
|
|
229
|
-
}, 0);
|
|
230
|
-
|
|
231
|
-
itinerary.legs.push(leg);
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
itinerary.distance = itinerary.coords.reduce((acc, coords, idx, arr) => {
|
|
236
|
-
if (idx === 0) {
|
|
237
|
-
return acc;
|
|
238
|
-
}
|
|
239
|
-
return acc + arr[idx - 1].distanceTo(coords);
|
|
240
|
-
}, 0);
|
|
241
|
-
|
|
242
|
-
// All legs have to be parsed before computing steps metadata
|
|
243
|
-
generateStepsMetadata(itinerary);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
routerResponse.from = routerResponse.itineraries[0].from;
|
|
247
|
-
routerResponse.to = routerResponse.itineraries[routerResponse.itineraries.length - 1].to;
|
|
248
|
-
|
|
249
|
-
return routerResponse;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
|
|
3
|
-
import { Coordinates, GraphEdge, GraphItinerary, GraphNode, Level } from '@wemap/geo';
|
|
4
|
-
import { OsmElement, OsmNode, OsmWay } from '@wemap/osm';
|
|
5
|
-
|
|
6
|
-
import Itinerary from '../model/Itinerary.js';
|
|
7
|
-
import RouterResponse from '../model/RouterResponse.js';
|
|
8
|
-
import { generateStepsMetadata } from '../Utils.js';
|
|
9
|
-
import StepsGeneration from '../wemap/WemapStepsGeneration.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Generate multi itineraries from the DB JSON
|
|
13
|
-
* @param {object} json JSON file provided by the DB.
|
|
14
|
-
* @param {Coordinates} from itinerary start
|
|
15
|
-
* @param {Coordinates} to itinerary end
|
|
16
|
-
* @returns {?RouterResponse}
|
|
17
|
-
*/
|
|
18
|
-
export function createRouterResponseFromJson(json, from, to) {
|
|
19
|
-
|
|
20
|
-
const { segments: jsonSegments } = json;
|
|
21
|
-
|
|
22
|
-
if (!jsonSegments) {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const routerResponse = new RouterResponse();
|
|
27
|
-
routerResponse.routerName = 'deutsche-bahn';
|
|
28
|
-
|
|
29
|
-
routerResponse.from = from;
|
|
30
|
-
routerResponse.to = to;
|
|
31
|
-
|
|
32
|
-
/** @type {GraphEdge<OsmElement>[]} */
|
|
33
|
-
const edges = [];
|
|
34
|
-
|
|
35
|
-
/** @type {GraphNode<OsmElement>[]} */
|
|
36
|
-
const nodes = [];
|
|
37
|
-
|
|
38
|
-
/** @type {number[]} */
|
|
39
|
-
const edgesWeights = [];
|
|
40
|
-
|
|
41
|
-
let id = 1;
|
|
42
|
-
for (const jsonSegment of jsonSegments) {
|
|
43
|
-
|
|
44
|
-
const level = new Level(jsonSegment.fromLevel, jsonSegment.toLevel);
|
|
45
|
-
const osmWay = new OsmWay(id++, null, level);
|
|
46
|
-
|
|
47
|
-
for (const jsonPoint of jsonSegment.polyline) {
|
|
48
|
-
const coord = new Coordinates(jsonPoint.lat, jsonPoint.lon, null, level);
|
|
49
|
-
|
|
50
|
-
if (nodes.length !== 0
|
|
51
|
-
&& nodes[nodes.length - 1].coords.equalsTo(coord)) {
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const osmNode = new OsmNode(id++, coord);
|
|
56
|
-
const node = new GraphNode(osmNode.coords, osmNode);
|
|
57
|
-
|
|
58
|
-
if (nodes.length !== 0) {
|
|
59
|
-
const prevNode = nodes[nodes.length - 1];
|
|
60
|
-
const edge = new GraphEdge(prevNode, node, level, osmWay);
|
|
61
|
-
edges.push(edge);
|
|
62
|
-
edgesWeights.push(prevNode.coords.distanceTo(osmNode));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
nodes.push(node);
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** @type {GraphItinerary<OsmElement>} */
|
|
71
|
-
const graphItinerary = new GraphItinerary();
|
|
72
|
-
graphItinerary.nodes = nodes;
|
|
73
|
-
graphItinerary.edges = edges;
|
|
74
|
-
graphItinerary.edgesWeights = edgesWeights;
|
|
75
|
-
graphItinerary.start = nodes[0].coords;
|
|
76
|
-
graphItinerary.end = nodes[nodes.length - 1].coords;
|
|
77
|
-
|
|
78
|
-
const points = nodes.map(node => node.coords);
|
|
79
|
-
const itinerary = Itinerary.fromOrderedCoordinates(points, from, to);
|
|
80
|
-
itinerary.legs[0].steps = StepsGeneration.fromGraphItinerary(graphItinerary);
|
|
81
|
-
itinerary.legs[0].steps.map((step, idx) => (step._idCoordsInLeg = idx));
|
|
82
|
-
|
|
83
|
-
// All legs have to be parsed before computing steps metadata
|
|
84
|
-
generateStepsMetadata(itinerary);
|
|
85
|
-
|
|
86
|
-
routerResponse.itineraries.push(itinerary);
|
|
87
|
-
|
|
88
|
-
return routerResponse;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
package/src/idfm/IdfmUtils.js
DELETED
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import { Coordinates, Utils as GeoUtils } from '@wemap/geo';
|
|
3
|
-
|
|
4
|
-
import Itinerary from '../model/Itinerary.js';
|
|
5
|
-
import Leg from '../model/Leg.js';
|
|
6
|
-
import RouterResponse from '../model/RouterResponse.js';
|
|
7
|
-
import Step from '../model/Step.js';
|
|
8
|
-
import { generateStepsMetadata, dateWithTimeZone } from '../Utils.js';
|
|
9
|
-
import Constants from '../Constants.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* List of all modes supported by the API
|
|
13
|
-
* http://doc.navitia.io/#physical-mode
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const routingModeCorrespondance = new Map();
|
|
17
|
-
routingModeCorrespondance.set('Air', Constants.ROUTING_MODE.AIRPLANE);
|
|
18
|
-
routingModeCorrespondance.set('Boat', Constants.ROUTING_MODE.BOAT);
|
|
19
|
-
routingModeCorrespondance.set('Bus', Constants.ROUTING_MODE.BUS);
|
|
20
|
-
routingModeCorrespondance.set('BusRapidTransit', Constants.ROUTING_MODE.BUS);
|
|
21
|
-
routingModeCorrespondance.set('Coach', Constants.ROUTING_MODE.BUS);
|
|
22
|
-
routingModeCorrespondance.set('Ferry', Constants.ROUTING_MODE.FERRY);
|
|
23
|
-
routingModeCorrespondance.set('Funicular', Constants.ROUTING_MODE.FUNICULAR);
|
|
24
|
-
routingModeCorrespondance.set('LocalTrain', Constants.ROUTING_MODE.TRAIN);
|
|
25
|
-
routingModeCorrespondance.set('LongDistanceTrain', Constants.ROUTING_MODE.TRAIN);
|
|
26
|
-
routingModeCorrespondance.set('Metro', Constants.ROUTING_MODE.METRO);
|
|
27
|
-
routingModeCorrespondance.set('Métro', Constants.ROUTING_MODE.METRO);
|
|
28
|
-
routingModeCorrespondance.set('RailShuttle', Constants.ROUTING_MODE.TRAIN);
|
|
29
|
-
routingModeCorrespondance.set('RapidTransit', Constants.ROUTING_MODE.BUS);
|
|
30
|
-
routingModeCorrespondance.set('Shuttle', Constants.ROUTING_MODE.BUS);
|
|
31
|
-
routingModeCorrespondance.set('SuspendedCableCar', Constants.ROUTING_MODE.FUNICULAR);
|
|
32
|
-
routingModeCorrespondance.set('Taxi', Constants.ROUTING_MODE.TAXI);
|
|
33
|
-
routingModeCorrespondance.set('Train', Constants.ROUTING_MODE.TRAIN);
|
|
34
|
-
routingModeCorrespondance.set('Tramway', Constants.ROUTING_MODE.TRAM);
|
|
35
|
-
routingModeCorrespondance.set('walking', Constants.ROUTING_MODE.WALK);
|
|
36
|
-
routingModeCorrespondance.set('bike', Constants.ROUTING_MODE.BIKE);
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param {object} json
|
|
40
|
-
* @returns {Coordinates}
|
|
41
|
-
*/
|
|
42
|
-
export function jsonToCoordinates(json) {
|
|
43
|
-
return new Coordinates(Number(json.lat), Number(json.lon));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function getSectionCoords(section) {
|
|
47
|
-
const from = section.from.stop_point ? jsonToCoordinates(section.from.stop_point.coord) : jsonToCoordinates(section.from.address.coord);
|
|
48
|
-
const to = section.to.stop_point ? jsonToCoordinates(section.to.stop_point.coord) : jsonToCoordinates(section.to.address.coord);
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
from,
|
|
52
|
-
to
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Get last item of a given array
|
|
58
|
-
* @param {Array} array
|
|
59
|
-
* @returns {any}
|
|
60
|
-
*/
|
|
61
|
-
function last(array) {
|
|
62
|
-
return array[array.length - 1];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Since the IDFM API does not provide coords for each step, we need to compute them
|
|
67
|
-
* We trim the coordinates of the leg with the distance of each step and keep the last result as the coords of the step
|
|
68
|
-
* @param {Leg} leg
|
|
69
|
-
*/
|
|
70
|
-
function findStepsCoord(leg) {
|
|
71
|
-
const { steps, coords } = leg;
|
|
72
|
-
|
|
73
|
-
const duplicatedCoords = [...coords];
|
|
74
|
-
let previousStep = steps[0];
|
|
75
|
-
let accumulatedIndex = 0;
|
|
76
|
-
|
|
77
|
-
for (const [idx, step] of steps.entries()) {
|
|
78
|
-
let newCoords;
|
|
79
|
-
|
|
80
|
-
if (idx === 0) {
|
|
81
|
-
step._idCoordsInLeg = 0;
|
|
82
|
-
newCoords = coords[0];
|
|
83
|
-
} else if (idx === steps.length - 1) {
|
|
84
|
-
step._idCoordsInLeg = coords.length - 1;
|
|
85
|
-
newCoords = last(coords);
|
|
86
|
-
} else {
|
|
87
|
-
const result = GeoUtils.trimRoute(duplicatedCoords, duplicatedCoords[0], previousStep.distance);
|
|
88
|
-
accumulatedIndex += result.length - 1;
|
|
89
|
-
|
|
90
|
-
duplicatedCoords.splice(0, result.length - 1);
|
|
91
|
-
|
|
92
|
-
step._idCoordsInLeg = accumulatedIndex;
|
|
93
|
-
|
|
94
|
-
newCoords = last(result);
|
|
95
|
-
|
|
96
|
-
coords[step._idCoordsInLeg] = newCoords;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
step.coords = newCoords;
|
|
100
|
-
|
|
101
|
-
previousStep = step;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* @param {string} stringDate (e.g. 20211117T104516)
|
|
107
|
-
* @returns {number}
|
|
108
|
-
*/
|
|
109
|
-
function dateStringToTimestamp(stringDate, timeZone) {
|
|
110
|
-
const yearStr = stringDate.substr(0, 4);
|
|
111
|
-
const monthStr = stringDate.substr(4, 2);
|
|
112
|
-
const dayStr = stringDate.substr(6, 2);
|
|
113
|
-
const hoursStr = stringDate.substr(9, 2);
|
|
114
|
-
const minutesStr = stringDate.substr(11, 2);
|
|
115
|
-
const secondsStr = stringDate.substr(13, 2);
|
|
116
|
-
|
|
117
|
-
return dateWithTimeZone(
|
|
118
|
-
Number(yearStr),
|
|
119
|
-
Number(monthStr) - 1,
|
|
120
|
-
Number(dayStr),
|
|
121
|
-
Number(hoursStr),
|
|
122
|
-
Number(minutesStr),
|
|
123
|
-
Number(secondsStr),
|
|
124
|
-
timeZone
|
|
125
|
-
).getTime();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Generate multi itineraries from OTP JSON
|
|
130
|
-
* @param {object} json JSON file provided by OTP.
|
|
131
|
-
* @returns {?RouterResponse}
|
|
132
|
-
*/
|
|
133
|
-
export function createRouterResponseFromJson(json) {
|
|
134
|
-
|
|
135
|
-
if (!json || !json.journeys) {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const routerResponse = new RouterResponse();
|
|
140
|
-
routerResponse.routerName = 'idfm';
|
|
141
|
-
|
|
142
|
-
routerResponse.from = getSectionCoords(json.journeys[0].sections[0]).from;
|
|
143
|
-
routerResponse.to = getSectionCoords(last(json.journeys[0].sections)).to;
|
|
144
|
-
|
|
145
|
-
const timeZone = json.context.timezone;
|
|
146
|
-
|
|
147
|
-
for (const jsonItinerary of json.journeys) {
|
|
148
|
-
|
|
149
|
-
const itinerary = new Itinerary();
|
|
150
|
-
|
|
151
|
-
itinerary.duration = jsonItinerary.duration;
|
|
152
|
-
itinerary.startTime = dateStringToTimestamp(jsonItinerary.departure_date_time, timeZone);
|
|
153
|
-
itinerary.endTime = dateStringToTimestamp(jsonItinerary.arrival_date_time, timeZone);
|
|
154
|
-
itinerary.from = routerResponse.from;
|
|
155
|
-
itinerary.to = routerResponse.to;
|
|
156
|
-
itinerary.distance = 0;
|
|
157
|
-
|
|
158
|
-
routerResponse.itineraries.push(itinerary);
|
|
159
|
-
|
|
160
|
-
for (const jsonSection of jsonItinerary.sections) {
|
|
161
|
-
|
|
162
|
-
if (jsonSection.type === 'waiting' || jsonSection.type === 'transfer') {
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const leg = new Leg();
|
|
167
|
-
let existingCoords = [];
|
|
168
|
-
const { from, to } = getSectionCoords(jsonSection);
|
|
169
|
-
|
|
170
|
-
leg.distance = 0;
|
|
171
|
-
leg.mode = routingModeCorrespondance.get(jsonSection.mode);
|
|
172
|
-
leg.duration = jsonSection.duration;
|
|
173
|
-
leg.startTime = dateStringToTimestamp(jsonSection.departure_date_time, timeZone);
|
|
174
|
-
leg.endTime = dateStringToTimestamp(jsonSection.arrival_date_time, timeZone);
|
|
175
|
-
|
|
176
|
-
leg.from = {
|
|
177
|
-
name: jsonSection.from.name,
|
|
178
|
-
coords: from
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
leg.to = {
|
|
182
|
-
name: jsonSection.to.name,
|
|
183
|
-
coords: to
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
// A section can have multiple same coordinates, we need to remove them
|
|
187
|
-
leg.coords = jsonSection.geojson.coordinates.reduce((acc, [lon, lat]) => {
|
|
188
|
-
if (!existingCoords.includes(`${lon}-${lat}`)) {
|
|
189
|
-
existingCoords = existingCoords.concat(`${lon}-${lat}`);
|
|
190
|
-
acc.push(new Coordinates(lat, lon));
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return acc;
|
|
194
|
-
}, []);
|
|
195
|
-
|
|
196
|
-
leg.steps = [];
|
|
197
|
-
|
|
198
|
-
if (jsonSection.path) {
|
|
199
|
-
for (const jsonPathLink of jsonSection.path) {
|
|
200
|
-
const step = new Step();
|
|
201
|
-
|
|
202
|
-
step.levelChange = null;
|
|
203
|
-
|
|
204
|
-
step.name = jsonPathLink.name;
|
|
205
|
-
step.distance = jsonPathLink.length;
|
|
206
|
-
|
|
207
|
-
leg.distance += step.distance;
|
|
208
|
-
leg.steps.push(step);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
findStepsCoord(leg);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (jsonSection.type === 'public_transport') {
|
|
215
|
-
leg.transportInfo = {
|
|
216
|
-
name: jsonSection.display_informations.code,
|
|
217
|
-
routeColor: jsonSection.display_informations.color,
|
|
218
|
-
routeTextColor: jsonSection.display_informations.text_color,
|
|
219
|
-
directionName: jsonSection.display_informations.direction
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
leg.mode = routingModeCorrespondance.get(jsonSection.display_informations.physical_mode);
|
|
223
|
-
|
|
224
|
-
const legStep = new Step();
|
|
225
|
-
legStep.coords = leg.coords[0];
|
|
226
|
-
legStep._idCoordsInLeg = 0;
|
|
227
|
-
legStep.name = leg.transportInfo.directionName;
|
|
228
|
-
legStep.levelChange = null;
|
|
229
|
-
legStep.distance = jsonSection.geojson.properties[0].length;
|
|
230
|
-
|
|
231
|
-
leg.steps = [legStep];
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
itinerary.distance += leg.distance;
|
|
235
|
-
|
|
236
|
-
itinerary.legs.push(leg);
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// All legs have to be parsed before computing steps metadata
|
|
241
|
-
generateStepsMetadata(itinerary);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return routerResponse;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|