@flowmap.gl/data 8.0.0-alpha.3 → 8.0.0-alpha.7

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