@wemap/routers 7.1.1 → 7.2.1

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/src/Utils.js CHANGED
@@ -1,3 +1,6 @@
1
+
2
+ import RouterResponse from './model/RouterResponse.js';
3
+
1
4
  /**
2
5
  * Get route duration
3
6
  * @param {Number} speed in km/h
@@ -6,3 +9,55 @@
6
9
  export function getDurationFromLength(length, speed = 5) {
7
10
  return length / (speed * 1000 / 3600);
8
11
  }
12
+
13
+ /* eslint-disable max-statements */
14
+ /* eslint-disable max-depth */
15
+ /**
16
+ * @param {RouterResponse} routerResponse
17
+ * @param {Number} levelFactor
18
+ */
19
+ export function multiplyRouterResponseLevel(routerResponse, levelFactor) {
20
+ if (routerResponse.from.level) {
21
+ routerResponse.from.level.multiplyBy(levelFactor);
22
+ }
23
+ if (routerResponse.to.level) {
24
+ routerResponse.to.level.multiplyBy(levelFactor);
25
+ }
26
+ for (const itinerary of routerResponse.itineraries) {
27
+ if (itinerary.from.level) {
28
+ itinerary.from.level.multiplyBy(levelFactor);
29
+ }
30
+ if (itinerary.to.level) {
31
+ itinerary.to.level.multiplyBy(levelFactor);
32
+ }
33
+
34
+ for (const leg of itinerary.legs) {
35
+ if (leg.from.coords.level) {
36
+ leg.from.coords.level.multiplyBy(levelFactor);
37
+ }
38
+ if (leg.to.coords.level) {
39
+ leg.to.coords.level.multiplyBy(levelFactor);
40
+ }
41
+ for (const coords of leg.coords) {
42
+ if (coords.level) {
43
+ coords.level.multiplyBy(levelFactor);
44
+ }
45
+ }
46
+ if (leg.steps) {
47
+ for (const step of leg.steps) {
48
+ if (step.coords.level) {
49
+ step.coords.level.multiplyBy(levelFactor);
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ if (itinerary._coords) {
56
+ for (const coords of itinerary._coords) {
57
+ if (coords.level) {
58
+ coords.level.multiplyBy(levelFactor);
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,60 @@
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 RouterResponse from './model/RouterResponse.js';
8
+ import { multiplyRouterResponseLevel } from './Utils.js';
9
+
10
+ const { expect } = chai;
11
+
12
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
+ const assetsPath = path.resolve(__dirname, '../assets');
14
+
15
+ describe('Routers Utils', () => {
16
+
17
+ it('multiplyRouterResponseLevel', () => {
18
+
19
+ const filePath = path.resolve(assetsPath, 'rr-wemap-meta-multi-level.json');
20
+ const fileString = fs.readFileSync(filePath, 'utf8');
21
+ const json = JSON.parse(fileString);
22
+
23
+ const routerResponse = RouterResponse.fromJson(json);
24
+ multiplyRouterResponseLevel(routerResponse, 5);
25
+
26
+ expect(routerResponse.from.level.val).equal(10);
27
+ expect(routerResponse.to.level.val).equal(5);
28
+
29
+ const itinerary = routerResponse.itineraries[0];
30
+ expect(itinerary.from.level.val).equal(10);
31
+ expect(itinerary.to.level.val).equal(5);
32
+
33
+ const leg = itinerary.legs[0];
34
+ expect(leg.from.coords.level.val).equal(10);
35
+ expect(leg.to.coords.level.val).equal(5);
36
+
37
+ for (let i = 0; i < leg.coords.length; i++) {
38
+ if (i <= 6) {
39
+ expect(leg.coords[i].level.val).equal(10);
40
+ } else if (i <= 8) {
41
+ expect(leg.coords[i].level.up).equal(10);
42
+ expect(leg.coords[i].level.low).equal(5);
43
+ } else {
44
+ expect(leg.coords[i].level.val).equal(5);
45
+ }
46
+ }
47
+
48
+ const { steps } = leg;
49
+ for (let i = 0; i < steps.length; i++) {
50
+ if (i <= 5) {
51
+ expect(steps[i].coords.level.val).equal(10);
52
+ } else {
53
+ expect(steps[i].coords.level.val).equal(5);
54
+ }
55
+ }
56
+ });
57
+
58
+
59
+ });
60
+
@@ -1,6 +1,10 @@
1
+ import { NoRouteFoundError } from '@wemap/geo';
1
2
  import { diffAngle } from '@wemap/maths';
2
3
 
3
4
  import Itinerary from '../model/Itinerary.js';
5
+ import IdfmRemoteRouterTokenError from './idfm/IdfmRemoteRouterTokenError.js';
6
+ import RemoteRouterServerUnreachable from './RemoteRouterServerUnreachable.js';
7
+ import RoutingModeCorrespondanceNotFound from './RoutingModeCorrespondanceNotFound.js';
4
8
 
5
9
 
6
10
  /**
@@ -76,3 +80,10 @@ export function dateWithTimeZone(year, month, day, hour, minute, second, timeZon
76
80
 
77
81
  return date;
78
82
  }
83
+
84
+ export function isRoutingError(e) {
85
+ return e instanceof RemoteRouterServerUnreachable
86
+ || e instanceof RoutingModeCorrespondanceNotFound
87
+ || e instanceof IdfmRemoteRouterTokenError
88
+ || e instanceof NoRouteFoundError;
89
+ }
@@ -103,14 +103,37 @@ class IdfmRemoteRouter extends RemoteRouter {
103
103
 
104
104
  const url = this.getURL(endpointUrl, mode, waypoints);
105
105
 
106
- const res = await fetch(url, {
106
+ const res = await (fetch(url, {
107
107
  method: 'GET',
108
108
  headers: { Authorization: 'Bearer ' + this.token }
109
+ }).catch(() => {
110
+ throw new RemoteRouterServerUnreachable(this.rname, url);
111
+ }));
112
+
113
+
114
+ const response = await res.json().catch(() => {
115
+ throw new RemoteRouterServerUnreachable(this.rname, url);
109
116
  });
117
+
118
+ // When IDFM failed to calculate an itinerary (ie. start or end
119
+ // point is far from network), it respond a 404 with an error message
120
+ if (res.status === 404) {
121
+ let errorMessage = 'no details.';
122
+ if (response && 'error' in response && 'message' in response.error) {
123
+ errorMessage = response.error.message;
124
+ }
125
+
126
+ const routerResponse = new RouterResponse();
127
+ routerResponse.routerName = this.rname;
128
+ routerResponse.from = waypoints[0];
129
+ routerResponse.to = waypoints[1];
130
+ routerResponse.error = errorMessage;
131
+ return routerResponse;
132
+ }
133
+
110
134
  if (res.status !== 200) {
111
135
  throw new RemoteRouterServerUnreachable(this.rname, url);
112
136
  }
113
- const response = await res.json();
114
137
 
115
138
  return this.createRouterResponseFromJson(response);
116
139
  }
@@ -181,17 +204,17 @@ class IdfmRemoteRouter extends RemoteRouter {
181
204
 
182
205
  let query = '';
183
206
  switch (mode) {
184
- case Constants.ROUTING_MODE.WALK:
185
- query = this.getWalkingQuery();
186
- break;
187
- case Constants.ROUTING_MODE.BIKE:
188
- query = this.getBikeQuery();
189
- break;
190
- case Constants.ROUTING_MODE.CAR:
191
- query = this.getCarQuery();
192
- break;
193
- default:
194
- break;
207
+ case Constants.ROUTING_MODE.WALK:
208
+ query = this.getWalkingQuery();
209
+ break;
210
+ case Constants.ROUTING_MODE.BIKE:
211
+ query = this.getBikeQuery();
212
+ break;
213
+ case Constants.ROUTING_MODE.CAR:
214
+ query = this.getCarQuery();
215
+ break;
216
+ default:
217
+ break;
195
218
  }
196
219
 
197
220
  url = `${url.origin}${url.pathname}${search}${query}`;
@@ -7,6 +7,7 @@ import Logger from '@wemap/logger';
7
7
  import IOMap from './IOMap.js';
8
8
  import WemapMetaRouterOptions from './WemapMetaRouterOptions.js';
9
9
  import RemoteRouterManager from '../remote/RemoteRouterManager.js';
10
+ import { isRoutingError } from '../remote/RemoteRouterUtils.js';
10
11
  import WemapMetaRemoteRouterOptions from '../remote/wemap-meta/WemapMetaRemoteRouterOptions.js';
11
12
  import WemapRouterOptions from '../wemap/WemapRouterOptions.js';
12
13
  import RouterResponse from '../model/RouterResponse.js';
@@ -63,6 +64,12 @@ class WemapMetaRouter {
63
64
  const start = waypoints[0];
64
65
  const end = waypoints[1];
65
66
 
67
+ const routerResponse = new RouterResponse();
68
+ routerResponse.routerName = this.rname;
69
+ routerResponse.from = start;
70
+ routerResponse.to = end;
71
+
72
+
66
73
  // Avoid cycles on remoteRouters
67
74
  const remoteRouters = options.remoteRouters.filter(
68
75
  ({ name }) => name !== WemapMetaRemoteRouterOptions.rname
@@ -101,7 +108,15 @@ class WemapMetaRouter {
101
108
  * 3 - intersection of this.maps and options.targetMaps is empty
102
109
  */
103
110
  if (!ioMapsToTest.length) {
104
- return RemoteRouterManager.getItinerariesWithFallback(remoteRouters, mode, waypoints);
111
+ try {
112
+ return await RemoteRouterManager.getItinerariesWithFallback(remoteRouters, mode, waypoints);
113
+ } catch (e) {
114
+ if (!isRoutingError(e)) {
115
+ throw e;
116
+ }
117
+ routerResponse.error = e.message;
118
+ return routerResponse;
119
+ }
105
120
  }
106
121
 
107
122
 
@@ -114,10 +129,8 @@ class WemapMetaRouter {
114
129
  *
115
130
  */
116
131
 
117
- const routerResponse = new RouterResponse();
118
- routerResponse.from = start;
119
- routerResponse.to = end;
120
-
132
+ /** @type {Itinerary} */
133
+ let ioMapItinerary;
121
134
 
122
135
  // Find the first map where the "start" is inside.
123
136
  const mapWithStart = ioMapsToTest.find(map => map.isPointInside(start));
@@ -134,9 +147,17 @@ class WemapMetaRouter {
134
147
  */
135
148
  if (mapWithStart && mapWithStart.isPointInside(end)) {
136
149
 
137
- const itinerary = mapWithStart.getItineraryInsideMap(start, end, wemapRouterOptions);
150
+ try {
151
+ ioMapItinerary = mapWithStart.getItineraryInsideMap(start, end, wemapRouterOptions);
152
+ } catch (e) {
153
+ if (!isRoutingError(e)) {
154
+ throw e;
155
+ }
156
+ routerResponse.error = `${e.message} - on map ${mapWithStart.name}.`;
157
+ return routerResponse;
158
+ }
138
159
 
139
- routerResponse.itineraries.push(itinerary);
160
+ routerResponse.itineraries.push(ioMapItinerary);
140
161
  routerResponse.routerName = [this.rname, WemapRouter.rname];
141
162
 
142
163
  return routerResponse;
@@ -146,21 +167,27 @@ class WemapMetaRouter {
146
167
  // Note: At this step, mapWithEnd is necessarily different from mapWithStart
147
168
  const mapWithEnd = ioMapsToTest.find(map => map.isPointInside(end));
148
169
 
170
+
171
+ /** @type {RouterResponse} */
172
+ let remoteRouterResponse;
173
+
149
174
  /*
150
175
  * Case 2
151
176
  *
152
177
  * If no io map have been found for "start" and "end", therefore use remote router.
153
178
  */
154
179
  if (!mapWithStart && !mapWithEnd) {
155
- return RemoteRouterManager.getItinerariesWithFallback(remoteRouters, mode, waypoints);
180
+ try {
181
+ return await RemoteRouterManager.getItinerariesWithFallback(remoteRouters, mode, waypoints);
182
+ } catch (e) {
183
+ if (!isRoutingError(e)) {
184
+ throw e;
185
+ }
186
+ routerResponse.error = e.message;
187
+ return routerResponse;
188
+ }
156
189
  }
157
190
 
158
- /** @type {RouterResponse} */
159
- let remoteRouterResponse;
160
-
161
- /** @type {Itinerary} */
162
- let ioMapItinerary;
163
-
164
191
  /**
165
192
  * Case 3
166
193
  *
@@ -184,23 +211,21 @@ class WemapMetaRouter {
184
211
 
185
212
  try {
186
213
  ioMapItinerary = mapWithStart.getBestItineraryFromStartToEntryPoints(start, end, wemapRouterOptions);
214
+ remoteRouterResponse = await RemoteRouterManager.getItinerariesWithFallback(
215
+ remoteRouters, mode, [ioMapItinerary.to, end]
216
+ );
217
+ if (!remoteRouterResponse.itineraries.length) {
218
+ throw new NoRouteFoundError(ioMapItinerary.to, end, remoteRouterResponse.error);
219
+ }
187
220
  } catch (e) {
188
- if (!(e instanceof NoRouteFoundError)) {
221
+ if (!isRoutingError(e)) {
189
222
  throw e;
190
223
  }
191
- routerResponse.error = `${e.message} - on map ${mapWithStart.name}.`;
192
- return routerResponse;
193
- }
194
- remoteRouterResponse = await RemoteRouterManager.getItinerariesWithFallback(
195
- remoteRouters, mode, [ioMapItinerary.to, end]
196
- );
197
-
198
-
199
- if (!remoteRouterResponse.itineraries.length) {
200
- routerResponse.error = `Tried to calculate an itinerary from "start"
201
- to "entrypoints" using wemap router on local map "${mapWithStart.name}" and
202
- an itinerary from "entrypoints" to "end" using remote routers
203
- (${remoteRouters.map(r => r.name).join(', ')}), but failed.`;
224
+ routerResponse.error = 'Tried to calculate an itinerary from "start" '
225
+ + `to "entrypoints" using wemap router on local map "${mapWithStart.name}" and `
226
+ + 'an itinerary from "entrypoints" to "end" using remote routers '
227
+ + `(${remoteRouters.map(r => r.name).join(', ')}), but failed. `
228
+ + `Details: ${e.message}.`;
204
229
  return routerResponse;
205
230
  }
206
231
 
@@ -240,22 +265,21 @@ class WemapMetaRouter {
240
265
  */
241
266
  try {
242
267
  ioMapItinerary = mapWithEnd.getBestItineraryFromEntryPointsToEnd(start, end, wemapRouterOptions);
268
+ remoteRouterResponse = await RemoteRouterManager.getItinerariesWithFallback(
269
+ remoteRouters, mode, [start, ioMapItinerary.from]
270
+ );
271
+ if (!remoteRouterResponse.itineraries.length) {
272
+ throw new NoRouteFoundError(start, ioMapItinerary.from, remoteRouterResponse.error);
273
+ }
243
274
  } catch (e) {
244
- if (!(e instanceof NoRouteFoundError)) {
275
+ if (!isRoutingError(e)) {
245
276
  throw e;
246
277
  }
247
- routerResponse.error = `${e.message} - on map ${mapWithEnd.name}.`;
248
- return routerResponse;
249
- }
250
- remoteRouterResponse = await RemoteRouterManager.getItinerariesWithFallback(
251
- remoteRouters, mode, [start, ioMapItinerary.from]
252
- );
253
-
254
- if (!remoteRouterResponse.itineraries.length) {
255
- routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints"
256
- using remote routers (${remoteRouters.map(r => r.name).join(', ')}) and an
257
- itinerary from "entrypoints" to "end" using wemap router on local map
258
- "${mapWithEnd.name}", but failed.`;
278
+ routerResponse.error = 'Tried to calculate an itinerary from "start" to "entrypoints" '
279
+ + `using remote routers (${remoteRouters.map(r => r.name).join(', ')}) and an `
280
+ + 'itinerary from "entrypoints" to "end" using wemap router on local map '
281
+ + `"${mapWithEnd.name}", but failed. `
282
+ + `Details: ${e.message}.`;
259
283
  return routerResponse;
260
284
  }
261
285
 
@@ -298,32 +322,23 @@ class WemapMetaRouter {
298
322
  let ioMapItinerary1, ioMapItinerary2;
299
323
  try {
300
324
  ioMapItinerary1 = mapWithStart.getBestItineraryFromStartToEntryPoints(start, end, wemapRouterOptions);
301
- } catch (e) {
302
- if (!(e instanceof NoRouteFoundError)) {
303
- throw e;
304
- }
305
- routerResponse.error = `${e.message} - on map ${mapWithStart.name}.`;
306
- return routerResponse;
307
- }
308
- try {
309
325
  ioMapItinerary2 = mapWithEnd.getBestItineraryFromEntryPointsToEnd(start, end, wemapRouterOptions);
326
+ remoteRouterResponse = await RemoteRouterManager.getItinerariesWithFallback(
327
+ remoteRouters, mode, [ioMapItinerary1.to, ioMapItinerary2.from]
328
+ );
329
+ if (!remoteRouterResponse.itineraries.length) {
330
+ throw new NoRouteFoundError(ioMapItinerary1.to, ioMapItinerary2.from, remoteRouterResponse.error);
331
+ }
310
332
  } catch (e) {
311
- if (!(e instanceof NoRouteFoundError)) {
333
+ if (!isRoutingError(e)) {
312
334
  throw e;
313
335
  }
314
- routerResponse.error = `${e.message} - on map ${mapWithEnd.name}.`;
315
- return routerResponse;
316
- }
317
- remoteRouterResponse = await RemoteRouterManager.getItinerariesWithFallback(
318
- remoteRouters, mode, [ioMapItinerary1.to, ioMapItinerary2.from]
319
- );
320
-
321
- if (!remoteRouterResponse.itineraries.length) {
322
- routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints1"
323
- using wemap router on local map "${mapWithStart.name}", an itinerary from
324
- "entrypoints1" to "entrypoints2" using remote routers
325
- (${remoteRouters.map(r => r.name).join(', ')}) and an itinerary from "entrypoints2"
326
- to "end" using wemap router on local map "${mapWithEnd.name}", but failed.`;
336
+ routerResponse.error = 'Tried to calculate an itinerary from "start" to "entrypoints1" '
337
+ + `using wemap router on local map "${mapWithStart.name}", an itinerary from `
338
+ + '"entrypoints1" to "entrypoints2" using remote routers '
339
+ + `(${remoteRouters.map(r => r.name).join(', ')}) and an itinerary from "entrypoints2" `
340
+ + `to "end" using wemap router on local map "${mapWithEnd.name}", but failed. `
341
+ + `Details: ${e.message}.`;
327
342
  return routerResponse;
328
343
  }
329
344