atriusmaps-node-sdk 3.3.196 → 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.
Files changed (109) hide show
  1. package/dist/cjs/_virtual/_empty_module_placeholder.js +2 -2
  2. package/dist/cjs/deploy/prepareSDKConfig.js +152 -2
  3. package/dist/cjs/nodesdk/nodeEntry.js +109 -0
  4. package/dist/cjs/package.json.js +190 -14
  5. package/dist/cjs/plugins/clientAPI/src/clientAPI.js +11 -2
  6. package/dist/cjs/plugins/dynamicPois/src/dynamicPois.js +218 -21
  7. package/dist/cjs/plugins/poiDataManager/src/poiDataManager.js +292 -21
  8. package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +99 -20
  9. package/dist/cjs/plugins/sdkServer/src/sdkServer.js +219 -2
  10. package/dist/cjs/plugins/sdkServer/src/util.js +16 -3
  11. package/dist/cjs/plugins/searchService/src/poiSearch.js +57 -19
  12. package/dist/cjs/plugins/searchService/src/searchService.js +246 -21
  13. package/dist/cjs/plugins/searchService/src/searchTypeahead.js +60 -3
  14. package/dist/cjs/plugins/searchService/src/utils.js +23 -4
  15. package/dist/cjs/plugins/venueDataLoader/src/venueDataLoader.js +472 -21
  16. package/dist/cjs/plugins/venueDataLoader/src/venueLoadingUtils.js +191 -23
  17. package/dist/cjs/plugins/wayfinder/src/findRoute.js +147 -19
  18. package/dist/cjs/plugins/wayfinder/src/minPriorityQueue.js +88 -2
  19. package/dist/cjs/plugins/wayfinder/src/navGraph.js +393 -5
  20. package/dist/cjs/plugins/wayfinder/src/navGraphDebug.js +110 -20
  21. package/dist/cjs/plugins/wayfinder/src/segmentBadges.js +28 -2
  22. package/dist/cjs/plugins/wayfinder/src/segmentBuilder.js +257 -19
  23. package/dist/cjs/plugins/wayfinder/src/segmentCategories.js +29 -2
  24. package/dist/cjs/plugins/wayfinder/src/stepBuilder.js +238 -3
  25. package/dist/cjs/plugins/wayfinder/src/wayfinder.js +597 -22
  26. package/dist/cjs/src/app.js +191 -25
  27. package/dist/cjs/src/configs/postproc-mol-url-parms.js +58 -2
  28. package/dist/cjs/src/configs/postproc-stateTracking.js +53 -19
  29. package/dist/cjs/src/controller.js +43 -4
  30. package/dist/cjs/src/debugTools.js +128 -23
  31. package/dist/cjs/src/env.js +17 -2
  32. package/dist/cjs/src/extModules/bustle.js +128 -4
  33. package/dist/cjs/src/extModules/flexapi/src/help.js +23 -4
  34. package/dist/cjs/src/extModules/flexapi/src/index.js +65 -4
  35. package/dist/cjs/src/extModules/flexapi/src/validate.js +133 -5
  36. package/dist/cjs/src/extModules/geohasher.js +90 -3
  37. package/dist/cjs/src/extModules/log.js +69 -2
  38. package/dist/cjs/src/historyManager.js +29 -2
  39. package/dist/cjs/src/utils/bounds.js +22 -4
  40. package/dist/cjs/src/utils/buildStructureLookup.js +31 -19
  41. package/dist/cjs/src/utils/configUtils.js +71 -3
  42. package/dist/cjs/src/utils/dom.js +48 -5
  43. package/dist/cjs/src/utils/funcs.js +30 -3
  44. package/dist/cjs/src/utils/geodesy.js +35 -3
  45. package/dist/cjs/src/utils/geom.js +209 -27
  46. package/dist/cjs/src/utils/i18n.js +69 -5
  47. package/dist/cjs/src/utils/observable.js +73 -2
  48. package/dist/cjs/src/utils/rand.js +82 -3
  49. package/dist/nodesdk/nodeEntry.js +1 -0
  50. package/dist/package.json.js +1 -0
  51. package/dist/plugins/searchService/src/searchService.js +1 -0
  52. package/dist/plugins/venueDataLoader/src/venueDataLoader.js +1 -0
  53. package/dist/plugins/venueDataLoader/src/venueLoadingUtils.js +1 -0
  54. package/dist/src/app.js +1 -0
  55. package/package.json +13 -9
  56. package/.yarnrc.yml +0 -1
  57. package/config/rollup.config.cjs.js +0 -31
  58. package/dist/cjs/deploy/nodeEntry.js +0 -20
  59. package/dist/cjs/src/auth/Auth.js +0 -23
  60. package/lib/deploy/nodeEntry.js +0 -1
  61. package/lib/package.json.js +0 -1
  62. package/lib/plugins/searchService/src/searchService.js +0 -1
  63. package/lib/plugins/venueDataLoader/src/venueDataLoader.js +0 -1
  64. package/lib/plugins/venueDataLoader/src/venueLoadingUtils.js +0 -1
  65. package/lib/src/app.js +0 -1
  66. package/lib/src/configs/sdkHeadless.json +0 -28
  67. /package/{lib → dist}/_virtual/_empty_module_placeholder.js +0 -0
  68. /package/{lib → dist}/deploy/prepareSDKConfig.js +0 -0
  69. /package/{lib → dist}/plugins/clientAPI/src/clientAPI.js +0 -0
  70. /package/{lib → dist}/plugins/dynamicPois/src/dynamicPois.js +0 -0
  71. /package/{lib → dist}/plugins/poiDataManager/src/poiDataManager.js +0 -0
  72. /package/{lib → dist}/plugins/sdkServer/src/sdkHeadless.js +0 -0
  73. /package/{lib → dist}/plugins/sdkServer/src/sdkServer.js +0 -0
  74. /package/{lib → dist}/plugins/sdkServer/src/util.js +0 -0
  75. /package/{lib → dist}/plugins/searchService/src/poiSearch.js +0 -0
  76. /package/{lib → dist}/plugins/searchService/src/searchTypeahead.js +0 -0
  77. /package/{lib → dist}/plugins/searchService/src/utils.js +0 -0
  78. /package/{lib → dist}/plugins/wayfinder/src/findRoute.js +0 -0
  79. /package/{lib → dist}/plugins/wayfinder/src/minPriorityQueue.js +0 -0
  80. /package/{lib → dist}/plugins/wayfinder/src/navGraph.js +0 -0
  81. /package/{lib → dist}/plugins/wayfinder/src/navGraphDebug.js +0 -0
  82. /package/{lib → dist}/plugins/wayfinder/src/segmentBadges.js +0 -0
  83. /package/{lib → dist}/plugins/wayfinder/src/segmentBuilder.js +0 -0
  84. /package/{lib → dist}/plugins/wayfinder/src/segmentCategories.js +0 -0
  85. /package/{lib → dist}/plugins/wayfinder/src/stepBuilder.js +0 -0
  86. /package/{lib → dist}/plugins/wayfinder/src/wayfinder.js +0 -0
  87. /package/{lib → dist}/src/configs/postproc-mol-url-parms.js +0 -0
  88. /package/{lib → dist}/src/configs/postproc-stateTracking.js +0 -0
  89. /package/{lib → dist}/src/configs/sdkHeadless.json.js +0 -0
  90. /package/{lib → dist}/src/controller.js +0 -0
  91. /package/{lib → dist}/src/debugTools.js +0 -0
  92. /package/{lib → dist}/src/env.js +0 -0
  93. /package/{lib → dist}/src/extModules/bustle.js +0 -0
  94. /package/{lib → dist}/src/extModules/flexapi/src/help.js +0 -0
  95. /package/{lib → dist}/src/extModules/flexapi/src/index.js +0 -0
  96. /package/{lib → dist}/src/extModules/flexapi/src/validate.js +0 -0
  97. /package/{lib → dist}/src/extModules/geohasher.js +0 -0
  98. /package/{lib → dist}/src/extModules/log.js +0 -0
  99. /package/{lib → dist}/src/historyManager.js +0 -0
  100. /package/{lib → dist}/src/utils/bounds.js +0 -0
  101. /package/{lib → dist}/src/utils/buildStructureLookup.js +0 -0
  102. /package/{lib → dist}/src/utils/configUtils.js +0 -0
  103. /package/{lib → dist}/src/utils/dom.js +0 -0
  104. /package/{lib → dist}/src/utils/funcs.js +0 -0
  105. /package/{lib → dist}/src/utils/geodesy.js +0 -0
  106. /package/{lib → dist}/src/utils/geom.js +0 -0
  107. /package/{lib → dist}/src/utils/i18n.js +0 -0
  108. /package/{lib → dist}/src/utils/observable.js +0 -0
  109. /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 e = require('ramda');
