@wemap/routers 6.2.3 → 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.
Files changed (57) hide show
  1. package/assets/biocbon-bergere-rdc-network.osm +163 -0
  2. package/assets/gare-de-lest-network-pp-bounds.osm +1615 -0
  3. package/dist/wemap-routers.es.js +3011 -0
  4. package/dist/wemap-routers.es.js.map +1 -0
  5. package/index.js +13 -5
  6. package/package.json +9 -6
  7. package/src/Constants.js +1 -0
  8. package/src/ItineraryInfoManager.spec.js +2 -2
  9. package/src/Utils.js +0 -77
  10. package/src/model/Itinerary.js +41 -5
  11. package/src/model/Itinerary.spec.js +91 -0
  12. package/src/model/Itinerary.type.spec.js +3 -78
  13. package/src/model/Leg.js +89 -19
  14. package/src/model/Leg.spec.js +110 -0
  15. package/src/model/Leg.type.spec.js +48 -0
  16. package/src/model/LevelChange.js +14 -24
  17. package/src/model/LevelChange.spec.js +78 -0
  18. package/src/model/LevelChange.type.spec.js +26 -0
  19. package/src/model/RouterResponse.js +70 -1
  20. package/src/model/RouterResponse.spec.js +85 -0
  21. package/src/model/RouterResponse.type.spec.js +7 -4
  22. package/src/model/Step.js +45 -6
  23. package/src/model/Step.spec.js +100 -0
  24. package/src/model/Step.type.spec.js +52 -0
  25. package/src/remote/RemoteRouter.js +31 -0
  26. package/src/remote/RemoteRouterManager.js +84 -0
  27. package/src/remote/RemoteRouterOptions.js +25 -0
  28. package/src/remote/RemoteRouterServerUnreachable.js +10 -0
  29. package/src/remote/RemoteRouterUtils.js +78 -0
  30. package/src/remote/RoutingModeCorrespondanceNotFound.js +18 -0
  31. package/src/remote/cityway/CitywayRemoteRouter.js +386 -0
  32. package/src/{cityway/CitywayUtils.spec.js → remote/cityway/CitywayRemoteRouter.spec.js} +19 -18
  33. package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.js +143 -0
  34. package/src/{deutsche-bahn/DeutscheBahnRouterUtils.spec.js → remote/deutsche-bahn/DeutscheBahnRemoteRouter.spec.js} +7 -6
  35. package/src/remote/idfm/IdfmRemoteRouter.js +432 -0
  36. package/src/{idfm/IdfmUtils.spec.js → remote/idfm/IdfmRemoteRouter.spec.js} +7 -6
  37. package/src/remote/idfm/IdfmRemoteRouterTokenError.js +6 -0
  38. package/src/remote/osrm/OsrmRemoteRouter.js +331 -0
  39. package/src/{osrm/OsrmUtils.spec.js → remote/osrm/OsrmRemoteRouter.spec.js} +9 -15
  40. package/src/remote/otp/OtpRemoteRouter.js +222 -0
  41. package/src/{otp/OtpUtils.spec.js → remote/otp/OtpRemoteRouter.spec.js} +10 -9
  42. package/src/remote/wemap-meta/WemapMetaRemoteRouter.js +57 -0
  43. package/src/remote/wemap-meta/WemapMetaRemoteRouter.spec.js +22 -0
  44. package/src/remote/wemap-meta/WemapMetaRemoteRouterOptions.js +36 -0
  45. package/src/remote/wemap-meta/WemapMetaRemoteRouterPayload.js +44 -0
  46. package/src/wemap/WemapRouter.js +6 -0
  47. package/src/wemap/WemapRouterUtils.js +10 -4
  48. package/src/wemap/WemapStepsGeneration.js +36 -9
  49. package/src/wemap-meta/IOMap.js +191 -0
  50. package/src/wemap-meta/WemapMetaRouter.js +314 -0
  51. package/src/wemap-meta/WemapMetaRouter.spec.js +119 -0
  52. package/src/wemap-meta/WemapMetaRouterOptions.js +20 -0
  53. package/src/cityway/CitywayUtils.js +0 -309
  54. package/src/deutsche-bahn/DeutscheBahnRouterUtils.js +0 -91
  55. package/src/idfm/IdfmUtils.js +0 -256
  56. package/src/osrm/OsrmUtils.js +0 -269
  57. package/src/otp/OtpUtils.js +0 -150
