@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/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.2",
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": "8851e7c4537556e51a3f0c52de9fc80d5e37ad73"
34
+ "gitHead": "52637f96a68517d6bae4f531ae980ea5eba372ba"
35
35
  }
@@ -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
- const date = new Date(
29
- Number(yearStr), Number(monthStr) - 1, Number(dayStr),
30
- Number(hoursStr), Number(minutesStr), Number(secondsStr)
31
- );
32
- return date.getTime();
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 === 'WALK' || leg.mode === 'BICYCLE') {
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 (leg.mode === 'BUS' || leg.mode === 'TRAMWAY' || leg.mode === 'FUNICULAR' || leg.mode === 'TRAIN') {
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 === 'TRAMWAY') {
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
- // expect(itinerary1.startTime).equal(1620659156000);
40
- // expect(itinerary1.endTime).equal(1620661535000);
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
- // expect(itinerary1leg1.startTime).equal(1620659156000);
46
- // expect(itinerary1leg1.endTime).equal(1620659340000);
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('BICYCLE');
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
+
@@ -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 || ['BUS', 'FUNICULAR', 'TRAM', 'TRAIN'].includes(leg.mode);
82
- isBicycle = isBicycle || ['BIKE', 'BICYCLE'].includes(leg.mode);
83
- isDriving = isDriving || leg.mode === 'CAR';
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 WALK, BIKE, BUS, TRAM, CAR, FUNICULAR */
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
  */