@flowmap.gl/data 8.0.0-alpha.0
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/LICENSE +199 -0
- package/dist/FlowMapAggregateAccessors.d.ts +15 -0
- package/dist/FlowMapAggregateAccessors.d.ts.map +1 -0
- package/dist/FlowMapAggregateAccessors.js +43 -0
- package/dist/FlowMapSelectors.d.ts +156 -0
- package/dist/FlowMapSelectors.d.ts.map +1 -0
- package/dist/FlowMapSelectors.js +831 -0
- package/dist/FlowMapState.d.ts +24 -0
- package/dist/FlowMapState.d.ts.map +1 -0
- package/dist/FlowMapState.js +2 -0
- package/dist/cluster/ClusterIndex.d.ts +42 -0
- package/dist/cluster/ClusterIndex.d.ts.map +1 -0
- package/dist/cluster/ClusterIndex.js +178 -0
- package/dist/cluster/cluster.d.ts +31 -0
- package/dist/cluster/cluster.d.ts.map +1 -0
- package/dist/cluster/cluster.js +206 -0
- package/dist/colors.d.ts +103 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +441 -0
- package/dist/getViewStateForLocations.d.ts +16 -0
- package/dist/getViewStateForLocations.d.ts.map +1 -0
- package/dist/getViewStateForLocations.js +30 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/provider/FlowMapDataProvider.d.ts +16 -0
- package/dist/provider/FlowMapDataProvider.d.ts.map +1 -0
- package/dist/provider/FlowMapDataProvider.js +17 -0
- package/dist/provider/LocalFlowMapDataProvider.d.ts +20 -0
- package/dist/provider/LocalFlowMapDataProvider.d.ts.map +1 -0
- package/dist/provider/LocalFlowMapDataProvider.js +87 -0
- package/dist/time.d.ts +24 -0
- package/dist/time.d.ts.map +1 -0
- package/dist/time.js +126 -0
- package/dist/types.d.ts +116 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/util.d.ts +2 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +4 -0
- package/package.json +48 -0
- package/src/FlowMapAggregateAccessors.ts +60 -0
- package/src/FlowMapSelectors.ts +1407 -0
- package/src/FlowMapState.ts +26 -0
- package/src/cluster/ClusterIndex.ts +266 -0
- package/src/cluster/cluster.ts +299 -0
- package/src/colors.ts +723 -0
- package/src/getViewStateForLocations.ts +64 -0
- package/src/index.ts +10 -0
- package/src/provider/FlowMapDataProvider.ts +63 -0
- package/src/provider/LocalFlowMapDataProvider.ts +108 -0
- package/src/time.ts +160 -0
- package/src/types.ts +162 -0
- package/src/util.ts +3 -0
- package/tsconfig.json +11 -0
- package/typings.d.ts +1 -0
|
@@ -0,0 +1,831 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 FlowmapBlue
|
|
3
|
+
* Copyright 2018-2020 Teralytics, modified by FlowmapBlue
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
import { bounds } from '@mapbox/geo-viewport';
|
|
19
|
+
import { ascending, descending, extent, min } from 'd3-array';
|
|
20
|
+
import { nest } from 'd3-collection';
|
|
21
|
+
import { scaleLinear, scaleSqrt } from 'd3-scale';
|
|
22
|
+
import KDBush from 'kdbush';
|
|
23
|
+
import { createSelector, createSelectorCreator, defaultMemoize, } from 'reselect';
|
|
24
|
+
import { alea } from 'seedrandom';
|
|
25
|
+
import { clusterLocations } from './cluster/cluster';
|
|
26
|
+
import { buildIndex, findAppropriateZoomLevel, makeLocationWeightGetter, } from './cluster/ClusterIndex';
|
|
27
|
+
import getColors, { getColorsRGBA, getDiffColorsRGBA, getFlowColorScale, isDiffColors, isDiffColorsRGBA, } from './colors';
|
|
28
|
+
import FlowMapAggregateAccessors from './FlowMapAggregateAccessors';
|
|
29
|
+
import { getTimeGranularityByKey, getTimeGranularityByOrder, getTimeGranularityForDate, } from './time';
|
|
30
|
+
import { isCluster, isLocationClusterNode, LocationFilterMode, } from './types';
|
|
31
|
+
import { flatMap } from './util';
|
|
32
|
+
const MAX_CLUSTER_ZOOM_LEVEL = 20;
|
|
33
|
+
const NUMBER_OF_FLOWS_TO_DISPLAY = 5000;
|
|
34
|
+
export default class FlowMapSelectors {
|
|
35
|
+
constructor(accessors) {
|
|
36
|
+
this.getFetchedFlows = (state, props) => props.flows;
|
|
37
|
+
this.getFetchedLocations = (state, props) => props.locations;
|
|
38
|
+
this.getSelectedLocations = (state, props) => state.filterState.selectedLocations;
|
|
39
|
+
this.getLocationFilterMode = (state, props) => state.filterState.locationFilterMode;
|
|
40
|
+
this.getClusteringEnabled = (state, props) => state.settingsState.clusteringEnabled;
|
|
41
|
+
this.getLocationTotalsEnabled = (state, props) => state.settingsState.locationTotalsEnabled;
|
|
42
|
+
this.getZoom = (state, props) => state.viewport.zoom;
|
|
43
|
+
this.getViewport = (state, props) => state.viewport;
|
|
44
|
+
this.getSelectedTimeRange = (state, props) => state.filterState.selectedTimeRange;
|
|
45
|
+
this.getColorSchemeKey = (state, props) => state.settingsState.colorScheme;
|
|
46
|
+
this.getDarkMode = (state, props) => state.settingsState.darkMode;
|
|
47
|
+
this.getFadeEnabled = (state, props) => state.settingsState.fadeEnabled;
|
|
48
|
+
this.getFadeAmount = (state, props) => state.settingsState.fadeAmount;
|
|
49
|
+
this.getAnimate = (state, props) => state.settingsState.animationEnabled;
|
|
50
|
+
this.getInvalidLocationIds = createSelector(this.getFetchedLocations, (locations) => {
|
|
51
|
+
if (!locations)
|
|
52
|
+
return undefined;
|
|
53
|
+
const invalid = [];
|
|
54
|
+
for (const location of locations) {
|
|
55
|
+
const id = this.accessors.getLocationId(location);
|
|
56
|
+
const [lon, lat] = this.accessors.getLocationCentroid(location) || [
|
|
57
|
+
NaN,
|
|
58
|
+
NaN,
|
|
59
|
+
];
|
|
60
|
+
if (!(-90 <= lat && lat <= 90) || !(-180 <= lon && lon <= 180)) {
|
|
61
|
+
invalid.push(id);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return invalid.length > 0 ? invalid : undefined;
|
|
65
|
+
});
|
|
66
|
+
this.getLocations = createSelector(this.getFetchedLocations, this.getInvalidLocationIds, (locations, invalidIds) => {
|
|
67
|
+
if (!locations)
|
|
68
|
+
return undefined;
|
|
69
|
+
if (!invalidIds || invalidIds.length === 0)
|
|
70
|
+
return locations;
|
|
71
|
+
const invalid = new Set(invalidIds);
|
|
72
|
+
return locations.filter((location) => !invalid.has(this.accessors.getLocationId(location)));
|
|
73
|
+
});
|
|
74
|
+
this.getLocationIds = createSelector(this.getLocations, (locations) => locations
|
|
75
|
+
? new Set(locations.map(this.accessors.getLocationId))
|
|
76
|
+
: undefined);
|
|
77
|
+
this.getSelectedLocationsSet = createSelector(this.getSelectedLocations, (ids) => ids && ids.length > 0 ? new Set(ids) : undefined);
|
|
78
|
+
this.getSortedFlowsForKnownLocations = createSelector(this.getFetchedFlows, this.getLocationIds, (flows, ids) => {
|
|
79
|
+
if (!ids || !flows)
|
|
80
|
+
return undefined;
|
|
81
|
+
return flows
|
|
82
|
+
.filter((flow) => ids.has(this.accessors.getFlowOriginId(flow)) &&
|
|
83
|
+
ids.has(this.accessors.getFlowDestId(flow)))
|
|
84
|
+
.sort((a, b) => descending(Math.abs(this.accessors.getFlowMagnitude(a)), Math.abs(this.accessors.getFlowMagnitude(b))));
|
|
85
|
+
});
|
|
86
|
+
this.getActualTimeExtent = createSelector(this.getSortedFlowsForKnownLocations, (flows) => {
|
|
87
|
+
if (!flows)
|
|
88
|
+
return undefined;
|
|
89
|
+
let start = null;
|
|
90
|
+
let end = null;
|
|
91
|
+
for (const flow of flows) {
|
|
92
|
+
const time = this.accessors.getFlowTime(flow);
|
|
93
|
+
if (time) {
|
|
94
|
+
if (start == null || start > time)
|
|
95
|
+
start = time;
|
|
96
|
+
if (end == null || end < time)
|
|
97
|
+
end = time;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!start || !end)
|
|
101
|
+
return undefined;
|
|
102
|
+
return [start, end];
|
|
103
|
+
});
|
|
104
|
+
this.getTimeGranularityKey = createSelector(this.getSortedFlowsForKnownLocations, this.getActualTimeExtent, (flows, timeExtent) => {
|
|
105
|
+
if (!flows || !timeExtent)
|
|
106
|
+
return undefined;
|
|
107
|
+
const minOrder = min(flows, (d) => {
|
|
108
|
+
const t = this.accessors.getFlowTime(d);
|
|
109
|
+
return t ? getTimeGranularityForDate(t).order : null;
|
|
110
|
+
});
|
|
111
|
+
if (minOrder == null)
|
|
112
|
+
return undefined;
|
|
113
|
+
const timeGranularity = getTimeGranularityByOrder(minOrder);
|
|
114
|
+
return timeGranularity ? timeGranularity.key : undefined;
|
|
115
|
+
});
|
|
116
|
+
this.getTimeExtent = createSelector(this.getActualTimeExtent, this.getTimeGranularityKey, (timeExtent, timeGranularityKey) => {
|
|
117
|
+
const timeGranularity = timeGranularityKey
|
|
118
|
+
? getTimeGranularityByKey(timeGranularityKey)
|
|
119
|
+
: undefined;
|
|
120
|
+
if (!timeExtent || !(timeGranularity === null || timeGranularity === void 0 ? void 0 : timeGranularity.interval))
|
|
121
|
+
return undefined;
|
|
122
|
+
const { interval } = timeGranularity;
|
|
123
|
+
return [timeExtent[0], interval.offset(interval.floor(timeExtent[1]), 1)];
|
|
124
|
+
});
|
|
125
|
+
this.getSortedFlowsForKnownLocationsFilteredByTime = createSelector(this.getSortedFlowsForKnownLocations, this.getTimeExtent, this.getSelectedTimeRange, (flows, timeExtent, timeRange) => {
|
|
126
|
+
if (!flows)
|
|
127
|
+
return undefined;
|
|
128
|
+
if (!timeExtent ||
|
|
129
|
+
!timeRange ||
|
|
130
|
+
(timeExtent[0] === timeRange[0] && timeExtent[1] === timeRange[1])) {
|
|
131
|
+
return flows;
|
|
132
|
+
}
|
|
133
|
+
return flows.filter((flow) => {
|
|
134
|
+
const time = this.accessors.getFlowTime(flow);
|
|
135
|
+
return time && timeRange[0] <= time && time < timeRange[1];
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
this.getLocationsHavingFlows = createSelector(this.getSortedFlowsForKnownLocations, this.getLocations, (flows, locations) => {
|
|
139
|
+
if (!locations || !flows)
|
|
140
|
+
return locations;
|
|
141
|
+
const withFlows = new Set();
|
|
142
|
+
for (const flow of flows) {
|
|
143
|
+
withFlows.add(this.accessors.getFlowOriginId(flow));
|
|
144
|
+
withFlows.add(this.accessors.getFlowDestId(flow));
|
|
145
|
+
}
|
|
146
|
+
return locations.filter((location) => withFlows.has(this.accessors.getLocationId(location)));
|
|
147
|
+
});
|
|
148
|
+
this.getLocationsById = createSelector(this.getLocationsHavingFlows, (locations) => {
|
|
149
|
+
if (!locations)
|
|
150
|
+
return undefined;
|
|
151
|
+
return nest()
|
|
152
|
+
.key((d) => this.accessors.getLocationId(d))
|
|
153
|
+
.rollup(([d]) => d)
|
|
154
|
+
.map(locations);
|
|
155
|
+
});
|
|
156
|
+
this.getClusterIndex = createSelector(this.getLocationsHavingFlows, this.getLocationsById, this.getSortedFlowsForKnownLocations, (locations, locationsById, flows) => {
|
|
157
|
+
if (!locations || !locationsById || !flows)
|
|
158
|
+
return undefined;
|
|
159
|
+
const getLocationWeight = makeLocationWeightGetter(flows, this.accessors.getFlowMapDataAccessors());
|
|
160
|
+
const clusterLevels = clusterLocations(locations, this.accessors.getFlowMapDataAccessors(), getLocationWeight, {
|
|
161
|
+
maxZoom: MAX_CLUSTER_ZOOM_LEVEL,
|
|
162
|
+
});
|
|
163
|
+
const clusterIndex = buildIndex(clusterLevels);
|
|
164
|
+
const { getLocationName, getLocationClusterName } = this.accessors.getFlowMapDataAccessors();
|
|
165
|
+
// Adding meaningful names
|
|
166
|
+
const getName = (id) => {
|
|
167
|
+
const loc = locationsById.get(id);
|
|
168
|
+
if (loc) {
|
|
169
|
+
return getLocationName
|
|
170
|
+
? getLocationName(loc)
|
|
171
|
+
: this.accessors.getLocationId(loc) || id;
|
|
172
|
+
}
|
|
173
|
+
return `"${id}"`;
|
|
174
|
+
};
|
|
175
|
+
for (const level of clusterLevels) {
|
|
176
|
+
for (const node of level.nodes) {
|
|
177
|
+
// Here mutating the nodes (adding names)
|
|
178
|
+
if (isCluster(node)) {
|
|
179
|
+
const leaves = clusterIndex.expandCluster(node);
|
|
180
|
+
leaves.sort((a, b) => descending(getLocationWeight(a), getLocationWeight(b)));
|
|
181
|
+
if (getLocationClusterName) {
|
|
182
|
+
node.name = getLocationClusterName(leaves);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
const topId = leaves[0];
|
|
186
|
+
const otherId = leaves.length === 2 ? leaves[1] : undefined;
|
|
187
|
+
node.name = `"${getName(topId)}" and ${otherId
|
|
188
|
+
? `"${getName(otherId)}"`
|
|
189
|
+
: `${leaves.length - 1} others`}`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
node.name = getName(node.id);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return clusterIndex;
|
|
198
|
+
});
|
|
199
|
+
this.getAvailableClusterZoomLevels = createSelector(this.getClusterIndex, this.getSelectedLocations, (clusterIndex, selectedLocations) => {
|
|
200
|
+
if (!clusterIndex) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
let maxZoom = Number.POSITIVE_INFINITY;
|
|
204
|
+
let minZoom = Number.NEGATIVE_INFINITY;
|
|
205
|
+
const adjust = (zoneId) => {
|
|
206
|
+
const cluster = clusterIndex.getClusterById(zoneId);
|
|
207
|
+
if (cluster) {
|
|
208
|
+
minZoom = Math.max(minZoom, cluster.zoom);
|
|
209
|
+
maxZoom = Math.min(maxZoom, cluster.zoom);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
const zoom = clusterIndex.getMinZoomForLocation(zoneId);
|
|
213
|
+
minZoom = Math.max(minZoom, zoom);
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
if (selectedLocations) {
|
|
217
|
+
for (const id of selectedLocations) {
|
|
218
|
+
adjust(id);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return clusterIndex.availableZoomLevels.filter((level) => minZoom <= level && level <= maxZoom);
|
|
222
|
+
});
|
|
223
|
+
this._getClusterZoom = createSelector(this.getClusterIndex, this.getZoom, this.getAvailableClusterZoomLevels, (clusterIndex, mapZoom, availableClusterZoomLevels) => {
|
|
224
|
+
if (!clusterIndex)
|
|
225
|
+
return undefined;
|
|
226
|
+
if (!availableClusterZoomLevels) {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
const clusterZoom = findAppropriateZoomLevel(availableClusterZoomLevels, mapZoom);
|
|
230
|
+
return clusterZoom;
|
|
231
|
+
});
|
|
232
|
+
this.getClusterZoom = (state, props) => {
|
|
233
|
+
const { settingsState } = state;
|
|
234
|
+
if (!settingsState.clusteringEnabled)
|
|
235
|
+
return undefined;
|
|
236
|
+
if (settingsState.clusteringAuto || settingsState.clusteringLevel == null) {
|
|
237
|
+
return this._getClusterZoom(state, props);
|
|
238
|
+
}
|
|
239
|
+
return settingsState.clusteringLevel;
|
|
240
|
+
};
|
|
241
|
+
this.getLocationsForSearchBox = createSelector(this.getClusteringEnabled, this.getLocationsHavingFlows, this.getSelectedLocations, this.getClusterZoom, this.getClusterIndex, (clusteringEnabled, locations, selectedLocations, clusterZoom, clusterIndex) => {
|
|
242
|
+
if (!locations)
|
|
243
|
+
return undefined;
|
|
244
|
+
let result = locations;
|
|
245
|
+
// if (clusteringEnabled) {
|
|
246
|
+
// if (clusterIndex) {
|
|
247
|
+
// const zoomItems = clusterIndex.getClusterNodesFor(clusterZoom);
|
|
248
|
+
// if (zoomItems) {
|
|
249
|
+
// result = result.concat(zoomItems.filter(isCluster));
|
|
250
|
+
// }
|
|
251
|
+
// }
|
|
252
|
+
// }
|
|
253
|
+
if (result && clusterIndex && selectedLocations) {
|
|
254
|
+
const toAppend = [];
|
|
255
|
+
for (const id of selectedLocations) {
|
|
256
|
+
const cluster = clusterIndex.getClusterById(id);
|
|
257
|
+
if (cluster &&
|
|
258
|
+
!result.find((d) => (isLocationClusterNode(d)
|
|
259
|
+
? d.id
|
|
260
|
+
: this.accessors.getLocationId(d)) === id)) {
|
|
261
|
+
toAppend.push(cluster);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (toAppend.length > 0) {
|
|
265
|
+
result = result.concat(toAppend);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return result;
|
|
269
|
+
});
|
|
270
|
+
this.getDiffMode = createSelector(this.getFetchedFlows, (flows) => {
|
|
271
|
+
if (flows &&
|
|
272
|
+
flows.find((f) => this.accessors.getFlowMagnitude(f) < 0)) {
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
return false;
|
|
276
|
+
});
|
|
277
|
+
this._getFlowMapColors = createSelector(this.getDiffMode, this.getColorSchemeKey, this.getDarkMode, this.getFadeEnabled, this.getFadeAmount, this.getAnimate, getColors);
|
|
278
|
+
this.getFlowMapColorsRGBA = createSelector(this._getFlowMapColors, (flowMapColors) => {
|
|
279
|
+
return isDiffColors(flowMapColors)
|
|
280
|
+
? getDiffColorsRGBA(flowMapColors)
|
|
281
|
+
: getColorsRGBA(flowMapColors);
|
|
282
|
+
});
|
|
283
|
+
this.getUnknownLocations = createSelector(this.getLocationIds, this.getFetchedFlows, this.getSortedFlowsForKnownLocations, (ids, flows, flowsForKnownLocations) => {
|
|
284
|
+
if (!ids || !flows)
|
|
285
|
+
return undefined;
|
|
286
|
+
if (flowsForKnownLocations &&
|
|
287
|
+
flows.length === flowsForKnownLocations.length)
|
|
288
|
+
return undefined;
|
|
289
|
+
const missing = new Set();
|
|
290
|
+
for (const flow of flows) {
|
|
291
|
+
if (!ids.has(this.accessors.getFlowOriginId(flow)))
|
|
292
|
+
missing.add(this.accessors.getFlowOriginId(flow));
|
|
293
|
+
if (!ids.has(this.accessors.getFlowDestId(flow)))
|
|
294
|
+
missing.add(this.accessors.getFlowDestId(flow));
|
|
295
|
+
}
|
|
296
|
+
return missing;
|
|
297
|
+
});
|
|
298
|
+
this.getSortedAggregatedFilteredFlows = createSelector(this.getClusterIndex, this.getClusteringEnabled, this.getSortedFlowsForKnownLocationsFilteredByTime, this.getClusterZoom, this.getTimeExtent, (clusterTree, isClusteringEnabled, flows, clusterZoom, timeExtent) => {
|
|
299
|
+
if (!flows)
|
|
300
|
+
return undefined;
|
|
301
|
+
let aggregated;
|
|
302
|
+
if (isClusteringEnabled && clusterTree && clusterZoom != null) {
|
|
303
|
+
aggregated = clusterTree.aggregateFlows(
|
|
304
|
+
// TODO: aggregate across time
|
|
305
|
+
// timeExtent != null
|
|
306
|
+
// ? aggregateFlows(flows) // clusterTree.aggregateFlows won't aggregate unclustered across time
|
|
307
|
+
// : flows,
|
|
308
|
+
flows, clusterZoom, this.accessors.getFlowMapDataAccessors());
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
aggregated = aggregateFlows(flows, this.accessors.getFlowMapDataAccessors());
|
|
312
|
+
}
|
|
313
|
+
aggregated.sort((a, b) => descending(Math.abs(this.accessors.getFlowMagnitude(a)), Math.abs(this.accessors.getFlowMagnitude(b))));
|
|
314
|
+
return aggregated;
|
|
315
|
+
});
|
|
316
|
+
this._getFlowMagnitudeExtent = createSelector(this.getSortedAggregatedFilteredFlows, this.getSelectedLocationsSet, this.getLocationFilterMode, (flows, selectedLocationsSet, locationFilterMode) => {
|
|
317
|
+
if (!flows)
|
|
318
|
+
return undefined;
|
|
319
|
+
let rv = undefined;
|
|
320
|
+
for (const f of flows) {
|
|
321
|
+
if (this.accessors.getFlowOriginId(f) !==
|
|
322
|
+
this.accessors.getFlowDestId(f) &&
|
|
323
|
+
this.isFlowInSelection(f, selectedLocationsSet, locationFilterMode)) {
|
|
324
|
+
const count = this.accessors.getFlowMagnitude(f);
|
|
325
|
+
if (rv == null) {
|
|
326
|
+
rv = [count, count];
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
if (count < rv[0])
|
|
330
|
+
rv[0] = count;
|
|
331
|
+
if (count > rv[1])
|
|
332
|
+
rv[1] = count;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return rv;
|
|
337
|
+
});
|
|
338
|
+
this.getExpandedSelectedLocationsSet = createSelector(this.getClusteringEnabled, this.getSelectedLocationsSet, this.getClusterIndex, (clusteringEnabled, selectedLocations, clusterIndex) => {
|
|
339
|
+
if (!selectedLocations || !clusterIndex) {
|
|
340
|
+
return selectedLocations;
|
|
341
|
+
}
|
|
342
|
+
const result = new Set();
|
|
343
|
+
for (const locationId of selectedLocations) {
|
|
344
|
+
const cluster = clusterIndex.getClusterById(locationId);
|
|
345
|
+
if (cluster) {
|
|
346
|
+
const expanded = clusterIndex.expandCluster(cluster);
|
|
347
|
+
for (const id of expanded) {
|
|
348
|
+
result.add(id);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
result.add(locationId);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return result;
|
|
356
|
+
});
|
|
357
|
+
this.getTotalCountsByTime = createSelector(this.getSortedFlowsForKnownLocations, this.getTimeGranularityKey, this.getTimeExtent, this.getExpandedSelectedLocationsSet, this.getLocationFilterMode, (flows, timeGranularityKey, timeExtent, selectedLocationSet, locationFilterMode) => {
|
|
358
|
+
const timeGranularity = timeGranularityKey
|
|
359
|
+
? getTimeGranularityByKey(timeGranularityKey)
|
|
360
|
+
: undefined;
|
|
361
|
+
if (!flows || !timeGranularity || !timeExtent)
|
|
362
|
+
return undefined;
|
|
363
|
+
const byTime = flows.reduce((m, flow) => {
|
|
364
|
+
var _a;
|
|
365
|
+
if (this.isFlowInSelection(flow, selectedLocationSet, locationFilterMode)) {
|
|
366
|
+
const key = timeGranularity
|
|
367
|
+
.interval(this.accessors.getFlowTime(flow))
|
|
368
|
+
.getTime();
|
|
369
|
+
m.set(key, ((_a = m.get(key)) !== null && _a !== void 0 ? _a : 0) + this.accessors.getFlowMagnitude(flow));
|
|
370
|
+
}
|
|
371
|
+
return m;
|
|
372
|
+
}, new Map());
|
|
373
|
+
return Array.from(byTime.entries()).map(([millis, count]) => ({
|
|
374
|
+
time: new Date(millis),
|
|
375
|
+
count,
|
|
376
|
+
}));
|
|
377
|
+
});
|
|
378
|
+
this.getMaxLocationCircleSize = createSelector(this.getLocationTotalsEnabled, (locationTotalsEnabled) => (locationTotalsEnabled ? 17 : 1));
|
|
379
|
+
this.getViewportBoundingBox = createSelector(this.getViewport, this.getMaxLocationCircleSize, (viewport, maxLocationCircleSize) => {
|
|
380
|
+
const pad = maxLocationCircleSize;
|
|
381
|
+
return bounds([viewport.longitude, viewport.latitude], viewport.zoom, [viewport.width + pad * 2, viewport.height + pad * 2], 512);
|
|
382
|
+
});
|
|
383
|
+
this.getLocationsForZoom = createSelector(this.getClusteringEnabled, this.getLocationsHavingFlows, this.getClusterIndex, this.getClusterZoom, (clusteringEnabled, locationsHavingFlows, clusterIndex, clusterZoom) => {
|
|
384
|
+
if (clusteringEnabled && clusterIndex) {
|
|
385
|
+
return clusterIndex.getClusterNodesFor(clusterZoom);
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
return locationsHavingFlows;
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
this.getLocationTotals = createSelector(this.getLocationsForZoom, this.getSortedAggregatedFilteredFlows, this.getSelectedLocationsSet, this.getLocationFilterMode, (locations, flows, selectedLocationsSet, locationFilterMode) => {
|
|
392
|
+
if (!flows)
|
|
393
|
+
return undefined;
|
|
394
|
+
const totals = new Map();
|
|
395
|
+
const add = (id, d) => {
|
|
396
|
+
var _a;
|
|
397
|
+
const rv = (_a = totals.get(id)) !== null && _a !== void 0 ? _a : {
|
|
398
|
+
incomingCount: 0,
|
|
399
|
+
outgoingCount: 0,
|
|
400
|
+
internalCount: 0,
|
|
401
|
+
};
|
|
402
|
+
if (d.incomingCount != null)
|
|
403
|
+
rv.incomingCount += d.incomingCount;
|
|
404
|
+
if (d.outgoingCount != null)
|
|
405
|
+
rv.outgoingCount += d.outgoingCount;
|
|
406
|
+
if (d.internalCount != null)
|
|
407
|
+
rv.internalCount += d.internalCount;
|
|
408
|
+
return rv;
|
|
409
|
+
};
|
|
410
|
+
for (const f of flows) {
|
|
411
|
+
if (this.isFlowInSelection(f, selectedLocationsSet, locationFilterMode)) {
|
|
412
|
+
const originId = this.accessors.getFlowOriginId(f);
|
|
413
|
+
const destId = this.accessors.getFlowDestId(f);
|
|
414
|
+
const count = this.accessors.getFlowMagnitude(f);
|
|
415
|
+
if (originId === destId) {
|
|
416
|
+
totals.set(originId, add(originId, { internalCount: count }));
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
totals.set(originId, add(originId, { outgoingCount: count }));
|
|
420
|
+
totals.set(destId, add(destId, { incomingCount: count }));
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return totals;
|
|
425
|
+
});
|
|
426
|
+
this.getLocationsTree = createSelector(this.getLocationsForZoom, (locations) => {
|
|
427
|
+
if (!locations) {
|
|
428
|
+
return undefined;
|
|
429
|
+
}
|
|
430
|
+
return new KDBush(
|
|
431
|
+
// @ts-ignore
|
|
432
|
+
locations, (location) => lngX(isLocationClusterNode(location)
|
|
433
|
+
? location.centroid[0]
|
|
434
|
+
: this.accessors.getLocationCentroid(location)[0]), (location) => latY(isLocationClusterNode(location)
|
|
435
|
+
? location.centroid[1]
|
|
436
|
+
: this.accessors.getLocationCentroid(location)[1]));
|
|
437
|
+
});
|
|
438
|
+
this._getLocationIdsInViewport = createSelector(this.getLocationsTree, this.getViewportBoundingBox, (tree, bbox) => {
|
|
439
|
+
const ids = this._getLocationsInBboxIndices(tree, bbox);
|
|
440
|
+
if (ids) {
|
|
441
|
+
return new Set(ids.map((idx) => tree.points[idx].id));
|
|
442
|
+
}
|
|
443
|
+
return undefined;
|
|
444
|
+
});
|
|
445
|
+
this.getLocationIdsInViewport =
|
|
446
|
+
// @ts-ignore
|
|
447
|
+
createSelectorCreator(
|
|
448
|
+
// @ts-ignore
|
|
449
|
+
defaultMemoize, (s1, s2, index) => {
|
|
450
|
+
if (s1 === s2)
|
|
451
|
+
return true;
|
|
452
|
+
if (s1 == null || s2 == null)
|
|
453
|
+
return false;
|
|
454
|
+
if (s1.size !== s2.size)
|
|
455
|
+
return false;
|
|
456
|
+
for (const item of s1)
|
|
457
|
+
if (!s2.has(item))
|
|
458
|
+
return false;
|
|
459
|
+
return true;
|
|
460
|
+
})(this._getLocationIdsInViewport, (locationIds) => {
|
|
461
|
+
if (!locationIds)
|
|
462
|
+
return undefined;
|
|
463
|
+
return locationIds;
|
|
464
|
+
});
|
|
465
|
+
this.getTotalUnfilteredCount = createSelector(this.getSortedFlowsForKnownLocations, (flows) => {
|
|
466
|
+
if (!flows)
|
|
467
|
+
return undefined;
|
|
468
|
+
return flows.reduce((m, flow) => m + this.accessors.getFlowMagnitude(flow), 0);
|
|
469
|
+
});
|
|
470
|
+
this.getTotalFilteredCount = createSelector(this.getSortedAggregatedFilteredFlows, this.getSelectedLocationsSet, this.getLocationFilterMode, (flows, selectedLocationSet, locationFilterMode) => {
|
|
471
|
+
if (!flows)
|
|
472
|
+
return undefined;
|
|
473
|
+
const count = flows.reduce((m, flow) => {
|
|
474
|
+
if (this.isFlowInSelection(flow, selectedLocationSet, locationFilterMode)) {
|
|
475
|
+
return m + this.accessors.getFlowMagnitude(flow);
|
|
476
|
+
}
|
|
477
|
+
return m;
|
|
478
|
+
}, 0);
|
|
479
|
+
return count;
|
|
480
|
+
});
|
|
481
|
+
this._getLocationTotalsExtent = createSelector(this.getLocationTotals, (locationTotals) => calcLocationTotalsExtent(locationTotals, undefined));
|
|
482
|
+
this._getLocationTotalsForViewportExtent = createSelector(this.getLocationTotals, this.getLocationIdsInViewport, (locationTotals, locationsInViewport) => calcLocationTotalsExtent(locationTotals, locationsInViewport));
|
|
483
|
+
this.getLocationTotalsExtent = (state, props) => {
|
|
484
|
+
if (state.settingsState.adaptiveScalesEnabled) {
|
|
485
|
+
return this._getLocationTotalsForViewportExtent(state, props);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
return this._getLocationTotalsExtent(state, props);
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
this.getFlowsForFlowMapLayer = createSelector(this.getSortedAggregatedFilteredFlows, this.getLocationIdsInViewport, this.getSelectedLocationsSet, this.getLocationFilterMode, (flows, locationIdsInViewport, selectedLocationsSet, locationFilterMode) => {
|
|
492
|
+
if (!flows || !locationIdsInViewport)
|
|
493
|
+
return undefined;
|
|
494
|
+
const picked = [];
|
|
495
|
+
let pickedCount = 0;
|
|
496
|
+
for (const flow of flows) {
|
|
497
|
+
const origin = this.accessors.getFlowOriginId(flow);
|
|
498
|
+
const dest = this.accessors.getFlowDestId(flow);
|
|
499
|
+
if (locationIdsInViewport.has(origin) ||
|
|
500
|
+
locationIdsInViewport.has(dest)) {
|
|
501
|
+
if (this.isFlowInSelection(flow, selectedLocationsSet, locationFilterMode)) {
|
|
502
|
+
if (origin !== dest) {
|
|
503
|
+
// exclude self-loops
|
|
504
|
+
picked.push(flow);
|
|
505
|
+
pickedCount++;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
// Only keep top
|
|
510
|
+
if (pickedCount > NUMBER_OF_FLOWS_TO_DISPLAY)
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
// assuming they are sorted in descending order,
|
|
514
|
+
// we need ascending for rendering
|
|
515
|
+
return picked.reverse();
|
|
516
|
+
});
|
|
517
|
+
this.getLocationMaxAbsTotalGetter = createSelector(this.getLocationTotals, (locationTotals) => {
|
|
518
|
+
return (locationId) => {
|
|
519
|
+
const total = locationTotals === null || locationTotals === void 0 ? void 0 : locationTotals.get(locationId);
|
|
520
|
+
if (!total)
|
|
521
|
+
return undefined;
|
|
522
|
+
return Math.max(Math.abs(total.incomingCount + total.internalCount), Math.abs(total.outgoingCount + total.internalCount));
|
|
523
|
+
};
|
|
524
|
+
});
|
|
525
|
+
this.getFlowThicknessScale = (state, props) => {
|
|
526
|
+
const magnitudeExtent = this.getFlowMagnitudeExtent(state, props);
|
|
527
|
+
if (!magnitudeExtent)
|
|
528
|
+
return undefined;
|
|
529
|
+
return scaleLinear()
|
|
530
|
+
.range([0.025, 0.5])
|
|
531
|
+
.domain([
|
|
532
|
+
0,
|
|
533
|
+
// should support diff mode too
|
|
534
|
+
Math.max.apply(null, magnitudeExtent.map((x) => Math.abs(x || 0))),
|
|
535
|
+
]);
|
|
536
|
+
};
|
|
537
|
+
this.getCircleSizeScale = (state, props) => {
|
|
538
|
+
const maxLocationCircleSize = this.getMaxLocationCircleSize(state, props);
|
|
539
|
+
const { locationTotalsEnabled } = state.settingsState;
|
|
540
|
+
if (!locationTotalsEnabled) {
|
|
541
|
+
return () => maxLocationCircleSize;
|
|
542
|
+
}
|
|
543
|
+
const locationTotalsExtent = this.getLocationTotalsExtent(state, props);
|
|
544
|
+
if (!locationTotalsExtent)
|
|
545
|
+
return undefined;
|
|
546
|
+
return scaleSqrt()
|
|
547
|
+
.range([0, maxLocationCircleSize])
|
|
548
|
+
.domain([
|
|
549
|
+
0,
|
|
550
|
+
// should support diff mode too
|
|
551
|
+
Math.max.apply(null, locationTotalsExtent.map((x) => Math.abs(x || 0))),
|
|
552
|
+
]);
|
|
553
|
+
};
|
|
554
|
+
this.getInCircleSizeGetter = createSelector(this.getCircleSizeScale, this.getLocationTotals, (circleSizeScale, locationTotals) => {
|
|
555
|
+
return (locationId) => {
|
|
556
|
+
const total = locationTotals === null || locationTotals === void 0 ? void 0 : locationTotals.get(locationId);
|
|
557
|
+
if (total && circleSizeScale) {
|
|
558
|
+
return (circleSizeScale(Math.abs(total.incomingCount + total.internalCount)) || 0);
|
|
559
|
+
}
|
|
560
|
+
return 0;
|
|
561
|
+
};
|
|
562
|
+
});
|
|
563
|
+
this.getOutCircleSizeGetter = createSelector(this.getCircleSizeScale, this.getLocationTotals, (circleSizeScale, locationTotals) => {
|
|
564
|
+
return (locationId) => {
|
|
565
|
+
const total = locationTotals === null || locationTotals === void 0 ? void 0 : locationTotals.get(locationId);
|
|
566
|
+
if (total && circleSizeScale) {
|
|
567
|
+
return (circleSizeScale(Math.abs(total.outgoingCount + total.internalCount)) || 0);
|
|
568
|
+
}
|
|
569
|
+
return 0;
|
|
570
|
+
};
|
|
571
|
+
});
|
|
572
|
+
this.getSortedLocationsForZoom = createSelector(this.getLocationsForZoom, this.getInCircleSizeGetter, this.getOutCircleSizeGetter, (locations, getInCircleSize, getOutCircleSize) => {
|
|
573
|
+
if (!locations)
|
|
574
|
+
return undefined;
|
|
575
|
+
const nextLocations = [...locations];
|
|
576
|
+
return nextLocations.sort((a, b) => {
|
|
577
|
+
const idA = this.accessors.getLocationId(a);
|
|
578
|
+
const idB = this.accessors.getLocationId(b);
|
|
579
|
+
return ascending(Math.max(getInCircleSize(idA), getOutCircleSize(idA)), Math.max(getInCircleSize(idB), getOutCircleSize(idB)));
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
this.getLocationsForFlowMapLayer = createSelector(this.getSortedLocationsForZoom,
|
|
583
|
+
// this.getLocationIdsInViewport,
|
|
584
|
+
(locations) => {
|
|
585
|
+
// if (!locations) return undefined;
|
|
586
|
+
// if (!locationIdsInViewport) return locations;
|
|
587
|
+
// if (locationIdsInViewport.size === locations.length) return locations;
|
|
588
|
+
// const filtered = [];
|
|
589
|
+
// for (const loc of locations) {
|
|
590
|
+
// if (locationIdsInViewport.has(loc.id)) {
|
|
591
|
+
// filtered.push(loc);
|
|
592
|
+
// }
|
|
593
|
+
// }
|
|
594
|
+
// return filtered;
|
|
595
|
+
// @ts-ignore
|
|
596
|
+
// return locations.filter(
|
|
597
|
+
// (loc: L | ClusterNode) => locationIdsInViewport!.has(loc.id)
|
|
598
|
+
// );
|
|
599
|
+
// TODO: return location in viewport + "connected" ones
|
|
600
|
+
return locations;
|
|
601
|
+
});
|
|
602
|
+
this.getLocationsForFlowMapLayerById = createSelector(this.getLocationsForFlowMapLayer, (locations) => {
|
|
603
|
+
if (!locations)
|
|
604
|
+
return undefined;
|
|
605
|
+
return locations.reduce((m, d) => (m.set(this.accessors.getLocationId(d), d), m), new Map());
|
|
606
|
+
});
|
|
607
|
+
this.accessors = new FlowMapAggregateAccessors(accessors);
|
|
608
|
+
this.setAccessors(accessors);
|
|
609
|
+
}
|
|
610
|
+
setAccessors(accessors) {
|
|
611
|
+
this.accessors = new FlowMapAggregateAccessors(accessors);
|
|
612
|
+
}
|
|
613
|
+
getFlowMagnitudeExtent(state, props) {
|
|
614
|
+
if (state.settingsState.adaptiveScalesEnabled) {
|
|
615
|
+
const flows = this.getFlowsForFlowMapLayer(state, props);
|
|
616
|
+
if (flows) {
|
|
617
|
+
const rv = extent(flows, this.accessors.getFlowMagnitude);
|
|
618
|
+
return rv[0] !== undefined && rv[1] !== undefined ? rv : undefined;
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
return undefined;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
return this._getFlowMagnitudeExtent(state, props);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
prepareLayersData(state, props) {
|
|
629
|
+
const locations = this.getLocationsForFlowMapLayer(state, props) || [];
|
|
630
|
+
const flows = this.getFlowsForFlowMapLayer(state, props) || [];
|
|
631
|
+
const { getFlowOriginId, getFlowDestId, getFlowMagnitude, getLocationId, getLocationCentroid, } = this.accessors;
|
|
632
|
+
const flowMapColors = this.getFlowMapColorsRGBA(state, props);
|
|
633
|
+
const { settingsState } = state;
|
|
634
|
+
const locationsById = this.getLocationsForFlowMapLayerById(state, props);
|
|
635
|
+
const getCentroid = (id) => {
|
|
636
|
+
const loc = locationsById === null || locationsById === void 0 ? void 0 : locationsById.get(id);
|
|
637
|
+
return loc ? getLocationCentroid(loc) : [0, 0];
|
|
638
|
+
};
|
|
639
|
+
const locationIdsInViewport = this.getLocationIdsInViewport(state, props);
|
|
640
|
+
const getInCircleSize = this.getInCircleSizeGetter(state, props);
|
|
641
|
+
const getOutCircleSize = this.getOutCircleSizeGetter(state, props);
|
|
642
|
+
const flowThicknessScale = this.getFlowThicknessScale(state, props);
|
|
643
|
+
const flowMagnitudeExtent = extent(flows, (f) => getFlowMagnitude(f));
|
|
644
|
+
const flowColorScale = getFlowColorScale(flowMapColors, flowMagnitudeExtent, false);
|
|
645
|
+
const circlePositions = new Float32Array(flatMap(locations, getLocationCentroid));
|
|
646
|
+
// TODO: diff mode
|
|
647
|
+
const circleColor = isDiffColorsRGBA(flowMapColors)
|
|
648
|
+
? flowMapColors.positive.locationCircles.inner
|
|
649
|
+
: flowMapColors.locationCircles.inner;
|
|
650
|
+
const circleColors = new Uint8Array(flatMap(locations, (d) => circleColor));
|
|
651
|
+
const inCircleRadii = new Float32Array(locations.map((loc) => {
|
|
652
|
+
const id = getLocationId(loc);
|
|
653
|
+
return (locationIdsInViewport === null || locationIdsInViewport === void 0 ? void 0 : locationIdsInViewport.has(id)) ? getInCircleSize(id) : 1.0;
|
|
654
|
+
}));
|
|
655
|
+
const outCircleRadii = new Float32Array(locations.map((loc) => {
|
|
656
|
+
const id = getLocationId(loc);
|
|
657
|
+
return (locationIdsInViewport === null || locationIdsInViewport === void 0 ? void 0 : locationIdsInViewport.has(id)) ? getOutCircleSize(id) : 1.0;
|
|
658
|
+
}));
|
|
659
|
+
const sourcePositions = new Float32Array(flatMap(flows, (d) => getCentroid(getFlowOriginId(d))));
|
|
660
|
+
const targetPositions = new Float32Array(flatMap(flows, (d) => getCentroid(getFlowDestId(d))));
|
|
661
|
+
const thicknesses = new Float32Array(flows.map((d) => flowThicknessScale ? flowThicknessScale(getFlowMagnitude(d)) || 0 : 0));
|
|
662
|
+
const endpointOffsets = new Float32Array(flatMap(flows, (d) => {
|
|
663
|
+
const originId = getFlowOriginId(d);
|
|
664
|
+
const destId = getFlowDestId(d);
|
|
665
|
+
return [
|
|
666
|
+
Math.max(getInCircleSize(originId), getOutCircleSize(originId)),
|
|
667
|
+
Math.max(getInCircleSize(destId), getOutCircleSize(destId)),
|
|
668
|
+
];
|
|
669
|
+
}));
|
|
670
|
+
const flowLineColors = new Uint8Array(flatMap(flows, (f) => flowColorScale(getFlowMagnitude(f))));
|
|
671
|
+
const staggeringValues = settingsState.animationEnabled
|
|
672
|
+
? new Float32Array(flows.map((f) =>
|
|
673
|
+
// @ts-ignore
|
|
674
|
+
new alea(`${getFlowOriginId(f)}-${getFlowDestId(f)}`)()))
|
|
675
|
+
: undefined;
|
|
676
|
+
return {
|
|
677
|
+
circleAttributes: {
|
|
678
|
+
length: locations.length,
|
|
679
|
+
attributes: {
|
|
680
|
+
getPosition: { value: circlePositions, size: 2 },
|
|
681
|
+
getColor: { value: circleColors, size: 4 },
|
|
682
|
+
getInRadius: { value: inCircleRadii, size: 1 },
|
|
683
|
+
getOutRadius: { value: outCircleRadii, size: 1 },
|
|
684
|
+
},
|
|
685
|
+
},
|
|
686
|
+
lineAttributes: {
|
|
687
|
+
length: flows.length,
|
|
688
|
+
attributes: Object.assign({ getSourcePosition: { value: sourcePositions, size: 2 }, getTargetPosition: { value: targetPositions, size: 2 }, getThickness: { value: thicknesses, size: 1 }, getColor: { value: flowLineColors, size: 4 }, getEndpointOffsets: { value: endpointOffsets, size: 2 } }, (staggeringValues
|
|
689
|
+
? { getStaggering: { value: staggeringValues, size: 1 } }
|
|
690
|
+
: {})),
|
|
691
|
+
},
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
getLocationsInBbox(tree, bbox) {
|
|
695
|
+
if (!tree)
|
|
696
|
+
return undefined;
|
|
697
|
+
return this._getLocationsInBboxIndices(tree, bbox).map((idx) => tree.points[idx]);
|
|
698
|
+
}
|
|
699
|
+
_getLocationsInBboxIndices(tree, bbox) {
|
|
700
|
+
if (!tree)
|
|
701
|
+
return undefined;
|
|
702
|
+
const [lon1, lat1, lon2, lat2] = bbox;
|
|
703
|
+
const [x1, y1, x2, y2] = [lngX(lon1), latY(lat1), lngX(lon2), latY(lat2)];
|
|
704
|
+
return tree.range(Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2));
|
|
705
|
+
}
|
|
706
|
+
isFlowInSelection(flow, selectedLocationsSet, locationFilterMode) {
|
|
707
|
+
const origin = this.accessors.getFlowOriginId(flow);
|
|
708
|
+
const dest = this.accessors.getFlowDestId(flow);
|
|
709
|
+
if (selectedLocationsSet) {
|
|
710
|
+
switch (locationFilterMode) {
|
|
711
|
+
case LocationFilterMode.ALL:
|
|
712
|
+
return (selectedLocationsSet.has(origin) || selectedLocationsSet.has(dest));
|
|
713
|
+
case LocationFilterMode.BETWEEN:
|
|
714
|
+
return (selectedLocationsSet.has(origin) && selectedLocationsSet.has(dest));
|
|
715
|
+
case LocationFilterMode.INCOMING:
|
|
716
|
+
return selectedLocationsSet.has(dest);
|
|
717
|
+
case LocationFilterMode.OUTGOING:
|
|
718
|
+
return selectedLocationsSet.has(origin);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return true;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
function calcLocationTotalsExtent(locationTotals, locationIdsInViewport) {
|
|
725
|
+
if (!locationTotals)
|
|
726
|
+
return undefined;
|
|
727
|
+
let rv = undefined;
|
|
728
|
+
for (const [id, { incomingCount, outgoingCount, internalCount },] of locationTotals.entries()) {
|
|
729
|
+
if (locationIdsInViewport == null || locationIdsInViewport.has(id)) {
|
|
730
|
+
const lo = Math.min(incomingCount + internalCount, outgoingCount + internalCount, internalCount);
|
|
731
|
+
const hi = Math.max(incomingCount + internalCount, outgoingCount + internalCount, internalCount);
|
|
732
|
+
if (!rv) {
|
|
733
|
+
rv = [lo, hi];
|
|
734
|
+
}
|
|
735
|
+
else {
|
|
736
|
+
if (lo < rv[0])
|
|
737
|
+
rv[0] = lo;
|
|
738
|
+
if (hi > rv[1])
|
|
739
|
+
rv[1] = hi;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
return rv;
|
|
744
|
+
}
|
|
745
|
+
// longitude/latitude to spherical mercator in [0..1] range
|
|
746
|
+
function lngX(lng) {
|
|
747
|
+
return lng / 360 + 0.5;
|
|
748
|
+
}
|
|
749
|
+
function latY(lat) {
|
|
750
|
+
const sin = Math.sin((lat * Math.PI) / 180);
|
|
751
|
+
const y = 0.5 - (0.25 * Math.log((1 + sin) / (1 - sin))) / Math.PI;
|
|
752
|
+
return y < 0 ? 0 : y > 1 ? 1 : y;
|
|
753
|
+
}
|
|
754
|
+
function aggregateFlows(flows, flowAccessors) {
|
|
755
|
+
// Sum up flows with same origin, dest
|
|
756
|
+
const byOriginDest = nest()
|
|
757
|
+
.key(flowAccessors.getFlowOriginId)
|
|
758
|
+
.key(flowAccessors.getFlowDestId)
|
|
759
|
+
.rollup((ff) => {
|
|
760
|
+
const origin = flowAccessors.getFlowOriginId(ff[0]);
|
|
761
|
+
const dest = flowAccessors.getFlowDestId(ff[0]);
|
|
762
|
+
// const color = ff[0].color;
|
|
763
|
+
const rv = {
|
|
764
|
+
aggregate: true,
|
|
765
|
+
origin,
|
|
766
|
+
dest,
|
|
767
|
+
count: ff.reduce((m, f) => {
|
|
768
|
+
const count = flowAccessors.getFlowMagnitude(f);
|
|
769
|
+
if (count) {
|
|
770
|
+
if (!isNaN(count) && isFinite(count))
|
|
771
|
+
return m + count;
|
|
772
|
+
}
|
|
773
|
+
return m;
|
|
774
|
+
}, 0),
|
|
775
|
+
// time: undefined,
|
|
776
|
+
};
|
|
777
|
+
// if (color) rv.color = color;
|
|
778
|
+
return rv;
|
|
779
|
+
})
|
|
780
|
+
.entries(flows);
|
|
781
|
+
const rv = [];
|
|
782
|
+
for (const { values } of byOriginDest) {
|
|
783
|
+
for (const { value } of values) {
|
|
784
|
+
rv.push(value);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
return rv;
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* This is used to augment hover picking info so that we can displace location tooltip
|
|
791
|
+
* @param circleAttributes
|
|
792
|
+
* @param index
|
|
793
|
+
*/
|
|
794
|
+
export function getOuterCircleRadiusByIndex(circleAttributes, index) {
|
|
795
|
+
const { getInRadius, getOutRadius } = circleAttributes.attributes;
|
|
796
|
+
return Math.max(getInRadius.value[index], getOutRadius.value[index]);
|
|
797
|
+
}
|
|
798
|
+
export function getLocationCentroidByIndex(circleAttributes, index) {
|
|
799
|
+
const { getPosition } = circleAttributes.attributes;
|
|
800
|
+
return [getPosition.value[index * 2], getPosition.value[index * 2 + 1]];
|
|
801
|
+
}
|
|
802
|
+
export function getFlowLineAttributesByIndex(lineAttributes, index) {
|
|
803
|
+
const { getColor, getEndpointOffsets, getSourcePosition, getTargetPosition, getThickness, getStaggering, } = lineAttributes.attributes;
|
|
804
|
+
return {
|
|
805
|
+
length: 1,
|
|
806
|
+
attributes: Object.assign({ getColor: {
|
|
807
|
+
value: getColor.value.subarray(index * 4, (index + 1) * 4),
|
|
808
|
+
size: 4,
|
|
809
|
+
}, getEndpointOffsets: {
|
|
810
|
+
value: getEndpointOffsets.value.subarray(index * 2, (index + 1) * 2),
|
|
811
|
+
size: 2,
|
|
812
|
+
}, getSourcePosition: {
|
|
813
|
+
value: getSourcePosition.value.subarray(index * 2, (index + 1) * 2),
|
|
814
|
+
size: 2,
|
|
815
|
+
}, getTargetPosition: {
|
|
816
|
+
value: getTargetPosition.value.subarray(index * 2, (index + 1) * 2),
|
|
817
|
+
size: 2,
|
|
818
|
+
}, getThickness: {
|
|
819
|
+
value: getThickness.value.subarray(index, index + 1),
|
|
820
|
+
size: 1,
|
|
821
|
+
} }, (getStaggering
|
|
822
|
+
? {
|
|
823
|
+
getStaggering: {
|
|
824
|
+
value: getStaggering.value.subarray(index, index + 1),
|
|
825
|
+
size: 1,
|
|
826
|
+
},
|
|
827
|
+
}
|
|
828
|
+
: undefined)),
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmxvd01hcFNlbGVjdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9GbG93TWFwU2VsZWN0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBRUgsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQzVDLE9BQU8sRUFBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDNUQsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNuQyxPQUFPLEVBQUMsV0FBVyxFQUFFLFNBQVMsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUNoRCxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxFQUNMLGNBQWMsRUFDZCxxQkFBcUIsRUFDckIsY0FBYyxHQUVmLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFDaEMsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUNMLFVBQVUsRUFFVix3QkFBd0IsRUFDeEIsd0JBQXdCLEdBQ3pCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxTQUFTLEVBQUUsRUFDaEIsYUFBYSxFQUNiLGlCQUFpQixFQUNqQixpQkFBaUIsRUFDakIsWUFBWSxFQUNaLGdCQUFnQixHQUNqQixNQUFNLFVBQVUsQ0FBQztBQUNsQixPQUFPLHlCQUF5QixNQUFNLDZCQUE2QixDQUFDO0FBRXBFLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIseUJBQXlCLEVBQ3pCLHlCQUF5QixHQUUxQixNQUFNLFFBQVEsQ0FBQztBQUNoQixPQUFPLEVBVUwsU0FBUyxFQUNULHFCQUFxQixFQUVyQixrQkFBa0IsR0FFbkIsTUFBTSxTQUFTLENBQUM7QUFDakIsT0FBTyxFQUFDLE9BQU8sRUFB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SUFBSSxFQUFFLENBQUM7aUJBQ1I7YUFDRjtZQUNILENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FDZjtLQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAyMDIyIEZsb3dtYXBCbHVlXG4gKiBDb3B5cmlnaHQgMjAxOC0yMDIwIFRlcmFseXRpY3MsIG1vZGlmaWVkIGJ5IEZsb3dtYXBCbHVlXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7Ym91bmRzfSBmcm9tICdAbWFwYm94L2dlby12aWV3cG9ydCc7XG5pbXBvcnQge2FzY2VuZGluZywgZGVzY2VuZGluZywgZXh0ZW50LCBtaW59IGZyb20gJ2QzLWFycmF5JztcbmltcG9ydCB7bmVzdH0gZnJvbSAnZDMtY29sbGVjdGlvbic7XG5pbXBvcnQge3NjYWxlTGluZWFyLCBzY2FsZVNxcnR9IGZyb20gJ2QzLXNjYWxlJztcbmltcG9ydCBLREJ1c2ggZnJvbSAna2RidXNoJztcbmltcG9ydCB7XG4gIGNyZWF0ZVNlbGVjdG9yLFxuICBjcmVhdGVTZWxlY3RvckNyZWF0b3IsXG4gIGRlZmF1bHRNZW1vaXplLFxuICBQYXJhbWV0cmljU2VsZWN0b3IsXG59IGZyb20gJ3Jlc2VsZWN0JztcbmltcG9ydCB7YWxlYX0gZnJvbSAnc2VlZHJhbmRvbSc7XG5pbXBvcnQge2NsdXN0ZXJMb2NhdGlvbnN9IGZyb20gJy4vY2x1c3Rlci9jbHVzdGVyJztcbmltcG9ydCB7XG4gIGJ1aWxkSW5kZXgsXG4gIENsdXN0ZXJJbmRleCxcbiAgZmluZEFwcHJvcHJpYXRlWm9vbUxldmVsLFxuICBtYWtlTG9jYXRpb25XZWlnaHRHZXR0ZXIsXG59IGZyb20gJy4vY2x1c3Rlci9DbHVzdGVySW5kZXgnO1xuaW1wb3J0IGdldENvbG9ycywge1xuICBnZXRDb2xvcnNSR0JBLFxuICBnZXREaWZmQ29sb3JzUkdCQSxcbiAgZ2V0Rmxvd0NvbG9yU2NhbGUsXG4gIGlzRGlmZkNvbG9ycyxcbiAgaXNEaWZmQ29sb3JzUkdCQSxcbn0gZnJvbSAnLi9jb2xvcnMnO1xuaW1wb3J0IEZsb3dNYXBBZ2dyZWdhdGVBY2Nlc3NvcnMgZnJvbSAnLi9GbG93TWFwQWdncmVnYXRlQWNjZXNzb3JzJztcbmltcG9ydCB7Rmxvd01hcFN0YXRlfSBmcm9tICcuL0Zsb3dNYXBTdGF0ZSc7XG5pbXBvcnQge1xuICBnZXRUaW1lR3JhbnVsYXJpdHlCeUtleSxcbiAgZ2V0VGltZUdyYW51bGFyaXR5QnlPcmRlcixcbiAgZ2V0VGltZUdyYW51bGFyaXR5Rm9yRGF0ZSxcbiAgVGltZUdyYW51bGFyaXR5S2V5LFxufSBmcm9tICcuL3RpbWUnO1xuaW1wb3J0IHtcbiAgQWdncmVnYXRlRmxvdyxcbiAgQ2x1c3RlcixcbiAgQ2x1c3Rlck5vZGUsXG4gIENvdW50QnlUaW1lLFxuICBGbG93QWNjZXNzb3JzLFxuICBGbG93Q2lyY2xlc0xheWVyQXR0cmlidXRlcyxcbiAgRmxvd0xpbmVzTGF5ZXJBdHRyaWJ1dGVzLFxuICBGbG93TWFwRGF0YSxcbiAgRmxvd01hcERhdGFBY2Nlc3NvcnMsXG4gIGlzQ2x1c3RlcixcbiAgaXNMb2NhdGlvbkNsdXN0ZXJOb2RlLFxuICBMYXllcnNEYXRhLFxuICBMb2NhdGlvbkZpbHRlck1vZGUsXG4gIExvY2F0aW9uVG90YWxzLFxufSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7ZmxhdE1hcH0gZnJvbSAnLi91dGlsJztcblxuY29uc3QgTUFYX0NMVVNURVJfWk9PTV9MRVZFTCA9IDIwO1xuY29uc3QgTlVNQkVSX09GX0ZMT1dTX1RPX0RJU1BMQVkgPSA1MDAwO1xudHlwZSBLREJ1c2hUcmVlID0gYW55O1xuXG5leHBvcnQgdHlwZSBTZWxlY3RvcjxMLCBGLCBUPiA9IFBhcmFtZXRyaWNTZWxlY3RvcjxcbiAgRmxvd01hcFN0YXRlLFxuICBGbG93TWFwRGF0YTxMLCBGPixcbiAgVFxuPjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmxvd01hcFNlbGVjdG9yczxMLCBGPiB7XG4gIGFjY2Vzc29yczogRmxvd01hcEFnZ3JlZ2F0ZUFjY2Vzc29yczxMLCBGPjtcblxuICBjb25zdHJ1Y3RvcihhY2Nlc3NvcnM6IEZsb3dNYXBEYXRhQWNjZXNzb3JzPEwsIEY+KSB7XG4gICAgdGhpcy5hY2Nlc3NvcnMgPSBuZXcgRmxvd01hcEFnZ3JlZ2F0ZUFjY2Vzc29ycyhhY2Nlc3NvcnMpO1xuICAgIHRoaXMuc2V0QWNjZXNzb3JzKGFjY2Vzc29ycyk7XG4gIH1cblxuICBzZXRBY2Nlc3NvcnMoYWNjZXNzb3JzOiBGbG93TWFwRGF0YUFjY2Vzc29yczxMLCBGPikge1xuICAgIHRoaXMuYWNjZXNzb3JzID0gbmV3IEZsb3dNYXBBZ2dyZWdhdGVBY2Nlc3NvcnMoYWNjZXNzb3JzKTtcbiAgfVxuXG4gIGdldEZldGNoZWRGbG93cyA9IChzdGF0ZTogRmxvd01hcFN0YXRlLCBwcm9wczogRmxvd01hcERhdGE8TCwgRj4pID0+XG4gICAgcHJvcHMuZmxvd3M7XG4gIGdldEZldGNoZWRMb2NhdGlvbnMgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHByb3BzLmxvY2F0aW9ucztcbiAgZ2V0U2VsZWN0ZWRMb2NhdGlvbnMgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLmZpbHRlclN0YXRlLnNlbGVjdGVkTG9jYXRpb25zO1xuICBnZXRMb2NhdGlvbkZpbHRlck1vZGUgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLmZpbHRlclN0YXRlLmxvY2F0aW9uRmlsdGVyTW9kZTtcbiAgZ2V0Q2x1c3RlcmluZ0VuYWJsZWQgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLnNldHRpbmdzU3RhdGUuY2x1c3RlcmluZ0VuYWJsZWQ7XG4gIGdldExvY2F0aW9uVG90YWxzRW5hYmxlZCA9IChzdGF0ZTogRmxvd01hcFN0YXRlLCBwcm9wczogRmxvd01hcERhdGE8TCwgRj4pID0+XG4gICAgc3RhdGUuc2V0dGluZ3NTdGF0ZS5sb2NhdGlvblRvdGFsc0VuYWJsZWQ7XG4gIGdldFpvb20gPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLnZpZXdwb3J0Lnpvb207XG4gIGdldFZpZXdwb3J0ID0gKHN0YXRlOiBGbG93TWFwU3RhdGUsIHByb3BzOiBGbG93TWFwRGF0YTxMLCBGPikgPT5cbiAgICBzdGF0ZS52aWV3cG9ydDtcbiAgZ2V0U2VsZWN0ZWRUaW1lUmFuZ2UgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLmZpbHRlclN0YXRlLnNlbGVjdGVkVGltZVJhbmdlO1xuXG4gIGdldENvbG9yU2NoZW1lS2V5OiBTZWxlY3RvcjxMLCBGLCBzdHJpbmcgfCB1bmRlZmluZWQ+ID0gKFxuICAgIHN0YXRlOiBGbG93TWFwU3RhdGUsXG4gICAgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+LFxuICApID0+IHN0YXRlLnNldHRpbmdzU3RhdGUuY29sb3JTY2hlbWU7XG5cbiAgZ2V0RGFya01vZGU6IFNlbGVjdG9yPEwsIEYsIGJvb2xlYW4+ID0gKFxuICAgIHN0YXRlOiBGbG93TWFwU3RhdGUsXG4gICAgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+LFxuICApID0+IHN0YXRlLnNldHRpbmdzU3RhdGUuZGFya01vZGU7XG5cbiAgZ2V0RmFkZUVuYWJsZWQ6IFNlbGVjdG9yPEwsIEYsIGJvb2xlYW4+ID0gKFxuICAgIHN0YXRlOiBGbG93TWFwU3RhdGUsXG4gICAgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+LFxuICApID0+IHN0YXRlLnNldHRpbmdzU3RhdGUuZmFkZUVuYWJsZWQ7XG5cbiAgZ2V0RmFkZUFtb3VudDogU2VsZWN0b3I8TCwgRiwgbnVtYmVyPiA9IChcbiAgICBzdGF0ZTogRmxvd01hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93TWFwRGF0YTxMLCBGPixcbiAgKSA9PiBzdGF0ZS5zZXR0aW5nc1N0YXRlLmZhZGVBbW91bnQ7XG5cbiAgZ2V0QW5pbWF0ZTogU2VsZWN0b3I8TCwgRiwgYm9vbGVhbj4gPSAoXG4gICAgc3RhdGU6IEZsb3dNYXBTdGF0ZSxcbiAgICBwcm9wczogRmxvd01hcERhdGE8TCwgRj4sXG4gICkgPT4gc3RhdGUuc2V0dGluZ3NTdGF0ZS5hbmltYXRpb25FbmFibGVkO1xuXG4gIGdldEludmFsaWRMb2NhdGlvbklkczogU2VsZWN0b3I8TCwgRiwgc3RyaW5nW10gfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRGZXRjaGVkTG9jYXRpb25zLFxuICAgIChsb2NhdGlvbnMpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgaW52YWxpZCA9IFtdO1xuICAgICAgZm9yIChjb25zdCBsb2NhdGlvbiBvZiBsb2NhdGlvbnMpIHtcbiAgICAgICAgY29uc3QgaWQgPSB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGxvY2F0aW9uKTtcbiAgICAgICAgY29uc3QgW2xvbiwgbGF0XSA9IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uQ2VudHJvaWQobG9jYXRpb24pIHx8IFtcbiAgICAgICAgICBOYU4sXG4gICAgICAgICAgTmFOLFxuICAgICAgICBdO1xuICAgICAgICBpZiAoISgtOTAgPD0gbGF0ICYmIGxhdCA8PSA5MCkgfHwgISgtMTgwIDw9IGxvbiAmJiBsb24gPD0gMTgwKSkge1xuICAgICAgICAgIGludmFsaWQucHVzaChpZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBpbnZhbGlkLmxlbmd0aCA+IDAgPyBpbnZhbGlkIDogdW5kZWZpbmVkO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0TG9jYXRpb25zOiBTZWxlY3RvcjxMLCBGLCBMW10gfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRGZXRjaGVkTG9jYXRpb25zLFxuICAgIHRoaXMuZ2V0SW52YWxpZExvY2F0aW9uSWRzLFxuICAgIChsb2NhdGlvbnMsIGludmFsaWRJZHMpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgaWYgKCFpbnZhbGlkSWRzIHx8IGludmFsaWRJZHMubGVuZ3RoID09PSAwKSByZXR1cm4gbG9jYXRpb25zO1xuICAgICAgY29uc3QgaW52YWxpZCA9IG5ldyBTZXQoaW52YWxpZElkcyk7XG4gICAgICByZXR1cm4gbG9jYXRpb25zLmZpbHRlcihcbiAgICAgICAgKGxvY2F0aW9uOiBMKSA9PiAhaW52YWxpZC5oYXModGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25JZChsb2NhdGlvbikpLFxuICAgICAgKTtcbiAgICB9LFxuICApO1xuXG4gIGdldExvY2F0aW9uSWRzOiBTZWxlY3RvcjxMLCBGLCBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9ucyxcbiAgICAobG9jYXRpb25zKSA9PlxuICAgICAgbG9jYXRpb25zXG4gICAgICAgID8gbmV3IFNldChsb2NhdGlvbnMubWFwKHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQpKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgKTtcblxuICBnZXRTZWxlY3RlZExvY2F0aW9uc1NldDogU2VsZWN0b3I8TCwgRiwgU2V0PHN0cmluZz4gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3Rvcih0aGlzLmdldFNlbGVjdGVkTG9jYXRpb25zLCAoaWRzKSA9PlxuICAgICAgaWRzICYmIGlkcy5sZW5ndGggPiAwID8gbmV3IFNldChpZHMpIDogdW5kZWZpbmVkLFxuICAgICk7XG5cbiAgZ2V0U29ydGVkRmxvd3NGb3JLbm93bkxvY2F0aW9uczogU2VsZWN0b3I8TCwgRiwgRltdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IodGhpcy5nZXRGZXRjaGVkRmxvd3MsIHRoaXMuZ2V0TG9jYXRpb25JZHMsIChmbG93cywgaWRzKSA9PiB7XG4gICAgICBpZiAoIWlkcyB8fCAhZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gZmxvd3NcbiAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAoZmxvdzogRikgPT5cbiAgICAgICAgICAgIGlkcy5oYXModGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGZsb3cpKSAmJlxuICAgICAgICAgICAgaWRzLmhhcyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZsb3cpKSxcbiAgICAgICAgKVxuICAgICAgICAuc29ydCgoYTogRiwgYjogRikgPT5cbiAgICAgICAgICBkZXNjZW5kaW5nKFxuICAgICAgICAgICAgTWF0aC5hYnModGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShhKSksXG4gICAgICAgICAgICBNYXRoLmFicyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGIpKSxcbiAgICAgICAgICApLFxuICAgICAgICApO1xuICAgIH0pO1xuXG4gIGdldEFjdHVhbFRpbWVFeHRlbnQ6IFNlbGVjdG9yPEwsIEYsIFtEYXRlLCBEYXRlXSB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKHRoaXMuZ2V0U29ydGVkRmxvd3NGb3JLbm93bkxvY2F0aW9ucywgKGZsb3dzKSA9PiB7XG4gICAgICBpZiAoIWZsb3dzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgbGV0IHN0YXJ0ID0gbnVsbDtcbiAgICAgIGxldCBlbmQgPSBudWxsO1xuICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgIGNvbnN0IHRpbWUgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93VGltZShmbG93KTtcbiAgICAgICAgaWYgKHRpbWUpIHtcbiAgICAgICAgICBpZiAoc3RhcnQgPT0gbnVsbCB8fCBzdGFydCA+IHRpbWUpIHN0YXJ0ID0gdGltZTtcbiAgICAgICAgICBpZiAoZW5kID09IG51bGwgfHwgZW5kIDwgdGltZSkgZW5kID0gdGltZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFzdGFydCB8fCAhZW5kKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIFtzdGFydCwgZW5kXTtcbiAgICB9KTtcblxuICBnZXRUaW1lR3JhbnVsYXJpdHlLZXk6IFNlbGVjdG9yPEwsIEYsIFRpbWVHcmFudWxhcml0eUtleSB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLFxuICAgICAgdGhpcy5nZXRBY3R1YWxUaW1lRXh0ZW50LFxuICAgICAgKGZsb3dzLCB0aW1lRXh0ZW50KSA9PiB7XG4gICAgICAgIGlmICghZmxvd3MgfHwgIXRpbWVFeHRlbnQpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgICAgY29uc3QgbWluT3JkZXIgPSBtaW4oZmxvd3MsIChkKSA9PiB7XG4gICAgICAgICAgY29uc3QgdCA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dUaW1lKGQpO1xuICAgICAgICAgIHJldHVybiB0ID8gZ2V0VGltZUdyYW51bGFyaXR5Rm9yRGF0ZSh0KS5vcmRlciA6IG51bGw7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAobWluT3JkZXIgPT0gbnVsbCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgdGltZUdyYW51bGFyaXR5ID0gZ2V0VGltZUdyYW51bGFyaXR5QnlPcmRlcihtaW5PcmRlcik7XG4gICAgICAgIHJldHVybiB0aW1lR3JhbnVsYXJpdHkgPyB0aW1lR3JhbnVsYXJpdHkua2V5IDogdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldFRpbWVFeHRlbnQ6IFNlbGVjdG9yPEwsIEYsIFtEYXRlLCBEYXRlXSB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldEFjdHVhbFRpbWVFeHRlbnQsXG4gICAgdGhpcy5nZXRUaW1lR3JhbnVsYXJpdHlLZXksXG4gICAgKHRpbWVFeHRlbnQsIHRpbWVHcmFudWxhcml0eUtleSkgPT4ge1xuICAgICAgY29uc3QgdGltZUdyYW51bGFyaXR5ID0gdGltZUdyYW51bGFyaXR5S2V5XG4gICAgICAgID8gZ2V0VGltZUdyYW51bGFyaXR5QnlLZXkodGltZUdyYW51bGFyaXR5S2V5KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgIGlmICghdGltZUV4dGVudCB8fCAhdGltZUdyYW51bGFyaXR5Py5pbnRlcnZhbCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHtpbnRlcnZhbH0gPSB0aW1lR3JhbnVsYXJpdHk7XG4gICAgICByZXR1cm4gW3RpbWVFeHRlbnRbMF0sIGludGVydmFsLm9mZnNldChpbnRlcnZhbC5mbG9vcih0aW1lRXh0ZW50WzFdKSwgMSldO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0U29ydGVkRmxvd3NGb3JLbm93bkxvY2F0aW9uc0ZpbHRlcmVkQnlUaW1lOiBTZWxlY3RvcjxcbiAgICBMLFxuICAgIEYsXG4gICAgRltdIHwgdW5kZWZpbmVkXG4gID4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnMsXG4gICAgdGhpcy5nZXRUaW1lRXh0ZW50LFxuICAgIHRoaXMuZ2V0U2VsZWN0ZWRUaW1lUmFuZ2UsXG4gICAgKGZsb3dzLCB0aW1lRXh0ZW50LCB0aW1lUmFuZ2UpID0+IHtcbiAgICAgIGlmICghZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBpZiAoXG4gICAgICAgICF0aW1lRXh0ZW50IHx8XG4gICAgICAgICF0aW1lUmFuZ2UgfHxcbiAgICAgICAgKHRpbWVFeHRlbnRbMF0gPT09IHRpbWVSYW5nZVswXSAmJiB0aW1lRXh0ZW50WzFdID09PSB0aW1lUmFuZ2VbMV0pXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIGZsb3dzO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZsb3dzLmZpbHRlcigoZmxvdykgPT4ge1xuICAgICAgICBjb25zdCB0aW1lID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd1RpbWUoZmxvdyk7XG4gICAgICAgIHJldHVybiB0aW1lICYmIHRpbWVSYW5nZVswXSA8PSB0aW1lICYmIHRpbWUgPCB0aW1lUmFuZ2VbMV07XG4gICAgICB9KTtcbiAgICB9LFxuICApO1xuXG4gIGdldExvY2F0aW9uc0hhdmluZ0Zsb3dzOiBTZWxlY3RvcjxMLCBGLCBMW10gfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLFxuICAgIHRoaXMuZ2V0TG9jYXRpb25zLFxuICAgIChmbG93cywgbG9jYXRpb25zKSA9PiB7XG4gICAgICBpZiAoIWxvY2F0aW9ucyB8fCAhZmxvd3MpIHJldHVybiBsb2NhdGlvbnM7XG4gICAgICBjb25zdCB3aXRoRmxvd3MgPSBuZXcgU2V0KCk7XG4gICAgICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MpIHtcbiAgICAgICAgd2l0aEZsb3dzLmFkZCh0aGlzLmFjY2Vzc29ycy5nZXRGbG93T3JpZ2luSWQoZmxvdykpO1xuICAgICAgICB3aXRoRmxvd3MuYWRkKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoZmxvdykpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxvY2F0aW9ucy5maWx0ZXIoKGxvY2F0aW9uOiBMKSA9PlxuICAgICAgICB3aXRoRmxvd3MuaGFzKHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQobG9jYXRpb24pKSxcbiAgICAgICk7XG4gICAgfSxcbiAgKTtcblxuICBnZXRMb2NhdGlvbnNCeUlkOiBTZWxlY3RvcjxMLCBGLCBNYXA8c3RyaW5nLCBMPiB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uc0hhdmluZ0Zsb3dzLFxuICAgIChsb2NhdGlvbnMpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIG5lc3Q8TCwgTD4oKVxuICAgICAgICAua2V5KChkOiBMKSA9PiB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGQpKVxuICAgICAgICAucm9sbHVwKChbZF0pID0+IGQpXG4gICAgICAgIC5tYXAobG9jYXRpb25zKSBhcyBhbnkgYXMgTWFwPHN0cmluZywgTD47XG4gICAgfSxcbiAgKTtcblxuICBnZXRDbHVzdGVySW5kZXg6IFNlbGVjdG9yPEwsIEYsIENsdXN0ZXJJbmRleDxGPiB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uc0hhdmluZ0Zsb3dzLFxuICAgIHRoaXMuZ2V0TG9jYXRpb25zQnlJZCxcbiAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnMsXG4gICAgKGxvY2F0aW9ucywgbG9jYXRpb25zQnlJZCwgZmxvd3MpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zIHx8ICFsb2NhdGlvbnNCeUlkIHx8ICFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgY29uc3QgZ2V0TG9jYXRpb25XZWlnaHQgPSBtYWtlTG9jYXRpb25XZWlnaHRHZXR0ZXIoXG4gICAgICAgIGZsb3dzLFxuICAgICAgICB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFwRGF0YUFjY2Vzc29ycygpLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGNsdXN0ZXJMZXZlbHMgPSBjbHVzdGVyTG9jYXRpb25zKFxuICAgICAgICBsb2NhdGlvbnMsXG4gICAgICAgIHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYXBEYXRhQWNjZXNzb3JzKCksXG4gICAgICAgIGdldExvY2F0aW9uV2VpZ2h0LFxuICAgICAgICB7XG4gICAgICAgICAgbWF4Wm9vbTogTUFYX0NMVVNURVJfWk9PTV9MRVZFTCxcbiAgICAgICAgfSxcbiAgICAgICk7XG4gICAgICBjb25zdCBjbHVzdGVySW5kZXggPSBidWlsZEluZGV4PEY+KGNsdXN0ZXJMZXZlbHMpO1xuICAgICAgY29uc3Qge2dldExvY2F0aW9uTmFtZSwgZ2V0TG9jYXRpb25DbHVzdGVyTmFtZX0gPVxuICAgICAgICB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFwRGF0YUFjY2Vzc29ycygpO1xuXG4gICAgICAvLyBBZGRpbmcgbWVhbmluZ2Z1bCBuYW1lc1xuICAgICAgY29uc3QgZ2V0TmFtZSA9IChpZDogc3RyaW5nKSA9PiB7XG4gICAgICAgIGNvbnN0IGxvYyA9IGxvY2F0aW9uc0J5SWQuZ2V0KGlkKTtcbiAgICAgICAgaWYgKGxvYykge1xuICAgICAgICAgIHJldHVybiBnZXRMb2NhdGlvbk5hbWVcbiAgICAgICAgICAgID8gZ2V0TG9jYXRpb25OYW1lKGxvYylcbiAgICAgICAgICAgIDogdGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25JZChsb2MpIHx8IGlkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBgXCIke2lkfVwiYDtcbiAgICAgIH07XG4gICAgICBmb3IgKGNvbnN0IGxldmVsIG9mIGNsdXN0ZXJMZXZlbHMpIHtcbiAgICAgICAgZm9yIChjb25zdCBub2RlIG9mIGxldmVsLm5vZGVzKSB7XG4gICAgICAgICAgLy8gSGVyZSBtdXRhdGluZyB0aGUgbm9kZXMgKGFkZGluZyBuYW1lcylcbiAgICAgICAgICBpZiAoaXNDbHVzdGVyKG5vZGUpKSB7XG4gICAgICAgICAgICBjb25zdCBsZWF2ZXMgPSBjbHVzdGVySW5kZXguZXhwYW5kQ2x1c3Rlcihub2RlKTtcblxuICAgICAgICAgICAgbGVhdmVzLnNvcnQoKGEsIGIpID0+XG4gICAgICAgICAgICAgIGRlc2NlbmRpbmcoZ2V0TG9jYXRpb25XZWlnaHQoYSksIGdldExvY2F0aW9uV2VpZ2h0KGIpKSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGlmIChnZXRMb2NhdGlvbkNsdXN0ZXJOYW1lKSB7XG4gICAgICAgICAgICAgIG5vZGUubmFtZSA9IGdldExvY2F0aW9uQ2x1c3Rlck5hbWUobGVhdmVzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNvbnN0IHRvcElkID0gbGVhdmVzWzBdO1xuICAgICAgICAgICAgICBjb25zdCBvdGhlcklkID0gbGVhdmVzLmxlbmd0aCA9PT0gMiA/IGxlYXZlc1sxXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgbm9kZS5uYW1lID0gYFwiJHtnZXROYW1lKHRvcElkKX1cIiBhbmQgJHtcbiAgICAgICAgICAgICAgICBvdGhlcklkXG4gICAgICAgICAgICAgICAgICA/IGBcIiR7Z2V0TmFtZShvdGhlcklkKX1cImBcbiAgICAgICAgICAgICAgICAgIDogYCR7bGVhdmVzLmxlbmd0aCAtIDF9IG90aGVyc2BcbiAgICAgICAgICAgICAgfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIChub2RlIGFzIGFueSkubmFtZSA9IGdldE5hbWUobm9kZS5pZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjbHVzdGVySW5kZXg7XG4gICAgfSxcbiAgKTtcblxuICBnZXRBdmFpbGFibGVDbHVzdGVyWm9vbUxldmVscyA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0Q2x1c3RlckluZGV4LFxuICAgIHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnMsXG4gICAgKGNsdXN0ZXJJbmRleCwgc2VsZWN0ZWRMb2NhdGlvbnMpOiBudW1iZXJbXSB8IHVuZGVmaW5lZCA9PiB7XG4gICAgICBpZiAoIWNsdXN0ZXJJbmRleCkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBsZXQgbWF4Wm9vbSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgIGxldCBtaW5ab29tID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZO1xuXG4gICAgICBjb25zdCBhZGp1c3QgPSAoem9uZUlkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgY2x1c3RlciA9IGNsdXN0ZXJJbmRleC5nZXRDbHVzdGVyQnlJZCh6b25lSWQpO1xuICAgICAgICBpZiAoY2x1c3Rlcikge1xuICAgICAgICAgIG1pblpvb20gPSBNYXRoLm1heChtaW5ab29tLCBjbHVzdGVyLnpvb20pO1xuICAgICAgICAgIG1heFpvb20gPSBNYXRoLm1pbihtYXhab29tLCBjbHVzdGVyLnpvb20pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IHpvb20gPSBjbHVzdGVySW5kZXguZ2V0TWluWm9vbUZvckxvY2F0aW9uKHpvbmVJZCk7XG4gICAgICAgICAgbWluWm9vbSA9IE1hdGgubWF4KG1pblpvb20sIHpvb20pO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBpZiAoc2VsZWN0ZWRMb2NhdGlvbnMpIHtcbiAgICAgICAgZm9yIChjb25zdCBpZCBvZiBzZWxlY3RlZExvY2F0aW9ucykge1xuICAgICAgICAgIGFkanVzdChpZCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNsdXN0ZXJJbmRleC5hdmFpbGFibGVab29tTGV2ZWxzLmZpbHRlcihcbiAgICAgICAgKGxldmVsKSA9PiBtaW5ab29tIDw9IGxldmVsICYmIGxldmVsIDw9IG1heFpvb20sXG4gICAgICApO1xuICAgIH0sXG4gICk7XG5cbiAgX2dldENsdXN0ZXJab29tOiBTZWxlY3RvcjxMLCBGLCBudW1iZXIgfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRDbHVzdGVySW5kZXgsXG4gICAgdGhpcy5nZXRab29tLFxuICAgIHRoaXMuZ2V0QXZhaWxhYmxlQ2x1c3Rlclpvb21MZXZlbHMsXG4gICAgKGNsdXN0ZXJJbmRleCwgbWFwWm9vbSwgYXZhaWxhYmxlQ2x1c3Rlclpvb21MZXZlbHMpID0+IHtcbiAgICAgIGlmICghY2x1c3RlckluZGV4KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgaWYgKCFhdmFpbGFibGVDbHVzdGVyWm9vbUxldmVscykge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjbHVzdGVyWm9vbSA9IGZpbmRBcHByb3ByaWF0ZVpvb21MZXZlbChcbiAgICAgICAgYXZhaWxhYmxlQ2x1c3Rlclpvb21MZXZlbHMsXG4gICAgICAgIG1hcFpvb20sXG4gICAgICApO1xuICAgICAgcmV0dXJuIGNsdXN0ZXJab29tO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0Q2x1c3Rlclpvb20gPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PiB7XG4gICAgY29uc3Qge3NldHRpbmdzU3RhdGV9ID0gc3RhdGU7XG4gICAgaWYgKCFzZXR0aW5nc1N0YXRlLmNsdXN0ZXJpbmdFbmFibGVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChzZXR0aW5nc1N0YXRlLmNsdXN0ZXJpbmdBdXRvIHx8IHNldHRpbmdzU3RhdGUuY2x1c3RlcmluZ0xldmVsID09IG51bGwpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRDbHVzdGVyWm9vbShzdGF0ZSwgcHJvcHMpO1xuICAgIH1cbiAgICByZXR1cm4gc2V0dGluZ3NTdGF0ZS5jbHVzdGVyaW5nTGV2ZWw7XG4gIH07XG5cbiAgZ2V0TG9jYXRpb25zRm9yU2VhcmNoQm94OiBTZWxlY3RvcjxMLCBGLCAoTCB8IENsdXN0ZXIpW10gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0Q2x1c3RlcmluZ0VuYWJsZWQsXG4gICAgICB0aGlzLmdldExvY2F0aW9uc0hhdmluZ0Zsb3dzLFxuICAgICAgdGhpcy5nZXRTZWxlY3RlZExvY2F0aW9ucyxcbiAgICAgIHRoaXMuZ2V0Q2x1c3Rlclpvb20sXG4gICAgICB0aGlzLmdldENsdXN0ZXJJbmRleCxcbiAgICAgIChcbiAgICAgICAgY2x1c3RlcmluZ0VuYWJsZWQsXG4gICAgICAgIGxvY2F0aW9ucyxcbiAgICAgICAgc2VsZWN0ZWRMb2NhdGlvbnMsXG4gICAgICAgIGNsdXN0ZXJab29tLFxuICAgICAgICBjbHVzdGVySW5kZXgsXG4gICAgICApID0+IHtcbiAgICAgICAgaWYgKCFsb2NhdGlvbnMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGxldCByZXN1bHQ6IChMIHwgQ2x1c3RlcilbXSA9IGxvY2F0aW9ucztcbiAgICAgICAgLy8gaWYgKGNsdXN0ZXJpbmdFbmFibGVkKSB7XG4gICAgICAgIC8vICAgaWYgKGNsdXN0ZXJJbmRleCkge1xuICAgICAgICAvLyAgICAgY29uc3Qgem9vbUl0ZW1zID0gY2x1c3RlckluZGV4LmdldENsdXN0ZXJOb2Rlc0ZvcihjbHVzdGVyWm9vbSk7XG4gICAgICAgIC8vICAgICBpZiAoem9vbUl0ZW1zKSB7XG4gICAgICAgIC8vICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQoem9vbUl0ZW1zLmZpbHRlcihpc0NsdXN0ZXIpKTtcbiAgICAgICAgLy8gICAgIH1cbiAgICAgICAgLy8gICB9XG4gICAgICAgIC8vIH1cblxuICAgICAgICBpZiAocmVzdWx0ICYmIGNsdXN0ZXJJbmRleCAmJiBzZWxlY3RlZExvY2F0aW9ucykge1xuICAgICAgICAgIGNvbnN0IHRvQXBwZW5kID0gW107XG4gICAgICAgICAgZm9yIChjb25zdCBpZCBvZiBzZWxlY3RlZExvY2F0aW9ucykge1xuICAgICAgICAgICAgY29uc3QgY2x1c3RlciA9IGNsdXN0ZXJJbmRleC5nZXRDbHVzdGVyQnlJZChpZCk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIGNsdXN0ZXIgJiZcbiAgICAgICAgICAgICAgIXJlc3VsdC5maW5kKFxuICAgICAgICAgICAgICAgIChkKSA9PlxuICAgICAgICAgICAgICAgICAgKGlzTG9jYXRpb25DbHVzdGVyTm9kZShkKVxuICAgICAgICAgICAgICAgICAgICA/IGQuaWRcbiAgICAgICAgICAgICAgICAgICAgOiB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGQpKSA9PT0gaWQsXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICB0b0FwcGVuZC5wdXNoKGNsdXN0ZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodG9BcHBlbmQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdCh0b0FwcGVuZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0RGlmZk1vZGU6IFNlbGVjdG9yPEwsIEYsIGJvb2xlYW4+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRGZXRjaGVkRmxvd3MsXG4gICAgKGZsb3dzKSA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIGZsb3dzICYmXG4gICAgICAgIGZsb3dzLmZpbmQoKGY6IEYpID0+IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoZikgPCAwKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICk7XG5cbiAgX2dldEZsb3dNYXBDb2xvcnMgPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldERpZmZNb2RlLFxuICAgIHRoaXMuZ2V0Q29sb3JTY2hlbWVLZXksXG4gICAgdGhpcy5nZXREYXJrTW9kZSxcbiAgICB0aGlzLmdldEZhZGVFbmFibGVkLFxuICAgIHRoaXMuZ2V0RmFkZUFtb3VudCxcbiAgICB0aGlzLmdldEFuaW1hdGUsXG4gICAgZ2V0Q29sb3JzLFxuICApO1xuXG4gIGdldEZsb3dNYXBDb2xvcnNSR0JBID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5fZ2V0Rmxvd01hcENvbG9ycyxcbiAgICAoZmxvd01hcENvbG9ycykgPT4ge1xuICAgICAgcmV0dXJuIGlzRGlmZkNvbG9ycyhmbG93TWFwQ29sb3JzKVxuICAgICAgICA/IGdldERpZmZDb2xvcnNSR0JBKGZsb3dNYXBDb2xvcnMpXG4gICAgICAgIDogZ2V0Q29sb3JzUkdCQShmbG93TWFwQ29sb3JzKTtcbiAgICB9LFxuICApO1xuXG4gIGdldFVua25vd25Mb2NhdGlvbnM6IFNlbGVjdG9yPEwsIEYsIFNldDxzdHJpbmc+IHwgdW5kZWZpbmVkPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25JZHMsXG4gICAgdGhpcy5nZXRGZXRjaGVkRmxvd3MsXG4gICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLFxuICAgIChpZHMsIGZsb3dzLCBmbG93c0Zvcktub3duTG9jYXRpb25zKSA9PiB7XG4gICAgICBpZiAoIWlkcyB8fCAhZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBpZiAoXG4gICAgICAgIGZsb3dzRm9yS25vd25Mb2NhdGlvbnMgJiZcbiAgICAgICAgZmxvd3MubGVuZ3RoID09PSBmbG93c0Zvcktub3duTG9jYXRpb25zLmxlbmd0aFxuICAgICAgKVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgbWlzc2luZyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgIGlmICghaWRzLmhhcyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93T3JpZ2luSWQoZmxvdykpKVxuICAgICAgICAgIG1pc3NpbmcuYWRkKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmbG93KSk7XG4gICAgICAgIGlmICghaWRzLmhhcyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZsb3cpKSlcbiAgICAgICAgICBtaXNzaW5nLmFkZCh0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZsb3cpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtaXNzaW5nO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0U29ydGVkQWdncmVnYXRlZEZpbHRlcmVkRmxvd3M6IFNlbGVjdG9yPFxuICAgIEwsXG4gICAgRixcbiAgICAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW10gfCB1bmRlZmluZWRcbiAgPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0Q2x1c3RlckluZGV4LFxuICAgIHRoaXMuZ2V0Q2x1c3RlcmluZ0VuYWJsZWQsXG4gICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zRmlsdGVyZWRCeVRpbWUsXG4gICAgdGhpcy5nZXRDbHVzdGVyWm9vbSxcbiAgICB0aGlzLmdldFRpbWVFeHRlbnQsXG4gICAgKGNsdXN0ZXJUcmVlLCBpc0NsdXN0ZXJpbmdFbmFibGVkLCBmbG93cywgY2x1c3Rlclpvb20sIHRpbWVFeHRlbnQpID0+IHtcbiAgICAgIGlmICghZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBsZXQgYWdncmVnYXRlZDogKEYgfCBBZ2dyZWdhdGVGbG93KVtdO1xuICAgICAgaWYgKGlzQ2x1c3RlcmluZ0VuYWJsZWQgJiYgY2x1c3RlclRyZWUgJiYgY2x1c3Rlclpvb20gIT0gbnVsbCkge1xuICAgICAgICBhZ2dyZWdhdGVkID0gY2x1c3RlclRyZWUuYWdncmVnYXRlRmxvd3MoXG4gICAgICAgICAgLy8gVE9ETzogYWdncmVnYXRlIGFjcm9zcyB0aW1lXG4gICAgICAgICAgLy8gdGltZUV4dGVudCAhPSBudWxsXG4gICAgICAgICAgLy8gICA/IGFnZ3JlZ2F0ZUZsb3dzKGZsb3dzKSAvLyBjbHVzdGVyVHJlZS5hZ2dyZWdhdGVGbG93cyB3b24ndCBhZ2dyZWdhdGUgdW5jbHVzdGVyZWQgYWNyb3NzIHRpbWVcbiAgICAgICAgICAvLyAgIDogZmxvd3MsXG4gICAgICAgICAgZmxvd3MsXG4gICAgICAgICAgY2x1c3Rlclpvb20sXG4gICAgICAgICAgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hcERhdGFBY2Nlc3NvcnMoKSxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFnZ3JlZ2F0ZWQgPSBhZ2dyZWdhdGVGbG93cyhcbiAgICAgICAgICBmbG93cyxcbiAgICAgICAgICB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFwRGF0YUFjY2Vzc29ycygpLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgYWdncmVnYXRlZC5zb3J0KChhLCBiKSA9PlxuICAgICAgICBkZXNjZW5kaW5nKFxuICAgICAgICAgIE1hdGguYWJzKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoYSkpLFxuICAgICAgICAgIE1hdGguYWJzKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoYikpLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBhZ2dyZWdhdGVkO1xuICAgIH0sXG4gICk7XG5cbiAgX2dldEZsb3dNYWduaXR1ZGVFeHRlbnQ6IFNlbGVjdG9yPEwsIEYsIFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0U29ydGVkQWdncmVnYXRlZEZpbHRlcmVkRmxvd3MsXG4gICAgICB0aGlzLmdldFNlbGVjdGVkTG9jYXRpb25zU2V0LFxuICAgICAgdGhpcy5nZXRMb2NhdGlvbkZpbHRlck1vZGUsXG4gICAgICAoZmxvd3MsIHNlbGVjdGVkTG9jYXRpb25zU2V0LCBsb2NhdGlvbkZpbHRlck1vZGUpID0+IHtcbiAgICAgICAgaWYgKCFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHJ2OiBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgICAgICBmb3IgKGNvbnN0IGYgb2YgZmxvd3MpIHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLmFjY2Vzc29ycy5nZXRGbG93T3JpZ2luSWQoZikgIT09XG4gICAgICAgICAgICAgIHRoaXMuYWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoZikgJiZcbiAgICAgICAgICAgIHRoaXMuaXNGbG93SW5TZWxlY3Rpb24oZiwgc2VsZWN0ZWRMb2NhdGlvbnNTZXQsIGxvY2F0aW9uRmlsdGVyTW9kZSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IGNvdW50ID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmKTtcbiAgICAgICAgICAgIGlmIChydiA9PSBudWxsKSB7XG4gICAgICAgICAgICAgIHJ2ID0gW2NvdW50LCBjb3VudF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoY291bnQgPCBydlswXSkgcnZbMF0gPSBjb3VudDtcbiAgICAgICAgICAgICAgaWYgKGNvdW50ID4gcnZbMV0pIHJ2WzFdID0gY291bnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBydjtcbiAgICAgIH0sXG4gICAgKTtcblxuICBnZXRFeHBhbmRlZFNlbGVjdGVkTG9jYXRpb25zU2V0OiBTZWxlY3RvcjxMLCBGLCBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRDbHVzdGVyaW5nRW5hYmxlZCxcbiAgICAgIHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgICB0aGlzLmdldENsdXN0ZXJJbmRleCxcbiAgICAgIChjbHVzdGVyaW5nRW5hYmxlZCwgc2VsZWN0ZWRMb2NhdGlvbnMsIGNsdXN0ZXJJbmRleCkgPT4ge1xuICAgICAgICBpZiAoIXNlbGVjdGVkTG9jYXRpb25zIHx8ICFjbHVzdGVySW5kZXgpIHtcbiAgICAgICAgICByZXR1cm4gc2VsZWN0ZWRMb2NhdGlvbnM7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgICAgZm9yIChjb25zdCBsb2NhdGlvbklkIG9mIHNlbGVjdGVkTG9jYXRpb25zKSB7XG4gICAgICAgICAgY29uc3QgY2x1c3RlciA9IGNsdXN0ZXJJbmRleC5nZXRDbHVzdGVyQnlJZChsb2NhdGlvbklkKTtcbiAgICAgICAgICBpZiAoY2x1c3Rlcikge1xuICAgICAgICAgICAgY29uc3QgZXhwYW5kZWQgPSBjbHVzdGVySW5kZXguZXhwYW5kQ2x1c3RlcihjbHVzdGVyKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaWQgb2YgZXhwYW5kZWQpIHtcbiAgICAgICAgICAgICAgcmVzdWx0LmFkZChpZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdC5hZGQobG9jYXRpb25JZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0VG90YWxDb3VudHNCeVRpbWU6IFNlbGVjdG9yPEwsIEYsIENvdW50QnlUaW1lW10gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0U29ydGVkRmxvd3NGb3JLbm93bkxvY2F0aW9ucyxcbiAgICAgIHRoaXMuZ2V0VGltZUdyYW51bGFyaXR5S2V5LFxuICAgICAgdGhpcy5nZXRUaW1lRXh0ZW50LFxuICAgICAgdGhpcy5nZXRFeHBhbmRlZFNlbGVjdGVkTG9jYXRpb25zU2V0LFxuICAgICAgdGhpcy5nZXRMb2NhdGlvbkZpbHRlck1vZGUsXG4gICAgICAoXG4gICAgICAgIGZsb3dzLFxuICAgICAgICB0aW1lR3JhbnVsYXJpdHlLZXksXG4gICAgICAgIHRpbWVFeHRlbnQsXG4gICAgICAgIHNlbGVjdGVkTG9jYXRpb25TZXQsXG4gICAgICAgIGxvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAgICkgPT4ge1xuICAgICAgICBjb25zdCB0aW1lR3JhbnVsYXJpdHkgPSB0aW1lR3JhbnVsYXJpdHlLZXlcbiAgICAgICAgICA/IGdldFRpbWVHcmFudWxhcml0eUJ5S2V5KHRpbWVHcmFudWxhcml0eUtleSlcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKCFmbG93cyB8fCAhdGltZUdyYW51bGFyaXR5IHx8ICF0aW1lRXh0ZW50KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBieVRpbWUgPSBmbG93cy5yZWR1Y2UoKG0sIGZsb3cpID0+IHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLmlzRmxvd0luU2VsZWN0aW9uKFxuICAgICAgICAgICAgICBmbG93LFxuICAgICAgICAgICAgICBzZWxlY3RlZExvY2F0aW9uU2V0LFxuICAgICAgICAgICAgICBsb2NhdGlvbkZpbHRlck1vZGUsXG4gICAgICAgICAgICApXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBrZXkgPSB0aW1lR3JhbnVsYXJpdHlcbiAgICAgICAgICAgICAgLmludGVydmFsKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dUaW1lKGZsb3cpKVxuICAgICAgICAgICAgICAuZ2V0VGltZSgpO1xuICAgICAgICAgICAgbS5zZXQoXG4gICAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgICAgKG0uZ2V0KGtleSkgPz8gMCkgKyB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGZsb3cpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG07XG4gICAgICAgIH0sIG5ldyBNYXA8bnVtYmVyLCBudW1iZXI+KCkpO1xuXG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKGJ5VGltZS5lbnRyaWVzKCkpLm1hcCgoW21pbGxpcywgY291bnRdKSA9PiAoe1xuICAgICAgICAgIHRpbWU6IG5ldyBEYXRlKG1pbGxpcyksXG4gICAgICAgICAgY291bnQsXG4gICAgICAgIH0pKTtcbiAgICAgIH0sXG4gICAgKTtcblxuICBnZXRNYXhMb2NhdGlvbkNpcmNsZVNpemU6IFNlbGVjdG9yPEwsIEYsIG51bWJlcj4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uVG90YWxzRW5hYmxlZCxcbiAgICAobG9jYXRpb25Ub3RhbHNFbmFibGVkKSA9PiAobG9jYXRpb25Ub3RhbHNFbmFibGVkID8gMTcgOiAxKSxcbiAgKTtcblxuICBnZXRWaWV3cG9ydEJvdW5kaW5nQm94OiBTZWxlY3RvcjxMLCBGLCBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXT4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRWaWV3cG9ydCxcbiAgICAgIHRoaXMuZ2V0TWF4TG9jYXRpb25DaXJjbGVTaXplLFxuICAgICAgKHZpZXdwb3J0LCBtYXhMb2NhdGlvbkNpcmNsZVNpemUpID0+IHtcbiAgICAgICAgY29uc3QgcGFkID0gbWF4TG9jYXRpb25DaXJjbGVTaXplO1xuICAgICAgICByZXR1cm4gYm91bmRzKFxuICAgICAgICAgIFt2aWV3cG9ydC5sb25naXR1ZGUsIHZpZXdwb3J0LmxhdGl0dWRlXSxcbiAgICAgICAgICB2aWV3cG9ydC56b29tLFxuICAgICAgICAgIFt2aWV3cG9ydC53aWR0aCArIHBhZCAqIDIsIHZpZXdwb3J0LmhlaWdodCArIHBhZCAqIDJdLFxuICAgICAgICAgIDUxMixcbiAgICAgICAgKTtcbiAgICAgIH0sXG4gICAgKTtcblxuICBnZXRMb2NhdGlvbnNGb3Jab29tOiBTZWxlY3RvcjxMLCBGLCBMW10gfCBDbHVzdGVyTm9kZVtdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldENsdXN0ZXJpbmdFbmFibGVkLFxuICAgICAgdGhpcy5nZXRMb2NhdGlvbnNIYXZpbmdGbG93cyxcbiAgICAgIHRoaXMuZ2V0Q2x1c3RlckluZGV4LFxuICAgICAgdGhpcy5nZXRDbHVzdGVyWm9vbSxcbiAgICAgIChjbHVzdGVyaW5nRW5hYmxlZCwgbG9jYXRpb25zSGF2aW5nRmxvd3MsIGNsdXN0ZXJJbmRleCwgY2x1c3Rlclpvb20pID0+IHtcbiAgICAgICAgaWYgKGNsdXN0ZXJpbmdFbmFibGVkICYmIGNsdXN0ZXJJbmRleCkge1xuICAgICAgICAgIHJldHVybiBjbHVzdGVySW5kZXguZ2V0Q2x1c3Rlck5vZGVzRm9yKGNsdXN0ZXJab29tKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gbG9jYXRpb25zSGF2aW5nRmxvd3M7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgKTtcblxuICBnZXRMb2NhdGlvblRvdGFsczogU2VsZWN0b3I8TCwgRiwgTWFwPHN0cmluZywgTG9jYXRpb25Ub3RhbHM+IHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldExvY2F0aW9uc0Zvclpvb20sXG4gICAgICB0aGlzLmdldFNvcnRlZEFnZ3JlZ2F0ZWRGaWx0ZXJlZEZsb3dzLFxuICAgICAgdGhpcy5nZXRTZWxlY3RlZExvY2F0aW9uc1NldCxcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25GaWx0ZXJNb2RlLFxuICAgICAgKGxvY2F0aW9ucywgZmxvd3MsIHNlbGVjdGVkTG9jYXRpb25zU2V0LCBsb2NhdGlvbkZpbHRlck1vZGUpID0+IHtcbiAgICAgICAgaWYgKCFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgdG90YWxzID0gbmV3IE1hcDxzdHJpbmcsIExvY2F0aW9uVG90YWxzPigpO1xuICAgICAgICBjb25zdCBhZGQgPSAoXG4gICAgICAgICAgaWQ6IHN0cmluZyxcbiAgICAgICAgICBkOiBQYXJ0aWFsPExvY2F0aW9uVG90YWxzPixcbiAgICAgICAgKTogTG9jYXRpb25Ub3RhbHMgPT4ge1xuICAgICAgICAgIGNvbnN0IHJ2ID0gdG90YWxzLmdldChpZCkgPz8ge1xuICAgICAgICAgICAgaW5jb21pbmdDb3VudDogMCxcbiAgICAgICAgICAgIG91dGdvaW5nQ291bnQ6IDAsXG4gICAgICAgICAgICBpbnRlcm5hbENvdW50OiAwLFxuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKGQuaW5jb21pbmdDb3VudCAhPSBudWxsKSBydi5pbmNvbWluZ0NvdW50ICs9IGQuaW5jb21pbmdDb3VudDtcbiAgICAgICAgICBpZiAoZC5vdXRnb2luZ0NvdW50ICE9IG51bGwpIHJ2Lm91dGdvaW5nQ291bnQgKz0gZC5vdXRnb2luZ0NvdW50O1xuICAgICAgICAgIGlmIChkLmludGVybmFsQ291bnQgIT0gbnVsbCkgcnYuaW50ZXJuYWxDb3VudCArPSBkLmludGVybmFsQ291bnQ7XG4gICAgICAgICAgcmV0dXJuIHJ2O1xuICAgICAgICB9O1xuICAgICAgICBmb3IgKGNvbnN0IGYgb2YgZmxvd3MpIHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLmlzRmxvd0luU2VsZWN0aW9uKGYsIHNlbGVjdGVkTG9jYXRpb25zU2V0LCBsb2NhdGlvbkZpbHRlck1vZGUpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBvcmlnaW5JZCA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmKTtcbiAgICAgICAgICAgIGNvbnN0IGRlc3RJZCA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoZik7XG4gICAgICAgICAgICBjb25zdCBjb3VudCA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoZik7XG4gICAgICAgICAgICBpZiAob3JpZ2luSWQgPT09IGRlc3RJZCkge1xuICAgICAgICAgICAgICB0b3RhbHMuc2V0KG9yaWdpbklkLCBhZGQob3JpZ2luSWQsIHtpbnRlcm5hbENvdW50OiBjb3VudH0pKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRvdGFscy5zZXQob3JpZ2luSWQsIGFkZChvcmlnaW5JZCwge291dGdvaW5nQ291bnQ6IGNvdW50fSkpO1xuICAgICAgICAgICAgICB0b3RhbHMuc2V0KGRlc3RJZCwgYWRkKGRlc3RJZCwge2luY29taW5nQ291bnQ6IGNvdW50fSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG90YWxzO1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldExvY2F0aW9uc1RyZWU6IFNlbGVjdG9yPEwsIEYsIEtEQnVzaFRyZWU+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRMb2NhdGlvbnNGb3Jab29tLFxuICAgIChsb2NhdGlvbnMpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IEtEQnVzaChcbiAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICBsb2NhdGlvbnMsXG4gICAgICAgIChsb2NhdGlvbjogTCB8IENsdXN0ZXJOb2RlKSA9PlxuICAgICAgICAgIGxuZ1goXG4gICAgICAgICAgICBpc0xvY2F0aW9uQ2x1c3Rlck5vZGUobG9jYXRpb24pXG4gICAgICAgICAgICAgID8gbG9jYXRpb24uY2VudHJvaWRbMF1cbiAgICAgICAgICAgICAgOiB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbkNlbnRyb2lkKGxvY2F0aW9uKVswXSxcbiAgICAgICAgICApLFxuICAgICAgICAobG9jYXRpb246IEwgfCBDbHVzdGVyTm9kZSkgPT5cbiAgICAgICAgICBsYXRZKFxuICAgICAgICAgICAgaXNMb2NhdGlvbkNsdXN0ZXJOb2RlKGxvY2F0aW9uKVxuICAgICAgICAgICAgICA/IGxvY2F0aW9uLmNlbnRyb2lkWzFdXG4gICAgICAgICAgICAgIDogdGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25DZW50cm9pZChsb2NhdGlvbilbMV0sXG4gICAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfSxcbiAgKTtcblxuICBfZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0OiBTZWxlY3RvcjxMLCBGLCBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRMb2NhdGlvbnNUcmVlLFxuICAgICAgdGhpcy5nZXRWaWV3cG9ydEJvdW5kaW5nQm94LFxuICAgICAgKHRyZWU6IEtEQnVzaFRyZWUsIGJib3g6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdKSA9PiB7XG4gICAgICAgIGNvbnN0IGlkcyA9IHRoaXMuX2dldExvY2F0aW9uc0luQmJveEluZGljZXModHJlZSwgYmJveCk7XG4gICAgICAgIGlmIChpZHMpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFNldChcbiAgICAgICAgICAgIGlkcy5tYXAoKGlkeDogbnVtYmVyKSA9PiB0cmVlLnBvaW50c1tpZHhdLmlkKSBhcyBBcnJheTxzdHJpbmc+LFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgKTtcblxuICBnZXRMb2NhdGlvbklkc0luVmlld3BvcnQ6IFNlbGVjdG9yPEwsIEYsIFNldDxzdHJpbmc+IHwgdW5kZWZpbmVkPiA9XG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIGNyZWF0ZVNlbGVjdG9yQ3JlYXRvcjxTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZD4oXG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBkZWZhdWx0TWVtb2l6ZSxcbiAgICAgIChcbiAgICAgICAgczE6IFNldDxzdHJpbmc+IHwgdW5kZWZpbmVkLFxuICAgICAgICBzMjogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQsXG4gICAgICAgIGluZGV4OiBudW1iZXIsXG4gICAgICApID0+IHtcbiAgICAgICAgaWYgKHMxID09PSBzMikgcmV0dXJuIHRydWU7XG4gICAgICAgIGlmIChzMSA9PSBudWxsIHx8IHMyID09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKHMxLnNpemUgIT09IHMyLnNpemUpIHJldHVybiBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHMxKSBpZiAoIXMyLmhhcyhpdGVtKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0sXG4gICAgKShcbiAgICAgIHRoaXMuX2dldExvY2F0aW9uSWRzSW5WaWV3cG9ydCxcbiAgICAgIChsb2NhdGlvbklkczogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQpID0+IHtcbiAgICAgICAgaWYgKCFsb2NhdGlvbklkcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIGxvY2F0aW9uSWRzO1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldFRvdGFsVW5maWx0ZXJlZENvdW50OiBTZWxlY3RvcjxMLCBGLCBudW1iZXIgfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLFxuICAgIChmbG93cykgPT4ge1xuICAgICAgaWYgKCFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBmbG93cy5yZWR1Y2UoXG4gICAgICAgIChtLCBmbG93KSA9PiBtICsgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmbG93KSxcbiAgICAgICAgMCxcbiAgICAgICk7XG4gICAgfSxcbiAgKTtcblxuICBnZXRUb3RhbEZpbHRlcmVkQ291bnQ6IFNlbGVjdG9yPEwsIEYsIG51bWJlciB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldFNvcnRlZEFnZ3JlZ2F0ZWRGaWx0ZXJlZEZsb3dzLFxuICAgIHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgdGhpcy5nZXRMb2NhdGlvbkZpbHRlck1vZGUsXG4gICAgKGZsb3dzLCBzZWxlY3RlZExvY2F0aW9uU2V0LCBsb2NhdGlvbkZpbHRlck1vZGUpID0+IHtcbiAgICAgIGlmICghZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBjb3VudCA9IGZsb3dzLnJlZHVjZSgobSwgZmxvdykgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgdGhpcy5pc0Zsb3dJblNlbGVjdGlvbihmbG93LCBzZWxlY3RlZExvY2F0aW9uU2V0LCBsb2NhdGlvbkZpbHRlck1vZGUpXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBtICsgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmbG93KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbTtcbiAgICAgIH0sIDApO1xuICAgICAgcmV0dXJuIGNvdW50O1xuICAgIH0sXG4gICk7XG5cbiAgX2dldExvY2F0aW9uVG90YWxzRXh0ZW50OiBTZWxlY3RvcjxMLCBGLCBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IodGhpcy5nZXRMb2NhdGlvblRvdGFscywgKGxvY2F0aW9uVG90YWxzKSA9PlxuICAgICAgY2FsY0xvY2F0aW9uVG90YWxzRXh0ZW50KGxvY2F0aW9uVG90YWxzLCB1bmRlZmluZWQpLFxuICAgICk7XG5cbiAgX2dldExvY2F0aW9uVG90YWxzRm9yVmlld3BvcnRFeHRlbnQ6IFNlbGVjdG9yPFxuICAgIEwsXG4gICAgRixcbiAgICBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkXG4gID4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uVG90YWxzLFxuICAgIHRoaXMuZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgIChsb2NhdGlvblRvdGFscywgbG9jYXRpb25zSW5WaWV3cG9ydCkgPT5cbiAgICAgIGNhbGNMb2NhdGlvblRvdGFsc0V4dGVudChsb2NhdGlvblRvdGFscywgbG9jYXRpb25zSW5WaWV3cG9ydCksXG4gICk7XG5cbiAgZ2V0TG9jYXRpb25Ub3RhbHNFeHRlbnQgPSAoXG4gICAgc3RhdGU6IEZsb3dNYXBTdGF0ZSxcbiAgICBwcm9wczogRmxvd01hcERhdGE8TCwgRj4sXG4gICk6IFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQgPT4ge1xuICAgIGlmIChzdGF0ZS5zZXR0aW5nc1N0YXRlLmFkYXB0aXZlU2NhbGVzRW5hYmxlZCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldExvY2F0aW9uVG90YWxzRm9yVmlld3BvcnRFeHRlbnQoc3RhdGUsIHByb3BzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldExvY2F0aW9uVG90YWxzRXh0ZW50KHN0YXRlLCBwcm9wcyk7XG4gICAgfVxuICB9O1xuXG4gIGdldEZsb3dzRm9yRmxvd01hcExheWVyOiBTZWxlY3RvcjxMLCBGLCAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW10gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0U29ydGVkQWdncmVnYXRlZEZpbHRlcmVkRmxvd3MsXG4gICAgICB0aGlzLmdldExvY2F0aW9uSWRzSW5WaWV3cG9ydCxcbiAgICAgIHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgICB0aGlzLmdldExvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAgIChcbiAgICAgICAgZmxvd3MsXG4gICAgICAgIGxvY2F0aW9uSWRzSW5WaWV3cG9ydCxcbiAgICAgICAgc2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgICAgIGxvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAgICkgPT4ge1xuICAgICAgICBpZiAoIWZsb3dzIHx8ICFsb2NhdGlvbklkc0luVmlld3BvcnQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHBpY2tlZDogKEYgfCBBZ2dyZWdhdGVGbG93KVtdID0gW107XG4gICAgICAgIGxldCBwaWNrZWRDb3VudCA9IDA7XG4gICAgICAgIGZvciAoY29uc3QgZmxvdyBvZiBmbG93cykge1xuICAgICAgICAgIGNvbnN0IG9yaWdpbiA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmbG93KTtcbiAgICAgICAgICBjb25zdCBkZXN0ID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd0Rlc3RJZChmbG93KTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBsb2NhdGlvbklkc0luVmlld3BvcnQuaGFzKG9yaWdpbikgfHxcbiAgICAgICAgICAgIGxvY2F0aW9uSWRzSW5WaWV3cG9ydC5oYXMoZGVzdClcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgdGhpcy5pc0Zsb3dJblNlbGVjdGlvbihcbiAgICAgICAgICAgICAgICBmbG93LFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkTG9jYXRpb25zU2V0LFxuICAgICAgICAgICAgICAgIGxvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGlmIChvcmlnaW4gIT09IGRlc3QpIHtcbiAgICAgICAgICAgICAgICAvLyBleGNsdWRlIHNlbGYtbG9vcHNcbiAgICAgICAgICAgICAgICBwaWNrZWQucHVzaChmbG93KTtcbiAgICAgICAgICAgICAgICBwaWNrZWRDb3VudCsrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIE9ubHkga2VlcCB0b3BcbiAgICAgICAgICBpZiAocGlja2VkQ291bnQgPiBOVU1CRVJfT0ZfRkxPV1NfVE9fRElTUExBWSkgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgLy8gYXNzdW1pbmcgdGhleSBhcmUgc29ydGVkIGluIGRlc2NlbmRpbmcgb3JkZXIsXG4gICAgICAgIC8vIHdlIG5lZWQgYXNjZW5kaW5nIGZvciByZW5kZXJpbmdcbiAgICAgICAgcmV0dXJuIHBpY2tlZC5yZXZlcnNlKCk7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0Rmxvd01hZ25pdHVkZUV4dGVudChcbiAgICBzdGF0ZTogRmxvd01hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93TWFwRGF0YTxMLCBGPixcbiAgKTogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHN0YXRlLnNldHRpbmdzU3RhdGUuYWRhcHRpdmVTY2FsZXNFbmFibGVkKSB7XG4gICAgICBjb25zdCBmbG93cyA9IHRoaXMuZ2V0Rmxvd3NGb3JGbG93TWFwTGF5ZXIoc3RhdGUsIHByb3BzKTtcbiAgICAgIGlmIChmbG93cykge1xuICAgICAgICBjb25zdCBydiA9IGV4dGVudChmbG93cywgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZSk7XG4gICAgICAgIHJldHVybiBydlswXSAhPT0gdW5kZWZpbmVkICYmIHJ2WzFdICE9PSB1bmRlZmluZWQgPyBydiA6IHVuZGVmaW5lZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRGbG93TWFnbml0dWRlRXh0ZW50KHN0YXRlLCBwcm9wcyk7XG4gICAgfVxuICB9XG5cbiAgZ2V0TG9jYXRpb25NYXhBYnNUb3RhbEdldHRlciA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25Ub3RhbHMsXG4gICAgKGxvY2F0aW9uVG90YWxzKSA9PiB7XG4gICAgICByZXR1cm4gKGxvY2F0aW9uSWQ6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCB0b3RhbCA9IGxvY2F0aW9uVG90YWxzPy5nZXQobG9jYXRpb25JZCk7XG4gICAgICAgIGlmICghdG90YWwpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChcbiAgICAgICAgICBNYXRoLmFicyh0b3RhbC5pbmNvbWluZ0NvdW50ICsgdG90YWwuaW50ZXJuYWxDb3VudCksXG4gICAgICAgICAgTWF0aC5hYnModG90YWwub3V0Z29pbmdDb3VudCArIHRvdGFsLmludGVybmFsQ291bnQpLFxuICAgICAgICApO1xuICAgICAgfTtcbiAgICB9LFxuICApO1xuXG4gIGdldEZsb3dUaGlja25lc3NTY2FsZSA9IChzdGF0ZTogRmxvd01hcFN0YXRlLCBwcm9wczogRmxvd01hcERhdGE8TCwgRj4pID0+IHtcbiAgICBjb25zdCBtYWduaXR1ZGVFeHRlbnQgPSB0aGlzLmdldEZsb3dNYWduaXR1ZGVFeHRlbnQoc3RhdGUsIHByb3BzKTtcbiAgICBpZiAoIW1hZ25pdHVkZUV4dGVudCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICByZXR1cm4gc2NhbGVMaW5lYXIoKVxuICAgICAgLnJhbmdlKFswLjAyNSwgMC41XSlcbiAgICAgIC5kb21haW4oW1xuICAgICAgICAwLFxuICAgICAgICAvLyBzaG91bGQgc3VwcG9ydCBkaWZmIG1vZGUgdG9vXG4gICAgICAgIE1hdGgubWF4LmFwcGx5KFxuICAgICAgICAgIG51bGwsXG4gICAgICAgICAgbWFnbml0dWRlRXh0ZW50Lm1hcCgoeDogbnVtYmVyIHwgdW5kZWZpbmVkKSA9PiBNYXRoLmFicyh4IHx8IDApKSxcbiAgICAgICAgKSxcbiAgICAgIF0pO1xuICB9O1xuXG4gIGdldENpcmNsZVNpemVTY2FsZSA9IChzdGF0ZTogRmxvd01hcFN0YXRlLCBwcm9wczogRmxvd01hcERhdGE8TCwgRj4pID0+IHtcbiAgICBjb25zdCBtYXhMb2NhdGlvbkNpcmNsZVNpemUgPSB0aGlzLmdldE1heExvY2F0aW9uQ2lyY2xlU2l6ZShzdGF0ZSwgcHJvcHMpO1xuICAgIGNvbnN0IHtsb2NhdGlvblRvdGFsc0VuYWJsZWR9ID0gc3RhdGUuc2V0dGluZ3NTdGF0ZTtcbiAgICBpZiAoIWxvY2F0aW9uVG90YWxzRW5hYmxlZCkge1xuICAgICAgcmV0dXJuICgpID0+IG1heExvY2F0aW9uQ2lyY2xlU2l6ZTtcbiAgICB9XG5cbiAgICBjb25zdCBsb2NhdGlvblRvdGFsc0V4dGVudCA9IHRoaXMuZ2V0TG9jYXRpb25Ub3RhbHNFeHRlbnQoc3RhdGUsIHByb3BzKTtcbiAgICBpZiAoIWxvY2F0aW9uVG90YWxzRXh0ZW50KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBzY2FsZVNxcnQoKVxuICAgICAgLnJhbmdlKFswLCBtYXhMb2NhdGlvbkNpcmNsZVNpemVdKVxuICAgICAgLmRvbWFpbihbXG4gICAgICAgIDAsXG4gICAgICAgIC8vIHNob3VsZCBzdXBwb3J0IGRpZmYgbW9kZSB0b29cbiAgICAgICAgTWF0aC5tYXguYXBwbHkoXG4gICAgICAgICAgbnVsbCxcbiAgICAgICAgICBsb2NhdGlvblRvdGFsc0V4dGVudC5tYXAoKHg6IG51bWJlciB8IHVuZGVmaW5lZCkgPT4gTWF0aC5hYnMoeCB8fCAwKSksXG4gICAgICAgICksXG4gICAgICBdKTtcbiAgfTtcblxuICBnZXRJbkNpcmNsZVNpemVHZXR0ZXIgPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldENpcmNsZVNpemVTY2FsZSxcbiAgICB0aGlzLmdldExvY2F0aW9uVG90YWxzLFxuICAgIChjaXJjbGVTaXplU2NhbGUsIGxvY2F0aW9uVG90YWxzKSA9PiB7XG4gICAgICByZXR1cm4gKGxvY2F0aW9uSWQ6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCB0b3RhbCA9IGxvY2F0aW9uVG90YWxzPy5nZXQobG9jYXRpb25JZCk7XG4gICAgICAgIGlmICh0b3RhbCAmJiBjaXJjbGVTaXplU2NhbGUpIHtcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgY2lyY2xlU2l6ZVNjYWxlKFxuICAgICAgICAgICAgICBNYXRoLmFicyh0b3RhbC5pbmNvbWluZ0NvdW50ICsgdG90YWwuaW50ZXJuYWxDb3VudCksXG4gICAgICAgICAgICApIHx8IDBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfTtcbiAgICB9LFxuICApO1xuXG4gIGdldE91dENpcmNsZVNpemVHZXR0ZXIgPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldENpcmNsZVNpemVTY2FsZSxcbiAgICB0aGlzLmdldExvY2F0aW9uVG90YWxzLFxuICAgIChjaXJjbGVTaXplU2NhbGUsIGxvY2F0aW9uVG90YWxzKSA9PiB7XG4gICAgICByZXR1cm4gKGxvY2F0aW9uSWQ6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCB0b3RhbCA9IGxvY2F0aW9uVG90YWxzPy5nZXQobG9jYXRpb25JZCk7XG4gICAgICAgIGlmICh0b3RhbCAmJiBjaXJjbGVTaXplU2NhbGUpIHtcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgY2lyY2xlU2l6ZVNjYWxlKFxuICAgICAgICAgICAgICBNYXRoLmFicyh0b3RhbC5vdXRnb2luZ0NvdW50ICsgdG90YWwuaW50ZXJuYWxDb3VudCksXG4gICAgICAgICAgICApIHx8IDBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfTtcbiAgICB9LFxuICApO1xuXG4gIGdldFNvcnRlZExvY2F0aW9uc0Zvclpvb206IFNlbGVjdG9yPEwsIEYsIExbXSB8IENsdXN0ZXJOb2RlW10gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25zRm9yWm9vbSxcbiAgICAgIHRoaXMuZ2V0SW5DaXJjbGVTaXplR2V0dGVyLFxuICAgICAgdGhpcy5nZXRPdXRDaXJjbGVTaXplR2V0dGVyLFxuICAgICAgKGxvY2F0aW9ucywgZ2V0SW5DaXJjbGVTaXplLCBnZXRPdXRDaXJjbGVTaXplKSA9PiB7XG4gICAgICAgIGlmICghbG9jYXRpb25zKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBuZXh0TG9jYXRpb25zID0gWy4uLmxvY2F0aW9uc10gYXMgTFtdIHwgQ2x1c3Rlck5vZGVbXTtcbiAgICAgICAgcmV0dXJuIG5leHRMb2NhdGlvbnMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgIGNvbnN0IGlkQSA9IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQoYSk7XG4gICAgICAgICAgY29uc3QgaWRCID0gdGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25JZChiKTtcbiAgICAgICAgICByZXR1cm4gYXNjZW5kaW5nKFxuICAgICAgICAgICAgTWF0aC5tYXgoZ2V0SW5DaXJjbGVTaXplKGlkQSksIGdldE91dENpcmNsZVNpemUoaWRBKSksXG4gICAgICAgICAgICBNYXRoLm1heChnZXRJbkNpcmNsZVNpemUoaWRCKSwgZ2V0T3V0Q2lyY2xlU2l6ZShpZEIpKSxcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgKTtcblxuICBnZXRMb2NhdGlvbnNGb3JGbG93TWFwTGF5ZXI6IFNlbGVjdG9yPFxuICAgIEwsXG4gICAgRixcbiAgICBBcnJheTxMIHwgQ2x1c3Rlck5vZGU+IHwgdW5kZWZpbmVkXG4gID4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldFNvcnRlZExvY2F0aW9uc0Zvclpvb20sXG4gICAgLy8gdGhpcy5nZXRMb2NhdGlvbklkc0luVmlld3BvcnQsXG4gICAgKFxuICAgICAgbG9jYXRpb25zLFxuICAgICAgLy8gbG9jYXRpb25JZHNJblZpZXdwb3J0XG4gICAgKSA9PiB7XG4gICAgICAvLyBpZiAoIWxvY2F0aW9ucykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIC8vIGlmICghbG9jYXRpb25JZHNJblZpZXdwb3J0KSByZXR1cm4gbG9jYXRpb25zO1xuICAgICAgLy8gaWYgKGxvY2F0aW9uSWRzSW5WaWV3cG9ydC5zaXplID09PSBsb2NhdGlvbnMubGVuZ3RoKSByZXR1cm4gbG9jYXRpb25zO1xuICAgICAgLy8gY29uc3QgZmlsdGVyZWQgPSBbXTtcbiAgICAgIC8vIGZvciAoY29uc3QgbG9jIG9mIGxvY2F0aW9ucykge1xuICAgICAgLy8gICBpZiAobG9jYXRpb25JZHNJblZpZXdwb3J0Lmhhcyhsb2MuaWQpKSB7XG4gICAgICAvLyAgICAgZmlsdGVyZWQucHVzaChsb2MpO1xuICAgICAgLy8gICB9XG4gICAgICAvLyB9XG4gICAgICAvLyByZXR1cm4gZmlsdGVyZWQ7XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAvLyByZXR1cm4gbG9jYXRpb25zLmZpbHRlcihcbiAgICAgIC8vICAgKGxvYzogTCB8IENsdXN0ZXJOb2RlKSA9PiBsb2NhdGlvbklkc0luVmlld3BvcnQhLmhhcyhsb2MuaWQpXG4gICAgICAvLyApO1xuICAgICAgLy8gVE9ETzogcmV0dXJuIGxvY2F0aW9uIGluIHZpZXdwb3J0ICsgXCJjb25uZWN0ZWRcIiBvbmVzXG4gICAgICByZXR1cm4gbG9jYXRpb25zO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0TG9jYXRpb25zRm9yRmxvd01hcExheWVyQnlJZDogU2VsZWN0b3I8XG4gICAgTCxcbiAgICBGLFxuICAgIE1hcDxzdHJpbmcsIEwgfCBDbHVzdGVyTm9kZT4gfCB1bmRlZmluZWRcbiAgPiA9IGNyZWF0ZVNlbGVjdG9yKHRoaXMuZ2V0TG9jYXRpb25zRm9yRmxvd01hcExheWVyLCAobG9jYXRpb25zKSA9PiB7XG4gICAgaWYgKCFsb2NhdGlvbnMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIGxvY2F0aW9ucy5yZWR1Y2UoXG4gICAgICAobSwgZCkgPT4gKG0uc2V0KHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQoZCksIGQpLCBtKSxcbiAgICAgIG5ldyBNYXAoKSxcbiAgICApO1xuICB9KTtcblxuICBwcmVwYXJlTGF5ZXJzRGF0YShzdGF0ZTogRmxvd01hcFN0YXRlLCBwcm9wczogRmxvd01hcERhdGE8TCwgRj4pOiBMYXllcnNEYXRhIHtcbiAgICBjb25zdCBsb2NhdGlvbnMgPSB0aGlzLmdldExvY2F0aW9uc0ZvckZsb3dNYXBMYXllcihzdGF0ZSwgcHJvcHMpIHx8IFtdO1xuICAgIGNvbnN0IGZsb3dzID0gdGhpcy5nZXRGbG93c0ZvckZsb3dNYXBMYXllcihzdGF0ZSwgcHJvcHMpIHx8IFtdO1xuICAgIGNvbnN0IHtcbiAgICAgIGdldEZsb3dPcmlnaW5JZCxcbiAgICAgIGdldEZsb3dEZXN0SWQsXG4gICAgICBnZXRGbG93TWFnbml0dWRlLFxuICAgICAgZ2V0TG9jYXRpb25JZCxcbiAgICAgIGdldExvY2F0aW9uQ2VudHJvaWQsXG4gICAgfSA9IHRoaXMuYWNjZXNzb3JzO1xuXG4gICAgY29uc3QgZmxvd01hcENvbG9ycyA9IHRoaXMuZ2V0Rmxvd01hcENvbG9yc1JHQkEoc3RhdGUsIHByb3BzKTtcbiAgICBjb25zdCB7c2V0dGluZ3NTdGF0ZX0gPSBzdGF0ZTtcblxuICAgIGNvbnN0IGxvY2F0aW9uc0J5SWQgPSB0aGlzLmdldExvY2F0aW9uc0ZvckZsb3dNYXBMYXllckJ5SWQoc3RhdGUsIHByb3BzKTtcbiAgICBjb25zdCBnZXRDZW50cm9pZCA9IChpZDogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBsb2MgPSBsb2NhdGlvbnNCeUlkPy5nZXQoaWQpO1xuICAgICAgcmV0dXJuIGxvYyA/IGdldExvY2F0aW9uQ2VudHJvaWQobG9jKSA6IFswLCAwXTtcbiAgICB9O1xuXG4gICAgY29uc3QgbG9jYXRpb25JZHNJblZpZXdwb3J0ID0gdGhpcy5nZXRMb2NhdGlvbklkc0luVmlld3BvcnQoc3RhdGUsIHByb3BzKTtcbiAgICBjb25zdCBnZXRJbkNpcmNsZVNpemUgPSB0aGlzLmdldEluQ2lyY2xlU2l6ZUdldHRlcihzdGF0ZSwgcHJvcHMpO1xuICAgIGNvbnN0IGdldE91dENpcmNsZVNpemUgPSB0aGlzLmdldE91dENpcmNsZVNpemVHZXR0ZXIoc3RhdGUsIHByb3BzKTtcblxuICAgIGNvbnN0IGZsb3dUaGlja25lc3NTY2FsZSA9IHRoaXMuZ2V0Rmxvd1RoaWNrbmVzc1NjYWxlKHN0YXRlLCBwcm9wcyk7XG5cbiAgICBjb25zdCBmbG93TWFnbml0dWRlRXh0ZW50ID0gZXh0ZW50KGZsb3dzLCAoZikgPT4gZ2V0Rmxvd01hZ25pdHVkZShmKSkgYXMgW1xuICAgICAgbnVtYmVyLFxuICAgICAgbnVtYmVyLFxuICAgIF07XG4gICAgY29uc3QgZmxvd0NvbG9yU2NhbGUgPSBnZXRGbG93Q29sb3JTY2FsZShcbiAgICAgIGZsb3dNYXBDb2xvcnMsXG4gICAgICBmbG93TWFnbml0dWRlRXh0ZW50LFxuICAgICAgZmFsc2UsXG4gICAgKTtcblxuICAgIGNvbnN0IGNpcmNsZVBvc2l0aW9ucyA9IG5ldyBGbG9hdDMyQXJyYXkoXG4gICAgICBmbGF0TWFwKGxvY2F0aW9ucywgZ2V0TG9jYXRpb25DZW50cm9pZCksXG4gICAgKTtcblxuICAgIC8vIFRPRE86IGRpZmYgbW9kZVxuICAgIGNvbnN0IGNpcmNsZUNvbG9yID0gaXNEaWZmQ29sb3JzUkdCQShmbG93TWFwQ29sb3JzKVxuICAgICAgPyBmbG93TWFwQ29sb3JzLnBvc2l0aXZlLmxvY2F0aW9uQ2lyY2xlcy5pbm5lclxuICAgICAgOiBmbG93TWFwQ29sb3JzLmxvY2F0aW9uQ2lyY2xlcy5pbm5lcjtcblxuICAgIGNvbnN0IGNpcmNsZUNvbG9ycyA9IG5ldyBVaW50OEFycmF5KGZsYXRNYXAobG9jYXRpb25zLCAoZCkgPT4gY2lyY2xlQ29sb3IpKTtcbiAgICBjb25zdCBpbkNpcmNsZVJhZGlpID0gbmV3IEZsb2F0MzJBcnJheShcbiAgICAgIGxvY2F0aW9ucy5tYXAoKGxvYykgPT4ge1xuICAgICAgICBjb25zdCBpZCA9IGdldExvY2F0aW9uSWQobG9jKTtcbiAgICAgICAgcmV0dXJuIGxvY2F0aW9uSWRzSW5WaWV3cG9ydD8uaGFzKGlkKSA/IGdldEluQ2lyY2xlU2l6ZShpZCkgOiAxLjA7XG4gICAgICB9KSxcbiAgICApO1xuICAgIGNvbnN0IG91dENpcmNsZVJhZGlpID0gbmV3IEZsb2F0MzJBcnJheShcbiAgICAgIGxvY2F0aW9ucy5tYXAoKGxvYykgPT4ge1xuICAgICAgICBjb25zdCBpZCA9IGdldExvY2F0aW9uSWQobG9jKTtcbiAgICAgICAgcmV0dXJuIGxvY2F0aW9uSWRzSW5WaWV3cG9ydD8uaGFzKGlkKSA/IGdldE91dENpcmNsZVNpemUoaWQpIDogMS4wO1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNvbnN0IHNvdXJjZVBvc2l0aW9ucyA9IG5ldyBGbG9hdDMyQXJyYXkoXG4gICAgICBmbGF0TWFwKGZsb3dzLCAoZDogRiB8IEFnZ3JlZ2F0ZUZsb3cpID0+IGdldENlbnRyb2lkKGdldEZsb3dPcmlnaW5JZChkKSkpLFxuICAgICk7XG4gICAgY29uc3QgdGFyZ2V0UG9zaXRpb25zID0gbmV3IEZsb2F0MzJBcnJheShcbiAgICAgIGZsYXRNYXAoZmxvd3MsIChkOiBGIHwgQWdncmVnYXRlRmxvdykgPT4gZ2V0Q2VudHJvaWQoZ2V0Rmxvd0Rlc3RJZChkKSkpLFxuICAgICk7XG4gICAgY29uc3QgdGhpY2tuZXNzZXMgPSBuZXcgRmxvYXQzMkFycmF5KFxuICAgICAgZmxvd3MubWFwKChkOiBGIHwgQWdncmVnYXRlRmxvdykgPT5cbiAgICAgICAgZmxvd1RoaWNrbmVzc1NjYWxlID8gZmxvd1RoaWNrbmVzc1NjYWxlKGdldEZsb3dNYWduaXR1ZGUoZCkpIHx8IDAgOiAwLFxuICAgICAgKSxcbiAgICApO1xuICAgIGNvbnN0IGVuZHBvaW50T2Zmc2V0cyA9IG5ldyBGbG9hdDMyQXJyYXkoXG4gICAgICBmbGF0TWFwKGZsb3dzLCAoZDogRiB8IEFnZ3JlZ2F0ZUZsb3cpID0+IHtcbiAgICAgICAgY29uc3Qgb3JpZ2luSWQgPSBnZXRGbG93T3JpZ2luSWQoZCk7XG4gICAgICAgIGNvbnN0IGRlc3RJZCA9IGdldEZsb3dEZXN0SWQoZCk7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgTWF0aC5tYXgoZ2V0SW5DaXJjbGVTaXplKG9yaWdpbklkKSwgZ2V0T3V0Q2lyY2xlU2l6ZShvcmlnaW5JZCkpLFxuICAgICAgICAgIE1hdGgubWF4KGdldEluQ2lyY2xlU2l6ZShkZXN0SWQpLCBnZXRPdXRDaXJjbGVTaXplKGRlc3RJZCkpLFxuICAgICAgICBdO1xuICAgICAgfSksXG4gICAgKTtcbiAgICBjb25zdCBmbG93TGluZUNvbG9ycyA9IG5ldyBVaW50OEFycmF5KFxuICAgICAgZmxhdE1hcChmbG93cywgKGY6IEYgfCBBZ2dyZWdhdGVGbG93KSA9PlxuICAgICAgICBmbG93Q29sb3JTY2FsZShnZXRGbG93TWFnbml0dWRlKGYpKSxcbiAgICAgICksXG4gICAgKTtcblxuICAgIGNvbnN0IHN0YWdnZXJpbmdWYWx1ZXMgPSBzZXR0aW5nc1N0YXRlLmFuaW1hdGlvbkVuYWJsZWRcbiAgICAgID8gbmV3IEZsb2F0MzJBcnJheShcbiAgICAgICAgICBmbG93cy5tYXAoKGY6IEYgfCBBZ2dyZWdhdGVGbG93KSA9PlxuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgbmV3IGFsZWEoYCR7Z2V0Rmxvd09yaWdpbklkKGYpfS0ke2dldEZsb3dEZXN0SWQoZil9YCkoKSxcbiAgICAgICAgICApLFxuICAgICAgICApXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIHJldHVybiB7XG4gICAgICBjaXJjbGVBdHRyaWJ1dGVzOiB7XG4gICAgICAgIGxlbmd0aDogbG9jYXRpb25zLmxlbmd0aCxcbiAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgIGdldFBvc2l0aW9uOiB7dmFsdWU6IGNpcmNsZVBvc2l0aW9ucywgc2l6ZTogMn0sXG4gICAgICAgICAgZ2V0Q29sb3I6IHt2YWx1ZTogY2lyY2xlQ29sb3JzLCBzaXplOiA0fSxcbiAgICAgICAgICBnZXRJblJhZGl1czoge3ZhbHVlOiBpbkNpcmNsZVJhZGlpLCBzaXplOiAxfSxcbiAgICAgICAgICBnZXRPdXRSYWRpdXM6IHt2YWx1ZTogb3V0Q2lyY2xlUmFkaWksIHNpemU6IDF9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGxpbmVBdHRyaWJ1dGVzOiB7XG4gICAgICAgIGxlbmd0aDogZmxvd3MubGVuZ3RoLFxuICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgZ2V0U291cmNlUG9zaXRpb246IHt2YWx1ZTogc291cmNlUG9zaXRpb25zLCBzaXplOiAyfSxcbiAgICAgICAgICBnZXRUYXJnZXRQb3NpdGlvbjoge3ZhbHVlOiB0YXJnZXRQb3NpdGlvbnMsIHNpemU6IDJ9LFxuICAgICAgICAgIGdldFRoaWNrbmVzczoge3ZhbHVlOiB0aGlja25lc3Nlcywgc2l6ZTogMX0sXG4gICAgICAgICAgZ2V0Q29sb3I6IHt2YWx1ZTogZmxvd0xpbmVDb2xvcnMsIHNpemU6IDR9LFxuICAgICAgICAgIGdldEVuZHBvaW50T2Zmc2V0czoge3ZhbHVlOiBlbmRwb2ludE9mZnNldHMsIHNpemU6IDJ9LFxuICAgICAgICAgIC4uLihzdGFnZ2VyaW5nVmFsdWVzXG4gICAgICAgICAgICA/IHtnZXRTdGFnZ2VyaW5nOiB7dmFsdWU6IHN0YWdnZXJpbmdWYWx1ZXMsIHNpemU6IDF9fVxuICAgICAgICAgICAgOiB7fSksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBnZXRMb2NhdGlvbnNJbkJib3goXG4gICAgdHJlZTogS0RCdXNoVHJlZSxcbiAgICBiYm94OiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgKTogQXJyYXk8TD4gfCB1bmRlZmluZWQge1xuICAgIGlmICghdHJlZSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICByZXR1cm4gdGhpcy5fZ2V0TG9jYXRpb25zSW5CYm94SW5kaWNlcyh0cmVlLCBiYm94KS5tYXAoXG4gICAgICAoaWR4OiBudW1iZXIpID0+IHRyZWUucG9pbnRzW2lkeF0sXG4gICAgKSBhcyBBcnJheTxMPjtcbiAgfVxuXG4gIF9nZXRMb2NhdGlvbnNJbkJib3hJbmRpY2VzKFxuICAgIHRyZWU6IEtEQnVzaFRyZWUsXG4gICAgYmJveDogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICkge1xuICAgIGlmICghdHJlZSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjb25zdCBbbG9uMSwgbGF0MSwgbG9uMiwgbGF0Ml0gPSBiYm94O1xuICAgIGNvbnN0IFt4MSwgeTEsIHgyLCB5Ml0gPSBbbG5nWChsb24xKSwgbGF0WShsYXQxKSwgbG5nWChsb24yKSwgbGF0WShsYXQyKV07XG4gICAgcmV0dXJuIHRyZWUucmFuZ2UoXG4gICAgICBNYXRoLm1pbih4MSwgeDIpLFxuICAgICAgTWF0aC5taW4oeTEsIHkyKSxcbiAgICAgIE1hdGgubWF4KHgxLCB4MiksXG4gICAgICBNYXRoLm1heCh5MSwgeTIpLFxuICAgICk7XG4gIH1cblxuICBpc0Zsb3dJblNlbGVjdGlvbihcbiAgICBmbG93OiBGIHwgQWdncmVnYXRlRmxvdyxcbiAgICBzZWxlY3RlZExvY2F0aW9uc1NldDogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQsXG4gICAgbG9jYXRpb25GaWx0ZXJNb2RlOiBMb2NhdGlvbkZpbHRlck1vZGUsXG4gICkge1xuICAgIGNvbnN0IG9yaWdpbiA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmbG93KTtcbiAgICBjb25zdCBkZXN0ID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd0Rlc3RJZChmbG93KTtcbiAgICBpZiAoc2VsZWN0ZWRMb2NhdGlvbnNTZXQpIHtcbiAgICAgIHN3aXRjaCAobG9jYXRpb25GaWx0ZXJNb2RlKSB7XG4gICAgICAgIGNhc2UgTG9jYXRpb25GaWx0ZXJNb2RlLkFMTDpcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKG9yaWdpbikgfHwgc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKGRlc3QpXG4gICAgICAgICAgKTtcbiAgICAgICAgY2FzZSBMb2NhdGlvbkZpbHRlck1vZGUuQkVUV0VFTjpcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKG9yaWdpbikgJiYgc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKGRlc3QpXG4gICAgICAgICAgKTtcbiAgICAgICAgY2FzZSBMb2NhdGlvbkZpbHRlck1vZGUuSU5DT01JTkc6XG4gICAgICAgICAgcmV0dXJuIHNlbGVjdGVkTG9jYXRpb25zU2V0LmhhcyhkZXN0KTtcbiAgICAgICAgY2FzZSBMb2NhdGlvbkZpbHRlck1vZGUuT1VUR09JTkc6XG4gICAgICAgICAgcmV0dXJuIHNlbGVjdGVkTG9jYXRpb25zU2V0LmhhcyhvcmlnaW4pO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIGNhbGNMb2NhdGlvblRvdGFscyhcbiAgLy8gICBsb2NhdGlvbnM6IChMIHwgQ2x1c3Rlck5vZGUpW10sXG4gIC8vICAgZmxvd3M6IEZbXSxcbiAgLy8gKTogTG9jYXRpb25zVG90YWxzIHtcbiAgLy8gICByZXR1cm4gZmxvd3MucmVkdWNlKFxuICAvLyAgICAgKGFjYzogTG9jYXRpb25zVG90YWxzLCBjdXJyKSA9PiB7XG4gIC8vICAgICAgIGNvbnN0IG9yaWdpbklkID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGN1cnIpO1xuICAvLyAgICAgICBjb25zdCBkZXN0SWQgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGN1cnIpO1xuICAvLyAgICAgICBjb25zdCBtYWduaXR1ZGUgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGN1cnIpO1xuICAvLyAgICAgICBpZiAob3JpZ2luSWQgPT09IGRlc3RJZCkge1xuICAvLyAgICAgICAgIGFjYy5pbnRlcm5hbFtvcmlnaW5JZF0gPSAoYWNjLmludGVybmFsW29yaWdpbklkXSB8fCAwKSArIG1hZ25pdHVkZTtcbiAgLy8gICAgICAgfSBlbHNlIHtcbiAgLy8gICAgICAgICBhY2Mub3V0Z29pbmdbb3JpZ2luSWRdID0gKGFjYy5vdXRnb2luZ1tvcmlnaW5JZF0gfHwgMCkgKyBtYWduaXR1ZGU7XG4gIC8vICAgICAgICAgYWNjLmluY29taW5nW2Rlc3RJZF0gPSAoYWNjLmluY29taW5nW2Rlc3RJZF0gfHwgMCkgKyBtYWduaXR1ZGU7XG4gIC8vICAgICAgIH1cbiAgLy8gICAgICAgcmV0dXJuIGFjYztcbiAgLy8gICAgIH0sXG4gIC8vICAgICB7aW5jb21pbmc6IHt9LCBvdXRnb2luZzoge30sIGludGVybmFsOiB7fX0sXG4gIC8vICAgKTtcbiAgLy8gfVxufVxuXG5mdW5jdGlvbiBjYWxjTG9jYXRpb25Ub3RhbHNFeHRlbnQoXG4gIGxvY2F0aW9uVG90YWxzOiBNYXA8c3RyaW5nLCBMb2NhdGlvblRvdGFscz4gfCB1bmRlZmluZWQsXG4gIGxvY2F0aW9uSWRzSW5WaWV3cG9ydDogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQsXG4pIHtcbiAgaWYgKCFsb2NhdGlvblRvdGFscykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgbGV0IHJ2OiBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICBmb3IgKGNvbnN0IFtcbiAgICBpZCxcbiAgICB7aW5jb21pbmdDb3VudCwgb3V0Z29pbmdDb3VudCwgaW50ZXJuYWxDb3VudH0sXG4gIF0gb2YgbG9jYXRpb25Ub3RhbHMuZW50cmllcygpKSB7XG4gICAgaWYgKGxvY2F0aW9uSWRzSW5WaWV3cG9ydCA9PSBudWxsIHx8IGxvY2F0aW9uSWRzSW5WaWV3cG9ydC5oYXMoaWQpKSB7XG4gICAgICBjb25zdCBsbyA9IE1hdGgubWluKFxuICAgICAgICBpbmNvbWluZ0NvdW50ICsgaW50ZXJuYWxDb3VudCxcbiAgICAgICAgb3V0Z29pbmdDb3VudCArIGludGVybmFsQ291bnQsXG4gICAgICAgIGludGVybmFsQ291bnQsXG4gICAgICApO1xuICAgICAgY29uc3QgaGkgPSBNYXRoLm1heChcbiAgICAgICAgaW5jb21pbmdDb3VudCArIGludGVybmFsQ291bnQsXG4gICAgICAgIG91dGdvaW5nQ291bnQgKyBpbnRlcm5hbENvdW50LFxuICAgICAgICBpbnRlcm5hbENvdW50LFxuICAgICAgKTtcbiAgICAgIGlmICghcnYpIHtcbiAgICAgICAgcnYgPSBbbG8sIGhpXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChsbyA8IHJ2WzBdKSBydlswXSA9IGxvO1xuICAgICAgICBpZiAoaGkgPiBydlsxXSkgcnZbMV0gPSBoaTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJ2O1xufVxuXG4vLyBsb25naXR1ZGUvbGF0aXR1ZGUgdG8gc3BoZXJpY2FsIG1lcmNhdG9yIGluIFswLi4xXSByYW5nZVxuZnVuY3Rpb24gbG5nWChsbmc6IG51bWJlcikge1xuICByZXR1cm4gbG5nIC8gMzYwICsgMC41O1xufVxuXG5mdW5jdGlvbiBsYXRZKGxhdDogbnVtYmVyKSB7XG4gIGNvbnN0IHNpbiA9IE1hdGguc2luKChsYXQgKiBNYXRoLlBJKSAvIDE4MCk7XG4gIGNvbnN0IHkgPSAwLjUgLSAoMC4yNSAqIE1hdGgubG9nKCgxICsgc2luKSAvICgxIC0gc2luKSkpIC8gTWF0aC5QSTtcbiAgcmV0dXJuIHkgPCAwID8gMCA6IHkgPiAxID8gMSA6IHk7XG59XG5cbmZ1bmN0aW9uIGFnZ3JlZ2F0ZUZsb3dzPEY+KFxuICBmbG93czogRltdLFxuICBmbG93QWNjZXNzb3JzOiBGbG93QWNjZXNzb3JzPEY+LFxuKTogQWdncmVnYXRlRmxvd1tdIHtcbiAgLy8gU3VtIHVwIGZsb3dzIHdpdGggc2FtZSBvcmlnaW4sIGRlc3RcbiAgY29uc3QgYnlPcmlnaW5EZXN0ID0gbmVzdDxGLCBBZ2dyZWdhdGVGbG93PigpXG4gICAgLmtleShmbG93QWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZClcbiAgICAua2V5KGZsb3dBY2Nlc3NvcnMuZ2V0Rmxvd0Rlc3RJZClcbiAgICAucm9sbHVwKChmZjogRltdKSA9PiB7XG4gICAgICBjb25zdCBvcmlnaW4gPSBmbG93QWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmZlswXSk7XG4gICAgICBjb25zdCBkZXN0ID0gZmxvd0FjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZmWzBdKTtcbiAgICAgIC8vIGNvbnN0IGNvbG9yID0gZmZbMF0uY29sb3I7XG4gICAgICBjb25zdCBydjogQWdncmVnYXRlRmxvdyA9IHtcbiAgICAgICAgYWdncmVnYXRlOiB0cnVlLFxuICAgICAgICBvcmlnaW4sXG4gICAgICAgIGRlc3QsXG4gICAgICAgIGNvdW50OiBmZi5yZWR1Y2UoKG0sIGYpID0+IHtcbiAgICAgICAgICBjb25zdCBjb3VudCA9IGZsb3dBY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmKTtcbiAgICAgICAgICBpZiAoY291bnQpIHtcbiAgICAgICAgICAgIGlmICghaXNOYU4oY291bnQpICYmIGlzRmluaXRlKGNvdW50KSkgcmV0dXJuIG0gKyBjb3VudDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG07XG4gICAgICAgIH0sIDApLFxuICAgICAgICAvLyB0aW1lOiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgICAgLy8gaWYgKGNvbG9yKSBydi5jb2xvciA9IGNvbG9yO1xuICAgICAgcmV0dXJuIHJ2O1xuICAgIH0pXG4gICAgLmVudHJpZXMoZmxvd3MpO1xuICBjb25zdCBydjogQWdncmVnYXRlRmxvd1tdID0gW107XG4gIGZvciAoY29uc3Qge3ZhbHVlc30gb2YgYnlPcmlnaW5EZXN0KSB7XG4gICAgZm9yIChjb25zdCB7dmFsdWV9IG9mIHZhbHVlcykge1xuICAgICAgcnYucHVzaCh2YWx1ZSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBydjtcbn1cblxuLyoqXG4gKiBUaGlzIGlzIHVzZWQgdG8gYXVnbWVudCBob3ZlciBwaWNraW5nIGluZm8gc28gdGhhdCB3ZSBjYW4gZGlzcGxhY2UgbG9jYXRpb24gdG9vbHRpcFxuICogQHBhcmFtIGNpcmNsZUF0dHJpYnV0ZXNcbiAqIEBwYXJhbSBpbmRleFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0T3V0ZXJDaXJjbGVSYWRpdXNCeUluZGV4KFxuICBjaXJjbGVBdHRyaWJ1dGVzOiBGbG93Q2lyY2xlc0xheWVyQXR0cmlidXRlcyxcbiAgaW5kZXg6IG51bWJlcixcbik6IG51bWJlciB7XG4gIGNvbnN0IHtnZXRJblJhZGl1cywgZ2V0T3V0UmFkaXVzfSA9IGNpcmNsZUF0dHJpYnV0ZXMuYXR0cmlidXRlcztcbiAgcmV0dXJuIE1hdGgubWF4KGdldEluUmFkaXVzLnZhbHVlW2luZGV4XSwgZ2V0T3V0UmFkaXVzLnZhbHVlW2luZGV4XSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb2NhdGlvbkNlbnRyb2lkQnlJbmRleChcbiAgY2lyY2xlQXR0cmlidXRlczogRmxvd0NpcmNsZXNMYXllckF0dHJpYnV0ZXMsXG4gIGluZGV4OiBudW1iZXIsXG4pOiBbbnVtYmVyLCBudW1iZXJdIHtcbiAgY29uc3Qge2dldFBvc2l0aW9ufSA9IGNpcmNsZUF0dHJpYnV0ZXMuYXR0cmlidXRlcztcbiAgcmV0dXJuIFtnZXRQb3NpdGlvbi52YWx1ZVtpbmRleCAqIDJdLCBnZXRQb3NpdGlvbi52YWx1ZVtpbmRleCAqIDIgKyAxXV07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGbG93TGluZUF0dHJpYnV0ZXNCeUluZGV4KFxuICBsaW5lQXR0cmlidXRlczogRmxvd0xpbmVzTGF5ZXJBdHRyaWJ1dGVzLFxuICBpbmRleDogbnVtYmVyLFxuKTogRmxvd0xpbmVzTGF5ZXJBdHRyaWJ1dGVzIHtcbiAgY29uc3Qge1xuICAgIGdldENvbG9yLFxuICAgIGdldEVuZHBvaW50T2Zmc2V0cyxcbiAgICBnZXRTb3VyY2VQb3NpdGlvbixcbiAgICBnZXRUYXJnZXRQb3NpdGlvbixcbiAgICBnZXRUaGlja25lc3MsXG4gICAgZ2V0U3RhZ2dlcmluZyxcbiAgfSA9IGxpbmVBdHRyaWJ1dGVzLmF0dHJpYnV0ZXM7XG4gIHJldHVybiB7XG4gICAgbGVuZ3RoOiAxLFxuICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgIGdldENvbG9yOiB7XG4gICAgICAgIHZhbHVlOiBnZXRDb2xvci52YWx1ZS5zdWJhcnJheShpbmRleCAqIDQsIChpbmRleCArIDEpICogNCksXG4gICAgICAgIHNpemU6IDQsXG4gICAgICB9LFxuICAgICAgZ2V0RW5kcG9pbnRPZmZzZXRzOiB7XG4gICAgICAgIHZhbHVlOiBnZXRFbmRwb2ludE9mZnNldHMudmFsdWUuc3ViYXJyYXkoaW5kZXggKiAyLCAoaW5kZXggKyAxKSAqIDIpLFxuICAgICAgICBzaXplOiAyLFxuICAgICAgfSxcbiAgICAgIGdldFNvdXJjZVBvc2l0aW9uOiB7XG4gICAgICAgIHZhbHVlOiBnZXRTb3VyY2VQb3NpdGlvbi52YWx1ZS5zdWJhcnJheShpbmRleCAqIDIsIChpbmRleCArIDEpICogMiksXG4gICAgICAgIHNpemU6IDIsXG4gICAgICB9LFxuICAgICAgZ2V0VGFyZ2V0UG9zaXRpb246IHtcbiAgICAgICAgdmFsdWU6IGdldFRhcmdldFBvc2l0aW9uLnZhbHVlLnN1YmFycmF5KGluZGV4ICogMiwgKGluZGV4ICsgMSkgKiAyKSxcbiAgICAgICAgc2l6ZTogMixcbiAgICAgIH0sXG4gICAgICBnZXRUaGlja25lc3M6IHtcbiAgICAgICAgdmFsdWU6IGdldFRoaWNrbmVzcy52YWx1ZS5zdWJhcnJheShpbmRleCwgaW5kZXggKyAxKSxcbiAgICAgICAgc2l6ZTogMSxcbiAgICAgIH0sXG4gICAgICAuLi4oZ2V0U3RhZ2dlcmluZ1xuICAgICAgICA/IHtcbiAgICAgICAgICAgIGdldFN0YWdnZXJpbmc6IHtcbiAgICAgICAgICAgICAgdmFsdWU6IGdldFN0YWdnZXJpbmcudmFsdWUuc3ViYXJyYXkoaW5kZXgsIGluZGV4ICsgMSksXG4gICAgICAgICAgICAgIHNpemU6IDEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH1cbiAgICAgICAgOiB1bmRlZmluZWQpLFxuICAgIH0sXG4gIH07XG59XG4iXX0=
|