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.
- 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 -14
- 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 -21
- 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 -3
- package/dist/cjs/src/utils/geodesy.js +35 -3
- package/dist/cjs/src/utils/geom.js +209 -27
- 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/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/src/app.js +1 -0
- package/package.json +13 -9
- package/.yarnrc.yml +0 -1
- package/config/rollup.config.cjs.js +0 -31
- package/dist/cjs/deploy/nodeEntry.js +0 -20
- 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/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/src/app.js +0 -1
- package/lib/src/configs/sdkHeadless.json +0 -28
- /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/dynamicPois/src/dynamicPois.js +0 -0
- /package/{lib → dist}/plugins/poiDataManager/src/poiDataManager.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/sdkHeadless.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/sdkServer.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/util.js +0 -0
- /package/{lib → dist}/plugins/searchService/src/poiSearch.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/navGraph.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/segmentBuilder.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/segmentCategories.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/stepBuilder.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/wayfinder.js +0 -0
- /package/{lib → dist}/src/configs/postproc-mol-url-parms.js +0 -0
- /package/{lib → dist}/src/configs/postproc-stateTracking.js +0 -0
- /package/{lib → dist}/src/configs/sdkHeadless.json.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/bustle.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/extModules/log.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/funcs.js +0 -0
- /package/{lib → dist}/src/utils/geodesy.js +0 -0
- /package/{lib → dist}/src/utils/geom.js +0 -0
- /package/{lib → dist}/src/utils/i18n.js +0 -0
- /package/{lib → dist}/src/utils/observable.js +0 -0
- /package/{lib → dist}/src/utils/rand.js +0 -0
|
@@ -2,32 +2,229 @@
|
|
|
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
|
|
|
8
8
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
9
|
|
|
10
10
|
function _interopNamespace(e) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
if (e && e.__esModule) return e;
|
|
12
|
+
var n = Object.create(null);
|
|
13
|
+
if (e) {
|
|
14
|
+
Object.keys(e).forEach(function (k) {
|
|
15
|
+
if (k !== 'default') {
|
|
16
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function () { return e[k]; }
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
n["default"] = e;
|
|
25
|
+
return Object.freeze(n);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
var
|
|
29
|
-
var
|
|
28
|
+
var R__namespace = /*#__PURE__*/_interopNamespace(R);
|
|
29
|
+
var Zousan__default = /*#__PURE__*/_interopDefaultLegacy(Zousan);
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
/*
|
|
32
|
+
This service obtains dynamic POI data from our own backend REST API service.
|
|
33
|
+
Currently it drives dynamic data for Security Wait Times and Parking Status.
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
Configuration Properties Recognized:
|
|
36
|
+
urlBase : to override the REST url base. i.e. for alpha use 'https://rest-alpha.locuslabs.com/v1'. You can also reference
|
|
37
|
+
a local file, such as './testDynamicPois.json'
|
|
38
|
+
|
|
39
|
+
Values defined by 'parking':
|
|
40
|
+
lotName: Name of the lot for this POI, such as 'East'
|
|
41
|
+
lotStatus: returns either 'Closed' or 'Open'
|
|
42
|
+
timeIsReal: If true, the time here is live and valid, else its a default fallback
|
|
43
|
+
rateDay: Daily Rate expressed in English: '$17 per day'
|
|
44
|
+
rateHour: Hourly Rate expressed in English: '$5 per hour'
|
|
45
|
+
timeToTerminal1: Time in walking or by shuttle to Terminal 1 : 'Shuttle 5-7'
|
|
46
|
+
timeToTerminal2: Time in nwalking or by shuttle to Terminal 2 : 'Walking 5-10'
|
|
47
|
+
lastUpdated: timestamp of last update (as sent by server)
|
|
48
|
+
|
|
49
|
+
Values defined by 'security'
|
|
50
|
+
queueTime: Estimated Time in queue (in minutes) : i.e. 45
|
|
51
|
+
isTemporarilyClosed: If true, this line is closed - else it is open
|
|
52
|
+
timeIsReal: If true, the time here is live and valid, else its a default fallback
|
|
53
|
+
lastUpdated: timestamp of last update (as sent by server)
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
const REFRESH_FREQUENCY = 1000 * 30; // every 30 seconds
|
|
57
|
+
|
|
58
|
+
function create (app, config) {
|
|
59
|
+
let dataLoadedProm = new Zousan__default["default"]();
|
|
60
|
+
const dynamicDataNotPending = new Zousan__default["default"]();
|
|
61
|
+
|
|
62
|
+
const init = async () => {
|
|
63
|
+
const urlBaseNew = config.urlBase || 'https://rest.locuslabs.com/v3';
|
|
64
|
+
const urlBase = config.urlBaseV1 || config.urlBase || 'https://rest.locuslabs.com/v1';
|
|
65
|
+
const accountId = app.config.plugins.venueDataLoader.accountId;
|
|
66
|
+
|
|
67
|
+
async function getURL () {
|
|
68
|
+
return dataLoadedProm
|
|
69
|
+
.then(venueData => {
|
|
70
|
+
let url = `${urlBase}/venue/${venueData.id}/account/${accountId}/get-all-dynamic-pois/`;
|
|
71
|
+
if (urlBase.startsWith('./') || urlBase.endsWith('.json'))
|
|
72
|
+
url = urlBase;
|
|
73
|
+
return url
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/*
|
|
78
|
+
API URL: https://gitlab.com/locuslabs/core-data-team/rest-api/-/blob/develop/v3/docs/REST%20API%20v3.postman_collection.json
|
|
79
|
+
*/
|
|
80
|
+
const getWaitTimesUrl = async () => dataLoadedProm.then(venueData =>
|
|
81
|
+
(urlBaseNew.startsWith('./') || urlBaseNew.endsWith('.json'))
|
|
82
|
+
? urlBaseNew
|
|
83
|
+
: `${urlBaseNew}/venueId/${venueData.id}/accountId/${accountId}/get-dynamic-queue-times/`);
|
|
84
|
+
|
|
85
|
+
const updateFromAPI = async () => {
|
|
86
|
+
Promise.all([
|
|
87
|
+
getURL()
|
|
88
|
+
.then(fetch)
|
|
89
|
+
.then(r => r.json())
|
|
90
|
+
.then(poiMap => processDynamicPois(Date.now(), poiMap)),
|
|
91
|
+
getWaitTimesUrl()
|
|
92
|
+
.then(fetch)
|
|
93
|
+
.then(r => r.json())
|
|
94
|
+
.then(waitTimes => processSecurityWaitTimes(Date.now(), waitTimes))
|
|
95
|
+
]).then(() => dynamicDataNotPending.resolve(true))
|
|
96
|
+
.catch(err => {
|
|
97
|
+
console.error(err);
|
|
98
|
+
dynamicDataNotPending.resolve(true);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Currently, the only way to know if a venue has dynamic POIs is if they have security wait times
|
|
103
|
+
// and the only way we know that is if they have queueTypes.
|
|
104
|
+
// I know this sounds "fragile" - but Jessica said it is our current truth.
|
|
105
|
+
// This will certainly need to change at some point.
|
|
106
|
+
const queueTypes = await app.bus.get('venueData/getQueueTypes');
|
|
107
|
+
if (queueTypes.SecurityLane && queueTypes.SecurityLane.length) {
|
|
108
|
+
dataLoadedProm
|
|
109
|
+
.then(updateFromAPI)
|
|
110
|
+
.then(() => setInterval(updateFromAPI, REFRESH_FREQUENCY));
|
|
111
|
+
} else
|
|
112
|
+
dynamicDataNotPending.resolve(true); // no need to wait for this since there is no dynamic data
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
function processDynamicPois (...args) {
|
|
116
|
+
processParkingPOIS(...args);
|
|
117
|
+
processOpenClosedPois(...args);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function processParkingPOIS (timeNowMs, poiMap) {
|
|
121
|
+
const idValuesMap =
|
|
122
|
+
R__namespace.pipe(
|
|
123
|
+
R__namespace.filter(poi => poi.category === 'parking'),
|
|
124
|
+
R__namespace.map(poi => {
|
|
125
|
+
const da = poi.dynamicAttributes;
|
|
126
|
+
if (!da)
|
|
127
|
+
throw Error(`No dynamicAttributes defined for parking POI ${poi.poiId}`)
|
|
128
|
+
const age = (timeNowMs - poi.timestamp) / 1000; // how long ago this was updated by backend (in seconds)
|
|
129
|
+
const props = (age < da['parking.timeToLive']) // if this update is recent enough, consider it "valid"
|
|
130
|
+
? R__namespace.pick(['lotStatus', 'rateDay', 'rateHour', 'timeIsReal', 'timeToTerminal1', 'timeToTerminal2'], poi)
|
|
131
|
+
: { lotStatus: da['parking.default'], rateDay: '$ -', rateHour: '$ -', timeIsReal: false };
|
|
132
|
+
|
|
133
|
+
return { ...props, lastUpdated: poi.timestamp, lotName: poi.lotName }
|
|
134
|
+
}))(poiMap);
|
|
135
|
+
|
|
136
|
+
app.bus.send('poi/setDynamicData', { plugin: 'parking', idValuesMap });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const getPOILabels = async idArray => {
|
|
140
|
+
const nameMap = { };
|
|
141
|
+
for (const poiId of idArray) {
|
|
142
|
+
const poi = await app.bus.get('poi/getById', { id: poiId });
|
|
143
|
+
if (poi)
|
|
144
|
+
nameMap[poiId] = poi.name;
|
|
145
|
+
}
|
|
146
|
+
return nameMap
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
*
|
|
151
|
+
* @param {Record<Number, DynamicQueueTime} queueTimes A map of POI Ids to dynamic queue times
|
|
152
|
+
* @param {Record<Number, String>} labels A map of POI Ids to map labels
|
|
153
|
+
* @param {*} feature A GeoJson feature
|
|
154
|
+
* @returns feature
|
|
155
|
+
*/
|
|
156
|
+
const mutateSecurityCheckpointLabel = (queueTimes, labels) => feature => {
|
|
157
|
+
const id = feature.properties.id;
|
|
158
|
+
const dynamicData = queueTimes[id];
|
|
159
|
+
const label = labels[id];
|
|
160
|
+
if (dynamicData) { // should we only show this message when "timeIsReal" is true?
|
|
161
|
+
const { queueTime, isTemporarilyClosed } = dynamicData;
|
|
162
|
+
const secondaryText = isTemporarilyClosed ? '(closed)' : `(${queueTime} minute wait)`;
|
|
163
|
+
feature.properties.text = `${label}\n${secondaryText}`;
|
|
164
|
+
}
|
|
165
|
+
return feature
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/*
|
|
169
|
+
API response: https://gitlab.com/locuslabs/core-data-team/json-schemas/-/blob/develop/src/api-marketplace/dynamic-queue-data.json
|
|
170
|
+
*/
|
|
171
|
+
async function processSecurityWaitTimes (timeNowMs, waitTimes) {
|
|
172
|
+
const idValuesMap = R__namespace.pipe(
|
|
173
|
+
R__namespace.map(waitTime => [waitTime.poiId, toDynamicWaitTime(timeNowMs, waitTime)]),
|
|
174
|
+
R__namespace.fromPairs
|
|
175
|
+
)(waitTimes);
|
|
176
|
+
|
|
177
|
+
app.bus.send('poi/setDynamicData', { plugin: 'security', idValuesMap });
|
|
178
|
+
|
|
179
|
+
const labels = await getPOILabels(Object.keys(idValuesMap)); // get a map of labels for the POIs - used in wait time labeling
|
|
180
|
+
|
|
181
|
+
app.bus.send('map/mutateFeature', {
|
|
182
|
+
functor: mutateSecurityCheckpointLabel(idValuesMap, labels)
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const toDynamicWaitTime = (timeNowMs, waitTime) => ({
|
|
187
|
+
queueTime: waitTime.queueTime,
|
|
188
|
+
isTemporarilyClosed: waitTime.isTemporarilyClosed,
|
|
189
|
+
timeIsReal: !waitTime.isQueueTimeDefault && waitTime.expiration > timeNowMs,
|
|
190
|
+
lastUpdated: timeNowMs
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
function processOpenClosedPois (timeNowMs, poiMap) {
|
|
194
|
+
const pathToOpenClosedData = ['dynamicData', 'openClosed'];
|
|
195
|
+
const openClosedPois = R__namespace.filter(R__namespace.hasPath(pathToOpenClosedData), poiMap);
|
|
196
|
+
const openClosedStatuses = R__namespace.map(R__namespace.path(pathToOpenClosedData), openClosedPois);
|
|
197
|
+
|
|
198
|
+
if (R__namespace.all(R__namespace.both(R__namespace.has('isOpen'), R__namespace.has('expiration')), R__namespace.values(openClosedStatuses))) {
|
|
199
|
+
const isExpired = R__namespace.pipe(R__namespace.prop('expiration'), R__namespace.lt(timeNowMs));
|
|
200
|
+
const idValuesMap = R__namespace.filter(isExpired, openClosedStatuses);
|
|
201
|
+
|
|
202
|
+
app.bus.send('poi/setDynamicData', { plugin: 'open-closed-status', idValuesMap });
|
|
203
|
+
} else {
|
|
204
|
+
throw Error('Open Closed poi status is malformed.')
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
app.bus.on('venueData/venueDataLoaded', ({ venueData }) => {
|
|
209
|
+
if (dataLoadedProm.v) // non-standard - indicates promise has been resolved...
|
|
210
|
+
dataLoadedProm = Zousan__default["default"].resolve(venueData);
|
|
211
|
+
else
|
|
212
|
+
dataLoadedProm.resolve(venueData);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// by returning this dynamicDataLoaded promise, we hold sdkReady event until this is resolved
|
|
216
|
+
app.bus.on('system/readywhenyouare', () => dynamicDataNotPending);
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
init,
|
|
220
|
+
internal: {
|
|
221
|
+
mutateSecurityCheckpointLabel,
|
|
222
|
+
processSecurityWaitTimes,
|
|
223
|
+
processParkingPOIS,
|
|
224
|
+
processOpenClosedPois,
|
|
225
|
+
processDynamicPois
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
exports.create = create;
|
|
@@ -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 configUtils = require('../../../src/utils/configUtils.js');
|
|
9
9
|
var i18n = require('../../../src/utils/i18n.js');
|
|
@@ -11,26 +11,297 @@ var i18n = require('../../../src/utils/i18n.js');
|
|
|
11
11
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
12
12
|
|
|
13
13
|
function _interopNamespace(e) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
if (e && e.__esModule) return e;
|
|
15
|
+
var n = Object.create(null);
|
|
16
|
+
if (e) {
|
|
17
|
+
Object.keys(e).forEach(function (k) {
|
|
18
|
+
if (k !== 'default') {
|
|
19
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
20
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return e[k]; }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
n["default"] = e;
|
|
28
|
+
return Object.freeze(n);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
var
|
|
32
|
-
var
|
|
31
|
+
var R__namespace = /*#__PURE__*/_interopNamespace(R);
|
|
32
|
+
var Zousan__default = /*#__PURE__*/_interopDefaultLegacy(Zousan);
|
|
33
33
|
|
|
34
|
-
async function
|
|
34
|
+
async function create (app, config) {
|
|
35
|
+
const log = app.log.sublog('poiDataManager');
|
|
36
|
+
const init = () => {
|
|
37
|
+
app.bus.send('venueData/loadPoiData');
|
|
38
|
+
};
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
let poisLoaded = new Zousan__default["default"]();
|
|
41
|
+
|
|
42
|
+
const fixPositionInfo = (poi, structuresLookup) => {
|
|
43
|
+
const { position } = poi;
|
|
44
|
+
const structure = structuresLookup.floorIdToStructure(position.floorId);
|
|
45
|
+
if (!structure) {
|
|
46
|
+
log.error(`No structure found for floorId: ${position.floorId} for POI ${poi.poiId}`);
|
|
47
|
+
return { ...poi }
|
|
48
|
+
}
|
|
49
|
+
const floor = structuresLookup.floorIdToFloor(position.floorId);
|
|
50
|
+
const detailedPosition = {
|
|
51
|
+
...position,
|
|
52
|
+
structureName: structure.name,
|
|
53
|
+
buildingId: structure.id,
|
|
54
|
+
floorName: floor.name,
|
|
55
|
+
floorOrdinal: floor.ordinal
|
|
56
|
+
};
|
|
57
|
+
return { ...poi, position: detailedPosition }
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// todo R.map may be enough to update dictionary values
|
|
61
|
+
const formatPois = (pois, structuresLookup) => {
|
|
62
|
+
return R__namespace.pipe(
|
|
63
|
+
R__namespace.values,
|
|
64
|
+
R__namespace.map(poi => {
|
|
65
|
+
poi.distance = null;
|
|
66
|
+
poi.isNavigable = poi.isNavigable === undefined || poi.isNavigable === true; // isNavigable is true as default, and is optional in the POI data
|
|
67
|
+
// poi.isNavigable = /^[a-mA-M]+/.test(poi.name) // uncomment for easy testing of isNavigable
|
|
68
|
+
if (poi.capacity)
|
|
69
|
+
addToRoomInfo(poi, { name: `Seats ${poi.capacity.join('-')}`, svgId: 'number-of-seats' });
|
|
70
|
+
if (poi.category.startsWith('meeting'))
|
|
71
|
+
addToRoomInfo(poi, { name: app.gt()('poiView:Conference Room'), svgId: 'conference-room' });
|
|
72
|
+
|
|
73
|
+
const roomId = getRoomId(poi);
|
|
74
|
+
if (roomId)
|
|
75
|
+
poi.roomId = roomId;
|
|
76
|
+
|
|
77
|
+
return [poi.poiId, fixPositionInfo(poi, structuresLookup)]
|
|
78
|
+
}),
|
|
79
|
+
R__namespace.fromPairs
|
|
80
|
+
)(pois)
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const addToRoomInfo = (poi, value) => {
|
|
84
|
+
if (!poi.roomInfo) {
|
|
85
|
+
poi.roomInfo = [];
|
|
86
|
+
}
|
|
87
|
+
poi.roomInfo.push(value);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const getRoomId = R__namespace.pipe(
|
|
91
|
+
R__namespace.propOr([], 'externalIds'),
|
|
92
|
+
R__namespace.find(R__namespace.propEq('type', 'roomId')),
|
|
93
|
+
R__namespace.prop('id'),
|
|
94
|
+
R__namespace.unless(R__namespace.isNil, R__namespace.tail)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
async function checkNavgraph (pois) {
|
|
98
|
+
const start = Date.now();
|
|
99
|
+
const badPois = [];
|
|
100
|
+
const navGraph = await app.bus.get('wayfinder/_getNavGraph');
|
|
101
|
+
Object.values(pois).forEach(poi => {
|
|
102
|
+
try {
|
|
103
|
+
const pos = poi.position;
|
|
104
|
+
const n = navGraph.findClosestNode(pos.floorId, pos.latitude, pos.longitude);
|
|
105
|
+
if (!n)
|
|
106
|
+
badPois.push({ id: poi.poiId, e: 'No closest Navgraph Node' });
|
|
107
|
+
} catch (e) {
|
|
108
|
+
log.error(e);
|
|
109
|
+
badPois.push({ id: poi.poiId, e: e.message });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
if (badPois.length)
|
|
114
|
+
log.warn('badPois:', badPois);
|
|
115
|
+
|
|
116
|
+
log(`Total time for navgraph POI check: ${Date.now() - start}ms`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function filterBadPois (pois) {
|
|
120
|
+
const badPois = [];
|
|
121
|
+
Object.values(pois).forEach(poi => {
|
|
122
|
+
try {
|
|
123
|
+
const pos = poi.position;
|
|
124
|
+
if (!pos)
|
|
125
|
+
badPois.push({ poi, e: 'No position information' });
|
|
126
|
+
else {
|
|
127
|
+
;['buildingId', 'structureName', 'floorId', 'floorName', 'floorOrdinal', 'latitude', 'longitude'].forEach(k => {
|
|
128
|
+
if (pos[k] === null || pos[k] === undefined)
|
|
129
|
+
badPois.push({ id: poi.poiId, e: `invalid position property: ${k}: ${pos[k]}` });
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
} catch (e) {
|
|
133
|
+
log.error(e);
|
|
134
|
+
badPois.push({ id: poi.poiId, e: e.message });
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (badPois.length) {
|
|
139
|
+
log.warn('badPois:', badPois);
|
|
140
|
+
badPois.forEach(ob => { delete pois[ob.id]; });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return pois
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function enhanceImages (pois) {
|
|
147
|
+
for (const poi of Object.values(pois))
|
|
148
|
+
await addImages(poi);
|
|
149
|
+
|
|
150
|
+
return pois
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
app.bus.on('venueData/poiDataLoaded', async ({ pois, structures }) => {
|
|
154
|
+
const structuresLookup = buildStructureLookup.buildStructuresLookup(structures);
|
|
155
|
+
pois = formatPois(pois, structuresLookup);
|
|
156
|
+
if (configUtils.debugIsTrue(app, 'pseudoTransPois'))
|
|
157
|
+
for (const id in pois)
|
|
158
|
+
pois[id] = pseudoTransPoi(pois[id], app.i18n().language);
|
|
159
|
+
|
|
160
|
+
pois = filterBadPois(pois);
|
|
161
|
+
|
|
162
|
+
await enhanceImages(pois);
|
|
163
|
+
poisLoaded.resolve(pois);
|
|
164
|
+
|
|
165
|
+
if (app.config.debug && app.env.isBrowser)
|
|
166
|
+
window._pois = pois;
|
|
167
|
+
|
|
168
|
+
if (app.config.debug)
|
|
169
|
+
checkNavgraph(pois); // this doesn't change the pois, but warns in the console...
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
app.bus.on('poi/getById', async ({ id }) => {
|
|
173
|
+
return poisLoaded.then(pois => pois[id])
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
app.bus.on('poi/getByFloorId', async ({ floorId }) => poisLoaded.then(
|
|
177
|
+
R__namespace.pickBy(R__namespace.pathEq(['position', 'floorId'], floorId))));
|
|
178
|
+
|
|
179
|
+
app.bus.on('poi/getByCategoryId', async ({ categoryId }) => {
|
|
180
|
+
// returns true for exact category matches or parent category matches
|
|
181
|
+
const categoryMatch = (poi) => poi.category === categoryId || poi.category.startsWith(categoryId + '.');
|
|
182
|
+
return poisLoaded.then(R__namespace.pickBy(categoryMatch))
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
app.bus.on('poi/getAll', async () => poisLoaded);
|
|
186
|
+
|
|
187
|
+
const checkpointPath = ['queue', 'primaryQueueId'];
|
|
188
|
+
const addOtherSecurityLanesIfNeeded = async poi => {
|
|
189
|
+
const primaryCheckpointId = R__namespace.path(checkpointPath, poi);
|
|
190
|
+
|
|
191
|
+
if (!primaryCheckpointId) return poi
|
|
192
|
+
|
|
193
|
+
const queueTypes = await app.bus.get('venueData/getQueueTypes');
|
|
194
|
+
const securityPoisMap = await app.bus.get('poi/getByCategoryId', { categoryId: 'security' });
|
|
195
|
+
const securityPoisList = Object.values(securityPoisMap);
|
|
196
|
+
|
|
197
|
+
poi.queue.otherQueues = prepareOtherSecurityLanes(queueTypes, poi, securityPoisList);
|
|
198
|
+
return poi
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const prepareOtherSecurityLanes = (queueTypes, currentPoi, securityPois) => {
|
|
202
|
+
const queueTypePath = ['queue', 'queueType'];
|
|
203
|
+
const queueType = R__namespace.path(queueTypePath, currentPoi);
|
|
204
|
+
if (!queueType)
|
|
205
|
+
return null
|
|
206
|
+
|
|
207
|
+
const queueSubtypes = queueTypes[queueType];
|
|
208
|
+
const primaryCheckpointId = R__namespace.path(checkpointPath, currentPoi);
|
|
209
|
+
return securityPois
|
|
210
|
+
.filter(R__namespace.pathEq(checkpointPath, primaryCheckpointId)) // filter only connected security checkpoints
|
|
211
|
+
.filter(poi => poi.poiId !== currentPoi.poiId) // skip current poi
|
|
212
|
+
.map(poi => {
|
|
213
|
+
const laneId = R__namespace.path(['queue', 'queueSubtype'], poi);
|
|
214
|
+
const lane = getLaneData(laneId)(queueSubtypes);
|
|
215
|
+
return { poiId: poi.poiId, ...lane }
|
|
216
|
+
})
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// if the value passed is non-null, simply return it. Else throw the error with the message specified.
|
|
220
|
+
// This is useful to insert into pipelines.
|
|
221
|
+
const ensureDefined = errorMsg => value => {
|
|
222
|
+
if (value != null)
|
|
223
|
+
return value
|
|
224
|
+
throw Error(errorMsg)
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const getLaneData = laneId => R__namespace.pipe(
|
|
228
|
+
R__namespace.find(R__namespace.propEq('id', laneId)),
|
|
229
|
+
ensureDefined(`No queue found with ID: ${laneId}`),
|
|
230
|
+
R__namespace.pick(['displayText', 'imageId'])
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Updates security checkpoint POI with a list of related security checkpoints.
|
|
235
|
+
*/
|
|
236
|
+
app.bus.on('poi/addOtherSecurityLanes', ({ poi }) => addOtherSecurityLanesIfNeeded(poi));
|
|
237
|
+
|
|
238
|
+
async function addImages (poi) {
|
|
239
|
+
if (!poi) return
|
|
240
|
+
const dpr = typeof window === 'undefined' ? 1 : (window.devicePixelRatio || 1);
|
|
241
|
+
if (!R__namespace.length(poi.images)) {
|
|
242
|
+
poi.images = [];
|
|
243
|
+
} else if (!poi.images[0].startsWith('https:')) { // then images are not yet transformed
|
|
244
|
+
poi.images = await Zousan__default["default"].all(
|
|
245
|
+
poi.images.map(imageName =>
|
|
246
|
+
app.bus.get('venueData/getPoiImageUrl', { imageName, size: `${Math.round(351 * dpr)}x${Math.round(197 * dpr)}` })));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return poi
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const getUniqueCategories = R__namespace.memoizeWith(R__namespace.identity, R__namespace.pipe(R__namespace.pluck('category'), R__namespace.values, R__namespace.uniq));
|
|
253
|
+
app.bus.on('poi/getAllCategories', async () => poisLoaded.then(getUniqueCategories));
|
|
254
|
+
|
|
255
|
+
app.bus.on('venueData/loadNewVenue', () => {
|
|
256
|
+
poisLoaded = new Zousan__default["default"]();
|
|
257
|
+
init();
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// See architectural document at https://docs.google.com/document/d/1NoBAboHR9BiX_vvLef-vp3ButrIQDWYofcTsdilEWvs/edit#
|
|
261
|
+
app.bus.on('poi/setDynamicData', ({ plugin, idValuesMap }) => {
|
|
262
|
+
poisLoaded
|
|
263
|
+
.then(pois => {
|
|
264
|
+
for (const poiId in idValuesMap) {
|
|
265
|
+
// const dd = { [plugin]: idValuesMap[poiId] }
|
|
266
|
+
const dynamicData = pois[poiId].dynamicData || {};
|
|
267
|
+
dynamicData[plugin] = { ...idValuesMap[poiId] };
|
|
268
|
+
const newPoi = R__namespace.mergeRight(pois[poiId], { dynamicData });
|
|
269
|
+
pois[poiId] = newPoi;
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const runTest = async (testRoutine) => {
|
|
275
|
+
await testRoutine();
|
|
276
|
+
return poisLoaded
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
init,
|
|
281
|
+
runTest,
|
|
282
|
+
internal: {
|
|
283
|
+
addImages,
|
|
284
|
+
pseudoTransPoi
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function pseudoTransPoi (poi, lang) {
|
|
290
|
+
['description', 'nearbyLandmark', 'name', 'phone', 'operationHours']
|
|
291
|
+
.forEach(p => {
|
|
292
|
+
if (poi[p])
|
|
293
|
+
poi[p] = i18n.toLang(poi[p], lang);
|
|
294
|
+
});
|
|
295
|
+
if (poi.keywords)
|
|
296
|
+
poi.keywords = poi.keywords.map(keyword => {
|
|
297
|
+
keyword.name = i18n.toLang(keyword.name, lang);
|
|
298
|
+
return keyword
|
|
299
|
+
});
|
|
300
|
+
if (poi.position.floorName)
|
|
301
|
+
poi.position.floorName = i18n.toLang(poi.position.floorName, lang);
|
|
302
|
+
if (poi.position.structureName)
|
|
303
|
+
poi.position.structureName = i18n.toLang(poi.position.structureName, lang);
|
|
304
|
+
return poi
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
exports.create = create;
|