@kepler.gl/utils 3.1.0-alpha.1 → 3.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aggregation.d.ts +13 -0
- package/dist/aggregation.js +84 -0
- package/dist/application-config.d.ts +25 -0
- package/dist/application-config.js +52 -0
- package/dist/arrow-data-container.d.ts +62 -0
- package/dist/arrow-data-container.js +331 -0
- package/dist/color-utils.d.ts +108 -0
- package/dist/color-utils.js +443 -0
- package/dist/data-container-interface.d.ts +138 -0
- package/dist/data-container-interface.js +6 -0
- package/dist/data-container-utils.d.ts +30 -0
- package/dist/data-container-utils.js +74 -0
- package/dist/data-row.d.ts +59 -0
- package/dist/data-row.js +110 -0
- package/dist/data-scale-utils.d.ts +119 -0
- package/dist/data-scale-utils.js +340 -0
- package/dist/data-utils.d.ts +98 -0
- package/dist/data-utils.js +436 -0
- package/dist/dataset-utils.d.ts +45 -0
- package/dist/dataset-utils.js +313 -0
- package/dist/dom-to-image.d.ts +73 -0
- package/dist/dom-to-image.js +421 -0
- package/dist/dom-utils.d.ts +23 -0
- package/dist/dom-utils.js +349 -0
- package/dist/effect-utils.d.ts +24 -0
- package/dist/effect-utils.js +166 -0
- package/dist/export-map-html.d.ts +9 -0
- package/dist/export-map-html.js +25 -0
- package/dist/export-utils.d.ts +40 -0
- package/dist/export-utils.js +201 -0
- package/dist/filter-utils.d.ts +331 -0
- package/dist/filter-utils.js +1214 -0
- package/dist/format.d.ts +3 -0
- package/dist/format.js +38 -0
- package/dist/gl-utils.d.ts +1 -0
- package/dist/gl-utils.js +27 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +941 -0
- package/dist/indexed-data-container.d.ts +34 -0
- package/dist/indexed-data-container.js +214 -0
- package/dist/locale-utils.d.ts +2 -0
- package/dist/locale-utils.js +39 -0
- package/dist/map-info-utils.d.ts +1 -0
- package/dist/map-info-utils.js +14 -0
- package/dist/map-style-utils/mapbox-gl-style-editor.d.ts +57 -0
- package/dist/map-style-utils/mapbox-gl-style-editor.js +188 -0
- package/dist/map-style-utils/mapbox-utils.d.ts +14 -0
- package/dist/map-style-utils/mapbox-utils.js +51 -0
- package/dist/map-utils.d.ts +9 -0
- package/dist/map-utils.js +48 -0
- package/dist/mapbox-utils.d.ts +7 -0
- package/dist/mapbox-utils.js +19 -0
- package/dist/noop.d.ts +1 -0
- package/dist/noop.js +13 -0
- package/dist/notifications-utils.d.ts +42 -0
- package/dist/notifications-utils.js +69 -0
- package/dist/observe-dimensions.d.ts +15 -0
- package/dist/observe-dimensions.js +130 -0
- package/dist/plot.d.ts +131 -0
- package/dist/plot.js +615 -0
- package/dist/position-utils.d.ts +6 -0
- package/dist/position-utils.js +26 -0
- package/dist/projection-utils.d.ts +22 -0
- package/dist/projection-utils.js +83 -0
- package/dist/quick-insertion-sort.d.ts +12 -0
- package/dist/quick-insertion-sort.js +132 -0
- package/dist/row-data-container.d.ts +31 -0
- package/dist/row-data-container.js +206 -0
- package/dist/searcher-utils.d.ts +1 -0
- package/dist/searcher-utils.js +25 -0
- package/dist/split-map-utils.d.ts +32 -0
- package/dist/split-map-utils.js +99 -0
- package/dist/strings.d.ts +4 -0
- package/dist/strings.js +16 -0
- package/dist/time.d.ts +54 -0
- package/dist/time.js +325 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.js +6 -0
- package/dist/utils.d.ts +104 -0
- package/dist/utils.js +241 -0
- package/package.json +14 -6
package/dist/plot.js
ADDED
@@ -0,0 +1,615 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
5
|
+
value: true
|
6
|
+
});
|
7
|
+
exports.adjustValueToAnimationWindow = adjustValueToAnimationWindow;
|
8
|
+
exports.binByTime = binByTime;
|
9
|
+
exports.getAggregationOptiosnBasedOnField = void 0;
|
10
|
+
exports.getBinThresholds = getBinThresholds;
|
11
|
+
exports.getChartTitle = getChartTitle;
|
12
|
+
exports.getDefaultPlotType = getDefaultPlotType;
|
13
|
+
exports.getFilterDataFunc = getFilterDataFunc;
|
14
|
+
exports.getLineChart = getLineChart;
|
15
|
+
exports.getPctChange = getPctChange;
|
16
|
+
exports.getRangeFilterBins = getRangeFilterBins;
|
17
|
+
exports.getTimeBins = getTimeBins;
|
18
|
+
exports.getValueAggrFunc = void 0;
|
19
|
+
exports.histogramFromDomain = histogramFromDomain;
|
20
|
+
exports.histogramFromThreshold = histogramFromThreshold;
|
21
|
+
exports.histogramFromValues = histogramFromValues;
|
22
|
+
exports.isPercentField = isPercentField;
|
23
|
+
exports.normalizeValue = normalizeValue;
|
24
|
+
exports.runGpuFilterForPlot = runGpuFilterForPlot;
|
25
|
+
exports.snapToMarks = snapToMarks;
|
26
|
+
exports.splitSeries = splitSeries;
|
27
|
+
exports.updateAggregationByField = updateAggregationByField;
|
28
|
+
exports.updateRangeFilterPlotType = updateRangeFilterPlotType;
|
29
|
+
exports.updateTimeFilterPlotType = updateTimeFilterPlotType;
|
30
|
+
exports.validBin = validBin;
|
31
|
+
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
32
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
33
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
34
|
+
var _d3Array = require("d3-array");
|
35
|
+
var _lodash = _interopRequireDefault(require("lodash.isequal"));
|
36
|
+
var _time = require("./time");
|
37
|
+
var _moment = _interopRequireDefault(require("moment"));
|
38
|
+
var _commonUtils = require("@kepler.gl/common-utils");
|
39
|
+
var _constants = require("@kepler.gl/constants");
|
40
|
+
var _dataUtils = require("./data-utils");
|
41
|
+
var _aggregation = require("./aggregation");
|
42
|
+
var _strings = require("./strings");
|
43
|
+
var _format = require("./format");
|
44
|
+
var _colorUtils = require("./color-utils");
|
45
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
46
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
47
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
48
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
49
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // SPDX-License-Identifier: MIT
|
50
|
+
// Copyright contributors to the kepler.gl project
|
51
|
+
// TODO kepler-table module isn't accessible from utils. Add compatible interface to types
|
52
|
+
|
53
|
+
/**
|
54
|
+
*
|
55
|
+
* @param thresholds
|
56
|
+
* @param values
|
57
|
+
* @param indexes
|
58
|
+
*/
|
59
|
+
function histogramFromThreshold(thresholds, values, valueAccessor) {
|
60
|
+
var filterEmptyBins = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
61
|
+
var getBins = (0, _d3Array.histogram)().domain([thresholds[0], thresholds[thresholds.length - 1]]).thresholds(thresholds);
|
62
|
+
if (valueAccessor) {
|
63
|
+
getBins.value(valueAccessor);
|
64
|
+
}
|
65
|
+
|
66
|
+
// @ts-ignore
|
67
|
+
var bins = getBins(values).map(function (bin) {
|
68
|
+
return {
|
69
|
+
count: bin.length,
|
70
|
+
indexes: bin,
|
71
|
+
x0: bin.x0,
|
72
|
+
x1: bin.x1
|
73
|
+
};
|
74
|
+
});
|
75
|
+
|
76
|
+
// d3-histogram ignores threshold values outside the domain
|
77
|
+
// The first bin.x0 is always equal to the minimum domain value, and the last bin.x1 is always equal to the maximum domain value.
|
78
|
+
|
79
|
+
// bins[0].x0 = thresholds[0];
|
80
|
+
// bins[bins.length - 1].x1 = thresholds[thresholds.length - 1];
|
81
|
+
|
82
|
+
// @ts-ignore
|
83
|
+
return filterEmptyBins ? bins.filter(function (b) {
|
84
|
+
return b.count > 0;
|
85
|
+
}) : bins;
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
*
|
90
|
+
* @param values
|
91
|
+
* @param numBins
|
92
|
+
* @param valueAccessor
|
93
|
+
*/
|
94
|
+
function histogramFromValues(values, numBins, valueAccessor) {
|
95
|
+
var getBins = (0, _d3Array.histogram)().thresholds(numBins);
|
96
|
+
if (valueAccessor) {
|
97
|
+
getBins.value(valueAccessor);
|
98
|
+
}
|
99
|
+
|
100
|
+
// @ts-ignore d3-array types doesn't match
|
101
|
+
return getBins(values).map(function (bin) {
|
102
|
+
return {
|
103
|
+
count: bin.length,
|
104
|
+
indexes: bin,
|
105
|
+
x0: bin.x0,
|
106
|
+
x1: bin.x1
|
107
|
+
};
|
108
|
+
}).filter(function (b) {
|
109
|
+
var x0 = b.x0,
|
110
|
+
x1 = b.x1;
|
111
|
+
return (0, _dataUtils.isNumber)(x0) && (0, _dataUtils.isNumber)(x1);
|
112
|
+
});
|
113
|
+
}
|
114
|
+
|
115
|
+
/**
|
116
|
+
*
|
117
|
+
* @param domain
|
118
|
+
* @param values
|
119
|
+
* @param numBins
|
120
|
+
* @param valueAccessor
|
121
|
+
*/
|
122
|
+
function histogramFromDomain(domain, values, numBins, valueAccessor) {
|
123
|
+
var getBins = (0, _d3Array.histogram)().thresholds((0, _d3Array.ticks)(domain[0], domain[1], numBins)).domain(domain);
|
124
|
+
if (valueAccessor) {
|
125
|
+
getBins.value(valueAccessor);
|
126
|
+
}
|
127
|
+
|
128
|
+
// @ts-ignore d3-array types doesn't match
|
129
|
+
return getBins(values).map(function (bin) {
|
130
|
+
return {
|
131
|
+
count: bin.length,
|
132
|
+
indexes: bin,
|
133
|
+
x0: bin.x0,
|
134
|
+
x1: bin.x1
|
135
|
+
};
|
136
|
+
});
|
137
|
+
}
|
138
|
+
|
139
|
+
/**
|
140
|
+
* @param filter
|
141
|
+
* @param datasets
|
142
|
+
* @param interval
|
143
|
+
*/
|
144
|
+
function getTimeBins(filter, datasets, interval) {
|
145
|
+
var bins = filter.timeBins || {};
|
146
|
+
filter.dataId.forEach(function (dataId, dataIdIdx) {
|
147
|
+
// reuse bins if filterData did not change
|
148
|
+
if (bins[dataId] && bins[dataId][interval]) {
|
149
|
+
return;
|
150
|
+
}
|
151
|
+
var dataset = datasets[dataId];
|
152
|
+
|
153
|
+
// do not apply current filter
|
154
|
+
var indexes = runGpuFilterForPlot(dataset, filter);
|
155
|
+
bins = _objectSpread(_objectSpread({}, bins), {}, (0, _defineProperty2["default"])({}, dataId, _objectSpread(_objectSpread({}, bins[dataId]), {}, (0, _defineProperty2["default"])({}, interval, binByTime(indexes, dataset, interval, filter)))));
|
156
|
+
});
|
157
|
+
return bins;
|
158
|
+
}
|
159
|
+
function binByTime(indexes, dataset, interval, filter) {
|
160
|
+
// gpuFilters need to be apply to filteredIndex
|
161
|
+
var mappedValue = (0, _time.getFilterMappedValue)(dataset, filter);
|
162
|
+
if (!mappedValue) {
|
163
|
+
return null;
|
164
|
+
}
|
165
|
+
var intervalBins = getBinThresholds(interval, filter.domain);
|
166
|
+
var valueAccessor = function valueAccessor(idx) {
|
167
|
+
return mappedValue[idx];
|
168
|
+
};
|
169
|
+
var bins = histogramFromThreshold(intervalBins, indexes, valueAccessor);
|
170
|
+
return bins;
|
171
|
+
}
|
172
|
+
function getBinThresholds(interval, domain) {
|
173
|
+
var timeInterval = (0, _time.intervalToFunction)(interval);
|
174
|
+
var _domain = (0, _slicedToArray2["default"])(domain, 2),
|
175
|
+
t0 = _domain[0],
|
176
|
+
t1 = _domain[1];
|
177
|
+
var floor = timeInterval.floor(t0).getTime();
|
178
|
+
var ceiling = timeInterval.ceil(t1).getTime();
|
179
|
+
if (!timeInterval) {
|
180
|
+
// if time interval is not defined
|
181
|
+
// this should not happen
|
182
|
+
return [t0, t0 + _constants.durationDay];
|
183
|
+
}
|
184
|
+
var binThresholds = timeInterval.range(floor, ceiling + 1).map(function (t) {
|
185
|
+
return _moment["default"].utc(t).valueOf();
|
186
|
+
});
|
187
|
+
var lastStep = binThresholds[binThresholds.length - 1];
|
188
|
+
if (lastStep === t1) {
|
189
|
+
// when last step equal to domain max, add one more step
|
190
|
+
binThresholds.push(_moment["default"].utc(timeInterval.offset(lastStep)).valueOf());
|
191
|
+
}
|
192
|
+
return binThresholds;
|
193
|
+
}
|
194
|
+
|
195
|
+
/**
|
196
|
+
* Run GPU filter on current filter result to generate indexes for ploting chart
|
197
|
+
* Skip ruuning for the same field
|
198
|
+
* @param dataset
|
199
|
+
* @param filter
|
200
|
+
*/
|
201
|
+
function runGpuFilterForPlot(dataset, filter) {
|
202
|
+
var skipIndexes = getSkipIndexes(dataset, filter);
|
203
|
+
var _dataset$gpuFilter = dataset.gpuFilter,
|
204
|
+
filterValueUpdateTriggers = _dataset$gpuFilter.filterValueUpdateTriggers,
|
205
|
+
filterRange = _dataset$gpuFilter.filterRange,
|
206
|
+
filterValueAccessor = _dataset$gpuFilter.filterValueAccessor,
|
207
|
+
filteredIndex = dataset.filteredIndex;
|
208
|
+
var getFilterValue = filterValueAccessor(dataset.dataContainer)();
|
209
|
+
var allChannels = Object.keys(filterValueUpdateTriggers).map(function (_, i) {
|
210
|
+
return i;
|
211
|
+
}).filter(function (i) {
|
212
|
+
return Object.values(filterValueUpdateTriggers)[i];
|
213
|
+
});
|
214
|
+
var skipAll = !allChannels.filter(function (i) {
|
215
|
+
return !skipIndexes.includes(i);
|
216
|
+
}).length;
|
217
|
+
if (skipAll) {
|
218
|
+
return filteredIndex;
|
219
|
+
}
|
220
|
+
var filterData = getFilterDataFunc(filterRange, getFilterValue, dataset.dataContainer, skipIndexes);
|
221
|
+
return filteredIndex.filter(filterData);
|
222
|
+
}
|
223
|
+
function getSkipIndexes(dataset, filter) {
|
224
|
+
// array of gpu filter names
|
225
|
+
if (!filter) {
|
226
|
+
return [];
|
227
|
+
}
|
228
|
+
var gpuFilters = Object.values(dataset.gpuFilter.filterValueUpdateTriggers);
|
229
|
+
var valueIndex = filter.dataId.findIndex(function (id) {
|
230
|
+
return id === dataset.id;
|
231
|
+
});
|
232
|
+
var filterColumn = filter.name[valueIndex];
|
233
|
+
return gpuFilters.reduce(function (accu, item, idx) {
|
234
|
+
if (item && filterColumn === item.name) {
|
235
|
+
accu.push(idx);
|
236
|
+
}
|
237
|
+
return accu;
|
238
|
+
}, []);
|
239
|
+
}
|
240
|
+
function getFilterDataFunc(filterRange, getFilterValue, dataContainer, skips) {
|
241
|
+
return function (index) {
|
242
|
+
return getFilterValue({
|
243
|
+
index: index
|
244
|
+
}).every(function (val, i) {
|
245
|
+
return skips.includes(i) || val >= filterRange[i][0] && val <= filterRange[i][1];
|
246
|
+
});
|
247
|
+
};
|
248
|
+
}
|
249
|
+
function validBin(b) {
|
250
|
+
return b.x0 !== undefined && b.x1 !== undefined;
|
251
|
+
}
|
252
|
+
|
253
|
+
/**
|
254
|
+
* Use in slider, given a number and an array of numbers, return the nears number from the array.
|
255
|
+
* Takes a value, timesteps and return the actual step.
|
256
|
+
* @param value
|
257
|
+
* @param marks
|
258
|
+
*/
|
259
|
+
function snapToMarks(value, marks) {
|
260
|
+
// always use bin x0
|
261
|
+
if (!marks.length) {
|
262
|
+
// @ts-expect-error looking at the usage null return value isn't expected and requires extra handling in a lot of places
|
263
|
+
return null;
|
264
|
+
}
|
265
|
+
var i = (0, _d3Array.bisectLeft)(marks, value);
|
266
|
+
if (i === 0) {
|
267
|
+
return marks[i];
|
268
|
+
} else if (i === marks.length) {
|
269
|
+
return marks[i - 1];
|
270
|
+
}
|
271
|
+
var idx = marks[i] - value < value - marks[i - 1] ? i : i - 1;
|
272
|
+
return marks[idx];
|
273
|
+
}
|
274
|
+
function normalizeValue(val, minValue, step, marks) {
|
275
|
+
if (marks && marks.length) {
|
276
|
+
return snapToMarks(val, marks);
|
277
|
+
}
|
278
|
+
return (0, _dataUtils.roundValToStep)(minValue, step, val);
|
279
|
+
}
|
280
|
+
function isPercentField(field) {
|
281
|
+
return field.metadata && field.metadata.numerator && field.metadata.denominator;
|
282
|
+
}
|
283
|
+
function updateAggregationByField(field, aggregation) {
|
284
|
+
// shouldn't apply sum to percent fiele type
|
285
|
+
// default aggregation is average
|
286
|
+
return field && isPercentField(field) ? _constants.AGGREGATION_TYPES.average : aggregation || _constants.AGGREGATION_TYPES.average;
|
287
|
+
}
|
288
|
+
var getAgregationType = function getAgregationType(field, aggregation) {
|
289
|
+
if (isPercentField(field)) {
|
290
|
+
return 'mean_of_percent';
|
291
|
+
}
|
292
|
+
return aggregation;
|
293
|
+
};
|
294
|
+
var getAggregationAccessor = function getAggregationAccessor(field, dataContainer, fields) {
|
295
|
+
if (isPercentField(field)) {
|
296
|
+
var numeratorIdx = fields.findIndex(function (f) {
|
297
|
+
return f.name === field.metadata.numerator;
|
298
|
+
});
|
299
|
+
var denominatorIdx = fields.findIndex(function (f) {
|
300
|
+
return f.name === field.metadata.denominator;
|
301
|
+
});
|
302
|
+
return {
|
303
|
+
getNumerator: function getNumerator(i) {
|
304
|
+
return dataContainer.valueAt(i, numeratorIdx);
|
305
|
+
},
|
306
|
+
getDenominator: function getDenominator(i) {
|
307
|
+
return dataContainer.valueAt(i, denominatorIdx);
|
308
|
+
}
|
309
|
+
};
|
310
|
+
}
|
311
|
+
return function (i) {
|
312
|
+
return field.valueAccessor({
|
313
|
+
index: i
|
314
|
+
});
|
315
|
+
};
|
316
|
+
};
|
317
|
+
var getValueAggrFunc = exports.getValueAggrFunc = function getValueAggrFunc(field, aggregation, dataset) {
|
318
|
+
var dataContainer = dataset.dataContainer,
|
319
|
+
fields = dataset.fields;
|
320
|
+
|
321
|
+
// The passed-in field might not have all the fields set (e.g. valueAccessor)
|
322
|
+
var datasetField = fields.find(function (f) {
|
323
|
+
return field && (f.name === field || f.name === field.name);
|
324
|
+
});
|
325
|
+
return datasetField && aggregation ? function (bin) {
|
326
|
+
return (0, _aggregation.aggregate)(bin.indexes, getAgregationType(datasetField, aggregation),
|
327
|
+
// @ts-expect-error can return {getNumerator, getDenominator}
|
328
|
+
getAggregationAccessor(datasetField, dataContainer, fields));
|
329
|
+
} : function (bin) {
|
330
|
+
return bin.count;
|
331
|
+
};
|
332
|
+
};
|
333
|
+
var getAggregationOptiosnBasedOnField = exports.getAggregationOptiosnBasedOnField = function getAggregationOptiosnBasedOnField(field) {
|
334
|
+
if (isPercentField(field)) {
|
335
|
+
// don't show sum
|
336
|
+
return _constants.TIME_AGGREGATION.filter(function (_ref) {
|
337
|
+
var id = _ref.id;
|
338
|
+
return id !== _constants.AGGREGATION_TYPES.sum;
|
339
|
+
});
|
340
|
+
}
|
341
|
+
return _constants.TIME_AGGREGATION;
|
342
|
+
};
|
343
|
+
function getDelta(bins, y, interval) {
|
344
|
+
// if (WOW[interval]) return getWow(bins, y, interval);
|
345
|
+
var lastBin = bins[bins.length - 1];
|
346
|
+
return {
|
347
|
+
delta: 'last',
|
348
|
+
pct: lastBin ? getPctChange(y, lastBin.y) : null
|
349
|
+
};
|
350
|
+
}
|
351
|
+
function getPctChange(y, y0) {
|
352
|
+
if (Number.isFinite(y) && Number.isFinite(y0) && y0 !== 0) {
|
353
|
+
return (y - y0) / y0;
|
354
|
+
}
|
355
|
+
return null;
|
356
|
+
}
|
357
|
+
|
358
|
+
/**
|
359
|
+
*
|
360
|
+
* @param datasets
|
361
|
+
* @param filter
|
362
|
+
*/
|
363
|
+
function getLineChart(datasets, filter) {
|
364
|
+
var _timeBins;
|
365
|
+
var dataId = filter.dataId,
|
366
|
+
yAxis = filter.yAxis,
|
367
|
+
plotType = filter.plotType,
|
368
|
+
lineChart = filter.lineChart;
|
369
|
+
var aggregation = plotType.aggregation,
|
370
|
+
interval = plotType.interval;
|
371
|
+
var seriesDataId = dataId[0];
|
372
|
+
var bins = (_timeBins = filter.timeBins) === null || _timeBins === void 0 || (_timeBins = _timeBins[seriesDataId]) === null || _timeBins === void 0 ? void 0 : _timeBins[interval];
|
373
|
+
if (lineChart && lineChart.aggregation === aggregation && lineChart.interval === interval && lineChart.yAxis === (yAxis === null || yAxis === void 0 ? void 0 : yAxis.name) &&
|
374
|
+
// we need to make sure we validate bins because of cross filter data changes
|
375
|
+
(0, _lodash["default"])(bins, lineChart === null || lineChart === void 0 ? void 0 : lineChart.bins)) {
|
376
|
+
// don't update lineChart if plotType hasn't change
|
377
|
+
return lineChart;
|
378
|
+
}
|
379
|
+
var dataset = datasets[seriesDataId];
|
380
|
+
var getYValue = getValueAggrFunc(yAxis, aggregation, dataset);
|
381
|
+
var init = [];
|
382
|
+
var series = (bins || []).reduce(function (accu, bin, i) {
|
383
|
+
var y = getYValue(bin);
|
384
|
+
var delta = getDelta(accu, y, interval);
|
385
|
+
accu.push(_objectSpread({
|
386
|
+
x: bin.x0,
|
387
|
+
y: y
|
388
|
+
}, delta));
|
389
|
+
return accu;
|
390
|
+
}, init);
|
391
|
+
var yDomain = (0, _d3Array.extent)(series, function (d) {
|
392
|
+
return d.y;
|
393
|
+
});
|
394
|
+
var xDomain = bins ? [bins[0].x0, bins[bins.length - 1].x1] : [];
|
395
|
+
|
396
|
+
// treat missing data as another series
|
397
|
+
var split = splitSeries(series);
|
398
|
+
var aggrName = _aggregation.AGGREGATION_NAME[aggregation];
|
399
|
+
return {
|
400
|
+
// @ts-ignore
|
401
|
+
yDomain: yDomain,
|
402
|
+
// @ts-ignore
|
403
|
+
xDomain: xDomain,
|
404
|
+
interval: interval,
|
405
|
+
aggregation: aggregation,
|
406
|
+
// @ts-ignore
|
407
|
+
series: split,
|
408
|
+
title: "".concat(aggrName, ' of ').concat(yAxis ? yAxis.name : 'Count'),
|
409
|
+
fieldType: yAxis ? yAxis.type : 'integer',
|
410
|
+
yAxis: yAxis ? yAxis.name : null,
|
411
|
+
allTime: {
|
412
|
+
title: "All Time Average",
|
413
|
+
value: (0, _aggregation.aggregate)(series, _constants.AGGREGATION_TYPES.average, function (d) {
|
414
|
+
return d.y;
|
415
|
+
})
|
416
|
+
},
|
417
|
+
// @ts-expect-error bins is Bins[], not a Bins map. Refactor to use correct types.
|
418
|
+
bins: bins
|
419
|
+
};
|
420
|
+
}
|
421
|
+
|
422
|
+
// split into multiple series when see missing data
|
423
|
+
function splitSeries(series) {
|
424
|
+
var lines = [];
|
425
|
+
var temp = [];
|
426
|
+
for (var i = 0; i < series.length; i++) {
|
427
|
+
var d = series[i];
|
428
|
+
if (!(0, _commonUtils.notNullorUndefined)(d.y) && temp.length) {
|
429
|
+
// ends temp
|
430
|
+
lines.push(temp);
|
431
|
+
temp = [];
|
432
|
+
} else if ((0, _commonUtils.notNullorUndefined)(d.y)) {
|
433
|
+
temp.push(d);
|
434
|
+
}
|
435
|
+
if (i === series.length - 1 && temp.length) {
|
436
|
+
lines.push(temp);
|
437
|
+
}
|
438
|
+
}
|
439
|
+
var markers = lines.length > 1 ? series.filter(function (d) {
|
440
|
+
return (0, _commonUtils.notNullorUndefined)(d.y);
|
441
|
+
}) : [];
|
442
|
+
return {
|
443
|
+
lines: lines,
|
444
|
+
markers: markers
|
445
|
+
};
|
446
|
+
}
|
447
|
+
function adjustValueToAnimationWindow(state, filter) {
|
448
|
+
var plotType = filter.plotType,
|
449
|
+
_filter$value = (0, _slicedToArray2["default"])(filter.value, 2),
|
450
|
+
value0 = _filter$value[0],
|
451
|
+
value1 = _filter$value[1],
|
452
|
+
animationWindow = filter.animationWindow;
|
453
|
+
var interval = plotType.interval || (0, _time.getInitialInterval)(filter, state.datasets);
|
454
|
+
var bins = getTimeBins(filter, state.datasets, interval);
|
455
|
+
var datasetBins = bins && Object.keys(bins).length && Object.values(bins)[0][interval];
|
456
|
+
var thresholds = (datasetBins || []).map(function (b) {
|
457
|
+
return b.x0;
|
458
|
+
});
|
459
|
+
var val0 = value0;
|
460
|
+
var val1 = value1;
|
461
|
+
var idx;
|
462
|
+
if (animationWindow === _constants.ANIMATION_WINDOW.interval) {
|
463
|
+
val0 = snapToMarks(value1, thresholds);
|
464
|
+
idx = thresholds.indexOf(val0);
|
465
|
+
val1 = idx > -1 ? datasetBins[idx].x1 : NaN;
|
466
|
+
} else {
|
467
|
+
// fit current value to window
|
468
|
+
val0 = snapToMarks(value0, thresholds);
|
469
|
+
val1 = snapToMarks(value1, thresholds);
|
470
|
+
if (val0 === val1) {
|
471
|
+
idx = thresholds.indexOf(val0);
|
472
|
+
if (idx === thresholds.length - 1) {
|
473
|
+
val0 = thresholds[idx - 1];
|
474
|
+
} else {
|
475
|
+
val1 = thresholds[idx + 1];
|
476
|
+
}
|
477
|
+
}
|
478
|
+
}
|
479
|
+
var updatedFilter = _objectSpread(_objectSpread({}, filter), {}, {
|
480
|
+
plotType: _objectSpread(_objectSpread({}, filter.plotType), {}, {
|
481
|
+
interval: interval
|
482
|
+
}),
|
483
|
+
timeBins: bins,
|
484
|
+
value: [val0, val1]
|
485
|
+
});
|
486
|
+
return updatedFilter;
|
487
|
+
}
|
488
|
+
|
489
|
+
/**
|
490
|
+
* Create or update colors for a filter plot
|
491
|
+
* @param filter
|
492
|
+
* @param datasets
|
493
|
+
* @param oldColorsByDataId
|
494
|
+
*/
|
495
|
+
function getFilterPlotColorsByDataId(filter, datasets, oldColorsByDataId) {
|
496
|
+
var colorsByDataId = oldColorsByDataId || {};
|
497
|
+
var _iterator = _createForOfIteratorHelper(filter.dataId),
|
498
|
+
_step;
|
499
|
+
try {
|
500
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
501
|
+
var dataId = _step.value;
|
502
|
+
if (!colorsByDataId[dataId] && datasets[dataId]) {
|
503
|
+
colorsByDataId = _objectSpread(_objectSpread({}, colorsByDataId), {}, (0, _defineProperty2["default"])({}, dataId, (0, _colorUtils.rgbToHex)(datasets[dataId].color)));
|
504
|
+
}
|
505
|
+
}
|
506
|
+
} catch (err) {
|
507
|
+
_iterator.e(err);
|
508
|
+
} finally {
|
509
|
+
_iterator.f();
|
510
|
+
}
|
511
|
+
return colorsByDataId;
|
512
|
+
}
|
513
|
+
|
514
|
+
/**
|
515
|
+
*
|
516
|
+
* @param filter
|
517
|
+
* @param plotType
|
518
|
+
* @param datasets
|
519
|
+
* @param dataId
|
520
|
+
*/
|
521
|
+
function updateTimeFilterPlotType(filter, plotType, datasets, dataId) {
|
522
|
+
var nextFilter = filter;
|
523
|
+
var nextPlotType = plotType;
|
524
|
+
if ((0, _typeof2["default"])(nextPlotType) !== 'object' || !nextPlotType.aggregation || !nextPlotType.interval) {
|
525
|
+
nextPlotType = getDefaultPlotType(filter, datasets);
|
526
|
+
}
|
527
|
+
if (filter.dataId.length > 1) {
|
528
|
+
nextPlotType = _objectSpread(_objectSpread({}, nextPlotType), {}, {
|
529
|
+
colorsByDataId: getFilterPlotColorsByDataId(filter, datasets, nextPlotType.colorsByDataId)
|
530
|
+
});
|
531
|
+
}
|
532
|
+
nextFilter = _objectSpread(_objectSpread({}, nextFilter), {}, {
|
533
|
+
plotType: nextPlotType
|
534
|
+
});
|
535
|
+
var bins = getTimeBins(nextFilter, datasets, nextPlotType.interval);
|
536
|
+
nextFilter = _objectSpread(_objectSpread({}, nextFilter), {}, {
|
537
|
+
timeBins: bins
|
538
|
+
});
|
539
|
+
if (plotType.type === _constants.PLOT_TYPES.histogram) {
|
540
|
+
// Histogram is calculated and memoized in the chart itself
|
541
|
+
} else if (plotType.type === _constants.PLOT_TYPES.lineChart) {
|
542
|
+
// we should be able to move this into its own component so react will do the shallow comparison for us.
|
543
|
+
nextFilter = _objectSpread(_objectSpread({}, nextFilter), {}, {
|
544
|
+
lineChart: getLineChart(datasets, nextFilter)
|
545
|
+
});
|
546
|
+
}
|
547
|
+
return nextFilter;
|
548
|
+
}
|
549
|
+
function getRangeFilterBins(filter, datasets, numBins) {
|
550
|
+
var domain = filter.domain;
|
551
|
+
if (!filter.dataId) return null;
|
552
|
+
return filter.dataId.reduce(function (acc, dataId, datasetIdx) {
|
553
|
+
var _filter$bins;
|
554
|
+
if ((_filter$bins = filter.bins) !== null && _filter$bins !== void 0 && _filter$bins[dataId]) {
|
555
|
+
// don't recalculate bins
|
556
|
+
acc[dataId] = filter.bins[dataId];
|
557
|
+
return acc;
|
558
|
+
}
|
559
|
+
var fieldName = filter.name[datasetIdx];
|
560
|
+
if (dataId && fieldName) {
|
561
|
+
var dataset = datasets[dataId];
|
562
|
+
var field = dataset === null || dataset === void 0 ? void 0 : dataset.getColumnField(fieldName);
|
563
|
+
if (dataset && field) {
|
564
|
+
var indexes = runGpuFilterForPlot(dataset, filter);
|
565
|
+
var valueAccessor = function valueAccessor(index) {
|
566
|
+
return field.valueAccessor({
|
567
|
+
index: index
|
568
|
+
});
|
569
|
+
};
|
570
|
+
acc[dataId] = histogramFromDomain(domain, indexes, numBins, valueAccessor);
|
571
|
+
}
|
572
|
+
}
|
573
|
+
return acc;
|
574
|
+
}, {});
|
575
|
+
}
|
576
|
+
function updateRangeFilterPlotType(filter, plotType, datasets, dataId) {
|
577
|
+
var nextFilter = _objectSpread(_objectSpread({}, filter), {}, {
|
578
|
+
plotType: plotType
|
579
|
+
});
|
580
|
+
|
581
|
+
// if (dataId) {
|
582
|
+
// // clear bins
|
583
|
+
// nextFilter = {
|
584
|
+
// ...nextFilter,
|
585
|
+
// bins: {
|
586
|
+
// ...nextFilter.bins,
|
587
|
+
// [dataId]: null
|
588
|
+
// }
|
589
|
+
// };
|
590
|
+
// }
|
591
|
+
|
592
|
+
return _objectSpread(_objectSpread({}, filter), {}, {
|
593
|
+
plotType: plotType,
|
594
|
+
bins: getRangeFilterBins(nextFilter, datasets, _constants.BINS)
|
595
|
+
});
|
596
|
+
}
|
597
|
+
function getChartTitle(yAxis, plotType) {
|
598
|
+
var yAxisName = yAxis === null || yAxis === void 0 ? void 0 : yAxis.displayName;
|
599
|
+
var aggregation = plotType.aggregation;
|
600
|
+
if (yAxisName) {
|
601
|
+
return (0, _strings.capitalizeFirstLetter)("".concat(aggregation, " ").concat(yAxisName, " over Time"));
|
602
|
+
}
|
603
|
+
return "Count of Rows over Time";
|
604
|
+
}
|
605
|
+
function getDefaultPlotType(filter, datasets) {
|
606
|
+
var interval = (0, _time.getInitialInterval)(filter, datasets);
|
607
|
+
var defaultTimeFormat = (0, _format.getDefaultTimeFormat)(interval);
|
608
|
+
return {
|
609
|
+
interval: interval,
|
610
|
+
defaultTimeFormat: defaultTimeFormat,
|
611
|
+
type: _constants.PLOT_TYPES.histogram,
|
612
|
+
aggregation: _constants.AGGREGATION_TYPES.sum
|
613
|
+
};
|
614
|
+
}
|
615
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZDNBcnJheSIsInJlcXVpcmUiLCJfbG9kYXNoIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl90aW1lIiwiX21vbWVudCIsIl9jb21tb25VdGlscyIsIl9jb25zdGFudHMiLCJfZGF0YVV0aWxzIiwiX2FnZ3JlZ2F0aW9uIiwiX3N0cmluZ3MiLCJfZm9ybWF0IiwiX2NvbG9yVXRpbHMiLCJfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlciIsInIiLCJlIiwidCIsIlN5bWJvbCIsIml0ZXJhdG9yIiwiQXJyYXkiLCJpc0FycmF5IiwiX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5IiwibGVuZ3RoIiwiX24iLCJGIiwicyIsIm4iLCJkb25lIiwidmFsdWUiLCJmIiwiVHlwZUVycm9yIiwibyIsImEiLCJ1IiwiY2FsbCIsIm5leHQiLCJfYXJyYXlMaWtlVG9BcnJheSIsInRvU3RyaW5nIiwic2xpY2UiLCJjb25zdHJ1Y3RvciIsIm5hbWUiLCJmcm9tIiwidGVzdCIsIm93bktleXMiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwiZmlsdGVyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiZGVmaW5lUHJvcGVydHkiLCJoaXN0b2dyYW1Gcm9tVGhyZXNob2xkIiwidGhyZXNob2xkcyIsInZhbHVlcyIsInZhbHVlQWNjZXNzb3IiLCJmaWx0ZXJFbXB0eUJpbnMiLCJ1bmRlZmluZWQiLCJnZXRCaW5zIiwiZDNIaXN0b2dyYW0iLCJkb21haW4iLCJiaW5zIiwibWFwIiwiYmluIiwiY291bnQiLCJpbmRleGVzIiwieDAiLCJ4MSIsImIiLCJoaXN0b2dyYW1Gcm9tVmFsdWVzIiwibnVtQmlucyIsImlzTnVtYmVyIiwiaGlzdG9ncmFtRnJvbURvbWFpbiIsInRpY2tzIiwiZ2V0VGltZUJpbnMiLCJkYXRhc2V0cyIsImludGVydmFsIiwidGltZUJpbnMiLCJkYXRhSWQiLCJkYXRhSWRJZHgiLCJkYXRhc2V0IiwicnVuR3B1RmlsdGVyRm9yUGxvdCIsImJpbkJ5VGltZSIsIm1hcHBlZFZhbHVlIiwiZ2V0RmlsdGVyTWFwcGVkVmFsdWUiLCJpbnRlcnZhbEJpbnMiLCJnZXRCaW5UaHJlc2hvbGRzIiwiaWR4IiwidGltZUludGVydmFsIiwiaW50ZXJ2YWxUb0Z1bmN0aW9uIiwiX2RvbWFpbiIsIl9zbGljZWRUb0FycmF5MiIsInQwIiwidDEiLCJmbG9vciIsImdldFRpbWUiLCJjZWlsaW5nIiwiY2VpbCIsImR1cmF0aW9uRGF5IiwiYmluVGhyZXNob2xkcyIsInJhbmdlIiwibW9tZW50IiwidXRjIiwidmFsdWVPZiIsImxhc3RTdGVwIiwib2Zmc2V0Iiwic2tpcEluZGV4ZXMiLCJnZXRTa2lwSW5kZXhlcyIsIl9kYXRhc2V0JGdwdUZpbHRlciIsImdwdUZpbHRlciIsImZpbHRlclZhbHVlVXBkYXRlVHJpZ2dlcnMiLCJmaWx0ZXJSYW5nZSIsImZpbHRlclZhbHVlQWNjZXNzb3IiLCJmaWx0ZXJlZEluZGV4IiwiZ2V0RmlsdGVyVmFsdWUiLCJkYXRhQ29udGFpbmVyIiwiYWxsQ2hhbm5lbHMiLCJfIiwiaSIsInNraXBBbGwiLCJpbmNsdWRlcyIsImZpbHRlckRhdGEiLCJnZXRGaWx0ZXJEYXRhRnVuYyIsImdwdUZpbHRlcnMiLCJ2YWx1ZUluZGV4IiwiZmluZEluZGV4IiwiaWQiLCJmaWx0ZXJDb2x1bW4iLCJyZWR1Y2UiLCJhY2N1IiwiaXRlbSIsInNraXBzIiwiaW5kZXgiLCJldmVyeSIsInZhbCIsInZhbGlkQmluIiwic25hcFRvTWFya3MiLCJtYXJrcyIsImJpc2VjdExlZnQiLCJub3JtYWxpemVWYWx1ZSIsIm1pblZhbHVlIiwic3RlcCIsInJvdW5kVmFsVG9TdGVwIiwiaXNQZXJjZW50RmllbGQiLCJmaWVsZCIsIm1ldGFkYXRhIiwibnVtZXJhdG9yIiwiZGVub21pbmF0b3IiLCJ1cGRhdGVBZ2dyZWdhdGlvbkJ5RmllbGQiLCJhZ2dyZWdhdGlvbiIsIkFHR1JFR0FUSU9OX1RZUEVTIiwiYXZlcmFnZSIsImdldEFncmVnYXRpb25UeXBlIiwiZ2V0QWdncmVnYXRpb25BY2Nlc3NvciIsImZpZWxkcyIsIm51bWVyYXRvcklkeCIsImRlbm9taW5hdG9ySWR4IiwiZ2V0TnVtZXJhdG9yIiwidmFsdWVBdCIsImdldERlbm9taW5hdG9yIiwiZ2V0VmFsdWVBZ2dyRnVuYyIsImV4cG9ydHMiLCJkYXRhc2V0RmllbGQiLCJmaW5kIiwiYWdncmVnYXRlIiwiZ2V0QWdncmVnYXRpb25PcHRpb3NuQmFzZWRPbkZpZWxkIiwiVElNRV9BR0dSRUdBVElPTiIsIl9yZWYiLCJzdW0iLCJnZXREZWx0YSIsInkiLCJsYXN0QmluIiwiZGVsdGEiLCJwY3QiLCJnZXRQY3RDaGFuZ2UiLCJ5MCIsIk51bWJlciIsImlzRmluaXRlIiwiZ2V0TGluZUNoYXJ0IiwiX3RpbWVCaW5zIiwieUF4aXMiLCJwbG90VHlwZSIsImxpbmVDaGFydCIsInNlcmllc0RhdGFJZCIsImlzRXF1YWwiLCJnZXRZVmFsdWUiLCJpbml0Iiwic2VyaWVzIiwieCIsInlEb21haW4iLCJleHRlbnQiLCJkIiwieERvbWFpbiIsInNwbGl0Iiwic3BsaXRTZXJpZXMiLCJhZ2dyTmFtZSIsIkFHR1JFR0FUSU9OX05BTUUiLCJ0aXRsZSIsImNvbmNhdCIsImZpZWxkVHlwZSIsInR5cGUiLCJhbGxUaW1lIiwibGluZXMiLCJ0ZW1wIiwibm90TnVsbG9yVW5kZWZpbmVkIiwibWFya2VycyIsImFkanVzdFZhbHVlVG9BbmltYXRpb25XaW5kb3ciLCJzdGF0ZSIsIl9maWx0ZXIkdmFsdWUiLCJ2YWx1ZTAiLCJ2YWx1ZTEiLCJhbmltYXRpb25XaW5kb3ciLCJnZXRJbml0aWFsSW50ZXJ2YWwiLCJkYXRhc2V0QmlucyIsInZhbDAiLCJ2YWwxIiwiQU5JTUFUSU9OX1dJTkRPVyIsImluZGV4T2YiLCJOYU4iLCJ1cGRhdGVkRmlsdGVyIiwiZ2V0RmlsdGVyUGxvdENvbG9yc0J5RGF0YUlkIiwib2xkQ29sb3JzQnlEYXRhSWQiLCJjb2xvcnNCeURhdGFJZCIsIl9pdGVyYXRvciIsIl9zdGVwIiwicmdiVG9IZXgiLCJjb2xvciIsImVyciIsInVwZGF0ZVRpbWVGaWx0ZXJQbG90VHlwZSIsIm5leHRGaWx0ZXIiLCJuZXh0UGxvdFR5cGUiLCJfdHlwZW9mMiIsImdldERlZmF1bHRQbG90VHlwZSIsIlBMT1RfVFlQRVMiLCJoaXN0b2dyYW0iLCJnZXRSYW5nZUZpbHRlckJpbnMiLCJhY2MiLCJkYXRhc2V0SWR4IiwiX2ZpbHRlciRiaW5zIiwiZmllbGROYW1lIiwiZ2V0Q29sdW1uRmllbGQiLCJ1cGRhdGVSYW5nZUZpbHRlclBsb3RUeXBlIiwiQklOUyIsImdldENoYXJ0VGl0bGUiLCJ5QXhpc05hbWUiLCJkaXNwbGF5TmFtZSIsImNhcGl0YWxpemVGaXJzdExldHRlciIsImRlZmF1bHRUaW1lRm9ybWF0IiwiZ2V0RGVmYXVsdFRpbWVGb3JtYXQiXSwic291cmNlcyI6WyIuLi9zcmMvcGxvdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQge2Jpc2VjdExlZnQsIGV4dGVudCwgaGlzdG9ncmFtIGFzIGQzSGlzdG9ncmFtLCB0aWNrc30gZnJvbSAnZDMtYXJyYXknO1xuaW1wb3J0IGlzRXF1YWwgZnJvbSAnbG9kYXNoLmlzZXF1YWwnO1xuaW1wb3J0IHtnZXRGaWx0ZXJNYXBwZWRWYWx1ZSwgZ2V0SW5pdGlhbEludGVydmFsLCBpbnRlcnZhbFRvRnVuY3Rpb259IGZyb20gJy4vdGltZSc7XG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQge1xuICBCaW4sXG4gIFRpbWVCaW5zLFxuICBNaWxsaXNlY29uZCxcbiAgVGltZVJhbmdlRmlsdGVyLFxuICBSYW5nZUZpbHRlcixcbiAgUGxvdFR5cGUsXG4gIEZpbHRlcixcbiAgTGluZUNoYXJ0LFxuICBGaWVsZCxcbiAgVmFsdWVPZixcbiAgTGluZURhdHVtXG59IGZyb20gJ0BrZXBsZXIuZ2wvdHlwZXMnO1xuaW1wb3J0IHtub3ROdWxsb3JVbmRlZmluZWR9IGZyb20gJ0BrZXBsZXIuZ2wvY29tbW9uLXV0aWxzJztcbmltcG9ydCB7XG4gIEFOSU1BVElPTl9XSU5ET1csXG4gIEJJTlMsXG4gIGR1cmF0aW9uRGF5LFxuICBUSU1FX0FHR1JFR0FUSU9OLFxuICBBR0dSRUdBVElPTl9UWVBFUyxcbiAgUExPVF9UWVBFUyxcbiAgQWdncmVnYXRpb25UeXBlc1xufSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5cbmltcG9ydCB7aXNOdW1iZXIsIHJvdW5kVmFsVG9TdGVwfSBmcm9tICcuL2RhdGEtdXRpbHMnO1xuaW1wb3J0IHthZ2dyZWdhdGUsIEFHR1JFR0FUSU9OX05BTUV9IGZyb20gJy4vYWdncmVnYXRpb24nO1xuaW1wb3J0IHtjYXBpdGFsaXplRmlyc3RMZXR0ZXJ9IGZyb20gJy4vc3RyaW5ncyc7XG5pbXBvcnQge2dldERlZmF1bHRUaW1lRm9ybWF0fSBmcm9tICcuL2Zvcm1hdCc7XG5pbXBvcnQge3JnYlRvSGV4fSBmcm9tICcuL2NvbG9yLXV0aWxzJztcbmltcG9ydCB7RGF0YUNvbnRhaW5lckludGVyZmFjZX0gZnJvbSAnLic7XG5pbXBvcnQge0tlcGxlclRhYmxlTW9kZWx9IGZyb20gJy4vdHlwZXMnO1xuXG4vLyBUT0RPIGtlcGxlci10YWJsZSBtb2R1bGUgaXNuJ3QgYWNjZXNzaWJsZSBmcm9tIHV0aWxzLiBBZGQgY29tcGF0aWJsZSBpbnRlcmZhY2UgdG8gdHlwZXNcbnR5cGUgRGF0YXNldHMgPSBhbnk7XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB0aHJlc2hvbGRzXG4gKiBAcGFyYW0gdmFsdWVzXG4gKiBAcGFyYW0gaW5kZXhlc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGlzdG9ncmFtRnJvbVRocmVzaG9sZChcbiAgdGhyZXNob2xkczogbnVtYmVyW10sXG4gIHZhbHVlczogbnVtYmVyW10sXG4gIHZhbHVlQWNjZXNzb3I/OiAoZDogdW5rbm93bikgPT4gbnVtYmVyLFxuICBmaWx0ZXJFbXB0eUJpbnMgPSB0cnVlXG4pOiBCaW5bXSB7XG4gIGNvbnN0IGdldEJpbnMgPSBkM0hpc3RvZ3JhbSgpXG4gICAgLmRvbWFpbihbdGhyZXNob2xkc1swXSwgdGhyZXNob2xkc1t0aHJlc2hvbGRzLmxlbmd0aCAtIDFdXSlcbiAgICAudGhyZXNob2xkcyh0aHJlc2hvbGRzKTtcblxuICBpZiAodmFsdWVBY2Nlc3Nvcikge1xuICAgIGdldEJpbnMudmFsdWUodmFsdWVBY2Nlc3Nvcik7XG4gIH1cblxuICAvLyBAdHMtaWdub3JlXG4gIGNvbnN0IGJpbnMgPSBnZXRCaW5zKHZhbHVlcykubWFwKGJpbiA9PiAoe1xuICAgIGNvdW50OiBiaW4ubGVuZ3RoLFxuICAgIGluZGV4ZXM6IGJpbixcbiAgICB4MDogYmluLngwLFxuICAgIHgxOiBiaW4ueDFcbiAgfSkpO1xuXG4gIC8vIGQzLWhpc3RvZ3JhbSBpZ25vcmVzIHRocmVzaG9sZCB2YWx1ZXMgb3V0c2lkZSB0aGUgZG9tYWluXG4gIC8vIFRoZSBmaXJzdCBiaW4ueDAgaXMgYWx3YXlzIGVxdWFsIHRvIHRoZSBtaW5pbXVtIGRvbWFpbiB2YWx1ZSwgYW5kIHRoZSBsYXN0IGJpbi54MSBpcyBhbHdheXMgZXF1YWwgdG8gdGhlIG1heGltdW0gZG9tYWluIHZhbHVlLlxuXG4gIC8vIGJpbnNbMF0ueDAgPSB0aHJlc2hvbGRzWzBdO1xuICAvLyBiaW5zW2JpbnMubGVuZ3RoIC0gMV0ueDEgPSB0aHJlc2hvbGRzW3RocmVzaG9sZHMubGVuZ3RoIC0gMV07XG5cbiAgLy8gQHRzLWlnbm9yZVxuICByZXR1cm4gZmlsdGVyRW1wdHlCaW5zID8gYmlucy5maWx0ZXIoYiA9PiBiLmNvdW50ID4gMCkgOiBiaW5zO1xufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0gdmFsdWVzXG4gKiBAcGFyYW0gbnVtQmluc1xuICogQHBhcmFtIHZhbHVlQWNjZXNzb3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhpc3RvZ3JhbUZyb21WYWx1ZXMoXG4gIHZhbHVlczogKE1pbGxpc2Vjb25kIHwgbnVsbCB8IG51bWJlcilbXSxcbiAgbnVtQmluczogbnVtYmVyLFxuICB2YWx1ZUFjY2Vzc29yPzogKGQ6IHVua25vd24pID0+IG51bWJlclxuKSB7XG4gIGNvbnN0IGdldEJpbnMgPSBkM0hpc3RvZ3JhbSgpLnRocmVzaG9sZHMobnVtQmlucyk7XG5cbiAgaWYgKHZhbHVlQWNjZXNzb3IpIHtcbiAgICBnZXRCaW5zLnZhbHVlKHZhbHVlQWNjZXNzb3IpO1xuICB9XG5cbiAgLy8gQHRzLWlnbm9yZSBkMy1hcnJheSB0eXBlcyBkb2Vzbid0IG1hdGNoXG4gIHJldHVybiBnZXRCaW5zKHZhbHVlcylcbiAgICAubWFwKGJpbiA9PiAoe1xuICAgICAgY291bnQ6IGJpbi5sZW5ndGgsXG4gICAgICBpbmRleGVzOiBiaW4sXG4gICAgICB4MDogYmluLngwLFxuICAgICAgeDE6IGJpbi54MVxuICAgIH0pKVxuICAgIC5maWx0ZXIoYiA9PiB7XG4gICAgICBjb25zdCB7eDAsIHgxfSA9IGI7XG4gICAgICByZXR1cm4gaXNOdW1iZXIoeDApICYmIGlzTnVtYmVyKHgxKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIGRvbWFpblxuICogQHBhcmFtIHZhbHVlc1xuICogQHBhcmFtIG51bUJpbnNcbiAqIEBwYXJhbSB2YWx1ZUFjY2Vzc29yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoaXN0b2dyYW1Gcm9tRG9tYWluKFxuICBkb21haW46IFtudW1iZXIsIG51bWJlcl0sXG4gIHZhbHVlczogKE1pbGxpc2Vjb25kIHwgbnVsbCB8IG51bWJlcilbXSxcbiAgbnVtQmluczogbnVtYmVyLFxuICB2YWx1ZUFjY2Vzc29yPzogKGQ6IHVua25vd24pID0+IG51bWJlclxuKTogQmluW10ge1xuICBjb25zdCBnZXRCaW5zID0gZDNIaXN0b2dyYW0oKS50aHJlc2hvbGRzKHRpY2tzKGRvbWFpblswXSwgZG9tYWluWzFdLCBudW1CaW5zKSkuZG9tYWluKGRvbWFpbik7XG4gIGlmICh2YWx1ZUFjY2Vzc29yKSB7XG4gICAgZ2V0Qmlucy52YWx1ZSh2YWx1ZUFjY2Vzc29yKTtcbiAgfVxuXG4gIC8vIEB0cy1pZ25vcmUgZDMtYXJyYXkgdHlwZXMgZG9lc24ndCBtYXRjaFxuICByZXR1cm4gZ2V0Qmlucyh2YWx1ZXMpLm1hcChiaW4gPT4gKHtcbiAgICBjb3VudDogYmluLmxlbmd0aCxcbiAgICBpbmRleGVzOiBiaW4sXG4gICAgeDA6IGJpbi54MCxcbiAgICB4MTogYmluLngxXG4gIH0pKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gZmlsdGVyXG4gKiBAcGFyYW0gZGF0YXNldHNcbiAqIEBwYXJhbSBpbnRlcnZhbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGltZUJpbnMoXG4gIGZpbHRlcjogVGltZVJhbmdlRmlsdGVyLFxuICBkYXRhc2V0czogRGF0YXNldHMsXG4gIGludGVydmFsOiBQbG90VHlwZVsnaW50ZXJ2YWwnXVxuKTogVGltZUJpbnMge1xuICBsZXQgYmlucyA9IGZpbHRlci50aW1lQmlucyB8fCB7fTtcblxuICBmaWx0ZXIuZGF0YUlkLmZvckVhY2goKGRhdGFJZCwgZGF0YUlkSWR4KSA9PiB7XG4gICAgLy8gcmV1c2UgYmlucyBpZiBmaWx0ZXJEYXRhIGRpZCBub3QgY2hhbmdlXG4gICAgaWYgKGJpbnNbZGF0YUlkXSAmJiBiaW5zW2RhdGFJZF1baW50ZXJ2YWxdKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGRhdGFzZXQgPSBkYXRhc2V0c1tkYXRhSWRdO1xuXG4gICAgLy8gZG8gbm90IGFwcGx5IGN1cnJlbnQgZmlsdGVyXG4gICAgY29uc3QgaW5kZXhlcyA9IHJ1bkdwdUZpbHRlckZvclBsb3QoZGF0YXNldCwgZmlsdGVyKTtcblxuICAgIGJpbnMgPSB7XG4gICAgICAuLi5iaW5zLFxuICAgICAgW2RhdGFJZF06IHtcbiAgICAgICAgLi4uYmluc1tkYXRhSWRdLFxuICAgICAgICBbaW50ZXJ2YWxdOiBiaW5CeVRpbWUoaW5kZXhlcywgZGF0YXNldCwgaW50ZXJ2YWwsIGZpbHRlcilcbiAgICAgIH1cbiAgICB9O1xuICB9KTtcblxuICByZXR1cm4gYmlucztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJpbkJ5VGltZShpbmRleGVzLCBkYXRhc2V0LCBpbnRlcnZhbCwgZmlsdGVyKSB7XG4gIC8vIGdwdUZpbHRlcnMgbmVlZCB0byBiZSBhcHBseSB0byBmaWx0ZXJlZEluZGV4XG4gIGNvbnN0IG1hcHBlZFZhbHVlID0gZ2V0RmlsdGVyTWFwcGVkVmFsdWUoZGF0YXNldCwgZmlsdGVyKTtcbiAgaWYgKCFtYXBwZWRWYWx1ZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IGludGVydmFsQmlucyA9IGdldEJpblRocmVzaG9sZHMoaW50ZXJ2YWwsIGZpbHRlci5kb21haW4pO1xuICBjb25zdCB2YWx1ZUFjY2Vzc29yID0gaWR4ID0+IG1hcHBlZFZhbHVlW2lkeF07XG4gIGNvbnN0IGJpbnMgPSBoaXN0b2dyYW1Gcm9tVGhyZXNob2xkKGludGVydmFsQmlucywgaW5kZXhlcywgdmFsdWVBY2Nlc3Nvcik7XG5cbiAgcmV0dXJuIGJpbnM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRCaW5UaHJlc2hvbGRzKGludGVydmFsOiBzdHJpbmcsIGRvbWFpbjogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gIGNvbnN0IHRpbWVJbnRlcnZhbCA9IGludGVydmFsVG9GdW5jdGlvbihpbnRlcnZhbCk7XG4gIGNvbnN0IFt0MCwgdDFdID0gZG9tYWluO1xuICBjb25zdCBmbG9vciA9IHRpbWVJbnRlcnZhbC5mbG9vcih0MCkuZ2V0VGltZSgpO1xuICBjb25zdCBjZWlsaW5nID0gdGltZUludGVydmFsLmNlaWwodDEpLmdldFRpbWUoKTtcblxuICBpZiAoIXRpbWVJbnRlcnZhbCkge1xuICAgIC8vIGlmIHRpbWUgaW50ZXJ2YWwgaXMgbm90IGRlZmluZWRcbiAgICAvLyB0aGlzIHNob3VsZCBub3QgaGFwcGVuXG4gICAgcmV0dXJuIFt0MCwgdDAgKyBkdXJhdGlvbkRheV07XG4gIH1cbiAgY29uc3QgYmluVGhyZXNob2xkcyA9IHRpbWVJbnRlcnZhbC5yYW5nZShmbG9vciwgY2VpbGluZyArIDEpLm1hcCh0ID0+IG1vbWVudC51dGModCkudmFsdWVPZigpKTtcbiAgY29uc3QgbGFzdFN0ZXAgPSBiaW5UaHJlc2hvbGRzW2JpblRocmVzaG9sZHMubGVuZ3RoIC0gMV07XG4gIGlmIChsYXN0U3RlcCA9PT0gdDEpIHtcbiAgICAvLyB3aGVuIGxhc3Qgc3RlcCBlcXVhbCB0byBkb21haW4gbWF4LCBhZGQgb25lIG1vcmUgc3RlcFxuICAgIGJpblRocmVzaG9sZHMucHVzaChtb21lbnQudXRjKHRpbWVJbnRlcnZhbC5vZmZzZXQobGFzdFN0ZXApKS52YWx1ZU9mKCkpO1xuICB9XG5cbiAgcmV0dXJuIGJpblRocmVzaG9sZHM7XG59XG5cbi8qKlxuICogUnVuIEdQVSBmaWx0ZXIgb24gY3VycmVudCBmaWx0ZXIgcmVzdWx0IHRvIGdlbmVyYXRlIGluZGV4ZXMgZm9yIHBsb3RpbmcgY2hhcnRcbiAqIFNraXAgcnV1bmluZyBmb3IgdGhlIHNhbWUgZmllbGRcbiAqIEBwYXJhbSBkYXRhc2V0XG4gKiBAcGFyYW0gZmlsdGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5HcHVGaWx0ZXJGb3JQbG90PEsgZXh0ZW5kcyBLZXBsZXJUYWJsZU1vZGVsPEssIEw+LCBMPihcbiAgZGF0YXNldDogSyxcbiAgZmlsdGVyPzogRmlsdGVyXG4pOiBudW1iZXJbXSB7XG4gIGNvbnN0IHNraXBJbmRleGVzID0gZ2V0U2tpcEluZGV4ZXMoZGF0YXNldCwgZmlsdGVyKTtcblxuICBjb25zdCB7XG4gICAgZ3B1RmlsdGVyOiB7ZmlsdGVyVmFsdWVVcGRhdGVUcmlnZ2VycywgZmlsdGVyUmFuZ2UsIGZpbHRlclZhbHVlQWNjZXNzb3J9LFxuICAgIGZpbHRlcmVkSW5kZXhcbiAgfSA9IGRhdGFzZXQ7XG4gIGNvbnN0IGdldEZpbHRlclZhbHVlID0gZmlsdGVyVmFsdWVBY2Nlc3NvcihkYXRhc2V0LmRhdGFDb250YWluZXIpKCk7XG5cbiAgY29uc3QgYWxsQ2hhbm5lbHMgPSBPYmplY3Qua2V5cyhmaWx0ZXJWYWx1ZVVwZGF0ZVRyaWdnZXJzKVxuICAgIC5tYXAoKF8sIGkpID0+IGkpXG4gICAgLmZpbHRlcihpID0+IE9iamVjdC52YWx1ZXMoZmlsdGVyVmFsdWVVcGRhdGVUcmlnZ2VycylbaV0pO1xuICBjb25zdCBza2lwQWxsID0gIWFsbENoYW5uZWxzLmZpbHRlcihpID0+ICFza2lwSW5kZXhlcy5pbmNsdWRlcyhpKSkubGVuZ3RoO1xuICBpZiAoc2tpcEFsbCkge1xuICAgIHJldHVybiBmaWx0ZXJlZEluZGV4O1xuICB9XG5cbiAgY29uc3QgZmlsdGVyRGF0YSA9IGdldEZpbHRlckRhdGFGdW5jKFxuICAgIGZpbHRlclJhbmdlLFxuICAgIGdldEZpbHRlclZhbHVlLFxuICAgIGRhdGFzZXQuZGF0YUNvbnRhaW5lcixcbiAgICBza2lwSW5kZXhlc1xuICApO1xuXG4gIHJldHVybiBmaWx0ZXJlZEluZGV4LmZpbHRlcihmaWx0ZXJEYXRhKTtcbn1cblxuZnVuY3Rpb24gZ2V0U2tpcEluZGV4ZXMoZGF0YXNldCwgZmlsdGVyKSB7XG4gIC8vIGFycmF5IG9mIGdwdSBmaWx0ZXIgbmFtZXNcbiAgaWYgKCFmaWx0ZXIpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgY29uc3QgZ3B1RmlsdGVycyA9IE9iamVjdC52YWx1ZXMoZGF0YXNldC5ncHVGaWx0ZXIuZmlsdGVyVmFsdWVVcGRhdGVUcmlnZ2VycykgYXMgKHtcbiAgICBuYW1lOiBzdHJpbmc7XG4gIH0gfCBudWxsKVtdO1xuICBjb25zdCB2YWx1ZUluZGV4ID0gZmlsdGVyLmRhdGFJZC5maW5kSW5kZXgoaWQgPT4gaWQgPT09IGRhdGFzZXQuaWQpO1xuICBjb25zdCBmaWx0ZXJDb2x1bW4gPSBmaWx0ZXIubmFtZVt2YWx1ZUluZGV4XTtcblxuICByZXR1cm4gZ3B1RmlsdGVycy5yZWR1Y2UoKGFjY3UsIGl0ZW0sIGlkeCkgPT4ge1xuICAgIGlmIChpdGVtICYmIGZpbHRlckNvbHVtbiA9PT0gaXRlbS5uYW1lKSB7XG4gICAgICBhY2N1LnB1c2goaWR4KTtcbiAgICB9XG4gICAgcmV0dXJuIGFjY3U7XG4gIH0sIFtdIGFzIG51bWJlcltdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZpbHRlckRhdGFGdW5jKFxuICBmaWx0ZXJSYW5nZSxcbiAgZ2V0RmlsdGVyVmFsdWUsXG4gIGRhdGFDb250YWluZXI6IERhdGFDb250YWluZXJJbnRlcmZhY2UsXG4gIHNraXBzXG4pIHtcbiAgcmV0dXJuIGluZGV4ID0+XG4gICAgZ2V0RmlsdGVyVmFsdWUoe2luZGV4fSkuZXZlcnkoXG4gICAgICAodmFsLCBpKSA9PiBza2lwcy5pbmNsdWRlcyhpKSB8fCAodmFsID49IGZpbHRlclJhbmdlW2ldWzBdICYmIHZhbCA8PSBmaWx0ZXJSYW5nZVtpXVsxXSlcbiAgICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRCaW4oYikge1xuICByZXR1cm4gYi54MCAhPT0gdW5kZWZpbmVkICYmIGIueDEgIT09IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBVc2UgaW4gc2xpZGVyLCBnaXZlbiBhIG51bWJlciBhbmQgYW4gYXJyYXkgb2YgbnVtYmVycywgcmV0dXJuIHRoZSBuZWFycyBudW1iZXIgZnJvbSB0aGUgYXJyYXkuXG4gKiBUYWtlcyBhIHZhbHVlLCB0aW1lc3RlcHMgYW5kIHJldHVybiB0aGUgYWN0dWFsIHN0ZXAuXG4gKiBAcGFyYW0gdmFsdWVcbiAqIEBwYXJhbSBtYXJrc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc25hcFRvTWFya3ModmFsdWU6IG51bWJlciwgbWFya3M6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgLy8gYWx3YXlzIHVzZSBiaW4geDBcbiAgaWYgKCFtYXJrcy5sZW5ndGgpIHtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIGxvb2tpbmcgYXQgdGhlIHVzYWdlIG51bGwgcmV0dXJuIHZhbHVlIGlzbid0IGV4cGVjdGVkIGFuZCByZXF1aXJlcyBleHRyYSBoYW5kbGluZyBpbiBhIGxvdCBvZiBwbGFjZXNcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBjb25zdCBpID0gYmlzZWN0TGVmdChtYXJrcywgdmFsdWUpO1xuICBpZiAoaSA9PT0gMCkge1xuICAgIHJldHVybiBtYXJrc1tpXTtcbiAgfSBlbHNlIGlmIChpID09PSBtYXJrcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gbWFya3NbaSAtIDFdO1xuICB9XG4gIGNvbnN0IGlkeCA9IG1hcmtzW2ldIC0gdmFsdWUgPCB2YWx1ZSAtIG1hcmtzW2kgLSAxXSA/IGkgOiBpIC0gMTtcbiAgcmV0dXJuIG1hcmtzW2lkeF07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVWYWx1ZSh2YWwsIG1pblZhbHVlLCBzdGVwLCBtYXJrcykge1xuICBpZiAobWFya3MgJiYgbWFya3MubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHNuYXBUb01hcmtzKHZhbCwgbWFya3MpO1xuICB9XG5cbiAgcmV0dXJuIHJvdW5kVmFsVG9TdGVwKG1pblZhbHVlLCBzdGVwLCB2YWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNQZXJjZW50RmllbGQoZmllbGQpIHtcbiAgcmV0dXJuIGZpZWxkLm1ldGFkYXRhICYmIGZpZWxkLm1ldGFkYXRhLm51bWVyYXRvciAmJiBmaWVsZC5tZXRhZGF0YS5kZW5vbWluYXRvcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUFnZ3JlZ2F0aW9uQnlGaWVsZChmaWVsZDogRmllbGQsIGFnZ3JlZ2F0aW9uOiBWYWx1ZU9mPEFnZ3JlZ2F0aW9uVHlwZXM+KSB7XG4gIC8vIHNob3VsZG4ndCBhcHBseSBzdW0gdG8gcGVyY2VudCBmaWVsZSB0eXBlXG4gIC8vIGRlZmF1bHQgYWdncmVnYXRpb24gaXMgYXZlcmFnZVxuICByZXR1cm4gZmllbGQgJiYgaXNQZXJjZW50RmllbGQoZmllbGQpXG4gICAgPyBBR0dSRUdBVElPTl9UWVBFUy5hdmVyYWdlXG4gICAgOiBhZ2dyZWdhdGlvbiB8fCBBR0dSRUdBVElPTl9UWVBFUy5hdmVyYWdlO1xufVxuXG5jb25zdCBnZXRBZ3JlZ2F0aW9uVHlwZSA9IChmaWVsZCwgYWdncmVnYXRpb24pID0+IHtcbiAgaWYgKGlzUGVyY2VudEZpZWxkKGZpZWxkKSkge1xuICAgIHJldHVybiAnbWVhbl9vZl9wZXJjZW50JztcbiAgfVxuICByZXR1cm4gYWdncmVnYXRpb247XG59O1xuXG5jb25zdCBnZXRBZ2dyZWdhdGlvbkFjY2Vzc29yID0gKGZpZWxkLCBkYXRhQ29udGFpbmVyOiBEYXRhQ29udGFpbmVySW50ZXJmYWNlLCBmaWVsZHMpID0+IHtcbiAgaWYgKGlzUGVyY2VudEZpZWxkKGZpZWxkKSkge1xuICAgIGNvbnN0IG51bWVyYXRvcklkeCA9IGZpZWxkcy5maW5kSW5kZXgoZiA9PiBmLm5hbWUgPT09IGZpZWxkLm1ldGFkYXRhLm51bWVyYXRvcik7XG4gICAgY29uc3QgZGVub21pbmF0b3JJZHggPSBmaWVsZHMuZmluZEluZGV4KGYgPT4gZi5uYW1lID09PSBmaWVsZC5tZXRhZGF0YS5kZW5vbWluYXRvcik7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZ2V0TnVtZXJhdG9yOiBpID0+IGRhdGFDb250YWluZXIudmFsdWVBdChpLCBudW1lcmF0b3JJZHgpLFxuICAgICAgZ2V0RGVub21pbmF0b3I6IGkgPT4gZGF0YUNvbnRhaW5lci52YWx1ZUF0KGksIGRlbm9taW5hdG9ySWR4KVxuICAgIH07XG4gIH1cblxuICByZXR1cm4gaSA9PiBmaWVsZC52YWx1ZUFjY2Vzc29yKHtpbmRleDogaX0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFZhbHVlQWdnckZ1bmMgPSAoXG4gIGZpZWxkOiBGaWVsZCB8IHN0cmluZyB8IG51bGwsXG4gIGFnZ3JlZ2F0aW9uOiBzdHJpbmcsXG4gIGRhdGFzZXQ6IEtlcGxlclRhYmxlTW9kZWw8YW55LCBhbnk+XG4pOiAoKGJpbjogQmluKSA9PiBudW1iZXIpID0+IHtcbiAgY29uc3Qge2RhdGFDb250YWluZXIsIGZpZWxkc30gPSBkYXRhc2V0O1xuXG4gIC8vIFRoZSBwYXNzZWQtaW4gZmllbGQgbWlnaHQgbm90IGhhdmUgYWxsIHRoZSBmaWVsZHMgc2V0IChlLmcuIHZhbHVlQWNjZXNzb3IpXG4gIGNvbnN0IGRhdGFzZXRGaWVsZCA9IGZpZWxkcy5maW5kKFxuICAgIGYgPT4gZmllbGQgJiYgKGYubmFtZSA9PT0gZmllbGQgfHwgZi5uYW1lID09PSAoZmllbGQgYXMgRmllbGQpLm5hbWUpXG4gICk7XG5cbiAgcmV0dXJuIGRhdGFzZXRGaWVsZCAmJiBhZ2dyZWdhdGlvblxuICAgID8gYmluID0+XG4gICAgICAgIGFnZ3JlZ2F0ZShcbiAgICAgICAgICBiaW4uaW5kZXhlcyxcbiAgICAgICAgICBnZXRBZ3JlZ2F0aW9uVHlwZShkYXRhc2V0RmllbGQsIGFnZ3JlZ2F0aW9uKSxcbiAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIGNhbiByZXR1cm4ge2dldE51bWVyYXRvciwgZ2V0RGVub21pbmF0b3J9XG4gICAgICAgICAgZ2V0QWdncmVnYXRpb25BY2Nlc3NvcihkYXRhc2V0RmllbGQsIGRhdGFDb250YWluZXIsIGZpZWxkcylcbiAgICAgICAgKVxuICAgIDogYmluID0+IGJpbi5jb3VudDtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRBZ2dyZWdhdGlvbk9wdGlvc25CYXNlZE9uRmllbGQgPSBmaWVsZCA9PiB7XG4gIGlmIChpc1BlcmNlbnRGaWVsZChmaWVsZCkpIHtcbiAgICAvLyBkb24ndCBzaG93IHN1bVxuICAgIHJldHVybiBUSU1FX0FHR1JFR0FUSU9OLmZpbHRlcigoe2lkfSkgPT4gaWQgIT09IEFHR1JFR0FUSU9OX1RZUEVTLnN1bSk7XG4gIH1cbiAgcmV0dXJuIFRJTUVfQUdHUkVHQVRJT047XG59O1xuXG5mdW5jdGlvbiBnZXREZWx0YShcbiAgYmluczogTGluZURhdHVtW10sXG4gIHk6IG51bWJlcixcbiAgaW50ZXJ2YWw6IFBsb3RUeXBlWydpbnRlcnZhbCddXG4pOiBQYXJ0aWFsPExpbmVEYXR1bT4gJiB7ZGVsdGE6ICdsYXN0JzsgcGN0OiBudW1iZXIgfCBudWxsfSB7XG4gIC8vIGlmIChXT1dbaW50ZXJ2YWxdKSByZXR1cm4gZ2V0V293KGJpbnMsIHksIGludGVydmFsKTtcbiAgY29uc3QgbGFzdEJpbiA9IGJpbnNbYmlucy5sZW5ndGggLSAxXTtcblxuICByZXR1cm4ge1xuICAgIGRlbHRhOiAnbGFzdCcsXG4gICAgcGN0OiBsYXN0QmluID8gZ2V0UGN0Q2hhbmdlKHksIGxhc3RCaW4ueSkgOiBudWxsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQY3RDaGFuZ2UoeTogdW5rbm93biwgeTA6IHVua25vd24pOiBudW1iZXIgfCBudWxsIHtcbiAgaWYgKE51bWJlci5pc0Zpbml0ZSh5KSAmJiBOdW1iZXIuaXNGaW5pdGUoeTApICYmIHkwICE9PSAwKSB7XG4gICAgcmV0dXJuICgoeSBhcyBudW1iZXIpIC0gKHkwIGFzIG51bWJlcikpIC8gKHkwIGFzIG51bWJlcik7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSBkYXRhc2V0c1xuICogQHBhcmFtIGZpbHRlclxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TGluZUNoYXJ0KGRhdGFzZXRzOiBEYXRhc2V0cywgZmlsdGVyOiBGaWx0ZXIpOiBMaW5lQ2hhcnQge1xuICBjb25zdCB7ZGF0YUlkLCB5QXhpcywgcGxvdFR5cGUsIGxpbmVDaGFydH0gPSBmaWx0ZXI7XG4gIGNvbnN0IHthZ2dyZWdhdGlvbiwgaW50ZXJ2YWx9ID0gcGxvdFR5cGU7XG4gIGNvbnN0IHNlcmllc0RhdGFJZCA9IGRhdGFJZFswXTtcbiAgY29uc3QgYmlucyA9IChmaWx0ZXIgYXMgVGltZVJhbmdlRmlsdGVyKS50aW1lQmlucz8uW3Nlcmllc0RhdGFJZF0/LltpbnRlcnZhbF07XG5cbiAgaWYgKFxuICAgIGxpbmVDaGFydCAmJlxuICAgIGxpbmVDaGFydC5hZ2dyZWdhdGlvbiA9PT0gYWdncmVnYXRpb24gJiZcbiAgICBsaW5lQ2hhcnQuaW50ZXJ2YWwgPT09IGludGVydmFsICYmXG4gICAgbGluZUNoYXJ0LnlBeGlzID09PSB5QXhpcz8ubmFtZSAmJlxuICAgIC8vIHdlIG5lZWQgdG8gbWFrZSBzdXJlIHdlIHZhbGlkYXRlIGJpbnMgYmVjYXVzZSBvZiBjcm9zcyBmaWx0ZXIgZGF0YSBjaGFuZ2VzXG4gICAgaXNFcXVhbChiaW5zLCBsaW5lQ2hhcnQ/LmJpbnMpXG4gICkge1xuICAgIC8vIGRvbid0IHVwZGF0ZSBsaW5lQ2hhcnQgaWYgcGxvdFR5cGUgaGFzbid0IGNoYW5nZVxuICAgIHJldHVybiBsaW5lQ2hhcnQ7XG4gIH1cblxuICBjb25zdCBkYXRhc2V0ID0gZGF0YXNldHNbc2VyaWVzRGF0YUlkXTtcbiAgY29uc3QgZ2V0WVZhbHVlID0gZ2V0VmFsdWVBZ2dyRnVuYyh5QXhpcywgYWdncmVnYXRpb24sIGRhdGFzZXQpO1xuXG4gIGNvbnN0IGluaXQ6IExpbmVEYXR1bVtdID0gW107XG4gIGNvbnN0IHNlcmllcyA9IChiaW5zIHx8IFtdKS5yZWR1Y2UoKGFjY3UsIGJpbiwgaSkgPT4ge1xuICAgIGNvbnN0IHkgPSBnZXRZVmFsdWUoYmluKTtcbiAgICBjb25zdCBkZWx0YSA9IGdldERlbHRhKGFjY3UsIHksIGludGVydmFsKTtcbiAgICBhY2N1LnB1c2goe1xuICAgICAgeDogYmluLngwLFxuICAgICAgeSxcbiAgICAgIC4uLmRlbHRhXG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3U7XG4gIH0sIGluaXQpO1xuXG4gIGNvbnN0IHlEb21haW4gPSBleHRlbnQ8e3k6IGFueX0+KHNlcmllcywgZCA9PiBkLnkpO1xuICBjb25zdCB4RG9tYWluID0gYmlucyA/IFtiaW5zWzBdLngwLCBiaW5zW2JpbnMubGVuZ3RoIC0gMV0ueDFdIDogW107XG5cbiAgLy8gdHJlYXQgbWlzc2luZyBkYXRhIGFzIGFub3RoZXIgc2VyaWVzXG4gIGNvbnN0IHNwbGl0ID0gc3BsaXRTZXJpZXMoc2VyaWVzKTtcbiAgY29uc3QgYWdnck5hbWUgPSBBR0dSRUdBVElPTl9OQU1FW2FnZ3JlZ2F0aW9uXTtcblxuICByZXR1cm4ge1xuICAgIC8vIEB0cy1pZ25vcmVcbiAgICB5RG9tYWluLFxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICB4RG9tYWluLFxuICAgIGludGVydmFsLFxuICAgIGFnZ3JlZ2F0aW9uLFxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBzZXJpZXM6IHNwbGl0LFxuICAgIHRpdGxlOiBgJHthZ2dyTmFtZX0keycgb2YgJ30ke3lBeGlzID8geUF4aXMubmFtZSA6ICdDb3VudCd9YCxcbiAgICBmaWVsZFR5cGU6IHlBeGlzID8geUF4aXMudHlwZSA6ICdpbnRlZ2VyJyxcbiAgICB5QXhpczogeUF4aXMgPyB5QXhpcy5uYW1lIDogbnVsbCxcbiAgICBhbGxUaW1lOiB7XG4gICAgICB0aXRsZTogYEFsbCBUaW1lIEF2ZXJhZ2VgLFxuICAgICAgdmFsdWU6IGFnZ3JlZ2F0ZShzZXJpZXMsIEFHR1JFR0FUSU9OX1RZUEVTLmF2ZXJhZ2UsIGQgPT4gZC55KVxuICAgIH0sXG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBiaW5zIGlzIEJpbnNbXSwgbm90IGEgQmlucyBtYXAuIFJlZmFjdG9yIHRvIHVzZSBjb3JyZWN0IHR5cGVzLlxuICAgIGJpbnNcbiAgfTtcbn1cblxuLy8gc3BsaXQgaW50byBtdWx0aXBsZSBzZXJpZXMgd2hlbiBzZWUgbWlzc2luZyBkYXRhXG5leHBvcnQgZnVuY3Rpb24gc3BsaXRTZXJpZXMoc2VyaWVzKSB7XG4gIGNvbnN0IGxpbmVzOiBhbnlbXSA9IFtdO1xuICBsZXQgdGVtcDogYW55W10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZXJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBkID0gc2VyaWVzW2ldO1xuICAgIGlmICghbm90TnVsbG9yVW5kZWZpbmVkKGQueSkgJiYgdGVtcC5sZW5ndGgpIHtcbiAgICAgIC8vIGVuZHMgdGVtcFxuICAgICAgbGluZXMucHVzaCh0ZW1wKTtcbiAgICAgIHRlbXAgPSBbXTtcbiAgICB9IGVsc2UgaWYgKG5vdE51bGxvclVuZGVmaW5lZChkLnkpKSB7XG4gICAgICB0ZW1wLnB1c2goZCk7XG4gICAgfVxuXG4gICAgaWYgKGkgPT09IHNlcmllcy5sZW5ndGggLSAxICYmIHRlbXAubGVuZ3RoKSB7XG4gICAgICBsaW5lcy5wdXNoKHRlbXApO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG1hcmtlcnMgPSBsaW5lcy5sZW5ndGggPiAxID8gc2VyaWVzLmZpbHRlcihkID0+IG5vdE51bGxvclVuZGVmaW5lZChkLnkpKSA6IFtdO1xuXG4gIHJldHVybiB7bGluZXMsIG1hcmtlcnN9O1xufVxuXG50eXBlIE1pblZpc1N0YXRlRm9yQW5pbWF0aW9uV2luZG93ID0ge1xuICBkYXRhc2V0czogRGF0YXNldHM7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gYWRqdXN0VmFsdWVUb0FuaW1hdGlvbldpbmRvdzxTIGV4dGVuZHMgTWluVmlzU3RhdGVGb3JBbmltYXRpb25XaW5kb3c+KFxuICBzdGF0ZTogUyxcbiAgZmlsdGVyOiBUaW1lUmFuZ2VGaWx0ZXJcbikge1xuICBjb25zdCB7XG4gICAgcGxvdFR5cGUsXG4gICAgdmFsdWU6IFt2YWx1ZTAsIHZhbHVlMV0sXG4gICAgYW5pbWF0aW9uV2luZG93XG4gIH0gPSBmaWx0ZXI7XG5cbiAgY29uc3QgaW50ZXJ2YWwgPSBwbG90VHlwZS5pbnRlcnZhbCB8fCBnZXRJbml0aWFsSW50ZXJ2YWwoZmlsdGVyLCBzdGF0ZS5kYXRhc2V0cyk7XG4gIGNvbnN0IGJpbnMgPSBnZXRUaW1lQmlucyhmaWx0ZXIsIHN0YXRlLmRhdGFzZXRzLCBpbnRlcnZhbCk7XG4gIGNvbnN0IGRhdGFzZXRCaW5zID0gYmlucyAmJiBPYmplY3Qua2V5cyhiaW5zKS5sZW5ndGggJiYgT2JqZWN0LnZhbHVlcyhiaW5zKVswXVtpbnRlcnZhbF07XG4gIGNvbnN0IHRocmVzaG9sZHMgPSAoZGF0YXNldEJpbnMgfHwgW10pLm1hcChiID0+IGIueDApO1xuXG4gIGxldCB2YWwwID0gdmFsdWUwO1xuICBsZXQgdmFsMSA9IHZhbHVlMTtcbiAgbGV0IGlkeDtcbiAgaWYgKGFuaW1hdGlvbldpbmRvdyA9PT0gQU5JTUFUSU9OX1dJTkRPVy5pbnRlcnZhbCkge1xuICAgIHZhbDAgPSBzbmFwVG9NYXJrcyh2YWx1ZTEsIHRocmVzaG9sZHMpO1xuICAgIGlkeCA9IHRocmVzaG9sZHMuaW5kZXhPZih2YWwwKTtcbiAgICB2YWwxID0gaWR4ID4gLTEgPyBkYXRhc2V0Qmluc1tpZHhdLngxIDogTmFOO1xuICB9IGVsc2Uge1xuICAgIC8vIGZpdCBjdXJyZW50IHZhbHVlIHRvIHdpbmRvd1xuICAgIHZhbDAgPSBzbmFwVG9NYXJrcyh2YWx1ZTAsIHRocmVzaG9sZHMpO1xuICAgIHZhbDEgPSBzbmFwVG9NYXJrcyh2YWx1ZTEsIHRocmVzaG9sZHMpO1xuXG4gICAgaWYgKHZhbDAgPT09IHZhbDEpIHtcbiAgICAgIGlkeCA9IHRocmVzaG9sZHMuaW5kZXhPZih2YWwwKTtcbiAgICAgIGlmIChpZHggPT09IHRocmVzaG9sZHMubGVuZ3RoIC0gMSkge1xuICAgICAgICB2YWwwID0gdGhyZXNob2xkc1tpZHggLSAxXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhbDEgPSB0aHJlc2hvbGRzW2lkeCArIDFdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHVwZGF0ZWRGaWx0ZXIgPSB7XG4gICAgLi4uZmlsdGVyLFxuICAgIHBsb3RUeXBlOiB7XG4gICAgICAuLi5maWx0ZXIucGxvdFR5cGUsXG4gICAgICBpbnRlcnZhbFxuICAgIH0sXG4gICAgdGltZUJpbnM6IGJpbnMsXG4gICAgdmFsdWU6IFt2YWwwLCB2YWwxXVxuICB9O1xuXG4gIHJldHVybiB1cGRhdGVkRmlsdGVyO1xufVxuXG4vKipcbiAqIENyZWF0ZSBvciB1cGRhdGUgY29sb3JzIGZvciBhIGZpbHRlciBwbG90XG4gKiBAcGFyYW0gZmlsdGVyXG4gKiBAcGFyYW0gZGF0YXNldHNcbiAqIEBwYXJhbSBvbGRDb2xvcnNCeURhdGFJZFxuICovXG5mdW5jdGlvbiBnZXRGaWx0ZXJQbG90Q29sb3JzQnlEYXRhSWQoZmlsdGVyLCBkYXRhc2V0cywgb2xkQ29sb3JzQnlEYXRhSWQpIHtcbiAgbGV0IGNvbG9yc0J5RGF0YUlkID0gb2xkQ29sb3JzQnlEYXRhSWQgfHwge307XG4gIGZvciAoY29uc3QgZGF0YUlkIG9mIGZpbHRlci5kYXRhSWQpIHtcbiAgICBpZiAoIWNvbG9yc0J5RGF0YUlkW2RhdGFJZF0gJiYgZGF0YXNldHNbZGF0YUlkXSkge1xuICAgICAgY29sb3JzQnlEYXRhSWQgPSB7XG4gICAgICAgIC4uLmNvbG9yc0J5RGF0YUlkLFxuICAgICAgICBbZGF0YUlkXTogcmdiVG9IZXgoZGF0YXNldHNbZGF0YUlkXS5jb2xvcilcbiAgICAgIH07XG4gICAgfVxuICB9XG4gIHJldHVybiBjb2xvcnNCeURhdGFJZDtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIGZpbHRlclxuICogQHBhcmFtIHBsb3RUeXBlXG4gKiBAcGFyYW0gZGF0YXNldHNcbiAqIEBwYXJhbSBkYXRhSWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVRpbWVGaWx0ZXJQbG90VHlwZShcbiAgZmlsdGVyOiBUaW1lUmFuZ2VGaWx0ZXIsXG4gIHBsb3RUeXBlOiBUaW1lUmFuZ2VGaWx0ZXJbJ3Bsb3RUeXBlJ10sXG4gIGRhdGFzZXRzOiBEYXRhc2V0cyxcbiAgZGF0YUlkPzogc3RyaW5nXG4pOiBUaW1lUmFuZ2VGaWx0ZXIge1xuICBsZXQgbmV4dEZpbHRlciA9IGZpbHRlcjtcbiAgbGV0IG5leHRQbG90VHlwZSA9IHBsb3RUeXBlO1xuICBpZiAodHlwZW9mIG5leHRQbG90VHlwZSAhPT0gJ29iamVjdCcgfHwgIW5leHRQbG90VHlwZS5hZ2dyZWdhdGlvbiB8fCAhbmV4dFBsb3RUeXBlLmludGVydmFsKSB7XG4gICAgbmV4dFBsb3RUeXBlID0gZ2V0RGVmYXVsdFBsb3RUeXBlKGZpbHRlciwgZGF0YXNldHMpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5kYXRhSWQubGVuZ3RoID4gMSkge1xuICAgIG5leHRQbG90VHlwZSA9IHtcbiAgICAgIC4uLm5leHRQbG90VHlwZSxcbiAgICAgIGNvbG9yc0J5RGF0YUlkOiBnZXRGaWx0ZXJQbG90Q29sb3JzQnlEYXRhSWQoZmlsdGVyLCBkYXRhc2V0cywgbmV4dFBsb3RUeXBlLmNvbG9yc0J5RGF0YUlkKVxuICAgIH07XG4gIH1cbiAgbmV4dEZpbHRlciA9IHtcbiAgICAuLi5uZXh0RmlsdGVyLFxuICAgIHBsb3RUeXBlOiBuZXh0UGxvdFR5cGVcbiAgfTtcblxuICBjb25zdCBiaW5zID0gZ2V0VGltZUJpbnMobmV4dEZpbHRlciwgZGF0YXNldHMsIG5leHRQbG90VHlwZS5pbnRlcnZhbCk7XG5cbiAgbmV4dEZpbHRlciA9IHtcbiAgICAuLi5uZXh0RmlsdGVyLFxuICAgIHRpbWVCaW5zOiBiaW5zXG4gIH07XG5cbiAgaWYgKHBsb3RUeXBlLnR5cGUgPT09IFBMT1RfVFlQRVMuaGlzdG9ncmFtKSB7XG4gICAgLy8gSGlzdG9ncmFtIGlzIGNhbGN1bGF0ZWQgYW5kIG1lbW9pemVkIGluIHRoZSBjaGFydCBpdHNlbGZcbiAgfSBlbHNlIGlmIChwbG90VHlwZS50eXBlID09PSBQTE9UX1RZUEVTLmxpbmVDaGFydCkge1xuICAgIC8vIHdlIHNob3VsZCBiZSBhYmxlIHRvIG1vdmUgdGhpcyBpbnRvIGl0cyBvd24gY29tcG9uZW50IHNvIHJlYWN0IHdpbGwgZG8gdGhlIHNoYWxsb3cgY29tcGFyaXNvbiBmb3IgdXMuXG4gICAgbmV4dEZpbHRlciA9IHtcbiAgICAgIC4uLm5leHRGaWx0ZXIsXG4gICAgICBsaW5lQ2hhcnQ6IGdldExpbmVDaGFydChkYXRhc2V0cywgbmV4dEZpbHRlcilcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIG5leHRGaWx0ZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRSYW5nZUZpbHRlckJpbnMoZmlsdGVyLCBkYXRhc2V0cywgbnVtQmlucykge1xuICBjb25zdCB7ZG9tYWlufSA9IGZpbHRlcjtcbiAgaWYgKCFmaWx0ZXIuZGF0YUlkKSByZXR1cm4gbnVsbDtcblxuICByZXR1cm4gZmlsdGVyLmRhdGFJZC5yZWR1Y2UoKGFjYywgZGF0YUlkLCBkYXRhc2V0SWR4KSA9PiB7XG4gICAgaWYgKGZpbHRlci5iaW5zPy5bZGF0YUlkXSkge1xuICAgICAgLy8gZG9uJ3QgcmVjYWxjdWxhdGUgYmluc1xuICAgICAgYWNjW2RhdGFJZF0gPSBmaWx0ZXIuYmluc1tkYXRhSWRdO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9XG4gICAgY29uc3QgZmllbGROYW1lID0gZmlsdGVyLm5hbWVbZGF0YXNldElkeF07XG4gICAgaWYgKGRhdGFJZCAmJiBmaWVsZE5hbWUpIHtcbiAgICAgIGNvbnN0IGRhdGFzZXQgPSBkYXRhc2V0c1tkYXRhSWRdO1xuICAgICAgY29uc3QgZmllbGQgPSBkYXRhc2V0Py5nZXRDb2x1bW5GaWVsZChmaWVsZE5hbWUpO1xuICAgICAgaWYgKGRhdGFzZXQgJiYgZmllbGQpIHtcbiAgICAgICAgY29uc3QgaW5kZXhlcyA9IHJ1bkdwdUZpbHRlckZvclBsb3QoZGF0YXNldCwgZmlsdGVyKTtcbiAgICAgICAgY29uc3QgdmFsdWVBY2Nlc3NvciA9IGluZGV4ID0+IGZpZWxkLnZhbHVlQWNjZXNzb3Ioe2luZGV4fSk7XG4gICAgICAgIGFjY1tkYXRhSWRdID0gaGlzdG9ncmFtRnJvbURvbWFpbihkb21haW4sIGluZGV4ZXMsIG51bUJpbnMsIHZhbHVlQWNjZXNzb3IpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYWNjO1xuICB9LCB7fSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVSYW5nZUZpbHRlclBsb3RUeXBlKFxuICBmaWx0ZXI6IFJhbmdlRmlsdGVyLFxuICBwbG90VHlwZTogUmFuZ2VGaWx0ZXJbJ3Bsb3RUeXBlJ10sXG4gIGRhdGFzZXRzOiBEYXRhc2V0cyxcbiAgZGF0YUlkPzogc3RyaW5nXG4pOiBSYW5nZUZpbHRlciB7XG4gIGNvbnN0IG5leHRGaWx0ZXIgPSB7XG4gICAgLi4uZmlsdGVyLFxuICAgIHBsb3RUeXBlXG4gIH07XG5cbiAgLy8gaWYgKGRhdGFJZCkge1xuICAvLyAgIC8vIGNsZWFyIGJpbnNcbiAgLy8gICBuZXh0RmlsdGVyID0ge1xuICAvLyAgICAgLi4ubmV4dEZpbHRlcixcbiAgLy8gICAgIGJpbnM6IHtcbiAgLy8gICAgICAgLi4ubmV4dEZpbHRlci5iaW5zLFxuICAvLyAgICAgICBbZGF0YUlkXTogbnVsbFxuICAvLyAgICAgfVxuICAvLyAgIH07XG4gIC8vIH1cblxuICByZXR1cm4ge1xuICAgIC4uLmZpbHRlcixcbiAgICBwbG90VHlwZSxcbiAgICBiaW5zOiBnZXRSYW5nZUZpbHRlckJpbnMobmV4dEZpbHRlciwgZGF0YXNldHMsIEJJTlMpXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDaGFydFRpdGxlKFxuICB5QXhpczoge2Rpc3BsYXlOYW1lPzogc3RyaW5nfSxcbiAgcGxvdFR5cGU6IHthZ2dyZWdhdGlvbjogc3RyaW5nfVxuKTogc3RyaW5nIHtcbiAgY29uc3QgeUF4aXNOYW1lID0geUF4aXM/LmRpc3BsYXlOYW1lO1xuICBjb25zdCB7YWdncmVnYXRpb259ID0gcGxvdFR5cGU7XG5cbiAgaWYgKHlBeGlzTmFtZSkge1xuICAgIHJldHVybiBjYXBpdGFsaXplRmlyc3RMZXR0ZXIoYCR7YWdncmVnYXRpb259ICR7eUF4aXNOYW1lfSBvdmVyIFRpbWVgKTtcbiAgfVxuXG4gIHJldHVybiBgQ291bnQgb2YgUm93cyBvdmVyIFRpbWVgO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGVmYXVsdFBsb3RUeXBlKGZpbHRlciwgZGF0YXNldHMpIHtcbiAgY29uc3QgaW50ZXJ2YWwgPSBnZXRJbml0aWFsSW50ZXJ2YWwoZmlsdGVyLCBkYXRhc2V0cyk7XG4gIGNvbnN0IGRlZmF1bHRUaW1lRm9ybWF0ID0gZ2V0RGVmYXVsdFRpbWVGb3JtYXQoaW50ZXJ2YWwpO1xuICByZXR1cm4ge1xuICAgIGludGVydmFsLFxuICAgIGRlZmF1bHRUaW1lRm9ybWF0LFxuICAgIHR5cGU6IFBMT1RfVFlQRVMuaGlzdG9ncmFtLFxuICAgIGFnZ3JlZ2F0aW9uOiBBR0dSRUdBVElPTl9UWVBFUy5zdW1cbiAgfTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEsUUFBQSxHQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBQyxzQkFBQSxDQUFBRixPQUFBO0FBQ0EsSUFBQUcsS0FBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksT0FBQSxHQUFBRixzQkFBQSxDQUFBRixPQUFBO0FBY0EsSUFBQUssWUFBQSxHQUFBTCxPQUFBO0FBQ0EsSUFBQU0sVUFBQSxHQUFBTixPQUFBO0FBVUEsSUFBQU8sVUFBQSxHQUFBUCxPQUFBO0FBQ0EsSUFBQVEsWUFBQSxHQUFBUixPQUFBO0FBQ0EsSUFBQVMsUUFBQSxHQUFBVCxPQUFBO0FBQ0EsSUFBQVUsT0FBQSxHQUFBVixPQUFBO0FBQ0EsSUFBQVcsV0FBQSxHQUFBWCxPQUFBO0FBQXVDLFNBQUFZLDJCQUFBQyxDQUFBLEVBQUFDLENBQUEsUUFBQUMsQ0FBQSx5QkFBQUMsTUFBQSxJQUFBSCxDQUFBLENBQUFHLE1BQUEsQ0FBQUMsUUFBQSxLQUFBSixDQUFBLHFCQUFBRSxDQUFBLFFBQUFHLEtBQUEsQ0FBQUMsT0FBQSxDQUFBTixDQUFBLE1BQUFFLENBQUEsR0FBQUssMkJBQUEsQ0FBQVAsQ0FBQSxNQUFBQyxDQUFBLElBQUFELENBQUEsdUJBQUFBLENBQUEsQ0FBQVEsTUFBQSxJQUFBTixDQUFBLEtBQUFGLENBQUEsR0FBQUUsQ0FBQSxPQUFBTyxFQUFBLE1BQUFDLENBQUEsWUFBQUEsRUFBQSxlQUFBQyxDQUFBLEVBQUFELENB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
|