@wemap/routers 6.0.2 → 6.2.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/itinerary-paris-idfm.json +9446 -0
- package/index.js +1 -0
- package/package.json +2 -2
- package/src/Constants.js +30 -0
- package/src/Utils.js +21 -0
- package/src/cityway/CitywayUtils.js +23 -11
- package/src/cityway/CitywayUtils.spec.js +5 -5
- package/src/idfm/IdfmUtils.js +247 -0
- package/src/idfm/IdfmUtils.spec.js +64 -0
- package/src/model/Itinerary.js +4 -3
- package/src/model/Leg.js +6 -1
package/index.js
CHANGED
|
@@ -19,6 +19,7 @@ export * as OsrmUtils from './src/osrm/OsrmUtils.js';
|
|
|
19
19
|
export * as OtpUtils from './src/otp/OtpUtils.js';
|
|
20
20
|
export * as CitywayUtils from './src/cityway/CitywayUtils.js';
|
|
21
21
|
export * as DeutscheBahnRouterUtils from './src/deutsche-bahn/DeutscheBahnRouterUtils.js';
|
|
22
|
+
export * as IdfmUtils from './src/idfm/IdfmUtils.js';
|
|
22
23
|
|
|
23
24
|
/* Others */
|
|
24
25
|
export { default as ItineraryInfoManager } from './src/ItineraryInfoManager.js';
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"directory": "packages/routers"
|
|
12
12
|
},
|
|
13
13
|
"name": "@wemap/routers",
|
|
14
|
-
"version": "6.0
|
|
14
|
+
"version": "6.2.0",
|
|
15
15
|
"bugs": {
|
|
16
16
|
"url": "https://github.com/wemap/wemap-modules-js/issues"
|
|
17
17
|
},
|
|
@@ -31,5 +31,5 @@
|
|
|
31
31
|
"@wemap/maths": "^6.0.0",
|
|
32
32
|
"@wemap/osm": "^6.0.0"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "52637f96a68517d6bae4f531ae980ea5eba372ba"
|
|
35
35
|
}
|
package/src/Constants.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const Constants = {};
|
|
2
|
+
|
|
3
|
+
Constants.ROUTING_MODE = {
|
|
4
|
+
AIRPLANE: 'AIRPLANE',
|
|
5
|
+
BOAT: 'BOAT',
|
|
6
|
+
BIKE: 'BIKE',
|
|
7
|
+
BUS: 'BUS',
|
|
8
|
+
CAR: 'CAR',
|
|
9
|
+
FERRY: 'FERRY',
|
|
10
|
+
FUNICULAR: 'FUNICULAR',
|
|
11
|
+
METRO: 'METRO',
|
|
12
|
+
TRAIN: 'TRAIN',
|
|
13
|
+
TAXI: 'TAXI',
|
|
14
|
+
TRAM: 'TRAM',
|
|
15
|
+
WALK: 'WALK'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
Constants.PUBLIC_TRANSPORT = [
|
|
19
|
+
Constants.ROUTING_MODE.AIRPLANE,
|
|
20
|
+
Constants.ROUTING_MODE.BOAT,
|
|
21
|
+
Constants.ROUTING_MODE.BUS,
|
|
22
|
+
Constants.ROUTING_MODE.FERRY,
|
|
23
|
+
Constants.ROUTING_MODE.FUNICULAR,
|
|
24
|
+
Constants.ROUTING_MODE.METRO,
|
|
25
|
+
Constants.ROUTING_MODE.TRAIN,
|
|
26
|
+
Constants.ROUTING_MODE.TAXI,
|
|
27
|
+
Constants.ROUTING_MODE.TRAM
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
export default Constants;
|
package/src/Utils.js
CHANGED
|
@@ -11,6 +11,27 @@ export function getDurationFromLength(length, speed = 5) {
|
|
|
11
11
|
return length / (speed * 1000 / 3600);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Create and return a date with a given timezone
|
|
16
|
+
* @param {number} year
|
|
17
|
+
* @param {number} month
|
|
18
|
+
* @param {number} day
|
|
19
|
+
* @param {number} hours
|
|
20
|
+
* @param {number} minutes
|
|
21
|
+
* @param {number} seconds
|
|
22
|
+
* @param {string} timeZone - timezone name (e.g. 'Europe/Paris')
|
|
23
|
+
*/
|
|
24
|
+
export function dateWithTimeZone(year, month, day, hour, minute, second, timeZone = 'Europe/Paris') {
|
|
25
|
+
const date = new Date(Date.UTC(year, month, day, hour, minute, second));
|
|
26
|
+
|
|
27
|
+
const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' }));
|
|
28
|
+
const tzDate = new Date(date.toLocaleString('en-US', { timeZone: timeZone }));
|
|
29
|
+
const offset = utcDate.getTime() - tzDate.getTime();
|
|
30
|
+
|
|
31
|
+
date.setTime(date.getTime() + offset);
|
|
32
|
+
|
|
33
|
+
return date;
|
|
34
|
+
}
|
|
14
35
|
|
|
15
36
|
/**
|
|
16
37
|
* @param {Itinerary} itinerary
|
|
@@ -7,7 +7,16 @@ import Itinerary from '../model/Itinerary.js';
|
|
|
7
7
|
import Leg from '../model/Leg.js';
|
|
8
8
|
import RouterResponse from '../model/RouterResponse.js';
|
|
9
9
|
import Step from '../model/Step.js';
|
|
10
|
-
import { generateStepsMetadata } from '../Utils.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);
|
|
11
20
|
|
|
12
21
|
/**
|
|
13
22
|
* @param {object} json
|
|
@@ -25,11 +34,15 @@ function jsonDateToTimestamp(jsonDate) {
|
|
|
25
34
|
const [dateStr, timeStr] = jsonDate.split(' ');
|
|
26
35
|
const [dayStr, monthStr, yearStr] = dateStr.split('/');
|
|
27
36
|
const [hoursStr, minutesStr, secondsStr] = timeStr.split(':');
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Number(
|
|
31
|
-
|
|
32
|
-
|
|
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();
|
|
33
46
|
}
|
|
34
47
|
|
|
35
48
|
/**
|
|
@@ -113,13 +126,13 @@ export function createRouterResponseFromJson(json) {
|
|
|
113
126
|
|
|
114
127
|
const leg = new Leg();
|
|
115
128
|
|
|
116
|
-
leg.mode = jsonLeg.TransportMode;
|
|
129
|
+
leg.mode = routingModeCorrespondance.get(jsonLeg.TransportMode);
|
|
117
130
|
leg.duration = parseDuration(jsonLeg.Duration);
|
|
118
131
|
leg.startTime = jsonDateToTimestamp(jsonLeg.Departure.Time);
|
|
119
132
|
leg.endTime = jsonDateToTimestamp(jsonLeg.Arrival.Time);
|
|
120
133
|
leg.coords = [];
|
|
121
134
|
|
|
122
|
-
if (leg.mode ===
|
|
135
|
+
if (leg.mode === Constants.ROUTING_MODE.WALK || leg.mode === Constants.ROUTING_MODE.BIKE) {
|
|
123
136
|
|
|
124
137
|
leg.from = {
|
|
125
138
|
name: jsonLeg.Departure.Site.Name,
|
|
@@ -160,7 +173,7 @@ export function createRouterResponseFromJson(json) {
|
|
|
160
173
|
leg.steps.push(step);
|
|
161
174
|
}
|
|
162
175
|
|
|
163
|
-
} else if (
|
|
176
|
+
} else if (Constants.PUBLIC_TRANSPORT.includes(leg.mode)) {
|
|
164
177
|
|
|
165
178
|
leg.from = {
|
|
166
179
|
name: jsonLeg.Departure.StopPlace.Name,
|
|
@@ -172,8 +185,7 @@ export function createRouterResponseFromJson(json) {
|
|
|
172
185
|
};
|
|
173
186
|
|
|
174
187
|
let transportName = jsonLeg.Line.Number;
|
|
175
|
-
if (leg.mode ===
|
|
176
|
-
leg.mode = 'TRAM';
|
|
188
|
+
if (leg.mode === Constants.ROUTING_MODE.TRAM) {
|
|
177
189
|
// In order to remove the "TRAM " prefix.
|
|
178
190
|
transportName = transportName.substr(5);
|
|
179
191
|
}
|
|
@@ -36,14 +36,14 @@ describe('CitywayUtils - createRouterResponseFromJson', () => {
|
|
|
36
36
|
expect(itinerary1.duration).equal(2379);
|
|
37
37
|
expect(itinerary1.mode).equal('PT');
|
|
38
38
|
// Do not work because of the input time format
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
expect(itinerary1.startTime).equal(1620659156000);
|
|
40
|
+
expect(itinerary1.endTime).equal(1620661535000);
|
|
41
41
|
expect(itinerary1.legs.length).equal(5);
|
|
42
42
|
|
|
43
43
|
const itinerary1leg1 = itinerary1.legs[0];
|
|
44
44
|
// Do not work because of the input time format
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
expect(itinerary1leg1.startTime).equal(1620659156000);
|
|
46
|
+
expect(itinerary1leg1.endTime).equal(1620659340000);
|
|
47
47
|
expect(itinerary1leg1.distance).to.be.closeTo(200.14, 0.1);
|
|
48
48
|
expect(itinerary1leg1.mode).equal('WALK');
|
|
49
49
|
expect(itinerary1leg1.transportInfo).is.null;
|
|
@@ -94,7 +94,7 @@ describe('CitywayUtils - createRouterResponseFromJson', () => {
|
|
|
94
94
|
verifyRouterResponseData(routerResponse);
|
|
95
95
|
|
|
96
96
|
expect(routerResponse.itineraries[0].mode).equal('BIKE');
|
|
97
|
-
expect(routerResponse.itineraries[0].legs[0].mode).equal('
|
|
97
|
+
expect(routerResponse.itineraries[0].legs[0].mode).equal('BIKE');
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
it('RouterResponse - 5', () => {
|
|
@@ -0,0 +1,247 @@
|
|
|
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
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* eslint-disable max-statements */
|
|
2
|
+
import chai from 'chai';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
import { Coordinates } from '@wemap/geo';
|
|
8
|
+
|
|
9
|
+
import { createRouterResponseFromJson } from './IdfmUtils.js';
|
|
10
|
+
|
|
11
|
+
import { verifyRouterResponseData } from '../model/RouterResponse.type.spec.js';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
const { expect } = chai;
|
|
15
|
+
|
|
16
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
|
|
18
|
+
describe('IdfmUtils - createRouterResponseFromJson', () => {
|
|
19
|
+
|
|
20
|
+
it('RouterResponse - 1', () => {
|
|
21
|
+
|
|
22
|
+
const filePath = path.resolve(__dirname, '../../assets/itinerary-paris-idfm.json');
|
|
23
|
+
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
24
|
+
const json = JSON.parse(fileString);
|
|
25
|
+
|
|
26
|
+
const routerResponse = createRouterResponseFromJson(json);
|
|
27
|
+
verifyRouterResponseData(routerResponse);
|
|
28
|
+
|
|
29
|
+
expect(routerResponse.routerName).equal('idfm');
|
|
30
|
+
expect(routerResponse.itineraries.length).equal(5);
|
|
31
|
+
expect(routerResponse.from.equalsTo(new Coordinates(48.875877, 2.301357))).true;
|
|
32
|
+
expect(routerResponse.to.equalsTo(new Coordinates(48.877877, 2.351929))).true;
|
|
33
|
+
|
|
34
|
+
const itinerary1 = routerResponse.itineraries[0];
|
|
35
|
+
expect(itinerary1.distance).to.be.closeTo(1242, 1);
|
|
36
|
+
expect(itinerary1.duration).equal(1842);
|
|
37
|
+
expect(itinerary1.mode).equal('PT');
|
|
38
|
+
// Do not work because of the input time format
|
|
39
|
+
expect(itinerary1.startTime).equal(1637596640000);
|
|
40
|
+
expect(itinerary1.endTime).equal(1637598482000);
|
|
41
|
+
expect(itinerary1.legs.length).equal(3);
|
|
42
|
+
|
|
43
|
+
const itinerary1leg1 = itinerary1.legs[0];
|
|
44
|
+
// Do not work because of the input time format
|
|
45
|
+
expect(itinerary1leg1.startTime).equal(1637596640000);
|
|
46
|
+
expect(itinerary1leg1.endTime).equal(1637597040000);
|
|
47
|
+
expect(itinerary1leg1.distance).to.be.closeTo(468, 1);
|
|
48
|
+
expect(itinerary1leg1.mode).equal('WALK');
|
|
49
|
+
expect(itinerary1leg1.transportInfo).is.null;
|
|
50
|
+
expect(itinerary1leg1.from.name).equal('8 Avenue Bertie Albrecht (Paris)');
|
|
51
|
+
expect(itinerary1leg1.from.coords.equalsTo(new Coordinates(48.875877, 2.301357))).true;
|
|
52
|
+
expect(itinerary1leg1.to.name).equal('Ternes (Paris)');
|
|
53
|
+
expect(itinerary1leg1.to.coords.equalsTo(new Coordinates(48.878228, 2.298113))).true;
|
|
54
|
+
|
|
55
|
+
const itinerary1leg2 = itinerary1.legs[1];
|
|
56
|
+
expect(itinerary1leg2.mode).equal('METRO');
|
|
57
|
+
expect(itinerary1leg2.transportInfo).is.not.null;
|
|
58
|
+
expect(itinerary1leg2.transportInfo.name).equal('2');
|
|
59
|
+
expect(itinerary1leg2.transportInfo.routeColor).equal('003CA6');
|
|
60
|
+
expect(itinerary1leg2.transportInfo.routeTextColor).equal('FFFFFF');
|
|
61
|
+
expect(itinerary1leg2.transportInfo.directionName).equal('Nation (Paris)');
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
package/src/model/Itinerary.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Coordinates, Network } from '@wemap/geo';
|
|
3
3
|
import Leg from './Leg.js';
|
|
4
4
|
import Step from './Step.js';
|
|
5
|
+
import Constants from '../Constants.js';
|
|
5
6
|
import { getDurationFromLength } from '../Utils.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -78,9 +79,9 @@ class Itinerary {
|
|
|
78
79
|
let isDriving;
|
|
79
80
|
|
|
80
81
|
this.legs.forEach((leg) => {
|
|
81
|
-
isPublicTransport = isPublicTransport ||
|
|
82
|
-
isBicycle = isBicycle ||
|
|
83
|
-
isDriving = isDriving || leg.mode ===
|
|
82
|
+
isPublicTransport = isPublicTransport || Constants.PUBLIC_TRANSPORT.includes(leg.mode);
|
|
83
|
+
isBicycle = isBicycle || leg.mode === Constants.ROUTING_MODE.BIKE;
|
|
84
|
+
isDriving = isDriving || leg.mode === Constants.ROUTING_MODE.CAR;
|
|
84
85
|
});
|
|
85
86
|
|
|
86
87
|
if (isPublicTransport) {
|
package/src/model/Leg.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Coordinates, Network } from '@wemap/geo';
|
|
2
2
|
|
|
3
3
|
import Step from './Step.js';
|
|
4
|
+
import Constants from '../Constants.js';
|
|
4
5
|
|
|
5
6
|
class Leg {
|
|
6
7
|
|
|
7
|
-
/** @type {!string} can be
|
|
8
|
+
/** @type {!string} can be values in Constants.ROUTING_MODE */
|
|
8
9
|
mode;
|
|
9
10
|
|
|
10
11
|
/** @type {!number} */
|
|
@@ -34,6 +35,10 @@ class Leg {
|
|
|
34
35
|
/** @type {?(Step[])} */
|
|
35
36
|
steps = null;
|
|
36
37
|
|
|
38
|
+
isPublicTransport() {
|
|
39
|
+
return Constants.PUBLIC_TRANSPORT.includes(this.mode);
|
|
40
|
+
}
|
|
41
|
+
|
|
37
42
|
/**
|
|
38
43
|
* @returns {Network}
|
|
39
44
|
*/
|