@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
@@ -0,0 +1,78 @@
1
+ import chai from 'chai';
2
+
3
+ import LevelChange from './LevelChange.js';
4
+ import checkLevelChangeType from './LevelChange.type.spec.js';
5
+
6
+ const { expect } = chai;
7
+
8
+ const levelChange1 = new LevelChange();
9
+ levelChange1.direction = 'up';
10
+ levelChange1.difference = 1;
11
+ levelChange1.type = 'stairs';
12
+
13
+ const levelChange2 = new LevelChange();
14
+ levelChange2.direction = 'down';
15
+ levelChange2.difference = -1;
16
+ levelChange2.type = 'elevator';
17
+
18
+ const levelChange3 = new LevelChange();
19
+ levelChange3.direction = 'up';
20
+ levelChange3.difference = 3;
21
+ levelChange3.type = 'conveyor';
22
+
23
+ const levelChange4 = new LevelChange();
24
+ levelChange4.direction = 'up';
25
+ levelChange4.difference = 1;
26
+
27
+ const levelChange5 = new LevelChange();
28
+ levelChange5.direction = 'up';
29
+ levelChange5.difference = 1;
30
+
31
+ describe('LevelChange', () => {
32
+
33
+ it('checkTypes', () => {
34
+ checkLevelChangeType(levelChange1);
35
+ checkLevelChangeType(levelChange2);
36
+ checkLevelChangeType(levelChange3);
37
+ checkLevelChangeType(levelChange4);
38
+ checkLevelChangeType(levelChange5);
39
+ });
40
+
41
+ it('equals', () => {
42
+ expect(levelChange1.equalsTo(levelChange1)).is.true;
43
+ expect(levelChange2.equalsTo(levelChange2)).is.true;
44
+ expect(levelChange3.equalsTo(levelChange3)).is.true;
45
+ expect(levelChange4.equalsTo(levelChange4)).is.true;
46
+ expect(levelChange4.equalsTo(levelChange5)).is.true;
47
+ expect(levelChange1.equalsTo(levelChange2)).is.false;
48
+ expect(levelChange1.equalsTo(levelChange3)).is.false;
49
+ expect(levelChange1.equalsTo(levelChange4)).is.false;
50
+ });
51
+
52
+ it('from / to JSON', () => {
53
+
54
+ const levelChange1Json = levelChange1.toJson();
55
+ expect(levelChange1Json).be.an('object');
56
+ const levelChange1Bis = LevelChange.fromJson(levelChange1Json);
57
+ expect(levelChange1.equalsTo(levelChange1Bis)).is.true;
58
+
59
+ const levelChange2Json = levelChange2.toJson();
60
+ expect(levelChange2Json).be.an('object');
61
+ const levelChange2Bis = LevelChange.fromJson(levelChange2Json);
62
+ expect(levelChange2.equalsTo(levelChange2Bis)).is.true;
63
+
64
+ const levelChange3Json = levelChange3.toJson();
65
+ expect(levelChange3Json).be.an('object');
66
+ const levelChange3Bis = LevelChange.fromJson(levelChange3Json);
67
+ expect(levelChange3.equalsTo(levelChange3Bis)).is.true;
68
+
69
+ const levelChange4Json = levelChange4.toJson();
70
+ expect(levelChange4Json).be.an('object');
71
+ const levelChange4Bis = LevelChange.fromJson(levelChange4Json);
72
+ expect(levelChange4.equalsTo(levelChange4Bis)).is.true;
73
+
74
+ });
75
+
76
+ });
77
+
78
+ export { levelChange1, levelChange2, levelChange3, levelChange4 };
@@ -0,0 +1,26 @@
1
+ import chai from 'chai';
2
+
3
+ import LevelChange from './LevelChange.js';
4
+
5
+ const { expect } = chai;
6
+
7
+ const isNullOrString = val => val === null || typeof val === 'string';
8
+
9
+ /**
10
+ * @param {LevelChange} levelChange
11
+ */
12
+ export default function checkLevelChangeType(levelChange) {
13
+
14
+ expect(levelChange).instanceOf(LevelChange);
15
+
16
+ const { direction, difference, type } = levelChange;
17
+
18
+ expect(direction).satisfies(str => ['up', 'down'].includes(str));
19
+ expect(difference).be.a('number');
20
+ expect(difference !== 0).is.true;
21
+ expect(difference < 0 ? direction === 'down' : direction === 'up').is.true;
22
+ expect(type).satisfies(isNullOrString);
23
+ if (type) {
24
+ expect(type).satisfies(str => ['elevator', 'conveyor', 'stairs'].includes(str));
25
+ }
26
+ }
@@ -1,9 +1,10 @@
1
1
  import { Coordinates } from '@wemap/geo';
