atriusmaps-node-sdk 1.0.0 → 3.2.28

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 (105) hide show
  1. package/README.md +76 -0
  2. package/config/rollup.config.cjs.js +31 -0
  3. package/dist/cjs/_virtual/_empty_module_placeholder.js +5 -0
  4. package/dist/cjs/deploy/nodeEntry.js +15 -0
  5. package/dist/cjs/deploy/prepareSDKConfig.js +9 -0
  6. package/dist/cjs/package.json +1 -0
  7. package/dist/cjs/package.json.js +11 -0
  8. package/dist/cjs/plugins/clientAPI/src/clientAPI.js +9 -0
  9. package/dist/cjs/plugins/dynamicPois/src/dynamicPois.js +33 -0
  10. package/dist/cjs/plugins/poiDataManager/src/poiDataManager.js +36 -0
  11. package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +31 -0
  12. package/dist/cjs/plugins/sdkServer/src/sdkServer.js +13 -0
  13. package/dist/cjs/plugins/sdkServer/src/util.js +10 -0
  14. package/dist/cjs/plugins/searchService/src/poiSearch.js +28 -0
  15. package/dist/cjs/plugins/searchService/src/searchService.js +37 -0
  16. package/dist/cjs/plugins/searchService/src/searchTypeahead.js +8 -0
  17. package/dist/cjs/plugins/searchService/src/utils.js +13 -0
  18. package/dist/cjs/plugins/venueDataLoader/src/venueDataLoader.js +36 -0
  19. package/dist/cjs/plugins/venueDataLoader/src/venueLoadingUtils.js +34 -0
  20. package/dist/cjs/plugins/wayfinder/src/findRoute.js +30 -0
  21. package/dist/cjs/plugins/wayfinder/src/minPriorityQueue.js +5 -0
  22. package/dist/cjs/plugins/wayfinder/src/navGraph.js +13 -0
  23. package/dist/cjs/plugins/wayfinder/src/navGraphDebug.js +30 -0
  24. package/dist/cjs/plugins/wayfinder/src/segmentBadges.js +5 -0
  25. package/dist/cjs/plugins/wayfinder/src/segmentBuilder.js +32 -0
  26. package/dist/cjs/plugins/wayfinder/src/segmentCategories.js +5 -0
  27. package/dist/cjs/plugins/wayfinder/src/stepBuilder.js +10 -0
  28. package/dist/cjs/plugins/wayfinder/src/wayfinder.js +40 -0
  29. package/dist/cjs/src/app.js +44 -0
  30. package/dist/cjs/src/auth/Auth.js +23 -0
  31. package/dist/cjs/src/configs/postproc-mol-url-parms.js +9 -0
  32. package/dist/cjs/src/configs/postproc-stateTracking.js +31 -0
  33. package/dist/cjs/src/configs/sdkHeadless.json.js +47 -0
  34. package/dist/cjs/src/controller.js +14 -0
  35. package/dist/cjs/src/debugTools.js +30 -0
  36. package/dist/cjs/src/env.js +7 -0
  37. package/dist/cjs/src/extModules/bustle.js +13 -0
  38. package/dist/cjs/src/extModules/flexapi/src/help.js +9 -0
  39. package/dist/cjs/src/extModules/flexapi/src/index.js +13 -0
  40. package/dist/cjs/src/extModules/flexapi/src/validate.js +10 -0
  41. package/dist/cjs/src/extModules/geohasher.js +8 -0
  42. package/dist/cjs/src/extModules/log.js +7 -0
  43. package/dist/cjs/src/historyManager.js +7 -0
  44. package/dist/cjs/src/utils/bounds.js +10 -0
  45. package/dist/cjs/src/utils/buildStructureLookup.js +29 -0
  46. package/dist/cjs/src/utils/configUtils.js +8 -0
  47. package/dist/cjs/src/utils/dom.js +10 -0
  48. package/dist/cjs/src/utils/funcs.js +15 -0
  49. package/dist/cjs/src/utils/geodesy.js +8 -0
  50. package/dist/cjs/src/utils/geom.js +35 -0
  51. package/dist/cjs/src/utils/i18n.js +14 -0
  52. package/dist/cjs/src/utils/observable.js +5 -0
  53. package/dist/cjs/src/utils/rand.js +8 -0
  54. package/lib/_virtual/_empty_module_placeholder.js +1 -0
  55. package/lib/deploy/nodeEntry.js +1 -58
  56. package/lib/deploy/prepareSDKConfig.js +1 -112
  57. package/lib/package.json.js +1 -143
  58. package/lib/plugins/clientAPI/src/clientAPI.js +1 -14
  59. package/lib/plugins/dynamicPois/src/dynamicPois.js +1 -131
  60. package/lib/plugins/poiDataManager/src/poiDataManager.js +1 -207
  61. package/lib/plugins/sdkServer/src/sdkHeadless.js +1 -53
  62. package/lib/plugins/sdkServer/src/sdkServer.js +1 -211
  63. package/lib/plugins/sdkServer/src/util.js +1 -18
  64. package/lib/plugins/searchService/src/poiSearch.js +1 -39
  65. package/lib/plugins/searchService/src/searchService.js +1 -234
  66. package/lib/plugins/searchService/src/searchTypeahead.js +1 -63
  67. package/lib/plugins/searchService/src/utils.js +1 -30
  68. package/lib/plugins/venueDataLoader/src/venueDataLoader.js +1 -465
  69. package/lib/plugins/venueDataLoader/src/venueLoadingUtils.js +1 -84
  70. package/lib/plugins/wayfinder/src/findRoute.js +1 -134
  71. package/lib/plugins/wayfinder/src/minPriorityQueue.js +1 -89
  72. package/lib/plugins/wayfinder/src/navGraph.js +1 -370
  73. package/lib/plugins/wayfinder/src/navGraphDebug.js +1 -95
  74. package/lib/plugins/wayfinder/src/segmentBadges.js +1 -29
  75. package/lib/plugins/wayfinder/src/segmentBuilder.js +1 -241
  76. package/lib/plugins/wayfinder/src/segmentCategories.js +1 -30
  77. package/lib/plugins/wayfinder/src/stepBuilder.js +1 -236
  78. package/lib/plugins/wayfinder/src/wayfinder.js +1 -452
  79. package/lib/src/app.js +1 -150
  80. package/lib/src/auth/Auth.js +1 -35
  81. package/lib/src/configs/postproc-mol-url-parms.js +1 -58
  82. package/lib/src/configs/postproc-stateTracking.js +1 -40
  83. package/lib/src/configs/sdkHeadless.json.js +1 -42
  84. package/lib/src/controller.js +1 -45
  85. package/lib/src/debugTools.js +1 -108
  86. package/lib/src/env.js +1 -17
  87. package/lib/src/extModules/bustle.js +1 -126
  88. package/lib/src/extModules/flexapi/src/help.js +1 -21
  89. package/lib/src/extModules/flexapi/src/index.js +1 -66
  90. package/lib/src/extModules/flexapi/src/validate.js +1 -131
  91. package/lib/src/extModules/geohasher.js +1 -90
  92. package/lib/src/extModules/log.js +1 -70
  93. package/lib/src/historyManager.js +1 -30
  94. package/lib/src/utils/bounds.js +1 -23
  95. package/lib/src/utils/buildStructureLookup.js +1 -17
  96. package/lib/src/utils/configUtils.js +1 -61
  97. package/lib/src/utils/dom.js +1 -46
  98. package/lib/src/utils/funcs.js +1 -50
  99. package/lib/src/utils/geodesy.js +1 -35
  100. package/lib/src/utils/geom.js +1 -141
  101. package/lib/src/utils/i18n.js +1 -70
  102. package/lib/src/utils/observable.js +1 -76
  103. package/lib/src/utils/rand.js +1 -82
  104. package/package.json +23 -6
  105. package/lib/_virtual/_empty_module_placeholder +0 -3
