@flowmap.gl/data 8.0.0-alpha.2 → 8.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{FlowMapAggregateAccessors.d.ts → FlowmapAggregateAccessors.d.ts} +6 -6
- package/dist/{FlowMapAggregateAccessors.d.ts.map → FlowmapAggregateAccessors.d.ts.map} +1 -1
- package/dist/{FlowMapAggregateAccessors.js → FlowmapAggregateAccessors.js} +3 -3
- package/dist/{FlowMapSelectors.d.ts → FlowmapSelectors.d.ts} +47 -45
- package/dist/FlowmapSelectors.d.ts.map +1 -0
- package/dist/FlowmapSelectors.js +869 -0
- package/dist/{FlowMapState.d.ts → FlowmapState.d.ts} +5 -2
- package/dist/FlowmapState.d.ts.map +1 -0
- package/dist/FlowmapState.js +2 -0
- package/dist/colors.d.ts +6 -6
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +42 -17
- package/dist/getViewStateForLocations.d.ts +12 -10
- package/dist/getViewStateForLocations.d.ts.map +1 -1
- package/dist/getViewStateForLocations.js +4 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -6
- 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 +95 -0
- package/dist/provider/WorkerFlowmapDataProvider.d.ts +42 -0
- package/dist/provider/WorkerFlowmapDataProvider.d.ts.map +1 -0
- package/dist/provider/WorkerFlowmapDataProvider.js +82 -0
- package/dist/provider/WorkerFlowmapDataProviderWorker.d.ts +2 -0
- package/dist/provider/WorkerFlowmapDataProviderWorker.d.ts.map +1 -0
- package/dist/provider/WorkerFlowmapDataProviderWorker.js +4 -0
- package/dist/provider/createWorkerDataProvider.d.ts +3 -0
- package/dist/provider/createWorkerDataProvider.d.ts.map +1 -0
- package/dist/provider/createWorkerDataProvider.js +21 -0
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/dist/util.d.ts +0 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +1 -4
- package/package.json +7 -2
- package/src/{FlowMapAggregateAccessors.ts → FlowmapAggregateAccessors.ts} +6 -6
- package/src/{FlowMapSelectors.ts → FlowmapSelectors.ts} +154 -113
- package/src/{FlowMapState.ts → FlowmapState.ts} +4 -1
- package/src/colors.ts +50 -16
- package/src/getViewStateForLocations.ts +20 -16
- package/src/index.ts +9 -6
- package/src/provider/{FlowMapDataProvider.ts → FlowmapDataProvider.ts} +14 -12
- package/src/provider/LocalFlowmapDataProvider.ts +119 -0
- package/src/provider/WorkerFlowmapDataProvider.ts +121 -0
- package/src/provider/WorkerFlowmapDataProviderWorker.ts +4 -0
- package/src/provider/createWorkerDataProvider.ts +18 -0
- package/src/types.ts +2 -2
- package/src/util.ts +0 -4
- package/dist/FlowMapSelectors.d.ts.map +0 -1
- package/dist/FlowMapSelectors.js +0 -834
- package/dist/FlowMapState.d.ts.map +0 -1
- package/dist/FlowMapState.js +0 -2
- package/dist/provider/FlowMapDataProvider.d.ts +0 -16
- package/dist/provider/FlowMapDataProvider.d.ts.map +0 -1
- package/dist/provider/FlowMapDataProvider.js +0 -17
- package/dist/provider/LocalFlowMapDataProvider.d.ts +0 -20
- package/dist/provider/LocalFlowMapDataProvider.d.ts.map +0 -1
- package/dist/provider/LocalFlowMapDataProvider.js +0 -87
- package/src/provider/LocalFlowMapDataProvider.ts +0 -105
|
@@ -0,0 +1,869 @@
|
|
|
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
|
+
const MAX_CLUSTER_ZOOM_LEVEL = 20;
|
|
32
|
+
export default class FlowmapSelectors {
|
|
33
|
+
constructor(accessors) {
|
|
34
|
+
this.getFetchedFlows = (state, props) => props.flows;
|
|
35
|
+
this.getFetchedLocations = (state, props) => props.locations;
|
|
36
|
+
this.getMaxTopFlowsDisplayNum = (state, props) => state.settingsState.maxTopFlowsDisplayNum;
|
|
37
|
+
this.getSelectedLocations = (state, props) => state.filterState.selectedLocations;
|
|
38
|
+
this.getLocationFilterMode = (state, props) => state.filterState.locationFilterMode;
|
|
39
|
+
this.getClusteringEnabled = (state, props) => state.settingsState.clusteringEnabled;
|
|
40
|
+
this.getLocationTotalsEnabled = (state, props) => state.settingsState.locationTotalsEnabled;
|
|
41
|
+
this.getZoom = (state, props) => state.viewport.zoom;
|
|
42
|
+
this.getViewport = (state, props) => state.viewport;
|
|
43
|
+
this.getSelectedTimeRange = (state, props) => state.filterState.selectedTimeRange;
|
|
44
|
+
this.getColorSchemeKey = (state, props) => state.settingsState.colorScheme;
|
|
45
|
+
this.getDarkMode = (state, props) => state.settingsState.darkMode;
|
|
46
|
+
this.getFadeEnabled = (state, props) => state.settingsState.fadeEnabled;
|
|
47
|
+
this.getFadeOpacityEnabled = (state, props) => state.settingsState.fadeOpacityEnabled;
|
|
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.getFadeOpacityEnabled, 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 = createSelectorCreator(defaultMemoize,
|
|
446
|
+
// @ts-ignore
|
|
447
|
+
(s1, s2, index) => {
|
|
448
|
+
if (s1 === s2)
|
|
449
|
+
return true;
|
|
450
|
+
if (s1 == null || s2 == null)
|
|
451
|
+
return false;
|
|
452
|
+
if (s1.size !== s2.size)
|
|
453
|
+
return false;
|
|
454
|
+
for (const item of s1)
|
|
455
|
+
if (!s2.has(item))
|
|
456
|
+
return false;
|
|
457
|
+
return true;
|
|
458
|
+
})(this._getLocationIdsInViewport, (locationIds) => {
|
|
459
|
+
if (!locationIds)
|
|
460
|
+
return undefined;
|
|
461
|
+
return locationIds;
|
|
462
|
+
});
|
|
463
|
+
this.getTotalUnfilteredCount = createSelector(this.getSortedFlowsForKnownLocations, (flows) => {
|
|
464
|
+
if (!flows)
|
|
465
|
+
return undefined;
|
|
466
|
+
return flows.reduce((m, flow) => m + this.accessors.getFlowMagnitude(flow), 0);
|
|
467
|
+
});
|
|
468
|
+
this.getTotalFilteredCount = createSelector(this.getSortedAggregatedFilteredFlows, this.getSelectedLocationsSet, this.getLocationFilterMode, (flows, selectedLocationSet, locationFilterMode) => {
|
|
469
|
+
if (!flows)
|
|
470
|
+
return undefined;
|
|
471
|
+
const count = flows.reduce((m, flow) => {
|
|
472
|
+
if (this.isFlowInSelection(flow, selectedLocationSet, locationFilterMode)) {
|
|
473
|
+
return m + this.accessors.getFlowMagnitude(flow);
|
|
474
|
+
}
|
|
475
|
+
return m;
|
|
476
|
+
}, 0);
|
|
477
|
+
return count;
|
|
478
|
+
});
|
|
479
|
+
this._getLocationTotalsExtent = createSelector(this.getLocationTotals, (locationTotals) => calcLocationTotalsExtent(locationTotals, undefined));
|
|
480
|
+
this._getLocationTotalsForViewportExtent = createSelector(this.getLocationTotals, this.getLocationIdsInViewport, (locationTotals, locationsInViewport) => calcLocationTotalsExtent(locationTotals, locationsInViewport));
|
|
481
|
+
this.getLocationTotalsExtent = (state, props) => {
|
|
482
|
+
if (state.settingsState.adaptiveScalesEnabled) {
|
|
483
|
+
return this._getLocationTotalsForViewportExtent(state, props);
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
return this._getLocationTotalsExtent(state, props);
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
this.getFlowsForFlowmapLayer = createSelector(this.getSortedAggregatedFilteredFlows, this.getLocationIdsInViewport, this.getSelectedLocationsSet, this.getLocationFilterMode, this.getMaxTopFlowsDisplayNum, (flows, locationIdsInViewport, selectedLocationsSet, locationFilterMode, maxTopFlowsDisplayNum) => {
|
|
490
|
+
if (!flows || !locationIdsInViewport)
|
|
491
|
+
return undefined;
|
|
492
|
+
const picked = [];
|
|
493
|
+
let pickedCount = 0;
|
|
494
|
+
for (const flow of flows) {
|
|
495
|
+
const origin = this.accessors.getFlowOriginId(flow);
|
|
496
|
+
const dest = this.accessors.getFlowDestId(flow);
|
|
497
|
+
if (locationIdsInViewport.has(origin) ||
|
|
498
|
+
locationIdsInViewport.has(dest)) {
|
|
499
|
+
if (this.isFlowInSelection(flow, selectedLocationsSet, locationFilterMode)) {
|
|
500
|
+
if (origin !== dest) {
|
|
501
|
+
// exclude self-loops
|
|
502
|
+
picked.push(flow);
|
|
503
|
+
pickedCount++;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
// Only keep top
|
|
508
|
+
if (pickedCount > maxTopFlowsDisplayNum)
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
// assuming they are sorted in descending order,
|
|
512
|
+
// we need ascending for rendering
|
|
513
|
+
return picked.reverse();
|
|
514
|
+
});
|
|
515
|
+
this._getFlowMagnitudeExtent = (state, props) => {
|
|
516
|
+
if (state.settingsState.adaptiveScalesEnabled) {
|
|
517
|
+
const flows = this.getFlowsForFlowmapLayer(state, props);
|
|
518
|
+
if (flows) {
|
|
519
|
+
const rv = extent(flows, this.accessors.getFlowMagnitude);
|
|
520
|
+
return rv[0] !== undefined && rv[1] !== undefined ? rv : undefined;
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
return undefined;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
return this.getFlowMagnitudeExtent(state, props);
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
this.getLocationMaxAbsTotalGetter = createSelector(this.getLocationTotals, (locationTotals) => {
|
|
531
|
+
return (locationId) => {
|
|
532
|
+
const total = locationTotals === null || locationTotals === void 0 ? void 0 : locationTotals.get(locationId);
|
|
533
|
+
if (!total)
|
|
534
|
+
return undefined;
|
|
535
|
+
return Math.max(Math.abs(total.incomingCount + total.internalCount), Math.abs(total.outgoingCount + total.internalCount));
|
|
536
|
+
};
|
|
537
|
+
});
|
|
538
|
+
this.getFlowThicknessScale = createSelector(this.getFlowMagnitudeExtent, (magnitudeExtent) => {
|
|
539
|
+
if (!magnitudeExtent)
|
|
540
|
+
return undefined;
|
|
541
|
+
return scaleLinear()
|
|
542
|
+
.range([0.025, 0.5])
|
|
543
|
+
.domain([
|
|
544
|
+
0,
|
|
545
|
+
// should support diff mode too
|
|
546
|
+
Math.max.apply(null, magnitudeExtent.map((x) => Math.abs(x || 0))),
|
|
547
|
+
]);
|
|
548
|
+
});
|
|
549
|
+
this.getCircleSizeScale = createSelector(this.getMaxLocationCircleSize, this.getLocationTotalsEnabled, this.getLocationTotalsExtent, (maxLocationCircleSize, locationTotalsEnabled, locationTotalsExtent) => {
|
|
550
|
+
if (!locationTotalsEnabled) {
|
|
551
|
+
return () => maxLocationCircleSize;
|
|
552
|
+
}
|
|
553
|
+
if (!locationTotalsExtent)
|
|
554
|
+
return undefined;
|
|
555
|
+
return scaleSqrt()
|
|
556
|
+
.range([0, maxLocationCircleSize])
|
|
557
|
+
.domain([
|
|
558
|
+
0,
|
|
559
|
+
// should support diff mode too
|
|
560
|
+
Math.max.apply(null, locationTotalsExtent.map((x) => Math.abs(x || 0))),
|
|
561
|
+
]);
|
|
562
|
+
});
|
|
563
|
+
this.getInCircleSizeGetter = 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.incomingCount + total.internalCount)) || 0);
|
|
568
|
+
}
|
|
569
|
+
return 0;
|
|
570
|
+
};
|
|
571
|
+
});
|
|
572
|
+
this.getOutCircleSizeGetter = createSelector(this.getCircleSizeScale, this.getLocationTotals, (circleSizeScale, locationTotals) => {
|
|
573
|
+
return (locationId) => {
|
|
574
|
+
const total = locationTotals === null || locationTotals === void 0 ? void 0 : locationTotals.get(locationId);
|
|
575
|
+
if (total && circleSizeScale) {
|
|
576
|
+
return (circleSizeScale(Math.abs(total.outgoingCount + total.internalCount)) || 0);
|
|
577
|
+
}
|
|
578
|
+
return 0;
|
|
579
|
+
};
|
|
580
|
+
});
|
|
581
|
+
this.getSortedLocationsForZoom = createSelector(this.getLocationsForZoom, this.getInCircleSizeGetter, this.getOutCircleSizeGetter, (locations, getInCircleSize, getOutCircleSize) => {
|
|
582
|
+
if (!locations)
|
|
583
|
+
return undefined;
|
|
584
|
+
const nextLocations = [...locations];
|
|
585
|
+
return nextLocations.sort((a, b) => {
|
|
586
|
+
const idA = this.accessors.getLocationId(a);
|
|
587
|
+
const idB = this.accessors.getLocationId(b);
|
|
588
|
+
return ascending(Math.max(getInCircleSize(idA), getOutCircleSize(idA)), Math.max(getInCircleSize(idB), getOutCircleSize(idB)));
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
this.getLocationsForFlowmapLayer = createSelector(this.getSortedLocationsForZoom,
|
|
592
|
+
// this.getLocationIdsInViewport,
|
|
593
|
+
(locations) => {
|
|
594
|
+
// if (!locations) return undefined;
|
|
595
|
+
// if (!locationIdsInViewport) return locations;
|
|
596
|
+
// if (locationIdsInViewport.size === locations.length) return locations;
|
|
597
|
+
// const filtered = [];
|
|
598
|
+
// for (const loc of locations) {
|
|
599
|
+
// if (locationIdsInViewport.has(loc.id)) {
|
|
600
|
+
// filtered.push(loc);
|
|
601
|
+
// }
|
|
602
|
+
// }
|
|
603
|
+
// return filtered;
|
|
604
|
+
// @ts-ignore
|
|
605
|
+
// return locations.filter(
|
|
606
|
+
// (loc: L | ClusterNode) => locationIdsInViewport!.has(loc.id)
|
|
607
|
+
// );
|
|
608
|
+
// TODO: return location in viewport + "connected" ones
|
|
609
|
+
return locations;
|
|
610
|
+
});
|
|
611
|
+
this.getLocationsForFlowmapLayerById = createSelector(this.getLocationsForFlowmapLayer, (locations) => {
|
|
612
|
+
if (!locations)
|
|
613
|
+
return undefined;
|
|
614
|
+
return locations.reduce((m, d) => (m.set(this.accessors.getLocationId(d), d), m), new Map());
|
|
615
|
+
});
|
|
616
|
+
this.getLayersData = createSelector(this.getLocationsForFlowmapLayer, this.getFlowsForFlowmapLayer, this.getFlowmapColorsRGBA, this.getLocationsForFlowmapLayerById, this.getLocationIdsInViewport, this.getInCircleSizeGetter, this.getOutCircleSizeGetter, this.getFlowThicknessScale, this.getAnimate, (locations, flows, flowmapColors, locationsById, locationIdsInViewport, getInCircleSize, getOutCircleSize, flowThicknessScale, animationEnabled) => {
|
|
617
|
+
return this._prepareLayersData(locations, flows, flowmapColors, locationsById, locationIdsInViewport, getInCircleSize, getOutCircleSize, flowThicknessScale, animationEnabled);
|
|
618
|
+
});
|
|
619
|
+
this.accessors = new FlowmapAggregateAccessors(accessors);
|
|
620
|
+
this.setAccessors(accessors);
|
|
621
|
+
}
|
|
622
|
+
setAccessors(accessors) {
|
|
623
|
+
this.accessors = new FlowmapAggregateAccessors(accessors);
|
|
624
|
+
}
|
|
625
|
+
prepareLayersData(state, props) {
|
|
626
|
+
const locations = this.getLocationsForFlowmapLayer(state, props) || [];
|
|
627
|
+
const flows = this.getFlowsForFlowmapLayer(state, props) || [];
|
|
628
|
+
const flowmapColors = this.getFlowmapColorsRGBA(state, props);
|
|
629
|
+
const locationsById = this.getLocationsForFlowmapLayerById(state, props);
|
|
630
|
+
const locationIdsInViewport = this.getLocationIdsInViewport(state, props);
|
|
631
|
+
const getInCircleSize = this.getInCircleSizeGetter(state, props);
|
|
632
|
+
const getOutCircleSize = this.getOutCircleSizeGetter(state, props);
|
|
633
|
+
const flowThicknessScale = this.getFlowThicknessScale(state, props);
|
|
634
|
+
return this._prepareLayersData(locations, flows, flowmapColors, locationsById, locationIdsInViewport, getInCircleSize, getOutCircleSize, flowThicknessScale, state.settingsState.animationEnabled);
|
|
635
|
+
}
|
|
636
|
+
_prepareLayersData(locations, flows, flowmapColors, locationsById, locationIdsInViewport, getInCircleSize, getOutCircleSize, flowThicknessScale, animationEnabled) {
|
|
637
|
+
if (!locations)
|
|
638
|
+
locations = [];
|
|
639
|
+
if (!flows)
|
|
640
|
+
flows = [];
|
|
641
|
+
const { getFlowOriginId, getFlowDestId, getFlowMagnitude, getLocationId, getLocationCentroid, } = this.accessors;
|
|
642
|
+
const getCentroid = (id) => {
|
|
643
|
+
const loc = locationsById === null || locationsById === void 0 ? void 0 : locationsById.get(id);
|
|
644
|
+
return loc ? getLocationCentroid(loc) : [0, 0];
|
|
645
|
+
};
|
|
646
|
+
const flowMagnitudeExtent = extent(flows, (f) => getFlowMagnitude(f));
|
|
647
|
+
const flowColorScale = getFlowColorScale(flowmapColors, flowMagnitudeExtent, false);
|
|
648
|
+
// Using a generator here helps to avoid creating intermediary arrays
|
|
649
|
+
const circlePositions = Float32Array.from((function* () {
|
|
650
|
+
for (const location of locations) {
|
|
651
|
+
// yield* effectively works as flatMap here
|
|
652
|
+
yield* getLocationCentroid(location);
|
|
653
|
+
}
|
|
654
|
+
})());
|
|
655
|
+
// TODO: diff mode
|
|
656
|
+
const circleColor = isDiffColorsRGBA(flowmapColors)
|
|
657
|
+
? flowmapColors.positive.locationCircles.inner
|
|
658
|
+
: flowmapColors.locationCircles.inner;
|
|
659
|
+
const circleColors = Uint8Array.from((function* () {
|
|
660
|
+
for (const location of locations) {
|
|
661
|
+
yield* circleColor;
|
|
662
|
+
}
|
|
663
|
+
})());
|
|
664
|
+
const inCircleRadii = Float32Array.from((function* () {
|
|
665
|
+
for (const location of locations) {
|
|
666
|
+
const id = getLocationId(location);
|
|
667
|
+
yield (locationIdsInViewport === null || locationIdsInViewport === void 0 ? void 0 : locationIdsInViewport.has(id)) ? getInCircleSize(id) : 1.0;
|
|
668
|
+
}
|
|
669
|
+
})());
|
|
670
|
+
const outCircleRadii = Float32Array.from((function* () {
|
|
671
|
+
for (const location of locations) {
|
|
672
|
+
const id = getLocationId(location);
|
|
673
|
+
yield (locationIdsInViewport === null || locationIdsInViewport === void 0 ? void 0 : locationIdsInViewport.has(id)) ? getOutCircleSize(id) : 1.0;
|
|
674
|
+
}
|
|
675
|
+
})());
|
|
676
|
+
const sourcePositions = Float32Array.from((function* () {
|
|
677
|
+
for (const flow of flows) {
|
|
678
|
+
yield* getCentroid(getFlowOriginId(flow));
|
|
679
|
+
}
|
|
680
|
+
})());
|
|
681
|
+
const targetPositions = Float32Array.from((function* () {
|
|
682
|
+
for (const flow of flows) {
|
|
683
|
+
yield* getCentroid(getFlowDestId(flow));
|
|
684
|
+
}
|
|
685
|
+
})());
|
|
686
|
+
const thicknesses = Float32Array.from((function* () {
|
|
687
|
+
for (const flow of flows) {
|
|
688
|
+
yield flowThicknessScale
|
|
689
|
+
? flowThicknessScale(getFlowMagnitude(flow)) || 0
|
|
690
|
+
: 0;
|
|
691
|
+
}
|
|
692
|
+
})());
|
|
693
|
+
const endpointOffsets = Float32Array.from((function* () {
|
|
694
|
+
for (const flow of flows) {
|
|
695
|
+
const originId = getFlowOriginId(flow);
|
|
696
|
+
const destId = getFlowDestId(flow);
|
|
697
|
+
yield Math.max(getInCircleSize(originId), getOutCircleSize(originId));
|
|
698
|
+
yield Math.max(getInCircleSize(destId), getOutCircleSize(destId));
|
|
699
|
+
}
|
|
700
|
+
})());
|
|
701
|
+
const flowLineColors = Uint8Array.from((function* () {
|
|
702
|
+
for (const flow of flows) {
|
|
703
|
+
yield* flowColorScale(getFlowMagnitude(flow));
|
|
704
|
+
}
|
|
705
|
+
})());
|
|
706
|
+
const staggeringValues = animationEnabled
|
|
707
|
+
? Float32Array.from((function* () {
|
|
708
|
+
for (const f of flows) {
|
|
709
|
+
// @ts-ignore
|
|
710
|
+
yield new alea(`${getFlowOriginId(f)}-${getFlowDestId(f)}`)();
|
|
711
|
+
}
|
|
712
|
+
})())
|
|
713
|
+
: undefined;
|
|
714
|
+
return {
|
|
715
|
+
circleAttributes: {
|
|
716
|
+
length: locations.length,
|
|
717
|
+
attributes: {
|
|
718
|
+
getPosition: { value: circlePositions, size: 2 },
|
|
719
|
+
getColor: { value: circleColors, size: 4 },
|
|
720
|
+
getInRadius: { value: inCircleRadii, size: 1 },
|
|
721
|
+
getOutRadius: { value: outCircleRadii, size: 1 },
|
|
722
|
+
},
|
|
723
|
+
},
|
|
724
|
+
lineAttributes: {
|
|
725
|
+
length: flows.length,
|
|
726
|
+
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
|
|
727
|
+
? { getStaggering: { value: staggeringValues, size: 1 } }
|
|
728
|
+
: {})),
|
|
729
|
+
},
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
getLocationsInBbox(tree, bbox) {
|
|
733
|
+
if (!tree)
|
|
734
|
+
return undefined;
|
|
735
|
+
return this._getLocationsInBboxIndices(tree, bbox).map((idx) => tree.points[idx]);
|
|
736
|
+
}
|
|
737
|
+
_getLocationsInBboxIndices(tree, bbox) {
|
|
738
|
+
if (!tree)
|
|
739
|
+
return undefined;
|
|
740
|
+
const [lon1, lat1, lon2, lat2] = bbox;
|
|
741
|
+
const [x1, y1, x2, y2] = [lngX(lon1), latY(lat1), lngX(lon2), latY(lat2)];
|
|
742
|
+
return tree.range(Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2));
|
|
743
|
+
}
|
|
744
|
+
isFlowInSelection(flow, selectedLocationsSet, locationFilterMode) {
|
|
745
|
+
const origin = this.accessors.getFlowOriginId(flow);
|
|
746
|
+
const dest = this.accessors.getFlowDestId(flow);
|
|
747
|
+
if (selectedLocationsSet) {
|
|
748
|
+
switch (locationFilterMode) {
|
|
749
|
+
case LocationFilterMode.ALL:
|
|
750
|
+
return (selectedLocationsSet.has(origin) || selectedLocationsSet.has(dest));
|
|
751
|
+
case LocationFilterMode.BETWEEN:
|
|
752
|
+
return (selectedLocationsSet.has(origin) && selectedLocationsSet.has(dest));
|
|
753
|
+
case LocationFilterMode.INCOMING:
|
|
754
|
+
return selectedLocationsSet.has(dest);
|
|
755
|
+
case LocationFilterMode.OUTGOING:
|
|
756
|
+
return selectedLocationsSet.has(origin);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
return true;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
function calcLocationTotalsExtent(locationTotals, locationIdsInViewport) {
|
|
763
|
+
if (!locationTotals)
|
|
764
|
+
return undefined;
|
|
765
|
+
let rv = undefined;
|
|
766
|
+
for (const [id, { incomingCount, outgoingCount, internalCount },] of locationTotals.entries()) {
|
|
767
|
+
if (locationIdsInViewport == null || locationIdsInViewport.has(id)) {
|
|
768
|
+
const lo = Math.min(incomingCount + internalCount, outgoingCount + internalCount, internalCount);
|
|
769
|
+
const hi = Math.max(incomingCount + internalCount, outgoingCount + internalCount, internalCount);
|
|
770
|
+
if (!rv) {
|
|
771
|
+
rv = [lo, hi];
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
if (lo < rv[0])
|
|
775
|
+
rv[0] = lo;
|
|
776
|
+
if (hi > rv[1])
|
|
777
|
+
rv[1] = hi;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
return rv;
|
|
782
|
+
}
|
|
783
|
+
// longitude/latitude to spherical mercator in [0..1] range
|
|
784
|
+
function lngX(lng) {
|
|
785
|
+
return lng / 360 + 0.5;
|
|
786
|
+
}
|
|
787
|
+
function latY(lat) {
|
|
788
|
+
const sin = Math.sin((lat * Math.PI) / 180);
|
|
789
|
+
const y = 0.5 - (0.25 * Math.log((1 + sin) / (1 - sin))) / Math.PI;
|
|
790
|
+
return y < 0 ? 0 : y > 1 ? 1 : y;
|
|
791
|
+
}
|
|
792
|
+
function aggregateFlows(flows, flowAccessors) {
|
|
793
|
+
// Sum up flows with same origin, dest
|
|
794
|
+
const byOriginDest = nest()
|
|
795
|
+
.key(flowAccessors.getFlowOriginId)
|
|
796
|
+
.key(flowAccessors.getFlowDestId)
|
|
797
|
+
.rollup((ff) => {
|
|
798
|
+
const origin = flowAccessors.getFlowOriginId(ff[0]);
|
|
799
|
+
const dest = flowAccessors.getFlowDestId(ff[0]);
|
|
800
|
+
// const color = ff[0].color;
|
|
801
|
+
const rv = {
|
|
802
|
+
aggregate: true,
|
|
803
|
+
origin,
|
|
804
|
+
dest,
|
|
805
|
+
count: ff.reduce((m, f) => {
|
|
806
|
+
const count = flowAccessors.getFlowMagnitude(f);
|
|
807
|
+
if (count) {
|
|
808
|
+
if (!isNaN(count) && isFinite(count))
|
|
809
|
+
return m + count;
|
|
810
|
+
}
|
|
811
|
+
return m;
|
|
812
|
+
}, 0),
|
|
813
|
+
// time: undefined,
|
|
814
|
+
};
|
|
815
|
+
// if (color) rv.color = color;
|
|
816
|
+
return rv;
|
|
817
|
+
})
|
|
818
|
+
.entries(flows);
|
|
819
|
+
const rv = [];
|
|
820
|
+
for (const { values } of byOriginDest) {
|
|
821
|
+
for (const { value } of values) {
|
|
822
|
+
rv.push(value);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return rv;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* This is used to augment hover picking info so that we can displace location tooltip
|
|
829
|
+
* @param circleAttributes
|
|
830
|
+
* @param index
|
|
831
|
+
*/
|
|
832
|
+
export function getOuterCircleRadiusByIndex(circleAttributes, index) {
|
|
833
|
+
const { getInRadius, getOutRadius } = circleAttributes.attributes;
|
|
834
|
+
return Math.max(getInRadius.value[index], getOutRadius.value[index]);
|
|
835
|
+
}
|
|
836
|
+
export function getLocationCentroidByIndex(circleAttributes, index) {
|
|
837
|
+
const { getPosition } = circleAttributes.attributes;
|
|
838
|
+
return [getPosition.value[index * 2], getPosition.value[index * 2 + 1]];
|
|
839
|
+
}
|
|
840
|
+
export function getFlowLineAttributesByIndex(lineAttributes, index) {
|
|
841
|
+
const { getColor, getEndpointOffsets, getSourcePosition, getTargetPosition, getThickness, getStaggering, } = lineAttributes.attributes;
|
|
842
|
+
return {
|
|
843
|
+
length: 1,
|
|
844
|
+
attributes: Object.assign({ getColor: {
|
|
845
|
+
value: getColor.value.subarray(index * 4, (index + 1) * 4),
|
|
846
|
+
size: 4,
|
|
847
|
+
}, getEndpointOffsets: {
|
|
848
|
+
value: getEndpointOffsets.value.subarray(index * 2, (index + 1) * 2),
|
|
849
|
+
size: 2,
|
|
850
|
+
}, getSourcePosition: {
|
|
851
|
+
value: getSourcePosition.value.subarray(index * 2, (index + 1) * 2),
|
|
852
|
+
size: 2,
|
|
853
|
+
}, getTargetPosition: {
|
|
854
|
+
value: getTargetPosition.value.subarray(index * 2, (index + 1) * 2),
|
|
855
|
+
size: 2,
|
|
856
|
+
}, getThickness: {
|
|
857
|
+
value: getThickness.value.subarray(index, index + 1),
|
|
858
|
+
size: 1,
|
|
859
|
+
} }, (getStaggering
|
|
860
|
+
? {
|
|
861
|
+
getStaggering: {
|
|
862
|
+
value: getStaggering.value.subarray(index, index + 1),
|
|
863
|
+
size: 1,
|
|
864
|
+
},
|
|
865
|
+
}
|
|
866
|
+
: undefined)),
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmxvd21hcFNlbGVjdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9GbG93bWFwU2VsZWN0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBRUgsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQzVDLE9BQU8sRUFBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDNUQsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNuQyxPQUFPLEVBQWMsV0FBVyxFQUFFLFNBQVMsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUM3RCxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxFQUNMLGNBQWMsRUFDZCxxQkFBcUIsRUFDckIsY0FBYyxHQUVmLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFDaEMsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUNMLFVBQVUsRUFFVix3QkFBd0IsRUFDeEIsd0JBQXdCLEdBQ3pCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxTQUFTLEVBQUUsRUFHaEIsYUFBYSxFQUNiLGlCQUFpQixFQUNqQixpQkFBaUIsRUFDakIsWUFBWSxFQUNaLGdCQUFnQixHQUNqQixNQUFNLFVBQVUsQ0FBQztBQUNsQixPQUFPLHlCQUF5QixNQUFNLDZCQUE2QixDQUFDO0FBRXBFLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIseUJBQXlCLEVBQ3pCLHlCQUF5QixHQUUxQixNQUFNLFFBQVEsQ0FBQztBQUNoQixPQUFPLEVBVUwsU0FBUyxFQUNULHFCQUFxQixFQUVyQixrQkFBa0IsR0FFbkIsTUFBTSxTQUFTLENBQUM7QUFFakIsTUFBTSxzQkFBc0IsR0FBRyxF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QyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNuRSxJQUFJLEVBQUUsQ0FBQzthQUNSLEVBQ0QsaUJBQWlCLEVBQUU7Z0JBQ2pCLEtBQUssRUFBRSxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNuRSxJQUFJLEVBQUUsQ0FBQzthQUNSLEVBQ0QsWUFBWSxFQUFFO2dCQUNaLEtBQUssRUFBRSxZQUFZLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQztnQkFDcEQsSUFBSSxFQUFFLENBQUM7YUFDUixJQUNFLENBQUMsYUFBYTtZQUNmLENBQUMsQ0FBQztnQkFDRSxhQUFhLEVBQUU7b0JBQ2IsS0FBSyxFQUFFLGFBQWEsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxLQUFLLEdBQUcsQ0FBQyxDQUFDO29CQUNyRCxJQUFJLEVBQUUsQ0FBQztpQkFDUjthQUNGO1lBQ0gsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUNmO0tBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IDIwMjIgRmxvd21hcEJsdWVcbiAqIENvcHlyaWdodCAyMDE4LTIwMjAgVGVyYWx5dGljcywgbW9kaWZpZWQgYnkgRmxvd21hcEJsdWVcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHtib3VuZHN9IGZyb20gJ0BtYXBib3gvZ2VvLXZpZXdwb3J0JztcbmltcG9ydCB7YXNjZW5kaW5nLCBkZXNjZW5kaW5nLCBleHRlbnQsIG1pbn0gZnJvbSAnZDMtYXJyYXknO1xuaW1wb3J0IHtuZXN0fSBmcm9tICdkMy1jb2xsZWN0aW9uJztcbmltcG9ydCB7U2NhbGVMaW5lYXIsIHNjYWxlTGluZWFyLCBzY2FsZVNxcnR9IGZyb20gJ2QzLXNjYWxlJztcbmltcG9ydCBLREJ1c2ggZnJvbSAna2RidXNoJztcbmltcG9ydCB7XG4gIGNyZWF0ZVNlbGVjdG9yLFxuICBjcmVhdGVTZWxlY3RvckNyZWF0b3IsXG4gIGRlZmF1bHRNZW1vaXplLFxuICBQYXJhbWV0cmljU2VsZWN0b3IsXG59IGZyb20gJ3Jlc2VsZWN0JztcbmltcG9ydCB7YWxlYX0gZnJvbSAnc2VlZHJhbmRvbSc7XG5pbXBvcnQge2NsdXN0ZXJMb2NhdGlvbnN9IGZyb20gJy4vY2x1c3Rlci9jbHVzdGVyJztcbmltcG9ydCB7XG4gIGJ1aWxkSW5kZXgsXG4gIENsdXN0ZXJJbmRleCxcbiAgZmluZEFwcHJvcHJpYXRlWm9vbUxldmVsLFxuICBtYWtlTG9jYXRpb25XZWlnaHRHZXR0ZXIsXG59IGZyb20gJy4vY2x1c3Rlci9DbHVzdGVySW5kZXgnO1xuaW1wb3J0IGdldENvbG9ycywge1xuICBDb2xvcnNSR0JBLFxuICBEaWZmQ29sb3JzUkdCQSxcbiAgZ2V0Q29sb3JzUkdCQSxcbiAgZ2V0RGlmZkNvbG9yc1JHQkEsXG4gIGdldEZsb3dDb2xvclNjYWxlLFxuICBpc0RpZmZDb2xvcnMsXG4gIGlzRGlmZkNvbG9yc1JHQkEsXG59IGZyb20gJy4vY29sb3JzJztcbmltcG9ydCBGbG93bWFwQWdncmVnYXRlQWNjZXNzb3JzIGZyb20gJy4vRmxvd21hcEFnZ3JlZ2F0ZUFjY2Vzc29ycyc7XG5pbXBvcnQge0Zsb3dtYXBTdGF0ZX0gZnJvbSAnLi9GbG93bWFwU3RhdGUnO1xuaW1wb3J0IHtcbiAgZ2V0VGltZUdyYW51bGFyaXR5QnlLZXksXG4gIGdldFRpbWVHcmFudWxhcml0eUJ5T3JkZXIsXG4gIGdldFRpbWVHcmFudWxhcml0eUZvckRhdGUsXG4gIFRpbWVHcmFudWxhcml0eUtleSxcbn0gZnJvbSAnLi90aW1lJztcbmltcG9ydCB7XG4gIEFnZ3JlZ2F0ZUZsb3csXG4gIENsdXN0ZXIsXG4gIENsdXN0ZXJOb2RlLFxuICBDb3VudEJ5VGltZSxcbiAgRmxvd0FjY2Vzc29ycyxcbiAgRmxvd0NpcmNsZXNMYXllckF0dHJpYnV0ZXMsXG4gIEZsb3dMaW5lc0xheWVyQXR0cmlidXRlcyxcbiAgRmxvd21hcERhdGEsXG4gIEZsb3dtYXBEYXRhQWNjZXNzb3JzLFxuICBpc0NsdXN0ZXIsXG4gIGlzTG9jYXRpb25DbHVzdGVyTm9kZSxcbiAgTGF5ZXJzRGF0YSxcbiAgTG9jYXRpb25GaWx0ZXJNb2RlLFxuICBMb2NhdGlvblRvdGFscyxcbn0gZnJvbSAnLi90eXBlcyc7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX1pPT01fTEVWRUwgPSAyMDtcbnR5cGUgS0RCdXNoVHJlZSA9IGFueTtcblxuZXhwb3J0IHR5cGUgU2VsZWN0b3I8TCwgRiwgVD4gPSBQYXJhbWV0cmljU2VsZWN0b3I8XG4gIEZsb3dtYXBTdGF0ZSxcbiAgRmxvd21hcERhdGE8TCwgRj4sXG4gIFRcbj47XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZsb3dtYXBTZWxlY3RvcnM8TCwgRj4ge1xuICBhY2Nlc3NvcnM6IEZsb3dtYXBBZ2dyZWdhdGVBY2Nlc3NvcnM8TCwgRj47XG5cbiAgY29uc3RydWN0b3IoYWNjZXNzb3JzOiBGbG93bWFwRGF0YUFjY2Vzc29yczxMLCBGPikge1xuICAgIHRoaXMuYWNjZXNzb3JzID0gbmV3IEZsb3dtYXBBZ2dyZWdhdGVBY2Nlc3NvcnMoYWNjZXNzb3JzKTtcbiAgICB0aGlzLnNldEFjY2Vzc29ycyhhY2Nlc3NvcnMpO1xuICB9XG5cbiAgc2V0QWNjZXNzb3JzKGFjY2Vzc29yczogRmxvd21hcERhdGFBY2Nlc3NvcnM8TCwgRj4pIHtcbiAgICB0aGlzLmFjY2Vzc29ycyA9IG5ldyBGbG93bWFwQWdncmVnYXRlQWNjZXNzb3JzKGFjY2Vzc29ycyk7XG4gIH1cblxuICBnZXRGZXRjaGVkRmxvd3MgPSAoc3RhdGU6IEZsb3dtYXBTdGF0ZSwgcHJvcHM6IEZsb3dtYXBEYXRhPEwsIEY+KSA9PlxuICAgIHByb3BzLmZsb3dzO1xuICBnZXRGZXRjaGVkTG9jYXRpb25zID0gKHN0YXRlOiBGbG93bWFwU3RhdGUsIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPikgPT5cbiAgICBwcm9wcy5sb2NhdGlvbnM7XG4gIGdldE1heFRvcEZsb3dzRGlzcGxheU51bSA9IChzdGF0ZTogRmxvd21hcFN0YXRlLCBwcm9wczogRmxvd21hcERhdGE8TCwgRj4pID0+XG4gICAgc3RhdGUuc2V0dGluZ3NTdGF0ZS5tYXhUb3BGbG93c0Rpc3BsYXlOdW07XG4gIGdldFNlbGVjdGVkTG9jYXRpb25zID0gKHN0YXRlOiBGbG93bWFwU3RhdGUsIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPikgPT5cbiAgICBzdGF0ZS5maWx0ZXJTdGF0ZS5zZWxlY3RlZExvY2F0aW9ucztcbiAgZ2V0TG9jYXRpb25GaWx0ZXJNb2RlID0gKHN0YXRlOiBGbG93bWFwU3RhdGUsIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPikgPT5cbiAgICBzdGF0ZS5maWx0ZXJTdGF0ZS5sb2NhdGlvbkZpbHRlck1vZGU7XG4gIGdldENsdXN0ZXJpbmdFbmFibGVkID0gKHN0YXRlOiBGbG93bWFwU3RhdGUsIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPikgPT5cbiAgICBzdGF0ZS5zZXR0aW5nc1N0YXRlLmNsdXN0ZXJpbmdFbmFibGVkO1xuICBnZXRMb2NhdGlvblRvdGFsc0VuYWJsZWQgPSAoc3RhdGU6IEZsb3dtYXBTdGF0ZSwgcHJvcHM6IEZsb3dtYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLnNldHRpbmdzU3RhdGUubG9jYXRpb25Ub3RhbHNFbmFibGVkO1xuICBnZXRab29tID0gKHN0YXRlOiBGbG93bWFwU3RhdGUsIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPikgPT5cbiAgICBzdGF0ZS52aWV3cG9ydC56b29tO1xuICBnZXRWaWV3cG9ydCA9IChzdGF0ZTogRmxvd21hcFN0YXRlLCBwcm9wczogRmxvd21hcERhdGE8TCwgRj4pID0+XG4gICAgc3RhdGUudmlld3BvcnQ7XG4gIGdldFNlbGVjdGVkVGltZVJhbmdlID0gKHN0YXRlOiBGbG93bWFwU3RhdGUsIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPikgPT5cbiAgICBzdGF0ZS5maWx0ZXJTdGF0ZS5zZWxlY3RlZFRpbWVSYW5nZTtcblxuICBnZXRDb2xvclNjaGVtZUtleTogU2VsZWN0b3I8TCwgRiwgc3RyaW5nIHwgdW5kZWZpbmVkPiA9IChcbiAgICBzdGF0ZTogRmxvd21hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPixcbiAgKSA9PiBzdGF0ZS5zZXR0aW5nc1N0YXRlLmNvbG9yU2NoZW1lO1xuXG4gIGdldERhcmtNb2RlOiBTZWxlY3RvcjxMLCBGLCBib29sZWFuPiA9IChcbiAgICBzdGF0ZTogRmxvd21hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPixcbiAgKSA9PiBzdGF0ZS5zZXR0aW5nc1N0YXRlLmRhcmtNb2RlO1xuXG4gIGdldEZhZGVFbmFibGVkOiBTZWxlY3RvcjxMLCBGLCBib29sZWFuPiA9IChcbiAgICBzdGF0ZTogRmxvd21hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPixcbiAgKSA9PiBzdGF0ZS5zZXR0aW5nc1N0YXRlLmZhZGVFbmFibGVkO1xuXG4gIGdldEZhZGVPcGFjaXR5RW5hYmxlZDogU2VsZWN0b3I8TCwgRiwgYm9vbGVhbj4gPSAoXG4gICAgc3RhdGU6IEZsb3dtYXBTdGF0ZSxcbiAgICBwcm9wczogRmxvd21hcERhdGE8TCwgRj4sXG4gICkgPT4gc3RhdGUuc2V0dGluZ3NTdGF0ZS5mYWRlT3BhY2l0eUVuYWJsZWQ7XG5cbiAgZ2V0RmFkZUFtb3VudDogU2VsZWN0b3I8TCwgRiwgbnVtYmVyPiA9IChcbiAgICBzdGF0ZTogRmxvd21hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPixcbiAgKSA9PiBzdGF0ZS5zZXR0aW5nc1N0YXRlLmZhZGVBbW91bnQ7XG5cbiAgZ2V0QW5pbWF0ZTogU2VsZWN0b3I8TCwgRiwgYm9vbGVhbj4gPSAoXG4gICAgc3RhdGU6IEZsb3dtYXBTdGF0ZSxcbiAgICBwcm9wczogRmxvd21hcERhdGE8TCwgRj4sXG4gICkgPT4gc3RhdGUuc2V0dGluZ3NTdGF0ZS5hbmltYXRpb25FbmFibGVkO1xuXG4gIGdldEludmFsaWRMb2NhdGlvbklkczogU2VsZWN0b3I8TCwgRiwgc3RyaW5nW10gfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRGZXRjaGVkTG9jYXRpb25zLFxuICAgIChsb2NhdGlvbnMpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgaW52YWxpZCA9IFtdO1xuICAgICAgZm9yIChjb25zdCBsb2NhdGlvbiBvZiBsb2NhdGlvbnMpIHtcbiAgICAgICAgY29uc3QgaWQgPSB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGxvY2F0aW9uKTtcbiAgICAgICAgY29uc3QgW2xvbiwgbGF0XSA9IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uQ2VudHJvaWQobG9jYXRpb24pIHx8IFtcbiAgICAgICAgICBOYU4sXG4gICAgICAgICAgTmFOLFxuICAgICAgICBdO1xuICAgICAgICBpZiAoISgtOTAgPD0gbGF0ICYmIGxhdCA8PSA5MCkgfHwgISgtMTgwIDw9IGxvbiAmJiBsb24gPD0gMTgwKSkge1xuICAgICAgICAgIGludmFsaWQucHVzaChpZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBpbnZhbGlkLmxlbmd0aCA+IDAgPyBpbnZhbGlkIDogdW5kZWZpbmVkO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0TG9jYXRpb25zOiBTZWxlY3RvcjxMLCBGLCBMW10gfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRGZXRjaGVkTG9jYXRpb25zLFxuICAgIHRoaXMuZ2V0SW52YWxpZExvY2F0aW9uSWRzLFxuICAgIChsb2NhdGlvbnMsIGludmFsaWRJZHMpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgaWYgKCFpbnZhbGlkSWRzIHx8IGludmFsaWRJZHMubGVuZ3RoID09PSAwKSByZXR1cm4gbG9jYXRpb25zO1xuICAgICAgY29uc3QgaW52YWxpZCA9IG5ldyBTZXQoaW52YWxpZElkcyk7XG4gICAgICByZXR1cm4gbG9jYXRpb25zLmZpbHRlcihcbiAgICAgICAgKGxvY2F0aW9uOiBMKSA9PiAhaW52YWxpZC5oYXModGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25JZChsb2NhdGlvbikpLFxuICAgICAgKTtcbiAgICB9LFxuICApO1xuXG4gIGdldExvY2F0aW9uSWRzOiBTZWxlY3RvcjxMLCBGLCBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9ucyxcbiAgICAobG9jYXRpb25zKSA9PlxuICAgICAgbG9jYXRpb25zXG4gICAgICAgID8gbmV3IFNldChsb2NhdGlvbnMubWFwKHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQpKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgKTtcblxuICBnZXRTZWxlY3RlZExvY2F0aW9uc1NldDogU2VsZWN0b3I8TCwgRiwgU2V0PHN0cmluZz4gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3Rvcih0aGlzLmdldFNlbGVjdGVkTG9jYXRpb25zLCAoaWRzKSA9PlxuICAgICAgaWRzICYmIGlkcy5sZW5ndGggPiAwID8gbmV3IFNldChpZHMpIDogdW5kZWZpbmVkLFxuICAgICk7XG5cbiAgZ2V0U29ydGVkRmxvd3NGb3JLbm93bkxvY2F0aW9uczogU2VsZWN0b3I8TCwgRiwgRltdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IodGhpcy5nZXRGZXRjaGVkRmxvd3MsIHRoaXMuZ2V0TG9jYXRpb25JZHMsIChmbG93cywgaWRzKSA9PiB7XG4gICAgICBpZiAoIWlkcyB8fCAhZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gZmxvd3NcbiAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAoZmxvdzogRikgPT5cbiAgICAgICAgICAgIGlkcy5oYXModGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGZsb3cpKSAmJlxuICAgICAgICAgICAgaWRzLmhhcyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZsb3cpKSxcbiAgICAgICAgKVxuICAgICAgICAuc29ydCgoYTogRiwgYjogRikgPT5cbiAgICAgICAgICBkZXNjZW5kaW5nKFxuICAgICAgICAgICAgTWF0aC5hYnModGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShhKSksXG4gICAgICAgICAgICBNYXRoLmFicyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGIpKSxcbiAgICAgICAgICApLFxuICAgICAgICApO1xuICAgIH0pO1xuXG4gIGdldEFjdHVhbFRpbWVFeHRlbnQ6IFNlbGVjdG9yPEwsIEYsIFtEYXRlLCBEYXRlXSB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKHRoaXMuZ2V0U29ydGVkRmxvd3NGb3JLbm93bkxvY2F0aW9ucywgKGZsb3dzKSA9PiB7XG4gICAgICBpZiAoIWZsb3dzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgbGV0IHN0YXJ0ID0gbnVsbDtcbiAgICAgIGxldCBlbmQgPSBudWxsO1xuICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgIGNvbnN0IHRpbWUgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93VGltZShmbG93KTtcbiAgICAgICAgaWYgKHRpbWUpIHtcbiAgICAgICAgICBpZiAoc3RhcnQgPT0gbnVsbCB8fCBzdGFydCA+IHRpbWUpIHN0YXJ0ID0gdGltZTtcbiAgICAgICAgICBpZiAoZW5kID09IG51bGwgfHwgZW5kIDwgdGltZSkgZW5kID0gdGltZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFzdGFydCB8fCAhZW5kKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIFtzdGFydCwgZW5kXTtcbiAgICB9KTtcblxuICBnZXRUaW1lR3JhbnVsYXJpdHlLZXk6IFNlbGVjdG9yPEwsIEYsIFRpbWVHcmFudWxhcml0eUtleSB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLFxuICAgICAgdGhpcy5nZXRBY3R1YWxUaW1lRXh0ZW50LFxuICAgICAgKGZsb3dzLCB0aW1lRXh0ZW50KSA9PiB7XG4gICAgICAgIGlmICghZmxvd3MgfHwgIXRpbWVFeHRlbnQpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgICAgY29uc3QgbWluT3JkZXIgPSBtaW4oZmxvd3MsIChkKSA9PiB7XG4gICAgICAgICAgY29uc3QgdCA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dUaW1lKGQpO1xuICAgICAgICAgIHJldHVybiB0ID8gZ2V0VGltZUdyYW51bGFyaXR5Rm9yRGF0ZSh0KS5vcmRlciA6IG51bGw7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAobWluT3JkZXIgPT0gbnVsbCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgdGltZUdyYW51bGFyaXR5ID0gZ2V0VGltZUdyYW51bGFyaXR5QnlPcmRlcihtaW5PcmRlcik7XG4gICAgICAgIHJldHVybiB0aW1lR3JhbnVsYXJpdHkgPyB0aW1lR3JhbnVsYXJpdHkua2V5IDogdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldFRpbWVFeHRlbnQ6IFNlbGVjdG9yPEwsIEYsIFtEYXRlLCBEYXRlXSB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldEFjdHVhbFRpbWVFeHRlbnQsXG4gICAgdGhpcy5nZXRUaW1lR3JhbnVsYXJpdHlLZXksXG4gICAgKHRpbWVFeHRlbnQsIHRpbWVHcmFudWxhcml0eUtleSkgPT4ge1xuICAgICAgY29uc3QgdGltZUdyYW51bGFyaXR5ID0gdGltZUdyYW51bGFyaXR5S2V5XG4gICAgICAgID8gZ2V0VGltZUdyYW51bGFyaXR5QnlLZXkodGltZUdyYW51bGFyaXR5S2V5KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgIGlmICghdGltZUV4dGVudCB8fCAhdGltZUdyYW51bGFyaXR5Py5pbnRlcnZhbCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHtpbnRlcnZhbH0gPSB0aW1lR3JhbnVsYXJpdHk7XG4gICAgICByZXR1cm4gW3RpbWVFeHRlbnRbMF0sIGludGVydmFsLm9mZnNldChpbnRlcnZhbC5mbG9vcih0aW1lRXh0ZW50WzFdKSwgMSldO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0U29ydGVkRmxvd3NGb3JLbm93bkxvY2F0aW9uc0ZpbHRlcmVkQnlUaW1lOiBTZWxlY3RvcjxcbiAgICBMLFxuICAgIEYsXG4gICAgRltdIHwgdW5kZWZpbmVkXG4gID4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnMsXG4gICAgdGhpcy5nZXRUaW1lRXh0ZW50LFxuICAgIHRoaXMuZ2V0U2VsZWN0ZWRUaW1lUmFuZ2UsXG4gICAgKGZsb3dzLCB0aW1lRXh0ZW50LCB0aW1lUmFuZ2UpID0+IHtcbiAgICAgIGlmICghZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBpZiAoXG4gICAgICAgICF0aW1lRXh0ZW50IHx8XG4gICAgICAgICF0aW1lUmFuZ2UgfHxcbiAgICAgICAgKHRpbWVFeHRlbnRbMF0gPT09IHRpbWVSYW5nZVswXSAmJiB0aW1lRXh0ZW50WzFdID09PSB0aW1lUmFuZ2VbMV0pXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIGZsb3dzO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZsb3dzLmZpbHRlcigoZmxvdykgPT4ge1xuICAgICAgICBjb25zdCB0aW1lID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd1RpbWUoZmxvdyk7XG4gICAgICAgIHJldHVybiB0aW1lICYmIHRpbWVSYW5nZVswXSA8PSB0aW1lICYmIHRpbWUgPCB0aW1lUmFuZ2VbMV07XG4gICAgICB9KTtcbiAgICB9LFxuICApO1xuXG4gIGdldExvY2F0aW9uc0hhdmluZ0Zsb3dzOiBTZWxlY3RvcjxMLCBGLCBMW10gfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLFxuICAgIHRoaXMuZ2V0TG9jYXRpb25zLFxuICAgIChmbG93cywgbG9jYXRpb25zKSA9PiB7XG4gICAgICBpZiAoIWxvY2F0aW9ucyB8fCAhZmxvd3MpIHJldHVybiBsb2NhdGlvbnM7XG4gICAgICBjb25zdCB3aXRoRmxvd3MgPSBuZXcgU2V0KCk7XG4gICAgICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MpIHtcbiAgICAgICAgd2l0aEZsb3dzLmFkZCh0aGlzLmFjY2Vzc29ycy5nZXRGbG93T3JpZ2luSWQoZmxvdykpO1xuICAgICAgICB3aXRoRmxvd3MuYWRkKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoZmxvdykpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxvY2F0aW9ucy5maWx0ZXIoKGxvY2F0aW9uOiBMKSA9PlxuICAgICAgICB3aXRoRmxvd3MuaGFzKHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQobG9jYXRpb24pKSxcbiAgICAgICk7XG4gICAgfSxcbiAgKTtcblxuICBnZXRMb2NhdGlvbnNCeUlkOiBTZWxlY3RvcjxMLCBGLCBNYXA8c3RyaW5nLCBMPiB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uc0hhdmluZ0Zsb3dzLFxuICAgIChsb2NhdGlvbnMpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIG5lc3Q8TCwgTD4oKVxuICAgICAgICAua2V5KChkOiBMKSA9PiB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGQpKVxuICAgICAgICAucm9sbHVwKChbZF0pID0+IGQpXG4gICAgICAgIC5tYXAobG9jYXRpb25zKSBhcyBhbnkgYXMgTWFwPHN0cmluZywgTD47XG4gICAgfSxcbiAgKTtcblxuICBnZXRDbHVzdGVySW5kZXg6IFNlbGVjdG9yPEwsIEYsIENsdXN0ZXJJbmRleDxGPiB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uc0hhdmluZ0Zsb3dzLFxuICAgIHRoaXMuZ2V0TG9jYXRpb25zQnlJZCxcbiAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnMsXG4gICAgKGxvY2F0aW9ucywgbG9jYXRpb25zQnlJZCwgZmxvd3MpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zIHx8ICFsb2NhdGlvbnNCeUlkIHx8ICFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgY29uc3QgZ2V0TG9jYXRpb25XZWlnaHQgPSBtYWtlTG9jYXRpb25XZWlnaHRHZXR0ZXIoXG4gICAgICAgIGZsb3dzLFxuICAgICAgICB0aGlzLmFjY2Vzc29ycy5nZXRGbG93bWFwRGF0YUFjY2Vzc29ycygpLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGNsdXN0ZXJMZXZlbHMgPSBjbHVzdGVyTG9jYXRpb25zKFxuICAgICAgICBsb2NhdGlvbnMsXG4gICAgICAgIHRoaXMuYWNjZXNzb3JzLmdldEZsb3dtYXBEYXRhQWNjZXNzb3JzKCksXG4gICAgICAgIGdldExvY2F0aW9uV2VpZ2h0LFxuICAgICAgICB7XG4gICAgICAgICAgbWF4Wm9vbTogTUFYX0NMVVNURVJfWk9PTV9MRVZFTCxcbiAgICAgICAgfSxcbiAgICAgICk7XG4gICAgICBjb25zdCBjbHVzdGVySW5kZXggPSBidWlsZEluZGV4PEY+KGNsdXN0ZXJMZXZlbHMpO1xuICAgICAgY29uc3Qge2dldExvY2F0aW9uTmFtZSwgZ2V0TG9jYXRpb25DbHVzdGVyTmFtZX0gPVxuICAgICAgICB0aGlzLmFjY2Vzc29ycy5nZXRGbG93bWFwRGF0YUFjY2Vzc29ycygpO1xuXG4gICAgICAvLyBBZGRpbmcgbWVhbmluZ2Z1bCBuYW1lc1xuICAgICAgY29uc3QgZ2V0TmFtZSA9IChpZDogc3RyaW5nKSA9PiB7XG4gICAgICAgIGNvbnN0IGxvYyA9IGxvY2F0aW9uc0J5SWQuZ2V0KGlkKTtcbiAgICAgICAgaWYgKGxvYykge1xuICAgICAgICAgIHJldHVybiBnZXRMb2NhdGlvbk5hbWVcbiAgICAgICAgICAgID8gZ2V0TG9jYXRpb25OYW1lKGxvYylcbiAgICAgICAgICAgIDogdGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25JZChsb2MpIHx8IGlkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBgXCIke2lkfVwiYDtcbiAgICAgIH07XG4gICAgICBmb3IgKGNvbnN0IGxldmVsIG9mIGNsdXN0ZXJMZXZlbHMpIHtcbiAgICAgICAgZm9yIChjb25zdCBub2RlIG9mIGxldmVsLm5vZGVzKSB7XG4gICAgICAgICAgLy8gSGVyZSBtdXRhdGluZyB0aGUgbm9kZXMgKGFkZGluZyBuYW1lcylcbiAgICAgICAgICBpZiAoaXNDbHVzdGVyKG5vZGUpKSB7XG4gICAgICAgICAgICBjb25zdCBsZWF2ZXMgPSBjbHVzdGVySW5kZXguZXhwYW5kQ2x1c3Rlcihub2RlKTtcblxuICAgICAgICAgICAgbGVhdmVzLnNvcnQoKGEsIGIpID0+XG4gICAgICAgICAgICAgIGRlc2NlbmRpbmcoZ2V0TG9jYXRpb25XZWlnaHQoYSksIGdldExvY2F0aW9uV2VpZ2h0KGIpKSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGlmIChnZXRMb2NhdGlvbkNsdXN0ZXJOYW1lKSB7XG4gICAgICAgICAgICAgIG5vZGUubmFtZSA9IGdldExvY2F0aW9uQ2x1c3Rlck5hbWUobGVhdmVzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNvbnN0IHRvcElkID0gbGVhdmVzWzBdO1xuICAgICAgICAgICAgICBjb25zdCBvdGhlcklkID0gbGVhdmVzLmxlbmd0aCA9PT0gMiA/IGxlYXZlc1sxXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgbm9kZS5uYW1lID0gYFwiJHtnZXROYW1lKHRvcElkKX1cIiBhbmQgJHtcbiAgICAgICAgICAgICAgICBvdGhlcklkXG4gICAgICAgICAgICAgICAgICA/IGBcIiR7Z2V0TmFtZShvdGhlcklkKX1cImBcbiAgICAgICAgICAgICAgICAgIDogYCR7bGVhdmVzLmxlbmd0aCAtIDF9IG90aGVyc2BcbiAgICAgICAgICAgICAgfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIChub2RlIGFzIGFueSkubmFtZSA9IGdldE5hbWUobm9kZS5pZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjbHVzdGVySW5kZXg7XG4gICAgfSxcbiAgKTtcblxuICBnZXRBdmFpbGFibGVDbHVzdGVyWm9vbUxldmVscyA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0Q2x1c3RlckluZGV4LFxuICAgIHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnMsXG4gICAgKGNsdXN0ZXJJbmRleCwgc2VsZWN0ZWRMb2NhdGlvbnMpOiBudW1iZXJbXSB8IHVuZGVmaW5lZCA9PiB7XG4gICAgICBpZiAoIWNsdXN0ZXJJbmRleCkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBsZXQgbWF4Wm9vbSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgIGxldCBtaW5ab29tID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZO1xuXG4gICAgICBjb25zdCBhZGp1c3QgPSAoem9uZUlkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgY2x1c3RlciA9IGNsdXN0ZXJJbmRleC5nZXRDbHVzdGVyQnlJZCh6b25lSWQpO1xuICAgICAgICBpZiAoY2x1c3Rlcikge1xuICAgICAgICAgIG1pblpvb20gPSBNYXRoLm1heChtaW5ab29tLCBjbHVzdGVyLnpvb20pO1xuICAgICAgICAgIG1heFpvb20gPSBNYXRoLm1pbihtYXhab29tLCBjbHVzdGVyLnpvb20pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IHpvb20gPSBjbHVzdGVySW5kZXguZ2V0TWluWm9vbUZvckxvY2F0aW9uKHpvbmVJZCk7XG4gICAgICAgICAgbWluWm9vbSA9IE1hdGgubWF4KG1pblpvb20sIHpvb20pO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBpZiAoc2VsZWN0ZWRMb2NhdGlvbnMpIHtcbiAgICAgICAgZm9yIChjb25zdCBpZCBvZiBzZWxlY3RlZExvY2F0aW9ucykge1xuICAgICAgICAgIGFkanVzdChpZCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNsdXN0ZXJJbmRleC5hdmFpbGFibGVab29tTGV2ZWxzLmZpbHRlcihcbiAgICAgICAgKGxldmVsKSA9PiBtaW5ab29tIDw9IGxldmVsICYmIGxldmVsIDw9IG1heFpvb20sXG4gICAgICApO1xuICAgIH0sXG4gICk7XG5cbiAgX2dldENsdXN0ZXJab29tOiBTZWxlY3RvcjxMLCBGLCBudW1iZXIgfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRDbHVzdGVySW5kZXgsXG4gICAgdGhpcy5nZXRab29tLFxuICAgIHRoaXMuZ2V0QXZhaWxhYmxlQ2x1c3Rlclpvb21MZXZlbHMsXG4gICAgKGNsdXN0ZXJJbmRleCwgbWFwWm9vbSwgYXZhaWxhYmxlQ2x1c3Rlclpvb21MZXZlbHMpID0+IHtcbiAgICAgIGlmICghY2x1c3RlckluZGV4KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgaWYgKCFhdmFpbGFibGVDbHVzdGVyWm9vbUxldmVscykge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjbHVzdGVyWm9vbSA9IGZpbmRBcHByb3ByaWF0ZVpvb21MZXZlbChcbiAgICAgICAgYXZhaWxhYmxlQ2x1c3Rlclpvb21MZXZlbHMsXG4gICAgICAgIG1hcFpvb20sXG4gICAgICApO1xuICAgICAgcmV0dXJuIGNsdXN0ZXJab29tO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0Q2x1c3Rlclpvb20gPSAoc3RhdGU6IEZsb3dtYXBTdGF0ZSwgcHJvcHM6IEZsb3dtYXBEYXRhPEwsIEY+KSA9PiB7XG4gICAgY29uc3Qge3NldHRpbmdzU3RhdGV9ID0gc3RhdGU7XG4gICAgaWYgKCFzZXR0aW5nc1N0YXRlLmNsdXN0ZXJpbmdFbmFibGVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChzZXR0aW5nc1N0YXRlLmNsdXN0ZXJpbmdBdXRvIHx8IHNldHRpbmdzU3RhdGUuY2x1c3RlcmluZ0xldmVsID09IG51bGwpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRDbHVzdGVyWm9vbShzdGF0ZSwgcHJvcHMpO1xuICAgIH1cbiAgICByZXR1cm4gc2V0dGluZ3NTdGF0ZS5jbHVzdGVyaW5nTGV2ZWw7XG4gIH07XG5cbiAgZ2V0TG9jYXRpb25zRm9yU2VhcmNoQm94OiBTZWxlY3RvcjxMLCBGLCAoTCB8IENsdXN0ZXIpW10gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0Q2x1c3RlcmluZ0VuYWJsZWQsXG4gICAgICB0aGlzLmdldExvY2F0aW9uc0hhdmluZ0Zsb3dzLFxuICAgICAgdGhpcy5nZXRTZWxlY3RlZExvY2F0aW9ucyxcbiAgICAgIHRoaXMuZ2V0Q2x1c3Rlclpvb20sXG4gICAgICB0aGlzLmdldENsdXN0ZXJJbmRleCxcbiAgICAgIChcbiAgICAgICAgY2x1c3RlcmluZ0VuYWJsZWQsXG4gICAgICAgIGxvY2F0aW9ucyxcbiAgICAgICAgc2VsZWN0ZWRMb2NhdGlvbnMsXG4gICAgICAgIGNsdXN0ZXJab29tLFxuICAgICAgICBjbHVzdGVySW5kZXgsXG4gICAgICApID0+IHtcbiAgICAgICAgaWYgKCFsb2NhdGlvbnMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGxldCByZXN1bHQ6IChMIHwgQ2x1c3RlcilbXSA9IGxvY2F0aW9ucztcbiAgICAgICAgLy8gaWYgKGNsdXN0ZXJpbmdFbmFibGVkKSB7XG4gICAgICAgIC8vICAgaWYgKGNsdXN0ZXJJbmRleCkge1xuICAgICAgICAvLyAgICAgY29uc3Qgem9vbUl0ZW1zID0gY2x1c3RlckluZGV4LmdldENsdXN0ZXJOb2Rlc0ZvcihjbHVzdGVyWm9vbSk7XG4gICAgICAgIC8vICAgICBpZiAoem9vbUl0ZW1zKSB7XG4gICAgICAgIC8vICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQoem9vbUl0ZW1zLmZpbHRlcihpc0NsdXN0ZXIpKTtcbiAgICAgICAgLy8gICAgIH1cbiAgICAgICAgLy8gICB9XG4gICAgICAgIC8vIH1cblxuICAgICAgICBpZiAocmVzdWx0ICYmIGNsdXN0ZXJJbmRleCAmJiBzZWxlY3RlZExvY2F0aW9ucykge1xuICAgICAgICAgIGNvbnN0IHRvQXBwZW5kID0gW107XG4gICAgICAgICAgZm9yIChjb25zdCBpZCBvZiBzZWxlY3RlZExvY2F0aW9ucykge1xuICAgICAgICAgICAgY29uc3QgY2x1c3RlciA9IGNsdXN0ZXJJbmRleC5nZXRDbHVzdGVyQnlJZChpZCk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIGNsdXN0ZXIgJiZcbiAgICAgICAgICAgICAgIXJlc3VsdC5maW5kKFxuICAgICAgICAgICAgICAgIChkKSA9PlxuICAgICAgICAgICAgICAgICAgKGlzTG9jYXRpb25DbHVzdGVyTm9kZShkKVxuICAgICAgICAgICAgICAgICAgICA/IGQuaWRcbiAgICAgICAgICAgICAgICAgICAgOiB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGQpKSA9PT0gaWQsXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICB0b0FwcGVuZC5wdXNoKGNsdXN0ZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodG9BcHBlbmQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdCh0b0FwcGVuZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0RGlmZk1vZGU6IFNlbGVjdG9yPEwsIEYsIGJvb2xlYW4+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRGZXRjaGVkRmxvd3MsXG4gICAgKGZsb3dzKSA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIGZsb3dzICYmXG4gICAgICAgIGZsb3dzLmZpbmQoKGY6IEYpID0+IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoZikgPCAwKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICk7XG5cbiAgX2dldEZsb3dtYXBDb2xvcnMgPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldERpZmZNb2RlLFxuICAgIHRoaXMuZ2V0Q29sb3JTY2hlbWVLZXksXG4gICAgdGhpcy5nZXREYXJrTW9kZSxcbiAgICB0aGlzLmdldEZhZGVFbmFibGVkLFxuICAgIHRoaXMuZ2V0RmFkZU9wYWNpdHlFbmFibGVkLFxuICAgIHRoaXMuZ2V0RmFkZUFtb3VudCxcbiAgICB0aGlzLmdldEFuaW1hdGUsXG4gICAgZ2V0Q29sb3JzLFxuICApO1xuXG4gIGdldEZsb3dtYXBDb2xvcnNSR0JBID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5fZ2V0Rmxvd21hcENvbG9ycyxcbiAgICAoZmxvd21hcENvbG9ycykgPT4ge1xuICAgICAgcmV0dXJuIGlzRGlmZkNvbG9ycyhmbG93bWFwQ29sb3JzKVxuICAgICAgICA/IGdldERpZmZDb2xvcnNSR0JBKGZsb3dtYXBDb2xvcnMpXG4gICAgICAgIDogZ2V0Q29sb3JzUkdCQShmbG93bWFwQ29sb3JzKTtcbiAgICB9LFxuICApO1xuXG4gIGdldFVua25vd25Mb2NhdGlvbnM6IFNlbGVjdG9yPEwsIEYsIFNldDxzdHJpbmc+IHwgdW5kZWZpbmVkPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25JZHMsXG4gICAgdGhpcy5nZXRGZXRjaGVkRmxvd3MsXG4gICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLFxuICAgIChpZHMsIGZsb3dzLCBmbG93c0Zvcktub3duTG9jYXRpb25zKSA9PiB7XG4gICAgICBpZiAoIWlkcyB8fCAhZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBpZiAoXG4gICAgICAgIGZsb3dzRm9yS25vd25Mb2NhdGlvbnMgJiZcbiAgICAgICAgZmxvd3MubGVuZ3RoID09PSBmbG93c0Zvcktub3duTG9jYXRpb25zLmxlbmd0aFxuICAgICAgKVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgbWlzc2luZyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgIGlmICghaWRzLmhhcyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93T3JpZ2luSWQoZmxvdykpKVxuICAgICAgICAgIG1pc3NpbmcuYWRkKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmbG93KSk7XG4gICAgICAgIGlmICghaWRzLmhhcyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZsb3cpKSlcbiAgICAgICAgICBtaXNzaW5nLmFkZCh0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZsb3cpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtaXNzaW5nO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0U29ydGVkQWdncmVnYXRlZEZpbHRlcmVkRmxvd3M6IFNlbGVjdG9yPFxuICAgIEwsXG4gICAgRixcbiAgICAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW10gfCB1bmRlZmluZWRcbiAgPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0Q2x1c3RlckluZGV4LFxuICAgIHRoaXMuZ2V0Q2x1c3RlcmluZ0VuYWJsZWQsXG4gICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zRmlsdGVyZWRCeVRpbWUsXG4gICAgdGhpcy5nZXRDbHVzdGVyWm9vbSxcbiAgICB0aGlzLmdldFRpbWVFeHRlbnQsXG4gICAgKGNsdXN0ZXJUcmVlLCBpc0NsdXN0ZXJpbmdFbmFibGVkLCBmbG93cywgY2x1c3Rlclpvb20sIHRpbWVFeHRlbnQpID0+IHtcbiAgICAgIGlmICghZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBsZXQgYWdncmVnYXRlZDogKEYgfCBBZ2dyZWdhdGVGbG93KVtdO1xuICAgICAgaWYgKGlzQ2x1c3RlcmluZ0VuYWJsZWQgJiYgY2x1c3RlclRyZWUgJiYgY2x1c3Rlclpvb20gIT0gbnVsbCkge1xuICAgICAgICBhZ2dyZWdhdGVkID0gY2x1c3RlclRyZWUuYWdncmVnYXRlRmxvd3MoXG4gICAgICAgICAgLy8gVE9ETzogYWdncmVnYXRlIGFjcm9zcyB0aW1lXG4gICAgICAgICAgLy8gdGltZUV4dGVudCAhPSBudWxsXG4gICAgICAgICAgLy8gICA/IGFnZ3JlZ2F0ZUZsb3dzKGZsb3dzKSAvLyBjbHVzdGVyVHJlZS5hZ2dyZWdhdGVGbG93cyB3b24ndCBhZ2dyZWdhdGUgdW5jbHVzdGVyZWQgYWNyb3NzIHRpbWVcbiAgICAgICAgICAvLyAgIDogZmxvd3MsXG4gICAgICAgICAgZmxvd3MsXG4gICAgICAgICAgY2x1c3Rlclpvb20sXG4gICAgICAgICAgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd21hcERhdGFBY2Nlc3NvcnMoKSxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFnZ3JlZ2F0ZWQgPSBhZ2dyZWdhdGVGbG93cyhcbiAgICAgICAgICBmbG93cyxcbiAgICAgICAgICB0aGlzLmFjY2Vzc29ycy5nZXRGbG93bWFwRGF0YUFjY2Vzc29ycygpLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgYWdncmVnYXRlZC5zb3J0KChhLCBiKSA9PlxuICAgICAgICBkZXNjZW5kaW5nKFxuICAgICAgICAgIE1hdGguYWJzKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoYSkpLFxuICAgICAgICAgIE1hdGguYWJzKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoYikpLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBhZ2dyZWdhdGVkO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0Rmxvd01hZ25pdHVkZUV4dGVudDogU2VsZWN0b3I8TCwgRiwgW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRTb3J0ZWRBZ2dyZWdhdGVkRmlsdGVyZWRGbG93cyxcbiAgICAgIHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgICB0aGlzLmdldExvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAgIChmbG93cywgc2VsZWN0ZWRMb2NhdGlvbnNTZXQsIGxvY2F0aW9uRmlsdGVyTW9kZSkgPT4ge1xuICAgICAgICBpZiAoIWZsb3dzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBsZXQgcnY6IFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGZvciAoY29uc3QgZiBvZiBmbG93cykge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuYWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmKSAhPT1cbiAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd0Rlc3RJZChmKSAmJlxuICAgICAgICAgICAgdGhpcy5pc0Zsb3dJblNlbGVjdGlvbihmLCBzZWxlY3RlZExvY2F0aW9uc1NldCwgbG9jYXRpb25GaWx0ZXJNb2RlKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGYpO1xuICAgICAgICAgICAgaWYgKHJ2ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgcnYgPSBbY291bnQsIGNvdW50XTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChjb3VudCA8IHJ2WzBdKSBydlswXSA9IGNvdW50O1xuICAgICAgICAgICAgICBpZiAoY291bnQgPiBydlsxXSkgcnZbMV0gPSBjb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJ2O1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldEV4cGFuZGVkU2VsZWN0ZWRMb2NhdGlvbnNTZXQ6IFNlbGVjdG9yPEwsIEYsIFNldDxzdHJpbmc+IHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldENsdXN0ZXJpbmdFbmFibGVkLFxuICAgICAgdGhpcy5nZXRTZWxlY3RlZExvY2F0aW9uc1NldCxcbiAgICAgIHRoaXMuZ2V0Q2x1c3RlckluZGV4LFxuICAgICAgKGNsdXN0ZXJpbmdFbmFibGVkLCBzZWxlY3RlZExvY2F0aW9ucywgY2x1c3RlckluZGV4KSA9PiB7XG4gICAgICAgIGlmICghc2VsZWN0ZWRMb2NhdGlvbnMgfHwgIWNsdXN0ZXJJbmRleCkge1xuICAgICAgICAgIHJldHVybiBzZWxlY3RlZExvY2F0aW9ucztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgICBmb3IgKGNvbnN0IGxvY2F0aW9uSWQgb2Ygc2VsZWN0ZWRMb2NhdGlvbnMpIHtcbiAgICAgICAgICBjb25zdCBjbHVzdGVyID0gY2x1c3RlckluZGV4LmdldENsdXN0ZXJCeUlkKGxvY2F0aW9uSWQpO1xuICAgICAgICAgIGlmIChjbHVzdGVyKSB7XG4gICAgICAgICAgICBjb25zdCBleHBhbmRlZCA9IGNsdXN0ZXJJbmRleC5leHBhbmRDbHVzdGVyKGNsdXN0ZXIpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBpZCBvZiBleHBhbmRlZCkge1xuICAgICAgICAgICAgICByZXN1bHQuYWRkKGlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0LmFkZChsb2NhdGlvbklkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0sXG4gICAgKTtcblxuICBnZXRUb3RhbENvdW50c0J5VGltZTogU2VsZWN0b3I8TCwgRiwgQ291bnRCeVRpbWVbXSB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLFxuICAgICAgdGhpcy5nZXRUaW1lR3JhbnVsYXJpdHlLZXksXG4gICAgICB0aGlzLmdldFRpbWVFeHRlbnQsXG4gICAgICB0aGlzLmdldEV4cGFuZGVkU2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgICB0aGlzLmdldExvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAgIChcbiAgICAgICAgZmxvd3MsXG4gICAgICAgIHRpbWVHcmFudWxhcml0eUtleSxcbiAgICAgICAgdGltZUV4dGVudCxcbiAgICAgICAgc2VsZWN0ZWRMb2NhdGlvblNldCxcbiAgICAgICAgbG9jYXRpb25GaWx0ZXJNb2RlLFxuICAgICAgKSA9PiB7XG4gICAgICAgIGNvbnN0IHRpbWVHcmFudWxhcml0eSA9IHRpbWVHcmFudWxhcml0eUtleVxuICAgICAgICAgID8gZ2V0VGltZUdyYW51bGFyaXR5QnlLZXkodGltZUdyYW51bGFyaXR5S2V5KVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgICBpZiAoIWZsb3dzIHx8ICF0aW1lR3JhbnVsYXJpdHkgfHwgIXRpbWVFeHRlbnQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IGJ5VGltZSA9IGZsb3dzLnJlZHVjZSgobSwgZmxvdykgPT4ge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuaXNGbG93SW5TZWxlY3Rpb24oXG4gICAgICAgICAgICAgIGZsb3csXG4gICAgICAgICAgICAgIHNlbGVjdGVkTG9jYXRpb25TZXQsXG4gICAgICAgICAgICAgIGxvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IGtleSA9IHRpbWVHcmFudWxhcml0eVxuICAgICAgICAgICAgICAuaW50ZXJ2YWwodGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd1RpbWUoZmxvdykpXG4gICAgICAgICAgICAgIC5nZXRUaW1lKCk7XG4gICAgICAgICAgICBtLnNldChcbiAgICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgICAobS5nZXQoa2V5KSA/PyAwKSArIHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoZmxvdyksXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbTtcbiAgICAgICAgfSwgbmV3IE1hcDxudW1iZXIsIG51bWJlcj4oKSk7XG5cbiAgICAgICAgcmV0dXJuIEFycmF5LmZyb20oYnlUaW1lLmVudHJpZXMoKSkubWFwKChbbWlsbGlzLCBjb3VudF0pID0+ICh7XG4gICAgICAgICAgdGltZTogbmV3IERhdGUobWlsbGlzKSxcbiAgICAgICAgICBjb3VudCxcbiAgICAgICAgfSkpO1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldE1heExvY2F0aW9uQ2lyY2xlU2l6ZTogU2VsZWN0b3I8TCwgRiwgbnVtYmVyPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25Ub3RhbHNFbmFibGVkLFxuICAgIChsb2NhdGlvblRvdGFsc0VuYWJsZWQpID0+IChsb2NhdGlvblRvdGFsc0VuYWJsZWQgPyAxNyA6IDEpLFxuICApO1xuXG4gIGdldFZpZXdwb3J0Qm91bmRpbmdCb3g6IFNlbGVjdG9yPEwsIEYsIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldFZpZXdwb3J0LFxuICAgICAgdGhpcy5nZXRNYXhMb2NhdGlvbkNpcmNsZVNpemUsXG4gICAgICAodmlld3BvcnQsIG1heExvY2F0aW9uQ2lyY2xlU2l6ZSkgPT4ge1xuICAgICAgICBjb25zdCBwYWQgPSBtYXhMb2NhdGlvbkNpcmNsZVNpemU7XG4gICAgICAgIHJldHVybiBib3VuZHMoXG4gICAgICAgICAgW3ZpZXdwb3J0LmxvbmdpdHVkZSwgdmlld3BvcnQubGF0aXR1ZGVdLFxuICAgICAgICAgIHZpZXdwb3J0Lnpvb20sXG4gICAgICAgICAgW3ZpZXdwb3J0LndpZHRoICsgcGFkICogMiwgdmlld3BvcnQuaGVpZ2h0ICsgcGFkICogMl0sXG4gICAgICAgICAgNTEyLFxuICAgICAgICApO1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldExvY2F0aW9uc0Zvclpvb206IFNlbGVjdG9yPEwsIEYsIExbXSB8IENsdXN0ZXJOb2RlW10gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0Q2x1c3RlcmluZ0VuYWJsZWQsXG4gICAgICB0aGlzLmdldExvY2F0aW9uc0hhdmluZ0Zsb3dzLFxuICAgICAgdGhpcy5nZXRDbHVzdGVySW5kZXgsXG4gICAgICB0aGlzLmdldENsdXN0ZXJab29tLFxuICAgICAgKGNsdXN0ZXJpbmdFbmFibGVkLCBsb2NhdGlvbnNIYXZpbmdGbG93cywgY2x1c3RlckluZGV4LCBjbHVzdGVyWm9vbSkgPT4ge1xuICAgICAgICBpZiAoY2x1c3RlcmluZ0VuYWJsZWQgJiYgY2x1c3RlckluZGV4KSB7XG4gICAgICAgICAgcmV0dXJuIGNsdXN0ZXJJbmRleC5nZXRDbHVzdGVyTm9kZXNGb3IoY2x1c3Rlclpvb20pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBsb2NhdGlvbnNIYXZpbmdGbG93cztcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICApO1xuXG4gIGdldExvY2F0aW9uVG90YWxzOiBTZWxlY3RvcjxMLCBGLCBNYXA8c3RyaW5nLCBMb2NhdGlvblRvdGFscz4gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25zRm9yWm9vbSxcbiAgICAgIHRoaXMuZ2V0U29ydGVkQWdncmVnYXRlZEZpbHRlcmVkRmxvd3MsXG4gICAgICB0aGlzLmdldFNlbGVjdGVkTG9jYXRpb25zU2V0LFxuICAgICAgdGhpcy5nZXRMb2NhdGlvbkZpbHRlck1vZGUsXG4gICAgICAobG9jYXRpb25zLCBmbG93cywgc2VsZWN0ZWRMb2NhdGlvbnNTZXQsIGxvY2F0aW9uRmlsdGVyTW9kZSkgPT4ge1xuICAgICAgICBpZiAoIWZsb3dzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCB0b3RhbHMgPSBuZXcgTWFwPHN0cmluZywgTG9jYXRpb25Ub3RhbHM+KCk7XG4gICAgICAgIGNvbnN0IGFkZCA9IChcbiAgICAgICAgICBpZDogc3RyaW5nLFxuICAgICAgICAgIGQ6IFBhcnRpYWw8TG9jYXRpb25Ub3RhbHM+LFxuICAgICAgICApOiBMb2NhdGlvblRvdGFscyA9PiB7XG4gICAgICAgICAgY29uc3QgcnYgPSB0b3RhbHMuZ2V0KGlkKSA/PyB7XG4gICAgICAgICAgICBpbmNvbWluZ0NvdW50OiAwLFxuICAgICAgICAgICAgb3V0Z29pbmdDb3VudDogMCxcbiAgICAgICAgICAgIGludGVybmFsQ291bnQ6IDAsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBpZiAoZC5pbmNvbWluZ0NvdW50ICE9IG51bGwpIHJ2LmluY29taW5nQ291bnQgKz0gZC5pbmNvbWluZ0NvdW50O1xuICAgICAgICAgIGlmIChkLm91dGdvaW5nQ291bnQgIT0gbnVsbCkgcnYub3V0Z29pbmdDb3VudCArPSBkLm91dGdvaW5nQ291bnQ7XG4gICAgICAgICAgaWYgKGQuaW50ZXJuYWxDb3VudCAhPSBudWxsKSBydi5pbnRlcm5hbENvdW50ICs9IGQuaW50ZXJuYWxDb3VudDtcbiAgICAgICAgICByZXR1cm4gcnY7XG4gICAgICAgIH07XG4gICAgICAgIGZvciAoY29uc3QgZiBvZiBmbG93cykge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuaXNGbG93SW5TZWxlY3Rpb24oZiwgc2VsZWN0ZWRMb2NhdGlvbnNTZXQsIGxvY2F0aW9uRmlsdGVyTW9kZSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IG9yaWdpbklkID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGYpO1xuICAgICAgICAgICAgY29uc3QgZGVzdElkID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd0Rlc3RJZChmKTtcbiAgICAgICAgICAgIGNvbnN0IGNvdW50ID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmKTtcbiAgICAgICAgICAgIGlmIChvcmlnaW5JZCA9PT0gZGVzdElkKSB7XG4gICAgICAgICAgICAgIHRvdGFscy5zZXQob3JpZ2luSWQsIGFkZChvcmlnaW5JZCwge2ludGVybmFsQ291bnQ6IGNvdW50fSkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdG90YWxzLnNldChvcmlnaW5JZCwgYWRkKG9yaWdpbklkLCB7b3V0Z29pbmdDb3VudDogY291bnR9KSk7XG4gICAgICAgICAgICAgIHRvdGFscy5zZXQoZGVzdElkLCBhZGQoZGVzdElkLCB7aW5jb21pbmdDb3VudDogY291bnR9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0b3RhbHM7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0TG9jYXRpb25zVHJlZTogU2VsZWN0b3I8TCwgRiwgS0RCdXNoVHJlZT4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uc0Zvclpvb20sXG4gICAgKGxvY2F0aW9ucykgPT4ge1xuICAgICAgaWYgKCFsb2NhdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgS0RCdXNoKFxuICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgIGxvY2F0aW9ucyxcbiAgICAgICAgKGxvY2F0aW9uOiBMIHwgQ2x1c3Rlck5vZGUpID0+XG4gICAgICAgICAgbG5nWChcbiAgICAgICAgICAgIGlzTG9jYXRpb25DbHVzdGVyTm9kZShsb2NhdGlvbilcbiAgICAgICAgICAgICAgPyBsb2NhdGlvbi5jZW50cm9pZFswXVxuICAgICAgICAgICAgICA6IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uQ2VudHJvaWQobG9jYXRpb24pWzBdLFxuICAgICAgICAgICksXG4gICAgICAgIChsb2NhdGlvbjogTCB8IENsdXN0ZXJOb2RlKSA9PlxuICAgICAgICAgIGxhdFkoXG4gICAgICAgICAgICBpc0xvY2F0aW9uQ2x1c3Rlck5vZGUobG9jYXRpb24pXG4gICAgICAgICAgICAgID8gbG9jYXRpb24uY2VudHJvaWRbMV1cbiAgICAgICAgICAgICAgOiB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbkNlbnRyb2lkKGxvY2F0aW9uKVsxXSxcbiAgICAgICAgICApLFxuICAgICAgKTtcbiAgICB9LFxuICApO1xuXG4gIF9nZXRMb2NhdGlvbklkc0luVmlld3BvcnQ6IFNlbGVjdG9yPEwsIEYsIFNldDxzdHJpbmc+IHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldExvY2F0aW9uc1RyZWUsXG4gICAgICB0aGlzLmdldFZpZXdwb3J0Qm91bmRpbmdCb3gsXG4gICAgICAodHJlZTogS0RCdXNoVHJlZSwgYmJveDogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pID0+IHtcbiAgICAgICAgY29uc3QgaWRzID0gdGhpcy5fZ2V0TG9jYXRpb25zSW5CYm94SW5kaWNlcyh0cmVlLCBiYm94KTtcbiAgICAgICAgaWYgKGlkcykge1xuICAgICAgICAgIHJldHVybiBuZXcgU2V0KFxuICAgICAgICAgICAgaWRzLm1hcCgoaWR4OiBudW1iZXIpID0+IHRyZWUucG9pbnRzW2lkeF0uaWQpIGFzIEFycmF5PHN0cmluZz4sXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldExvY2F0aW9uSWRzSW5WaWV3cG9ydDogU2VsZWN0b3I8TCwgRiwgU2V0PHN0cmluZz4gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvckNyZWF0b3IoXG4gICAgICBkZWZhdWx0TWVtb2l6ZSxcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIChcbiAgICAgICAgczE6IFNldDxzdHJpbmc+IHwgdW5kZWZpbmVkLFxuICAgICAgICBzMjogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQsXG4gICAgICAgIGluZGV4OiBudW1iZXIsXG4gICAgICApID0+IHtcbiAgICAgICAgaWYgKHMxID09PSBzMikgcmV0dXJuIHRydWU7XG4gICAgICAgIGlmIChzMSA9PSBudWxsIHx8IHMyID09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKHMxLnNpemUgIT09IHMyLnNpemUpIHJldHVybiBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHMxKSBpZiAoIXMyLmhhcyhpdGVtKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0sXG4gICAgKShcbiAgICAgIHRoaXMuX2dldExvY2F0aW9uSWRzSW5WaWV3cG9ydCxcbiAgICAgIChsb2NhdGlvbklkczogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQpID0+IHtcbiAgICAgICAgaWYgKCFsb2NhdGlvbklkcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIGxvY2F0aW9uSWRzO1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldFRvdGFsVW5maWx0ZXJlZENvdW50OiBTZWxlY3RvcjxMLCBGLCBudW1iZXIgfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLFxuICAgIChmbG93cykgPT4ge1xuICAgICAgaWYgKCFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBmbG93cy5yZWR1Y2UoXG4gICAgICAgIChtLCBmbG93KSA9PiBtICsgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmbG93KSxcbiAgICAgICAgMCxcbiAgICAgICk7XG4gICAgfSxcbiAgKTtcblxuICBnZXRUb3RhbEZpbHRlcmVkQ291bnQ6IFNlbGVjdG9yPEwsIEYsIG51bWJlciB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldFNvcnRlZEFnZ3JlZ2F0ZWRGaWx0ZXJlZEZsb3dzLFxuICAgIHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgdGhpcy5nZXRMb2NhdGlvbkZpbHRlck1vZGUsXG4gICAgKGZsb3dzLCBzZWxlY3RlZExvY2F0aW9uU2V0LCBsb2NhdGlvbkZpbHRlck1vZGUpID0+IHtcbiAgICAgIGlmICghZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBjb3VudCA9IGZsb3dzLnJlZHVjZSgobSwgZmxvdykgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgdGhpcy5pc0Zsb3dJblNlbGVjdGlvbihmbG93LCBzZWxlY3RlZExvY2F0aW9uU2V0LCBsb2NhdGlvbkZpbHRlck1vZGUpXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBtICsgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmbG93KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbTtcbiAgICAgIH0sIDApO1xuICAgICAgcmV0dXJuIGNvdW50O1xuICAgIH0sXG4gICk7XG5cbiAgX2dldExvY2F0aW9uVG90YWxzRXh0ZW50OiBTZWxlY3RvcjxMLCBGLCBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IodGhpcy5nZXRMb2NhdGlvblRvdGFscywgKGxvY2F0aW9uVG90YWxzKSA9PlxuICAgICAgY2FsY0xvY2F0aW9uVG90YWxzRXh0ZW50KGxvY2F0aW9uVG90YWxzLCB1bmRlZmluZWQpLFxuICAgICk7XG5cbiAgX2dldExvY2F0aW9uVG90YWxzRm9yVmlld3BvcnRFeHRlbnQ6IFNlbGVjdG9yPFxuICAgIEwsXG4gICAgRixcbiAgICBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkXG4gID4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uVG90YWxzLFxuICAgIHRoaXMuZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgIChsb2NhdGlvblRvdGFscywgbG9jYXRpb25zSW5WaWV3cG9ydCkgPT5cbiAgICAgIGNhbGNMb2NhdGlvblRvdGFsc0V4dGVudChsb2NhdGlvblRvdGFscywgbG9jYXRpb25zSW5WaWV3cG9ydCksXG4gICk7XG5cbiAgZ2V0TG9jYXRpb25Ub3RhbHNFeHRlbnQgPSAoXG4gICAgc3RhdGU6IEZsb3dtYXBTdGF0ZSxcbiAgICBwcm9wczogRmxvd21hcERhdGE8TCwgRj4sXG4gICk6IFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQgPT4ge1xuICAgIGlmIChzdGF0ZS5zZXR0aW5nc1N0YXRlLmFkYXB0aXZlU2NhbGVzRW5hYmxlZCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldExvY2F0aW9uVG90YWxzRm9yVmlld3BvcnRFeHRlbnQoc3RhdGUsIHByb3BzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldExvY2F0aW9uVG90YWxzRXh0ZW50KHN0YXRlLCBwcm9wcyk7XG4gICAgfVxuICB9O1xuXG4gIGdldEZsb3dzRm9yRmxvd21hcExheWVyOiBTZWxlY3RvcjxMLCBGLCAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW10gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0U29ydGVkQWdncmVnYXRlZEZpbHRlcmVkRmxvd3MsXG4gICAgICB0aGlzLmdldExvY2F0aW9uSWRzSW5WaWV3cG9ydCxcbiAgICAgIHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgICB0aGlzLmdldExvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAgIHRoaXMuZ2V0TWF4VG9wRmxvd3NEaXNwbGF5TnVtLFxuICAgICAgKFxuICAgICAgICBmbG93cyxcbiAgICAgICAgbG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgICAgICBzZWxlY3RlZExvY2F0aW9uc1NldCxcbiAgICAgICAgbG9jYXRpb25GaWx0ZXJNb2RlLFxuICAgICAgICBtYXhUb3BGbG93c0Rpc3BsYXlOdW0sXG4gICAgICApID0+IHtcbiAgICAgICAgaWYgKCFmbG93cyB8fCAhbG9jYXRpb25JZHNJblZpZXdwb3J0KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBwaWNrZWQ6IChGIHwgQWdncmVnYXRlRmxvdylbXSA9IFtdO1xuICAgICAgICBsZXQgcGlja2VkQ291bnQgPSAwO1xuICAgICAgICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MpIHtcbiAgICAgICAgICBjb25zdCBvcmlnaW4gPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93T3JpZ2luSWQoZmxvdyk7XG4gICAgICAgICAgY29uc3QgZGVzdCA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoZmxvdyk7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgbG9jYXRpb25JZHNJblZpZXdwb3J0LmhhcyhvcmlnaW4pIHx8XG4gICAgICAgICAgICBsb2NhdGlvbklkc0luVmlld3BvcnQuaGFzKGRlc3QpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIHRoaXMuaXNGbG93SW5TZWxlY3Rpb24oXG4gICAgICAgICAgICAgICAgZmxvdyxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZExvY2F0aW9uc1NldCxcbiAgICAgICAgICAgICAgICBsb2NhdGlvbkZpbHRlck1vZGUsXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICBpZiAob3JpZ2luICE9PSBkZXN0KSB7XG4gICAgICAgICAgICAgICAgLy8gZXhjbHVkZSBzZWxmLWxvb3BzXG4gICAgICAgICAgICAgICAgcGlja2VkLnB1c2goZmxvdyk7XG4gICAgICAgICAgICAgICAgcGlja2VkQ291bnQrKztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBPbmx5IGtlZXAgdG9wXG4gICAgICAgICAgaWYgKHBpY2tlZENvdW50ID4gbWF4VG9wRmxvd3NEaXNwbGF5TnVtKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLyBhc3N1bWluZyB0aGV5IGFyZSBzb3J0ZWQgaW4gZGVzY2VuZGluZyBvcmRlcixcbiAgICAgICAgLy8gd2UgbmVlZCBhc2NlbmRpbmcgZm9yIHJlbmRlcmluZ1xuICAgICAgICByZXR1cm4gcGlja2VkLnJldmVyc2UoKTtcbiAgICAgIH0sXG4gICAgKTtcblxuICBfZ2V0Rmxvd01hZ25pdHVkZUV4dGVudCA9IChcbiAgICBzdGF0ZTogRmxvd21hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPixcbiAgKTogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZCA9PiB7XG4gICAgaWYgKHN0YXRlLnNldHRpbmdzU3RhdGUuYWRhcHRpdmVTY2FsZXNFbmFibGVkKSB7XG4gICAgICBjb25zdCBmbG93cyA9IHRoaXMuZ2V0Rmxvd3NGb3JGbG93bWFwTGF5ZXIoc3RhdGUsIHByb3BzKTtcbiAgICAgIGlmIChmbG93cykge1xuICAgICAgICBjb25zdCBydiA9IGV4dGVudChmbG93cywgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZSk7XG4gICAgICAgIHJldHVybiBydlswXSAhPT0gdW5kZWZpbmVkICYmIHJ2WzFdICE9PSB1bmRlZmluZWQgPyBydiA6IHVuZGVmaW5lZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEZsb3dNYWduaXR1ZGVFeHRlbnQoc3RhdGUsIHByb3BzKTtcbiAgICB9XG4gIH07XG5cbiAgZ2V0TG9jYXRpb25NYXhBYnNUb3RhbEdldHRlciA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25Ub3RhbHMsXG4gICAgKGxvY2F0aW9uVG90YWxzKSA9PiB7XG4gICAgICByZXR1cm4gKGxvY2F0aW9uSWQ6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCB0b3RhbCA9IGxvY2F0aW9uVG90YWxzPy5nZXQobG9jYXRpb25JZCk7XG4gICAgICAgIGlmICghdG90YWwpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChcbiAgICAgICAgICBNYXRoLmFicyh0b3RhbC5pbmNvbWluZ0NvdW50ICsgdG90YWwuaW50ZXJuYWxDb3VudCksXG4gICAgICAgICAgTWF0aC5hYnModG90YWwub3V0Z29pbmdDb3VudCArIHRvdGFsLmludGVybmFsQ291bnQpLFxuICAgICAgICApO1xuICAgICAgfTtcbiAgICB9LFxuICApO1xuXG4gIGdldEZsb3dUaGlja25lc3NTY2FsZSA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0Rmxvd01hZ25pdHVkZUV4dGVudCxcbiAgICAobWFnbml0dWRlRXh0ZW50KSA9PiB7XG4gICAgICBpZiAoIW1hZ25pdHVkZUV4dGVudCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBzY2FsZUxpbmVhcigpXG4gICAgICAgIC5yYW5nZShbMC4wMjUsIDAuNV0pXG4gICAgICAgIC5kb21haW4oW1xuICAgICAgICAgIDAsXG4gICAgICAgICAgLy8gc2hvdWxkIHN1cHBvcnQgZGlmZiBtb2RlIHRvb1xuICAgICAgICAgIE1hdGgubWF4LmFwcGx5KFxuICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgIG1hZ25pdHVkZUV4dGVudC5tYXAoKHg6IG51bWJlciB8IHVuZGVmaW5lZCkgPT4gTWF0aC5hYnMoeCB8fCAwKSksXG4gICAgICAgICAgKSxcbiAgICAgICAgXSk7XG4gICAgfSxcbiAgKTtcblxuICBnZXRDaXJjbGVTaXplU2NhbGUgPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldE1heExvY2F0aW9uQ2lyY2xlU2l6ZSxcbiAgICB0aGlzLmdldExvY2F0aW9uVG90YWxzRW5hYmxlZCxcbiAgICB0aGlzLmdldExvY2F0aW9uVG90YWxzRXh0ZW50LFxuICAgIChtYXhMb2NhdGlvbkNpcmNsZVNpemUsIGxvY2F0aW9uVG90YWxzRW5hYmxlZCwgbG9jYXRpb25Ub3RhbHNFeHRlbnQpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25Ub3RhbHNFbmFibGVkKSB7XG4gICAgICAgIHJldHVybiAoKSA9PiBtYXhMb2NhdGlvbkNpcmNsZVNpemU7XG4gICAgICB9XG4gICAgICBpZiAoIWxvY2F0aW9uVG90YWxzRXh0ZW50KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIHNjYWxlU3FydCgpXG4gICAgICAgIC5yYW5nZShbMCwgbWF4TG9jYXRpb25DaXJjbGVTaXplXSlcbiAgICAgICAgLmRvbWFpbihbXG4gICAgICAgICAgMCxcbiAgICAgICAgICAvLyBzaG91bGQgc3VwcG9ydCBkaWZmIG1vZGUgdG9vXG4gICAgICAgICAgTWF0aC5tYXguYXBwbHkoXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgbG9jYXRpb25Ub3RhbHNFeHRlbnQubWFwKCh4OiBudW1iZXIgfCB1bmRlZmluZWQpID0+XG4gICAgICAgICAgICAgIE1hdGguYWJzKHggfHwgMCksXG4gICAgICAgICAgICApLFxuICAgICAgICAgICksXG4gICAgICAgIF0pO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0SW5DaXJjbGVTaXplR2V0dGVyID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRDaXJjbGVTaXplU2NhbGUsXG4gICAgdGhpcy5nZXRMb2NhdGlvblRvdGFscyxcbiAgICAoY2lyY2xlU2l6ZVNjYWxlLCBsb2NhdGlvblRvdGFscykgPT4ge1xuICAgICAgcmV0dXJuIChsb2NhdGlvbklkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgdG90YWwgPSBsb2NhdGlvblRvdGFscz8uZ2V0KGxvY2F0aW9uSWQpO1xuICAgICAgICBpZiAodG90YWwgJiYgY2lyY2xlU2l6ZVNjYWxlKSB7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGNpcmNsZVNpemVTY2FsZShcbiAgICAgICAgICAgICAgTWF0aC5hYnModG90YWwuaW5jb21pbmdDb3VudCArIHRvdGFsLmludGVybmFsQ291bnQpLFxuICAgICAgICAgICAgKSB8fCAwXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH07XG4gICAgfSxcbiAgKTtcblxuICBnZXRPdXRDaXJjbGVTaXplR2V0dGVyID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRDaXJjbGVTaXplU2NhbGUsXG4gICAgdGhpcy5nZXRMb2NhdGlvblRvdGFscyxcbiAgICAoY2lyY2xlU2l6ZVNjYWxlLCBsb2NhdGlvblRvdGFscykgPT4ge1xuICAgICAgcmV0dXJuIChsb2NhdGlvbklkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgdG90YWwgPSBsb2NhdGlvblRvdGFscz8uZ2V0KGxvY2F0aW9uSWQpO1xuICAgICAgICBpZiAodG90YWwgJiYgY2lyY2xlU2l6ZVNjYWxlKSB7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGNpcmNsZVNpemVTY2FsZShcbiAgICAgICAgICAgICAgTWF0aC5hYnModG90YWwub3V0Z29pbmdDb3VudCArIHRvdGFsLmludGVybmFsQ291bnQpLFxuICAgICAgICAgICAgKSB8fCAwXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH07XG4gICAgfSxcbiAgKTtcblxuICBnZXRTb3J0ZWRMb2NhdGlvbnNGb3Jab29tOiBTZWxlY3RvcjxMLCBGLCBMW10gfCBDbHVzdGVyTm9kZVtdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldExvY2F0aW9uc0Zvclpvb20sXG4gICAgICB0aGlzLmdldEluQ2lyY2xlU2l6ZUdldHRlcixcbiAgICAgIHRoaXMuZ2V0T3V0Q2lyY2xlU2l6ZUdldHRlcixcbiAgICAgIChsb2NhdGlvbnMsIGdldEluQ2lyY2xlU2l6ZSwgZ2V0T3V0Q2lyY2xlU2l6ZSkgPT4ge1xuICAgICAgICBpZiAoIWxvY2F0aW9ucykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgbmV4dExvY2F0aW9ucyA9IFsuLi5sb2NhdGlvbnNdIGFzIExbXSB8IENsdXN0ZXJOb2RlW107XG4gICAgICAgIHJldHVybiBuZXh0TG9jYXRpb25zLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICBjb25zdCBpZEEgPSB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGEpO1xuICAgICAgICAgIGNvbnN0IGlkQiA9IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQoYik7XG4gICAgICAgICAgcmV0dXJuIGFzY2VuZGluZyhcbiAgICAgICAgICAgIE1hdGgubWF4KGdldEluQ2lyY2xlU2l6ZShpZEEpLCBnZXRPdXRDaXJjbGVTaXplKGlkQSkpLFxuICAgICAgICAgICAgTWF0aC5tYXgoZ2V0SW5DaXJjbGVTaXplKGlkQiksIGdldE91dENpcmNsZVNpemUoaWRCKSksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0TG9jYXRpb25zRm9yRmxvd21hcExheWVyOiBTZWxlY3RvcjxcbiAgICBMLFxuICAgIEYsXG4gICAgQXJyYXk8TCB8IENsdXN0ZXJOb2RlPiB8IHVuZGVmaW5lZFxuICA+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRTb3J0ZWRMb2NhdGlvbnNGb3Jab29tLFxuICAgIC8vIHRoaXMuZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgIChcbiAgICAgIGxvY2F0aW9ucyxcbiAgICAgIC8vIGxvY2F0aW9uSWRzSW5WaWV3cG9ydFxuICAgICkgPT4ge1xuICAgICAgLy8gaWYgKCFsb2NhdGlvbnMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAvLyBpZiAoIWxvY2F0aW9uSWRzSW5WaWV3cG9ydCkgcmV0dXJuIGxvY2F0aW9ucztcbiAgICAgIC8vIGlmIChsb2NhdGlvbklkc0luVmlld3BvcnQuc2l6ZSA9PT0gbG9jYXRpb25zLmxlbmd0aCkgcmV0dXJuIGxvY2F0aW9ucztcbiAgICAgIC8vIGNvbnN0IGZpbHRlcmVkID0gW107XG4gICAgICAvLyBmb3IgKGNvbnN0IGxvYyBvZiBsb2NhdGlvbnMpIHtcbiAgICAgIC8vICAgaWYgKGxvY2F0aW9uSWRzSW5WaWV3cG9ydC5oYXMobG9jLmlkKSkge1xuICAgICAgLy8gICAgIGZpbHRlcmVkLnB1c2gobG9jKTtcbiAgICAgIC8vICAgfVxuICAgICAgLy8gfVxuICAgICAgLy8gcmV0dXJuIGZpbHRlcmVkO1xuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgLy8gcmV0dXJuIGxvY2F0aW9ucy5maWx0ZXIoXG4gICAgICAvLyAgIChsb2M6IEwgfCBDbHVzdGVyTm9kZSkgPT4gbG9jYXRpb25JZHNJblZpZXdwb3J0IS5oYXMobG9jLmlkKVxuICAgICAgLy8gKTtcbiAgICAgIC8vIFRPRE86IHJldHVybiBsb2NhdGlvbiBpbiB2aWV3cG9ydCArIFwiY29ubmVjdGVkXCIgb25lc1xuICAgICAgcmV0dXJuIGxvY2F0aW9ucztcbiAgICB9LFxuICApO1xuXG4gIGdldExvY2F0aW9uc0ZvckZsb3dtYXBMYXllckJ5SWQ6IFNlbGVjdG9yPFxuICAgIEwsXG4gICAgRixcbiAgICBNYXA8c3RyaW5nLCBMIHwgQ2x1c3Rlck5vZGU+IHwgdW5kZWZpbmVkXG4gID4gPSBjcmVhdGVTZWxlY3Rvcih0aGlzLmdldExvY2F0aW9uc0ZvckZsb3dtYXBMYXllciwgKGxvY2F0aW9ucykgPT4ge1xuICAgIGlmICghbG9jYXRpb25zKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBsb2NhdGlvbnMucmVkdWNlKFxuICAgICAgKG0sIGQpID0+IChtLnNldCh0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGQpLCBkKSwgbSksXG4gICAgICBuZXcgTWFwKCksXG4gICAgKTtcbiAgfSk7XG5cbiAgZ2V0TGF5ZXJzRGF0YTogU2VsZWN0b3I8TCwgRiwgTGF5ZXJzRGF0YT4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uc0ZvckZsb3dtYXBMYXllcixcbiAgICB0aGlzLmdldEZsb3dzRm9yRmxvd21hcExheWVyLFxuICAgIHRoaXMuZ2V0Rmxvd21hcENvbG9yc1JHQkEsXG4gICAgdGhpcy5nZXRMb2NhdGlvbnNGb3JGbG93bWFwTGF5ZXJCeUlkLFxuICAgIHRoaXMuZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgIHRoaXMuZ2V0SW5DaXJjbGVTaXplR2V0dGVyLFxuICAgIHRoaXMuZ2V0T3V0Q2lyY2xlU2l6ZUdldHRlcixcbiAgICB0aGlzLmdldEZsb3dUaGlja25lc3NTY2FsZSxcbiAgICB0aGlzLmdldEFuaW1hdGUsXG4gICAgKFxuICAgICAgbG9jYXRpb25zLFxuICAgICAgZmxvd3MsXG4gICAgICBmbG93bWFwQ29sb3JzLFxuICAgICAgbG9jYXRpb25zQnlJZCxcbiAgICAgIGxvY2F0aW9uSWRzSW5WaWV3cG9ydCxcbiAgICAgIGdldEluQ2lyY2xlU2l6ZSxcbiAgICAgIGdldE91dENpcmNsZVNpemUsXG4gICAgICBmbG93VGhpY2tuZXNzU2NhbGUsXG4gICAgICBhbmltYXRpb25FbmFibGVkLFxuICAgICkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuX3ByZXBhcmVMYXllcnNEYXRhKFxuICAgICAgICBsb2NhdGlvbnMsXG4gICAgICAgIGZsb3dzLFxuICAgICAgICBmbG93bWFwQ29sb3JzLFxuICAgICAgICBsb2NhdGlvbnNCeUlkLFxuICAgICAgICBsb2NhdGlvbklkc0luVmlld3BvcnQsXG4gICAgICAgIGdldEluQ2lyY2xlU2l6ZSxcbiAgICAgICAgZ2V0T3V0Q2lyY2xlU2l6ZSxcbiAgICAgICAgZmxvd1RoaWNrbmVzc1NjYWxlLFxuICAgICAgICBhbmltYXRpb25FbmFibGVkLFxuICAgICAgKTtcbiAgICB9LFxuICApO1xuXG4gIHByZXBhcmVMYXllcnNEYXRhKHN0YXRlOiBGbG93bWFwU3RhdGUsIHByb3BzOiBGbG93bWFwRGF0YTxMLCBGPik6IExheWVyc0RhdGEge1xuICAgIGNvbnN0IGxvY2F0aW9ucyA9IHRoaXMuZ2V0TG9jYXRpb25zRm9yRmxvd21hcExheWVyKHN0YXRlLCBwcm9wcykgfHwgW107XG4gICAgY29uc3QgZmxvd3MgPSB0aGlzLmdldEZsb3dzRm9yRmxvd21hcExheWVyKHN0YXRlLCBwcm9wcykgfHwgW107XG4gICAgY29uc3QgZmxvd21hcENvbG9ycyA9IHRoaXMuZ2V0Rmxvd21hcENvbG9yc1JHQkEoc3RhdGUsIHByb3BzKTtcbiAgICBjb25zdCBsb2NhdGlvbnNCeUlkID0gdGhpcy5nZXRMb2NhdGlvbnNGb3JGbG93bWFwTGF5ZXJCeUlkKHN0YXRlLCBwcm9wcyk7XG4gICAgY29uc3QgbG9jYXRpb25JZHNJblZpZXdwb3J0ID0gdGhpcy5nZXRMb2NhdGlvbklkc0luVmlld3BvcnQoc3RhdGUsIHByb3BzKTtcbiAgICBjb25zdCBnZXRJbkNpcmNsZVNpemUgPSB0aGlzLmdldEluQ2lyY2xlU2l6ZUdldHRlcihzdGF0ZSwgcHJvcHMpO1xuICAgIGNvbnN0IGdldE91dENpcmNsZVNpemUgPSB0aGlzLmdldE91dENpcmNsZVNpemVHZXR0ZXIoc3RhdGUsIHByb3BzKTtcbiAgICBjb25zdCBmbG93VGhpY2tuZXNzU2NhbGUgPSB0aGlzLmdldEZsb3dUaGlja25lc3NTY2FsZShzdGF0ZSwgcHJvcHMpO1xuICAgIHJldHVybiB0aGlzLl9wcmVwYXJlTGF5ZXJzRGF0YShcbiAgICAgIGxvY2F0aW9ucyxcbiAgICAgIGZsb3dzLFxuICAgICAgZmxvd21hcENvbG9ycyxcbiAgICAgIGxvY2F0aW9uc0J5SWQsXG4gICAgICBsb2NhdGlvbklkc0luVmlld3BvcnQsXG4gICAgICBnZXRJbkNpcmNsZVNpemUsXG4gICAgICBnZXRPdXRDaXJjbGVTaXplLFxuICAgICAgZmxvd1RoaWNrbmVzc1NjYWxlLFxuICAgICAgc3RhdGUuc2V0dGluZ3NTdGF0ZS5hbmltYXRpb25FbmFibGVkLFxuICAgICk7XG4gIH1cblxuICBfcHJlcGFyZUxheWVyc0RhdGEoXG4gICAgbG9jYXRpb25zOiAoTCB8IENsdXN0ZXJOb2RlKVtdIHwgdW5kZWZpbmVkLFxuICAgIGZsb3dzOiAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW10gfCB1bmRlZmluZWQsXG4gICAgZmxvd21hcENvbG9yczogRGlmZkNvbG9yc1JHQkEgfCBDb2xvcnNSR0JBLFxuICAgIGxvY2F0aW9uc0J5SWQ6IE1hcDxzdHJpbmcsIEwgfCBDbHVzdGVyTm9kZT4gfCB1bmRlZmluZWQsXG4gICAgbG9jYXRpb25JZHNJblZpZXdwb3J0OiBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZCxcbiAgICBnZXRJbkNpcmNsZVNpemU6IChsb2NhdGlvbklkOiBzdHJpbmcpID0+IG51bWJlcixcbiAgICBnZXRPdXRDaXJjbGVTaXplOiAobG9jYXRpb25JZDogc3RyaW5nKSA9PiBudW1iZXIsXG4gICAgZmxvd1RoaWNrbmVzc1NjYWxlOiBTY2FsZUxpbmVhcjxudW1iZXIsIG51bWJlciwgbmV2ZXI+IHwgdW5kZWZpbmVkLFxuICAgIGFuaW1hdGlvbkVuYWJsZWQ6IGJvb2xlYW4sXG4gICk6IExheWVyc0RhdGEge1xuICAgIGlmICghbG9jYXRpb25zKSBsb2NhdGlvbnMgPSBbXTtcbiAgICBpZiAoIWZsb3dzKSBmbG93cyA9IFtdO1xuICAgIGNvbnN0IHtcbiAgICAgIGdldEZsb3dPcmlnaW5JZCxcbiAgICAgIGdldEZsb3dEZXN0SWQsXG4gICAgICBnZXRGbG93TWFnbml0dWRlLFxuICAgICAgZ2V0TG9jYXRpb25JZCxcbiAgICAgIGdldExvY2F0aW9uQ2VudHJvaWQsXG4gICAgfSA9IHRoaXMuYWNjZXNzb3JzO1xuXG4gICAgY29uc3QgZ2V0Q2VudHJvaWQgPSAoaWQ6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgbG9jID0gbG9jYXRpb25zQnlJZD8uZ2V0KGlkKTtcbiAgICAgIHJldHVybiBsb2MgPyBnZXRMb2NhdGlvbkNlbnRyb2lkKGxvYykgOiBbMCwgMF07XG4gICAgfTtcblxuICAgIGNvbnN0IGZsb3dNYWduaXR1ZGVFeHRlbnQgPSBleHRlbnQoZmxvd3MsIChmKSA9PiBnZXRGbG93TWFnbml0dWRlKGYpKSBhcyBbXG4gICAgICBudW1iZXIsXG4gICAgICBudW1iZXIsXG4gICAgXTtcbiAgICBjb25zdCBmbG93Q29sb3JTY2FsZSA9IGdldEZsb3dDb2xvclNjYWxlKFxuICAgICAgZmxvd21hcENvbG9ycyxcbiAgICAgIGZsb3dNYWduaXR1ZGVFeHRlbnQsXG4gICAgICBmYWxzZSxcbiAgICApO1xuXG4gICAgLy8gVXNpbmcgYSBnZW5lcmF0b3IgaGVyZSBoZWxwcyB0byBhdm9pZCBjcmVhdGluZyBpbnRlcm1lZGlhcnkgYXJyYXlzXG4gICAgY29uc3QgY2lyY2xlUG9zaXRpb25zID0gRmxvYXQzMkFycmF5LmZyb20oXG4gICAgICAoZnVuY3Rpb24qICgpIHtcbiAgICAgICAgZm9yIChjb25zdCBsb2NhdGlvbiBvZiBsb2NhdGlvbnMpIHtcbiAgICAgICAgICAvLyB5aWVsZCogZWZmZWN0aXZlbHkgd29ya3MgYXMgZmxhdE1hcCBoZXJlXG4gICAgICAgICAgeWllbGQqIGdldExvY2F0aW9uQ2VudHJvaWQobG9jYXRpb24pO1xuICAgICAgICB9XG4gICAgICB9KSgpLFxuICAgICk7XG5cbiAgICAvLyBUT0RPOiBkaWZmIG1vZGVcbiAgICBjb25zdCBjaXJjbGVDb2xvciA9IGlzRGlmZkNvbG9yc1JHQkEoZmxvd21hcENvbG9ycylcbiAgICAgID8gZmxvd21hcENvbG9ycy5wb3NpdGl2ZS5sb2NhdGlvbkNpcmNsZXMuaW5uZXJcbiAgICAgIDogZmxvd21hcENvbG9ycy5sb2NhdGlvbkNpcmNsZXMuaW5uZXI7XG5cbiAgICBjb25zdCBjaXJjbGVDb2xvcnMgPSBVaW50OEFycmF5LmZyb20oXG4gICAgICAoZnVuY3Rpb24qICgpIHtcbiAgICAgICAgZm9yIChjb25zdCBsb2NhdGlvbiBvZiBsb2NhdGlvbnMpIHtcbiAgICAgICAgICB5aWVsZCogY2lyY2xlQ29sb3I7XG4gICAgICAgIH1cbiAgICAgIH0pKCksXG4gICAgKTtcblxuICAgIGNvbnN0IGluQ2lyY2xlUmFkaWkgPSBGbG9hdDMyQXJyYXkuZnJvbShcbiAgICAgIChmdW5jdGlvbiogKCkge1xuICAgICAgICBmb3IgKGNvbnN0IGxvY2F0aW9uIG9mIGxvY2F0aW9ucykge1xuICAgICAgICAgIGNvbnN0IGlkID0gZ2V0TG9jYXRpb25JZChsb2NhdGlvbik7XG4gICAgICAgICAgeWllbGQgbG9jYXRpb25JZHNJblZpZXdwb3J0Py5oYXMoaWQpID8gZ2V0SW5DaXJjbGVTaXplKGlkKSA6IDEuMDtcbiAgICAgICAgfVxuICAgICAgfSkoKSxcbiAgICApO1xuICAgIGNvbnN0IG91dENpcmNsZVJhZGlpID0gRmxvYXQzMkFycmF5LmZyb20oXG4gICAgICAoZnVuY3Rpb24qICgpIHtcbiAgICAgICAgZm9yIChjb25zdCBsb2NhdGlvbiBvZiBsb2NhdGlvbnMpIHtcbiAgICAgICAgICBjb25zdCBpZCA9IGdldExvY2F0aW9uSWQobG9jYXRpb24pO1xuICAgICAgICAgIHlpZWxkIGxvY2F0aW9uSWRzSW5WaWV3cG9ydD8uaGFzKGlkKSA/IGdldE91dENpcmNsZVNpemUoaWQpIDogMS4wO1xuICAgICAgICB9XG4gICAgICB9KSgpLFxuICAgICk7XG5cbiAgICBjb25zdCBzb3VyY2VQb3NpdGlvbnMgPSBGbG9hdDMyQXJyYXkuZnJvbShcbiAgICAgIChmdW5jdGlvbiogKCkge1xuICAgICAgICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MpIHtcbiAgICAgICAgICB5aWVsZCogZ2V0Q2VudHJvaWQoZ2V0Rmxvd09yaWdpbklkKGZsb3cpKTtcbiAgICAgICAgfVxuICAgICAgfSkoKSxcbiAgICApO1xuICAgIGNvbnN0IHRhcmdldFBvc2l0aW9ucyA9IEZsb2F0MzJBcnJheS5mcm9tKFxuICAgICAgKGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgIGZvciAoY29uc3QgZmxvdyBvZiBmbG93cykge1xuICAgICAgICAgIHlpZWxkKiBnZXRDZW50cm9pZChnZXRGbG93RGVzdElkKGZsb3cpKTtcbiAgICAgICAgfVxuICAgICAgfSkoKSxcbiAgICApO1xuICAgIGNvbnN0IHRoaWNrbmVzc2VzID0gRmxvYXQzMkFycmF5LmZyb20oXG4gICAgICAoZnVuY3Rpb24qICgpIHtcbiAgICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgICAgeWllbGQgZmxvd1RoaWNrbmVzc1NjYWxlXG4gICAgICAgICAgICA/IGZsb3dUaGlja25lc3NTY2FsZShnZXRGbG93TWFnbml0dWRlKGZsb3cpKSB8fCAwXG4gICAgICAgICAgICA6IDA7XG4gICAgICAgIH1cbiAgICAgIH0pKCksXG4gICAgKTtcbiAgICBjb25zdCBlbmRwb2ludE9mZnNldHMgPSBGbG9hdDMyQXJyYXkuZnJvbShcbiAgICAgIChmdW5jdGlvbiogKCkge1xuICAgICAgICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MpIHtcbiAgICAgICAgICBjb25zdCBvcmlnaW5JZCA9IGdldEZsb3dPcmlnaW5JZChmbG93KTtcbiAgICAgICAgICBjb25zdCBkZXN0SWQgPSBnZXRGbG93RGVzdElkKGZsb3cpO1xuICAgICAgICAgIHlpZWxkIE1hdGgubWF4KGdldEluQ2lyY2xlU2l6ZShvcmlnaW5JZCksIGdldE91dENpcmNsZVNpemUob3JpZ2luSWQpKTtcbiAgICAgICAgICB5aWVsZCBNYXRoLm1heChnZXRJbkNpcmNsZVNpemUoZGVzdElkKSwgZ2V0T3V0Q2lyY2xlU2l6ZShkZXN0SWQpKTtcbiAgICAgICAgfVxuICAgICAgfSkoKSxcbiAgICApO1xuICAgIGNvbnN0IGZsb3dMaW5lQ29sb3JzID0gVWludDhBcnJheS5mcm9tKFxuICAgICAgKGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgIGZvciAoY29uc3QgZmxvdyBvZiBmbG93cykge1xuICAgICAgICAgIHlpZWxkKiBmbG93Q29sb3JTY2FsZShnZXRGbG93TWFnbml0dWRlKGZsb3cpKTtcbiAgICAgICAgfVxuICAgICAgfSkoKSxcbiAgICApO1xuXG4gICAgY29uc3Qgc3RhZ2dlcmluZ1ZhbHVlcyA9IGFuaW1hdGlvbkVuYWJsZWRcbiAgICAgID8gRmxvYXQzMkFycmF5LmZyb20oXG4gICAgICAgICAgKGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGYgb2YgZmxvd3MpIHtcbiAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICB5aWVsZCBuZXcgYWxlYShgJHtnZXRGbG93T3JpZ2luSWQoZil9LSR7Z2V0Rmxvd0Rlc3RJZChmKX1gKSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pKCksXG4gICAgICAgIClcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNpcmNsZUF0dHJpYnV0ZXM6IHtcbiAgICAgICAgbGVuZ3RoOiBsb2NhdGlvbnMubGVuZ3RoLFxuICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgZ2V0UG9zaXRpb246IHt2YWx1ZTogY2lyY2xlUG9zaXRpb25zLCBzaXplOiAyfSxcbiAgICAgICAgICBnZXRDb2xvcjoge3ZhbHVlOiBjaXJjbGVDb2xvcnMsIHNpemU6IDR9LFxuICAgICAgICAgIGdldEluUmFkaXVzOiB7dmFsdWU6IGluQ2lyY2xlUmFkaWksIHNpemU6IDF9LFxuICAgICAgICAgIGdldE91dFJhZGl1czoge3ZhbHVlOiBvdXRDaXJjbGVSYWRpaSwgc2l6ZTogMX0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgbGluZUF0dHJpYnV0ZXM6IHtcbiAgICAgICAgbGVuZ3RoOiBmbG93cy5sZW5ndGgsXG4gICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICBnZXRTb3VyY2VQb3NpdGlvbjoge3ZhbHVlOiBzb3VyY2VQb3NpdGlvbnMsIHNpemU6IDJ9LFxuICAgICAgICAgIGdldFRhcmdldFBvc2l0aW9uOiB7dmFsdWU6IHRhcmdldFBvc2l0aW9ucywgc2l6ZTogMn0sXG4gICAgICAgICAgZ2V0VGhpY2tuZXNzOiB7dmFsdWU6IHRoaWNrbmVzc2VzLCBzaXplOiAxfSxcbiAgICAgICAgICBnZXRDb2xvcjoge3ZhbHVlOiBmbG93TGluZUNvbG9ycywgc2l6ZTogNH0sXG4gICAgICAgICAgZ2V0RW5kcG9pbnRPZmZzZXRzOiB7dmFsdWU6IGVuZHBvaW50T2Zmc2V0cywgc2l6ZTogMn0sXG4gICAgICAgICAgLi4uKHN0YWdnZXJpbmdWYWx1ZXNcbiAgICAgICAgICAgID8ge2dldFN0YWdnZXJpbmc6IHt2YWx1ZTogc3RhZ2dlcmluZ1ZhbHVlcywgc2l6ZTogMX19XG4gICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIGdldExvY2F0aW9uc0luQmJveChcbiAgICB0cmVlOiBLREJ1c2hUcmVlLFxuICAgIGJib3g6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICApOiBBcnJheTxMPiB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF0cmVlKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiB0aGlzLl9nZXRMb2NhdGlvbnNJbkJib3hJbmRpY2VzKHRyZWUsIGJib3gpLm1hcChcbiAgICAgIChpZHg6IG51bWJlcikgPT4gdHJlZS5wb2ludHNbaWR4XSxcbiAgICApIGFzIEFycmF5PEw+O1xuICB9XG5cbiAgX2dldExvY2F0aW9uc0luQmJveEluZGljZXMoXG4gICAgdHJlZTogS0RCdXNoVHJlZSxcbiAgICBiYm94OiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgKSB7XG4gICAgaWYgKCF0cmVlKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IFtsb24xLCBsYXQxLCBsb24yLCBsYXQyXSA9IGJib3g7XG4gICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyXSA9IFtsbmdYKGxvbjEpLCBsYXRZKGxhdDEpLCBsbmdYKGxvbjIpLCBsYXRZKGxhdDIpXTtcbiAgICByZXR1cm4gdHJlZS5yYW5nZShcbiAgICAgIE1hdGgubWluKHgxLCB4MiksXG4gICAgICBNYXRoLm1pbih5MSwgeTIpLFxuICAgICAgTWF0aC5tYXgoeDEsIHgyKSxcbiAgICAgIE1hdGgubWF4KHkxLCB5MiksXG4gICAgKTtcbiAgfVxuXG4gIGlzRmxvd0luU2VsZWN0aW9uKFxuICAgIGZsb3c6IEYgfCBBZ2dyZWdhdGVGbG93LFxuICAgIHNlbGVjdGVkTG9jYXRpb25zU2V0OiBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZCxcbiAgICBsb2NhdGlvbkZpbHRlck1vZGU6IExvY2F0aW9uRmlsdGVyTW9kZSxcbiAgKSB7XG4gICAgY29uc3Qgb3JpZ2luID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGZsb3cpO1xuICAgIGNvbnN0IGRlc3QgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZsb3cpO1xuICAgIGlmIChzZWxlY3RlZExvY2F0aW9uc1NldCkge1xuICAgICAgc3dpdGNoIChsb2NhdGlvbkZpbHRlck1vZGUpIHtcbiAgICAgICAgY2FzZSBMb2NhdGlvbkZpbHRlck1vZGUuQUxMOlxuICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBzZWxlY3RlZExvY2F0aW9uc1NldC5oYXMob3JpZ2luKSB8fCBzZWxlY3RlZExvY2F0aW9uc1NldC5oYXMoZGVzdClcbiAgICAgICAgICApO1xuICAgICAgICBjYXNlIExvY2F0aW9uRmlsdGVyTW9kZS5CRVRXRUVOOlxuICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBzZWxlY3RlZExvY2F0aW9uc1NldC5oYXMob3JpZ2luKSAmJiBzZWxlY3RlZExvY2F0aW9uc1NldC5oYXMoZGVzdClcbiAgICAgICAgICApO1xuICAgICAgICBjYXNlIExvY2F0aW9uRmlsdGVyTW9kZS5JTkNPTUlORzpcbiAgICAgICAgICByZXR1cm4gc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKGRlc3QpO1xuICAgICAgICBjYXNlIExvY2F0aW9uRmlsdGVyTW9kZS5PVVRHT0lORzpcbiAgICAgICAgICByZXR1cm4gc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKG9yaWdpbik7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gY2FsY0xvY2F0aW9uVG90YWxzKFxuICAvLyAgIGxvY2F0aW9uczogKEwgfCBDbHVzdGVyTm9kZSlbXSxcbiAgLy8gICBmbG93czogRltdLFxuICAvLyApOiBMb2NhdGlvbnNUb3RhbHMge1xuICAvLyAgIHJldHVybiBmbG93cy5yZWR1Y2UoXG4gIC8vICAgICAoYWNjOiBMb2NhdGlvbnNUb3RhbHMsIGN1cnIpID0+IHtcbiAgLy8gICAgICAgY29uc3Qgb3JpZ2luSWQgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93T3JpZ2luSWQoY3Vycik7XG4gIC8vICAgICAgIGNvbnN0IGRlc3RJZCA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoY3Vycik7XG4gIC8vICAgICAgIGNvbnN0IG1hZ25pdHVkZSA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoY3Vycik7XG4gIC8vICAgICAgIGlmIChvcmlnaW5JZCA9PT0gZGVzdElkKSB7XG4gIC8vICAgICAgICAgYWNjLmludGVybmFsW29yaWdpbklkXSA9IChhY2MuaW50ZXJuYWxbb3JpZ2luSWRdIHx8IDApICsgbWFnbml0dWRlO1xuICAvLyAgICAgICB9IGVsc2Uge1xuICAvLyAgICAgICAgIGFjYy5vdXRnb2luZ1tvcmlnaW5JZF0gPSAoYWNjLm91dGdvaW5nW29yaWdpbklkXSB8fCAwKSArIG1hZ25pdHVkZTtcbiAgLy8gICAgICAgICBhY2MuaW5jb21pbmdbZGVzdElkXSA9IChhY2MuaW5jb21pbmdbZGVzdElkXSB8fCAwKSArIG1hZ25pdHVkZTtcbiAgLy8gICAgICAgfVxuICAvLyAgICAgICByZXR1cm4gYWNjO1xuICAvLyAgICAgfSxcbiAgLy8gICAgIHtpbmNvbWluZzoge30sIG91dGdvaW5nOiB7fSwgaW50ZXJuYWw6IHt9fSxcbiAgLy8gICApO1xuICAvLyB9XG59XG5cbmZ1bmN0aW9uIGNhbGNMb2NhdGlvblRvdGFsc0V4dGVudChcbiAgbG9jYXRpb25Ub3RhbHM6IE1hcDxzdHJpbmcsIExvY2F0aW9uVG90YWxzPiB8IHVuZGVmaW5lZCxcbiAgbG9jYXRpb25JZHNJblZpZXdwb3J0OiBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZCxcbikge1xuICBpZiAoIWxvY2F0aW9uVG90YWxzKSByZXR1cm4gdW5kZWZpbmVkO1xuICBsZXQgcnY6IFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3QgW1xuICAgIGlkLFxuICAgIHtpbmNvbWluZ0NvdW50LCBvdXRnb2luZ0NvdW50LCBpbnRlcm5hbENvdW50fSxcbiAgXSBvZiBsb2NhdGlvblRvdGFscy5lbnRyaWVzKCkpIHtcbiAgICBpZiAobG9jYXRpb25JZHNJblZpZXdwb3J0ID09IG51bGwgfHwgbG9jYXRpb25JZHNJblZpZXdwb3J0LmhhcyhpZCkpIHtcbiAgICAgIGNvbnN0IGxvID0gTWF0aC5taW4oXG4gICAgICAgIGluY29taW5nQ291bnQgKyBpbnRlcm5hbENvdW50LFxuICAgICAgICBvdXRnb2luZ0NvdW50ICsgaW50ZXJuYWxDb3VudCxcbiAgICAgICAgaW50ZXJuYWxDb3VudCxcbiAgICAgICk7XG4gICAgICBjb25zdCBoaSA9IE1hdGgubWF4KFxuICAgICAgICBpbmNvbWluZ0NvdW50ICsgaW50ZXJuYWxDb3VudCxcbiAgICAgICAgb3V0Z29pbmdDb3VudCArIGludGVybmFsQ291bnQsXG4gICAgICAgIGludGVybmFsQ291bnQsXG4gICAgICApO1xuICAgICAgaWYgKCFydikge1xuICAgICAgICBydiA9IFtsbywgaGldO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGxvIDwgcnZbMF0pIHJ2WzBdID0gbG87XG4gICAgICAgIGlmIChoaSA+IHJ2WzFdKSBydlsxXSA9IGhpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcnY7XG59XG5cbi8vIGxvbmdpdHVkZS9sYXRpdHVkZSB0byBzcGhlcmljYWwgbWVyY2F0b3IgaW4gWzAuLjFdIHJhbmdlXG5mdW5jdGlvbiBsbmdYKGxuZzogbnVtYmVyKSB7XG4gIHJldHVybiBsbmcgLyAzNjAgKyAwLjU7XG59XG5cbmZ1bmN0aW9uIGxhdFkobGF0OiBudW1iZXIpIHtcbiAgY29uc3Qgc2luID0gTWF0aC5zaW4oKGxhdCAqIE1hdGguUEkpIC8gMTgwKTtcbiAgY29uc3QgeSA9IDAuNSAtICgwLjI1ICogTWF0aC5sb2coKDEgKyBzaW4pIC8gKDEgLSBzaW4pKSkgLyBNYXRoLlBJO1xuICByZXR1cm4geSA8IDAgPyAwIDogeSA+IDEgPyAxIDogeTtcbn1cblxuZnVuY3Rpb24gYWdncmVnYXRlRmxvd3M8Rj4oXG4gIGZsb3dzOiBGW10sXG4gIGZsb3dBY2Nlc3NvcnM6IEZsb3dBY2Nlc3NvcnM8Rj4sXG4pOiBBZ2dyZWdhdGVGbG93W10ge1xuICAvLyBTdW0gdXAgZmxvd3Mgd2l0aCBzYW1lIG9yaWdpbiwgZGVzdFxuICBjb25zdCBieU9yaWdpbkRlc3QgPSBuZXN0PEYsIEFnZ3JlZ2F0ZUZsb3c+KClcbiAgICAua2V5KGZsb3dBY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKVxuICAgIC5rZXkoZmxvd0FjY2Vzc29ycy5nZXRGbG93RGVzdElkKVxuICAgIC5yb2xsdXAoKGZmOiBGW10pID0+IHtcbiAgICAgIGNvbnN0IG9yaWdpbiA9IGZsb3dBY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGZmWzBdKTtcbiAgICAgIGNvbnN0IGRlc3QgPSBmbG93QWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoZmZbMF0pO1xuICAgICAgLy8gY29uc3QgY29sb3IgPSBmZlswXS5jb2xvcjtcbiAgICAgIGNvbnN0IHJ2OiBBZ2dyZWdhdGVGbG93ID0ge1xuICAgICAgICBhZ2dyZWdhdGU6IHRydWUsXG4gICAgICAgIG9yaWdpbixcbiAgICAgICAgZGVzdCxcbiAgICAgICAgY291bnQ6IGZmLnJlZHVjZSgobSwgZikgPT4ge1xuICAgICAgICAgIGNvbnN0IGNvdW50ID0gZmxvd0FjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGYpO1xuICAgICAgICAgIGlmIChjb3VudCkge1xuICAgICAgICAgICAgaWYgKCFpc05hTihjb3VudCkgJiYgaXNGaW5pdGUoY291bnQpKSByZXR1cm4gbSArIGNvdW50O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbTtcbiAgICAgICAgfSwgMCksXG4gICAgICAgIC8vIHRpbWU6IHVuZGVmaW5lZCxcbiAgICAgIH07XG4gICAgICAvLyBpZiAoY29sb3IpIHJ2LmNvbG9yID0gY29sb3I7XG4gICAgICByZXR1cm4gcnY7XG4gICAgfSlcbiAgICAuZW50cmllcyhmbG93cyk7XG4gIGNvbnN0IHJ2OiBBZ2dyZWdhdGVGbG93W10gPSBbXTtcbiAgZm9yIChjb25zdCB7dmFsdWVzfSBvZiBieU9yaWdpbkRlc3QpIHtcbiAgICBmb3IgKGNvbnN0IHt2YWx1ZX0gb2YgdmFsdWVzKSB7XG4gICAgICBydi5wdXNoKHZhbHVlKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJ2O1xufVxuXG4vKipcbiAqIFRoaXMgaXMgdXNlZCB0byBhdWdtZW50IGhvdmVyIHBpY2tpbmcgaW5mbyBzbyB0aGF0IHdlIGNhbiBkaXNwbGFjZSBsb2NhdGlvbiB0b29sdGlwXG4gKiBAcGFyYW0gY2lyY2xlQXR0cmlidXRlc1xuICogQHBhcmFtIGluZGV4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRPdXRlckNpcmNsZVJhZGl1c0J5SW5kZXgoXG4gIGNpcmNsZUF0dHJpYnV0ZXM6IEZsb3dDaXJjbGVzTGF5ZXJBdHRyaWJ1dGVzLFxuICBpbmRleDogbnVtYmVyLFxuKTogbnVtYmVyIHtcbiAgY29uc3Qge2dldEluUmFkaXVzLCBnZXRPdXRSYWRpdXN9ID0gY2lyY2xlQXR0cmlidXRlcy5hdHRyaWJ1dGVzO1xuICByZXR1cm4gTWF0aC5tYXgoZ2V0SW5SYWRpdXMudmFsdWVbaW5kZXhdLCBnZXRPdXRSYWRpdXMudmFsdWVbaW5kZXhdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExvY2F0aW9uQ2VudHJvaWRCeUluZGV4KFxuICBjaXJjbGVBdHRyaWJ1dGVzOiBGbG93Q2lyY2xlc0xheWVyQXR0cmlidXRlcyxcbiAgaW5kZXg6IG51bWJlcixcbik6IFtudW1iZXIsIG51bWJlcl0ge1xuICBjb25zdCB7Z2V0UG9zaXRpb259ID0gY2lyY2xlQXR0cmlidXRlcy5hdHRyaWJ1dGVzO1xuICByZXR1cm4gW2dldFBvc2l0aW9uLnZhbHVlW2luZGV4ICogMl0sIGdldFBvc2l0aW9uLnZhbHVlW2luZGV4ICogMiArIDFdXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZsb3dMaW5lQXR0cmlidXRlc0J5SW5kZXgoXG4gIGxpbmVBdHRyaWJ1dGVzOiBGbG93TGluZXNMYXllckF0dHJpYnV0ZXMsXG4gIGluZGV4OiBudW1iZXIsXG4pOiBGbG93TGluZXNMYXllckF0dHJpYnV0ZXMge1xuICBjb25zdCB7XG4gICAgZ2V0Q29sb3IsXG4gICAgZ2V0RW5kcG9pbnRPZmZzZXRzLFxuICAgIGdldFNvdXJjZVBvc2l0aW9uLFxuICAgIGdldFRhcmdldFBvc2l0aW9uLFxuICAgIGdldFRoaWNrbmVzcyxcbiAgICBnZXRTdGFnZ2VyaW5nLFxuICB9ID0gbGluZUF0dHJpYnV0ZXMuYXR0cmlidXRlcztcbiAgcmV0dXJuIHtcbiAgICBsZW5ndGg6IDEsXG4gICAgYXR0cmlidXRlczoge1xuICAgICAgZ2V0Q29sb3I6IHtcbiAgICAgICAgdmFsdWU6IGdldENvbG9yLnZhbHVlLnN1YmFycmF5KGluZGV4ICogNCwgKGluZGV4ICsgMSkgKiA0KSxcbiAgICAgICAgc2l6ZTogNCxcbiAgICAgIH0sXG4gICAgICBnZXRFbmRwb2ludE9mZnNldHM6IHtcbiAgICAgICAgdmFsdWU6IGdldEVuZHBvaW50T2Zmc2V0cy52YWx1ZS5zdWJhcnJheShpbmRleCAqIDIsIChpbmRleCArIDEpICogMiksXG4gICAgICAgIHNpemU6IDIsXG4gICAgICB9LFxuICAgICAgZ2V0U291cmNlUG9zaXRpb246IHtcbiAgICAgICAgdmFsdWU6IGdldFNvdXJjZVBvc2l0aW9uLnZhbHVlLnN1YmFycmF5KGluZGV4ICogMiwgKGluZGV4ICsgMSkgKiAyKSxcbiAgICAgICAgc2l6ZTogMixcbiAgICAgIH0sXG4gICAgICBnZXRUYXJnZXRQb3NpdGlvbjoge1xuICAgICAgICB2YWx1ZTogZ2V0VGFyZ2V0UG9zaXRpb24udmFsdWUuc3ViYXJyYXkoaW5kZXggKiAyLCAoaW5kZXggKyAxKSAqIDIpLFxuICAgICAgICBzaXplOiAyLFxuICAgICAgfSxcbiAgICAgIGdldFRoaWNrbmVzczoge1xuICAgICAgICB2YWx1ZTogZ2V0VGhpY2tuZXNzLnZhbHVlLnN1YmFycmF5KGluZGV4LCBpbmRleCArIDEpLFxuICAgICAgICBzaXplOiAxLFxuICAgICAgfSxcbiAgICAgIC4uLihnZXRTdGFnZ2VyaW5nXG4gICAgICAgID8ge1xuICAgICAgICAgICAgZ2V0U3RhZ2dlcmluZzoge1xuICAgICAgICAgICAgICB2YWx1ZTogZ2V0U3RhZ2dlcmluZy52YWx1ZS5zdWJhcnJheShpbmRleCwgaW5kZXggKyAxKSxcbiAgICAgICAgICAgICAgc2l6ZTogMSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfVxuICAgICAgICA6IHVuZGVmaW5lZCksXG4gICAgfSxcbiAgfTtcbn1cbiJdfQ==
|