2
2
 
3
3
  import Itinerary from './Itinerary.js';
4
+
4
5
  class RouterResponse {
5
6
 
6
- /** @type {!string} */
7
+ /** @type {!string|Array<string>} */
7
8
  routerName;
8
9
 
9
10
  /** @type {!Coordinates} */
@@ -14,6 +15,74 @@ class RouterResponse {
14
15
 
15
16
  /** @type {!(Itinerary[])} */
16
17
  itineraries = [];
18
+
19
+ /** @type {?object} */
20
+ error = null;
21
+
22
+ /**
23
+ * @param {RouterResponse} obj1
24
+ * @param {RouterResponse} obj2
25
+ * @returns {Boolean}
26
+ */
27
+ static equalsTo(obj1, obj2) {
28
+ const intermediate = obj1.routerName === obj2.routerName
29
+ && obj1.from.equalsTo(obj2.from)
30
+ && obj1.to.equalsTo(obj2.to)
31
+ && obj1.itineraries.length === obj2.itineraries.length;
32
+
33
+ if (!intermediate) {
34
+ return false;
35
+ }
36
+
37
+ for (let i = 0; i < obj1.itineraries.length; i++) {
38
+ if (!obj1.itineraries[i].equalsTo(obj2.itineraries[i])) {
39
+ return false;
40
+ }
41
+ }
42
+
43
+ return true;
44
+ }
45
+
46
+ /**
47
+ * @param {RouterResponse} obj
48
+ * @returns {Boolean}
49
+ */
50
+ equalsTo(obj) {
51
+ return RouterResponse.equalsTo(this, obj);
52
+ }
53
+
54
+
55
+ /**
56
+ * @returns {object}
57
+ */
58
+ toJson() {
59
+ const json = {
60
+ routerName: this.routerName,
61
+ from: this.from.toCompressedJson(),
62
+ to: this.to.toCompressedJson(),
63
+ itineraries: this.itineraries.map(itinerary => itinerary.toJson())
64
+ };
65
+ if (this.error) {
66
+ json.error = this.error;
67
+ }
68
+ return json;
69
+ }
70
+
71
+ /**
72
+ * @param {object} json
73
+ * @returns {RouterResponse}
74
+ */
75
+ static fromJson(json) {
76
+ const routerResponse = new RouterResponse();
77
+ routerResponse.routerName = json.routerName;
78
+ routerResponse.from = Coordinates.fromCompressedJson(json.from);
79
+ routerResponse.to = Coordinates.fromCompressedJson(json.to);
80
+ routerResponse.itineraries = json.itineraries.map(Itinerary.fromJson);
81
+ if (json.error) {
82
+ routerResponse.error = json.error;
83
+ }
84
+ return routerResponse;
85
+ }
17
86
  }
18
87
 
19
88
  export default RouterResponse;
@@ -0,0 +1,85 @@
1
+ /* eslint-disable max-statements */
2
+ import chai from 'chai';
3
+
4
+ import { Coordinates } from '@wemap/geo';
5
+
6
+ import RouterResponse from './RouterResponse.js';
7
+ import checkRouterResponseType from './RouterResponse.type.spec.js';
8
+ import { itinerary1, itinerary2, itinerary3, itinerary4 } from './Itinerary.spec.js';
9
+
10
+ const { expect } = chai;
11
+
12
+ const routerResponse1 = new RouterResponse();
13
+ routerResponse1.routerName = 'foo1';
14
+ routerResponse1.from = new Coordinates(0, 0);
15
+ routerResponse1.to = new Coordinates(1, 0);
16
+ routerResponse1.itineraries = [itinerary1];
17
+
18
+ const routerResponse2 = new RouterResponse();
19
+ routerResponse2.routerName = 'foo2';
20
+ routerResponse2.from = new Coordinates(0, 0);
21
+ routerResponse2.to = new Coordinates(1, 0);
22
+ routerResponse2.itineraries = [itinerary1, itinerary2];
23
+
24
+ const routerResponse3 = new RouterResponse();
25
+ routerResponse3.routerName = 'foo3';
26
+ routerResponse3.from = new Coordinates(0, 0);
27
+ routerResponse3.to = new Coordinates(2, 0);
28
+ routerResponse3.itineraries = [itinerary1, itinerary2, itinerary3, itinerary4];
29
+
30
+ const routerResponse4 = new RouterResponse();
31
+ routerResponse4.routerName = 'foo4';
32
+ routerResponse4.from = new Coordinates(1, 0);
33
+ routerResponse4.to = new Coordinates(4, 0);
34
+ routerResponse4.itineraries = [itinerary1];
35
+
36
+ const routerResponse5 = new RouterResponse();
37
+ Object.assign(routerResponse5, routerResponse4);
38
+
39
+ describe('RouterResponse', () => {
40
+
41
+ it('checkTypes', () => {
42
+ checkRouterResponseType(routerResponse1);
43
+ checkRouterResponseType(routerResponse2);
44
+ checkRouterResponseType(routerResponse3);
45
+ checkRouterResponseType(routerResponse4);
46
+ });
47
+
48
+ it('equals', () => {
49
+ expect(routerResponse1.equalsTo(routerResponse1)).is.true;
50
+ expect(routerResponse2.equalsTo(routerResponse2)).is.true;
51
+ expect(routerResponse3.equalsTo(routerResponse3)).is.true;
52
+ expect(routerResponse4.equalsTo(routerResponse4)).is.true;
53
+ expect(routerResponse4.equalsTo(routerResponse5)).is.true;
54
+ expect(routerResponse1.equalsTo(routerResponse2)).is.false;
55
+ expect(routerResponse1.equalsTo(routerResponse3)).is.false;
56
+ expect(routerResponse1.equalsTo(routerResponse4)).is.false;
57
+ });
58
+
59
+ it('from / to JSON', () => {
60
+
61
+ const routerResponse1Json = routerResponse1.toJson();
62
+ expect(routerResponse1Json).be.an('object');
63
+ const routerResponse1Bis = RouterResponse.fromJson(routerResponse1Json);
64
+ expect(routerResponse1.equalsTo(routerResponse1Bis)).is.true;
65
+
66
+ const routerResponse2Json = routerResponse2.toJson();
67
+ expect(routerResponse2Json).be.an('object');
68
+ const routerResponse2Bis = RouterResponse.fromJson(routerResponse2Json);
69
+ expect(routerResponse2.equalsTo(routerResponse2Bis)).is.true;
70
+
71
+ const routerResponse3Json = routerResponse3.toJson();
72
+ expect(routerResponse3Json).be.an('object');
73
+ const routerResponse3Bis = RouterResponse.fromJson(routerResponse3Json);
74
+ expect(routerResponse3.equalsTo(routerResponse3Bis)).is.true;
75
+
76
+ const routerResponse4Json = routerResponse4.toJson();
77
+ expect(routerResponse4Json).be.an('object');
78
+ const routerResponse4Bis = RouterResponse.fromJson(routerResponse4Json);
79
+ expect(routerResponse4.equalsTo(routerResponse4Bis)).is.true;
80
+
81
+ });
82
+
83
+ });
84
+
85
+ export { routerResponse1, routerResponse2, routerResponse3, routerResponse4 };
@@ -4,21 +4,24 @@ import { Coordinates } from '@wemap/geo';
4
4
 
5
5
  import RouterResponse from './RouterResponse.js';
6
6
 
7
- import { verifyItineraryData } from './Itinerary.type.spec.js';
7
+ import checkItineraryType from './Itinerary.type.spec.js';
8
8
 
9
9
  const { expect } = chai;
10
10
 
11
11
  /**
12
12
  * @param {RouterResponse} routerResponse
13
13
  */
14
- export function verifyRouterResponseData(routerResponse) {
14
+ export default function checkRouterResponseType(routerResponse) {
15
15
 
16
16
  expect(routerResponse).instanceOf(RouterResponse);
17
- expect(routerResponse.routerName).be.a('string');
17
+ expect(routerResponse.routerName).satisfy(val => {
18
+ return typeof val === 'string'
19
+ || Array.isArray(val) && val.every(val2 => typeof val2 === 'string');
20
+ });
18
21
  expect(routerResponse.from).instanceOf(Coordinates);
19
22
  expect(routerResponse.to).instanceOf(Coordinates);
20
23
  expect(routerResponse.itineraries).be.an('array');
21
- routerResponse.itineraries.forEach(verifyItineraryData);
24
+ routerResponse.itineraries.forEach(checkItineraryType);
22
25
 
23
26
  }
24
27
 
package/src/model/Step.js CHANGED
@@ -46,6 +46,45 @@ class Step {
46
46
  /** @type {!number} */
47
47
  _idCoordsInLeg = null;
48
48
 
49
+ /**
50
+ * @param {Step} obj1
51
+ * @param {Step} obj2
52
+ * @returns {Boolean}
53
+ */
54
+ static equalsTo(obj1, obj2) {
55
+ return obj1.firstStep === obj2.firstStep
56
+ && obj1.lastStep === obj2.lastStep
57
+ && obj1.number === obj2.number
58
+ && obj1.coords.equalsTo(obj2.coords)
59
+ && obj1.angle === obj2.angle
60
+ && obj1.previousBearing === obj2.previousBearing
61
+ && obj1.nextBearing === obj2.nextBearing
62
+ && obj1.distance === obj2.distance
63
+ && obj1.duration === obj2.duration
64
+ && obj1.name === obj2.name
65
+ && (
66
+ obj1.levelChange === obj2.levelChange
67
+ || obj1.levelChange !== null && obj1.levelChange.equalsTo(obj2.levelChange)
68
+ )
69
+ && (
70
+ obj1.extras === obj2.extras
71
+ || (
72
+ obj1.extras !== null
73
+ && obj1.extras.subwayEntrance === obj2.extras.subwayEntrance
74
+ && obj1.extras.subwayEntranceRef === obj2.extras.subwayEntranceRef
75
+ )
76
+ )
77
+ && obj1._idCoordsInLeg === obj2._idCoordsInLeg;
78
+ }
79
+
80
+ /**
81
+ * @param {Step} obj
82
+ * @returns {Boolean}
83
+ */
84
+ equalsTo(obj) {
85
+ return Step.equalsTo(this, obj);
86
+ }
87
+
49
88
  /**
50
89
  * @returns {object}
51
90
  */
@@ -93,22 +132,22 @@ class Step {
93
132
  step.nextBearing = json.nextBearing;
94
133
  step.distance = json.distance;
95
134
  step._idCoordsInLeg = json._idCoordsInLeg;
96
- if (json.firstStep) {
135
+ if (typeof json.firstStep === 'boolean') {
97
136
  step.firstStep = json.firstStep;
98
137
  }
99
- if (json.lastStep) {
138
+ if (typeof json.lastStep === 'boolean') {
100
139
  step.lastStep = json.lastStep;
101
140
  }
102
- if (json.duration) {
141
+ if (typeof json.duration === 'number') {
103
142
  step.duration = json.duration;
104
143
  }
105
- if (json.name) {
144
+ if (typeof json.name === 'string') {
106
145
  step.name = json.name;
107
146
  }
108
- if (json.levelChange) {
147
+ if (typeof json.levelChange === 'object') {
109
148
  step.levelChange = LevelChange.fromJson(json.levelChange);
110
149
  }
111
- if (json.extras) {
150
+ if (typeof json.extras === 'object') {
112
151
  step.extras = json.extras;
113
152
  }
114
153
  return step;
@@ -0,0 +1,100 @@
1
+ /* eslint-disable max-statements */
2
+ import { Coordinates } from '@wemap/geo';
3
+ import chai from 'chai';
4
+
5
+ import Step from './Step.js';
6
+ import checkStepType from './Step.type.spec.js';
7
+ import { levelChange1 } from './LevelChange.spec.js';
8
+
9
+ const { expect } = chai;
10
+
11
+ const step1 = new Step();
12
+ step1.firstStep = true;
13
+ step1.lastStep = false;
14
+ step1.number = 1;
15
+ step1.coords = new Coordinates(0, 0);
16
+ step1.angle = 0;
17
+ step1.previousBearing = 0;
18
+ step1.nextBearing = 0;
19
+ step1.distance = 10;
20
+ step1._idCoordsInLeg = 0;
21
+
22
+ const step2 = new Step();
23
+ Object.assign(step2, step1);
24
+ step2.firstStep = false;
25
+ step2.number = 2;
26
+ step2.coords = new Coordinates(1, 0);
27
+ step2.distance = step1.coords.distanceTo(step2.coords);
28
+ step2.extras = { subwayEntrance: true, subwayEntranceRef: 'toto' };
29
+ step2._idCoordsInLeg = 1;
30
+
31
+ const step3 = new Step();
32
+ Object.assign(step3, step2);
33
+ step3.number = 3;
34
+ step3.coords = new Coordinates(2, 0, null);
35
+ step3.distance = step2.coords.distanceTo(step3.coords);
36
+ step3.duration = step3.distance * 2;
37
+ step3.levelChange = levelChange1;
38
+ step3.extras = { subwayEntrance: false };
39
+ step3._idCoordsInLeg = 2;
40
+
41
+ const step4 = new Step();
42
+ Object.assign(step4, step3);
43
+ step4.lastStep = true;
44
+ step4.number = 4;
45
+ step4.coords = new Coordinates(3, 0);
46
+ step4.distance = step3.coords.distanceTo(step4.coords);
47
+ step4.name = 'end';
48
+ step4.extras = {};
49
+ step4._idCoordsInLeg = 3;
50
+
51
+ const step5 = new Step();
52
+ Object.assign(step5, step4);
53
+
54
+ describe('Step', () => {
55
+
56
+ it('checkTypes', () => {
57
+ checkStepType(step1);
58
+ checkStepType(step2);
59
+ checkStepType(step3);
60
+ checkStepType(step4);
61
+ });
62
+
63
+ it('equals', () => {
64
+ expect(step1.equalsTo(step1)).is.true;
65
+ expect(step2.equalsTo(step2)).is.true;
66
+ expect(step3.equalsTo(step3)).is.true;
67
+ expect(step4.equalsTo(step4)).is.true;
68
+ expect(step4.equalsTo(step5)).is.true;
69
+ expect(step1.equalsTo(step2)).is.false;
70
+ expect(step1.equalsTo(step3)).is.false;
71
+ expect(step1.equalsTo(step4)).is.false;
72
+ });
73
+
74
+ it('from / to JSON', () => {
75
+
76
+ const step1Json = step1.toJson();
77
+ expect(step1Json).be.an('object');
78
+ const step1Bis = Step.fromJson(step1Json);
79
+ expect(step1.equalsTo(step1Bis)).is.true;
80
+
81
+ const step2Json = step2.toJson();
82
+ expect(step2Json).be.an('object');
83
+ const step2Bis = Step.fromJson(step2Json);
84
+ expect(step2.equalsTo(step2Bis)).is.true;
85
+
86
+ const step3Json = step3.toJson();
87
+ expect(step3Json).be.an('object');
88
+ const step3Bis = Step.fromJson(step3Json);
89
+ expect(step3.equalsTo(step3Bis)).is.true;
90
+
91
+ const step4Json = step4.toJson();
92
+ expect(step4Json).be.an('object');
93
+ const step4Bis = Step.fromJson(step4Json);
94
+ expect(step4.equalsTo(step4Bis)).is.true;
95
+
96
+ });
97
+
98
+ });
99
+
100
+ export { step1, step2, step3, step4 };
@@ -0,0 +1,52 @@
1
+ import chai from 'chai';
2
+
3
+ import { Coordinates } from '@wemap/geo';
4
+
5
+ import LevelChange from './LevelChange.js';
6
+ import Step from './Step.js';
7
+ import checkLevelChangeType from './LevelChange.type.spec.js';
8
+
9
+ const { expect } = chai;
10
+
11
+
12
+ const isNullOrNumber = val => val === null || typeof val === 'number';
13
+ const isNullOrString = val => val === null || typeof val === 'string';
14
+ const isNullOrObject = val => val === null || typeof val === 'object';
15
+ const isNullOrLevelChange = val => val === null || val instanceof LevelChange;
16
+
17
+ const isUndefinedOrBoolean = val => typeof val === 'undefined' || typeof val === 'boolean';
18
+ const isUndefinedOrString = val => typeof val === 'undefined' || typeof val === 'string';
19
+
20
+ const stepExtraProperties = ['subwayEntrance', 'subwayEntranceRef'];
21
+
22
+ /**
23
+ * @param {Step} step
24
+ */
25
+ export default function checkStepType(step) {
26
+
27
+ expect(step).instanceOf(Step);
28
+ expect(step.firstStep).be.a('boolean');
29
+ expect(step.lastStep).be.a('boolean');
30
+ expect(step.number).be.a('number');
31
+ expect(step.coords).instanceOf(Coordinates);
32
+ expect(step.angle).be.a('number');
33
+ expect(step.previousBearing).be.a('number');
34
+ expect(step.nextBearing).be.a('number');
35
+ expect(step.distance).be.a('number');
36
+ expect(step.duration).satisfies(isNullOrNumber);
37
+ expect(step.name).satisfies(isNullOrString);
38
+ expect(step.levelChange).satisfies(isNullOrLevelChange);
39
+ if (step.levelChange) {
40
+ checkLevelChangeType(step.levelChange);
41
+ }
42
+ expect(step._idCoordsInLeg).be.a('number');
43
+
44
+ expect(step.extras).satisfies(isNullOrObject);
45
+ if (step.extras !== null) {
46
+ for (const key of Object.keys(step.extras)) {
47
+ expect(stepExtraProperties).includes(key);
48
+ }
49
+ expect(step.extras.subwayEntrance).satisfies(isUndefinedOrBoolean);
50
+ expect(step.extras.subwayEntranceRef).satisfies(isUndefinedOrString);
51
+ }
52
+ }
@@ -0,0 +1,31 @@
1
+ import { Coordinates } from '@wemap/geo';
2
+
3
+ import RouterResponse from '../model/RouterResponse.js';
4
+ import RemoteRouterOptions from './RemoteRouterOptions.js';
5
+
6
+ class RemoteRouter {
7
+
8
+ /**
9
+ * Get the router name
10
+ * @type {string} the router name
11
+ */
12
+ get rname() {
13
+ return 'Unknown';
14
+ }
15
+
16
+ /**
17
+ * @abstract
18
+ * @param {string} endpointUrl
19
+ * @param {string} mode see Constants.ROUTING_MODE
20
+ * @param {Array<Coordinates>} waypoints
21
+ * @param {RemoteRouterOptions} options
22
+ * @returns {!RouterResponse}
23
+ */
24
+ // eslint-disable-next-line no-unused-vars
25
+ async getItineraries(endpointUrl, mode, waypoints, options = new RemoteRouterOptions()) {
26
+ throw new Error('RemoteRouter "' + this.rname + '" does not @override getItineraries()');
27
+ }
28
+
29
+ }
30
+
31
+ export default RemoteRouter;
@@ -0,0 +1,84 @@
1
+ import { Coordinates } from '@wemap/geo';
2
+
3
+ import RouterResponse from '../model/RouterResponse.js';
4
+ import RemoteRouter from './RemoteRouter.js';
5
+ import CitywayRemoteRouter from './cityway/CitywayRemoteRouter.js';
6
+ import DeutscheBahnRemoteRouter from './deutsche-bahn/DeutscheBahnRemoteRouter.js';
7
+ import IdfmRemoteRouter from './idfm/IdfmRemoteRouter.js';
8
+ import OsrmRemoteRouter from './osrm/OsrmRemoteRouter.js';
9
+ import OtpRemoteRouter from './otp/OtpRemoteRouter.js';
10
+ import RemoteRouterOptions from './RemoteRouterOptions.js';
11
+ import RemoteRouterServerUnreachable from './RemoteRouterServerUnreachable.js';
12
+ import RoutingModeCorrespondanceNotFound from './RoutingModeCorrespondanceNotFound.js';
13
+ import IdfmRemoteRouterTokenError from './idfm/IdfmRemoteRouterTokenError.js';
14
+
15
+ /**
16
+ * Singleton
17
+ */
18
+ class RemoteRouterManager {
19
+
20
+ /** @type {RemoteRouter[]} */
21
+ remoteRouters = [
22
+ CitywayRemoteRouter,
23
+ DeutscheBahnRemoteRouter,
24
+ IdfmRemoteRouter,
25
+ OsrmRemoteRouter,
26
+ OtpRemoteRouter
27
+ ];
28
+
29
+ /**
30
+ * @param {string} name
31
+ * @returns {RemoteRouter}
32
+ */
33
+ getRouterByName(name) {
34
+ return this.remoteRouters.find(remoteRouter => remoteRouter.rname === name);
35
+ }
36
+
37
+ /**
38
+ * @param {!string} endpointUrl
39
+ * @param {!string} mode see Constants.ROUTING_MODE
40
+ * @param {Array<Coordinates>} waypoints
41
+ * @param {?RemoteRouterOptions} options
42
+ * @returns {!RouterResponse}
43
+ * @throws {RemoteRouterServerUnreachable}
44
+ * @throws {RoutingModeCorrespondanceNotFound}
45
+ * @throws {IdfmRemoteRouterTokenError}
46
+ */
47
+ async getItineraries(name, endpointUrl, mode, waypoints, options = new RemoteRouterOptions()) {
48
+ const router = this.getRouterByName(name);
49
+ if (!router) {
50
+ throw new Error(`Unknown "${this.rname}" remote router`);
51
+ }
52
+ return router.getItineraries(endpointUrl, mode, waypoints, options);
53
+ }
54
+
55
+
56
+ /**
57
+ * @param {!{name: string, endpointUrl: string}[]} remoteRouters
58
+ * @param {!string} mode see Constants.ROUTING_MODE
59
+ * @param {!Array<Coordinates>} waypoints
60
+ * @param {?RemoteRouterOptions} options
61
+ * @returns {!RouterResponse}
62
+ * @throws {RemoteRouterServerUnreachable}
63
+ * @throws {RoutingModeCorrespondanceNotFound}
64
+ * @throws {IdfmRemoteRouterTokenError}
65
+ */
66
+ async getItinerariesWithFallback(remoteRouters, mode, waypoints, options = new RemoteRouterOptions()) {
67
+ let routerResponse;
68
+ for (const { name, endpointUrl } of remoteRouters) {
69
+ routerResponse = await this.getItineraries(name, endpointUrl, mode, waypoints, options);
70
+ if (routerResponse.itineraries.length) {
71
+ return routerResponse;
72
+ }
73
+ }
74
+ if (!routerResponse) {
75
+ routerResponse = new RouterResponse();
76
+ routerResponse.from = waypoints[0];
77
+ routerResponse.to = waypoints[waypoints.length];
78
+ }
79
+ return routerResponse;
80
+ }
81
+
82
+ }
83
+
84
+ export default new RemoteRouterManager();
@@ -0,0 +1,25 @@
1
+ class RemoteRouterOptions {
2
+
3
+ /** @type {boolean} */
4
+ useStairs = true;
5
+
6
+ /**
7
+ * @returns {object}
8
+ */
9
+ toJson() {
10
+ return { useStairs: this.useStairs };
11
+ }
12
+
13
+ /**
14
+ * @param {object}
15
+ * @returns {RemoteRouterOptions}
16
+ */
17
+ static fromJson(json) {
18
+ const obj = new RemoteRouterOptions();
19
+ obj.useStairs = json.useStairs;
20
+ return obj;
21
+ }
22
+
23
+ }
24
+
25
+ export default RemoteRouterOptions;
@@ -0,0 +1,10 @@
1
+ export default class RemoteRouterServerUnreachable extends Error {
2
+
3
+ /**
4
+ * @param {!string} name
5
+ * @param {!string} endpointUrl
6
+ */
7
+ constructor(name, endpointUrl) {
8
+ super(`Remote router server ${name} is unreachable. URL: ${endpointUrl}`);
9
+ }
10
+ }