kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
325 lines (309 loc) • 39.1 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TileTimeInterval = exports.TIME_INTERVALS_ORDERED = exports.TIMELINE_MODES = exports.SAMPLE_TIMELINE = exports.LayerToFilterTimeInterval = void 0;
exports.filterIntervalOptions = filterIntervalOptions;
exports.getFilterMappedValue = getFilterMappedValue;
exports.getInitialInterval = getInitialInterval;
exports.getIntervalByTicks = getIntervalByTicks;
exports.getTimelineFromFilter = exports.getTimelineFromAnimationConfig = void 0;
exports.intervalToFunction = intervalToFunction;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _d3Array = require("d3-array");
var _moment = _interopRequireDefault(require("moment"));
var _constants = require("@kepler.gl/constants");
var _commonUtils = require("@kepler.gl/common-utils");
var _aggregation = require("./aggregation");
var _plot = require("./plot");
// SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
var TIMELINE_MODES = exports.TIMELINE_MODES = {
inner: 'inner',
outer: 'outer'
};
var TileTimeInterval = exports.TileTimeInterval = {
YEAR: 'Y',
MONTH: 'M',
DAY: 'D',
HOUR: 'H',
MINUTE: 'T'
};
var TIME_INTERVALS_ORDERED = exports.TIME_INTERVALS_ORDERED = [TileTimeInterval.MINUTE, TileTimeInterval.HOUR, TileTimeInterval.DAY, TileTimeInterval.MONTH, TileTimeInterval.YEAR];
var LayerToFilterTimeInterval = exports.LayerToFilterTimeInterval = (0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])({}, TileTimeInterval.MINUTE, _constants.INTERVAL['1-minute']), TileTimeInterval.HOUR, _constants.INTERVAL['1-hour']), TileTimeInterval.DAY, _constants.INTERVAL['1-day']), TileTimeInterval.MONTH, _constants.INTERVAL['1-month']), TileTimeInterval.YEAR, _constants.INTERVAL['1-year']);
var SAMPLE_TIMELINE = exports.SAMPLE_TIMELINE = {
// value: [15], // represent 15% of the all width
value: [5, 15],
// represent start at 5% and ends at 15%
domain: [1, 100],
// represent the total domain
speed: 1,
enableInteraction: false,
// can use interact with this timeline
isAnimating: false,
step: null,
// @todo: giuseppe coverType: 'inner' | 'outer'
mode: TIMELINE_MODES.inner
// ....
};
var getTimelineFromAnimationConfig = exports.getTimelineFromAnimationConfig = function getTimelineFromAnimationConfig(animationConfig) {
var currentTime = animationConfig.currentTime,
domain = animationConfig.domain,
speed = animationConfig.speed,
isAnimating = animationConfig.isAnimating,
timeSteps = animationConfig.timeSteps,
defaultTimeFormat = animationConfig.defaultTimeFormat,
timeFormat = animationConfig.timeFormat,
timezone = animationConfig.timezone;
return {
// @ts-expect-error
value: (0, _commonUtils.toArray)(currentTime),
enableInteraction: true,
domain: domain,
speed: speed,
isAnimating: isAnimating || false,
timeSteps: timeSteps,
defaultTimeFormat: defaultTimeFormat,
timeFormat: timeFormat,
timezone: timezone,
timeBins: null,
marks: null
};
};
// check if the data inherent default time interval
// https://github.com/d3/d3-scale/blob/732ed4b1cd5c643700571d1089c7deb8472242a6/src/time.js#L69
// given number of ticks, calculate a reasonable interval
function getIntervalByTicks(ticks, start, stop) {
if (ticks === null) ticks = 10;
var tickIntervals = Object.values(_constants.TICK_INTERVALS);
var interval;
var step;
// If a desired tick count is specified, pick a reasonable tick interval
// based on the extent of the domain and a rough estimate of tick size.
// Otherwise, assume interval is already a time interval and use it.
if (typeof ticks === 'number') {
var target = Math.abs(stop - start) / ticks;
var i = (0, _d3Array.bisector)(function (d) {
return d.duration;
}).right(tickIntervals, target);
if (i === tickIntervals.length) {
step = (0, _d3Array.tickStep)(start / _constants.durationYear, stop / _constants.durationYear, ticks);
interval = 'year';
} else if (i) {
var tickInterval = tickIntervals[target / tickIntervals[i - 1].duration < tickIntervals[i].duration / target ? i - 1 : i];
// @ts-ignore TODO/ib
step = tickInterval.step;
// @ts-ignore TODO/ib
interval = tickInterval.interval;
} else {
step = Math.max((0, _d3Array.tickStep)(start, stop, ticks), 1);
interval = 'millisecond';
}
}
return "".concat(step, "-").concat(interval);
}
// get a number of unique samples
function getUniqueSamples(values, count) {
var i = -1;
var samples = [];
var sampleMap = {};
while (i++ < values.length && samples.length < count) {
var v = values[i];
if (v !== undefined && v !== null && !sampleMap[v]) {
sampleMap[v] = true;
samples.push(v);
}
}
return Object.values(samples);
}
/**
* Given an array of epoch timestamp. sort it, if number of element
* share the same time interval exceed thresholf, and total steps smaller than 100, return it, else return null
* @param values
*/
function detectInterval() {
var values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var domain = arguments.length > 1 ? arguments[1] : undefined;
var maxSteps = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10;
var threshold = 0.7;
var sorted = values.sort(_d3Array.ascending);
// get first 100 unique sorted ts
var samples = getUniqueSamples(sorted, 100);
if (samples.length < 2) {
return null;
}
// get all intervals
var intervals = samples.reduce(function (accu, d, i) {
if (i > 0) {
var duration = _moment["default"].duration(_moment["default"].utc(samples[i]).diff(_moment["default"].utc(samples[i - 1])));
var _getDurationUnit = getDurationUnit(duration),
_getDurationUnit2 = (0, _slicedToArray2["default"])(_getDurationUnit, 2),
dur = _getDurationUnit2[0],
c = _getDurationUnit2[1];
accu.push("".concat(c, "-").concat(dur));
}
return accu;
}, []);
// find the most occured interval
var occur = (0, _aggregation.getFrequency)(intervals);
var maxOccr = Object.keys(occur).reduce(function (prev, key) {
return occur[prev] >= occur[key] ? prev : key;
}, Object.keys(occur)[0]);
// if occurance passed threshold
var mostOccur = occur[maxOccr] / intervals.length;
if (mostOccur >= threshold) {
var _maxOccr$split = maxOccr.split('-'),
_maxOccr$split2 = (0, _slicedToArray2["default"])(_maxOccr$split, 2),
step = _maxOccr$split2[0],
dur = _maxOccr$split2[1];
var durationSecond = _constants.DURATIONS[dur] * parseInt(step); // eslint-disable-line radix
var totalSteps = (domain[1] - domain[0]) / durationSecond;
if (totalSteps < maxSteps) {
// duration function is .days interval is day
return maxOccr.substring(0, maxOccr.length - 1);
}
}
return null;
}
/**
* mappedValue is saved to dataset.fields.filterProps
* @param dataset {KeplerTable}
* @param filter
*/
function getFilterMappedValue(dataset, filter) {
var dataId = dataset.id;
var fieldName = filter.name[filter.dataId.indexOf(dataId)];
var field = dataset.getColumnField(fieldName);
if (!field) {
// eslint-disable-next-line no-console, no-undef
console.warn("field ".concat(fieldName, " does not exist on dataset"));
return null;
}
var mappedValue = (field.filterProps || {}).mappedValue;
if (!mappedValue) {
// eslint-disable-next-line no-console, no-undef
console.warn("mappedValue doesnt exist on filter field ".concat(filter.name));
return null;
}
return mappedValue;
}
/**
* Find the round unit of given durmostOccurtion: x years | months | days
* @param duration
*/
function getDurationUnit(duration) {
var durFuncs = Object.keys(_constants.DURATIONS);
for (var i = 0; i < durFuncs.length; i++) {
var c = duration[durFuncs[i]]();
if (c > 0) {
return [durFuncs[i], c];
}
}
return ['milliseconds', 1];
}
function intervalToFunction(id) {
var _id$split = id.split('-'),
_id$split2 = (0, _slicedToArray2["default"])(_id$split, 2),
stepStr = _id$split2[0],
interval = _id$split2[1];
var step = parseInt(stepStr); // eslint-disable-line radix
if (!step) {
// eslint-disable-next-line no-console, no-undef
console.warn('Step is not an integer');
return null;
}
if (!_constants.TIME_INTERVALS[interval]) {
// eslint-disable-next-line no-console, no-undef
console.warn("Undefined time interval ".concat(interval));
return null;
}
return _constants.TIME_INTERVALS[interval].every(step);
}
/**
* Get initial interval from filter and datasets
* @param filter
* @param datasets
* @returns
*/
function getInitialInterval(filter, datasets) {
var domain = filter.domain;
var mergeMappedValue = filter.dataId.reduce(function (accu, dataId) {
var mappedValue = getFilterMappedValue(datasets[dataId], filter);
if (!mappedValue) {
return accu;
}
for (var i = 0; i < mappedValue.length; i++) {
accu.push(mappedValue[i]);
}
return accu;
}, []);
// check if data has predefined interval
var interval = detectInterval(mergeMappedValue, domain);
if (!interval) {
// @ts-expect-error need better types for domain
var _domain = (0, _slicedToArray2["default"])(domain, 2),
t0 = _domain[0],
t1 = _domain[1];
interval = getIntervalByTicks(_constants.BINS_LARGE, t0, t1);
}
return interval;
}
// Filter interval options by time filter domain
// max number of interval is 1000
/**
*
* @param options
* @param domain
*/
function filterIntervalOptions(options, domain) {
var maxBins = 1000;
var minBins = 2;
var timeSpan = domain[1] - domain[0];
return options.filter(function (op) {
var id = op.id;
if (!_constants.TICK_INTERVALS[id]) {
return false;
}
var interval = _constants.TICK_INTERVALS[id];
// rough count on bins
var count = timeSpan / (interval.step * interval.duration);
return count >= minBins && count <= maxBins;
});
}
/**
* Get timeline from filter
* @param filter TimeRangeFilter filter
* @returns Timeline
*/
var getTimelineFromFilter = exports.getTimelineFromFilter = function getTimelineFromFilter(filter) {
var value = filter.value,
domain = filter.domain,
speed = filter.speed,
isAnimating = filter.isAnimating,
step = filter.step,
timeSteps = filter.timeSteps,
defaultTimeFormat = filter.defaultTimeFormat,
timeFormat = filter.timeFormat,
timezone = filter.timezone,
timeBins = filter.timeBins,
animationWindow = filter.animationWindow,
plotType = filter.plotType;
return {
value: value,
enableInteraction: true,
domain: domain,
speed: speed,
isAnimating: isAnimating,
step: step,
timeSteps: timeSteps,
defaultTimeFormat: defaultTimeFormat,
timeFormat: timeFormat,
timezone: timezone,
timeBins: timeBins,
animationWindow: animationWindow,
marks: (0, _plot.getBinThresholds)(plotType === null || plotType === void 0 ? void 0 : plotType.interval, domain)
};
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZDNBcnJheSIsInJlcXVpcmUiLCJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9jb25zdGFudHMiLCJfY29tbW9uVXRpbHMiLCJfYWdncmVnYXRpb24iLCJfcGxvdCIsIlRJTUVMSU5FX01PREVTIiwiZXhwb3J0cyIsImlubmVyIiwib3V0ZXIiLCJUaWxlVGltZUludGVydmFsIiwiWUVBUiIsIk1PTlRIIiwiREFZIiwiSE9VUiIsIk1JTlVURSIsIlRJTUVfSU5URVJWQUxTX09SREVSRUQiLCJMYXllclRvRmlsdGVyVGltZUludGVydmFsIiwiX2RlZmluZVByb3BlcnR5MiIsIklOVEVSVkFMIiwiU0FNUExFX1RJTUVMSU5FIiwidmFsdWUiLCJkb21haW4iLCJzcGVlZCIsImVuYWJsZUludGVyYWN0aW9uIiwiaXNBbmltYXRpbmciLCJzdGVwIiwibW9kZSIsImdldFRpbWVsaW5lRnJvbUFuaW1hdGlvbkNvbmZpZyIsImFuaW1hdGlvbkNvbmZpZyIsImN1cnJlbnRUaW1lIiwidGltZVN0ZXBzIiwiZGVmYXVsdFRpbWVGb3JtYXQiLCJ0aW1lRm9ybWF0IiwidGltZXpvbmUiLCJ0b0FycmF5IiwidGltZUJpbnMiLCJtYXJrcyIsImdldEludGVydmFsQnlUaWNrcyIsInRpY2tzIiwic3RhcnQiLCJzdG9wIiwidGlja0ludGVydmFscyIsIk9iamVjdCIsInZhbHVlcyIsIlRJQ0tfSU5URVJWQUxTIiwiaW50ZXJ2YWwiLCJ0YXJnZXQiLCJNYXRoIiwiYWJzIiwiaSIsImJpc2VjdG9yIiwiZCIsImR1cmF0aW9uIiwicmlnaHQiLCJsZW5ndGgiLCJ0aWNrU3RlcCIsImR1cmF0aW9uWWVhciIsInRpY2tJbnRlcnZhbCIsIm1heCIsImNvbmNhdCIsImdldFVuaXF1ZVNhbXBsZXMiLCJjb3VudCIsInNhbXBsZXMiLCJzYW1wbGVNYXAiLCJ2IiwidW5kZWZpbmVkIiwicHVzaCIsImRldGVjdEludGVydmFsIiwiYXJndW1lbnRzIiwibWF4U3RlcHMiLCJ0aHJlc2hvbGQiLCJzb3J0ZWQiLCJzb3J0IiwiYXNjZW5kaW5nIiwiaW50ZXJ2YWxzIiwicmVkdWNlIiwiYWNjdSIsIm1vbWVudCIsInV0YyIsImRpZmYiLCJfZ2V0RHVyYXRpb25Vbml0IiwiZ2V0RHVyYXRpb25Vbml0IiwiX2dldER1cmF0aW9uVW5pdDIiLCJfc2xpY2VkVG9BcnJheTIiLCJkdXIiLCJjIiwib2NjdXIiLCJnZXRGcmVxdWVuY3kiLCJtYXhPY2NyIiwia2V5cyIsInByZXYiLCJrZXkiLCJtb3N0T2NjdXIiLCJfbWF4T2NjciRzcGxpdCIsInNwbGl0IiwiX21heE9jY3Ikc3BsaXQyIiwiZHVyYXRpb25TZWNvbmQiLCJEVVJBVElPTlMiLCJwYXJzZUludCIsInRvdGFsU3RlcHMiLCJzdWJzdHJpbmciLCJnZXRGaWx0ZXJNYXBwZWRWYWx1ZSIsImRhdGFzZXQiLCJmaWx0ZXIiLCJkYXRhSWQiLCJpZCIsImZpZWxkTmFtZSIsIm5hbWUiLCJpbmRleE9mIiwiZmllbGQiLCJnZXRDb2x1bW5GaWVsZCIsImNvbnNvbGUiLCJ3YXJuIiwibWFwcGVkVmFsdWUiLCJmaWx0ZXJQcm9wcyIsImR1ckZ1bmNzIiwiaW50ZXJ2YWxUb0Z1bmN0aW9uIiwiX2lkJHNwbGl0IiwiX2lkJHNwbGl0MiIsInN0ZXBTdHIiLCJUSU1FX0lOVEVSVkFMUyIsImV2ZXJ5IiwiZ2V0SW5pdGlhbEludGVydmFsIiwiZGF0YXNldHMiLCJtZXJnZU1hcHBlZFZhbHVlIiwiX2RvbWFpbiIsInQwIiwidDEiLCJCSU5TX0xBUkdFIiwiZmlsdGVySW50ZXJ2YWxPcHRpb25zIiwib3B0aW9ucyIsIm1heEJpbnMiLCJtaW5CaW5zIiwidGltZVNwYW4iLCJvcCIsImdldFRpbWVsaW5lRnJvbUZpbHRlciIsImFuaW1hdGlvbldpbmRvdyIsInBsb3RUeXBlIiwiZ2V0QmluVGhyZXNob2xkcyJdLCJzb3VyY2VzIjpbIi4uL3NyYy90aW1lLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCB7YXNjZW5kaW5nLCBiaXNlY3RvciwgdGlja1N0ZXB9IGZyb20gJ2QzLWFycmF5JztcbmltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcblxuaW1wb3J0IHtcbiAgVElDS19JTlRFUlZBTFMsXG4gIEJJTlNfTEFSR0UsXG4gIERVUkFUSU9OUyxcbiAgVElNRV9JTlRFUlZBTFMsXG4gIGR1cmF0aW9uWWVhcixcbiAgSU5URVJWQUwsXG4gIFRpY2tJbnRlcnZhbFxufSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5pbXBvcnQge3RvQXJyYXl9IGZyb20gJ0BrZXBsZXIuZ2wvY29tbW9uLXV0aWxzJztcbmltcG9ydCB7QW5pbWF0aW9uQ29uZmlnLCBUaW1lbGluZSwgVGltZVJhbmdlRmlsdGVyLCBGaWx0ZXJ9IGZyb20gJ0BrZXBsZXIuZ2wvdHlwZXMnO1xuXG5pbXBvcnQge2dldEZyZXF1ZW5jeX0gZnJvbSAnLi9hZ2dyZWdhdGlvbic7XG5pbXBvcnQge2dldEJpblRocmVzaG9sZHN9IGZyb20gJy4vcGxvdCc7XG5pbXBvcnQge0tlcGxlclRhYmxlTW9kZWx9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgY29uc3QgVElNRUxJTkVfTU9ERVMgPSB7XG4gIGlubmVyOiAnaW5uZXInLFxuICBvdXRlcjogJ291dGVyJ1xufTtcblxuZXhwb3J0IGNvbnN0IFRpbGVUaW1lSW50ZXJ2YWwgPSB7XG4gIFlFQVI6ICdZJyxcbiAgTU9OVEg6ICdNJyxcbiAgREFZOiAnRCcsXG4gIEhPVVI6ICdIJyxcbiAgTUlOVVRFOiAnVCdcbn07XG5cbmV4cG9ydCBjb25zdCBUSU1FX0lOVEVSVkFMU19PUkRFUkVEID0gW1xuICBUaWxlVGltZUludGVydmFsLk1JTlVURSxcbiAgVGlsZVRpbWVJbnRlcnZhbC5IT1VSLFxuICBUaWxlVGltZUludGVydmFsLkRBWSxcbiAgVGlsZVRpbWVJbnRlcnZhbC5NT05USCxcbiAgVGlsZVRpbWVJbnRlcnZhbC5ZRUFSXG5dO1xuXG5leHBvcnQgY29uc3QgTGF5ZXJUb0ZpbHRlclRpbWVJbnRlcnZhbCA9IHtcbiAgW1RpbGVUaW1lSW50ZXJ2YWwuTUlOVVRFXTogSU5URVJWQUxbJzEtbWludXRlJ10sXG4gIFtUaWxlVGltZUludGVydmFsLkhPVVJdOiBJTlRFUlZBTFsnMS1ob3VyJ10sXG4gIFtUaWxlVGltZUludGVydmFsLkRBWV06IElOVEVSVkFMWycxLWRheSddLFxuICBbVGlsZVRpbWVJbnRlcnZhbC5NT05USF06IElOVEVSVkFMWycxLW1vbnRoJ10sXG4gIFtUaWxlVGltZUludGVydmFsLllFQVJdOiBJTlRFUlZBTFsnMS15ZWFyJ11cbn07XG5cbmV4cG9ydCBjb25zdCBTQU1QTEVfVElNRUxJTkUgPSB7XG4gIC8vIHZhbHVlOiBbMTVdLCAvLyByZXByZXNlbnQgMTUlIG9mIHRoZSBhbGwgd2lkdGhcbiAgdmFsdWU6IFs1LCAxNV0sIC8vIHJlcHJlc2VudCBzdGFydCBhdCA1JSBhbmQgZW5kcyBhdCAxNSVcbiAgZG9tYWluOiBbMSwgMTAwXSwgLy8gcmVwcmVzZW50IHRoZSB0b3RhbCBkb21haW5cbiAgc3BlZWQ6IDEsXG4gIGVuYWJsZUludGVyYWN0aW9uOiBmYWxzZSwgLy8gY2FuIHVzZSBpbnRlcmFjdCB3aXRoIHRoaXMgdGltZWxpbmVcbiAgaXNBbmltYXRpbmc6IGZhbHNlLFxuICBzdGVwOiBudWxsLFxuICAvLyBAdG9kbzogZ2l1c2VwcGUgY292ZXJUeXBlOiAnaW5uZXInIHwgJ291dGVyJ1xuICBtb2RlOiBUSU1FTElORV9NT0RFUy5pbm5lclxuICAvLyAgLi4uLlxufTtcblxuZXhwb3J0IGNvbnN0IGdldFRpbWVsaW5lRnJvbUFuaW1hdGlvbkNvbmZpZyA9IChhbmltYXRpb25Db25maWc6IEFuaW1hdGlvbkNvbmZpZyk6IFRpbWVsaW5lID0+IHtcbiAgY29uc3Qge1xuICAgIGN1cnJlbnRUaW1lLFxuICAgIGRvbWFpbixcbiAgICBzcGVlZCxcbiAgICBpc0FuaW1hdGluZyxcbiAgICB0aW1lU3RlcHMsXG4gICAgZGVmYXVsdFRpbWVGb3JtYXQsXG4gICAgdGltZUZvcm1hdCxcbiAgICB0aW1lem9uZVxuICB9ID0gYW5pbWF0aW9uQ29uZmlnO1xuXG4gIHJldHVybiB7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgIHZhbHVlOiB0b0FycmF5KGN1cnJlbnRUaW1lKSxcbiAgICBlbmFibGVJbnRlcmFjdGlvbjogdHJ1ZSxcbiAgICBkb21haW4sXG4gICAgc3BlZWQsXG4gICAgaXNBbmltYXRpbmc6IGlzQW5pbWF0aW5nIHx8IGZhbHNlLFxuICAgIHRpbWVTdGVwcyxcbiAgICBkZWZhdWx0VGltZUZvcm1hdCxcbiAgICB0aW1lRm9ybWF0LFxuICAgIHRpbWV6b25lLFxuICAgIHRpbWVCaW5zOiBudWxsLFxuICAgIG1hcmtzOiBudWxsXG4gIH07XG59O1xuXG4vLyBjaGVjayBpZiB0aGUgZGF0YSBpbmhlcmVudCBkZWZhdWx0IHRpbWUgaW50ZXJ2YWxcblxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2QzL2QzLXNjYWxlL2Jsb2IvNzMyZWQ0YjFjZDVjNjQzNzAwNTcxZDEwODljN2RlYjg0NzIyNDJhNi9zcmMvdGltZS5qcyNMNjlcbi8vIGdpdmVuIG51bWJlciBvZiB0aWNrcywgY2FsY3VsYXRlIGEgcmVhc29uYWJsZSBpbnRlcnZhbFxuZXhwb3J0IGZ1bmN0aW9uIGdldEludGVydmFsQnlUaWNrcyh0aWNrcywgc3RhcnQsIHN0b3ApIHtcbiAgaWYgKHRpY2tzID09PSBudWxsKSB0aWNrcyA9IDEwO1xuICBjb25zdCB0aWNrSW50ZXJ2YWxzID0gT2JqZWN0LnZhbHVlcyhUSUNLX0lOVEVSVkFMUyk7XG4gIGxldCBpbnRlcnZhbDtcbiAgbGV0IHN0ZXA7XG4gIC8vIElmIGEgZGVzaXJlZCB0aWNrIGNvdW50IGlzIHNwZWNpZmllZCwgcGljayBhIHJlYXNvbmFibGUgdGljayBpbnRlcnZhbFxuICAvLyBiYXNlZCBvbiB0aGUgZXh0ZW50IG9mIHRoZSBkb21haW4gYW5kIGEgcm91Z2ggZXN0aW1hdGUgb2YgdGljayBzaXplLlxuICAvLyBPdGhlcndpc2UsIGFzc3VtZSBpbnRlcnZhbCBpcyBhbHJlYWR5IGEgdGltZSBpbnRlcnZhbCBhbmQgdXNlIGl0LlxuICBpZiAodHlwZW9mIHRpY2tzID09PSAnbnVtYmVyJykge1xuICAgIGNvbnN0IHRhcmdldCA9IE1hdGguYWJzKHN0b3AgLSBzdGFydCkgLyB0aWNrcztcbiAgICBjb25zdCBpID0gYmlzZWN0b3IoKGQ6IFRpY2tJbnRlcnZhbCkgPT4gZC5kdXJhdGlvbikucmlnaHQodGlja0ludGVydmFscywgdGFyZ2V0KTtcbiAgICBpZiAoaSA9PT0gdGlja0ludGVydmFscy5sZW5ndGgpIHtcbiAgICAgIHN0ZXAgPSB0aWNrU3RlcChzdGFydCAvIGR1cmF0aW9uWWVhciwgc3RvcCAvIGR1cmF0aW9uWWVhciwgdGlja3MpO1xuICAgICAgaW50ZXJ2YWwgPSAneWVhcic7XG4gICAgfSBlbHNlIGlmIChpKSB7XG4gICAgICBjb25zdCB0aWNrSW50ZXJ2YWwgPVxuICAgICAgICB0aWNrSW50ZXJ2YWxzW1xuICAgICAgICAgIHRhcmdldCAvIHRpY2tJbnRlcnZhbHNbaSAtIDFdLmR1cmF0aW9uIDwgdGlja0ludGVydmFsc1tpXS5kdXJhdGlvbiAvIHRhcmdldCA/IGkgLSAxIDogaVxuICAgICAgICBdO1xuICAgICAgLy8gQHRzLWlnbm9yZSBUT0RPL2liXG4gICAgICBzdGVwID0gdGlja0ludGVydmFsLnN0ZXA7XG4gICAgICAvLyBAdHMtaWdub3JlIFRPRE8vaWJcbiAgICAgIGludGVydmFsID0gdGlja0ludGVydmFsLmludGVydmFsO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdGVwID0gTWF0aC5tYXgodGlja1N0ZXAoc3RhcnQsIHN0b3AsIHRpY2tzKSwgMSk7XG4gICAgICBpbnRlcnZhbCA9ICdtaWxsaXNlY29uZCc7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGAke3N0ZXB9LSR7aW50ZXJ2YWx9YDtcbn1cblxuLy8gZ2V0IGEgIG51bWJlciBvZiB1bmlxdWUgc2FtcGxlc1xuZnVuY3Rpb24gZ2V0VW5pcXVlU2FtcGxlcyh2YWx1ZXMsIGNvdW50KSB7XG4gIGxldCBpID0gLTE7XG4gIGNvbnN0IHNhbXBsZXM6IGFueVtdID0gW107XG4gIGNvbnN0IHNhbXBsZU1hcCA9IHt9O1xuICB3aGlsZSAoaSsrIDwgdmFsdWVzLmxlbmd0aCAmJiBzYW1wbGVzLmxlbmd0aCA8IGNvdW50KSB7XG4gICAgY29uc3QgdiA9IHZhbHVlc1tpXTtcbiAgICBpZiAodiAhPT0gdW5kZWZpbmVkICYmIHYgIT09IG51bGwgJiYgIXNhbXBsZU1hcFt2XSkge1xuICAgICAgc2FtcGxlTWFwW3ZdID0gdHJ1ZTtcbiAgICAgIHNhbXBsZXMucHVzaCh2KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhzYW1wbGVzKTtcbn1cblxuLyoqXG4gKiBHaXZlbiBhbiBhcnJheSBvZiBlcG9jaCB0aW1lc3RhbXAuIHNvcnQgaXQsIGlmIG51bWJlciBvZiBlbGVtZW50XG4gKiBzaGFyZSB0aGUgc2FtZSB0aW1lIGludGVydmFsIGV4Y2VlZCB0aHJlc2hvbGYsIGFuZCB0b3RhbCBzdGVwcyBzbWFsbGVyIHRoYW4gMTAwLCByZXR1cm4gaXQsIGVsc2UgcmV0dXJuIG51bGxcbiAqIEBwYXJhbSB2YWx1ZXNcbiAqL1xuZnVuY3Rpb24gZGV0ZWN0SW50ZXJ2YWwodmFsdWVzOiBudW1iZXJbXSA9IFtdLCBkb21haW4sIG1heFN0ZXBzID0gMTApIHtcbiAgY29uc3QgdGhyZXNob2xkID0gMC43O1xuXG4gIGNvbnN0IHNvcnRlZCA9IHZhbHVlcy5zb3J0KGFzY2VuZGluZyk7XG5cbiAgLy8gZ2V0IGZpcnN0IDEwMCB1bmlxdWUgc29ydGVkIHRzXG4gIGNvbnN0IHNhbXBsZXMgPSBnZXRVbmlxdWVTYW1wbGVzKHNvcnRlZCwgMTAwKTtcbiAgaWYgKHNhbXBsZXMubGVuZ3RoIDwgMikge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLy8gZ2V0IGFsbCBpbnRlcnZhbHNcbiAgY29uc3QgaW50ZXJ2YWxzID0gc2FtcGxlcy5yZWR1Y2UoKGFjY3UsIGQsIGkpID0+IHtcbiAgICBpZiAoaSA+IDApIHtcbiAgICAgIGNvbnN0IGR1cmF0aW9uID0gbW9tZW50LmR1cmF0aW9uKG1vbWVudC51dGMoc2FtcGxlc1tpXSkuZGlmZihtb21lbnQudXRjKHNhbXBsZXNbaSAtIDFdKSkpO1xuICAgICAgY29uc3QgW2R1ciwgY10gPSBnZXREdXJhdGlvblVuaXQoZHVyYXRpb24pO1xuICAgICAgYWNjdS5wdXNoKGAke2N9LSR7ZHVyfWApO1xuICAgIH1cbiAgICByZXR1cm4gYWNjdTtcbiAgfSwgW10pO1xuXG4gIC8vIGZpbmQgdGhlIG1vc3Qgb2NjdXJlZCBpbnRlcnZhbFxuICBjb25zdCBvY2N1ciA9IGdldEZyZXF1ZW5jeShpbnRlcnZhbHMpO1xuICBjb25zdCBtYXhPY2NyID0gT2JqZWN0LmtleXMob2NjdXIpLnJlZHVjZShcbiAgICAocHJldiwga2V5KSA9PiAob2NjdXJbcHJldl0gPj0gb2NjdXJba2V5XSA/IHByZXYgOiBrZXkpLFxuICAgIE9iamVjdC5rZXlzKG9jY3VyKVswXVxuICApO1xuXG4gIC8vIGlmIG9jY3VyYW5jZSBwYXNzZWQgdGhyZXNob2xkXG4gIGNvbnN0IG1vc3RPY2N1ciA9IG9jY3VyW21heE9jY3JdIC8gaW50ZXJ2YWxzLmxlbmd0aDtcbiAgaWYgKG1vc3RPY2N1ciA+PSB0aHJlc2hvbGQpIHtcbiAgICBjb25zdCBbc3RlcCwgZHVyXSA9IG1heE9jY3Iuc3BsaXQoJy0nKTtcbiAgICBjb25zdCBkdXJhdGlvblNlY29uZCA9IERVUkFUSU9OU1tkdXJdICogcGFyc2VJbnQoc3RlcCk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcmFkaXhcbiAgICBjb25zdCB0b3RhbFN0ZXBzID0gKGRvbWFpblsxXSAtIGRvbWFpblswXSkgLyBkdXJhdGlvblNlY29uZDtcblxuICAgIGlmICh0b3RhbFN0ZXBzIDwgbWF4U3RlcHMpIHtcbiAgICAgIC8vIGR1cmF0aW9uIGZ1bmN0aW9uIGlzIC5kYXlzIGludGVydmFsIGlzIGRheVxuICAgICAgcmV0dXJuIG1heE9jY3Iuc3Vic3RyaW5nKDAsIG1heE9jY3IubGVuZ3RoIC0gMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogbWFwcGVkVmFsdWUgaXMgc2F2ZWQgdG8gZGF0YXNldC5maWVsZHMuZmlsdGVyUHJvcHNcbiAqIEBwYXJhbSBkYXRhc2V0IHtLZXBsZXJUYWJsZX1cbiAqIEBwYXJhbSBmaWx0ZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEZpbHRlck1hcHBlZFZhbHVlKFxuICBkYXRhc2V0OiBLZXBsZXJUYWJsZU1vZGVsPGFueSwgYW55PixcbiAgZmlsdGVyOiBGaWx0ZXJcbik6IEZpbHRlclsnbWFwcGVkVmFsdWUnXSB8IG51bGwge1xuICBjb25zdCBkYXRhSWQgPSBkYXRhc2V0LmlkO1xuICBjb25zdCBmaWVsZE5hbWUgPSBmaWx0ZXIubmFtZVtmaWx0ZXIuZGF0YUlkLmluZGV4T2YoZGF0YUlkKV07XG4gIGNvbnN0IGZpZWxkID0gZGF0YXNldC5nZXRDb2x1bW5GaWVsZChmaWVsZE5hbWUpO1xuXG4gIGlmICghZmllbGQpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZSwgbm8tdW5kZWZcbiAgICBjb25zb2xlLndhcm4oYGZpZWxkICR7ZmllbGROYW1lfSBkb2VzIG5vdCBleGlzdCBvbiBkYXRhc2V0YCk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgY29uc3QgbWFwcGVkVmFsdWUgPSAoZmllbGQuZmlsdGVyUHJvcHMgfHwge30pLm1hcHBlZFZhbHVlO1xuICBpZiAoIW1hcHBlZFZhbHVlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGUsIG5vLXVuZGVmXG4gICAgY29uc29sZS53YXJuKGBtYXBwZWRWYWx1ZSBkb2VzbnQgZXhpc3Qgb24gZmlsdGVyIGZpZWxkICR7ZmlsdGVyLm5hbWV9YCk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgcmV0dXJuIG1hcHBlZFZhbHVlO1xufVxuLyoqXG4gKiBGaW5kIHRoZSByb3VuZCB1bml0IG9mIGdpdmVuIGR1cm1vc3RPY2N1cnRpb246IHggeWVhcnMgfCBtb250aHMgfCBkYXlzXG4gKiBAcGFyYW0gZHVyYXRpb25cbiAqL1xuZnVuY3Rpb24gZ2V0RHVyYXRpb25Vbml0KGR1cmF0aW9uKSB7XG4gIGNvbnN0IGR1ckZ1bmNzID0gT2JqZWN0LmtleXMoRFVSQVRJT05TKTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkdXJGdW5jcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGMgPSBkdXJhdGlvbltkdXJGdW5jc1tpXV0oKTtcbiAgICBpZiAoYyA+IDApIHtcbiAgICAgIHJldHVybiBbZHVyRnVuY3NbaV0sIGNdO1xuICAgIH1cbiAgfVxuICByZXR1cm4gWydtaWxsaXNlY29uZHMnLCAxXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGludGVydmFsVG9GdW5jdGlvbihpZDogc3RyaW5nKSB7XG4gIGNvbnN0IFtzdGVwU3RyLCBpbnRlcnZhbF0gPSBpZC5zcGxpdCgnLScpO1xuICBjb25zdCBzdGVwID0gcGFyc2VJbnQoc3RlcFN0cik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcmFkaXhcbiAgaWYgKCFzdGVwKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGUsIG5vLXVuZGVmXG4gICAgY29uc29sZS53YXJuKCdTdGVwIGlzIG5vdCBhbiBpbnRlZ2VyJyk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAoIVRJTUVfSU5URVJWQUxTW2ludGVydmFsXSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlLCBuby11bmRlZlxuICAgIGNvbnNvbGUud2FybihgVW5kZWZpbmVkIHRpbWUgaW50ZXJ2YWwgJHtpbnRlcnZhbH1gKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBUSU1FX0lOVEVSVkFMU1tpbnRlcnZhbF0uZXZlcnkoc3RlcCk7XG59XG5cbi8qKlxuICogR2V0IGluaXRpYWwgaW50ZXJ2YWwgZnJvbSBmaWx0ZXIgYW5kIGRhdGFzZXRzXG4gKiBAcGFyYW0gZmlsdGVyXG4gKiBAcGFyYW0gZGF0YXNldHNcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJbml0aWFsSW50ZXJ2YWwoXG4gIGZpbHRlcjogRmlsdGVyLFxuICBkYXRhc2V0czogUmVjb3JkPHN0cmluZywgS2VwbGVyVGFibGVNb2RlbDxhbnksIGFueT4+XG4pOiBzdHJpbmcge1xuICBjb25zdCB7ZG9tYWlufSA9IGZpbHRlcjtcbiAgY29uc3QgbWVyZ2VNYXBwZWRWYWx1ZSA9IGZpbHRlci5kYXRhSWQucmVkdWNlKChhY2N1LCBkYXRhSWQpID0+IHtcbiAgICBjb25zdCBtYXBwZWRWYWx1ZSA9IGdldEZpbHRlck1hcHBlZFZhbHVlKGRhdGFzZXRzW2RhdGFJZF0sIGZpbHRlcik7XG4gICAgaWYgKCFtYXBwZWRWYWx1ZSkge1xuICAgICAgcmV0dXJuIGFjY3U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXBwZWRWYWx1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgYWNjdS5wdXNoKG1hcHBlZFZhbHVlW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIGFjY3U7XG4gIH0sIFtdIGFzIGFueVtdKTtcblxuICAvLyBjaGVjayBpZiBkYXRhIGhhcyBwcmVkZWZpbmVkIGludGVydmFsXG4gIGxldCBpbnRlcnZhbCA9IGRldGVjdEludGVydmFsKG1lcmdlTWFwcGVkVmFsdWUsIGRvbWFpbik7XG5cbiAgaWYgKCFpbnRlcnZhbCkge1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgbmVlZCBiZXR0ZXIgdHlwZXMgZm9yIGRvbWFpblxuICAgIGNvbnN0IFt0MCwgdDFdID0gZG9tYWluO1xuICAgIGludGVydmFsID0gZ2V0SW50ZXJ2YWxCeVRpY2tzKEJJTlNfTEFSR0UsIHQwLCB0MSk7XG4gIH1cblxuICByZXR1cm4gaW50ZXJ2YWw7XG59XG5cbi8vIEZpbHRlciBpbnRlcnZhbCBvcHRpb25zIGJ5IHRpbWUgZmlsdGVyIGRvbWFpblxuLy8gbWF4IG51bWJlciBvZiBpbnRlcnZhbCBpcyAxMDAwXG4vKipcbiAqXG4gKiBAcGFyYW0gb3B0aW9uc1xuICogQHBhcmFtIGRvbWFpblxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVySW50ZXJ2YWxPcHRpb25zKG9wdGlvbnMsIGRvbWFpbikge1xuICBjb25zdCBtYXhCaW5zID0gMTAwMDtcbiAgY29uc3QgbWluQmlucyA9IDI7XG4gIGNvbnN0IHRpbWVTcGFuID0gZG9tYWluWzFdIC0gZG9tYWluWzBdO1xuXG4gIHJldHVybiBvcHRpb25zLmZpbHRlcihvcCA9PiB7XG4gICAgY29uc3Qge2lkfSA9IG9wO1xuICAgIGlmICghVElDS19JTlRFUlZBTFNbaWRdKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaW50ZXJ2YWwgPSBUSUNLX0lOVEVSVkFMU1tpZF07XG5cbiAgICAvLyByb3VnaCBjb3VudCBvbiBiaW5zXG4gICAgY29uc3QgY291bnQgPSB0aW1lU3BhbiAvIChpbnRlcnZhbC5zdGVwICogaW50ZXJ2YWwuZHVyYXRpb24pO1xuXG4gICAgcmV0dXJuIGNvdW50ID49IG1pbkJpbnMgJiYgY291bnQgPD0gbWF4QmlucztcbiAgfSk7XG59XG5cbi8qKlxuICogR2V0IHRpbWVsaW5lIGZyb20gZmlsdGVyXG4gKiBAcGFyYW0gZmlsdGVyIFRpbWVSYW5nZUZpbHRlciBmaWx0ZXJcbiAqIEByZXR1cm5zIFRpbWVsaW5lXG4gKi9cbmV4cG9ydCBjb25zdCBnZXRUaW1lbGluZUZyb21GaWx0ZXIgPSAoZmlsdGVyOiBUaW1lUmFuZ2VGaWx0ZXIpOiBUaW1lbGluZSA9PiB7XG4gIGNvbnN0IHtcbiAgICB2YWx1ZSxcbiAgICBkb21haW4sXG4gICAgc3BlZWQsXG4gICAgaXNBbmltYXRpbmcsXG4gICAgc3RlcCxcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgdGltZVN0ZXBzLFxuICAgIGRlZmF1bHRUaW1lRm9ybWF0LFxuICAgIHRpbWVGb3JtYXQsXG4gICAgdGltZXpvbmUsXG4gICAgdGltZUJpbnMsXG4gICAgYW5pbWF0aW9uV2luZG93LFxuICAgIHBsb3RUeXBlXG4gIH0gPSBmaWx0ZXI7XG5cbiAgcmV0dXJuIHtcbiAgICB2YWx1ZSxcbiAgICBlbmFibGVJbnRlcmFjdGlvbjogdHJ1ZSxcbiAgICBkb21haW4sXG4gICAgc3BlZWQsXG4gICAgaXNBbmltYXRpbmcsXG4gICAgc3RlcCxcbiAgICB0aW1lU3RlcHMsXG4gICAgZGVmYXVsdFRpbWVGb3JtYXQsXG4gICAgdGltZUZvcm1hdCxcbiAgICB0aW1lem9uZSxcbiAgICB0aW1lQmlucyxcbiAgICBhbmltYXRpb25XaW5kb3csXG4gICAgbWFya3M6IGdldEJpblRocmVzaG9sZHMocGxvdFR5cGU/LmludGVydmFsLCBkb21haW4pXG4gIH07XG59O1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFHQSxJQUFBQSxRQUFBLEdBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFDLHNCQUFBLENBQUFGLE9BQUE7QUFFQSxJQUFBRyxVQUFBLEdBQUFILE9BQUE7QUFTQSxJQUFBSSxZQUFBLEdBQUFKLE9BQUE7QUFHQSxJQUFBSyxZQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxLQUFBLEdBQUFOLE9BQUE7QUFuQkE7QUFDQTs7QUFxQk8sSUFBTU8sY0FBYyxHQUFBQyxPQUFBLENBQUFELGNBQUEsR0FBRztFQUM1QkUsS0FBSyxFQUFFLE9BQU87RUFDZEMsS0FBSyxFQUFFO0FBQ1QsQ0FBQztBQUVNLElBQU1DLGdCQUFnQixHQUFBSCxPQUFBLENBQUFHLGdCQUFBLEdBQUc7RUFDOUJDLElBQUksRUFBRSxHQUFHO0VBQ1RDLEtBQUssRUFBRSxHQUFHO0VBQ1ZDLEdBQUcsRUFBRSxHQUFHO0VBQ1JDLElBQUksRUFBRSxHQUFHO0VB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
;