6
- var a = require('zousan');
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
- 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);
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 e__namespace = /*#__PURE__*/_interopNamespace(e);
35
- var a__default = /*#__PURE__*/_interopDefaultLegacy(a);
34
+ var R__namespace = /*#__PURE__*/_interopNamespace(R);
35
+ var Zousan__default = /*#__PURE__*/_interopDefaultLegacy(Zousan);
36
36
 
37
- const u={SECURITY:"SecurityLane",IMMIGRATION:"ImmigrationLane"};function d(d,l){const p=d.log.sublog("wayfinder"),c=async()=>{d.bus.send("venueData/loadNavGraph");};let f=new a__default["default"];d.bus.on("wayfinder/_getNavGraph",(()=>f)),d.bus.on("venueData/navGraphLoaded",(async({navGraphData:t,structures:n})=>{const e=buildStructureLookup.buildStructuresLookup(n),i=await y(),a=navGraph.createNavGraph(t,e.floorIdToOrdinal,e.floorIdToStructureId,i);f.resolve(a);}));const y=async()=>{const n=await d.bus.get("poi/getByCategoryId",{categoryId:"security"});return e__namespace.pipe(e__namespace.map(m),e__namespace.filter(e__namespace.identity))(n)},m=n=>n.queue&&{type:e__namespace.path(["queue","queueType"],n),id:e__namespace.path(["queue","queueSubtype"],n)};d.bus.on("wayfinder/showNavLineFromPhysicalLocation",(async({toEndpoint:t,selectedSecurityLanes:n=null,requiresAccessibility:o})=>async function(t,n,o){const e=await T({fromEndpoint:t,toEndpoint:n,options:o});if(e){const{segments:t}=e;o.primary&&d.bus.send("map/resetNavlineFeatures"),d.bus.send("map/showNavlineFeatures",{segments:t,category:o.primary?"primary":"alternative"});}return e}(await d.bus.get("user/getPhysicalLocation"),t,{selectedSecurityLanes:n,requiresAccessibility:o,primary:!0})));const h=(t,n)=>d.bus.get("poi/getById",{id:t}).then((o=>{if(o&&o.position)return w(o,n);throw Error("Unknown POI ID "+t)}));const I=["lat","lng","floorId","ordinal"],g=e__namespace.pipe(e__namespace.pick(I),e__namespace.keys,e__namespace.propEq("length",I.length),Boolean),w=(t,n)=>({lat:t.position.latitude,lng:t.position.longitude,floorId:t.position.floorId,ordinal:n(t.position.floorId),title:t.name});async function T({fromEndpoint:t,toEndpoint:n,options:o={}}){return f.then((async e=>{o.compareFindPaths=l.compareFindPaths;const r=findRoute.findRoute(e,t,n,o);if(!r)return null;t.floorId&&n.floorId&&b(t,n,r);const a=await d.bus.get("venueData/getFloorIdToNameMap"),u=await d.bus.get("venueData/getQueueTypes"),c=d.gt();o.requiresAccessibility;const{steps:f,segments:y}=segmentBuilder.buildSegments(r.waypoints,t,n,a,c,u);p.info("route",r);const m=Math.round(r.waypoints.reduce(((t,{eta:n})=>t+n),0)),h=Math.round(r.waypoints.reduce(((t,{distance:n})=>t+n),0));return {...r,segments:y,steps:f,time:m,distance:h}}))}d.bus.on("wayfinder/getNavigationEndpoint",(({ep:t})=>async function(t){return f.then((n=>{if(!t)throw Error("wayfinder: Invalid endpoint definition",t);if("number"==typeof t)return h(t,n.floorIdToOrdinal);if("string"==typeof t){if(t.match(/^\d+$/))return h(parseInt(t),n.floorIdToOrdinal);if(t.indexOf(",")>0){let[o,e,i,r]=t.split(",");if(!n.floorIdToStructureId(i))throw Error("Unknown floorId in endpoint: "+i);return r||(r="Starting Point"),{lat:parseFloat(o),lng:parseFloat(e),ordinal:n.floorIdToOrdinal(i),floorId:i,title:r}}}if(g(t))return t;if(t.latitude)return {lat:t.latitude,lng:t.longitude,floorId:t.floorId,ordinal:n.floorIdToOrdinal(t.floorId),title:t.title};if(t.position&&t.name)return w(t,n.floorIdToOrdinal);throw Error("Invalid start or end point: "+t)}))}(t))),d.bus.on("wayfinder/checkIfPathHasSecurity",(({fromEndpoint:n,toEndpoint:o,options:e={}})=>f.then((r=>{e.compareFindPaths=l.compareFindPaths;const a=findRoute.findRoute(r,n,o,e);if(!a)return {routeExists:!1};const s=n=>Boolean(a.waypoints.find(e__namespace.pathEq(["securityLane","type"],n)));return {routeExists:!0,queues:a.waypoints.filter((n=>e__namespace.pathEq(["securityLane","type"],u.SECURITY,n)||e__namespace.pathEq(["securityLane","type"],u.IMMIGRATION,n))),hasSecurity:s(u.SECURITY),hasImmigration:s(u.IMMIGRATION)}})))),d.bus.on("wayfinder/getRoute",T);const b=(t,n,o)=>d.bus.send("session/submitEvent",{type:"navigation",startPosition:{venueId:t.floorId.split("-")[0],buildingId:o.waypoints[0].position.structureId,floorId:o.waypoints[0].position.floorId,lat:o.waypoints[0].position.lat,lng:o.waypoints[0].position.lng},endPosition:{venueId:n.floorId.split("-")[0],buildingId:o.waypoints[o.waypoints.length-1].position.structureId,floorId:o.waypoints[o.waypoints.length-1].position.floorId,lat:o.waypoints[o.waypoints.length-1].position.lat,lng:o.waypoints[o.waypoints.length-1].position.lng}});function v(n,o,e,i){let r=e__namespace.clone(n);return r=E(r,e,i),o&&o.length?{...r,transitTime:S(o,"transitTime"),distance:S(o,"distance")}:(r.distance="start"===i?P(r,e):P(e,r),r.transitTime=L(r.distance),r)}function S(n,o){return e__namespace.aperture(2,n).map((([n,o])=>{return (e=o.id,n=>e__namespace.find((t=>t.dst===e),n.edges))(n);var e;})).map(e__namespace.prop(o)).reduce(((t,n)=>t+n),0)}function E(t,n,o){return {...t,[o+"Information"]:{lat:n?.lat||n?.position?.latitude,lng:n?.lng||n?.position?.longitude,floorId:n?.floorId||n?.position?.floorId}}}function P(t,n){return geodesy.distance(n?.lat||n?.position?.latitude,n?.lng||n?.position?.longitude,t?.lat||t?.position?.latitude,t?.lng||t?.position?.longitude)}function L(t){return t/60}function O(n){const o=n.filter((t=>null!==t));return e__namespace.sortBy(e__namespace.propOr(1/0,"transitTime"),o)}function q(n,o,e,i,r){const a=M(o,i,n),s=M(e,n,r);if(!a||!s)return null;const u=N(o,a),d=N(e,s);let l=e__namespace.clone(n);return l=E(l,i,"start"),l=E(l,r,"end"),{...l,transitTime:u+d,distance:a+s,startInformation:{...l.startInformation,transitTime:u,distance:a},endInformation:{...l.endInformation,transitTime:d,distance:s}}}function N(t,n){return t&&t.length?S(t,"transitTime"):L(n)}function M(t,n,o){return t&&t.length?S(t,"distance"):P(o,n)}return d.bus.on("wayfinder/addPathTimeSingle",(async({poi:t,startLocation:n,options:o={}})=>n?f.then((e=>function(t,n,o,e){const i=w(o,t.floorIdToOrdinal),r=t.findShortestPath(e,i,n);return v(o,r,e,"start")}(e,o,t,n))):t)),d.bus.on("wayfinder/addPathTimeMultiple",(async({pois:n,startLocation:o,options:e={}})=>o?f.then((i=>function(n,o,e,i){try{const r=e__namespace.clone(e),a=r.map((t=>w(t,n.floorIdToOrdinal))),s=n.findAllShortestPaths(i,a,o);return O(r.map(((t,n)=>v(t,s[n],i,"start"))))}catch(t){return p.error(t),e}}(i,e,n,o))):n)),d.bus.on("wayfinder/multipointAddPathTimeMultiple",(async({pois:n,startLocation:o,endLocation:e,options:i={}})=>o||e?f.then((r=>function(n,o,e,i,r){try{const a=e__namespace.clone(e),s=a.map((t=>w(t,n.floorIdToOrdinal)));let u,d,l;return i&&(u=n.findAllShortestPaths(i,s,o)),r&&(d=function(t,n,o,e){const i=[];for(const r of n)i.push(t.findShortestPath(r,o,e));return i}(n,s,r,o)),l=i&&r?a.map(((t,n)=>q(t,u[n],d[n],i,r))):i?a.map(((t,n)=>v(t,u[n],i,"start"))):a.map(((t,n)=>v(t,d[n],r,"end"))),O(l)}catch(t){return p.error(t),e}}(r,i,n,o,e))):n)),d.bus.on("wayfinder/multipointAddPathTimeSingle",(async({poi:t,startLocation:n,endLocation:o,options:e={}})=>n||o?f.then((i=>function(t,n,o,e,i){const r=w(o,t.floorIdToOrdinal);let a,s;e&&(a=t.findShortestPath(e,r,n));i&&(s=t.findShortestPath(r,i,n));return e&&i?q(o,a,s,e,i):e?v(o,a,e,"start"):i?v(o,s,i,"end"):o}(i,e,t,n,o))):t)),d.bus.on("venueData/loadNewVenue",(()=>{f=new a__default["default"],c();})),d.bus.on("poi/setDynamicData",(({plugin:t,idValuesMap:n})=>{"security"===t&&f.then((t=>t.updateWithSecurityWaitTime(n)));})),d.bus.on("wayfinder/getNavGraphFeatures",(()=>f.then((({_nodes:t})=>navGraphDebug.enrichDebugNavGraph(t))))),{init:c,internal:{resolveNavGraph:t=>f.resolve(t),prepareSecurityLanes:y}}}
37
+ const DEFAULT_WALKING_SPEED_M_PER_MIN = 60;
38
38
 
39
- exports.SecurityLaneType = u;
40
- exports.create = d;
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;