@flowmap.gl/data 8.0.0-alpha.4 → 8.0.0-alpha.8
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 -46
- package/dist/FlowmapSelectors.d.ts.map +1 -0
- package/dist/FlowmapSelectors.js +870 -0
- package/dist/{FlowMapState.d.ts → FlowmapState.d.ts} +5 -3
- package/dist/{FlowMapState.d.ts.map → FlowmapState.d.ts.map} +1 -1
- package/dist/{FlowMapState.js → FlowmapState.js} +1 -1
- package/dist/colors.d.ts +7 -7
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +20 -10
- package/dist/getViewStateForLocations.d.ts +18 -11
- package/dist/getViewStateForLocations.d.ts.map +1 -1
- package/dist/getViewStateForLocations.js +21 -18
- 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/package.json +7 -3
- package/src/{FlowMapAggregateAccessors.ts → FlowmapAggregateAccessors.ts} +6 -6
- package/src/{FlowMapSelectors.ts → FlowmapSelectors.ts} +89 -86
- package/src/{FlowMapState.ts → FlowmapState.ts} +4 -2
- package/src/colors.ts +22 -12
- package/src/getViewStateForLocations.ts +39 -35
- 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/dist/FlowMapSelectors.d.ts.map +0 -1
- package/dist/FlowMapSelectors.js +0 -869
- 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
package/dist/FlowMapSelectors.js
DELETED
|
@@ -1,869 +0,0 @@
|
|
|
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
|
-
const NUMBER_OF_FLOWS_TO_DISPLAY = 5000;
|
|
33
|
-
export default class FlowMapSelectors {
|
|
34
|
-
constructor(accessors) {
|
|
35
|
-
this.getFetchedFlows = (state, props) => props.flows;
|
|
36
|
-
this.getFetchedLocations = (state, props) => props.locations;
|
|
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, (flows, locationIdsInViewport, selectedLocationsSet, locationFilterMode) => {
|
|
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 > NUMBER_OF_FLOWS_TO_DISPLAY)
|
|
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 yield here helps to avoid creating intermediary arrays
|
|
649
|
-
const circlePositions = Float32Array.from((function* () {
|
|
650
|
-
for (const location of locations) {
|
|
651
|
-
// yield* effectively does same 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 flow 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmxvd01hcFNlbGVjdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9GbG93TWFwU2VsZWN0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBRUgsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQzVDLE9BQU8sRUFBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDNUQsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNuQyxPQUFPLEVBQWMsV0FBVyxFQUFFLFNBQVMsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUM3RCxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxFQUNMLGNBQWMsRUFDZCxxQkFBcUIsRUFDckIsY0FBYyxHQUVmLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFDaEMsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUNMLFVBQVUsRUFFVix3QkFBd0IsRUFDeEIsd0JBQXdCLEdBQ3pCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxTQUFTLEVBQUUsRUFHaEIsYUFBYSxFQUNiLGlCQUFpQixFQUNqQixpQkFBaUIsRUFDakIsWUFBWSxFQUNaLGdCQUFnQixHQUNqQixNQUFNLFVBQVUsQ0FBQztBQUNsQixPQUFPLHlCQUF5QixNQUFNLDZCQUE2QixDQUFDO0FBRXBFLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIseUJBQXlCLEVBQ3pCLHlCQUF5QixHQUUxQixNQUFNLFFBQVEsQ0FBQztBQUNoQixPQUFPLEVBVUwsU0FBUyxFQUNULHFCQUFxQixFQUVyQixrQkFBa0IsR0FFbkIsTUFBTSxTQUFTLENBQUM7QUFFakIsTUFBTSxzQkFBc0IsR0FBRyxF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QUksRUFBRSxDQUFDO2FBQ1IsRUFDRCxpQkFBaUIsRUFBRTtnQkFDakIsS0FBSyxFQUFFLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ25FLElBQUksRUFBRSxDQUFDO2FBQ1IsRUFDRCxZQUFZLEVBQUU7Z0JBQ1osS0FBSyxFQUFFLFlBQVksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxLQUFLLEdBQUcsQ0FBQyxDQUFDO2dCQUNwRCxJQUFJLEVBQUUsQ0FBQzthQUNSLElBQ0UsQ0FBQyxhQUFhO1lBQ2YsQ0FBQyxDQUFDO2dCQUNFLGFBQWEsRUFBRTtvQkFDYixLQUFLLEVBQUUsYUFBYSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxDQUFDLENBQUM7b0JBQ3JELElBQUksRUFBRSxDQUFDO2lCQUNSO2FBQ0Y7WUFDSCxDQUFDLENBQUMsU0FBUyxDQUFDLENBQ2Y7S0FDRixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgMjAyMiBGbG93bWFwQmx1ZVxuICogQ29weXJpZ2h0IDIwMTgtMjAyMCBUZXJhbHl0aWNzLCBtb2RpZmllZCBieSBGbG93bWFwQmx1ZVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQge2JvdW5kc30gZnJvbSAnQG1hcGJveC9nZW8tdmlld3BvcnQnO1xuaW1wb3J0IHthc2NlbmRpbmcsIGRlc2NlbmRpbmcsIGV4dGVudCwgbWlufSBmcm9tICdkMy1hcnJheSc7XG5pbXBvcnQge25lc3R9IGZyb20gJ2QzLWNvbGxlY3Rpb24nO1xuaW1wb3J0IHtTY2FsZUxpbmVhciwgc2NhbGVMaW5lYXIsIHNjYWxlU3FydH0gZnJvbSAnZDMtc2NhbGUnO1xuaW1wb3J0IEtEQnVzaCBmcm9tICdrZGJ1c2gnO1xuaW1wb3J0IHtcbiAgY3JlYXRlU2VsZWN0b3IsXG4gIGNyZWF0ZVNlbGVjdG9yQ3JlYXRvcixcbiAgZGVmYXVsdE1lbW9pemUsXG4gIFBhcmFtZXRyaWNTZWxlY3Rvcixcbn0gZnJvbSAncmVzZWxlY3QnO1xuaW1wb3J0IHthbGVhfSBmcm9tICdzZWVkcmFuZG9tJztcbmltcG9ydCB7Y2x1c3RlckxvY2F0aW9uc30gZnJvbSAnLi9jbHVzdGVyL2NsdXN0ZXInO1xuaW1wb3J0IHtcbiAgYnVpbGRJbmRleCxcbiAgQ2x1c3RlckluZGV4LFxuICBmaW5kQXBwcm9wcmlhdGVab29tTGV2ZWwsXG4gIG1ha2VMb2NhdGlvbldlaWdodEdldHRlcixcbn0gZnJvbSAnLi9jbHVzdGVyL0NsdXN0ZXJJbmRleCc7XG5pbXBvcnQgZ2V0Q29sb3JzLCB7XG4gIENvbG9yc1JHQkEsXG4gIERpZmZDb2xvcnNSR0JBLFxuICBnZXRDb2xvcnNSR0JBLFxuICBnZXREaWZmQ29sb3JzUkdCQSxcbiAgZ2V0Rmxvd0NvbG9yU2NhbGUsXG4gIGlzRGlmZkNvbG9ycyxcbiAgaXNEaWZmQ29sb3JzUkdCQSxcbn0gZnJvbSAnLi9jb2xvcnMnO1xuaW1wb3J0IEZsb3dNYXBBZ2dyZWdhdGVBY2Nlc3NvcnMgZnJvbSAnLi9GbG93TWFwQWdncmVnYXRlQWNjZXNzb3JzJztcbmltcG9ydCB7Rmxvd01hcFN0YXRlfSBmcm9tICcuL0Zsb3dNYXBTdGF0ZSc7XG5pbXBvcnQge1xuICBnZXRUaW1lR3JhbnVsYXJpdHlCeUtleSxcbiAgZ2V0VGltZUdyYW51bGFyaXR5QnlPcmRlcixcbiAgZ2V0VGltZUdyYW51bGFyaXR5Rm9yRGF0ZSxcbiAgVGltZUdyYW51bGFyaXR5S2V5LFxufSBmcm9tICcuL3RpbWUnO1xuaW1wb3J0IHtcbiAgQWdncmVnYXRlRmxvdyxcbiAgQ2x1c3RlcixcbiAgQ2x1c3Rlck5vZGUsXG4gIENvdW50QnlUaW1lLFxuICBGbG93QWNjZXNzb3JzLFxuICBGbG93Q2lyY2xlc0xheWVyQXR0cmlidXRlcyxcbiAgRmxvd0xpbmVzTGF5ZXJBdHRyaWJ1dGVzLFxuICBGbG93TWFwRGF0YSxcbiAgRmxvd01hcERhdGFBY2Nlc3NvcnMsXG4gIGlzQ2x1c3RlcixcbiAgaXNMb2NhdGlvbkNsdXN0ZXJOb2RlLFxuICBMYXllcnNEYXRhLFxuICBMb2NhdGlvbkZpbHRlck1vZGUsXG4gIExvY2F0aW9uVG90YWxzLFxufSBmcm9tICcuL3R5cGVzJztcblxuY29uc3QgTUFYX0NMVVNURVJfWk9PTV9MRVZFTCA9IDIwO1xuY29uc3QgTlVNQkVSX09GX0ZMT1dTX1RPX0RJU1BMQVkgPSA1MDAwO1xudHlwZSBLREJ1c2hUcmVlID0gYW55O1xuXG5leHBvcnQgdHlwZSBTZWxlY3RvcjxMLCBGLCBUPiA9IFBhcmFtZXRyaWNTZWxlY3RvcjxcbiAgRmxvd01hcFN0YXRlLFxuICBGbG93TWFwRGF0YTxMLCBGPixcbiAgVFxuPjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmxvd01hcFNlbGVjdG9yczxMLCBGPiB7XG4gIGFjY2Vzc29yczogRmxvd01hcEFnZ3JlZ2F0ZUFjY2Vzc29yczxMLCBGPjtcblxuICBjb25zdHJ1Y3RvcihhY2Nlc3NvcnM6IEZsb3dNYXBEYXRhQWNjZXNzb3JzPEwsIEY+KSB7XG4gICAgdGhpcy5hY2Nlc3NvcnMgPSBuZXcgRmxvd01hcEFnZ3JlZ2F0ZUFjY2Vzc29ycyhhY2Nlc3NvcnMpO1xuICAgIHRoaXMuc2V0QWNjZXNzb3JzKGFjY2Vzc29ycyk7XG4gIH1cblxuICBzZXRBY2Nlc3NvcnMoYWNjZXNzb3JzOiBGbG93TWFwRGF0YUFjY2Vzc29yczxMLCBGPikge1xuICAgIHRoaXMuYWNjZXNzb3JzID0gbmV3IEZsb3dNYXBBZ2dyZWdhdGVBY2Nlc3NvcnMoYWNjZXNzb3JzKTtcbiAgfVxuXG4gIGdldEZldGNoZWRGbG93cyA9IChzdGF0ZTogRmxvd01hcFN0YXRlLCBwcm9wczogRmxvd01hcERhdGE8TCwgRj4pID0+XG4gICAgcHJvcHMuZmxvd3M7XG4gIGdldEZldGNoZWRMb2NhdGlvbnMgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHByb3BzLmxvY2F0aW9ucztcbiAgZ2V0U2VsZWN0ZWRMb2NhdGlvbnMgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLmZpbHRlclN0YXRlLnNlbGVjdGVkTG9jYXRpb25zO1xuICBnZXRMb2NhdGlvbkZpbHRlck1vZGUgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLmZpbHRlclN0YXRlLmxvY2F0aW9uRmlsdGVyTW9kZTtcbiAgZ2V0Q2x1c3RlcmluZ0VuYWJsZWQgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLnNldHRpbmdzU3RhdGUuY2x1c3RlcmluZ0VuYWJsZWQ7XG4gIGdldExvY2F0aW9uVG90YWxzRW5hYmxlZCA9IChzdGF0ZTogRmxvd01hcFN0YXRlLCBwcm9wczogRmxvd01hcERhdGE8TCwgRj4pID0+XG4gICAgc3RhdGUuc2V0dGluZ3NTdGF0ZS5sb2NhdGlvblRvdGFsc0VuYWJsZWQ7XG4gIGdldFpvb20gPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLnZpZXdwb3J0Lnpvb207XG4gIGdldFZpZXdwb3J0ID0gKHN0YXRlOiBGbG93TWFwU3RhdGUsIHByb3BzOiBGbG93TWFwRGF0YTxMLCBGPikgPT5cbiAgICBzdGF0ZS52aWV3cG9ydDtcbiAgZ2V0U2VsZWN0ZWRUaW1lUmFuZ2UgPSAoc3RhdGU6IEZsb3dNYXBTdGF0ZSwgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+KSA9PlxuICAgIHN0YXRlLmZpbHRlclN0YXRlLnNlbGVjdGVkVGltZVJhbmdlO1xuXG4gIGdldENvbG9yU2NoZW1lS2V5OiBTZWxlY3RvcjxMLCBGLCBzdHJpbmcgfCB1bmRlZmluZWQ+ID0gKFxuICAgIHN0YXRlOiBGbG93TWFwU3RhdGUsXG4gICAgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+LFxuICApID0+IHN0YXRlLnNldHRpbmdzU3RhdGUuY29sb3JTY2hlbWU7XG5cbiAgZ2V0RGFya01vZGU6IFNlbGVjdG9yPEwsIEYsIGJvb2xlYW4+ID0gKFxuICAgIHN0YXRlOiBGbG93TWFwU3RhdGUsXG4gICAgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+LFxuICApID0+IHN0YXRlLnNldHRpbmdzU3RhdGUuZGFya01vZGU7XG5cbiAgZ2V0RmFkZUVuYWJsZWQ6IFNlbGVjdG9yPEwsIEYsIGJvb2xlYW4+ID0gKFxuICAgIHN0YXRlOiBGbG93TWFwU3RhdGUsXG4gICAgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+LFxuICApID0+IHN0YXRlLnNldHRpbmdzU3RhdGUuZmFkZUVuYWJsZWQ7XG5cbiAgZ2V0RmFkZU9wYWNpdHlFbmFibGVkOiBTZWxlY3RvcjxMLCBGLCBib29sZWFuPiA9IChcbiAgICBzdGF0ZTogRmxvd01hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93TWFwRGF0YTxMLCBGPixcbiAgKSA9PiBzdGF0ZS5zZXR0aW5nc1N0YXRlLmZhZGVPcGFjaXR5RW5hYmxlZDtcblxuICBnZXRGYWRlQW1vdW50OiBTZWxlY3RvcjxMLCBGLCBudW1iZXI+ID0gKFxuICAgIHN0YXRlOiBGbG93TWFwU3RhdGUsXG4gICAgcHJvcHM6IEZsb3dNYXBEYXRhPEwsIEY+LFxuICApID0+IHN0YXRlLnNldHRpbmdzU3RhdGUuZmFkZUFtb3VudDtcblxuICBnZXRBbmltYXRlOiBTZWxlY3RvcjxMLCBGLCBib29sZWFuPiA9IChcbiAgICBzdGF0ZTogRmxvd01hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93TWFwRGF0YTxMLCBGPixcbiAgKSA9PiBzdGF0ZS5zZXR0aW5nc1N0YXRlLmFuaW1hdGlvbkVuYWJsZWQ7XG5cbiAgZ2V0SW52YWxpZExvY2F0aW9uSWRzOiBTZWxlY3RvcjxMLCBGLCBzdHJpbmdbXSB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldEZldGNoZWRMb2NhdGlvbnMsXG4gICAgKGxvY2F0aW9ucykgPT4ge1xuICAgICAgaWYgKCFsb2NhdGlvbnMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBpbnZhbGlkID0gW107XG4gICAgICBmb3IgKGNvbnN0IGxvY2F0aW9uIG9mIGxvY2F0aW9ucykge1xuICAgICAgICBjb25zdCBpZCA9IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQobG9jYXRpb24pO1xuICAgICAgICBjb25zdCBbbG9uLCBsYXRdID0gdGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25DZW50cm9pZChsb2NhdGlvbikgfHwgW1xuICAgICAgICAgIE5hTixcbiAgICAgICAgICBOYU4sXG4gICAgICAgIF07XG4gICAgICAgIGlmICghKC05MCA8PSBsYXQgJiYgbGF0IDw9IDkwKSB8fCAhKC0xODAgPD0gbG9uICYmIGxvbiA8PSAxODApKSB7XG4gICAgICAgICAgaW52YWxpZC5wdXNoKGlkKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGludmFsaWQubGVuZ3RoID4gMCA/IGludmFsaWQgOiB1bmRlZmluZWQ7XG4gICAgfSxcbiAgKTtcblxuICBnZXRMb2NhdGlvbnM6IFNlbGVjdG9yPEwsIEYsIExbXSB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldEZldGNoZWRMb2NhdGlvbnMsXG4gICAgdGhpcy5nZXRJbnZhbGlkTG9jYXRpb25JZHMsXG4gICAgKGxvY2F0aW9ucywgaW52YWxpZElkcykgPT4ge1xuICAgICAgaWYgKCFsb2NhdGlvbnMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBpZiAoIWludmFsaWRJZHMgfHwgaW52YWxpZElkcy5sZW5ndGggPT09IDApIHJldHVybiBsb2NhdGlvbnM7XG4gICAgICBjb25zdCBpbnZhbGlkID0gbmV3IFNldChpbnZhbGlkSWRzKTtcbiAgICAgIHJldHVybiBsb2NhdGlvbnMuZmlsdGVyKFxuICAgICAgICAobG9jYXRpb246IEwpID0+ICFpbnZhbGlkLmhhcyh0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGxvY2F0aW9uKSksXG4gICAgICApO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0TG9jYXRpb25JZHM6IFNlbGVjdG9yPEwsIEYsIFNldDxzdHJpbmc+IHwgdW5kZWZpbmVkPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25zLFxuICAgIChsb2NhdGlvbnMpID0+XG4gICAgICBsb2NhdGlvbnNcbiAgICAgICAgPyBuZXcgU2V0KGxvY2F0aW9ucy5tYXAodGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25JZCkpXG4gICAgICAgIDogdW5kZWZpbmVkLFxuICApO1xuXG4gIGdldFNlbGVjdGVkTG9jYXRpb25zU2V0OiBTZWxlY3RvcjxMLCBGLCBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnMsIChpZHMpID0+XG4gICAgICBpZHMgJiYgaWRzLmxlbmd0aCA+IDAgPyBuZXcgU2V0KGlkcykgOiB1bmRlZmluZWQsXG4gICAgKTtcblxuICBnZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zOiBTZWxlY3RvcjxMLCBGLCBGW10gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3Rvcih0aGlzLmdldEZldGNoZWRGbG93cywgdGhpcy5nZXRMb2NhdGlvbklkcywgKGZsb3dzLCBpZHMpID0+IHtcbiAgICAgIGlmICghaWRzIHx8ICFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBmbG93c1xuICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgIChmbG93OiBGKSA9PlxuICAgICAgICAgICAgaWRzLmhhcyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93T3JpZ2luSWQoZmxvdykpICYmXG4gICAgICAgICAgICBpZHMuaGFzKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoZmxvdykpLFxuICAgICAgICApXG4gICAgICAgIC5zb3J0KChhOiBGLCBiOiBGKSA9PlxuICAgICAgICAgIGRlc2NlbmRpbmcoXG4gICAgICAgICAgICBNYXRoLmFicyh0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGEpKSxcbiAgICAgICAgICAgIE1hdGguYWJzKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoYikpLFxuICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgfSk7XG5cbiAgZ2V0QWN0dWFsVGltZUV4dGVudDogU2VsZWN0b3I8TCwgRiwgW0RhdGUsIERhdGVdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IodGhpcy5nZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zLCAoZmxvd3MpID0+IHtcbiAgICAgIGlmICghZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBsZXQgc3RhcnQgPSBudWxsO1xuICAgICAgbGV0IGVuZCA9IG51bGw7XG4gICAgICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MpIHtcbiAgICAgICAgY29uc3QgdGltZSA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dUaW1lKGZsb3cpO1xuICAgICAgICBpZiAodGltZSkge1xuICAgICAgICAgIGlmIChzdGFydCA9PSBudWxsIHx8IHN0YXJ0ID4gdGltZSkgc3RhcnQgPSB0aW1lO1xuICAgICAgICAgIGlmIChlbmQgPT0gbnVsbCB8fCBlbmQgPCB0aW1lKSBlbmQgPSB0aW1lO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIXN0YXJ0IHx8ICFlbmQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gW3N0YXJ0LCBlbmRdO1xuICAgIH0pO1xuXG4gIGdldFRpbWVHcmFudWxhcml0eUtleTogU2VsZWN0b3I8TCwgRiwgVGltZUdyYW51bGFyaXR5S2V5IHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnMsXG4gICAgICB0aGlzLmdldEFjdHVhbFRpbWVFeHRlbnQsXG4gICAgICAoZmxvd3MsIHRpbWVFeHRlbnQpID0+IHtcbiAgICAgICAgaWYgKCFmbG93cyB8fCAhdGltZUV4dGVudCkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgICBjb25zdCBtaW5PcmRlciA9IG1pbihmbG93cywgKGQpID0+IHtcbiAgICAgICAgICBjb25zdCB0ID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd1RpbWUoZCk7XG4gICAgICAgICAgcmV0dXJuIHQgPyBnZXRUaW1lR3JhbnVsYXJpdHlGb3JEYXRlKHQpLm9yZGVyIDogbnVsbDtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChtaW5PcmRlciA9PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCB0aW1lR3JhbnVsYXJpdHkgPSBnZXRUaW1lR3JhbnVsYXJpdHlCeU9yZGVyKG1pbk9yZGVyKTtcbiAgICAgICAgcmV0dXJuIHRpbWVHcmFudWxhcml0eSA/IHRpbWVHcmFudWxhcml0eS5rZXkgOiB1bmRlZmluZWQ7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0VGltZUV4dGVudDogU2VsZWN0b3I8TCwgRiwgW0RhdGUsIERhdGVdIHwgdW5kZWZpbmVkPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0QWN0dWFsVGltZUV4dGVudCxcbiAgICB0aGlzLmdldFRpbWVHcmFudWxhcml0eUtleSxcbiAgICAodGltZUV4dGVudCwgdGltZUdyYW51bGFyaXR5S2V5KSA9PiB7XG4gICAgICBjb25zdCB0aW1lR3JhbnVsYXJpdHkgPSB0aW1lR3JhbnVsYXJpdHlLZXlcbiAgICAgICAgPyBnZXRUaW1lR3JhbnVsYXJpdHlCeUtleSh0aW1lR3JhbnVsYXJpdHlLZXkpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgaWYgKCF0aW1lRXh0ZW50IHx8ICF0aW1lR3JhbnVsYXJpdHk/LmludGVydmFsKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgY29uc3Qge2ludGVydmFsfSA9IHRpbWVHcmFudWxhcml0eTtcbiAgICAgIHJldHVybiBbdGltZUV4dGVudFswXSwgaW50ZXJ2YWwub2Zmc2V0KGludGVydmFsLmZsb29yKHRpbWVFeHRlbnRbMV0pLCAxKV07XG4gICAgfSxcbiAgKTtcblxuICBnZXRTb3J0ZWRGbG93c0Zvcktub3duTG9jYXRpb25zRmlsdGVyZWRCeVRpbWU6IFNlbGVjdG9yPFxuICAgIEwsXG4gICAgRixcbiAgICBGW10gfCB1bmRlZmluZWRcbiAgPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0U29ydGVkRmxvd3NGb3JLbm93bkxvY2F0aW9ucyxcbiAgICB0aGlzLmdldFRpbWVFeHRlbnQsXG4gICAgdGhpcy5nZXRTZWxlY3RlZFRpbWVSYW5nZSxcbiAgICAoZmxvd3MsIHRpbWVFeHRlbnQsIHRpbWVSYW5nZSkgPT4ge1xuICAgICAgaWYgKCFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIGlmIChcbiAgICAgICAgIXRpbWVFeHRlbnQgfHxcbiAgICAgICAgIXRpbWVSYW5nZSB8fFxuICAgICAgICAodGltZUV4dGVudFswXSA9PT0gdGltZVJhbmdlWzBdICYmIHRpbWVFeHRlbnRbMV0gPT09IHRpbWVSYW5nZVsxXSlcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gZmxvd3M7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmxvd3MuZmlsdGVyKChmbG93KSA9PiB7XG4gICAgICAgIGNvbnN0IHRpbWUgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93VGltZShmbG93KTtcbiAgICAgICAgcmV0dXJuIHRpbWUgJiYgdGltZVJhbmdlWzBdIDw9IHRpbWUgJiYgdGltZSA8IHRpbWVSYW5nZVsxXTtcbiAgICAgIH0pO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0TG9jYXRpb25zSGF2aW5nRmxvd3M6IFNlbGVjdG9yPEwsIEYsIExbXSB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnMsXG4gICAgdGhpcy5nZXRMb2NhdGlvbnMsXG4gICAgKGZsb3dzLCBsb2NhdGlvbnMpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25zIHx8ICFmbG93cykgcmV0dXJuIGxvY2F0aW9ucztcbiAgICAgIGNvbnN0IHdpdGhGbG93cyA9IG5ldyBTZXQoKTtcbiAgICAgIGZvciAoY29uc3QgZmxvdyBvZiBmbG93cykge1xuICAgICAgICB3aXRoRmxvd3MuYWRkKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmbG93KSk7XG4gICAgICAgIHdpdGhGbG93cy5hZGQodGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd0Rlc3RJZChmbG93KSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbG9jYXRpb25zLmZpbHRlcigobG9jYXRpb246IEwpID0+XG4gICAgICAgIHdpdGhGbG93cy5oYXModGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25JZChsb2NhdGlvbikpLFxuICAgICAgKTtcbiAgICB9LFxuICApO1xuXG4gIGdldExvY2F0aW9uc0J5SWQ6IFNlbGVjdG9yPEwsIEYsIE1hcDxzdHJpbmcsIEw+IHwgdW5kZWZpbmVkPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25zSGF2aW5nRmxvd3MsXG4gICAgKGxvY2F0aW9ucykgPT4ge1xuICAgICAgaWYgKCFsb2NhdGlvbnMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gbmVzdDxMLCBMPigpXG4gICAgICAgIC5rZXkoKGQ6IEwpID0+IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQoZCkpXG4gICAgICAgIC5yb2xsdXAoKFtkXSkgPT4gZClcbiAgICAgICAgLm1hcChsb2NhdGlvbnMpIGFzIGFueSBhcyBNYXA8c3RyaW5nLCBMPjtcbiAgICB9LFxuICApO1xuXG4gIGdldENsdXN0ZXJJbmRleDogU2VsZWN0b3I8TCwgRiwgQ2x1c3RlckluZGV4PEY+IHwgdW5kZWZpbmVkPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25zSGF2aW5nRmxvd3MsXG4gICAgdGhpcy5nZXRMb2NhdGlvbnNCeUlkLFxuICAgIHRoaXMuZ2V0U29ydGVkRmxvd3NGb3JLbm93bkxvY2F0aW9ucyxcbiAgICAobG9jYXRpb25zLCBsb2NhdGlvbnNCeUlkLCBmbG93cykgPT4ge1xuICAgICAgaWYgKCFsb2NhdGlvbnMgfHwgIWxvY2F0aW9uc0J5SWQgfHwgIWZsb3dzKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgICBjb25zdCBnZXRMb2NhdGlvbldlaWdodCA9IG1ha2VMb2NhdGlvbldlaWdodEdldHRlcihcbiAgICAgICAgZmxvd3MsXG4gICAgICAgIHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYXBEYXRhQWNjZXNzb3JzKCksXG4gICAgICApO1xuICAgICAgY29uc3QgY2x1c3RlckxldmVscyA9IGNsdXN0ZXJMb2NhdGlvbnMoXG4gICAgICAgIGxvY2F0aW9ucyxcbiAgICAgICAgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hcERhdGFBY2Nlc3NvcnMoKSxcbiAgICAgICAgZ2V0TG9jYXRpb25XZWlnaHQsXG4gICAgICAgIHtcbiAgICAgICAgICBtYXhab29tOiBNQVhfQ0xVU1RFUl9aT09NX0xFVkVMLFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGNsdXN0ZXJJbmRleCA9IGJ1aWxkSW5kZXg8Rj4oY2x1c3RlckxldmVscyk7XG4gICAgICBjb25zdCB7Z2V0TG9jYXRpb25OYW1lLCBnZXRMb2NhdGlvbkNsdXN0ZXJOYW1lfSA9XG4gICAgICAgIHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYXBEYXRhQWNjZXNzb3JzKCk7XG5cbiAgICAgIC8vIEFkZGluZyBtZWFuaW5nZnVsIG5hbWVzXG4gICAgICBjb25zdCBnZXROYW1lID0gKGlkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgbG9jID0gbG9jYXRpb25zQnlJZC5nZXQoaWQpO1xuICAgICAgICBpZiAobG9jKSB7XG4gICAgICAgICAgcmV0dXJuIGdldExvY2F0aW9uTmFtZVxuICAgICAgICAgICAgPyBnZXRMb2NhdGlvbk5hbWUobG9jKVxuICAgICAgICAgICAgOiB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGxvYykgfHwgaWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGBcIiR7aWR9XCJgO1xuICAgICAgfTtcbiAgICAgIGZvciAoY29uc3QgbGV2ZWwgb2YgY2x1c3RlckxldmVscykge1xuICAgICAgICBmb3IgKGNvbnN0IG5vZGUgb2YgbGV2ZWwubm9kZXMpIHtcbiAgICAgICAgICAvLyBIZXJlIG11dGF0aW5nIHRoZSBub2RlcyAoYWRkaW5nIG5hbWVzKVxuICAgICAgICAgIGlmIChpc0NsdXN0ZXIobm9kZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGxlYXZlcyA9IGNsdXN0ZXJJbmRleC5leHBhbmRDbHVzdGVyKG5vZGUpO1xuXG4gICAgICAgICAgICBsZWF2ZXMuc29ydCgoYSwgYikgPT5cbiAgICAgICAgICAgICAgZGVzY2VuZGluZyhnZXRMb2NhdGlvbldlaWdodChhKSwgZ2V0TG9jYXRpb25XZWlnaHQoYikpLFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgaWYgKGdldExvY2F0aW9uQ2x1c3Rlck5hbWUpIHtcbiAgICAgICAgICAgICAgbm9kZS5uYW1lID0gZ2V0TG9jYXRpb25DbHVzdGVyTmFtZShsZWF2ZXMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY29uc3QgdG9wSWQgPSBsZWF2ZXNbMF07XG4gICAgICAgICAgICAgIGNvbnN0IG90aGVySWQgPSBsZWF2ZXMubGVuZ3RoID09PSAyID8gbGVhdmVzWzFdIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICBub2RlLm5hbWUgPSBgXCIke2dldE5hbWUodG9wSWQpfVwiIGFuZCAke1xuICAgICAgICAgICAgICAgIG90aGVySWRcbiAgICAgICAgICAgICAgICAgID8gYFwiJHtnZXROYW1lKG90aGVySWQpfVwiYFxuICAgICAgICAgICAgICAgICAgOiBgJHtsZWF2ZXMubGVuZ3RoIC0gMX0gb3RoZXJzYFxuICAgICAgICAgICAgICB9YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgKG5vZGUgYXMgYW55KS5uYW1lID0gZ2V0TmFtZShub2RlLmlkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNsdXN0ZXJJbmRleDtcbiAgICB9LFxuICApO1xuXG4gIGdldEF2YWlsYWJsZUNsdXN0ZXJab29tTGV2ZWxzID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRDbHVzdGVySW5kZXgsXG4gICAgdGhpcy5nZXRTZWxlY3RlZExvY2F0aW9ucyxcbiAgICAoY2x1c3RlckluZGV4LCBzZWxlY3RlZExvY2F0aW9ucyk6IG51bWJlcltdIHwgdW5kZWZpbmVkID0+IHtcbiAgICAgIGlmICghY2x1c3RlckluZGV4KSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGxldCBtYXhab29tID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuICAgICAgbGV0IG1pblpvb20gPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XG5cbiAgICAgIGNvbnN0IGFkanVzdCA9ICh6b25lSWQ6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBjbHVzdGVyID0gY2x1c3RlckluZGV4LmdldENsdXN0ZXJCeUlkKHpvbmVJZCk7XG4gICAgICAgIGlmIChjbHVzdGVyKSB7XG4gICAgICAgICAgbWluWm9vbSA9IE1hdGgubWF4KG1pblpvb20sIGNsdXN0ZXIuem9vbSk7XG4gICAgICAgICAgbWF4Wm9vbSA9IE1hdGgubWluKG1heFpvb20sIGNsdXN0ZXIuem9vbSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3Qgem9vbSA9IGNsdXN0ZXJJbmRleC5nZXRNaW5ab29tRm9yTG9jYXRpb24oem9uZUlkKTtcbiAgICAgICAgICBtaW5ab29tID0gTWF0aC5tYXgobWluWm9vbSwgem9vbSk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmIChzZWxlY3RlZExvY2F0aW9ucykge1xuICAgICAgICBmb3IgKGNvbnN0IGlkIG9mIHNlbGVjdGVkTG9jYXRpb25zKSB7XG4gICAgICAgICAgYWRqdXN0KGlkKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gY2x1c3RlckluZGV4LmF2YWlsYWJsZVpvb21MZXZlbHMuZmlsdGVyKFxuICAgICAgICAobGV2ZWwpID0+IG1pblpvb20gPD0gbGV2ZWwgJiYgbGV2ZWwgPD0gbWF4Wm9vbSxcbiAgICAgICk7XG4gICAgfSxcbiAgKTtcblxuICBfZ2V0Q2x1c3Rlclpvb206IFNlbGVjdG9yPEwsIEYsIG51bWJlciB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldENsdXN0ZXJJbmRleCxcbiAgICB0aGlzLmdldFpvb20sXG4gICAgdGhpcy5nZXRBdmFpbGFibGVDbHVzdGVyWm9vbUxldmVscyxcbiAgICAoY2x1c3RlckluZGV4LCBtYXBab29tLCBhdmFpbGFibGVDbHVzdGVyWm9vbUxldmVscykgPT4ge1xuICAgICAgaWYgKCFjbHVzdGVySW5kZXgpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBpZiAoIWF2YWlsYWJsZUNsdXN0ZXJab29tTGV2ZWxzKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNsdXN0ZXJab29tID0gZmluZEFwcHJvcHJpYXRlWm9vbUxldmVsKFxuICAgICAgICBhdmFpbGFibGVDbHVzdGVyWm9vbUxldmVscyxcbiAgICAgICAgbWFwWm9vbSxcbiAgICAgICk7XG4gICAgICByZXR1cm4gY2x1c3Rlclpvb207XG4gICAgfSxcbiAgKTtcblxuICBnZXRDbHVzdGVyWm9vbSA9IChzdGF0ZTogRmxvd01hcFN0YXRlLCBwcm9wczogRmxvd01hcERhdGE8TCwgRj4pID0+IHtcbiAgICBjb25zdCB7c2V0dGluZ3NTdGF0ZX0gPSBzdGF0ZTtcbiAgICBpZiAoIXNldHRpbmdzU3RhdGUuY2x1c3RlcmluZ0VuYWJsZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgaWYgKHNldHRpbmdzU3RhdGUuY2x1c3RlcmluZ0F1dG8gfHwgc2V0dGluZ3NTdGF0ZS5jbHVzdGVyaW5nTGV2ZWwgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldENsdXN0ZXJab29tKHN0YXRlLCBwcm9wcyk7XG4gICAgfVxuICAgIHJldHVybiBzZXR0aW5nc1N0YXRlLmNsdXN0ZXJpbmdMZXZlbDtcbiAgfTtcblxuICBnZXRMb2NhdGlvbnNGb3JTZWFyY2hCb3g6IFNlbGVjdG9yPEwsIEYsIChMIHwgQ2x1c3RlcilbXSB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRDbHVzdGVyaW5nRW5hYmxlZCxcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25zSGF2aW5nRmxvd3MsXG4gICAgICB0aGlzLmdldFNlbGVjdGVkTG9jYXRpb25zLFxuICAgICAgdGhpcy5nZXRDbHVzdGVyWm9vbSxcbiAgICAgIHRoaXMuZ2V0Q2x1c3RlckluZGV4LFxuICAgICAgKFxuICAgICAgICBjbHVzdGVyaW5nRW5hYmxlZCxcbiAgICAgICAgbG9jYXRpb25zLFxuICAgICAgICBzZWxlY3RlZExvY2F0aW9ucyxcbiAgICAgICAgY2x1c3Rlclpvb20sXG4gICAgICAgIGNsdXN0ZXJJbmRleCxcbiAgICAgICkgPT4ge1xuICAgICAgICBpZiAoIWxvY2F0aW9ucykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHJlc3VsdDogKEwgfCBDbHVzdGVyKVtdID0gbG9jYXRpb25zO1xuICAgICAgICAvLyBpZiAoY2x1c3RlcmluZ0VuYWJsZWQpIHtcbiAgICAgICAgLy8gICBpZiAoY2x1c3RlckluZGV4KSB7XG4gICAgICAgIC8vICAgICBjb25zdCB6b29tSXRlbXMgPSBjbHVzdGVySW5kZXguZ2V0Q2x1c3Rlck5vZGVzRm9yKGNsdXN0ZXJab29tKTtcbiAgICAgICAgLy8gICAgIGlmICh6b29tSXRlbXMpIHtcbiAgICAgICAgLy8gICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdCh6b29tSXRlbXMuZmlsdGVyKGlzQ2x1c3RlcikpO1xuICAgICAgICAvLyAgICAgfVxuICAgICAgICAvLyAgIH1cbiAgICAgICAgLy8gfVxuXG4gICAgICAgIGlmIChyZXN1bHQgJiYgY2x1c3RlckluZGV4ICYmIHNlbGVjdGVkTG9jYXRpb25zKSB7XG4gICAgICAgICAgY29uc3QgdG9BcHBlbmQgPSBbXTtcbiAgICAgICAgICBmb3IgKGNvbnN0IGlkIG9mIHNlbGVjdGVkTG9jYXRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCBjbHVzdGVyID0gY2x1c3RlckluZGV4LmdldENsdXN0ZXJCeUlkKGlkKTtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgY2x1c3RlciAmJlxuICAgICAgICAgICAgICAhcmVzdWx0LmZpbmQoXG4gICAgICAgICAgICAgICAgKGQpID0+XG4gICAgICAgICAgICAgICAgICAoaXNMb2NhdGlvbkNsdXN0ZXJOb2RlKGQpXG4gICAgICAgICAgICAgICAgICAgID8gZC5pZFxuICAgICAgICAgICAgICAgICAgICA6IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQoZCkpID09PSBpZCxcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIHRvQXBwZW5kLnB1c2goY2x1c3Rlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0b0FwcGVuZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KHRvQXBwZW5kKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0sXG4gICAgKTtcblxuICBnZXREaWZmTW9kZTogU2VsZWN0b3I8TCwgRiwgYm9vbGVhbj4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldEZldGNoZWRGbG93cyxcbiAgICAoZmxvd3MpID0+IHtcbiAgICAgIGlmIChcbiAgICAgICAgZmxvd3MgJiZcbiAgICAgICAgZmxvd3MuZmluZCgoZjogRikgPT4gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmKSA8IDApXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgKTtcblxuICBfZ2V0Rmxvd01hcENvbG9ycyA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0RGlmZk1vZGUsXG4gICAgdGhpcy5nZXRDb2xvclNjaGVtZUtleSxcbiAgICB0aGlzLmdldERhcmtNb2RlLFxuICAgIHRoaXMuZ2V0RmFkZUVuYWJsZWQsXG4gICAgdGhpcy5nZXRGYWRlT3BhY2l0eUVuYWJsZWQsXG4gICAgdGhpcy5nZXRGYWRlQW1vdW50LFxuICAgIHRoaXMuZ2V0QW5pbWF0ZSxcbiAgICBnZXRDb2xvcnMsXG4gICk7XG5cbiAgZ2V0Rmxvd01hcENvbG9yc1JHQkEgPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLl9nZXRGbG93TWFwQ29sb3JzLFxuICAgIChmbG93TWFwQ29sb3JzKSA9PiB7XG4gICAgICByZXR1cm4gaXNEaWZmQ29sb3JzKGZsb3dNYXBDb2xvcnMpXG4gICAgICAgID8gZ2V0RGlmZkNvbG9yc1JHQkEoZmxvd01hcENvbG9ycylcbiAgICAgICAgOiBnZXRDb2xvcnNSR0JBKGZsb3dNYXBDb2xvcnMpO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0VW5rbm93bkxvY2F0aW9uczogU2VsZWN0b3I8TCwgRiwgU2V0PHN0cmluZz4gfCB1bmRlZmluZWQ+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRMb2NhdGlvbklkcyxcbiAgICB0aGlzLmdldEZldGNoZWRGbG93cyxcbiAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnMsXG4gICAgKGlkcywgZmxvd3MsIGZsb3dzRm9yS25vd25Mb2NhdGlvbnMpID0+IHtcbiAgICAgIGlmICghaWRzIHx8ICFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIGlmIChcbiAgICAgICAgZmxvd3NGb3JLbm93bkxvY2F0aW9ucyAmJlxuICAgICAgICBmbG93cy5sZW5ndGggPT09IGZsb3dzRm9yS25vd25Mb2NhdGlvbnMubGVuZ3RoXG4gICAgICApXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBtaXNzaW5nID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MpIHtcbiAgICAgICAgaWYgKCFpZHMuaGFzKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmbG93KSkpXG4gICAgICAgICAgbWlzc2luZy5hZGQodGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGZsb3cpKTtcbiAgICAgICAgaWYgKCFpZHMuaGFzKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoZmxvdykpKVxuICAgICAgICAgIG1pc3NpbmcuYWRkKHRoaXMuYWNjZXNzb3JzLmdldEZsb3dEZXN0SWQoZmxvdykpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG1pc3Npbmc7XG4gICAgfSxcbiAgKTtcblxuICBnZXRTb3J0ZWRBZ2dyZWdhdGVkRmlsdGVyZWRGbG93czogU2VsZWN0b3I8XG4gICAgTCxcbiAgICBGLFxuICAgIChGIHwgQWdncmVnYXRlRmxvdylbXSB8IHVuZGVmaW5lZFxuICA+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRDbHVzdGVySW5kZXgsXG4gICAgdGhpcy5nZXRDbHVzdGVyaW5nRW5hYmxlZCxcbiAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnNGaWx0ZXJlZEJ5VGltZSxcbiAgICB0aGlzLmdldENsdXN0ZXJab29tLFxuICAgIHRoaXMuZ2V0VGltZUV4dGVudCxcbiAgICAoY2x1c3RlclRyZWUsIGlzQ2x1c3RlcmluZ0VuYWJsZWQsIGZsb3dzLCBjbHVzdGVyWm9vbSwgdGltZUV4dGVudCkgPT4ge1xuICAgICAgaWYgKCFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIGxldCBhZ2dyZWdhdGVkOiAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW107XG4gICAgICBpZiAoaXNDbHVzdGVyaW5nRW5hYmxlZCAmJiBjbHVzdGVyVHJlZSAmJiBjbHVzdGVyWm9vbSAhPSBudWxsKSB7XG4gICAgICAgIGFnZ3JlZ2F0ZWQgPSBjbHVzdGVyVHJlZS5hZ2dyZWdhdGVGbG93cyhcbiAgICAgICAgICAvLyBUT0RPOiBhZ2dyZWdhdGUgYWNyb3NzIHRpbWVcbiAgICAgICAgICAvLyB0aW1lRXh0ZW50ICE9IG51bGxcbiAgICAgICAgICAvLyAgID8gYWdncmVnYXRlRmxvd3MoZmxvd3MpIC8vIGNsdXN0ZXJUcmVlLmFnZ3JlZ2F0ZUZsb3dzIHdvbid0IGFnZ3JlZ2F0ZSB1bmNsdXN0ZXJlZCBhY3Jvc3MgdGltZVxuICAgICAgICAgIC8vICAgOiBmbG93cyxcbiAgICAgICAgICBmbG93cyxcbiAgICAgICAgICBjbHVzdGVyWm9vbSxcbiAgICAgICAgICB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFwRGF0YUFjY2Vzc29ycygpLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWdncmVnYXRlZCA9IGFnZ3JlZ2F0ZUZsb3dzKFxuICAgICAgICAgIGZsb3dzLFxuICAgICAgICAgIHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYXBEYXRhQWNjZXNzb3JzKCksXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBhZ2dyZWdhdGVkLnNvcnQoKGEsIGIpID0+XG4gICAgICAgIGRlc2NlbmRpbmcoXG4gICAgICAgICAgTWF0aC5hYnModGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShhKSksXG4gICAgICAgICAgTWF0aC5hYnModGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShiKSksXG4gICAgICAgICksXG4gICAgICApO1xuICAgICAgcmV0dXJuIGFnZ3JlZ2F0ZWQ7XG4gICAgfSxcbiAgKTtcblxuICBnZXRGbG93TWFnbml0dWRlRXh0ZW50OiBTZWxlY3RvcjxMLCBGLCBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldFNvcnRlZEFnZ3JlZ2F0ZWRGaWx0ZXJlZEZsb3dzLFxuICAgICAgdGhpcy5nZXRTZWxlY3RlZExvY2F0aW9uc1NldCxcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25GaWx0ZXJNb2RlLFxuICAgICAgKGZsb3dzLCBzZWxlY3RlZExvY2F0aW9uc1NldCwgbG9jYXRpb25GaWx0ZXJNb2RlKSA9PiB7XG4gICAgICAgIGlmICghZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGxldCBydjogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgZm9yIChjb25zdCBmIG9mIGZsb3dzKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGYpICE9PVxuICAgICAgICAgICAgICB0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGYpICYmXG4gICAgICAgICAgICB0aGlzLmlzRmxvd0luU2VsZWN0aW9uKGYsIHNlbGVjdGVkTG9jYXRpb25zU2V0LCBsb2NhdGlvbkZpbHRlck1vZGUpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBjb3VudCA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dNYWduaXR1ZGUoZik7XG4gICAgICAgICAgICBpZiAocnYgPT0gbnVsbCkge1xuICAgICAgICAgICAgICBydiA9IFtjb3VudCwgY291bnRdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKGNvdW50IDwgcnZbMF0pIHJ2WzBdID0gY291bnQ7XG4gICAgICAgICAgICAgIGlmIChjb3VudCA+IHJ2WzFdKSBydlsxXSA9IGNvdW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcnY7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0RXhwYW5kZWRTZWxlY3RlZExvY2F0aW9uc1NldDogU2VsZWN0b3I8TCwgRiwgU2V0PHN0cmluZz4gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0Q2x1c3RlcmluZ0VuYWJsZWQsXG4gICAgICB0aGlzLmdldFNlbGVjdGVkTG9jYXRpb25zU2V0LFxuICAgICAgdGhpcy5nZXRDbHVzdGVySW5kZXgsXG4gICAgICAoY2x1c3RlcmluZ0VuYWJsZWQsIHNlbGVjdGVkTG9jYXRpb25zLCBjbHVzdGVySW5kZXgpID0+IHtcbiAgICAgICAgaWYgKCFzZWxlY3RlZExvY2F0aW9ucyB8fCAhY2x1c3RlckluZGV4KSB7XG4gICAgICAgICAgcmV0dXJuIHNlbGVjdGVkTG9jYXRpb25zO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICAgIGZvciAoY29uc3QgbG9jYXRpb25JZCBvZiBzZWxlY3RlZExvY2F0aW9ucykge1xuICAgICAgICAgIGNvbnN0IGNsdXN0ZXIgPSBjbHVzdGVySW5kZXguZ2V0Q2x1c3RlckJ5SWQobG9jYXRpb25JZCk7XG4gICAgICAgICAgaWYgKGNsdXN0ZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGV4cGFuZGVkID0gY2x1c3RlckluZGV4LmV4cGFuZENsdXN0ZXIoY2x1c3Rlcik7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGlkIG9mIGV4cGFuZGVkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdC5hZGQoaWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQuYWRkKGxvY2F0aW9uSWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSxcbiAgICApO1xuXG4gIGdldFRvdGFsQ291bnRzQnlUaW1lOiBTZWxlY3RvcjxMLCBGLCBDb3VudEJ5VGltZVtdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnMsXG4gICAgICB0aGlzLmdldFRpbWVHcmFudWxhcml0eUtleSxcbiAgICAgIHRoaXMuZ2V0VGltZUV4dGVudCxcbiAgICAgIHRoaXMuZ2V0RXhwYW5kZWRTZWxlY3RlZExvY2F0aW9uc1NldCxcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25GaWx0ZXJNb2RlLFxuICAgICAgKFxuICAgICAgICBmbG93cyxcbiAgICAgICAgdGltZUdyYW51bGFyaXR5S2V5LFxuICAgICAgICB0aW1lRXh0ZW50LFxuICAgICAgICBzZWxlY3RlZExvY2F0aW9uU2V0LFxuICAgICAgICBsb2NhdGlvbkZpbHRlck1vZGUsXG4gICAgICApID0+IHtcbiAgICAgICAgY29uc3QgdGltZUdyYW51bGFyaXR5ID0gdGltZUdyYW51bGFyaXR5S2V5XG4gICAgICAgICAgPyBnZXRUaW1lR3JhbnVsYXJpdHlCeUtleSh0aW1lR3JhbnVsYXJpdHlLZXkpXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIGlmICghZmxvd3MgfHwgIXRpbWVHcmFudWxhcml0eSB8fCAhdGltZUV4dGVudCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgYnlUaW1lID0gZmxvd3MucmVkdWNlKChtLCBmbG93KSA9PiB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5pc0Zsb3dJblNlbGVjdGlvbihcbiAgICAgICAgICAgICAgZmxvdyxcbiAgICAgICAgICAgICAgc2VsZWN0ZWRMb2NhdGlvblNldCxcbiAgICAgICAgICAgICAgbG9jYXRpb25GaWx0ZXJNb2RlLFxuICAgICAgICAgICAgKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29uc3Qga2V5ID0gdGltZUdyYW51bGFyaXR5XG4gICAgICAgICAgICAgIC5pbnRlcnZhbCh0aGlzLmFjY2Vzc29ycy5nZXRGbG93VGltZShmbG93KSlcbiAgICAgICAgICAgICAgLmdldFRpbWUoKTtcbiAgICAgICAgICAgIG0uc2V0KFxuICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgIChtLmdldChrZXkpID8/IDApICsgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmbG93KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBtO1xuICAgICAgICB9LCBuZXcgTWFwPG51bWJlciwgbnVtYmVyPigpKTtcblxuICAgICAgICByZXR1cm4gQXJyYXkuZnJvbShieVRpbWUuZW50cmllcygpKS5tYXAoKFttaWxsaXMsIGNvdW50XSkgPT4gKHtcbiAgICAgICAgICB0aW1lOiBuZXcgRGF0ZShtaWxsaXMpLFxuICAgICAgICAgIGNvdW50LFxuICAgICAgICB9KSk7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0TWF4TG9jYXRpb25DaXJjbGVTaXplOiBTZWxlY3RvcjxMLCBGLCBudW1iZXI+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRMb2NhdGlvblRvdGFsc0VuYWJsZWQsXG4gICAgKGxvY2F0aW9uVG90YWxzRW5hYmxlZCkgPT4gKGxvY2F0aW9uVG90YWxzRW5hYmxlZCA/IDE3IDogMSksXG4gICk7XG5cbiAgZ2V0Vmlld3BvcnRCb3VuZGluZ0JveDogU2VsZWN0b3I8TCwgRiwgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0Vmlld3BvcnQsXG4gICAgICB0aGlzLmdldE1heExvY2F0aW9uQ2lyY2xlU2l6ZSxcbiAgICAgICh2aWV3cG9ydCwgbWF4TG9jYXRpb25DaXJjbGVTaXplKSA9PiB7XG4gICAgICAgIGNvbnN0IHBhZCA9IG1heExvY2F0aW9uQ2lyY2xlU2l6ZTtcbiAgICAgICAgcmV0dXJuIGJvdW5kcyhcbiAgICAgICAgICBbdmlld3BvcnQubG9uZ2l0dWRlLCB2aWV3cG9ydC5sYXRpdHVkZV0sXG4gICAgICAgICAgdmlld3BvcnQuem9vbSxcbiAgICAgICAgICBbdmlld3BvcnQud2lkdGggKyBwYWQgKiAyLCB2aWV3cG9ydC5oZWlnaHQgKyBwYWQgKiAyXSxcbiAgICAgICAgICA1MTIsXG4gICAgICAgICk7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0TG9jYXRpb25zRm9yWm9vbTogU2VsZWN0b3I8TCwgRiwgTFtdIHwgQ2x1c3Rlck5vZGVbXSB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRDbHVzdGVyaW5nRW5hYmxlZCxcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25zSGF2aW5nRmxvd3MsXG4gICAgICB0aGlzLmdldENsdXN0ZXJJbmRleCxcbiAgICAgIHRoaXMuZ2V0Q2x1c3Rlclpvb20sXG4gICAgICAoY2x1c3RlcmluZ0VuYWJsZWQsIGxvY2F0aW9uc0hhdmluZ0Zsb3dzLCBjbHVzdGVySW5kZXgsIGNsdXN0ZXJab29tKSA9PiB7XG4gICAgICAgIGlmIChjbHVzdGVyaW5nRW5hYmxlZCAmJiBjbHVzdGVySW5kZXgpIHtcbiAgICAgICAgICByZXR1cm4gY2x1c3RlckluZGV4LmdldENsdXN0ZXJOb2Rlc0ZvcihjbHVzdGVyWm9vbSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGxvY2F0aW9uc0hhdmluZ0Zsb3dzO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0TG9jYXRpb25Ub3RhbHM6IFNlbGVjdG9yPEwsIEYsIE1hcDxzdHJpbmcsIExvY2F0aW9uVG90YWxzPiB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRMb2NhdGlvbnNGb3Jab29tLFxuICAgICAgdGhpcy5nZXRTb3J0ZWRBZ2dyZWdhdGVkRmlsdGVyZWRGbG93cyxcbiAgICAgIHRoaXMuZ2V0U2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgICB0aGlzLmdldExvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAgIChsb2NhdGlvbnMsIGZsb3dzLCBzZWxlY3RlZExvY2F0aW9uc1NldCwgbG9jYXRpb25GaWx0ZXJNb2RlKSA9PiB7XG4gICAgICAgIGlmICghZmxvd3MpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHRvdGFscyA9IG5ldyBNYXA8c3RyaW5nLCBMb2NhdGlvblRvdGFscz4oKTtcbiAgICAgICAgY29uc3QgYWRkID0gKFxuICAgICAgICAgIGlkOiBzdHJpbmcsXG4gICAgICAgICAgZDogUGFydGlhbDxMb2NhdGlvblRvdGFscz4sXG4gICAgICAgICk6IExvY2F0aW9uVG90YWxzID0+IHtcbiAgICAgICAgICBjb25zdCBydiA9IHRvdGFscy5nZXQoaWQpID8/IHtcbiAgICAgICAgICAgIGluY29taW5nQ291bnQ6IDAsXG4gICAgICAgICAgICBvdXRnb2luZ0NvdW50OiAwLFxuICAgICAgICAgICAgaW50ZXJuYWxDb3VudDogMCxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmIChkLmluY29taW5nQ291bnQgIT0gbnVsbCkgcnYuaW5jb21pbmdDb3VudCArPSBkLmluY29taW5nQ291bnQ7XG4gICAgICAgICAgaWYgKGQub3V0Z29pbmdDb3VudCAhPSBudWxsKSBydi5vdXRnb2luZ0NvdW50ICs9IGQub3V0Z29pbmdDb3VudDtcbiAgICAgICAgICBpZiAoZC5pbnRlcm5hbENvdW50ICE9IG51bGwpIHJ2LmludGVybmFsQ291bnQgKz0gZC5pbnRlcm5hbENvdW50O1xuICAgICAgICAgIHJldHVybiBydjtcbiAgICAgICAgfTtcbiAgICAgICAgZm9yIChjb25zdCBmIG9mIGZsb3dzKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5pc0Zsb3dJblNlbGVjdGlvbihmLCBzZWxlY3RlZExvY2F0aW9uc1NldCwgbG9jYXRpb25GaWx0ZXJNb2RlKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgY29uc3Qgb3JpZ2luSWQgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93T3JpZ2luSWQoZik7XG4gICAgICAgICAgICBjb25zdCBkZXN0SWQgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGYpO1xuICAgICAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGYpO1xuICAgICAgICAgICAgaWYgKG9yaWdpbklkID09PSBkZXN0SWQpIHtcbiAgICAgICAgICAgICAgdG90YWxzLnNldChvcmlnaW5JZCwgYWRkKG9yaWdpbklkLCB7aW50ZXJuYWxDb3VudDogY291bnR9KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0b3RhbHMuc2V0KG9yaWdpbklkLCBhZGQob3JpZ2luSWQsIHtvdXRnb2luZ0NvdW50OiBjb3VudH0pKTtcbiAgICAgICAgICAgICAgdG90YWxzLnNldChkZXN0SWQsIGFkZChkZXN0SWQsIHtpbmNvbWluZ0NvdW50OiBjb3VudH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRvdGFscztcbiAgICAgIH0sXG4gICAgKTtcblxuICBnZXRMb2NhdGlvbnNUcmVlOiBTZWxlY3RvcjxMLCBGLCBLREJ1c2hUcmVlPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25zRm9yWm9vbSxcbiAgICAobG9jYXRpb25zKSA9PiB7XG4gICAgICBpZiAoIWxvY2F0aW9ucykge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBLREJ1c2goXG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgbG9jYXRpb25zLFxuICAgICAgICAobG9jYXRpb246IEwgfCBDbHVzdGVyTm9kZSkgPT5cbiAgICAgICAgICBsbmdYKFxuICAgICAgICAgICAgaXNMb2NhdGlvbkNsdXN0ZXJOb2RlKGxvY2F0aW9uKVxuICAgICAgICAgICAgICA/IGxvY2F0aW9uLmNlbnRyb2lkWzBdXG4gICAgICAgICAgICAgIDogdGhpcy5hY2Nlc3NvcnMuZ2V0TG9jYXRpb25DZW50cm9pZChsb2NhdGlvbilbMF0sXG4gICAgICAgICAgKSxcbiAgICAgICAgKGxvY2F0aW9uOiBMIHwgQ2x1c3Rlck5vZGUpID0+XG4gICAgICAgICAgbGF0WShcbiAgICAgICAgICAgIGlzTG9jYXRpb25DbHVzdGVyTm9kZShsb2NhdGlvbilcbiAgICAgICAgICAgICAgPyBsb2NhdGlvbi5jZW50cm9pZFsxXVxuICAgICAgICAgICAgICA6IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uQ2VudHJvaWQobG9jYXRpb24pWzFdLFxuICAgICAgICAgICksXG4gICAgICApO1xuICAgIH0sXG4gICk7XG5cbiAgX2dldExvY2F0aW9uSWRzSW5WaWV3cG9ydDogU2VsZWN0b3I8TCwgRiwgU2V0PHN0cmluZz4gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3RvcihcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25zVHJlZSxcbiAgICAgIHRoaXMuZ2V0Vmlld3BvcnRCb3VuZGluZ0JveCxcbiAgICAgICh0cmVlOiBLREJ1c2hUcmVlLCBiYm94OiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSkgPT4ge1xuICAgICAgICBjb25zdCBpZHMgPSB0aGlzLl9nZXRMb2NhdGlvbnNJbkJib3hJbmRpY2VzKHRyZWUsIGJib3gpO1xuICAgICAgICBpZiAoaWRzKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBTZXQoXG4gICAgICAgICAgICBpZHMubWFwKChpZHg6IG51bWJlcikgPT4gdHJlZS5wb2ludHNbaWR4XS5pZCkgYXMgQXJyYXk8c3RyaW5nPixcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0OiBTZWxlY3RvcjxMLCBGLCBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yQ3JlYXRvcihcbiAgICAgIGRlZmF1bHRNZW1vaXplLFxuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgKFxuICAgICAgICBzMTogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQsXG4gICAgICAgIHMyOiBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZCxcbiAgICAgICAgaW5kZXg6IG51bWJlcixcbiAgICAgICkgPT4ge1xuICAgICAgICBpZiAoczEgPT09IHMyKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgaWYgKHMxID09IG51bGwgfHwgczIgPT0gbnVsbCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAoczEuc2l6ZSAhPT0gczIuc2l6ZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgczEpIGlmICghczIuaGFzKGl0ZW0pKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICApKFxuICAgICAgdGhpcy5fZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgICAgKGxvY2F0aW9uSWRzOiBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZCkgPT4ge1xuICAgICAgICBpZiAoIWxvY2F0aW9uSWRzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4gbG9jYXRpb25JZHM7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0VG90YWxVbmZpbHRlcmVkQ291bnQ6IFNlbGVjdG9yPEwsIEYsIG51bWJlciB8IHVuZGVmaW5lZD4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldFNvcnRlZEZsb3dzRm9yS25vd25Mb2NhdGlvbnMsXG4gICAgKGZsb3dzKSA9PiB7XG4gICAgICBpZiAoIWZsb3dzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIGZsb3dzLnJlZHVjZShcbiAgICAgICAgKG0sIGZsb3cpID0+IG0gKyB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGZsb3cpLFxuICAgICAgICAwLFxuICAgICAgKTtcbiAgICB9LFxuICApO1xuXG4gIGdldFRvdGFsRmlsdGVyZWRDb3VudDogU2VsZWN0b3I8TCwgRiwgbnVtYmVyIHwgdW5kZWZpbmVkPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0U29ydGVkQWdncmVnYXRlZEZpbHRlcmVkRmxvd3MsXG4gICAgdGhpcy5nZXRTZWxlY3RlZExvY2F0aW9uc1NldCxcbiAgICB0aGlzLmdldExvY2F0aW9uRmlsdGVyTW9kZSxcbiAgICAoZmxvd3MsIHNlbGVjdGVkTG9jYXRpb25TZXQsIGxvY2F0aW9uRmlsdGVyTW9kZSkgPT4ge1xuICAgICAgaWYgKCFmbG93cykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IGNvdW50ID0gZmxvd3MucmVkdWNlKChtLCBmbG93KSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICB0aGlzLmlzRmxvd0luU2VsZWN0aW9uKGZsb3csIHNlbGVjdGVkTG9jYXRpb25TZXQsIGxvY2F0aW9uRmlsdGVyTW9kZSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgcmV0dXJuIG0gKyB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGZsb3cpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtO1xuICAgICAgfSwgMCk7XG4gICAgICByZXR1cm4gY291bnQ7XG4gICAgfSxcbiAgKTtcblxuICBfZ2V0TG9jYXRpb25Ub3RhbHNFeHRlbnQ6IFNlbGVjdG9yPEwsIEYsIFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQ+ID1cbiAgICBjcmVhdGVTZWxlY3Rvcih0aGlzLmdldExvY2F0aW9uVG90YWxzLCAobG9jYXRpb25Ub3RhbHMpID0+XG4gICAgICBjYWxjTG9jYXRpb25Ub3RhbHNFeHRlbnQobG9jYXRpb25Ub3RhbHMsIHVuZGVmaW5lZCksXG4gICAgKTtcblxuICBfZ2V0TG9jYXRpb25Ub3RhbHNGb3JWaWV3cG9ydEV4dGVudDogU2VsZWN0b3I8XG4gICAgTCxcbiAgICBGLFxuICAgIFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWRcbiAgPiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25Ub3RhbHMsXG4gICAgdGhpcy5nZXRMb2NhdGlvbklkc0luVmlld3BvcnQsXG4gICAgKGxvY2F0aW9uVG90YWxzLCBsb2NhdGlvbnNJblZpZXdwb3J0KSA9PlxuICAgICAgY2FsY0xvY2F0aW9uVG90YWxzRXh0ZW50KGxvY2F0aW9uVG90YWxzLCBsb2NhdGlvbnNJblZpZXdwb3J0KSxcbiAgKTtcblxuICBnZXRMb2NhdGlvblRvdGFsc0V4dGVudCA9IChcbiAgICBzdGF0ZTogRmxvd01hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93TWFwRGF0YTxMLCBGPixcbiAgKTogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZCA9PiB7XG4gICAgaWYgKHN0YXRlLnNldHRpbmdzU3RhdGUuYWRhcHRpdmVTY2FsZXNFbmFibGVkKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0TG9jYXRpb25Ub3RhbHNGb3JWaWV3cG9ydEV4dGVudChzdGF0ZSwgcHJvcHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0TG9jYXRpb25Ub3RhbHNFeHRlbnQoc3RhdGUsIHByb3BzKTtcbiAgICB9XG4gIH07XG5cbiAgZ2V0Rmxvd3NGb3JGbG93TWFwTGF5ZXI6IFNlbGVjdG9yPEwsIEYsIChGIHwgQWdncmVnYXRlRmxvdylbXSB8IHVuZGVmaW5lZD4gPVxuICAgIGNyZWF0ZVNlbGVjdG9yKFxuICAgICAgdGhpcy5nZXRTb3J0ZWRBZ2dyZWdhdGVkRmlsdGVyZWRGbG93cyxcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgICAgdGhpcy5nZXRTZWxlY3RlZExvY2F0aW9uc1NldCxcbiAgICAgIHRoaXMuZ2V0TG9jYXRpb25GaWx0ZXJNb2RlLFxuICAgICAgKFxuICAgICAgICBmbG93cyxcbiAgICAgICAgbG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgICAgICBzZWxlY3RlZExvY2F0aW9uc1NldCxcbiAgICAgICAgbG9jYXRpb25GaWx0ZXJNb2RlLFxuICAgICAgKSA9PiB7XG4gICAgICAgIGlmICghZmxvd3MgfHwgIWxvY2F0aW9uSWRzSW5WaWV3cG9ydCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgcGlja2VkOiAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW10gPSBbXTtcbiAgICAgICAgbGV0IHBpY2tlZENvdW50ID0gMDtcbiAgICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgICAgY29uc3Qgb3JpZ2luID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGZsb3cpO1xuICAgICAgICAgIGNvbnN0IGRlc3QgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZsb3cpO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGxvY2F0aW9uSWRzSW5WaWV3cG9ydC5oYXMob3JpZ2luKSB8fFxuICAgICAgICAgICAgbG9jYXRpb25JZHNJblZpZXdwb3J0LmhhcyhkZXN0KVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICB0aGlzLmlzRmxvd0luU2VsZWN0aW9uKFxuICAgICAgICAgICAgICAgIGZsb3csXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRMb2NhdGlvbnNTZXQsXG4gICAgICAgICAgICAgICAgbG9jYXRpb25GaWx0ZXJNb2RlLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgaWYgKG9yaWdpbiAhPT0gZGVzdCkge1xuICAgICAgICAgICAgICAgIC8vIGV4Y2x1ZGUgc2VsZi1sb29wc1xuICAgICAgICAgICAgICAgIHBpY2tlZC5wdXNoKGZsb3cpO1xuICAgICAgICAgICAgICAgIHBpY2tlZENvdW50Kys7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gT25seSBrZWVwIHRvcFxuICAgICAgICAgIGlmIChwaWNrZWRDb3VudCA+IE5VTUJFUl9PRl9GTE9XU19UT19ESVNQTEFZKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLyBhc3N1bWluZyB0aGV5IGFyZSBzb3J0ZWQgaW4gZGVzY2VuZGluZyBvcmRlcixcbiAgICAgICAgLy8gd2UgbmVlZCBhc2NlbmRpbmcgZm9yIHJlbmRlcmluZ1xuICAgICAgICByZXR1cm4gcGlja2VkLnJldmVyc2UoKTtcbiAgICAgIH0sXG4gICAgKTtcblxuICBfZ2V0Rmxvd01hZ25pdHVkZUV4dGVudCA9IChcbiAgICBzdGF0ZTogRmxvd01hcFN0YXRlLFxuICAgIHByb3BzOiBGbG93TWFwRGF0YTxMLCBGPixcbiAgKTogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZCA9PiB7XG4gICAgaWYgKHN0YXRlLnNldHRpbmdzU3RhdGUuYWRhcHRpdmVTY2FsZXNFbmFibGVkKSB7XG4gICAgICBjb25zdCBmbG93cyA9IHRoaXMuZ2V0Rmxvd3NGb3JGbG93TWFwTGF5ZXIoc3RhdGUsIHByb3BzKTtcbiAgICAgIGlmIChmbG93cykge1xuICAgICAgICBjb25zdCBydiA9IGV4dGVudChmbG93cywgdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZSk7XG4gICAgICAgIHJldHVybiBydlswXSAhPT0gdW5kZWZpbmVkICYmIHJ2WzFdICE9PSB1bmRlZmluZWQgPyBydiA6IHVuZGVmaW5lZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEZsb3dNYWduaXR1ZGVFeHRlbnQoc3RhdGUsIHByb3BzKTtcbiAgICB9XG4gIH07XG5cbiAgZ2V0TG9jYXRpb25NYXhBYnNUb3RhbEdldHRlciA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0TG9jYXRpb25Ub3RhbHMsXG4gICAgKGxvY2F0aW9uVG90YWxzKSA9PiB7XG4gICAgICByZXR1cm4gKGxvY2F0aW9uSWQ6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCB0b3RhbCA9IGxvY2F0aW9uVG90YWxzPy5nZXQobG9jYXRpb25JZCk7XG4gICAgICAgIGlmICghdG90YWwpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChcbiAgICAgICAgICBNYXRoLmFicyh0b3RhbC5pbmNvbWluZ0NvdW50ICsgdG90YWwuaW50ZXJuYWxDb3VudCksXG4gICAgICAgICAgTWF0aC5hYnModG90YWwub3V0Z29pbmdDb3VudCArIHRvdGFsLmludGVybmFsQ291bnQpLFxuICAgICAgICApO1xuICAgICAgfTtcbiAgICB9LFxuICApO1xuXG4gIGdldEZsb3dUaGlja25lc3NTY2FsZSA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuZ2V0Rmxvd01hZ25pdHVkZUV4dGVudCxcbiAgICAobWFnbml0dWRlRXh0ZW50KSA9PiB7XG4gICAgICBpZiAoIW1hZ25pdHVkZUV4dGVudCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBzY2FsZUxpbmVhcigpXG4gICAgICAgIC5yYW5nZShbMC4wMjUsIDAuNV0pXG4gICAgICAgIC5kb21haW4oW1xuICAgICAgICAgIDAsXG4gICAgICAgICAgLy8gc2hvdWxkIHN1cHBvcnQgZGlmZiBtb2RlIHRvb1xuICAgICAgICAgIE1hdGgubWF4LmFwcGx5KFxuICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgIG1hZ25pdHVkZUV4dGVudC5tYXAoKHg6IG51bWJlciB8IHVuZGVmaW5lZCkgPT4gTWF0aC5hYnMoeCB8fCAwKSksXG4gICAgICAgICAgKSxcbiAgICAgICAgXSk7XG4gICAgfSxcbiAgKTtcblxuICBnZXRDaXJjbGVTaXplU2NhbGUgPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldE1heExvY2F0aW9uQ2lyY2xlU2l6ZSxcbiAgICB0aGlzLmdldExvY2F0aW9uVG90YWxzRW5hYmxlZCxcbiAgICB0aGlzLmdldExvY2F0aW9uVG90YWxzRXh0ZW50LFxuICAgIChtYXhMb2NhdGlvbkNpcmNsZVNpemUsIGxvY2F0aW9uVG90YWxzRW5hYmxlZCwgbG9jYXRpb25Ub3RhbHNFeHRlbnQpID0+IHtcbiAgICAgIGlmICghbG9jYXRpb25Ub3RhbHNFbmFibGVkKSB7XG4gICAgICAgIHJldHVybiAoKSA9PiBtYXhMb2NhdGlvbkNpcmNsZVNpemU7XG4gICAgICB9XG4gICAgICBpZiAoIWxvY2F0aW9uVG90YWxzRXh0ZW50KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIHNjYWxlU3FydCgpXG4gICAgICAgIC5yYW5nZShbMCwgbWF4TG9jYXRpb25DaXJjbGVTaXplXSlcbiAgICAgICAgLmRvbWFpbihbXG4gICAgICAgICAgMCxcbiAgICAgICAgICAvLyBzaG91bGQgc3VwcG9ydCBkaWZmIG1vZGUgdG9vXG4gICAgICAgICAgTWF0aC5tYXguYXBwbHkoXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgbG9jYXRpb25Ub3RhbHNFeHRlbnQubWFwKCh4OiBudW1iZXIgfCB1bmRlZmluZWQpID0+XG4gICAgICAgICAgICAgIE1hdGguYWJzKHggfHwgMCksXG4gICAgICAgICAgICApLFxuICAgICAgICAgICksXG4gICAgICAgIF0pO1xuICAgIH0sXG4gICk7XG5cbiAgZ2V0SW5DaXJjbGVTaXplR2V0dGVyID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRDaXJjbGVTaXplU2NhbGUsXG4gICAgdGhpcy5nZXRMb2NhdGlvblRvdGFscyxcbiAgICAoY2lyY2xlU2l6ZVNjYWxlLCBsb2NhdGlvblRvdGFscykgPT4ge1xuICAgICAgcmV0dXJuIChsb2NhdGlvbklkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgdG90YWwgPSBsb2NhdGlvblRvdGFscz8uZ2V0KGxvY2F0aW9uSWQpO1xuICAgICAgICBpZiAodG90YWwgJiYgY2lyY2xlU2l6ZVNjYWxlKSB7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGNpcmNsZVNpemVTY2FsZShcbiAgICAgICAgICAgICAgTWF0aC5hYnModG90YWwuaW5jb21pbmdDb3VudCArIHRvdGFsLmludGVybmFsQ291bnQpLFxuICAgICAgICAgICAgKSB8fCAwXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH07XG4gICAgfSxcbiAgKTtcblxuICBnZXRPdXRDaXJjbGVTaXplR2V0dGVyID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRDaXJjbGVTaXplU2NhbGUsXG4gICAgdGhpcy5nZXRMb2NhdGlvblRvdGFscyxcbiAgICAoY2lyY2xlU2l6ZVNjYWxlLCBsb2NhdGlvblRvdGFscykgPT4ge1xuICAgICAgcmV0dXJuIChsb2NhdGlvbklkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgdG90YWwgPSBsb2NhdGlvblRvdGFscz8uZ2V0KGxvY2F0aW9uSWQpO1xuICAgICAgICBpZiAodG90YWwgJiYgY2lyY2xlU2l6ZVNjYWxlKSB7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGNpcmNsZVNpemVTY2FsZShcbiAgICAgICAgICAgICAgTWF0aC5hYnModG90YWwub3V0Z29pbmdDb3VudCArIHRvdGFsLmludGVybmFsQ291bnQpLFxuICAgICAgICAgICAgKSB8fCAwXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH07XG4gICAgfSxcbiAgKTtcblxuICBnZXRTb3J0ZWRMb2NhdGlvbnNGb3Jab29tOiBTZWxlY3RvcjxMLCBGLCBMW10gfCBDbHVzdGVyTm9kZVtdIHwgdW5kZWZpbmVkPiA9XG4gICAgY3JlYXRlU2VsZWN0b3IoXG4gICAgICB0aGlzLmdldExvY2F0aW9uc0Zvclpvb20sXG4gICAgICB0aGlzLmdldEluQ2lyY2xlU2l6ZUdldHRlcixcbiAgICAgIHRoaXMuZ2V0T3V0Q2lyY2xlU2l6ZUdldHRlcixcbiAgICAgIChsb2NhdGlvbnMsIGdldEluQ2lyY2xlU2l6ZSwgZ2V0T3V0Q2lyY2xlU2l6ZSkgPT4ge1xuICAgICAgICBpZiAoIWxvY2F0aW9ucykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgbmV4dExvY2F0aW9ucyA9IFsuLi5sb2NhdGlvbnNdIGFzIExbXSB8IENsdXN0ZXJOb2RlW107XG4gICAgICAgIHJldHVybiBuZXh0TG9jYXRpb25zLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICBjb25zdCBpZEEgPSB0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGEpO1xuICAgICAgICAgIGNvbnN0IGlkQiA9IHRoaXMuYWNjZXNzb3JzLmdldExvY2F0aW9uSWQoYik7XG4gICAgICAgICAgcmV0dXJuIGFzY2VuZGluZyhcbiAgICAgICAgICAgIE1hdGgubWF4KGdldEluQ2lyY2xlU2l6ZShpZEEpLCBnZXRPdXRDaXJjbGVTaXplKGlkQSkpLFxuICAgICAgICAgICAgTWF0aC5tYXgoZ2V0SW5DaXJjbGVTaXplKGlkQiksIGdldE91dENpcmNsZVNpemUoaWRCKSksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICk7XG5cbiAgZ2V0TG9jYXRpb25zRm9yRmxvd01hcExheWVyOiBTZWxlY3RvcjxcbiAgICBMLFxuICAgIEYsXG4gICAgQXJyYXk8TCB8IENsdXN0ZXJOb2RlPiB8IHVuZGVmaW5lZFxuICA+ID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy5nZXRTb3J0ZWRMb2NhdGlvbnNGb3Jab29tLFxuICAgIC8vIHRoaXMuZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgIChcbiAgICAgIGxvY2F0aW9ucyxcbiAgICAgIC8vIGxvY2F0aW9uSWRzSW5WaWV3cG9ydFxuICAgICkgPT4ge1xuICAgICAgLy8gaWYgKCFsb2NhdGlvbnMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAvLyBpZiAoIWxvY2F0aW9uSWRzSW5WaWV3cG9ydCkgcmV0dXJuIGxvY2F0aW9ucztcbiAgICAgIC8vIGlmIChsb2NhdGlvbklkc0luVmlld3BvcnQuc2l6ZSA9PT0gbG9jYXRpb25zLmxlbmd0aCkgcmV0dXJuIGxvY2F0aW9ucztcbiAgICAgIC8vIGNvbnN0IGZpbHRlcmVkID0gW107XG4gICAgICAvLyBmb3IgKGNvbnN0IGxvYyBvZiBsb2NhdGlvbnMpIHtcbiAgICAgIC8vICAgaWYgKGxvY2F0aW9uSWRzSW5WaWV3cG9ydC5oYXMobG9jLmlkKSkge1xuICAgICAgLy8gICAgIGZpbHRlcmVkLnB1c2gobG9jKTtcbiAgICAgIC8vICAgfVxuICAgICAgLy8gfVxuICAgICAgLy8gcmV0dXJuIGZpbHRlcmVkO1xuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgLy8gcmV0dXJuIGxvY2F0aW9ucy5maWx0ZXIoXG4gICAgICAvLyAgIChsb2M6IEwgfCBDbHVzdGVyTm9kZSkgPT4gbG9jYXRpb25JZHNJblZpZXdwb3J0IS5oYXMobG9jLmlkKVxuICAgICAgLy8gKTtcbiAgICAgIC8vIFRPRE86IHJldHVybiBsb2NhdGlvbiBpbiB2aWV3cG9ydCArIFwiY29ubmVjdGVkXCIgb25lc1xuICAgICAgcmV0dXJuIGxvY2F0aW9ucztcbiAgICB9LFxuICApO1xuXG4gIGdldExvY2F0aW9uc0ZvckZsb3dNYXBMYXllckJ5SWQ6IFNlbGVjdG9yPFxuICAgIEwsXG4gICAgRixcbiAgICBNYXA8c3RyaW5nLCBMIHwgQ2x1c3Rlck5vZGU+IHwgdW5kZWZpbmVkXG4gID4gPSBjcmVhdGVTZWxlY3Rvcih0aGlzLmdldExvY2F0aW9uc0ZvckZsb3dNYXBMYXllciwgKGxvY2F0aW9ucykgPT4ge1xuICAgIGlmICghbG9jYXRpb25zKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBsb2NhdGlvbnMucmVkdWNlKFxuICAgICAgKG0sIGQpID0+IChtLnNldCh0aGlzLmFjY2Vzc29ycy5nZXRMb2NhdGlvbklkKGQpLCBkKSwgbSksXG4gICAgICBuZXcgTWFwKCksXG4gICAgKTtcbiAgfSk7XG5cbiAgZ2V0TGF5ZXJzRGF0YTogU2VsZWN0b3I8TCwgRiwgTGF5ZXJzRGF0YT4gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmdldExvY2F0aW9uc0ZvckZsb3dNYXBMYXllcixcbiAgICB0aGlzLmdldEZsb3dzRm9yRmxvd01hcExheWVyLFxuICAgIHRoaXMuZ2V0Rmxvd01hcENvbG9yc1JHQkEsXG4gICAgdGhpcy5nZXRMb2NhdGlvbnNGb3JGbG93TWFwTGF5ZXJCeUlkLFxuICAgIHRoaXMuZ2V0TG9jYXRpb25JZHNJblZpZXdwb3J0LFxuICAgIHRoaXMuZ2V0SW5DaXJjbGVTaXplR2V0dGVyLFxuICAgIHRoaXMuZ2V0T3V0Q2lyY2xlU2l6ZUdldHRlcixcbiAgICB0aGlzLmdldEZsb3dUaGlja25lc3NTY2FsZSxcbiAgICB0aGlzLmdldEFuaW1hdGUsXG4gICAgKFxuICAgICAgbG9jYXRpb25zLFxuICAgICAgZmxvd3MsXG4gICAgICBmbG93TWFwQ29sb3JzLFxuICAgICAgbG9jYXRpb25zQnlJZCxcbiAgICAgIGxvY2F0aW9uSWRzSW5WaWV3cG9ydCxcbiAgICAgIGdldEluQ2lyY2xlU2l6ZSxcbiAgICAgIGdldE91dENpcmNsZVNpemUsXG4gICAgICBmbG93VGhpY2tuZXNzU2NhbGUsXG4gICAgICBhbmltYXRpb25FbmFibGVkLFxuICAgICkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuX3ByZXBhcmVMYXllcnNEYXRhKFxuICAgICAgICBsb2NhdGlvbnMsXG4gICAgICAgIGZsb3dzLFxuICAgICAgICBmbG93TWFwQ29sb3JzLFxuICAgICAgICBsb2NhdGlvbnNCeUlkLFxuICAgICAgICBsb2NhdGlvbklkc0luVmlld3BvcnQsXG4gICAgICAgIGdldEluQ2lyY2xlU2l6ZSxcbiAgICAgICAgZ2V0T3V0Q2lyY2xlU2l6ZSxcbiAgICAgICAgZmxvd1RoaWNrbmVzc1NjYWxlLFxuICAgICAgICBhbmltYXRpb25FbmFibGVkLFxuICAgICAgKTtcbiAgICB9LFxuICApO1xuXG4gIHByZXBhcmVMYXllcnNEYXRhKHN0YXRlOiBGbG93TWFwU3RhdGUsIHByb3BzOiBGbG93TWFwRGF0YTxMLCBGPik6IExheWVyc0RhdGEge1xuICAgIGNvbnN0IGxvY2F0aW9ucyA9IHRoaXMuZ2V0TG9jYXRpb25zRm9yRmxvd01hcExheWVyKHN0YXRlLCBwcm9wcykgfHwgW107XG4gICAgY29uc3QgZmxvd3MgPSB0aGlzLmdldEZsb3dzRm9yRmxvd01hcExheWVyKHN0YXRlLCBwcm9wcykgfHwgW107XG4gICAgY29uc3QgZmxvd01hcENvbG9ycyA9IHRoaXMuZ2V0Rmxvd01hcENvbG9yc1JHQkEoc3RhdGUsIHByb3BzKTtcbiAgICBjb25zdCBsb2NhdGlvbnNCeUlkID0gdGhpcy5nZXRMb2NhdGlvbnNGb3JGbG93TWFwTGF5ZXJCeUlkKHN0YXRlLCBwcm9wcyk7XG4gICAgY29uc3QgbG9jYXRpb25JZHNJblZpZXdwb3J0ID0gdGhpcy5nZXRMb2NhdGlvbklkc0luVmlld3BvcnQoc3RhdGUsIHByb3BzKTtcbiAgICBjb25zdCBnZXRJbkNpcmNsZVNpemUgPSB0aGlzLmdldEluQ2lyY2xlU2l6ZUdldHRlcihzdGF0ZSwgcHJvcHMpO1xuICAgIGNvbnN0IGdldE91dENpcmNsZVNpemUgPSB0aGlzLmdldE91dENpcmNsZVNpemVHZXR0ZXIoc3RhdGUsIHByb3BzKTtcbiAgICBjb25zdCBmbG93VGhpY2tuZXNzU2NhbGUgPSB0aGlzLmdldEZsb3dUaGlja25lc3NTY2FsZShzdGF0ZSwgcHJvcHMpO1xuICAgIHJldHVybiB0aGlzLl9wcmVwYXJlTGF5ZXJzRGF0YShcbiAgICAgIGxvY2F0aW9ucyxcbiAgICAgIGZsb3dzLFxuICAgICAgZmxvd01hcENvbG9ycyxcbiAgICAgIGxvY2F0aW9uc0J5SWQsXG4gICAgICBsb2NhdGlvbklkc0luVmlld3BvcnQsXG4gICAgICBnZXRJbkNpcmNsZVNpemUsXG4gICAgICBnZXRPdXRDaXJjbGVTaXplLFxuICAgICAgZmxvd1RoaWNrbmVzc1NjYWxlLFxuICAgICAgc3RhdGUuc2V0dGluZ3NTdGF0ZS5hbmltYXRpb25FbmFibGVkLFxuICAgICk7XG4gIH1cblxuICBfcHJlcGFyZUxheWVyc0RhdGEoXG4gICAgbG9jYXRpb25zOiAoTCB8IENsdXN0ZXJOb2RlKVtdIHwgdW5kZWZpbmVkLFxuICAgIGZsb3dzOiAoRiB8IEFnZ3JlZ2F0ZUZsb3cpW10gfCB1bmRlZmluZWQsXG4gICAgZmxvd01hcENvbG9yczogRGlmZkNvbG9yc1JHQkEgfCBDb2xvcnNSR0JBLFxuICAgIGxvY2F0aW9uc0J5SWQ6IE1hcDxzdHJpbmcsIEwgfCBDbHVzdGVyTm9kZT4gfCB1bmRlZmluZWQsXG4gICAgbG9jYXRpb25JZHNJblZpZXdwb3J0OiBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZCxcbiAgICBnZXRJbkNpcmNsZVNpemU6IChsb2NhdGlvbklkOiBzdHJpbmcpID0+IG51bWJlcixcbiAgICBnZXRPdXRDaXJjbGVTaXplOiAobG9jYXRpb25JZDogc3RyaW5nKSA9PiBudW1iZXIsXG4gICAgZmxvd1RoaWNrbmVzc1NjYWxlOiBTY2FsZUxpbmVhcjxudW1iZXIsIG51bWJlciwgbmV2ZXI+IHwgdW5kZWZpbmVkLFxuICAgIGFuaW1hdGlvbkVuYWJsZWQ6IGJvb2xlYW4sXG4gICk6IExheWVyc0RhdGEge1xuICAgIGlmICghbG9jYXRpb25zKSBsb2NhdGlvbnMgPSBbXTtcbiAgICBpZiAoIWZsb3dzKSBmbG93cyA9IFtdO1xuICAgIGNvbnN0IHtcbiAgICAgIGdldEZsb3dPcmlnaW5JZCxcbiAgICAgIGdldEZsb3dEZXN0SWQsXG4gICAgICBnZXRGbG93TWFnbml0dWRlLFxuICAgICAgZ2V0TG9jYXRpb25JZCxcbiAgICAgIGdldExvY2F0aW9uQ2VudHJvaWQsXG4gICAgfSA9IHRoaXMuYWNjZXNzb3JzO1xuXG4gICAgY29uc3QgZ2V0Q2VudHJvaWQgPSAoaWQ6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgbG9jID0gbG9jYXRpb25zQnlJZD8uZ2V0KGlkKTtcbiAgICAgIHJldHVybiBsb2MgPyBnZXRMb2NhdGlvbkNlbnRyb2lkKGxvYykgOiBbMCwgMF07XG4gICAgfTtcblxuICAgIGNvbnN0IGZsb3dNYWduaXR1ZGVFeHRlbnQgPSBleHRlbnQoZmxvd3MsIChmKSA9PiBnZXRGbG93TWFnbml0dWRlKGYpKSBhcyBbXG4gICAgICBudW1iZXIsXG4gICAgICBudW1iZXIsXG4gICAgXTtcbiAgICBjb25zdCBmbG93Q29sb3JTY2FsZSA9IGdldEZsb3dDb2xvclNjYWxlKFxuICAgICAgZmxvd01hcENvbG9ycyxcbiAgICAgIGZsb3dNYWduaXR1ZGVFeHRlbnQsXG4gICAgICBmYWxzZSxcbiAgICApO1xuXG4gICAgLy8gVXNpbmcgeWllbGQgaGVyZSBoZWxwcyB0byBhdm9pZCBjcmVhdGluZyBpbnRlcm1lZGlhcnkgYXJyYXlzXG4gICAgY29uc3QgY2lyY2xlUG9zaXRpb25zID0gRmxvYXQzMkFycmF5LmZyb20oXG4gICAgICAoZnVuY3Rpb24qICgpIHtcbiAgICAgICAgZm9yIChjb25zdCBsb2NhdGlvbiBvZiBsb2NhdGlvbnMpIHtcbiAgICAgICAgICAvLyB5aWVsZCogZWZmZWN0aXZlbHkgZG9lcyBzYW1lIGFzIGZsYXRNYXAgaGVyZVxuICAgICAgICAgIHlpZWxkKiBnZXRMb2NhdGlvbkNlbnRyb2lkKGxvY2F0aW9uKTtcbiAgICAgICAgfVxuICAgICAgfSkoKSxcbiAgICApO1xuXG4gICAgLy8gVE9ETzogZGlmZiBtb2RlXG4gICAgY29uc3QgY2lyY2xlQ29sb3IgPSBpc0RpZmZDb2xvcnNSR0JBKGZsb3dNYXBDb2xvcnMpXG4gICAgICA/IGZsb3dNYXBDb2xvcnMucG9zaXRpdmUubG9jYXRpb25DaXJjbGVzLmlubmVyXG4gICAgICA6IGZsb3dNYXBDb2xvcnMubG9jYXRpb25DaXJjbGVzLmlubmVyO1xuXG4gICAgY29uc3QgY2lyY2xlQ29sb3JzID0gVWludDhBcnJheS5mcm9tKFxuICAgICAgKGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgIGZvciAoY29uc3QgbG9jYXRpb24gb2YgbG9jYXRpb25zKSB7XG4gICAgICAgICAgeWllbGQqIGNpcmNsZUNvbG9yO1xuICAgICAgICB9XG4gICAgICB9KSgpLFxuICAgICk7XG5cbiAgICBjb25zdCBpbkNpcmNsZVJhZGlpID0gRmxvYXQzMkFycmF5LmZyb20oXG4gICAgICAoZnVuY3Rpb24qICgpIHtcbiAgICAgICAgZm9yIChjb25zdCBsb2NhdGlvbiBvZiBsb2NhdGlvbnMpIHtcbiAgICAgICAgICBjb25zdCBpZCA9IGdldExvY2F0aW9uSWQobG9jYXRpb24pO1xuICAgICAgICAgIHlpZWxkIGxvY2F0aW9uSWRzSW5WaWV3cG9ydD8uaGFzKGlkKSA/IGdldEluQ2lyY2xlU2l6ZShpZCkgOiAxLjA7XG4gICAgICAgIH1cbiAgICAgIH0pKCksXG4gICAgKTtcbiAgICBjb25zdCBvdXRDaXJjbGVSYWRpaSA9IEZsb2F0MzJBcnJheS5mcm9tKFxuICAgICAgKGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgIGZvciAoY29uc3QgbG9jYXRpb24gb2YgbG9jYXRpb25zKSB7XG4gICAgICAgICAgY29uc3QgaWQgPSBnZXRMb2NhdGlvbklkKGxvY2F0aW9uKTtcbiAgICAgICAgICB5aWVsZCBsb2NhdGlvbklkc0luVmlld3BvcnQ/LmhhcyhpZCkgPyBnZXRPdXRDaXJjbGVTaXplKGlkKSA6IDEuMDtcbiAgICAgICAgfVxuICAgICAgfSkoKSxcbiAgICApO1xuXG4gICAgY29uc3Qgc291cmNlUG9zaXRpb25zID0gRmxvYXQzMkFycmF5LmZyb20oXG4gICAgICAoZnVuY3Rpb24qICgpIHtcbiAgICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgICAgeWllbGQqIGdldENlbnRyb2lkKGdldEZsb3dPcmlnaW5JZChmbG93KSk7XG4gICAgICAgIH1cbiAgICAgIH0pKCksXG4gICAgKTtcbiAgICBjb25zdCB0YXJnZXRQb3NpdGlvbnMgPSBGbG9hdDMyQXJyYXkuZnJvbShcbiAgICAgIChmdW5jdGlvbiogKCkge1xuICAgICAgICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MpIHtcbiAgICAgICAgICB5aWVsZCogZ2V0Q2VudHJvaWQoZ2V0Rmxvd0Rlc3RJZChmbG93KSk7XG4gICAgICAgIH1cbiAgICAgIH0pKCksXG4gICAgKTtcbiAgICBjb25zdCB0aGlja25lc3NlcyA9IEZsb2F0MzJBcnJheS5mcm9tKFxuICAgICAgKGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgIGZvciAoY29uc3QgZmxvdyBvZiBmbG93cykge1xuICAgICAgICAgIHlpZWxkIGZsb3dUaGlja25lc3NTY2FsZVxuICAgICAgICAgICAgPyBmbG93VGhpY2tuZXNzU2NhbGUoZ2V0Rmxvd01hZ25pdHVkZShmbG93KSkgfHwgMFxuICAgICAgICAgICAgOiAwO1xuICAgICAgICB9XG4gICAgICB9KSgpLFxuICAgICk7XG4gICAgY29uc3QgZW5kcG9pbnRPZmZzZXRzID0gRmxvYXQzMkFycmF5LmZyb20oXG4gICAgICAoZnVuY3Rpb24qICgpIHtcbiAgICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgICAgY29uc3Qgb3JpZ2luSWQgPSBnZXRGbG93T3JpZ2luSWQoZmxvdyk7XG4gICAgICAgICAgY29uc3QgZGVzdElkID0gZ2V0Rmxvd0Rlc3RJZChmbG93KTtcbiAgICAgICAgICB5aWVsZCBNYXRoLm1heChnZXRJbkNpcmNsZVNpemUob3JpZ2luSWQpLCBnZXRPdXRDaXJjbGVTaXplKG9yaWdpbklkKSk7XG4gICAgICAgICAgeWllbGQgTWF0aC5tYXgoZ2V0SW5DaXJjbGVTaXplKGRlc3RJZCksIGdldE91dENpcmNsZVNpemUoZGVzdElkKSk7XG4gICAgICAgIH1cbiAgICAgIH0pKCksXG4gICAgKTtcbiAgICBjb25zdCBmbG93TGluZUNvbG9ycyA9IFVpbnQ4QXJyYXkuZnJvbShcbiAgICAgIChmdW5jdGlvbiogKCkge1xuICAgICAgICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MpIHtcbiAgICAgICAgICB5aWVsZCogZmxvd0NvbG9yU2NhbGUoZ2V0Rmxvd01hZ25pdHVkZShmbG93KSk7XG4gICAgICAgIH1cbiAgICAgIH0pKCksXG4gICAgKTtcblxuICAgIGNvbnN0IHN0YWdnZXJpbmdWYWx1ZXMgPSBhbmltYXRpb25FbmFibGVkXG4gICAgICA/IEZsb2F0MzJBcnJheS5mcm9tKFxuICAgICAgICAgIChmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgeWllbGQgbmV3IGFsZWEoYCR7Z2V0Rmxvd09yaWdpbklkKGYpfS0ke2dldEZsb3dEZXN0SWQoZil9YCkoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSgpLFxuICAgICAgICApXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIHJldHVybiB7XG4gICAgICBjaXJjbGVBdHRyaWJ1dGVzOiB7XG4gICAgICAgIGxlbmd0aDogbG9jYXRpb25zLmxlbmd0aCxcbiAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgIGdldFBvc2l0aW9uOiB7dmFsdWU6IGNpcmNsZVBvc2l0aW9ucywgc2l6ZTogMn0sXG4gICAgICAgICAgZ2V0Q29sb3I6IHt2YWx1ZTogY2lyY2xlQ29sb3JzLCBzaXplOiA0fSxcbiAgICAgICAgICBnZXRJblJhZGl1czoge3ZhbHVlOiBpbkNpcmNsZVJhZGlpLCBzaXplOiAxfSxcbiAgICAgICAgICBnZXRPdXRSYWRpdXM6IHt2YWx1ZTogb3V0Q2lyY2xlUmFkaWksIHNpemU6IDF9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGxpbmVBdHRyaWJ1dGVzOiB7XG4gICAgICAgIGxlbmd0aDogZmxvd3MubGVuZ3RoLFxuICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgZ2V0U291cmNlUG9zaXRpb246IHt2YWx1ZTogc291cmNlUG9zaXRpb25zLCBzaXplOiAyfSxcbiAgICAgICAgICBnZXRUYXJnZXRQb3NpdGlvbjoge3ZhbHVlOiB0YXJnZXRQb3NpdGlvbnMsIHNpemU6IDJ9LFxuICAgICAgICAgIGdldFRoaWNrbmVzczoge3ZhbHVlOiB0aGlja25lc3Nlcywgc2l6ZTogMX0sXG4gICAgICAgICAgZ2V0Q29sb3I6IHt2YWx1ZTogZmxvd0xpbmVDb2xvcnMsIHNpemU6IDR9LFxuICAgICAgICAgIGdldEVuZHBvaW50T2Zmc2V0czoge3ZhbHVlOiBlbmRwb2ludE9mZnNldHMsIHNpemU6IDJ9LFxuICAgICAgICAgIC4uLihzdGFnZ2VyaW5nVmFsdWVzXG4gICAgICAgICAgICA/IHtnZXRTdGFnZ2VyaW5nOiB7dmFsdWU6IHN0YWdnZXJpbmdWYWx1ZXMsIHNpemU6IDF9fVxuICAgICAgICAgICAgOiB7fSksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBnZXRMb2NhdGlvbnNJbkJib3goXG4gICAgdHJlZTogS0RCdXNoVHJlZSxcbiAgICBiYm94OiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgKTogQXJyYXk8TD4gfCB1bmRlZmluZWQge1xuICAgIGlmICghdHJlZSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICByZXR1cm4gdGhpcy5fZ2V0TG9jYXRpb25zSW5CYm94SW5kaWNlcyh0cmVlLCBiYm94KS5tYXAoXG4gICAgICAoaWR4OiBudW1iZXIpID0+IHRyZWUucG9pbnRzW2lkeF0sXG4gICAgKSBhcyBBcnJheTxMPjtcbiAgfVxuXG4gIF9nZXRMb2NhdGlvbnNJbkJib3hJbmRpY2VzKFxuICAgIHRyZWU6IEtEQnVzaFRyZWUsXG4gICAgYmJveDogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICkge1xuICAgIGlmICghdHJlZSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjb25zdCBbbG9uMSwgbGF0MSwgbG9uMiwgbGF0Ml0gPSBiYm94O1xuICAgIGNvbnN0IFt4MSwgeTEsIHgyLCB5Ml0gPSBbbG5nWChsb24xKSwgbGF0WShsYXQxKSwgbG5nWChsb24yKSwgbGF0WShsYXQyKV07XG4gICAgcmV0dXJuIHRyZWUucmFuZ2UoXG4gICAgICBNYXRoLm1pbih4MSwgeDIpLFxuICAgICAgTWF0aC5taW4oeTEsIHkyKSxcbiAgICAgIE1hdGgubWF4KHgxLCB4MiksXG4gICAgICBNYXRoLm1heCh5MSwgeTIpLFxuICAgICk7XG4gIH1cblxuICBpc0Zsb3dJblNlbGVjdGlvbihcbiAgICBmbG93OiBGIHwgQWdncmVnYXRlRmxvdyxcbiAgICBzZWxlY3RlZExvY2F0aW9uc1NldDogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQsXG4gICAgbG9jYXRpb25GaWx0ZXJNb2RlOiBMb2NhdGlvbkZpbHRlck1vZGUsXG4gICkge1xuICAgIGNvbnN0IG9yaWdpbiA9IHRoaXMuYWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmbG93KTtcbiAgICBjb25zdCBkZXN0ID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd0Rlc3RJZChmbG93KTtcbiAgICBpZiAoc2VsZWN0ZWRMb2NhdGlvbnNTZXQpIHtcbiAgICAgIHN3aXRjaCAobG9jYXRpb25GaWx0ZXJNb2RlKSB7XG4gICAgICAgIGNhc2UgTG9jYXRpb25GaWx0ZXJNb2RlLkFMTDpcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKG9yaWdpbikgfHwgc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKGRlc3QpXG4gICAgICAgICAgKTtcbiAgICAgICAgY2FzZSBMb2NhdGlvbkZpbHRlck1vZGUuQkVUV0VFTjpcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKG9yaWdpbikgJiYgc2VsZWN0ZWRMb2NhdGlvbnNTZXQuaGFzKGRlc3QpXG4gICAgICAgICAgKTtcbiAgICAgICAgY2FzZSBMb2NhdGlvbkZpbHRlck1vZGUuSU5DT01JTkc6XG4gICAgICAgICAgcmV0dXJuIHNlbGVjdGVkTG9jYXRpb25zU2V0LmhhcyhkZXN0KTtcbiAgICAgICAgY2FzZSBMb2NhdGlvbkZpbHRlck1vZGUuT1VUR09JTkc6XG4gICAgICAgICAgcmV0dXJuIHNlbGVjdGVkTG9jYXRpb25zU2V0LmhhcyhvcmlnaW4pO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIGNhbGNMb2NhdGlvblRvdGFscyhcbiAgLy8gICBsb2NhdGlvbnM6IChMIHwgQ2x1c3Rlck5vZGUpW10sXG4gIC8vICAgZmxvd3M6IEZbXSxcbiAgLy8gKTogTG9jYXRpb25zVG90YWxzIHtcbiAgLy8gICByZXR1cm4gZmxvd3MucmVkdWNlKFxuICAvLyAgICAgKGFjYzogTG9jYXRpb25zVG90YWxzLCBjdXJyKSA9PiB7XG4gIC8vICAgICAgIGNvbnN0IG9yaWdpbklkID0gdGhpcy5hY2Nlc3NvcnMuZ2V0Rmxvd09yaWdpbklkKGN1cnIpO1xuICAvLyAgICAgICBjb25zdCBkZXN0SWQgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93RGVzdElkKGN1cnIpO1xuICAvLyAgICAgICBjb25zdCBtYWduaXR1ZGUgPSB0aGlzLmFjY2Vzc29ycy5nZXRGbG93TWFnbml0dWRlKGN1cnIpO1xuICAvLyAgICAgICBpZiAob3JpZ2luSWQgPT09IGRlc3RJZCkge1xuICAvLyAgICAgICAgIGFjYy5pbnRlcm5hbFtvcmlnaW5JZF0gPSAoYWNjLmludGVybmFsW29yaWdpbklkXSB8fCAwKSArIG1hZ25pdHVkZTtcbiAgLy8gICAgICAgfSBlbHNlIHtcbiAgLy8gICAgICAgICBhY2Mub3V0Z29pbmdbb3JpZ2luSWRdID0gKGFjYy5vdXRnb2luZ1tvcmlnaW5JZF0gfHwgMCkgKyBtYWduaXR1ZGU7XG4gIC8vICAgICAgICAgYWNjLmluY29taW5nW2Rlc3RJZF0gPSAoYWNjLmluY29taW5nW2Rlc3RJZF0gfHwgMCkgKyBtYWduaXR1ZGU7XG4gIC8vICAgICAgIH1cbiAgLy8gICAgICAgcmV0dXJuIGFjYztcbiAgLy8gICAgIH0sXG4gIC8vICAgICB7aW5jb21pbmc6IHt9LCBvdXRnb2luZzoge30sIGludGVybmFsOiB7fX0sXG4gIC8vICAgKTtcbiAgLy8gfVxufVxuXG5mdW5jdGlvbiBjYWxjTG9jYXRpb25Ub3RhbHNFeHRlbnQoXG4gIGxvY2F0aW9uVG90YWxzOiBNYXA8c3RyaW5nLCBMb2NhdGlvblRvdGFscz4gfCB1bmRlZmluZWQsXG4gIGxvY2F0aW9uSWRzSW5WaWV3cG9ydDogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQsXG4pIHtcbiAgaWYgKCFsb2NhdGlvblRvdGFscykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgbGV0IHJ2OiBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICBmb3IgKGNvbnN0IFtcbiAgICBpZCxcbiAgICB7aW5jb21pbmdDb3VudCwgb3V0Z29pbmdDb3VudCwgaW50ZXJuYWxDb3VudH0sXG4gIF0gb2YgbG9jYXRpb25Ub3RhbHMuZW50cmllcygpKSB7XG4gICAgaWYgKGxvY2F0aW9uSWRzSW5WaWV3cG9ydCA9PSBudWxsIHx8IGxvY2F0aW9uSWRzSW5WaWV3cG9ydC5oYXMoaWQpKSB7XG4gICAgICBjb25zdCBsbyA9IE1hdGgubWluKFxuICAgICAgICBpbmNvbWluZ0NvdW50ICsgaW50ZXJuYWxDb3VudCxcbiAgICAgICAgb3V0Z29pbmdDb3VudCArIGludGVybmFsQ291bnQsXG4gICAgICAgIGludGVybmFsQ291bnQsXG4gICAgICApO1xuICAgICAgY29uc3QgaGkgPSBNYXRoLm1heChcbiAgICAgICAgaW5jb21pbmdDb3VudCArIGludGVybmFsQ291bnQsXG4gICAgICAgIG91dGdvaW5nQ291bnQgKyBpbnRlcm5hbENvdW50LFxuICAgICAgICBpbnRlcm5hbENvdW50LFxuICAgICAgKTtcbiAgICAgIGlmICghcnYpIHtcbiAgICAgICAgcnYgPSBbbG8sIGhpXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChsbyA8IHJ2WzBdKSBydlswXSA9IGxvO1xuICAgICAgICBpZiAoaGkgPiBydlsxXSkgcnZbMV0gPSBoaTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJ2O1xufVxuXG4vLyBsb25naXR1ZGUvbGF0aXR1ZGUgdG8gc3BoZXJpY2FsIG1lcmNhdG9yIGluIFswLi4xXSByYW5nZVxuZnVuY3Rpb24gbG5nWChsbmc6IG51bWJlcikge1xuICByZXR1cm4gbG5nIC8gMzYwICsgMC41O1xufVxuXG5mdW5jdGlvbiBsYXRZKGxhdDogbnVtYmVyKSB7XG4gIGNvbnN0IHNpbiA9IE1hdGguc2luKChsYXQgKiBNYXRoLlBJKSAvIDE4MCk7XG4gIGNvbnN0IHkgPSAwLjUgLSAoMC4yNSAqIE1hdGgubG9nKCgxICsgc2luKSAvICgxIC0gc2luKSkpIC8gTWF0aC5QSTtcbiAgcmV0dXJuIHkgPCAwID8gMCA6IHkgPiAxID8gMSA6IHk7XG59XG5cbmZ1bmN0aW9uIGFnZ3JlZ2F0ZUZsb3dzPEY+KFxuICBmbG93czogRltdLFxuICBmbG93QWNjZXNzb3JzOiBGbG93QWNjZXNzb3JzPEY+LFxuKTogQWdncmVnYXRlRmxvd1tdIHtcbiAgLy8gU3VtIHVwIGZsb3dzIHdpdGggc2FtZSBvcmlnaW4sIGRlc3RcbiAgY29uc3QgYnlPcmlnaW5EZXN0ID0gbmVzdDxGLCBBZ2dyZWdhdGVGbG93PigpXG4gICAgLmtleShmbG93QWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZClcbiAgICAua2V5KGZsb3dBY2Nlc3NvcnMuZ2V0Rmxvd0Rlc3RJZClcbiAgICAucm9sbHVwKChmZjogRltdKSA9PiB7XG4gICAgICBjb25zdCBvcmlnaW4gPSBmbG93QWNjZXNzb3JzLmdldEZsb3dPcmlnaW5JZChmZlswXSk7XG4gICAgICBjb25zdCBkZXN0ID0gZmxvd0FjY2Vzc29ycy5nZXRGbG93RGVzdElkKGZmWzBdKTtcbiAgICAgIC8vIGNvbnN0IGNvbG9yID0gZmZbMF0uY29sb3I7XG4gICAgICBjb25zdCBydjogQWdncmVnYXRlRmxvdyA9IHtcbiAgICAgICAgYWdncmVnYXRlOiB0cnVlLFxuICAgICAgICBvcmlnaW4sXG4gICAgICAgIGRlc3QsXG4gICAgICAgIGNvdW50OiBmZi5yZWR1Y2UoKG0sIGYpID0+IHtcbiAgICAgICAgICBjb25zdCBjb3VudCA9IGZsb3dBY2Nlc3NvcnMuZ2V0Rmxvd01hZ25pdHVkZShmKTtcbiAgICAgICAgICBpZiAoY291bnQpIHtcbiAgICAgICAgICAgIGlmICghaXNOYU4oY291bnQpICYmIGlzRmluaXRlKGNvdW50KSkgcmV0dXJuIG0gKyBjb3VudDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG07XG4gICAgICAgIH0sIDApLFxuICAgICAgICAvLyB0aW1lOiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgICAgLy8gaWYgKGNvbG9yKSBydi5jb2xvciA9IGNvbG9yO1xuICAgICAgcmV0dXJuIHJ2O1xuICAgIH0pXG4gICAgLmVudHJpZXMoZmxvd3MpO1xuICBjb25zdCBydjogQWdncmVnYXRlRmxvd1tdID0gW107XG4gIGZvciAoY29uc3Qge3ZhbHVlc30gb2YgYnlPcmlnaW5EZXN0KSB7XG4gICAgZm9yIChjb25zdCB7dmFsdWV9IG9mIHZhbHVlcykge1xuICAgICAgcnYucHVzaCh2YWx1ZSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBydjtcbn1cblxuLyoqXG4gKiBUaGlzIGlzIHVzZWQgdG8gYXVnbWVudCBob3ZlciBwaWNraW5nIGluZm8gc28gdGhhdCB3ZSBjYW4gZGlzcGxhY2UgbG9jYXRpb24gdG9vbHRpcFxuICogQHBhcmFtIGNpcmNsZUF0dHJpYnV0ZXNcbiAqIEBwYXJhbSBpbmRleFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0T3V0ZXJDaXJjbGVSYWRpdXNCeUluZGV4KFxuICBjaXJjbGVBdHRyaWJ1dGVzOiBGbG93Q2lyY2xlc0xheWVyQXR0cmlidXRlcyxcbiAgaW5kZXg6IG51bWJlcixcbik6IG51bWJlciB7XG4gIGNvbnN0IHtnZXRJblJhZGl1cywgZ2V0T3V0UmFkaXVzfSA9IGNpcmNsZUF0dHJpYnV0ZXMuYXR0cmlidXRlcztcbiAgcmV0dXJuIE1hdGgubWF4KGdldEluUmFkaXVzLnZhbHVlW2luZGV4XSwgZ2V0T3V0UmFkaXVzLnZhbHVlW2luZGV4XSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb2NhdGlvbkNlbnRyb2lkQnlJbmRleChcbiAgY2lyY2xlQXR0cmlidXRlczogRmxvd0NpcmNsZXNMYXllckF0dHJpYnV0ZXMsXG4gIGluZGV4OiBudW1iZXIsXG4pOiBbbnVtYmVyLCBudW1iZXJdIHtcbiAgY29uc3Qge2dldFBvc2l0aW9ufSA9IGNpcmNsZUF0dHJpYnV0ZXMuYXR0cmlidXRlcztcbiAgcmV0dXJuIFtnZXRQb3NpdGlvbi52YWx1ZVtpbmRleCAqIDJdLCBnZXRQb3NpdGlvbi52YWx1ZVtpbmRleCAqIDIgKyAxXV07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGbG93TGluZUF0dHJpYnV0ZXNCeUluZGV4KFxuICBsaW5lQXR0cmlidXRlczogRmxvd0xpbmVzTGF5ZXJBdHRyaWJ1dGVzLFxuICBpbmRleDogbnVtYmVyLFxuKTogRmxvd0xpbmVzTGF5ZXJBdHRyaWJ1dGVzIHtcbiAgY29uc3Qge1xuICAgIGdldENvbG9yLFxuICAgIGdldEVuZHBvaW50T2Zmc2V0cyxcbiAgICBnZXRTb3VyY2VQb3NpdGlvbixcbiAgICBnZXRUYXJnZXRQb3NpdGlvbixcbiAgICBnZXRUaGlja25lc3MsXG4gICAgZ2V0U3RhZ2dlcmluZyxcbiAgfSA9IGxpbmVBdHRyaWJ1dGVzLmF0dHJpYnV0ZXM7XG4gIHJldHVybiB7XG4gICAgbGVuZ3RoOiAxLFxuICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgIGdldENvbG9yOiB7XG4gICAgICAgIHZhbHVlOiBnZXRDb2xvci52YWx1ZS5zdWJhcnJheShpbmRleCAqIDQsIChpbmRleCArIDEpICogNCksXG4gICAgICAgIHNpemU6IDQsXG4gICAgICB9LFxuICAgICAgZ2V0RW5kcG9pbnRPZmZzZXRzOiB7XG4gICAgICAgIHZhbHVlOiBnZXRFbmRwb2ludE9mZnNldHMudmFsdWUuc3ViYXJyYXkoaW5kZXggKiAyLCAoaW5kZXggKyAxKSAqIDIpLFxuICAgICAgICBzaXplOiAyLFxuICAgICAgfSxcbiAgICAgIGdldFNvdXJjZVBvc2l0aW9uOiB7XG4gICAgICAgIHZhbHVlOiBnZXRTb3VyY2VQb3NpdGlvbi52YWx1ZS5zdWJhcnJheShpbmRleCAqIDIsIChpbmRleCArIDEpICogMiksXG4gICAgICAgIHNpemU6IDIsXG4gICAgICB9LFxuICAgICAgZ2V0VGFyZ2V0UG9zaXRpb246IHtcbiAgICAgICAgdmFsdWU6IGdldFRhcmdldFBvc2l0aW9uLnZhbHVlLnN1YmFycmF5KGluZGV4ICogMiwgKGluZGV4ICsgMSkgKiAyKSxcbiAgICAgICAgc2l6ZTogMixcbiAgICAgIH0sXG4gICAgICBnZXRUaGlja25lc3M6IHtcbiAgICAgICAgdmFsdWU6IGdldFRoaWNrbmVzcy52YWx1ZS5zdWJhcnJheShpbmRleCwgaW5kZXggKyAxKSxcbiAgICAgICAgc2l6ZTogMSxcbiAgICAgIH0sXG4gICAgICAuLi4oZ2V0U3RhZ2dlcmluZ1xuICAgICAgICA/IHtcbiAgICAgICAgICAgIGdldFN0YWdnZXJpbmc6IHtcbiAgICAgICAgICAgICAgdmFsdWU6IGdldFN0YWdnZXJpbmcudmFsdWUuc3ViYXJyYXkoaW5kZXgsIGluZGV4ICsgMSksXG4gICAgICAgICAgICAgIHNpemU6IDEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH1cbiAgICAgICAgOiB1bmRlZmluZWQpLFxuICAgIH0sXG4gIH07XG59XG4iXX0=
|