atriusmaps-node-sdk 3.3.31 → 3.3.225
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/README.md +19 -1
- package/dist/cjs/_virtual/_empty_module_placeholder.js +2 -2
- package/dist/cjs/deploy/prepareSDKConfig.js +152 -2
- package/dist/cjs/nodesdk/nodeEntry.js +109 -0
- package/dist/cjs/package.json.js +190 -7
- package/dist/cjs/plugins/clientAPI/src/clientAPI.js +11 -2
- package/dist/cjs/plugins/dynamicPois/src/dynamicPois.js +218 -21
- package/dist/cjs/plugins/poiDataManager/src/poiDataManager.js +292 -21
- package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +99 -20
- package/dist/cjs/plugins/sdkServer/src/sdkServer.js +219 -2
- package/dist/cjs/plugins/sdkServer/src/util.js +16 -3
- package/dist/cjs/plugins/searchService/src/poiSearch.js +57 -19
- package/dist/cjs/plugins/searchService/src/searchService.js +246 -21
- package/dist/cjs/plugins/searchService/src/searchTypeahead.js +60 -3
- package/dist/cjs/plugins/searchService/src/utils.js +23 -4
- package/dist/cjs/plugins/venueDataLoader/src/venueDataLoader.js +472 -23
- package/dist/cjs/plugins/venueDataLoader/src/venueLoadingUtils.js +191 -23
- package/dist/cjs/plugins/wayfinder/src/findRoute.js +147 -19
- package/dist/cjs/plugins/wayfinder/src/minPriorityQueue.js +88 -2
- package/dist/cjs/plugins/wayfinder/src/navGraph.js +393 -5
- package/dist/cjs/plugins/wayfinder/src/navGraphDebug.js +110 -20
- package/dist/cjs/plugins/wayfinder/src/segmentBadges.js +28 -2
- package/dist/cjs/plugins/wayfinder/src/segmentBuilder.js +257 -19
- package/dist/cjs/plugins/wayfinder/src/segmentCategories.js +29 -2
- package/dist/cjs/plugins/wayfinder/src/stepBuilder.js +238 -3
- package/dist/cjs/plugins/wayfinder/src/wayfinder.js +597 -22
- package/dist/cjs/src/app.js +191 -25
- package/dist/cjs/src/configs/postproc-mol-url-parms.js +58 -2
- package/dist/cjs/src/configs/postproc-stateTracking.js +53 -19
- package/dist/cjs/src/controller.js +43 -4
- package/dist/cjs/src/debugTools.js +128 -23
- package/dist/cjs/src/env.js +17 -2
- package/dist/cjs/src/extModules/bustle.js +128 -4
- package/dist/cjs/src/extModules/flexapi/src/help.js +23 -4
- package/dist/cjs/src/extModules/flexapi/src/index.js +65 -4
- package/dist/cjs/src/extModules/flexapi/src/validate.js +133 -5
- package/dist/cjs/src/extModules/geohasher.js +90 -3
- package/dist/cjs/src/extModules/log.js +69 -2
- package/dist/cjs/src/historyManager.js +29 -2
- package/dist/cjs/src/utils/bounds.js +22 -4
- package/dist/cjs/src/utils/buildStructureLookup.js +31 -19
- package/dist/cjs/src/utils/configUtils.js +71 -3
- package/dist/cjs/src/utils/dom.js +48 -5
- package/dist/cjs/src/utils/funcs.js +30 -7
- package/dist/cjs/src/utils/geodesy.js +35 -3
- package/dist/cjs/src/utils/geom.js +212 -25
- package/dist/cjs/src/utils/i18n.js +69 -5
- package/dist/cjs/src/utils/observable.js +73 -2
- package/dist/cjs/src/utils/rand.js +82 -3
- package/dist/nodesdk/nodeEntry.js +1 -0
- package/dist/package.json.js +1 -0
- package/dist/plugins/dynamicPois/src/dynamicPois.js +1 -0
- package/dist/plugins/sdkServer/src/sdkHeadless.js +1 -0
- package/{lib → dist}/plugins/sdkServer/src/sdkServer.js +1 -1
- package/dist/plugins/searchService/src/poiSearch.js +1 -0
- package/dist/plugins/searchService/src/searchService.js +1 -0
- package/dist/plugins/venueDataLoader/src/venueDataLoader.js +1 -0
- package/dist/plugins/venueDataLoader/src/venueLoadingUtils.js +1 -0
- package/dist/plugins/wayfinder/src/navGraph.js +1 -0
- package/{lib → dist}/plugins/wayfinder/src/segmentBuilder.js +1 -1
- package/dist/plugins/wayfinder/src/stepBuilder.js +1 -0
- package/dist/plugins/wayfinder/src/wayfinder.js +1 -0
- package/dist/src/app.js +1 -0
- package/dist/src/configs/postproc-mol-url-parms.js +1 -0
- package/{lib → dist}/src/configs/sdkHeadless.json.js +1 -1
- package/dist/src/extModules/bustle.js +1 -0
- package/dist/src/extModules/log.js +1 -0
- package/dist/src/utils/funcs.js +1 -0
- package/dist/src/utils/geom.js +1 -0
- package/dist/src/utils/i18n.js +1 -0
- package/package.json +17 -9
- package/config/rollup.config.cjs.js +0 -31
- package/dist/cjs/deploy/nodeEntry.js +0 -15
- package/dist/cjs/src/auth/Auth.js +0 -23
- package/lib/deploy/nodeEntry.js +0 -1
- package/lib/package.json.js +0 -1
- package/lib/plugins/dynamicPois/src/dynamicPois.js +0 -1
- package/lib/plugins/sdkServer/src/sdkHeadless.js +0 -1
- package/lib/plugins/searchService/src/poiSearch.js +0 -1
- package/lib/plugins/searchService/src/searchService.js +0 -1
- package/lib/plugins/venueDataLoader/src/venueDataLoader.js +0 -1
- package/lib/plugins/venueDataLoader/src/venueLoadingUtils.js +0 -1
- package/lib/plugins/wayfinder/src/navGraph.js +0 -1
- package/lib/plugins/wayfinder/src/stepBuilder.js +0 -1
- package/lib/plugins/wayfinder/src/wayfinder.js +0 -1
- package/lib/src/app.js +0 -1
- package/lib/src/auth/Auth.js +0 -1
- package/lib/src/configs/postproc-mol-url-parms.js +0 -1
- package/lib/src/configs/sdkHeadless.json +0 -28
- package/lib/src/extModules/bustle.js +0 -1
- package/lib/src/extModules/log.js +0 -1
- package/lib/src/utils/funcs.js +0 -1
- package/lib/src/utils/geom.js +0 -1
- package/lib/src/utils/i18n.js +0 -1
- /package/{lib → dist}/_virtual/_empty_module_placeholder.js +0 -0
- /package/{lib → dist}/deploy/prepareSDKConfig.js +0 -0
- /package/{lib → dist}/plugins/clientAPI/src/clientAPI.js +0 -0
- /package/{lib → dist}/plugins/poiDataManager/src/poiDataManager.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/util.js +0 -0
- /package/{lib → dist}/plugins/searchService/src/searchTypeahead.js +0 -0
- /package/{lib → dist}/plugins/searchService/src/utils.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/findRoute.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/minPriorityQueue.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/navGraphDebug.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/segmentBadges.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/segmentCategories.js +0 -0
- /package/{lib → dist}/src/configs/postproc-stateTracking.js +0 -0
- /package/{lib → dist}/src/controller.js +0 -0
- /package/{lib → dist}/src/debugTools.js +0 -0
- /package/{lib → dist}/src/env.js +0 -0
- /package/{lib → dist}/src/extModules/flexapi/src/help.js +0 -0
- /package/{lib → dist}/src/extModules/flexapi/src/index.js +0 -0
- /package/{lib → dist}/src/extModules/flexapi/src/validate.js +0 -0
- /package/{lib → dist}/src/extModules/geohasher.js +0 -0
- /package/{lib → dist}/src/historyManager.js +0 -0
- /package/{lib → dist}/src/utils/bounds.js +0 -0
- /package/{lib → dist}/src/utils/buildStructureLookup.js +0 -0
- /package/{lib → dist}/src/utils/configUtils.js +0 -0
- /package/{lib → dist}/src/utils/dom.js +0 -0
- /package/{lib → dist}/src/utils/geodesy.js +0 -0
- /package/{lib → dist}/src/utils/observable.js +0 -0
- /package/{lib → dist}/src/utils/rand.js +0 -0
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
var
|
|
5
|
+
var R = require('ramda');
|
|
6
|
+
var Zousan = require('zousan');
|
|
7
7
|
var buildStructureLookup = require('../../../src/utils/buildStructureLookup.js');
|
|
8
8
|
var geodesy = require('../../../src/utils/geodesy.js');
|
|
9
9
|
var findRoute = require('./findRoute.js');
|
|
@@ -14,27 +14,602 @@ var segmentBuilder = require('./segmentBuilder.js');
|
|
|
14
14
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
15
15
|
|
|
16
16
|
function _interopNamespace(e) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
if (e && e.__esModule) return e;
|
|
18
|
+
var n = Object.create(null);
|
|
19
|
+
if (e) {
|
|
20
|
+
Object.keys(e).forEach(function (k) {
|
|
21
|
+
if (k !== 'default') {
|
|
22
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
23
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function () { return e[k]; }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
n["default"] = e;
|
|
31
|
+
return Object.freeze(n);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
var
|
|
35
|
-
var
|
|
34
|
+
var R__namespace = /*#__PURE__*/_interopNamespace(R);
|
|
35
|
+
var Zousan__default = /*#__PURE__*/_interopDefaultLegacy(Zousan);
|
|
36
36
|
|
|
37
|
-
const
|
|
37
|
+
const DEFAULT_WALKING_SPEED_M_PER_MIN = 60;
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
const getEdgeTo = dst => node => R__namespace.find(e => e.dst === dst, node.edges);
|
|
40
|
+
|
|
41
|
+
// todo may be not needed
|
|
42
|
+
const SecurityLaneType = {
|
|
43
|
+
SECURITY: 'SecurityLane',
|
|
44
|
+
IMMIGRATION: 'ImmigrationLane'
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @typedef {Object} Endpoint
|
|
49
|
+
* @property {number} lat - latitude
|
|
50
|
+
* @property {number} lng - longitude
|
|
51
|
+
* @property {string} title
|
|
52
|
+
* @property {string} [floorId] - usually present
|
|
53
|
+
* @property {number} [ordinal] - optional
|
|
54
|
+
*
|
|
55
|
+
* @typedef SecurityLaneIdsMap
|
|
56
|
+
* @property {string[]} SecurityLane - list of ids of security lanes
|
|
57
|
+
* @property {string[]} ImmigrationLane - list of ids of immigration lanes
|
|
58
|
+
*
|
|
59
|
+
* @typedef Route
|
|
60
|
+
* @property {Step[]} steps - list of navigation steps
|
|
61
|
+
* @property {Segment[]} segments - list of navigation line segments
|
|
62
|
+
* @property {number} time - total route time
|
|
63
|
+
* @property {number} distance - total route distance
|
|
64
|
+
*
|
|
65
|
+
* @typedef RouteOptions
|
|
66
|
+
* @property {SecurityLaneIdsMap} selectedSecurityLanes - map of selected lane ids by type
|
|
67
|
+
* @property {boolean} requiresAccessibility - true if route should be accessible
|
|
68
|
+
* @property {boolean} compareFindPaths - indicate whether to calculate path using 2 methods and then compare their performance
|
|
69
|
+
*
|
|
70
|
+
* @typedef SecurityWaitTime
|
|
71
|
+
* @property {number} queueTime
|
|
72
|
+
* @property {boolean} timeIsReal
|
|
73
|
+
* @property {boolean} isTemporarilyClosed
|
|
74
|
+
*
|
|
75
|
+
* @typedef {Array<number>} Coordinate - pair of lng and lat
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
function create (app, config) {
|
|
79
|
+
const log = app.log.sublog('wayfinder');
|
|
80
|
+
const init = async () => {
|
|
81
|
+
app.bus.send('venueData/loadNavGraph');
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
let graphLoadedProm = new Zousan__default["default"]();
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Returns nav graph object for testing purposes.
|
|
88
|
+
* Result includes nav nodes, edges, functions to update dynamic data and calculate shortest paths
|
|
89
|
+
*
|
|
90
|
+
* @returns {Object}
|
|
91
|
+
*/
|
|
92
|
+
app.bus.on('wayfinder/_getNavGraph', () => graphLoadedProm);
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @typedef RawNavGraph
|
|
96
|
+
* @property Array.<RawNavEdge> edges
|
|
97
|
+
* @property Array.<RawNavNode> nodes
|
|
98
|
+
*
|
|
99
|
+
* @typedef RawNavEdge
|
|
100
|
+
* @property {string} s - id of start node
|
|
101
|
+
* @property {string} d - id of destination node
|
|
102
|
+
* @property {number} l - custom transit time
|
|
103
|
+
* @property {boolean} h - is edge a driveway
|
|
104
|
+
* @property {string} t - edge type
|
|
105
|
+
* @property {Array.<{ s, o, i, e }>|null} p - list of Bezier points
|
|
106
|
+
*
|
|
107
|
+
* @typedef RawNavNode
|
|
108
|
+
* @property {string} id
|
|
109
|
+
* @property {string} floorId
|
|
110
|
+
* @property {number} lat
|
|
111
|
+
* @property {number} lng
|
|
112
|
+
*
|
|
113
|
+
* Transforms raw nav graph data and list of structures
|
|
114
|
+
* to nav graph object with functions to build shortest paths
|
|
115
|
+
*
|
|
116
|
+
* @param {RawNavGraph} navGraphData
|
|
117
|
+
* @param {Array.<Structure>} structures
|
|
118
|
+
*/
|
|
119
|
+
app.bus.on('venueData/navGraphLoaded', async ({ navGraphData, structures }) => {
|
|
120
|
+
const structureLookup = buildStructureLookup.buildStructuresLookup(structures);
|
|
121
|
+
const securityLanesMap = await prepareSecurityLanes();
|
|
122
|
+
const graph = navGraph.createNavGraph(
|
|
123
|
+
navGraphData,
|
|
124
|
+
structureLookup.floorIdToOrdinal,
|
|
125
|
+
structureLookup.floorIdToStructureId,
|
|
126
|
+
securityLanesMap
|
|
127
|
+
);
|
|
128
|
+
graphLoadedProm.resolve(graph);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const prepareSecurityLanes = async () => {
|
|
132
|
+
const securityPois = await app.bus.get('poi/getByCategoryId', { categoryId: 'security' });
|
|
133
|
+
return R__namespace.pipe(R__namespace.map(getSecurityLane), R__namespace.filter(R__namespace.identity))(securityPois)
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const getSecurityLane = poi => poi.queue && {
|
|
137
|
+
type: R__namespace.path(['queue', 'queueType'], poi),
|
|
138
|
+
id: R__namespace.path(['queue', 'queueSubtype'], poi)
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Returns a shortest path from user physical location to provided destination
|
|
143
|
+
* and triggers rendering navigation line on the map
|
|
144
|
+
*
|
|
145
|
+
* @param {Endpoint} toEndpoint
|
|
146
|
+
* @param {Boolean} requiresAccessibility
|
|
147
|
+
* @param {SecurityLaneIdsMap} selectedSecurityLanes
|
|
148
|
+
* @returns {Route}
|
|
149
|
+
*/
|
|
150
|
+
app.bus.on('wayfinder/showNavLineFromPhysicalLocation', async ({ toEndpoint, selectedSecurityLanes = null, requiresAccessibility }) => {
|
|
151
|
+
const physicalLocation = await app.bus.get('user/getPhysicalLocation');
|
|
152
|
+
return navigateFromTo(physicalLocation, toEndpoint, { selectedSecurityLanes, requiresAccessibility, primary: true })
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
async function navigateFromTo (fromEndpoint, toEndpoint, options) {
|
|
156
|
+
const route = await getRoute({ fromEndpoint, toEndpoint, options });
|
|
157
|
+
if (route) {
|
|
158
|
+
const { segments } = route;
|
|
159
|
+
if (options.primary)
|
|
160
|
+
app.bus.send('map/resetNavlineFeatures');
|
|
161
|
+
app.bus.send('map/showNavlineFeatures', { segments, category: options.primary ? 'primary' : 'alternative' });
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return route
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const poiIdToNavigationEndpoint = (id, floorIdToOrdinal) =>
|
|
168
|
+
app.bus.get('poi/getById', { id })
|
|
169
|
+
.then(poi => {
|
|
170
|
+
if (poi && poi.position) {
|
|
171
|
+
return poiToNavigationEndpoint(poi, floorIdToOrdinal)
|
|
172
|
+
} else
|
|
173
|
+
throw Error('Unknown POI ID ' + id)
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @busEvent wayfinder/getNavigationEndpoint
|
|
178
|
+
*
|
|
179
|
+
* Returns an object of the Endoint type.
|
|
180
|
+
* wayfinding uses this structure to find the closest node
|
|
181
|
+
* for shortestPath calculations, etc.
|
|
182
|
+
* @param {Object} p - can be a POI (or similar) or a string with lat,lng[,floorId[,name]] or location defined as { latitutde, longitude [, floorId] [, title] }
|
|
183
|
+
* @returns {Endpoint} navigational endpoint
|
|
184
|
+
*/
|
|
185
|
+
async function getNavigationEndpoint (p) {
|
|
186
|
+
return graphLoadedProm.then(graph => {
|
|
187
|
+
if (!p)
|
|
188
|
+
throw Error('wayfinder: Invalid endpoint definition', p)
|
|
189
|
+
|
|
190
|
+
if (typeof p === 'number')
|
|
191
|
+
return poiIdToNavigationEndpoint(p, graph.floorIdToOrdinal)
|
|
192
|
+
|
|
193
|
+
if (typeof p === 'string') {
|
|
194
|
+
if (p.match(/^\d+$/)) // single integer - assume its poi id
|
|
195
|
+
return poiIdToNavigationEndpoint(parseInt(p), graph.floorIdToOrdinal)
|
|
196
|
+
|
|
197
|
+
if (p.indexOf(',') > 0) { // lat,lng,floorId,desc format
|
|
198
|
+
let [lat, lng, floorId, title] = p.split(',');
|
|
199
|
+
if (!graph.floorIdToStructureId(floorId))
|
|
200
|
+
throw Error('Unknown floorId in endpoint: ' + floorId)
|
|
201
|
+
if (!title)
|
|
202
|
+
title = 'Starting Point';
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
lat: parseFloat(lat),
|
|
206
|
+
lng: parseFloat(lng),
|
|
207
|
+
ordinal: graph.floorIdToOrdinal(floorId),
|
|
208
|
+
floorId,
|
|
209
|
+
title
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (isEndpoint(p))
|
|
215
|
+
return p
|
|
216
|
+
|
|
217
|
+
if (p.latitude)
|
|
218
|
+
return {
|
|
219
|
+
lat: p.latitude,
|
|
220
|
+
lng: p.longitude,
|
|
221
|
+
floorId: p.floorId,
|
|
222
|
+
ordinal: graph.floorIdToOrdinal(p.floorId),
|
|
223
|
+
title: p.title
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (p.position && p.name) // looks like a POI or some other
|
|
227
|
+
return poiToNavigationEndpoint(p, graph.floorIdToOrdinal)
|
|
228
|
+
|
|
229
|
+
throw Error('Invalid start or end point: ' + p)
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const endpointProps = ['lat', 'lng', 'floorId', 'ordinal'];
|
|
234
|
+
const isEndpoint = R__namespace.pipe(
|
|
235
|
+
R__namespace.pick(endpointProps),
|
|
236
|
+
R__namespace.keys,
|
|
237
|
+
R__namespace.propEq('length', endpointProps.length),
|
|
238
|
+
Boolean
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const poiToNavigationEndpoint = (poi, floorIdToOrdinal) => ({
|
|
242
|
+
lat: poi.position.latitude,
|
|
243
|
+
lng: poi.position.longitude,
|
|
244
|
+
floorId: poi.position.floorId,
|
|
245
|
+
ordinal: floorIdToOrdinal(poi.position.floorId),
|
|
246
|
+
title: poi.name
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Transforms provided data to endpoint type object
|
|
251
|
+
*
|
|
252
|
+
* @return {Endpoint} - navigation endpoint
|
|
253
|
+
*/
|
|
254
|
+
app.bus.on('wayfinder/getNavigationEndpoint', ({ ep }) => getNavigationEndpoint(ep));
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* @typedef PathSecurityInfo
|
|
258
|
+
* @property {boolean} routeExists
|
|
259
|
+
* @property {boolean} [hasSecurity]
|
|
260
|
+
* @property {boolean} [hasImmigration]
|
|
261
|
+
*
|
|
262
|
+
* Checks if there is a path between 2 endpoints which satisfies passed options
|
|
263
|
+
* and if this path includes security and immigration lanes
|
|
264
|
+
*
|
|
265
|
+
* @param {Endpoint} fromEndpoint
|
|
266
|
+
* @param {Endpoint} toEndpoint
|
|
267
|
+
* @param {RouteOptions} options
|
|
268
|
+
* @returns {PathSecurityInfo}
|
|
269
|
+
*/
|
|
270
|
+
app.bus.on('wayfinder/checkIfPathHasSecurity', ({ fromEndpoint, toEndpoint, options = {} }) => graphLoadedProm
|
|
271
|
+
.then(graph => {
|
|
272
|
+
options.compareFindPaths = config.compareFindPaths;
|
|
273
|
+
const route = findRoute.findRoute(graph, fromEndpoint, toEndpoint, options);
|
|
274
|
+
|
|
275
|
+
if (!route) return { routeExists: false }
|
|
276
|
+
|
|
277
|
+
const queues = route.waypoints
|
|
278
|
+
.filter(node =>
|
|
279
|
+
R__namespace.pathEq(['securityLane', 'type'], SecurityLaneType.SECURITY, node) ||
|
|
280
|
+
R__namespace.pathEq(['securityLane', 'type'], SecurityLaneType.IMMIGRATION, node));
|
|
281
|
+
const containsSecurityLaneType = type => Boolean(route.waypoints.find(R__namespace.pathEq(['securityLane', 'type'], type)));
|
|
282
|
+
return {
|
|
283
|
+
routeExists: true,
|
|
284
|
+
queues,
|
|
285
|
+
hasSecurity: containsSecurityLaneType(SecurityLaneType.SECURITY),
|
|
286
|
+
hasImmigration: containsSecurityLaneType(SecurityLaneType.IMMIGRATION)
|
|
287
|
+
}
|
|
288
|
+
}));
|
|
289
|
+
|
|
290
|
+
app.bus.on('wayfinder/getRoute', getRoute);
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* @busEvent wayfinder/getRoute
|
|
294
|
+
*
|
|
295
|
+
* Builds the shortest path between 2 endpoints which satisfies passed options
|
|
296
|
+
*
|
|
297
|
+
* @param {RouteOptions} options
|
|
298
|
+
* @param {Endpoint} fromEndpoint
|
|
299
|
+
* @param {Endpoint} toEndpoint
|
|
300
|
+
*
|
|
301
|
+
* @return {(Route|null)} route - route or null if no route available
|
|
302
|
+
*/
|
|
303
|
+
async function getRoute ({ fromEndpoint, toEndpoint, options = {} }) {
|
|
304
|
+
return graphLoadedProm
|
|
305
|
+
.then(async graph => {
|
|
306
|
+
options.compareFindPaths = config.compareFindPaths;
|
|
307
|
+
const route = findRoute.findRoute(graph, fromEndpoint, toEndpoint, options);
|
|
308
|
+
if (!route) return null
|
|
309
|
+
if (fromEndpoint.floorId && toEndpoint.floorId) // these usually have floorId defined, but can be only ordinal
|
|
310
|
+
sendRouteAnalytic(fromEndpoint, toEndpoint, route); // todo move to analytics (NOTE: we call this twice for each nav, doubling stats!)
|
|
311
|
+
const floorIdToNameMap = await app.bus.get('venueData/getFloorIdToNameMap');
|
|
312
|
+
const queueTypes = await app.bus.get('venueData/getQueueTypes');
|
|
313
|
+
const translate = app.gt();
|
|
314
|
+
options.requiresAccessibility;
|
|
315
|
+
const { steps, segments } = segmentBuilder.buildSegments(
|
|
316
|
+
route.waypoints,
|
|
317
|
+
fromEndpoint,
|
|
318
|
+
toEndpoint,
|
|
319
|
+
floorIdToNameMap,
|
|
320
|
+
translate,
|
|
321
|
+
queueTypes);
|
|
322
|
+
|
|
323
|
+
log.info('route', route);
|
|
324
|
+
const time = Math.round(route.waypoints.reduce((total, { eta }) => total + eta, 0));
|
|
325
|
+
const distance = Math.round(route.waypoints.reduce((total, { distance }) => total + distance, 0));
|
|
326
|
+
return { ...route, segments, steps, time, distance }
|
|
327
|
+
})
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const sendRouteAnalytic = (start, end, navigationPath) => app.bus.send('session/submitEvent', {
|
|
331
|
+
type: 'navigation',
|
|
332
|
+
startPosition: {
|
|
333
|
+
venueId: start.floorId.split('-')[0],
|
|
334
|
+
buildingId: navigationPath.waypoints[0].position.structureId,
|
|
335
|
+
floorId: navigationPath.waypoints[0].position.floorId,
|
|
336
|
+
lat: navigationPath.waypoints[0].position.lat,
|
|
337
|
+
lng: navigationPath.waypoints[0].position.lng
|
|
338
|
+
},
|
|
339
|
+
endPosition: {
|
|
340
|
+
venueId: end.floorId.split('-')[0],
|
|
341
|
+
buildingId: navigationPath.waypoints[navigationPath.waypoints.length - 1].position.structureId,
|
|
342
|
+
floorId: navigationPath.waypoints[navigationPath.waypoints.length - 1].position.floorId,
|
|
343
|
+
lat: navigationPath.waypoints[navigationPath.waypoints.length - 1].position.lat,
|
|
344
|
+
lng: navigationPath.waypoints[navigationPath.waypoints.length - 1].position.lng
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Calculates transit time and distance of shortest path to start location which satisfies passed options
|
|
350
|
+
* and returns copy of POI with these new properties
|
|
351
|
+
*
|
|
352
|
+
* @param {Endpoint} startLocation
|
|
353
|
+
* @param {RouteOptions} options
|
|
354
|
+
* @returns {Object} - POI
|
|
355
|
+
*/
|
|
356
|
+
app.bus.on('wayfinder/addPathTimeSingle', async ({ poi, startLocation, options = {} }) => {
|
|
357
|
+
if (!startLocation) return poi
|
|
358
|
+
return graphLoadedProm.then(graph => addPathTimeSingle(graph, options, poi, startLocation))
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
function addPathTimeSingle (graph, options, poi, start) {
|
|
362
|
+
const end = poiToNavigationEndpoint(poi, graph.floorIdToOrdinal);
|
|
363
|
+
const path = graph.findShortestPath(start, end, options);
|
|
364
|
+
|
|
365
|
+
return resolveAndAddPathProps(poi, path, start, 'start')
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Calculates transit time and distance of shortest path from each POI to start location which satisfies passed options
|
|
370
|
+
* and returns list of copies of POI with these new properties
|
|
371
|
+
*
|
|
372
|
+
* @param {Endpoint} startLocation
|
|
373
|
+
* @param {RouteOptions} options
|
|
374
|
+
* @param pois: array of pois
|
|
375
|
+
* @returns Array.<Object> - list of POIs
|
|
376
|
+
*/
|
|
377
|
+
app.bus.on('wayfinder/addPathTimeMultiple', async ({ pois, startLocation, options = {} }) => {
|
|
378
|
+
if (!startLocation) return pois
|
|
379
|
+
return graphLoadedProm.then(graph => addPathTimeMultiple(graph, options, pois, startLocation))
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
function addPathTimeMultiple (graph, options, pois, start) {
|
|
383
|
+
try {
|
|
384
|
+
const poisList = R__namespace.clone(pois);
|
|
385
|
+
const poiLocations = poisList.map(poi => poiToNavigationEndpoint(poi, graph.floorIdToOrdinal));
|
|
386
|
+
|
|
387
|
+
const paths = graph.findAllShortestPaths(start, poiLocations, options);
|
|
388
|
+
const poisWithPathProps = poisList.map((poi, i) => resolveAndAddPathProps(poi, paths[i], start, 'start'));
|
|
389
|
+
|
|
390
|
+
return filterAndSort(poisWithPathProps)
|
|
391
|
+
} catch (e) {
|
|
392
|
+
log.error(e);
|
|
393
|
+
return pois
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function resolveAndAddPathProps (poi, path, endpoint, endpointType) {
|
|
398
|
+
let updatedPoi = R__namespace.clone(poi);
|
|
399
|
+
updatedPoi = addEndpointInformation(updatedPoi, endpoint, endpointType);
|
|
400
|
+
|
|
401
|
+
if (path && path.length) {
|
|
402
|
+
return {
|
|
403
|
+
...updatedPoi,
|
|
404
|
+
transitTime: calculateTotalPathProperty(path, 'transitTime'),
|
|
405
|
+
distance: calculateTotalPathProperty(path, 'distance')
|
|
406
|
+
}
|
|
407
|
+
} else {
|
|
408
|
+
updatedPoi.distance = (endpointType === 'start') ? getGeoDistance(updatedPoi, endpoint) : getGeoDistance(endpoint, updatedPoi);
|
|
409
|
+
updatedPoi.transitTime = getTransitTime(updatedPoi.distance);
|
|
410
|
+
return updatedPoi
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function calculateTotalPathProperty (path, propertyName) {
|
|
415
|
+
return R__namespace.aperture(2, path)
|
|
416
|
+
.map(([from, to]) => getEdgeTo(to.id)(from))
|
|
417
|
+
.map(R__namespace.prop(propertyName))
|
|
418
|
+
.reduce((totalTime, edgeTime) => totalTime + edgeTime, 0)
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function addEndpointInformation (poi, endpoint, endpointType) {
|
|
422
|
+
return {
|
|
423
|
+
...poi,
|
|
424
|
+
[endpointType + 'Information']: {
|
|
425
|
+
lat: (endpoint?.lat || endpoint?.position?.latitude),
|
|
426
|
+
lng: (endpoint?.lng || endpoint?.position?.longitude),
|
|
427
|
+
floorId: (endpoint?.floorId || endpoint?.position?.floorId)
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function getGeoDistance (endLocation, startLocation) {
|
|
433
|
+
return geodesy.distance(
|
|
434
|
+
(startLocation?.lat || startLocation?.position?.latitude), (startLocation?.lng || startLocation?.position?.longitude),
|
|
435
|
+
(endLocation?.lat || endLocation?.position?.latitude), (endLocation?.lng || endLocation?.position?.longitude))
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function getTransitTime (distance) { return distance / DEFAULT_WALKING_SPEED_M_PER_MIN }
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Calculates transit time and distance of shortest path from the start location to each POI
|
|
442
|
+
* and calculates transit time and distance of shortest path from each POI to end location,
|
|
443
|
+
* where both calculates must satisfy the passed options,
|
|
444
|
+
* then adds the transit times and distances to create a total for each POI
|
|
445
|
+
* and returns list of copies of POI with these new properties
|
|
446
|
+
*
|
|
447
|
+
* @param {Endpoint} startLocation
|
|
448
|
+
* @param {Endpoint} endLocation
|
|
449
|
+
* @param {RouteOptions} options
|
|
450
|
+
* @param pois: array of pois
|
|
451
|
+
* @returns Array.<Object> - list of POIs
|
|
452
|
+
*/
|
|
453
|
+
app.bus.on('wayfinder/multipointAddPathTimeMultiple', async ({ pois, startLocation, endLocation, options = {} }) => {
|
|
454
|
+
if (!startLocation && !endLocation) return pois
|
|
455
|
+
return graphLoadedProm.then(graph => multipointAddPathTimeMultiple(graph, options, pois, startLocation, endLocation))
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
function multipointAddPathTimeMultiple (graph, options, pois, start, end) {
|
|
459
|
+
try {
|
|
460
|
+
const poisList = R__namespace.clone(pois);
|
|
461
|
+
const poiLocations = poisList.map(poi => poiToNavigationEndpoint(poi, graph.floorIdToOrdinal));
|
|
462
|
+
|
|
463
|
+
let pathsPrimary, pathsSecondary;
|
|
464
|
+
if (start) { pathsPrimary = graph.findAllShortestPaths(start, poiLocations, options); }
|
|
465
|
+
if (end) { pathsSecondary = getAllSecondaryPaths(graph, poiLocations, end, options); }
|
|
466
|
+
|
|
467
|
+
let poisWithPathProps;
|
|
468
|
+
if (start && end) {
|
|
469
|
+
poisWithPathProps = poisList.map((poi, i) => resolveAndAddMultipointPathProps(poi, pathsPrimary[i], pathsSecondary[i], start, end));
|
|
470
|
+
} else if (start) {
|
|
471
|
+
poisWithPathProps = poisList.map((poi, i) => resolveAndAddPathProps(poi, pathsPrimary[i], start, 'start'));
|
|
472
|
+
} else {
|
|
473
|
+
poisWithPathProps = poisList.map((poi, i) => resolveAndAddPathProps(poi, pathsSecondary[i], end, 'end'));
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return filterAndSort(poisWithPathProps)
|
|
477
|
+
} catch (e) {
|
|
478
|
+
log.error(e);
|
|
479
|
+
return pois
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function filterAndSort (pois) {
|
|
484
|
+
const poisWithPathProps = pois.filter(poi => poi !== null);
|
|
485
|
+
return R__namespace.sortBy(R__namespace.propOr(Infinity, 'transitTime'), poisWithPathProps)
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function resolveAndAddMultipointPathProps (poi, pathPrimary, pathSecondary, startLocation, endLocation) {
|
|
489
|
+
const distancePrimary = resolvePathDistance(pathPrimary, startLocation, poi);
|
|
490
|
+
const distanceSecondary = resolvePathDistance(pathSecondary, poi, endLocation);
|
|
491
|
+
|
|
492
|
+
if (!distancePrimary || !distanceSecondary) return null // ensure poi is reachable from both locations
|
|
493
|
+
|
|
494
|
+
const timePrimary = resolvePathTime(pathPrimary, distancePrimary);
|
|
495
|
+
const timeSecondary = resolvePathTime(pathSecondary, distanceSecondary);
|
|
496
|
+
|
|
497
|
+
// create deep copy of poi and add information on the start and end locations
|
|
498
|
+
let updatedPoi = R__namespace.clone(poi);
|
|
499
|
+
updatedPoi = addEndpointInformation(updatedPoi, startLocation, 'start');
|
|
500
|
+
updatedPoi = addEndpointInformation(updatedPoi, endLocation, 'end');
|
|
501
|
+
|
|
502
|
+
return {
|
|
503
|
+
...updatedPoi,
|
|
504
|
+
transitTime: timePrimary + timeSecondary,
|
|
505
|
+
distance: distancePrimary + distanceSecondary,
|
|
506
|
+
startInformation: { ...updatedPoi.startInformation, transitTime: timePrimary, distance: distancePrimary },
|
|
507
|
+
endInformation: { ...updatedPoi.endInformation, transitTime: timeSecondary, distance: distanceSecondary }
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function getAllSecondaryPaths (graph, poiLocations, endLocation, options) {
|
|
512
|
+
const pathsSecondary = [];
|
|
513
|
+
for (const pointAsStart of poiLocations) {
|
|
514
|
+
pathsSecondary.push(graph.findShortestPath(pointAsStart, endLocation, options));
|
|
515
|
+
}
|
|
516
|
+
return pathsSecondary
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function resolvePathTime (path, distance) {
|
|
520
|
+
return (path && path.length) ? calculateTotalPathProperty(path, 'transitTime') : getTransitTime(distance)
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function resolvePathDistance (path, startLocation, endLocation) {
|
|
524
|
+
return (path && path.length) ? calculateTotalPathProperty(path, 'distance') : getGeoDistance(endLocation, startLocation)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Calculates transit time and distance of shortest path from start location to POI
|
|
529
|
+
* and calculates transit time and distance of shortest path from POI to end location,
|
|
530
|
+
* where both calculates must satisfy the passed options,
|
|
531
|
+
* then adds the transit times and distances to create a total for the POI
|
|
532
|
+
* and returns copy of POI with these new properties
|
|
533
|
+
*
|
|
534
|
+
* @param {Endpoint} endLocation
|
|
535
|
+
* @param {Endpoint} startLocation
|
|
536
|
+
* @param {RouteOptions} options
|
|
537
|
+
* @returns {Object} - POI
|
|
538
|
+
*/
|
|
539
|
+
app.bus.on('wayfinder/multipointAddPathTimeSingle', async ({ poi, startLocation, endLocation, options = {} }) => {
|
|
540
|
+
if (!startLocation && !endLocation) return poi
|
|
541
|
+
return graphLoadedProm.then(graph => multipointAddPathTimeSingle(graph, options, poi, startLocation, endLocation))
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
function multipointAddPathTimeSingle (graph, options, poi, start, end) {
|
|
545
|
+
const poiLocation = poiToNavigationEndpoint(poi, graph.floorIdToOrdinal);
|
|
546
|
+
|
|
547
|
+
let pathPrimary, pathSecondary;
|
|
548
|
+
if (start) { pathPrimary = graph.findShortestPath(start, poiLocation, options); }
|
|
549
|
+
if (end) { pathSecondary = graph.findShortestPath(poiLocation, end, options); }
|
|
550
|
+
|
|
551
|
+
// add two distances and times
|
|
552
|
+
if (start && end) {
|
|
553
|
+
return resolveAndAddMultipointPathProps(poi, pathPrimary, pathSecondary, start, end)
|
|
554
|
+
} else if (start) {
|
|
555
|
+
return resolveAndAddPathProps(poi, pathPrimary, start, 'start')
|
|
556
|
+
} else if (end) {
|
|
557
|
+
return resolveAndAddPathProps(poi, pathSecondary, end, 'end')
|
|
558
|
+
} else return poi
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Resets plugin state
|
|
563
|
+
*/
|
|
564
|
+
app.bus.on('venueData/loadNewVenue', () => {
|
|
565
|
+
graphLoadedProm = new Zousan__default["default"]();
|
|
566
|
+
init();
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Updates nav graph dynamic data if security data is passed
|
|
571
|
+
*
|
|
572
|
+
* @param {string} plugin - type of dynamic data
|
|
573
|
+
* @param {Object<string, SecurityWaitTime|Object>} - dictionary of POI id to dynamic data object
|
|
574
|
+
*/
|
|
575
|
+
app.bus.on('poi/setDynamicData', ({ plugin, idValuesMap }) => {
|
|
576
|
+
if (plugin !== 'security') return
|
|
577
|
+
graphLoadedProm.then(graph => graph.updateWithSecurityWaitTime(idValuesMap));
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Returns a list of edges and nodes in a format convenient to display them on the map
|
|
582
|
+
*
|
|
583
|
+
* @typedef DebugNode
|
|
584
|
+
* @property {string} floorId
|
|
585
|
+
* @property {string} id
|
|
586
|
+
* @property {boolean} isOrphaned
|
|
587
|
+
* @property {number} lat
|
|
588
|
+
* @property {number} lng
|
|
589
|
+
* @property {number} ordinal
|
|
590
|
+
* @property {string} structureId
|
|
591
|
+
*
|
|
592
|
+
* @typedef DebugEdge
|
|
593
|
+
* @property {Coordinate} startCoordinates
|
|
594
|
+
* @property {Coordinate} endCoordinates
|
|
595
|
+
* @property {boolean} isDriveway
|
|
596
|
+
* @property {number} ordinal
|
|
597
|
+
* @property {string} category
|
|
598
|
+
* @property {string} defaultStrokeColor
|
|
599
|
+
*
|
|
600
|
+
* @returns {{nodes: DebugNode[], edges: DebugEdge[]}} debug nav graph
|
|
601
|
+
*/
|
|
602
|
+
app.bus.on('wayfinder/getNavGraphFeatures', () => graphLoadedProm
|
|
603
|
+
.then(({ _nodes }) => navGraphDebug.enrichDebugNavGraph(_nodes)));
|
|
604
|
+
|
|
605
|
+
return {
|
|
606
|
+
init,
|
|
607
|
+
internal: {
|
|
608
|
+
resolveNavGraph: graph => graphLoadedProm.resolve(graph),
|
|
609
|
+
prepareSecurityLanes
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
exports.SecurityLaneType = SecurityLaneType;
|
|
615
|
+
exports.create = create;
|