@wemap/routers 12.10.8 → 12.10.9
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/dist/helpers/InstructionManager.d.ts +20 -0
- package/dist/helpers/InstructionManagerV1.d.ts +7 -0
- package/{index.ts → dist/index.d.ts} +1 -11
- package/dist/index.js +1 -5099
- package/dist/index.js.map +1 -1
- package/dist/src/ItineraryInfoManager.d.ts +31 -0
- package/dist/src/RoutingError.d.ts +24 -0
- package/{src/StatusCode.ts → dist/src/StatusCode.d.ts} +2 -3
- package/dist/src/Utils.d.ts +6 -0
- package/dist/src/graph/Edge.d.ts +32 -0
- package/dist/src/graph/Graph.d.ts +40 -0
- package/dist/src/graph/GraphProjection.d.ts +11 -0
- package/dist/src/graph/GraphProjectionOptions.d.ts +7 -0
- package/dist/src/graph/GraphRoute.d.ts +19 -0
- package/dist/src/graph/GraphRouter.d.ts +20 -0
- package/dist/src/graph/GraphRouterEngine.d.ts +77 -0
- package/{src/graph/GraphRouterOptions.ts → dist/src/graph/GraphRouterOptions.d.ts} +5 -7
- package/dist/src/graph/GraphRouterOptionsBuilder.d.ts +20 -0
- package/dist/src/graph/NoRouteFoundError.d.ts +12 -0
- package/dist/src/graph/Vertex.d.ts +19 -0
- package/dist/src/model/Itinerary.d.ts +81 -0
- package/dist/src/model/Leg.d.ts +66 -0
- package/dist/src/model/LevelChange.d.ts +7 -0
- package/dist/src/model/RouterRequest.d.ts +40 -0
- package/dist/src/model/Step.d.ts +42 -0
- package/dist/src/model/StepExtra.d.ts +3 -0
- package/dist/src/model/StepsBuilder.d.ts +16 -0
- package/dist/src/model/TransitMode.d.ts +5 -0
- package/{src/model/TravelMode.ts → dist/src/model/TravelMode.d.ts} +1 -2
- package/dist/src/model/generateSteps.d.ts +0 -0
- package/{src/remote/RemoteRouter.ts → dist/src/remote/RemoteRouter.d.ts} +2 -7
- package/dist/src/remote/RemoteRouterManager.d.ts +731 -0
- package/dist/src/remote/RemoteRouterUtils.d.ts +6 -0
- package/dist/src/remote/cityway/CitywayRemoteRouter.d.ts +109 -0
- package/dist/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.d.ts +31 -0
- package/dist/src/remote/geovelo/GeoveloRemoteRouter.d.ts +106 -0
- package/dist/src/remote/idfm/IdfmRemoteRouter.d.ts +123 -0
- package/dist/src/remote/navitia/NavitiaRemoteRouter.d.ts +34 -0
- package/dist/src/remote/navitia/types.d.ts +87 -0
- package/dist/src/remote/osrm/OsrmRemoteRouter.d.ts +70 -0
- package/dist/src/remote/otp/OtpRemoteRouter.d.ts +69 -0
- package/dist/src/remote/wemap-multi/WemapMultiRemoteRouter.d.ts +19 -0
- package/dist/src/types.d.ts +31 -0
- package/dist/src/wemap-multi/CustomGraphMap.d.ts +56 -0
- package/dist/src/wemap-multi/CustomGraphMapTester.d.ts +39 -0
- package/dist/src/wemap-multi/WemapMultiRouter.d.ts +14 -0
- package/dist/src/wemap-osm/OsmGraphUtils.d.ts +11 -0
- package/dist/tests/CommonTest.d.ts +8 -0
- package/package.json +11 -8
- package/assets/biocbon-bergere-rdc-network.osm +0 -163
- package/assets/bureaux-wemap-montpellier-network.osm +0 -174
- package/assets/components.osm +0 -146
- package/assets/elevator-models-4.osm +0 -89
- package/assets/elevator-models.osm +0 -354
- package/assets/exit-graph.osm +0 -25
- package/assets/gare-de-lest-network-pp-bounds.osm +0 -1613
- package/assets/gare-de-lyon-extract.osm +0 -174
- package/assets/geovelo-montpellier.json +0 -1144
- package/assets/horizontal-elevator.osm +0 -12
- package/assets/itinerary-deutsche-bahn-1.json +0 -368
- package/assets/itinerary-grenoble-otp-1.json +0 -1536
- package/assets/itinerary-grenoble-otp-2.json +0 -1092
- package/assets/itinerary-info-two-points-proj.osm +0 -39
- package/assets/itinerary-info-two-points.osm +0 -24
- package/assets/itinerary-lehavre-cityway-1.json +0 -6799
- package/assets/itinerary-lehavre-cityway-2.json +0 -2133
- package/assets/itinerary-lehavre-cityway-3.json +0 -12577
- package/assets/itinerary-lehavre-cityway-4.json +0 -1451
- package/assets/itinerary-lehavre-cityway-5.json +0 -5925
- package/assets/itinerary-lemans-navitia.json +0 -7768
- package/assets/itinerary-montpellier-osrm-3.json +0 -185
- package/assets/itinerary-montpellier-outdoor-without-steps.json +0 -110
- package/assets/itinerary-montpellier-outdoor.json +0 -513
- package/assets/itinerary-paris-idfm-2.json +0 -1838
- package/assets/itinerary-paris-idfm.json +0 -27727
- package/assets/itinerary-step-not-on-path-osrm.json +0 -457
- package/assets/itinerary-with-duplicate-nodes.json +0 -110
- package/assets/network-conveying-backward.osm +0 -74
- package/assets/network-elevator.osm +0 -48
- package/assets/network-escalators.osm +0 -50
- package/assets/network-simple.osm +0 -27
- package/assets/network-steps-same-level.osm +0 -283
- package/assets/network-with-modifiers.osm +0 -39
- package/assets/one-way.osm +0 -46
- package/assets/report-map-1.osm +0 -36
- package/assets/report-map-2.osm +0 -29
- package/assets/report-map-3.osm +0 -15
- package/assets/rr-wemap-multi-indoor-outdoor-indoor.json +0 -1352
- package/assets/rr-wemap-multi-indoor-outdoor.json +0 -145
- package/assets/rr-wemap-multi-multi-level.json +0 -262
- package/assets/rr-wemap-multi-outdoor-indoor.json +0 -145
- package/assets/rr-wemap-multi-outdoor-outdoor.json +0 -207
- package/assets/rr-wemap-multi-remote-indoor-indoor.json +0 -155
- package/assets/rr-wemap-multi-remote-indoor-outdoor-indoor.json +0 -668
- package/assets/rr-wemap-multi-remote-indoor-outdoor.json +0 -154
- package/assets/rr-wemap-multi-remote-outdoor-indoor.json +0 -179
- package/assets/rr-wemap-multi-remote-outdoor-outdoor.json +0 -109
- package/assets/stairs-and-exit.osm +0 -47
- package/helpers/InstructionManager.ts +0 -184
- package/helpers/InstructionManagerV1.ts +0 -95
- package/src/ItineraryInfoManager.spec.ts +0 -183
- package/src/ItineraryInfoManager.ts +0 -181
- package/src/RoutingError.ts +0 -60
- package/src/Utils.ts +0 -8
- package/src/graph/Edge.spec.ts +0 -32
- package/src/graph/Edge.ts +0 -64
- package/src/graph/Graph.spec.ts +0 -509
- package/src/graph/Graph.ts +0 -272
- package/src/graph/GraphProjection.ts +0 -15
- package/src/graph/GraphProjectionOptions.ts +0 -8
- package/src/graph/GraphRoute.spec.ts +0 -15
- package/src/graph/GraphRoute.ts +0 -43
- package/src/graph/GraphRouter.spec.ts +0 -317
- package/src/graph/GraphRouter.ts +0 -229
- package/src/graph/GraphRouterEngine.ts +0 -248
- package/src/graph/GraphRouterOptionsBuilder.ts +0 -98
- package/src/graph/NoRouteFoundError.ts +0 -39
- package/src/graph/Vertex.spec.ts +0 -42
- package/src/graph/Vertex.ts +0 -45
- package/src/model/Itinerary.spec.ts +0 -134
- package/src/model/Itinerary.ts +0 -370
- package/src/model/Leg.spec.ts +0 -107
- package/src/model/Leg.ts +0 -224
- package/src/model/LevelChange.spec.ts +0 -50
- package/src/model/LevelChange.ts +0 -14
- package/src/model/RouterRequest.ts +0 -33
- package/src/model/Step.spec.ts +0 -99
- package/src/model/Step.ts +0 -90
- package/src/model/StepExtra.ts +0 -1
- package/src/model/StepsBuilder.ts +0 -242
- package/src/model/TransitMode.spec.ts +0 -31
- package/src/model/TransitMode.ts +0 -28
- package/src/model/generateSteps.ts +0 -102
- package/src/remote/RemoteRouterManager.spec.ts +0 -178
- package/src/remote/RemoteRouterManager.ts +0 -72
- package/src/remote/RemoteRouterUtils.ts +0 -25
- package/src/remote/cityway/CitywayRemoteRouter.spec.ts +0 -122
- package/src/remote/cityway/CitywayRemoteRouter.ts +0 -435
- package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.spec.ts +0 -52
- package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.ts +0 -85
- package/src/remote/geovelo/GeoveloRemoteRouter.spec.ts +0 -54
- package/src/remote/geovelo/GeoveloRemoteRouter.ts +0 -293
- package/src/remote/idfm/IdfmRemoteRouter.spec.ts +0 -102
- package/src/remote/idfm/IdfmRemoteRouter.ts +0 -523
- package/src/remote/navitia/NavitiaRemoteRouter.spec.ts +0 -116
- package/src/remote/navitia/NavitiaRemoteRouter.ts +0 -445
- package/src/remote/navitia/types.ts +0 -73
- package/src/remote/osrm/OsrmRemoteRouter.spec.ts +0 -127
- package/src/remote/osrm/OsrmRemoteRouter.ts +0 -303
- package/src/remote/otp/OtpRemoteRouter.spec.ts +0 -103
- package/src/remote/otp/OtpRemoteRouter.ts +0 -223
- package/src/remote/wemap-multi/WemapMultiRemoteRouter.spec.ts +0 -103
- package/src/remote/wemap-multi/WemapMultiRemoteRouter.ts +0 -56
- package/src/types.ts +0 -32
- package/src/wemap-multi/CustomGraphMap.spec.ts +0 -40
- package/src/wemap-multi/CustomGraphMap.ts +0 -213
- package/src/wemap-multi/CustomGraphMapTester.spec.ts +0 -48
- package/src/wemap-multi/CustomGraphMapTester.ts +0 -90
- package/src/wemap-multi/WemapMultiRouter.spec.ts +0 -138
- package/src/wemap-multi/WemapMultiRouter.ts +0 -329
- package/src/wemap-osm/OsmGraphUtils.spec.ts +0 -165
- package/src/wemap-osm/OsmGraphUtils.ts +0 -173
- package/src/wemap-osm/OsmRouter.elevators.spec.ts +0 -106
- package/src/wemap-osm/OsmRouter.spec.ts +0 -292
- package/tests/CommonTest.ts +0 -78
- package/tsconfig.json +0 -3
- package/vite.config.ts +0 -4
|
@@ -1,523 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import { Coordinates, Utils as GeoUtils } from '@wemap/geo';
|
|
3
|
-
import Logger from '@wemap/logger';
|
|
4
|
-
|
|
5
|
-
import Itinerary from '../../model/Itinerary.js';
|
|
6
|
-
import Leg, { TransportInfo } from '../../model/Leg.js';
|
|
7
|
-
import { dateWithTimeZone } from '../RemoteRouterUtils.js';
|
|
8
|
-
import StepsBuilder from '../../model/StepsBuilder.js';
|
|
9
|
-
import RemoteRouter from '../RemoteRouter.js';
|
|
10
|
-
import { areTransitAndTravelModeConsistent, type TransitMode } from '../../model/TransitMode.js';
|
|
11
|
-
import { type MinStepInfo } from '../../model/Step.js';
|
|
12
|
-
import { RouterRequest } from '../../model/RouterRequest.js';
|
|
13
|
-
import { RemoteRoutingError } from '../../RoutingError.js';
|
|
14
|
-
import GeoveloRemoteRouter from '../geovelo/GeoveloRemoteRouter.js';
|
|
15
|
-
|
|
16
|
-
type IdfmCoordinates = { lat: number | string, lon: number | string };
|
|
17
|
-
type IdfmPath = {
|
|
18
|
-
name: string,
|
|
19
|
-
length: number
|
|
20
|
-
} & ({ instruction_start_coordinate: IdfmCoordinates } | { via_uri: string });
|
|
21
|
-
|
|
22
|
-
type IdfmWaypoint = { name: string }
|
|
23
|
-
& (
|
|
24
|
-
{ stop_point: { coord: IdfmCoordinates } } |
|
|
25
|
-
{ address: { coord: IdfmCoordinates } } |
|
|
26
|
-
{ poi: { coord: IdfmCoordinates } }
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
type IdfmSection = {
|
|
30
|
-
id: string;
|
|
31
|
-
type: 'waiting' | 'transfer' | string,
|
|
32
|
-
mode: string,
|
|
33
|
-
departure_date_time: string,
|
|
34
|
-
arrival_date_time: string,
|
|
35
|
-
duration: number,
|
|
36
|
-
geojson: {
|
|
37
|
-
coordinates: [number, number][],
|
|
38
|
-
properties: { length: number }[]
|
|
39
|
-
},
|
|
40
|
-
path: IdfmPath[],
|
|
41
|
-
display_informations: {
|
|
42
|
-
code: string,
|
|
43
|
-
color: string,
|
|
44
|
-
text_color: string,
|
|
45
|
-
direction: string,
|
|
46
|
-
physical_mode: string
|
|
47
|
-
},
|
|
48
|
-
from: IdfmWaypoint,
|
|
49
|
-
to: IdfmWaypoint,
|
|
50
|
-
vias?: {
|
|
51
|
-
id: string;
|
|
52
|
-
name: string;
|
|
53
|
-
access_point: {
|
|
54
|
-
id: string;
|
|
55
|
-
name: string;
|
|
56
|
-
coord: {
|
|
57
|
-
lon: string;
|
|
58
|
-
lat: string;
|
|
59
|
-
},
|
|
60
|
-
embedded_type: string;
|
|
61
|
-
},
|
|
62
|
-
is_entrance: boolean,
|
|
63
|
-
is_exit: boolean,
|
|
64
|
-
length: number,
|
|
65
|
-
traversal_time: number,
|
|
66
|
-
pathway_mode: number
|
|
67
|
-
}[]
|
|
68
|
-
}
|
|
69
|
-
type IdfmJson = {
|
|
70
|
-
journeys: {
|
|
71
|
-
duration: number,
|
|
72
|
-
departure_date_time: string,
|
|
73
|
-
arrival_date_time: string,
|
|
74
|
-
sections: IdfmSection[]
|
|
75
|
-
}[],
|
|
76
|
-
context: {
|
|
77
|
-
timezone: string
|
|
78
|
-
};
|
|
79
|
-
error: {
|
|
80
|
-
message?: string;
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
type IdfmIntermediateStep = {
|
|
85
|
-
name: string,
|
|
86
|
-
distance: number
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* List of all modes supported by the API
|
|
91
|
-
* http://doc.navitia.io/#physical-mode
|
|
92
|
-
*/
|
|
93
|
-
|
|
94
|
-
const transitModeCorrespondance = new Map<string, TransitMode>();
|
|
95
|
-
transitModeCorrespondance.set('Air', 'AIRPLANE');
|
|
96
|
-
transitModeCorrespondance.set('Boat', 'BOAT');
|
|
97
|
-
transitModeCorrespondance.set('Bus', 'BUS');
|
|
98
|
-
transitModeCorrespondance.set('BusRapidTransit', 'BUS');
|
|
99
|
-
transitModeCorrespondance.set('Coach', 'BUS');
|
|
100
|
-
transitModeCorrespondance.set('Ferry', 'FERRY');
|
|
101
|
-
transitModeCorrespondance.set('Funicular', 'FUNICULAR');
|
|
102
|
-
transitModeCorrespondance.set('LocalTrain', 'TRAIN');
|
|
103
|
-
transitModeCorrespondance.set('LongDistanceTrain', 'TRAIN');
|
|
104
|
-
transitModeCorrespondance.set('Metro', 'METRO');
|
|
105
|
-
transitModeCorrespondance.set('Métro', 'METRO');
|
|
106
|
-
transitModeCorrespondance.set('RailShuttle', 'TRAIN');
|
|
107
|
-
transitModeCorrespondance.set('RapidTransit', 'BUS');
|
|
108
|
-
transitModeCorrespondance.set('Shuttle', 'BUS');
|
|
109
|
-
transitModeCorrespondance.set('SuspendedCableCar', 'FUNICULAR');
|
|
110
|
-
transitModeCorrespondance.set('Taxi', 'TAXI');
|
|
111
|
-
transitModeCorrespondance.set('Train', 'TRAIN');
|
|
112
|
-
transitModeCorrespondance.set('RER', 'TRAIN');
|
|
113
|
-
transitModeCorrespondance.set('Tramway', 'TRAM');
|
|
114
|
-
transitModeCorrespondance.set('walking', 'WALK');
|
|
115
|
-
transitModeCorrespondance.set('bike', 'BIKE');
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* List of transports modes
|
|
119
|
-
*/
|
|
120
|
-
const TRANSPORT_IDS = [
|
|
121
|
-
'physical_mode:Air',
|
|
122
|
-
'physical_mode:Boat',
|
|
123
|
-
'physical_mode:Bus',
|
|
124
|
-
'physical_mode:BusRapidTransit',
|
|
125
|
-
'physical_mode:Coach',
|
|
126
|
-
'physical_mode:Ferry',
|
|
127
|
-
'physical_mode:Funicular',
|
|
128
|
-
'physical_mode:LocalTrain',
|
|
129
|
-
'physical_mode:LongDistanceTrain',
|
|
130
|
-
'physical_mode:Metro',
|
|
131
|
-
'physical_mode:RailShuttle',
|
|
132
|
-
'physical_mode:RapidTransit',
|
|
133
|
-
'physical_mode:Shuttle',
|
|
134
|
-
'physical_mode:SuspendedCableCar',
|
|
135
|
-
'physical_mode:Taxi',
|
|
136
|
-
'physical_mode:Train',
|
|
137
|
-
'physical_mode:Tramway'
|
|
138
|
-
];
|
|
139
|
-
|
|
140
|
-
const apiKey = 'qWHj6ax6DMttG8DX6tH9CQARaiTgQ1Di';
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
function jsonToCoordinates(json: IdfmCoordinates) {
|
|
144
|
-
return new Coordinates(Number(json.lat), Number(json.lon));
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function last<T>(array: T[]) {
|
|
148
|
-
return array[array.length - 1];
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* stringDate (e.g. 20211117T104516)
|
|
153
|
-
*/
|
|
154
|
-
function dateStringToTimestamp(stringDate: string, timeZone: string) {
|
|
155
|
-
const yearStr = stringDate.substr(0, 4);
|
|
156
|
-
const monthStr = stringDate.substr(4, 2);
|
|
157
|
-
const dayStr = stringDate.substr(6, 2);
|
|
158
|
-
const hoursStr = stringDate.substr(9, 2);
|
|
159
|
-
const minutesStr = stringDate.substr(11, 2);
|
|
160
|
-
const secondsStr = stringDate.substr(13, 2);
|
|
161
|
-
|
|
162
|
-
return dateWithTimeZone(
|
|
163
|
-
Number(yearStr),
|
|
164
|
-
Number(monthStr) - 1,
|
|
165
|
-
Number(dayStr),
|
|
166
|
-
Number(hoursStr),
|
|
167
|
-
Number(minutesStr),
|
|
168
|
-
Number(secondsStr),
|
|
169
|
-
timeZone
|
|
170
|
-
).getTime();
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Singleton.
|
|
176
|
-
*/
|
|
177
|
-
class IdfmRemoteRouter extends RemoteRouter {
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* @override
|
|
181
|
-
*/
|
|
182
|
-
get rname() { return 'idfm' as const; }
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
async getItineraries(endpointUrl: string, routerRequest: RouterRequest) {
|
|
186
|
-
const { travelMode } = routerRequest;
|
|
187
|
-
if (travelMode === 'BIKE') {
|
|
188
|
-
// IDFM does not support bike routing, we use Geovelo instead
|
|
189
|
-
return GeoveloRemoteRouter.getItineraries('https://idfm.getwemap.com/marketplace/computedroutes', routerRequest);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const url = this.getURL(endpointUrl, routerRequest);
|
|
193
|
-
|
|
194
|
-
const res = await (fetch(url, {
|
|
195
|
-
method: 'GET',
|
|
196
|
-
headers: { apiKey }
|
|
197
|
-
}).catch(() => {
|
|
198
|
-
throw RemoteRoutingError.unreachableServer(this.rname, url);
|
|
199
|
-
}));
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const jsonResponse: IdfmJson = await res.json().catch(() => {
|
|
203
|
-
throw RemoteRoutingError.responseNotParsing(this.rname, url);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
// When IDFM failed to calculate an itinerary (ie. start or end
|
|
207
|
-
// point is far from network), it respond a 404 with an error message
|
|
208
|
-
// or a 200 with an error message
|
|
209
|
-
if (jsonResponse && jsonResponse.error) {
|
|
210
|
-
throw RemoteRoutingError.notFound(this.rname, jsonResponse.error.message);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const itineraries = this.parseResponse(jsonResponse);
|
|
214
|
-
|
|
215
|
-
const sameModeFound = itineraries.some((itinerary) => areTransitAndTravelModeConsistent(itinerary.transitMode, routerRequest.travelMode));
|
|
216
|
-
|
|
217
|
-
if (!sameModeFound) {
|
|
218
|
-
throw RemoteRoutingError.notFound(
|
|
219
|
-
this.rname,
|
|
220
|
-
'Selected mode of transport was not found for this itinerary.'
|
|
221
|
-
)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return itineraries;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
getURL(endpointUrl: string, routerRequest: RouterRequest) {
|
|
228
|
-
const { origin, destination, waypoints, travelMode } = routerRequest;
|
|
229
|
-
|
|
230
|
-
if ((waypoints || []).length > 0) {
|
|
231
|
-
Logger.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints?.length})`);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const url = new URL(endpointUrl);
|
|
235
|
-
|
|
236
|
-
const coreParams = new URLSearchParams();
|
|
237
|
-
coreParams.set('from', `${origin.longitude};${origin.latitude}`);
|
|
238
|
-
coreParams.set('to', `${destination.longitude};${destination.latitude}`);
|
|
239
|
-
coreParams.set('data_freshness', 'realtime');
|
|
240
|
-
|
|
241
|
-
if (routerRequest.itineraryModifiers?.avoidStairs) {
|
|
242
|
-
coreParams.set('wheelchair', 'true')
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
let queryParams: URLSearchParams = new URLSearchParams();
|
|
246
|
-
switch (travelMode) {
|
|
247
|
-
case 'WALK':
|
|
248
|
-
queryParams = this.getWalkingQuery();
|
|
249
|
-
break;
|
|
250
|
-
case 'BIKE':
|
|
251
|
-
queryParams = this.getBikeQuery();
|
|
252
|
-
break;
|
|
253
|
-
case 'CAR':
|
|
254
|
-
queryParams = this.getCarQuery();
|
|
255
|
-
break;
|
|
256
|
-
default:
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
[coreParams, queryParams].map(params => {
|
|
261
|
-
for (const pair of params.entries()) {
|
|
262
|
-
url.searchParams.append(pair[0], pair[1]);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
return url.toString();
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
getCarQuery() {
|
|
270
|
-
const urlSearchParams = new URLSearchParams();
|
|
271
|
-
|
|
272
|
-
TRANSPORT_IDS.forEach((id) => {
|
|
273
|
-
urlSearchParams.append('forbidden_uris[]', id);
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
urlSearchParams.append('first_section_mode[]', 'walking');
|
|
277
|
-
urlSearchParams.append('first_section_mode[]', 'car');
|
|
278
|
-
urlSearchParams.append('last_section_mode[]', 'walking');
|
|
279
|
-
urlSearchParams.append('last_section_mode[]', 'car');
|
|
280
|
-
|
|
281
|
-
return urlSearchParams;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
getWalkingQuery() {
|
|
285
|
-
const urlSearchParams = new URLSearchParams();
|
|
286
|
-
|
|
287
|
-
TRANSPORT_IDS.forEach((id) => {
|
|
288
|
-
urlSearchParams.append('forbidden_uris[]', id);
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
urlSearchParams.append('first_section_mode[]', 'walking');
|
|
292
|
-
urlSearchParams.append('last_section_mode[]', 'walking');
|
|
293
|
-
|
|
294
|
-
return urlSearchParams;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
getBikeQuery() {
|
|
298
|
-
const urlSearchParams = new URLSearchParams();
|
|
299
|
-
|
|
300
|
-
TRANSPORT_IDS.forEach((id) => {
|
|
301
|
-
urlSearchParams.append('forbidden_uris[]', id);
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
urlSearchParams.append('first_section_mode[]', 'bike');
|
|
305
|
-
urlSearchParams.append('last_section_mode[]', 'bike');
|
|
306
|
-
|
|
307
|
-
return urlSearchParams;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
getSectionCoords(section: IdfmSection) {
|
|
312
|
-
let from: IdfmCoordinates | undefined;
|
|
313
|
-
let to: IdfmCoordinates | undefined;
|
|
314
|
-
|
|
315
|
-
if ('stop_point' in section.from) {
|
|
316
|
-
from = section.from.stop_point.coord;
|
|
317
|
-
} else if ('address' in section.from) {
|
|
318
|
-
from = section.from.address.coord;
|
|
319
|
-
} else {
|
|
320
|
-
from = section.from.poi.coord;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if ('stop_point' in section.to) {
|
|
324
|
-
to = section.to.stop_point.coord;
|
|
325
|
-
} else if ('address' in section.to) {
|
|
326
|
-
to = section.to.address.coord;
|
|
327
|
-
} else {
|
|
328
|
-
to = section.to.poi.coord;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
return {
|
|
332
|
-
from: jsonToCoordinates(from),
|
|
333
|
-
to: jsonToCoordinates(to)
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Since the IDFM API does not provide coords for each step, we need to compute them
|
|
339
|
-
* We trim the coordinates of the leg with the distance of each step and keep the last result as the coords of the step
|
|
340
|
-
* @param {Leg} leg
|
|
341
|
-
*/
|
|
342
|
-
findStepsCoord(legCoords: Coordinates[], steps: IdfmIntermediateStep[]) {
|
|
343
|
-
const coords = legCoords;
|
|
344
|
-
|
|
345
|
-
const duplicatedCoords = [...coords];
|
|
346
|
-
let previousStep = steps[0];
|
|
347
|
-
let accumulatedIndex = 0;
|
|
348
|
-
const outputSteps = [];
|
|
349
|
-
|
|
350
|
-
for (const [idx, step] of steps.entries()) {
|
|
351
|
-
let newCoords: Coordinates;
|
|
352
|
-
|
|
353
|
-
let _idCoordsInLeg;
|
|
354
|
-
|
|
355
|
-
if (idx === 0) {
|
|
356
|
-
_idCoordsInLeg = 0;
|
|
357
|
-
newCoords = coords[0];
|
|
358
|
-
} else if (idx === steps.length - 1) {
|
|
359
|
-
_idCoordsInLeg = coords.length - 1;
|
|
360
|
-
newCoords = last(coords);
|
|
361
|
-
} else if (duplicatedCoords.length === 1) {
|
|
362
|
-
accumulatedIndex++;
|
|
363
|
-
|
|
364
|
-
_idCoordsInLeg = accumulatedIndex;
|
|
365
|
-
|
|
366
|
-
newCoords = duplicatedCoords[0];
|
|
367
|
-
|
|
368
|
-
coords[_idCoordsInLeg] = newCoords;
|
|
369
|
-
} else {
|
|
370
|
-
const result = GeoUtils.trimRoute(duplicatedCoords, duplicatedCoords[0], previousStep.distance);
|
|
371
|
-
accumulatedIndex += result.length - 1;
|
|
372
|
-
|
|
373
|
-
duplicatedCoords.splice(0, result.length - 1);
|
|
374
|
-
|
|
375
|
-
_idCoordsInLeg = accumulatedIndex;
|
|
376
|
-
|
|
377
|
-
newCoords = last(result);
|
|
378
|
-
|
|
379
|
-
coords[_idCoordsInLeg] = newCoords;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
outputSteps.push({
|
|
383
|
-
...step,
|
|
384
|
-
coords: newCoords
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
previousStep = step;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return outputSteps;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
findStepCoords(step: IdfmSection['path'][number], section: IdfmSection) {
|
|
394
|
-
if ('instruction_start_coordinate' in step) {
|
|
395
|
-
return jsonToCoordinates(step.instruction_start_coordinate);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
const via = section.vias?.find(via => via.id === step.via_uri);
|
|
399
|
-
if (via) {
|
|
400
|
-
return jsonToCoordinates(via.access_point.coord);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
parseResponse(json: IdfmJson) {
|
|
405
|
-
|
|
406
|
-
if (!json || !json.journeys) {
|
|
407
|
-
throw RemoteRoutingError.notFound(this.rname, json.error?.message);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
const itineraries = [];
|
|
411
|
-
|
|
412
|
-
const timeZone = json.context.timezone;
|
|
413
|
-
|
|
414
|
-
for (const jsonItinerary of json.journeys) {
|
|
415
|
-
|
|
416
|
-
const legs = [];
|
|
417
|
-
|
|
418
|
-
for (const jsonSection of jsonItinerary.sections) {
|
|
419
|
-
|
|
420
|
-
if (jsonSection.type === 'waiting' || jsonSection.type === 'transfer') {
|
|
421
|
-
continue;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
const { from: startSection, to: endSection } = this.getSectionCoords(jsonSection);
|
|
425
|
-
|
|
426
|
-
// A section can have multiple same coordinates, we need to remove them
|
|
427
|
-
let existingCoords: string[] = [];
|
|
428
|
-
const legCoords = jsonSection.geojson.coordinates.reduce((acc, [lon, lat]) => {
|
|
429
|
-
if (!existingCoords.includes(`${lon}-${lat}`)) {
|
|
430
|
-
existingCoords = existingCoords.concat(`${lon}-${lat}`);
|
|
431
|
-
acc.push(new Coordinates(lat, lon));
|
|
432
|
-
}
|
|
433
|
-
return acc;
|
|
434
|
-
}, [] as Coordinates[]);
|
|
435
|
-
|
|
436
|
-
const stepsBuilder = new StepsBuilder().setStart(startSection).setEnd(endSection).setPathCoords(legCoords);
|
|
437
|
-
let transportInfo: TransportInfo | undefined;
|
|
438
|
-
let transitMode = transitModeCorrespondance.get(jsonSection.mode) as TransitMode;
|
|
439
|
-
|
|
440
|
-
if (jsonSection.path) {
|
|
441
|
-
const useIDFMSteps = jsonSection.path.every(step => 'instruction_start_coordinate' in step || step.via_uri);
|
|
442
|
-
const idfmIntermediateSteps = [];
|
|
443
|
-
|
|
444
|
-
for (const jsonPathLink of jsonSection.path) {
|
|
445
|
-
let coords: Coordinates;
|
|
446
|
-
if (useIDFMSteps) {
|
|
447
|
-
coords = this.findStepCoords(jsonPathLink, jsonSection)!;
|
|
448
|
-
|
|
449
|
-
const intermediateStep = {
|
|
450
|
-
name: jsonPathLink.name,
|
|
451
|
-
distance: jsonPathLink.length,
|
|
452
|
-
coords
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
stepsBuilder.addStepInfo(intermediateStep);
|
|
456
|
-
} else {
|
|
457
|
-
idfmIntermediateSteps.push({
|
|
458
|
-
name: jsonPathLink.name,
|
|
459
|
-
distance: jsonPathLink.length,
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
if (!useIDFMSteps) {
|
|
465
|
-
stepsBuilder.setStepsInfo(this.findStepsCoord(legCoords, idfmIntermediateSteps));
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
if (jsonSection.type === 'public_transport') {
|
|
470
|
-
transportInfo = {
|
|
471
|
-
name: jsonSection.display_informations.code,
|
|
472
|
-
routeColor: jsonSection.display_informations.color,
|
|
473
|
-
routeTextColor: jsonSection.display_informations.text_color,
|
|
474
|
-
directionName: jsonSection.display_informations.direction
|
|
475
|
-
};
|
|
476
|
-
|
|
477
|
-
transitMode = transitModeCorrespondance.get(jsonSection.display_informations.physical_mode) as TransitMode;
|
|
478
|
-
|
|
479
|
-
const legStep: MinStepInfo = {
|
|
480
|
-
coords: legCoords[0],
|
|
481
|
-
name: transportInfo.directionName,
|
|
482
|
-
distance: jsonSection.geojson.properties[0].length
|
|
483
|
-
};
|
|
484
|
-
stepsBuilder.setStepsInfo([legStep]);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
const leg = new Leg({
|
|
488
|
-
transitMode,
|
|
489
|
-
duration: jsonSection.duration,
|
|
490
|
-
startTime: dateStringToTimestamp(jsonSection.departure_date_time, timeZone),
|
|
491
|
-
endTime: dateStringToTimestamp(jsonSection.arrival_date_time, timeZone),
|
|
492
|
-
start: {
|
|
493
|
-
name: jsonSection.from.name,
|
|
494
|
-
coords: startSection
|
|
495
|
-
},
|
|
496
|
-
end: {
|
|
497
|
-
name: jsonSection.to.name,
|
|
498
|
-
coords: endSection
|
|
499
|
-
},
|
|
500
|
-
coords: legCoords,
|
|
501
|
-
transportInfo,
|
|
502
|
-
steps: stepsBuilder.build()
|
|
503
|
-
});
|
|
504
|
-
legs.push(leg);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
const itinerary = new Itinerary({
|
|
508
|
-
duration: jsonItinerary.duration,
|
|
509
|
-
startTime: dateStringToTimestamp(jsonItinerary.departure_date_time, timeZone),
|
|
510
|
-
endTime: dateStringToTimestamp(jsonItinerary.arrival_date_time, timeZone),
|
|
511
|
-
origin: this.getSectionCoords(jsonItinerary.sections[0]).from,
|
|
512
|
-
destination: this.getSectionCoords(last(jsonItinerary.sections)).to,
|
|
513
|
-
legs
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
itineraries.push(itinerary);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
return itineraries;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
export default new IdfmRemoteRouter();
|
|
@@ -1,116 +0,0 @@
|
|
|
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 NavitiaRemoteRouter from './NavitiaRemoteRouter.js';
|
|
10
|
-
import { verifyStepsCoherence } from '../../model/Itinerary.spec.js';
|
|
11
|
-
import { areTransitAndTravelModeConsistent } from '../../model/TransitMode.js';
|
|
12
|
-
|
|
13
|
-
const { expect } = chai;
|
|
14
|
-
|
|
15
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
const assetsPath = path.resolve(__dirname, '../../../assets');
|
|
17
|
-
|
|
18
|
-
describe('NavitiaRouter - parseResponse', () => {
|
|
19
|
-
|
|
20
|
-
it('Itineraries - 1', () => {
|
|
21
|
-
|
|
22
|
-
const filePath = path.resolve(assetsPath, 'itinerary-lemans-navitia.json');
|
|
23
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
24
|
-
const json = JSON.parse(fileString);
|
|
25
|
-
|
|
26
|
-
const itineraries = NavitiaRemoteRouter.parseResponse(json);
|
|
27
|
-
itineraries.forEach(verifyStepsCoherence);
|
|
28
|
-
|
|
29
|
-
expect(itineraries.length).equal(5);
|
|
30
|
-
|
|
31
|
-
const itinerary1 = itineraries[0];
|
|
32
|
-
expect(itinerary1.origin.equals(new Coordinates(48.007274, 0.187574))).true;
|
|
33
|
-
expect(itinerary1.destination.equals(new Coordinates(48.005228, 0.205664))).true;
|
|
34
|
-
expect(itinerary1.distance).to.be.closeTo(1710, 1);
|
|
35
|
-
expect(itinerary1.duration).equal(1140);
|
|
36
|
-
expect(itinerary1.transitMode).equal('TRAM');
|
|
37
|
-
// Do not work because of the input time format
|
|
38
|
-
expect(itinerary1.startTime).equal(1722854691000);
|
|
39
|
-
expect(itinerary1.endTime).equal(1722855831000);
|
|
40
|
-
expect(itinerary1.legs.length).equal(3);
|
|
41
|
-
|
|
42
|
-
expect(areTransitAndTravelModeConsistent(itinerary1.transitMode, 'TRANSIT')).is.true;
|
|
43
|
-
|
|
44
|
-
const itinerary1leg1 = itinerary1.legs[0];
|
|
45
|
-
// Do not work because of the input time format
|
|
46
|
-
expect(itinerary1leg1.startTime).equal(1722854691000);
|
|
47
|
-
expect(itinerary1leg1.endTime).equal(1722854885000);
|
|
48
|
-
expect(itinerary1leg1.distance).to.be.closeTo(224, 1);
|
|
49
|
-
expect(itinerary1leg1.transitMode).equal('WALK');
|
|
50
|
-
expect(itinerary1leg1.transportInfo).is.null;
|
|
51
|
-
expect(itinerary1leg1.start.name).equal('33 Rue Saint-Pavin des Champs (Le Mans)');
|
|
52
|
-
expect(itinerary1leg1.start.coords.distanceTo(new Coordinates(48.007274, 0.187574))).to.be.closeTo(0, 1);
|
|
53
|
-
expect(itinerary1leg1.end.name).equal('Lafayette (Le Mans)');
|
|
54
|
-
expect(itinerary1leg1.end.coords.distanceTo(new Coordinates(48.006794, 0.190226))).to.be.closeTo(0, 1);
|
|
55
|
-
|
|
56
|
-
const itinerary1leg2 = itinerary1.legs[1];
|
|
57
|
-
expect(itinerary1leg2.transitMode).equal('TRAM');
|
|
58
|
-
expect(itinerary1leg2.transportInfo).is.not.null;
|
|
59
|
-
expect(itinerary1leg2.transportInfo?.name).equal('T1');
|
|
60
|
-
expect(itinerary1leg2.transportInfo?.routeColor).equal('E5261D');
|
|
61
|
-
expect(itinerary1leg2.transportInfo?.routeTextColor).equal('FFFFFF');
|
|
62
|
-
expect(itinerary1leg2.transportInfo?.directionName).equal('Antarès - Stade Marie Marvingt (Le Mans)');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('Itineraries - 2', () => {
|
|
66
|
-
|
|
67
|
-
const filePath = path.resolve(assetsPath, 'itinerary-lemans-navitia.json');
|
|
68
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
69
|
-
const json = JSON.parse(fileString);
|
|
70
|
-
|
|
71
|
-
const itineraries = NavitiaRemoteRouter.parseResponse(json);
|
|
72
|
-
itineraries.forEach(verifyStepsCoherence);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const itinerary2 = itineraries[1];
|
|
76
|
-
expect(itinerary2.origin.equals(new Coordinates(48.007274, 0.187574))).true;
|
|
77
|
-
expect(itinerary2.destination.equals(new Coordinates(48.005228, 0.205664))).true;
|
|
78
|
-
expect(itinerary2.distance).to.be.closeTo(1995, 1);
|
|
79
|
-
expect(itinerary2.duration).equal(1452);
|
|
80
|
-
expect(itinerary2.transitMode).equal('MULTI');
|
|
81
|
-
// Do not work because of the input time format
|
|
82
|
-
expect(itinerary2.startTime).equal(1722854691000);
|
|
83
|
-
expect(itinerary2.endTime).equal(1722856143000);
|
|
84
|
-
expect(itinerary2.legs.length).equal(4);
|
|
85
|
-
|
|
86
|
-
expect(areTransitAndTravelModeConsistent(itinerary2.transitMode, 'TRANSIT')).is.true;
|
|
87
|
-
|
|
88
|
-
const itinerary2leg1 = itinerary2.legs[0];
|
|
89
|
-
// Do not work because of the input time format
|
|
90
|
-
expect(itinerary2leg1.startTime).equal(1722854691000);
|
|
91
|
-
expect(itinerary2leg1.endTime).equal(1722854885000);
|
|
92
|
-
expect(itinerary2leg1.distance).to.be.closeTo(224, 1);
|
|
93
|
-
expect(itinerary2leg1.transitMode).equal('WALK');
|
|
94
|
-
expect(itinerary2leg1.transportInfo).is.null;
|
|
95
|
-
expect(itinerary2leg1.start.name).equal('33 Rue Saint-Pavin des Champs (Le Mans)');
|
|
96
|
-
expect(itinerary2leg1.start.coords.distanceTo(new Coordinates(48.007274, 0.187574))).to.be.closeTo(0, 1);
|
|
97
|
-
expect(itinerary2leg1.end.name).equal('Lafayette (Le Mans)');
|
|
98
|
-
expect(itinerary2leg1.end.coords.distanceTo(new Coordinates(48.006794, 0.190226))).to.be.closeTo(0, 1);
|
|
99
|
-
|
|
100
|
-
const itinerary2leg2 = itinerary2.legs[1];
|
|
101
|
-
expect(itinerary2leg2.transitMode).equal('TRAM');
|
|
102
|
-
expect(itinerary2leg2.transportInfo).is.not.null;
|
|
103
|
-
expect(itinerary2leg2.transportInfo?.name).equal('T1');
|
|
104
|
-
expect(itinerary2leg2.transportInfo?.routeColor).equal('E5261D');
|
|
105
|
-
expect(itinerary2leg2.transportInfo?.routeTextColor).equal('FFFFFF');
|
|
106
|
-
expect(itinerary2leg2.transportInfo?.directionName).equal('Antarès - Stade Marie Marvingt (Le Mans)');
|
|
107
|
-
|
|
108
|
-
const itinerary2leg3 = itinerary2.legs[2];
|
|
109
|
-
expect(itinerary2leg3.transitMode).equal('BUS');
|
|
110
|
-
expect(itinerary2leg3.transportInfo).is.not.null;
|
|
111
|
-
expect(itinerary2leg3.transportInfo?.name).equal('6');
|
|
112
|
-
expect(itinerary2leg3.transportInfo?.routeColor).equal('C3057F');
|
|
113
|
-
expect(itinerary2leg3.transportInfo?.routeTextColor).equal('FFFFFF');
|
|
114
|
-
expect(itinerary2leg3.transportInfo?.directionName).equal('St-Martin (Le Mans)');
|
|
115
|
-
});
|
|
116
|
-
});
|