@@ -1,134 +1 @@
1
- import * as R from 'ramda';
2
- import { SecurityLaneType } from './wayfinder.js';
3
-
4
- const getEdgeTo = dst => node => R.find(e => e.dst === dst, node.edges);
5
-
6
- /**
7
- * Returns the shortest route (or path) from start to end.
8
- * @param {Object} start must include {floorId, lat, lng}
9
- * @param {Object} end must include {floorId, lat, lng}
10
- * @param {Object} options optional settings for choosing route
11
- * @param {boolean} options.requiresAccessibility if true, only accessible routes are returned (no stairs or escalators)
12
- * @returns {[nodes]} array of NavGraph nodes OR null if no route exists
13
- * @throws if start or end is not defined
14
- */
15
- const calculateRoute = (graph, start, end, options) => {
16
- if (!start || !end)
17
- throw Error('bad calculate Route request!')
18
- return graph.findShortestPath(start, end, options)
19
- };
20
-
21
- /**
22
- * @typedef Waypoint
23
- * @property {FullPosition} position
24
- * @property {number} distance
25
- * @property {number} eta
26
- * @property {boolean} isSecurityCheckpoint
27
- * @property {boolean} isPortal
28
- * @property {string} portalType
29
- * @property {number} levelDifference
30
- * @property {boolean} isDestination
31
- * @property {SecurityWaitTime|null} securityWaitTimes
32
- * @property {SecurityLane|null} securityLane
33
- * @property {CurvedPath|null} curvedPathForward
34
- *
35
- * @typedef SecurityLane
36
- * @property {string} id
37
- * @property {string} type
38
- *
39
- * @typedef FullPosition
40
- * @property {string} floorId
41
- * @property {string} lat
42
- * @property {number} lng
43
- * @property {number} ordinal
44
- * @property {string} structureId
45
- *
46
- * @typedef {Array.<CurvedPoint>} CurvedPath
47
- *
48
- * @typedef CurvedPoint
49
- * @property {ObjCoordinate} end
50
- * @property {ObjCoordinate} in
51
- * @property {ObjCoordinate} out
52
- * @property {ObjCoordinate} start
53
- *
54
- * @typedef {{lng: number, lat: number}} ObjCoordinate
55
- *
56
- * Returns the shortest route (or path) from start to end.
57
- * @param graph
58
- * @param {Endpoint} start
59
- * @param {Endpoint} destination
60
- * @param {RouteOptions} options
61
- * @return {{waypoints: Array.<Waypoint>}|null}
62
- */
63
- // todo refactor
64
- const findRoute = (graph, start, destination, options = {}) => {
65
- const waypoints = [];
66
- const queues = [];
67
-
68
- let hasSecurity = false;
69
- let hasImmigration = false;
70
-
71
- const routeNodes = calculateRoute(graph, start, destination, options);
72
-
73
- if (routeNodes === null)
74
- return null
75
-
76
- let previousRouteNode = null;
77
- for (let i = 0; i < routeNodes.length; i++) {
78
- const waypoint = {
79
- distance: 0,
80
- eta: 0
81
- };
82
-
83
- if (previousRouteNode) {
84
- const edgeUsed = getEdgeTo(routeNodes[i].id)(previousRouteNode);
85
- if (edgeUsed != null) {
86
- waypoint.distance = edgeUsed.distance;
87
- waypoint.eta = edgeUsed.transitTime;
88
-
89
- if (edgeUsed.type !== 'Ground') {
90
- waypoint.portalType = edgeUsed.type;
91
- waypoint.isPortal = true;
92
- }
93
-
94
- if (edgeUsed.o)
95
- waypoint.poiId = edgeUsed.o;
96
-
97
- if (edgeUsed.path)
98
- waypoint.curvedPathForward = edgeUsed.path;
99
- if (edgeUsed.securityWaitTimes) {
100
- waypoint.securityWaitTimes = edgeUsed.securityWaitTimes;
101
- waypoint.eta = waypoint.securityWaitTimes.queueTime;
102
- }
103
-
104
- if (edgeUsed.securityLane) {
105
- waypoint.securityLane = edgeUsed.securityLane;
106
- waypoint.isSecurityCheckpoint = true;
107
- if (edgeUsed.securityLane.type === SecurityLaneType.SECURITY)
108
- hasSecurity = true;
109
- if (edgeUsed.securityLane.type === SecurityLaneType.IMMIGRATION)
110
- hasImmigration = true;
111
- if (edgeUsed.o)
112
- queues.push(edgeUsed.o);
113
- }
114
- }
115
- }
116
-
117
- waypoint.levelDifference = previousRouteNode ? routeNodes[i].ordinal - previousRouteNode.ordinal : 0;
118
- waypoint.position = R.omit(['edges', 'id'], { ...routeNodes[i] });
119
-
120
- waypoints.push(waypoint);
121
-
122
- previousRouteNode = routeNodes[i];
123
- }
124
- R.last(waypoints).isDestination = true;
125
-
126
- return {
127
- waypoints,
128
- queues,
129
- hasSecurity,
130
- hasImmigration
131
- }
132
- };
133
-
134
- export { findRoute };
1
+ import*as e from"ramda";import{SecurityLaneType as t}from"./wayfinder.js";const i=t=>i=>e.find((e=>e.dst===t),i.edges),r=(r,s,a,n={})=>{const o=[],u=[];let c=!1,l=!1;const d=((e,t,i,r)=>{if(!t||!i)throw Error("bad calculate Route request!");return e.findShortestPath(t,i,r)})(r,s,a,n);if(null===d)return null;let y=null;for(let r=0;r<d.length;r++){const s={distance:0,eta:0};if(y){const e=i(d[r].id)(y);null!=e&&(s.distance=e.distance,s.eta=e.transitTime,"Ground"!==e.type&&(s.portalType=e.type,s.isPortal=!0),e.o&&(s.poiId=e.o),e.path&&(s.curvedPathForward=e.path),e.securityWaitTimes&&(s.securityWaitTimes=e.securityWaitTimes,s.eta=s.securityWaitTimes.queueTime),e.securityLane&&(s.securityLane=e.securityLane,s.isSecurityCheckpoint=!0,e.securityLane.type===t.SECURITY&&(c=!0),e.securityLane.type===t.IMMIGRATION&&(l=!0),e.o&&u.push(e.o)))}s.levelDifference=y?d[r].ordinal-y.ordinal:0,s.position=e.omit(["edges","id"],{...d[r]}),o.push(s),y=d[r]}return e.last(o).isDestination=!0,{waypoints:o,queues:u,hasSecurity:c,hasImmigration:l}};export{r as findRoute};
@@ -1,89 +1 @@
1
- class MinPriorityQueue {
2
- constructor () {
3
- this.heap = [null]; // array representation of binary heap
4
- this.heapMap = {};
5
- }
6
-
7
- offerWithPriority (node, priority) {
8
- const index = this.heap.push([node, priority]) - 1;
9
-
10
- this.heapMap[node] = index;
11
- this.bubble(index);
12
- }
13
-
14
- raisePriority (node, priority) {
15
- const index = this.heapMap[node];
16
- this.heap[index][1] = priority;
17
-
18
- this.bubble(index);
19
- }
20
-
21
- poll () {
22
- if (this.heap.length === 1) {
23
- return null
24
- }
25
- if (this.heap.length === 2) {
26
- const value = this.heap.pop()[0];
27
- delete this.heapMap[value];
28
- return value
29
- }
30
-
31
- const value = this.heap[1][0];
32
- delete this.heapMap[value];
33
-
34
- this.heap[1] = this.heap.pop();
35
- this.heapMap[this.heap[1][0]] = 1;
36
-
37
- this.sink(1);
38
-
39
- return value
40
- }
41
-
42
- isEmpty () {
43
- return this.heap.length === 1
44
- }
45
-
46
- bubble (i) {
47
- while (i > 1) {
48
- const parentIndex = i >> 1; // floor(i/2)
49
-
50
- if (!this.isHigherPriority(i, parentIndex)) {
51
- break
52
- }
53
-
54
- this.swap(i, parentIndex);
55
- i = parentIndex;
56
- }
57
- }
58
-
59
- sink (i) {
60
- while (i * 2 < this.heap.length) {
61
- const isRightChildHigherPriority = (this.heap[i * 2 + 1] === undefined)
62
- ? false
63
- : this.isHigherPriority(i * 2 + 1, i * 2); // i*2 +1 might be null
64
- const childIndex = isRightChildHigherPriority ? i * 2 + 1 : i * 2;
65
-
66
- if (this.isHigherPriority(i, childIndex)) {
67
- break
68
- }
69
-
70
- this.swap(i, childIndex);
71
- i = childIndex;
72
- }
73
- }
74
-
75
- swap (i, j) {
76
- this.heapMap[this.heap[i][0]] = j;
77
- this.heapMap[this.heap[j][0]] = i;
78
-
79
- const temp = this.heap[i];
80
- this.heap[i] = this.heap[j];
81
- this.heap[j] = temp;
82
- }
83
-
84
- isHigherPriority (i, j) {
85
- return this.heap[i][1] < this.heap[j][1] // lower score -> higher priority
86
- }
87
- }
88
-
89
- export default MinPriorityQueue;
1
+ class h{constructor(){this.heap=[null],this.heapMap={}}offerWithPriority(h,i){const t=this.heap.push([h,i])-1;this.heapMap[h]=t,this.bubble(t)}raisePriority(h,i){const t=this.heapMap[h];this.heap[t][1]=i,this.bubble(t)}poll(){if(1===this.heap.length)return null;if(2===this.heap.length){const h=this.heap.pop()[0];return delete this.heapMap[h],h}const h=this.heap[1][0];return delete this.heapMap[h],this.heap[1]=this.heap.pop(),this.heapMap[this.heap[1][0]]=1,this.sink(1),h}isEmpty(){return 1===this.heap.length}bubble(h){for(;h>1;){const i=h>>1;if(!this.isHigherPriority(h,i))break;this.swap(h,i),h=i}}sink(h){for(;2*h<this.heap.length;){const i=void 0!==this.heap[2*h+1]&&this.isHigherPriority(2*h+1,2*h)?2*h+1:2*h;if(this.isHigherPriority(h,i))break;this.swap(h,i),h=i}}swap(h,i){this.heapMap[this.heap[h][0]]=i,this.heapMap[this.heap[i][0]]=h;const t=this.heap[h];this.heap[h]=this.heap[i],this.heap[i]=t}isHigherPriority(h,i){return this.heap[h][1]<this.heap[i][1]}}export{h as default};
@@ -1,370 +1 @@
1
- import { pick, isNil, map, omit, path } from 'ramda';
2
- import { encode, calculateAdjacent } from '../../../src/extModules/geohasher.js';
3
- import { distance } from '../../../src/utils/geodesy.js';
4
- import MinPriorityQueue from './minPriorityQueue.js';
5
-
6
- const DEFAULT_WALKING_SPEED_M_PER_MIN = 60;
7
- const CLOSED_CHECKPOINT_EDGE_WEIGHT = 9999;
8
-
9
- /**
10
- * @typedef NavNode
11
- * @property {number} ordinal
12
- * @property {Array.<NavEdge>} edges
13
- * @property {string} id
14
- * @property {number} lat
15
- * @property {number} lng
16
- * @property {string} floorId
17
- * @property {structureId} structureId
18
- *
19
- * @typedef NavEdge
20
- * @property {string} dst - id of node at edge end
21
- * @property {string} src - id of node at edge start
22
- * @property {number} distance
23
- * @property {string|undefined} o - id of security lane POI associated with this edge
24
- * @property {CurvedPath|null} path - list of Bezier points if edge represents curve
25
- * @property {boolean} isAccessible
26
- * @property {boolean} isDriveway - true if edge points to POI, false if edge just connects other edges
27
- * @property {number} transitTime
28
- * @property {string} type
29
- * @property {number} weight - value used by Dijkstra algorithm (usually edge time or distance)
30
- *
31
- * @param {RawNavGraph} data
32
- * @param {function} floorIdToOrdinal
33
- * @param {function} floorIdToStructureId
34
- * @param {Array.<SecurityLane>} securityLanesMap - list of security lanes
35
- * @return {Object}
36
- */
37
- // todo remove dead commented code
38
- function createNavGraph (data, floorIdToOrdinal, floorIdToStructureId, securityLanesMap) {
39
- const nodes = { };
40
- const geoDb = { };
41
- let securityWaitTimes = {};
42
-
43
- data.nodes.forEach(nodeData => {
44
- const ordinal = floorIdToOrdinal(nodeData.floorId);
45
- const structureId = floorIdToStructureId(nodeData.floorId);
46
- const node = {
47
- ...pick(['id', 'lat', 'lng', 'floorId'], nodeData),
48
- edges: [],
49
- ordinal,
50
- structureId
51
- };
52
- addNode(node);
53
- });
54
-
55
- data.edges.forEach(ed => nodes[ed.s].edges.push(createEdge(ed, nodes)));
56
-
57
- function addNode (node) {
58
- const largeGeo = node.floorId + ':' + encode(node.lat, node.lng).substr(0, 7);
59
- const mediumGeo = node.floorId + ':' + encode(node.lat, node.lng).substr(0, 8);
60
-
61
- if (!geoDb[largeGeo])
62
- geoDb[largeGeo] = [];
63
-
64
- geoDb[largeGeo].push(node);
65
-
66
- if (!geoDb[mediumGeo])
67
- geoDb[mediumGeo] = [];
68
-
69
- geoDb[mediumGeo].push(node);
70
-
71
- nodes[node.id] = node;
72
- }
73
-
74
- function createEdge (data, nodes) {
75
- const type = getEdgeType(data);
76
- const isAccessible = type.toLowerCase() !== 'escalator' && type.toLowerCase() !== 'stairs';
77
- // todo consider calculating edge distance with 'path' differently
78
- const distance = distanceBetweenNodes(data.s, data.d, nodes);
79
- const transitTime = data.l || distance / DEFAULT_WALKING_SPEED_M_PER_MIN;
80
-
81
- const buildCurvedPath = points => points.map(point => {
82
- return {
83
- start: { lat: point.s[0], lng: point.s[1] },
84
- out: { lat: point.o[0], lng: point.o[1] },
85
- in: { lat: point.i[0], lng: point.i[1] },
86
- end: { lat: point.e[0], lng: point.e[1] }
87
- }
88
- });
89
-
90
- const path = data.p ? buildCurvedPath(data.p) : null;
91
-
92
- return {
93
- distance,
94
- dst: data.d,
95
- o: data.o,
96
- isAccessible,
97
- isDriveway: !isNil(data.h) && !data.h,
98
- src: data.s,
99
- transitTime,
100
- type,
101
- path,
102
- weight: transitTime
103
- }
104
- }
105
-
106
- function getEdgeType (data) {
107
- if (data.x) return 'Security Checkpoint'
108
- if (data.t === '') return 'Ground'
109
- return data.t
110
- }
111
-
112
- function findShortestPathEntry (start, end, nodes, options = {}) {
113
- const startNode = findClosestNode(start.floorId, start.lat, start.lng, geoDb, nodes);
114
- const endNode = findClosestNode(end.floorId, end.lat, end.lng, geoDb, nodes);
115
-
116
- // This code section does improve performance by about 10-20%, but comes at a cost
117
- // of making the caching unusable in some cases
118
- // if (start.structureId === end.structureId) {
119
- // options.minOrd = Math.min(start.ordinal, end.ordinal)
120
- // options.maxOrd = Math.max(start.ordinal, end.ordinal)
121
- // options.structureId = start.structureId
122
- // }
123
- return findShortestPath(startNode, endNode, nodes, securityWaitTimes, securityLanesMap, options)
124
- }
125
- /**
126
- * @param {Endpoint} start - start endpoint
127
- * @param {Array.<Endpoint>} destArray - list of destinations
128
- * @param {RouteOptions} options extra options (such as requireAccessibility)
129
- * @returns {Array.<Array.<NavNode>>} array of routes corresponding to destinations specified
130
- */
131
- function findAllShortestPaths (start, destArray, options) {
132
- const lat = start.lat || start.latitude; // handle bluedot location
133
- const lng = start.lng || start.longitude; // handle bluedot location
134
- const startNode = findClosestNode(start.floorId, lat, lng, geoDb, nodes);
135
- const destNodeArray = destArray.map(dest => findClosestNode(dest.floorId, dest.lat, dest.lng, geoDb, nodes));
136
- if (!startNode || !destNodeArray.length) return []
137
- return findAllShortestPathsImpl(startNode, destNodeArray, nodes, securityWaitTimes, securityLanesMap, options)
138
- }
139
-
140
- function updateWithSecurityWaitTime (waitTimesData) {
141
- securityWaitTimes = map(omit(['lastUpdated']), waitTimesData);
142
- clearCache();
143
- }
144
-
145
- return {
146
- _nodes: nodes,
147
- _geoDb: geoDb,
148
- findShortestPath: (start, end, options) => findShortestPathEntry(start, end, nodes, options),
149
- findAllShortestPaths,
150
- floorIdToOrdinal, // todo lets get rid of this...
151
- floorIdToStructureId, // todo lets get rid of this...,
152
- updateWithSecurityWaitTime,
153
- clearCache
154
- }
155
- }
156
-
157
- function distanceBetweenNodes (n1, n2, nodes) {
158
- const node1 = nodes[n1];
159
- const node2 = nodes[n2];
160
- const distance$1 = distance(node1.lat, node1.lng, node2.lat, node2.lng);
161
- return distance$1
162
- }
163
-
164
- /**
165
- * @param {Object.<Node>} start - a node in the navGraph to start on
166
- * @param {Array.<Node>} destinations - array of nodes to find path to
167
- * @param {Object.<string, NavNode>} nodes - dictionary of nodes by id
168
- * @param {Object.<string, SecurityWaitTime>} securityWaitTimes - map of POI id to security wait time
169
- * @param {Object.<string, SecurityLane>} securityLanesMap - map of POI id to security lane
170
- * @param {RouteOptions} [options={}] extra options (such as requireAccessibility)
171
- * @returns {Array.<Array.<Node>>} list of shortest path to each destination
172
- */
173
- function findAllShortestPathsImpl (start, destinations, nodes, securityWaitTimes = {}, securityLanesMap = {}, options = {}) {
174
- // const previous = findPaths(start, start, nodes, options)
175
-
176
- // const backtrackPath = node => buildBacktrackPath(nodes, previous, node)
177
- // const poiNodeTuples = Array.from(destinations.entries())
178
-
179
- // const poiPathTuples = poiNodeTuples.map(([poi, node]) => [poi, backtrackPath(node)])
180
- // return new Map(poiPathTuples)
181
- return destinations.map(d => findShortestPath(start, d, nodes, securityWaitTimes, securityLanesMap, options))
182
- }
183
-
184
- let cost, prev, visited, visitQueue, lastStartId, lastOptionsStr;
185
-
186
- const clearCache = () => {
187
- cost = { };
188
- prev = { };
189
- visited = { };
190
- visitQueue = new MinPriorityQueue();
191
- lastStartId = null;
192
- lastOptionsStr = {};
193
- };
194
-
195
- // This is a temporary name during a "probation" period - then I will
196
- // ditch findShortestPath and rewrite findAllShortestPaths and ditch
197
- // backtrackPath, etc.
198
- // NOTE: export just for testing
199
- /**
200
- * @param {Object<Node>} start a node in the navGraph to start on
201
- * @param {Object<Node>} end a node in the navGraph to find path to
202
- * @param {Object.<string, Node>} nodes dictionary of nodes by id
203
- * @param {Object.<string, SecurityWaitTime>} securityWaitTimes - map of POI id to security wait time
204
- * @param {Object.<string, SecurityLane>} securityLanesMap - map of POI id to security lane
205
- * @param {RouteOptions} options={} extra options (such as requireAccessibility)
206
- * @returns {Array.<Node>} an array of nodes that represent the shortest route from start to end. null if no route exists.
207
- */
208
- function findShortestPath (start, end, nodes, securityWaitTimes = {}, securityLanesMap = {}, options = { }) {
209
- if (start.id !== lastStartId || lastOptionsStr !== JSON.stringify(options)) {
210
- clearCache();
211
- visitQueue.offerWithPriority(start.id, 0);
212
- cost[start.id] = 0;
213
- visited[start.id] = true;
214
-
215
- lastStartId = start.id;
216
- lastOptionsStr = JSON.stringify(options);
217
- }
218
-
219
- // continue crawling paths - but stop once we found destination
220
- while (!visitQueue.isEmpty() && !visited[end.id]) {
221
- const node = nodes[visitQueue.poll()]; // pop
222
- const ccost = cost[node.id]; // current cost to this node
223
- for (let ei = 0; ei < node.edges.length; ei++) {
224
- const e = node.edges[ei]; // next edge from this node
225
-
226
- if (visited[e.dst])
227
- continue
228
-
229
- if (options.requiresAccessibility && !e.isAccessible) {
230
- // ignore not accessible edges if we're looking for an accessible route
231
- continue
232
- }
233
-
234
- // This code section does improve performance by about 10-20%, but comes at a cost
235
- // of making the caching unusable in some cases
236
- // if ((options.minOrd !== undefined && nodes[e.dst].ordinal < options.minOrd) ||
237
- // (options.maxOrd !== undefined && nodes[e.dst].ordinal > options.maxOrd) ||
238
- // (options.structureId !== undefined && nodes[e.dst].structureId !== options.structureId))
239
- // continue
240
-
241
- let weight = e.weight;
242
- if (e.o && securityWaitTimes[e.o]) {
243
- const dynamicData = securityWaitTimes[e.o];
244
- if (dynamicData.queueTime) weight = dynamicData.queueTime;
245
- if (dynamicData.isTemporarilyClosed) weight = CLOSED_CHECKPOINT_EDGE_WEIGHT;
246
- e.securityWaitTimes = dynamicData;
247
- }
248
-
249
- if (e.o && securityLanesMap[e.o]) {
250
- e.securityLane = securityLanesMap[e.o];
251
- const { type, id } = securityLanesMap[e.o];
252
- const securityLanesIds = path(['selectedSecurityLanes', type], options);
253
- if (securityLanesIds && !securityLanesIds.includes(id))
254
- continue
255
- }
256
-
257
- if (cost[e.dst] === undefined) {
258
- prev[e.dst] = node;
259
- cost[e.dst] = ccost + weight;
260
- visitQueue.offerWithPriority(e.dst, ccost + weight); // add node to the toCheck array
261
- } else
262
- if (cost[e.dst] > (ccost + weight)) { // is this a shorter path? Relaxation...
263
- // if so, update the cost and parent
264
- cost[e.dst] = ccost + weight;
265
- prev[e.dst] = node;
266
- visitQueue.raisePriority(e.dst, ccost + weight);
267
- }
268
- }
269
- visited[node.id] = true; // we have now been selected
270
- }
271
-
272
- if (!visited[end.id]) // if we never found our endpoint, it was inaccessible
273
- return null
274
-
275
- // build the path and return it
276
- const path$1 = [];
277
- let node = end;
278
- while (node) {
279
- path$1.push(node);
280
- node = prev[node.id];
281
- }
282
- return path$1.reverse()
283
- }
284
-
285
- function geohashSearch (floorId, geohash, geoDb, size) {
286
- const geohashPrefix = geohash.substr(0, size);
287
-
288
- const searchGeos = [];
289
- searchGeos.push(floorId + ':' + calculateAdjacent(calculateAdjacent(geohashPrefix, 'top'), 'left'));
290
- searchGeos.push(floorId + ':' + calculateAdjacent(geohashPrefix, 'top'));
291
- searchGeos.push(floorId + ':' + calculateAdjacent(calculateAdjacent(geohashPrefix, 'top'), 'right'));
292
- searchGeos.push(floorId + ':' + calculateAdjacent(geohashPrefix, 'left'));
293
- searchGeos.push(floorId + ':' + geohashPrefix);
294
- searchGeos.push(floorId + ':' + calculateAdjacent(geohashPrefix, 'right'));
295
- searchGeos.push(floorId + ':' + calculateAdjacent(calculateAdjacent(geohashPrefix, 'bottom'), 'left'));
296
- searchGeos.push(floorId + ':' + calculateAdjacent(geohashPrefix, 'bottom'));
297
- searchGeos.push(floorId + ':' + calculateAdjacent(calculateAdjacent(geohashPrefix, 'bottom'), 'right'));
298
-
299
- const nodes = [];
300
- for (let i = 0; i < searchGeos.length; i++) {
301
- const nodesFound = geoDb[searchGeos[i]];
302
- if (nodesFound) {
303
- for (let j = 0; j < nodesFound.length; j++)
304
- nodes.push(nodesFound[j]);
305
- }
306
- }
307
-
308
- return nodes
309
- }
310
-
311
- function findNodesByGeohash (floorId, geohash, geoDb, nodes) {
312
- let foundNodes = geohashSearch(floorId, geohash, geoDb, 8);
313
- if (foundNodes.length > 0)
314
- return foundNodes
315
-
316
- // broaden our search a bit and try again...
317
- foundNodes = geohashSearch(floorId, geohash, geoDb, 7);
318
- if (foundNodes.length > 0)
319
- return foundNodes
320
-
321
- // punt!
322
- return Object.values(nodes)
323
- }
324
-
325
- /**
326
- * @param floorId
327
- * @param lat
328
- * @param lng
329
- * @param geoDb
330
- * @param {Object<string, NavNode>} nodes - dictionary of node id to node object
331
- * @return {NavNode} - node that is on the same floor and closest to the lat,lng point
332
- */
333
- function findClosestNode (floorId, lat, lng, geoDb, nodes) {
334
- const cnodes = findNodesByGeohash(floorId, encode(lat, lng), geoDb, nodes);
335
-
336
- const nodeWithDistance = [];
337
- for (let i = 0; i < cnodes.length; i++) {
338
- // Attached distance to each node from the origin.
339
- const distance$1 = distance(lat, lng, cnodes[i].lat, cnodes[i].lng);
340
- nodeWithDistance.push([cnodes[i], distance$1]);
341
- }
342
- // todo do not sort, just find min node
343
- // Sort by distance.
344
- nodeWithDistance.sort(function (a, b) { return a[1] - b[1] });
345
- const nodesSortedByDistance = [];
346
- for (let i = 0; i < nodeWithDistance.length; i++)
347
- nodesSortedByDistance.push(nodeWithDistance[i][0]);
348
-
349
- return nodesSortedByDistance[0]
350
- }
351
-
352
- // A slightly slower alternative to findClosestNode (an experiment - its simpler, but slower)
353
- // function findClosestNode2 (floorId, lat, lng, nodes) {
354
- // return selectShortest(Object.values(nodes)
355
- // .filter(n => n.floorId === floorId)
356
- // .map(n => [n, getGeoDistance([n.lat, n.lng], [lat, lng])]))
357
- // }
358
-
359
- // companion to above function - it returns closest node
360
- // ar is 2-dim array - ar[i][0] = node, ar[i][1] = distance
361
- // TODO: use this approach in findClosestNode - no need to sort first!
362
- // function selectShortest (ar) {
363
- // let shortest = ar[0]
364
- // for (let i = 1; i < ar.length; i++)
365
- // if (ar[i][1] < shortest[1]) shortest = ar[i]
366
-
367
- // return shortest[0]
368
- // }
369
-
370
- export { createNavGraph, findShortestPath };
1
+ import{pick as t,isNil as o,map as e,omit as n,path as r}from"ramda";import{encode as s,calculateAdjacent as i}from"../../../src/extModules/geohasher.js";import{distance as l}from"../../../src/utils/geodesy.js";import u from"./minPriorityQueue.js";function d(r,i,l,u){const d={},c={};let a={};return r.nodes.forEach((o=>{const e=i(o.floorId),n=l(o.floorId);!function(t){const o=t.floorId+":"+s(t.lat,t.lng).substr(0,7),e=t.floorId+":"+s(t.lat,t.lng).substr(0,8);c[o]||(c[o]=[]);c[o].push(t),c[e]||(c[e]=[]);c[e].push(t),d[t.id]=t}({...t(["id","lat","lng","floorId"],o),edges:[],ordinal:e,structureId:n})})),r.edges.forEach((t=>d[t.s].edges.push(function(t,e){const n=function(t){return t.x?"Security Checkpoint":""===t.t?"Ground":t.t}(t),r="escalator"!==n.toLowerCase()&&"stairs"!==n.toLowerCase(),s=f(t.s,t.d,e),i=t.l||s/60,l=t=>t.map((t=>({start:{lat:t.s[0],lng:t.s[1]},out:{lat:t.o[0],lng:t.o[1]},in:{lat:t.i[0],lng:t.i[1]},end:{lat:t.e[0],lng:t.e[1]}}))),u=t.p?l(t.p):null;return{distance:s,dst:t.d,o:t.o,isAccessible:r,isDriveway:!o(t.h)&&!t.h,src:t.s,transitTime:i,type:n,path:u,weight:i}}(t,d)))),{_nodes:d,_geoDb:c,findClosestNode:(t,o,e)=>w(t,o,e,c,d),findShortestPath:(t,o,e)=>function(t,o,e,n={}){return I(w(t.floorId,t.lat,t.lng,c,e),w(o.floorId,o.lat,o.lng,c,e),e,a,u,n)}(t,o,d,e),findAllShortestPaths:function(t,o,e){if(!t.floorId)throw Error("attempt to find a shortest path with null floorId");const n=t.lat||t.latitude,r=t.lng||t.longitude,s=w(t.floorId,n,r,c,d),i=o.map((t=>w(t.floorId,t.lat,t.lng,c,d)));return s&&i.length?function(t,o,e,n={},r={},s={}){return o.map((o=>{try{return I(t,o,e,n,r,s)}catch(t){return null}}))}(s,i,d,a,u,e):[]},floorIdToOrdinal:i,floorIdToStructureId:l,updateWithSecurityWaitTime:function(t){a=e(n(["lastUpdated"]),t),y()},clearCache:y}}function f(t,o,e){const n=e[t],r=e[o];return l(n.lat,n.lng,r.lat,r.lng)}let c,a,h,g,p,m;const y=()=>{c={},a={},h={},g=new u,p=null,m={}};function I(t,o,e,n={},s={},i={}){for(t.id===p&&m===JSON.stringify(i)||(y(),g.offerWithPriority(t.id,0),c[t.id]=0,h[t.id]=!0,p=t.id,m=JSON.stringify(i));!g.isEmpty()&&!h[o.id];){const t=e[g.poll()],o=c[t.id];for(let e=0;e<t.edges.length;e++){const l=t.edges[e];if(h[l.dst])continue;if(i.requiresAccessibility&&!l.isAccessible)continue;let u=l.weight;if(l.o&&n[l.o]){const t=n[l.o];t.queueTime&&(u=t.queueTime),t.isTemporarilyClosed&&(u=9999),l.securityWaitTimes=t}if(l.o&&s[l.o]){l.securityLane=s[l.o];const{type:t,id:o}=s[l.o],e=r(["selectedSecurityLanes",t],i);if(e&&!e.includes(o))continue}void 0===c[l.dst]?(a[l.dst]=t,c[l.dst]=o+u,g.offerWithPriority(l.dst,o+u)):c[l.dst]>o+u&&(c[l.dst]=o+u,a[l.dst]=t,g.raisePriority(l.dst,o+u))}h[t.id]=!0}if(!h[o.id])return null;const l=[];let u=o;for(;u;)l.push(u),u=a[u.id];return l.reverse()}function b(t,o,e,n){const r=o.substr(0,n),s=[];s.push(t+":"+i(i(r,"top"),"left")),s.push(t+":"+i(r,"top")),s.push(t+":"+i(i(r,"top"),"right")),s.push(t+":"+i(r,"left")),s.push(t+":"+r),s.push(t+":"+i(r,"right")),s.push(t+":"+i(i(r,"bottom"),"left")),s.push(t+":"+i(r,"bottom")),s.push(t+":"+i(i(r,"bottom"),"right"));const l=[];for(let t=0;t<s.length;t++){const o=e[s[t]];if(o)for(let t=0;t<o.length;t++)l.push(o[t])}return l}function w(t,o,e,n,r){const i=function(t,o,e,n){let r=b(t,o,e,8);return r.length>0?r:(r=b(t,o,e,7),r.length>0?r:null)}(t,s(o,e),n)||function(t,o,e,n){const r=Object.values(n).filter((o=>o.floorId===t)).map((t=>[t,l([t.lat,t.lng],[o,e])]));if(!r.length)throw Error(`findClosestNode2 found no nodes on floor ${t}`);return function(t){let o=t[0];for(let e=1;e<t.length;e++)t[e][1]<o[1]&&(o=t[e]);return o[0]}(r)}(t,o,e,r),u=[];for(let t=0;t<i.length;t++){const n=l(o,e,i[t].lat,i[t].lng);u.push([i[t],n])}u.sort((function(t,o){return t[1]-o[1]}));const d=[];for(let t=0;t<u.length;t++)d.push(u[t][0]);return d[0]}export{d as createNavGraph,I as findShortestPath};