@@ -1,309 +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('TRAMWAY', Constants.ROUTING_MODE.TRAM);
17
- routingModeCorrespondance.set('METRO', Constants.ROUTING_MODE.METRO);
18
- routingModeCorrespondance.set('FUNICULAR', Constants.ROUTING_MODE.FUNICULAR);
19
- routingModeCorrespondance.set('BUS', Constants.ROUTING_MODE.BUS);
20
- routingModeCorrespondance.set('COACH', Constants.ROUTING_MODE.BUS);
21
- routingModeCorrespondance.set('SCHOOL', Constants.ROUTING_MODE.BUS);
22
- routingModeCorrespondance.set('BUS_PMR', Constants.ROUTING_MODE.BUS);
23
- routingModeCorrespondance.set('MINIBUS', Constants.ROUTING_MODE.BUS);
24
- routingModeCorrespondance.set('TROLLEY_BUS', Constants.ROUTING_MODE.BUS);
25
- routingModeCorrespondance.set('TAXIBUS', Constants.ROUTING_MODE.BUS);
26
- routingModeCorrespondance.set('SHUTTLE', Constants.ROUTING_MODE.BUS);
27
- routingModeCorrespondance.set('TRAIN', Constants.ROUTING_MODE.TRAIN);
28
- routingModeCorrespondance.set('HST', Constants.ROUTING_MODE.TRAIN);
29
- routingModeCorrespondance.set('LOCAL_TRAIN', Constants.ROUTING_MODE.TRAIN);
30
- routingModeCorrespondance.set('AIR', Constants.ROUTING_MODE.AIRPLANE);
31
- routingModeCorrespondance.set('FERRY', Constants.ROUTING_MODE.BOAT);
32
- routingModeCorrespondance.set('TAXI', Constants.ROUTING_MODE.UNKNOWN);
33
- routingModeCorrespondance.set('CAR_POOL', Constants.ROUTING_MODE.UNKNOWN);
34
- routingModeCorrespondance.set('PRIVATE_VEHICLE', Constants.ROUTING_MODE.CAR);
35
- routingModeCorrespondance.set('SCOOTER', Constants.ROUTING_MODE.MOTO);
36
-
37
- const planTripType = new Map();
38
- planTripType.set(0, Constants.ROUTING_MODE.BUS);
39
- planTripType.set(1, Constants.ROUTING_MODE.WALK);
40
- planTripType.set(2, Constants.ROUTING_MODE.BIKE);
41
- planTripType.set(3, Constants.ROUTING_MODE.CAR);
42
- planTripType.set(4, Constants.ROUTING_MODE.UNKNOWN);
43
- planTripType.set(5, Constants.ROUTING_MODE.UNKNOWN);
44
- planTripType.set(6, Constants.ROUTING_MODE.UNKNOWN);
45
- planTripType.set(7, Constants.ROUTING_MODE.UNKNOWN);
46
- planTripType.set(8, Constants.ROUTING_MODE.UNKNOWN);
47
- planTripType.set(9, Constants.ROUTING_MODE.UNKNOWN);
48
- planTripType.set(10, Constants.ROUTING_MODE.UNKNOWN);
49
- planTripType.set(11, Constants.ROUTING_MODE.UNKNOWN);
50
- planTripType.set(12, Constants.ROUTING_MODE.UNKNOWN);
51
- planTripType.set(13, Constants.ROUTING_MODE.UNKNOWN);
52
- planTripType.set(14, Constants.ROUTING_MODE.UNKNOWN);
53
-
54
- /**
55
- * @param {object} json
56
- * @returns {Coordinates}
57
- */
58
- export function jsonToCoordinates(json) {
59
- return new Coordinates(json.Lat, json.Long);
60
- }
61
-
62
- /**
63
- * @param {string} jsonDate
64
- * @returns {number}
65
- */
66
- function jsonDateToTimestamp(jsonDate) {
67
- const [dateStr, timeStr] = jsonDate.split(' ');
68
- const [dayStr, monthStr, yearStr] = dateStr.split('/');
69
- const [hoursStr, minutesStr, secondsStr] = timeStr.split(':');
70
-
71
- return dateWithTimeZone(
72
- Number(yearStr),
73
- Number(monthStr) - 1,
74
- Number(dayStr),
75
- Number(hoursStr),
76
- Number(minutesStr),
77
- Number(secondsStr)
78
- ).getTime();
79
- }
80
-
81
- /**
82
- * @param {string} wktGeometry
83
- * @returns {Coordinates[]}
84
- */
85
- function parseWKTGeometry(wktGeometry) {
86
- const tmpCoordsStr = wktGeometry.match(/LINESTRING \((.*)\)/i);
87
- const tmpCoordsPt = wktGeometry.match(/POINT \((.*)\)/i);
88
- if (!tmpCoordsStr && !tmpCoordsPt) {
89
- return null;
90
- }
91
-
92
- if (tmpCoordsPt) {
93
- const [lng, lat] = tmpCoordsPt[1].split(' ');
94
- return [new Coordinates(Number(lat), Number(lng))];
95
- }
96
-
97
- return tmpCoordsStr[1].split(',').map(str => {
98
- const sp = str.trim().split(' ');
99
- return new Coordinates(Number(sp[1]), Number(sp[0]));
100
- });
101
- }
102
-
103
- /**
104
- * @param {string} iso8601Duration
105
- * @see https://stackoverflow.com/a/29153059/2239938
106
- */
107
- function parseDuration(iso8601Duration) {
108
- const iso8601DurationRegex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/;
109
-
110
- var matches = iso8601Duration.match(iso8601DurationRegex);
111
-
112
- // const sign = typeof matches[1] === 'undefined' ? '+' : '-',
113
- const years = typeof matches[2] === 'undefined' ? 0 : Number(matches[2]);
114
- const months = typeof matches[3] === 'undefined' ? 0 : Number(matches[3]);
115
- const weeks = typeof matches[4] === 'undefined' ? 0 : Number(matches[4]);
116
- const days = typeof matches[5] === 'undefined' ? 0 : Number(matches[5]);
117
- const hours = typeof matches[6] === 'undefined' ? 0 : Number(matches[6]);
118
- const minutes = typeof matches[7] === 'undefined' ? 0 : Number(matches[7]);
119
- const seconds = typeof matches[8] === 'undefined' ? 0 : Number(matches[8]);
120
-
121
- return seconds
122
- + minutes * 60
123
- + hours * 3600
124
- + days * 86400
125
- + weeks * (86400 * 7)
126
- + months * (86400 * 30)
127
- + years * (86400 * 365.25);
128
- }
129
-
130
- /**
131
- * Generate multi itineraries from Cityway JSON
132
- * @param {object} json JSON file provided by Cityway.
133
- * @returns {?RouterResponse}
134
- * @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
135
- */
136
- export function createRouterResponseFromJson(json) {
137
-
138
- if (json.StatusCode !== 200 || !json.Data || !json.Data.length) {
139
- return null;
140
- }
141
-
142
- const routerResponse = new RouterResponse();
143
- routerResponse.routerName = 'cityway';
144
-
145
-
146
- // Do not know if it the best approach, but it works...
147
- const allJsonTrips = json.Data.reduce((acc, dataObj) => {
148
- acc.push(...dataObj.response.trips.Trip.map(trip => ({
149
- ...trip,
150
- ...(dataObj.hasOwnProperty('PlanTripType') ? {PlanTripType: dataObj.PlanTripType} : {})
151
- })));
152
- return acc;
153
- }, []);
154
-
155
- // eslint-disable-next-line no-labels
156
- itineraryLoop:
157
- for (const trip of allJsonTrips) {
158
-
159
- if (trip.hasOwnProperty('PlanTripType') && planTripType.get(trip.PlanTripType) === Constants.ROUTING_MODE.UNKNOWN) {
160
- continue;
161
- }
162
-
163
- const itinerary = new Itinerary();
164
-
165
- itinerary.duration = parseDuration(trip.Duration);
166
- itinerary.startTime = jsonDateToTimestamp(trip.Departure.Time);
167
- itinerary.from = jsonToCoordinates(trip.Departure.Site.Position);
168
- itinerary.endTime = jsonDateToTimestamp(trip.Arrival.Time);
169
- itinerary.to = jsonToCoordinates(trip.Arrival.Site.Position);
170
-
171
- for (const jsonSection of trip.sections.Section) {
172
-
173
- const jsonLeg = jsonSection.Leg ? jsonSection.Leg : jsonSection.PTRide;
174
-
175
- const leg = new Leg();
176
-
177
- leg.mode = routingModeCorrespondance.get(jsonLeg.TransportMode);
178
- leg.duration = parseDuration(jsonLeg.Duration);
179
- leg.startTime = jsonDateToTimestamp(jsonLeg.Departure.Time);
180
- leg.endTime = jsonDateToTimestamp(jsonLeg.Arrival.Time);
181
- leg.coords = [];
182
-
183
- if (leg.mode === Constants.ROUTING_MODE.UNKNOWN) {
184
- // eslint-disable-next-line
185
- continue itineraryLoop;
186
- }
187
-
188
- if (leg.mode === Constants.ROUTING_MODE.WALK
189
- || leg.mode === Constants.ROUTING_MODE.BIKE
190
- || leg.mode === Constants.ROUTING_MODE.CAR) {
191
-
192
- leg.from = {
193
- name: jsonLeg.Departure.Site.Name,
194
- coords: jsonToCoordinates(jsonLeg.Departure.Site.Position)
195
- };
196
- leg.to = {
197
- name: jsonLeg.Arrival.Site.Name,
198
- coords: jsonToCoordinates(jsonLeg.Arrival.Site.Position)
199
- };
200
-
201
- leg.steps = [];
202
- for (const jsonPathLink of jsonLeg.pathLinks.PathLink) {
203
- const step = new Step();
204
- let stepCoords;
205
- if (jsonPathLink.Geometry) {
206
- stepCoords = parseWKTGeometry(jsonPathLink.Geometry);
207
- } else {
208
- stepCoords = [leg.from.coords, leg.to.coords];
209
- }
210
- step.coords = stepCoords[0];
211
- step._idCoordsInLeg = leg.coords.length;
212
- stepCoords.forEach((coords, idx) => {
213
- if (
214
- idx !== 0
215
- || leg.coords.length === 0
216
- || !leg.coords[leg.coords.length - 1].equalsTo(coords)
217
- ) {
218
- leg.coords.push(coords);
219
- }
220
- });
221
-
222
-
223
- step.name = jsonPathLink.Departure.Site.Name;
224
- step.levelChange = null;
225
-
226
- step.distance = jsonPathLink.Distance;
227
-
228
- leg.steps.push(step);
229
- }
230
-
231
- } else if (Constants.PUBLIC_TRANSPORT.includes(leg.mode)) {
232
-
233
- leg.from = {
234
- name: jsonLeg.Departure.StopPlace.Name,
235
- coords: jsonToCoordinates(jsonLeg.Departure.StopPlace.Position)
236
- };
237
- leg.to = {
238
- name: jsonLeg.Arrival.StopPlace.Name,
239
- coords: jsonToCoordinates(jsonLeg.Arrival.StopPlace.Position)
240
- };
241
-
242
- let transportName = jsonLeg.Line.Number;
243
- if (leg.mode === Constants.ROUTING_MODE.TRAM && transportName.toLowerCase().includes('tram')) {
244
- // In order to remove the "TRAM " prefix.
245
- transportName = transportName.substr(5);
246
- }
247
-
248
- leg.transportInfo = {
249
- name: transportName,
250
- routeColor: jsonLeg.Line.Color,
251
- routeTextColor: jsonLeg.Line.TextColor,
252
- directionName: jsonLeg.Destination
253
- };
254
-
255
- for (const jsonStep of jsonLeg.steps.Step) {
256
- const stepCoords = parseWKTGeometry(jsonStep.Geometry);
257
- stepCoords.forEach((coords, idx) => {
258
- if (
259
- idx !== 0
260
- || leg.coords.length === 0
261
- || !leg.coords[leg.coords.length - 1].equalsTo(coords)
262
- ) {
263
- leg.coords.push(coords);
264
- }
265
- });
266
- }
267
-
268
- const legStep = new Step();
269
- legStep.coords = leg.coords[0];
270
- legStep._idCoordsInLeg = 0;
271
- legStep.name = jsonLeg.Line.Name;
272
- legStep.levelChange = null;
273
- legStep.distance = jsonLeg.Distance;
274
- leg.steps = [legStep];
275
- } else {
276
- Logger.warn(`[CitywayParser] Unknown leg mode: ${jsonLeg.TransportMode}`);
277
- }
278
-
279
- leg.distance = leg.coords.reduce((acc, coords, idx, arr) => {
280
- if (idx === 0) {
281
- return acc;
282
- }
283
- return acc + arr[idx - 1].distanceTo(coords);
284
- }, 0);
285
-
286
- itinerary.legs.push(leg);
287
-
288
- }
289
-
290
- routerResponse.itineraries.push(itinerary);
291
-
292
- itinerary.distance = itinerary.coords.reduce((acc, coords, idx, arr) => {
293
- if (idx === 0) {
294
- return acc;
295
- }
296
- return acc + arr[idx - 1].distanceTo(coords);
297
- }, 0);
298
-
299
- // All legs have to be parsed before computing steps metadata
300
- generateStepsMetadata(itinerary);
301
- }
302
-
303
- routerResponse.from = routerResponse.itineraries[0].from;
304
- routerResponse.to = routerResponse.itineraries[routerResponse.itineraries.length - 1].to;
305
-
306
- return routerResponse;
307
- }
308
-
309
-
@@ -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
-
@@ -1,256 +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('RER', Constants.ROUTING_MODE.TRAIN);
35
- routingModeCorrespondance.set('Tramway', Constants.ROUTING_MODE.TRAM);
36
- routingModeCorrespondance.set('walking', Constants.ROUTING_MODE.WALK);
37
- routingModeCorrespondance.set('bike', Constants.ROUTING_MODE.BIKE);
38
-
39
- /**
40
- * @param {object} json
41
- * @returns {Coordinates}
42
- */
43
- export function jsonToCoordinates(json) {
44
- return new Coordinates(Number(json.lat), Number(json.lon));
45
- }
46
-
47
- function getSectionCoords(section) {
48
- const from = section.from.stop_point ? jsonToCoordinates(section.from.stop_point.coord) : jsonToCoordinates(section.from.address.coord);
49
- const to = section.to.stop_point ? jsonToCoordinates(section.to.stop_point.coord) : jsonToCoordinates(section.to.address.coord);
50
-
51
- return {
52
- from,
53
- to
54
- };
55
- }
56
-
57
- /**
58
- * Get last item of a given array
59
- * @param {Array} array
60
- * @returns {any}
61
- */
62
- function last(array) {
63
- return array[array.length - 1];
64
- }
65
-
66
- /**
67
- * Since the IDFM API does not provide coords for each step, we need to compute them
68
- * We trim the coordinates of the leg with the distance of each step and keep the last result as the coords of the step
69
- * @param {Leg} leg
70
- */
71
- function findStepsCoord(leg) {
72
- const { steps, coords } = leg;
73
-
74
- const duplicatedCoords = [...coords];
75
- let previousStep = steps[0];
76
- let accumulatedIndex = 0;
77
-
78
- for (const [idx, step] of steps.entries()) {
79
- let newCoords;
80
-
81
- if (idx === 0) {
82
- step._idCoordsInLeg = 0;
83
- newCoords = coords[0];
84
- } else if (idx === steps.length - 1) {
85
- step._idCoordsInLeg = coords.length - 1;
86
- newCoords = last(coords);
87
- } else if (duplicatedCoords.length === 1) {
88
- accumulatedIndex++;
89
-
90
- step._idCoordsInLeg = accumulatedIndex;
91
-
92
- newCoords = duplicatedCoords[0];
93
-
94
- coords[step._idCoordsInLeg] = newCoords;
95
- } else {
96
- const result = GeoUtils.trimRoute(duplicatedCoords, duplicatedCoords[0], previousStep.distance);
97
- accumulatedIndex += result.length - 1;
98
-
99
- duplicatedCoords.splice(0, result.length - 1);
100
-
101
- step._idCoordsInLeg = accumulatedIndex;
102
-
103
- newCoords = last(result);
104
-
105
- coords[step._idCoordsInLeg] = newCoords;
106
- }
107
-
108
- step.coords = newCoords;
109
-
110
- previousStep = step;
111
- }
112
- }
113
-
114
- /**
115
- * @param {string} stringDate (e.g. 20211117T104516)
116
- * @returns {number}
117
- */
118
- function dateStringToTimestamp(stringDate, timeZone) {
119
- const yearStr = stringDate.substr(0, 4);
120
- const monthStr = stringDate.substr(4, 2);
121
- const dayStr = stringDate.substr(6, 2);
122
- const hoursStr = stringDate.substr(9, 2);
123
- const minutesStr = stringDate.substr(11, 2);
124
- const secondsStr = stringDate.substr(13, 2);
125
-
126
- return dateWithTimeZone(
127
- Number(yearStr),
128
- Number(monthStr) - 1,
129
- Number(dayStr),
130
- Number(hoursStr),
131
- Number(minutesStr),
132
- Number(secondsStr),
133
- timeZone
134
- ).getTime();
135
- }
136
-
137
- /**
138
- * Generate multi itineraries from OTP JSON
139
- * @param {object} json JSON file provided by OTP.
140
- * @returns {?RouterResponse}
141
- */
142
- export function createRouterResponseFromJson(json) {
143
-
144
- if (!json || !json.journeys) {
145
- return null;
146
- }
147
-
148
- const routerResponse = new RouterResponse();
149
- routerResponse.routerName = 'idfm';
150
-
151
- routerResponse.from = getSectionCoords(json.journeys[0].sections[0]).from;
152
- routerResponse.to = getSectionCoords(last(json.journeys[0].sections)).to;
153
-
154
- const timeZone = json.context.timezone;
155
-
156
- for (const jsonItinerary of json.journeys) {
157
-
158
- const itinerary = new Itinerary();
159
-
160
- itinerary.duration = jsonItinerary.duration;
161
- itinerary.startTime = dateStringToTimestamp(jsonItinerary.departure_date_time, timeZone);
162
- itinerary.endTime = dateStringToTimestamp(jsonItinerary.arrival_date_time, timeZone);
163
- itinerary.from = routerResponse.from;
164
- itinerary.to = routerResponse.to;
165
- itinerary.distance = 0;
166
-
167
- routerResponse.itineraries.push(itinerary);
168
-
169
- for (const jsonSection of jsonItinerary.sections) {
170
-
171
- if (jsonSection.type === 'waiting' || jsonSection.type === 'transfer') {
172
- continue;
173
- }
174
-
175
- const leg = new Leg();
176
- let existingCoords = [];
177
- const { from, to } = getSectionCoords(jsonSection);
178
-
179
- leg.distance = 0;
180
- leg.mode = routingModeCorrespondance.get(jsonSection.mode);
181
- leg.duration = jsonSection.duration;
182
- leg.startTime = dateStringToTimestamp(jsonSection.departure_date_time, timeZone);
183
- leg.endTime = dateStringToTimestamp(jsonSection.arrival_date_time, timeZone);
184
-
185
- leg.from = {
186
- name: jsonSection.from.name,
187
- coords: from
188
- };
189
-
190
- leg.to = {
191
- name: jsonSection.to.name,
192
- coords: to
193
- };
194
-
195
- // A section can have multiple same coordinates, we need to remove them
196
- leg.coords = jsonSection.geojson.coordinates.reduce((acc, [lon, lat]) => {
197
- if (!existingCoords.includes(`${lon}-${lat}`)) {
198
- existingCoords = existingCoords.concat(`${lon}-${lat}`);
199
- acc.push(new Coordinates(lat, lon));
200
- }
201
-
202
- return acc;
203
- }, []);
204
-
205
- leg.steps = [];
206
-
207
- if (jsonSection.path) {
208
- for (const jsonPathLink of jsonSection.path) {
209
- const step = new Step();
210
-
211
- step.levelChange = null;
212
-
213
- step.name = jsonPathLink.name;
214
- step.distance = jsonPathLink.length;
215
-
216
- leg.distance += step.distance;
217
- leg.steps.push(step);
218
- }
219
-
220
- findStepsCoord(leg);
221
- }
222
-
223
- if (jsonSection.type === 'public_transport') {
224
- leg.transportInfo = {
225
- name: jsonSection.display_informations.code,
226
- routeColor: jsonSection.display_informations.color,
227
- routeTextColor: jsonSection.display_informations.text_color,
228
- directionName: jsonSection.display_informations.direction
229
- };
230
-
231
- leg.mode = routingModeCorrespondance.get(jsonSection.display_informations.physical_mode);
232
-
233
- const legStep = new Step();
234
- legStep.coords = leg.coords[0];
235
- legStep._idCoordsInLeg = 0;
236
- legStep.name = leg.transportInfo.directionName;
237
- legStep.levelChange = null;
238
- legStep.distance = jsonSection.geojson.properties[0].length;
239
-
240
- leg.steps = [legStep];
241
- }
242
-
243
- itinerary.distance += leg.distance;
244
-
245
- itinerary.legs.push(leg);
246
-
247
- }
248
-
249
- // All legs have to be parsed before computing steps metadata
250
- generateStepsMetadata(itinerary);
251
- }
252
-
253
- return routerResponse;
254
- }
255
-
256
-