kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
659 lines (553 loc) • 61.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getDefaultFilter = getDefaultFilter;
exports.getFilterProps = getFilterProps;
exports.getFieldDomain = getFieldDomain;
exports.filterData = filterData;
exports.isDataMatchFilter = isDataMatchFilter;
exports.adjustValueToFilterDomain = adjustValueToFilterDomain;
exports.getNumericFieldDomain = getNumericFieldDomain;
exports.getTimestampFieldDomain = getTimestampFieldDomain;
exports.histogramConstruct = histogramConstruct;
exports.formatNumberByStep = formatNumberByStep;
exports.isInRange = isInRange;
exports.getTimeWidgetTitleFormatter = getTimeWidgetTitleFormatter;
exports.getTimeWidgetHintFormatter = getTimeWidgetHintFormatter;
exports.isValidFilterValue = isValidFilterValue;
exports.getFilterPlot = getFilterPlot;
exports.getDefaultFilterPlotType = getDefaultFilterPlotType;
exports.TIME_ANIMATION_SPEED = exports.BASE_SPEED = exports.FILTER_COMPONENTS = exports.PLOT_TYPES = exports.FILTER_TYPES = exports.enlargedHistogramBins = exports.histogramBins = exports.TimestampStepMap = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _moment = _interopRequireDefault(require("moment"));
var _d3Array = require("d3-array");
var _keymirror = _interopRequireDefault(require("keymirror"));
var _defaultSettings = require("../constants/default-settings");
var _dataUtils = require("./data-utils");
var ScaleUtils = _interopRequireWildcard(require("./data-scale-utils"));
var _utils = require("./utils");
var _FILTER_TYPES$timeRan, _FILTER_TYPES$range, _SupportedPlotType, _FILTER_COMPONENTS;
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var TimestampStepMap = [{
max: 1,
step: 0.05
}, {
max: 10,
step: 0.1
}, {
max: 100,
step: 1
}, {
max: 500,
step: 5
}, {
max: 1000,
step: 10
}, {
max: 5000,
step: 50
}, {
max: Number.POSITIVE_INFINITY,
step: 1000
}];
exports.TimestampStepMap = TimestampStepMap;
var histogramBins = 30;
exports.histogramBins = histogramBins;
var enlargedHistogramBins = 100;
exports.enlargedHistogramBins = enlargedHistogramBins;
var durationSecond = 1000;
var durationMinute = durationSecond * 60;
var durationHour = durationMinute * 60;
var durationDay = durationHour * 24;
var durationWeek = durationDay * 7;
var durationYear = durationDay * 365;
var FILTER_TYPES = (0, _keymirror["default"])({
range: null,
select: null,
timeRange: null,
multiSelect: null
});
exports.FILTER_TYPES = FILTER_TYPES;
var PLOT_TYPES = (0, _keymirror["default"])({
histogram: null,
lineChart: null
});
exports.PLOT_TYPES = PLOT_TYPES;
var SupportedPlotType = (_SupportedPlotType = {}, (0, _defineProperty2["default"])(_SupportedPlotType, FILTER_TYPES.timeRange, (_FILTER_TYPES$timeRan = {
"default": 'histogram'
}, (0, _defineProperty2["default"])(_FILTER_TYPES$timeRan, _defaultSettings.ALL_FIELD_TYPES.integer, 'lineChart'), (0, _defineProperty2["default"])(_FILTER_TYPES$timeRan, _defaultSettings.ALL_FIELD_TYPES.real, 'lineChart'), _FILTER_TYPES$timeRan)), (0, _defineProperty2["default"])(_SupportedPlotType, FILTER_TYPES.range, (_FILTER_TYPES$range = {
"default": 'histogram'
}, (0, _defineProperty2["default"])(_FILTER_TYPES$range, _defaultSettings.ALL_FIELD_TYPES.integer, 'lineChart'), (0, _defineProperty2["default"])(_FILTER_TYPES$range, _defaultSettings.ALL_FIELD_TYPES.real, 'lineChart'), _FILTER_TYPES$range)), _SupportedPlotType);
var FILTER_COMPONENTS = (_FILTER_COMPONENTS = {}, (0, _defineProperty2["default"])(_FILTER_COMPONENTS, FILTER_TYPES.select, 'SingleSelectFilter'), (0, _defineProperty2["default"])(_FILTER_COMPONENTS, FILTER_TYPES.multiSelect, 'MultiSelectFilter'), (0, _defineProperty2["default"])(_FILTER_COMPONENTS, FILTER_TYPES.timeRange, 'TimeRangeFilter'), (0, _defineProperty2["default"])(_FILTER_COMPONENTS, FILTER_TYPES.range, 'RangeFilter'), _FILTER_COMPONENTS);
exports.FILTER_COMPONENTS = FILTER_COMPONENTS;
var BASE_SPEED = 600;
exports.BASE_SPEED = BASE_SPEED;
var TIME_ANIMATION_SPEED = [{
label: '0.5x',
value: 0.5
}, {
label: '1x',
value: 1
}, {
label: '2x',
value: 2
}, {
label: '4x',
value: 4
}];
exports.TIME_ANIMATION_SPEED = TIME_ANIMATION_SPEED;
function getDefaultFilter(dataId) {
return {
// link to dataset Id
dataId: dataId,
// should allow to edit dataId
freeze: false,
id: (0, _utils.generateHashId)(4),
// time range filter specific
fixedDomain: false,
enlarged: false,
isAnimating: false,
speed: 1,
// field specific
name: null,
type: null,
fieldIdx: null,
domain: null,
value: null,
// plot
plotType: PLOT_TYPES.histogram,
yAxis: null,
interval: null
};
}
/**
* Get default filter prop based on field type
*
* @param {Object[]} data
* @param {object} field
* @returns {object} default filter
*/
function getFilterProps(data, field) {
var filterProp = _objectSpread({}, getFieldDomain(data, field), {
fieldType: field.type
});
switch (field.type) {
case _defaultSettings.ALL_FIELD_TYPES.real:
case _defaultSettings.ALL_FIELD_TYPES.integer:
return _objectSpread({}, filterProp, {
value: filterProp.domain,
type: FILTER_TYPES.range,
typeOptions: [FILTER_TYPES.range]
});
case _defaultSettings.ALL_FIELD_TYPES["boolean"]:
return _objectSpread({}, filterProp, {
type: FILTER_TYPES.select,
value: true
});
case _defaultSettings.ALL_FIELD_TYPES.string:
case _defaultSettings.ALL_FIELD_TYPES.date:
return _objectSpread({}, filterProp, {
type: FILTER_TYPES.multiSelect,
value: []
});
case _defaultSettings.ALL_FIELD_TYPES.timestamp:
return _objectSpread({}, filterProp, {
type: FILTER_TYPES.timeRange,
enlarged: true,
fixedDomain: true,
value: filterProp.domain
});
default:
return {};
}
}
/**
* Calculate field domain based on field type and data
*
* @param {Object[]} data
* @param {object} field
* @returns {object} with domain as key
*/
function getFieldDomain(data, field) {
var fieldIdx = field.tableFieldIndex - 1;
var isTime = field.type === _defaultSettings.ALL_FIELD_TYPES.timestamp;
var valueAccessor = _dataUtils.maybeToDate.bind(null, isTime, fieldIdx, field.format);
var domain; // console.log('data and field in getFieldDomain', data, field);
switch (field.type) {
case _defaultSettings.ALL_FIELD_TYPES.real:
case _defaultSettings.ALL_FIELD_TYPES.integer:
// calculate domain and step
return getNumericFieldDomain(data, valueAccessor);
case _defaultSettings.ALL_FIELD_TYPES["boolean"]:
return {
domain: [true, false]
};
case _defaultSettings.ALL_FIELD_TYPES.string:
case _defaultSettings.ALL_FIELD_TYPES.date:
domain = ScaleUtils.getOrdinalDomain(data, valueAccessor);
return {
domain: domain
};
case _defaultSettings.ALL_FIELD_TYPES.timestamp:
return getTimestampFieldDomain(data, valueAccessor);
default:
return {
domain: ScaleUtils.getOrdinalDomain(data, valueAccessor)
};
}
}
/**
* Filter data based on an array of filters
*
* @param {Object[]} data
* @param {string} dataId
* @param {Object[]} filters
* @returns {Object[]} data
* @returns {Number[]} filteredIndex
*/
function filterData(data, dataId, filters) {
if (!data || !dataId) {
// why would there not be any data? are we over doing this?
return {
data: [],
filteredIndex: []
};
}
if (!filters.length) {
return {
data: data,
filteredIndex: data.map(function (_, i) {
return i;
}),
filteredIndexForDomain: data.map(function (_, i) {
return i;
})
};
}
var appliedFilters = filters.filter(function (d) {
return d.dataId === dataId && d.fieldIdx > -1 && d.value !== null;
});
var _appliedFilters$reduc = appliedFilters.reduce(function (accu, f) {
if (f.dataId === dataId && f.fieldIdx > -1 && f.value !== null) {
(f.fixedDomain ? accu[1] : accu[0]).push(f);
}
return accu;
}, [[], []]),
_appliedFilters$reduc2 = (0, _slicedToArray2["default"])(_appliedFilters$reduc, 2),
dynamicDomainFilters = _appliedFilters$reduc2[0],
fixedDomainFilters = _appliedFilters$reduc2[1]; // console.log(dynamicDomainFilters)
// console.log(fixedDomainFilters)
// we save a reference of allData index here to access dataToFeature
// in geojson and hexgonId layer
// console.time('filterData');
var _data$reduce = data.reduce(function (accu, d, i) {
// generate 2 sets of
// filter data used to calculate layer Domain
var matchForDomain = dynamicDomainFilters.every(function (filter) {
return isDataMatchFilter(d, filter, i);
});
if (matchForDomain) {
accu.filteredIndexForDomain.push(i); // filter data for render
var matchForRender = fixedDomainFilters.every(function (filter) {
return isDataMatchFilter(d, filter, i);
});
if (matchForRender) {
accu.filtered.push(d);
accu.filteredIndex.push(i);
}
}
return accu;
}, {
filtered: [],
filteredIndex: [],
filteredIndexForDomain: []
}),
filtered = _data$reduce.filtered,
filteredIndex = _data$reduce.filteredIndex,
filteredIndexForDomain = _data$reduce.filteredIndexForDomain; // console.log('data==', data.length)
// console.log('filtered==', filtered.length)
// console.log('filteredIndex==', filteredIndex.length)
// console.log('filteredIndexForDomain==', filteredIndexForDomain.length)
//
// console.timeEnd('filterData');
return {
data: filtered,
filteredIndex: filteredIndex,
filteredIndexForDomain: filteredIndexForDomain
};
}
/**
* Check if value is in range of filter
*
* @param {Object[]} data
* @param {Object} filter
* @param {number} i
* @returns {Boolean} - whether value falls in the range of the filter
*/
function isDataMatchFilter(data, filter, i) {
var val = data[filter.fieldIdx];
if (!filter.type) {
return true;
}
switch (filter.type) {
case FILTER_TYPES.range:
return isInRange(val, filter.value);
case FILTER_TYPES.timeRange:
var timeVal = filter.mappedValue ? filter.mappedValue[i] : _moment["default"].utc(val).valueOf();
return isInRange(timeVal, filter.value);
case FILTER_TYPES.multiSelect:
return filter.value.includes(val);
case FILTER_TYPES.select:
return filter.value === val;
default:
return true;
}
}
/**
* Call by parsing filters from URL
* Check if value of filter within filter domain, if not adjust it to match
* filter domain
*
* @param {string[] | string | number | number[]} value
* @param {Array} filter.domain
* @param {String} filter.type
* @returns {*} - adjusted value to match filter or null to remove filter
*/
/* eslint-disable complexity */
function adjustValueToFilterDomain(value, _ref) {
var domain = _ref.domain,
type = _ref.type;
if (!domain || !type) {
return false;
}
switch (type) {
case FILTER_TYPES.range:
case FILTER_TYPES.timeRange:
if (!Array.isArray(value) || value.length !== 2) {
return domain.map(function (d) {
return d;
});
}
return value.map(function (d, i) {
return (0, _dataUtils.notNullorUndefined)(d) && isInRange(d, domain) ? d : domain[i];
});
case FILTER_TYPES.multiSelect:
if (!Array.isArray(value)) {
return [];
}
var filteredValue = value.filter(function (d) {
return domain.includes(d);
});
return filteredValue.length ? filteredValue : [];
case FILTER_TYPES.select:
return domain.includes(value) ? value : true;
default:
return null;
}
}
/* eslint-enable complexity */
/**
* Calculate numeric domain and suitable step
*
* @param {Object[]} data
* @param {function} valueAccessor
* @returns {object} domain and step
*/
function getNumericFieldDomain(data, valueAccessor) {
var domain = [0, 1];
var step = 0.1;
var mappedValue = Array.isArray(data) ? data.map(valueAccessor) : [];
if (Array.isArray(data) && data.length > 1) {
domain = ScaleUtils.getLinearDomain(mappedValue);
var diff = domain[1] - domain[0]; // in case equal domain, [96, 96], which will break quantize scale
if (!diff) {
domain[1] = domain[0] + 1;
}
step = getNumericStepSize(diff) || step;
domain[0] = formatNumberByStep(domain[0], step, 'floor');
domain[1] = formatNumberByStep(domain[1], step, 'ceil');
}
var _getHistogram = getHistogram(domain, mappedValue),
histogram = _getHistogram.histogram,
enlargedHistogram = _getHistogram.enlargedHistogram;
return {
domain: domain,
step: step,
histogram: histogram,
enlargedHistogram: enlargedHistogram
};
}
function getNumericStepSize(diff) {
if (diff > 100) {
return 1;
} else if (diff < 20 && diff > 3) {
return 0.01;
} else if (diff <= 3) {
return 0.001;
}
}
/**
* Calculate timestamp domain and suitable step
*
* @param {Object[]} data
* @param {function} valueAccessor
* @returns {object} domain and step
*/
function getTimestampFieldDomain(data, valueAccessor) {
// to avoid converting string format time to epoch
// every time we compare we store a value mapped to int in filter domain
var mappedValue = Array.isArray(data) ? data.map(valueAccessor) : [];
var domain = ScaleUtils.getLinearDomain(mappedValue);
var step = 0.01;
var diff = domain[1] - domain[0];
var entry = TimestampStepMap.find(function (f) {
return f.max >= diff;
});
if (entry) {
step = entry.step;
}
var _getHistogram2 = getHistogram(domain, mappedValue),
histogram = _getHistogram2.histogram,
enlargedHistogram = _getHistogram2.enlargedHistogram;
return {
domain: domain,
step: step,
mappedValue: mappedValue,
histogram: histogram,
enlargedHistogram: enlargedHistogram
};
}
function histogramConstruct(domain, mappedValue, bins) {
return (0, _d3Array.histogram)().thresholds((0, _d3Array.ticks)(domain[0], domain[1], bins)).domain(domain)(mappedValue).map(function (bin) {
return {
count: bin.length,
x0: bin.x0,
x1: bin.x1
};
});
}
/**
* Calculate histogram from domain and array of values
*
* @param {number[]} domain
* @param {Object[]} mappedValue
* @returns {Array[]} histogram
*/
function getHistogram(domain, mappedValue) {
var histogram = histogramConstruct(domain, mappedValue, histogramBins);
var enlargedHistogram = histogramConstruct(domain, mappedValue, enlargedHistogramBins);
return {
histogram: histogram,
enlargedHistogram: enlargedHistogram
};
}
/**
* round number based on step
*
* @param {number} val
* @param {number} step
* @param {string} bound
* @returns {number} rounded number
*/
function formatNumberByStep(val, step, bound) {
if (bound === 'floor') {
return Math.floor(val * (1 / step)) / (1 / step);
}
return Math.ceil(val * (1 / step)) / (1 / step);
}
function isInRange(val, domain) {
if (!Array.isArray(domain)) {
return false;
}
return val >= domain[0] && val <= domain[1];
}
function getTimeWidgetTitleFormatter(domain) {
if (!Array.isArray(domain)) {
return null;
}
var diff = domain[1] - domain[0];
return diff > durationYear ? 'MM/DD/YY' : diff > durationDay ? 'MM/DD hha' : 'MM/DD hh:mma';
}
function getTimeWidgetHintFormatter(domain) {
if (!Array.isArray(domain)) {
return null;
}
var diff = domain[1] - domain[0];
return diff > durationYear ? 'MM/DD/YY' : diff > durationWeek ? 'MM/DD' : diff > durationDay ? 'MM/DD hha' : diff > durationHour ? 'hh:mma' : 'hh:mm:ssa';
}
/**
* Sanity check on filters to prepare for save
* @param {String} type - filter type
* @param {*} value - filter value
* @returns {boolean} whether filter is value
*/
function isValidFilterValue(_ref2) {
var type = _ref2.type,
value = _ref2.value;
if (!type) {
return false;
}
switch (type) {
case FILTER_TYPES.select:
return value === true || value === false;
case FILTER_TYPES.range:
case FILTER_TYPES.timeRange:
return Array.isArray(value) && value.every(function (v) {
return v !== null && !isNaN(v);
});
case FILTER_TYPES.multiSelect:
return Array.isArray(value) && Boolean(value.length);
case FILTER_TYPES.input:
return Boolean(value.length);
default:
return true;
}
}
function getFilterPlot(filter, allData) {
if (filter.plotType === PLOT_TYPES.histogram || !filter.yAxis) {
// histogram should be calculated when create filter
return {};
}
var mappedValue = filter.mappedValue;
var yAxis = filter.yAxis; // return lineChart
var series = allData.map(function (d, i) {
return {
x: mappedValue[i],
y: d[yAxis.tableFieldIndex - 1]
};
}).filter(function (_ref3) {
var x = _ref3.x,
y = _ref3.y;
return Number.isFinite(x) && Number.isFinite(y);
}).sort(function (a, b) {
return (0, _d3Array.ascending)(a.x, b.x);
});
var yDomain = (0, _d3Array.extent)(series, function (d) {
return d.y;
});
var xDomain = [series[0].x, series[series.length - 1].x];
return {
lineChart: {
series: series,
yDomain: yDomain,
xDomain: xDomain
},
yAxis: yAxis
};
}
function getDefaultFilterPlotType(filter) {
var filterPlotTypes = SupportedPlotType[filter.type];
if (!filterPlotTypes) {
return null;
}
if (!filter.yAxis) {
return filterPlotTypes["default"];
}
return filterPlotTypes[filter.yAxis.type] || null;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9maWx0ZXItdXRpbHMuanMiXSwibmFtZXMiOlsiVGltZXN0YW1wU3RlcE1hcCIsIm1heCIsInN0ZXAiLCJOdW1iZXIiLCJQT1NJVElWRV9JTkZJTklUWSIsImhpc3RvZ3JhbUJpbnMiLCJlbmxhcmdlZEhpc3RvZ3JhbUJpbnMiLCJkdXJhdGlvblNlY29uZCIsImR1cmF0aW9uTWludXRlIiwiZHVyYXRpb25Ib3VyIiwiZHVyYXRpb25EYXkiLCJkdXJhdGlvbldlZWsiLCJkdXJhdGlvblllYXIiLCJGSUxURVJfVFlQRVMiLCJyYW5nZSIsInNlbGVjdCIsInRpbWVSYW5nZSIsIm11bHRpU2VsZWN0IiwiUExPVF9UWVBFUyIsImhpc3RvZ3JhbSIsImxpbmVDaGFydCIsIlN1cHBvcnRlZFBsb3RUeXBlIiwiQUxMX0ZJRUxEX1RZUEVTIiwiaW50ZWdlciIsInJlYWwiLCJGSUxURVJfQ09NUE9ORU5UUyIsIkJBU0VfU1BFRUQiLCJUSU1FX0FOSU1BVElPTl9TUEVFRCIsImxhYmVsIiwidmFsdWUiLCJnZXREZWZhdWx0RmlsdGVyIiwiZGF0YUlkIiwiZnJlZXplIiwiaWQiLCJmaXhlZERvbWFpbiIsImVubGFyZ2VkIiwiaXNBbmltYXRpbmciLCJzcGVlZCIsIm5hbWUiLCJ0eXBlIiwiZmllbGRJZHgiLCJkb21haW4iLCJwbG90VHlwZSIsInlBeGlzIiwiaW50ZXJ2YWwiLCJnZXRGaWx0ZXJQcm9wcyIsImRhdGEiLCJmaWVsZCIsImZpbHRlclByb3AiLCJnZXRGaWVsZERvbWFpbiIsImZpZWxkVHlwZSIsInR5cGVPcHRpb25zIiwic3RyaW5nIiwiZGF0ZSIsInRpbWVzdGFtcCIsInRhYmxlRmllbGRJbmRleCIsImlzVGltZSIsInZhbHVlQWNjZXNzb3IiLCJtYXliZVRvRGF0ZSIsImJpbmQiLCJmb3JtYXQiLCJnZXROdW1lcmljRmllbGREb21haW4iLCJTY2FsZVV0aWxzIiwiZ2V0T3JkaW5hbERvbWFpbiIsImdldFRpbWVzdGFtcEZpZWxkRG9tYWluIiwiZmlsdGVyRGF0YSIsImZpbHRlcnMiLCJmaWx0ZXJlZEluZGV4IiwibGVuZ3RoIiwibWFwIiwiXyIsImkiLCJmaWx0ZXJlZEluZGV4Rm9yRG9tYWluIiwiYXBwbGllZEZpbHRlcnMiLCJmaWx0ZXIiLCJkIiwicmVkdWNlIiwiYWNjdSIsImYiLCJwdXNoIiwiZHluYW1pY0RvbWFpbkZpbHRlcnMiLCJmaXhlZERvbWFpbkZpbHRlcnMiLCJtYXRjaEZvckRvbWFpbiIsImV2ZXJ5IiwiaXNEYXRhTWF0Y2hGaWx0ZXIiLCJtYXRjaEZvclJlbmRlciIsImZpbHRlcmVkIiwidmFsIiwiaXNJblJhbmdlIiwidGltZVZhbCIsIm1hcHBlZFZhbHVlIiwibW9tZW50IiwidXRjIiwidmFsdWVPZiIsImluY2x1ZGVzIiwiYWRqdXN0VmFsdWVUb0ZpbHRlckRvbWFpbiIsIkFycmF5IiwiaXNBcnJheSIsImZpbHRlcmVkVmFsdWUiLCJnZXRMaW5lYXJEb21haW4iLCJkaWZmIiwiZ2V0TnVtZXJpY1N0ZXBTaXplIiwiZm9ybWF0TnVtYmVyQnlTdGVwIiwiZ2V0SGlzdG9ncmFtIiwiZW5sYXJnZWRIaXN0b2dyYW0iLCJlbnRyeSIsImZpbmQiLCJoaXN0b2dyYW1Db25zdHJ1Y3QiLCJiaW5zIiwidGhyZXNob2xkcyIsImJpbiIsImNvdW50IiwieDAiLCJ4MSIsImJvdW5kIiwiTWF0aCIsImZsb29yIiwiY2VpbCIsImdldFRpbWVXaWRnZXRUaXRsZUZvcm1hdHRlciIsImdldFRpbWVXaWRnZXRIaW50Rm9ybWF0dGVyIiwiaXNWYWxpZEZpbHRlclZhbHVlIiwidiIsImlzTmFOIiwiQm9vbGVhbiIsImlucHV0IiwiZ2V0RmlsdGVyUGxvdCIsImFsbERhdGEiLCJzZXJpZXMiLCJ4IiwieSIsImlzRmluaXRlIiwic29ydCIsImEiLCJiIiwieURvbWFpbiIsInhEb21haW4iLCJnZXREZWZhdWx0RmlsdGVyUGxvdFR5cGUiLCJmaWx0ZXJQbG90VHlwZXMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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Q0FBTixDQUFVQyxDQUFYLEVBQWNELE1BQU0sQ0FBQ0EsTUFBTSxDQUFDM0QsTUFBUCxHQUFnQixDQUFqQixDQUFOLENBQTBCNEQsQ0FBeEMsQ0FBaEI7QUFFQSxTQUFPO0FBQUM1RyxJQUFBQSxTQUFTLEVBQUU7QUFBQzJHLE1BQUFBLE1BQU0sRUFBTkEsTUFBRDtBQUFTTyxNQUFBQSxPQUFPLEVBQVBBLE9BQVQ7QUFBa0JDLE1BQUFBLE9BQU8sRUFBUEE7QUFBbEIsS0FBWjtBQUF3QzVGLElBQUFBLEtBQUssRUFBTEE7QUFBeEMsR0FBUDtBQUNEOztBQUVNLFNBQVM2Rix3QkFBVCxDQUFrQzlELE1BQWxDLEVBQTBDO0FBQy9DLE1BQU0rRCxlQUFlLEdBQUdwSCxpQkFBaUIsQ0FBQ3FELE1BQU0sQ0FBQ25DLElBQVIsQ0FBekM7O0FBQ0EsTUFBSSxDQUFDa0csZUFBTCxFQUFzQjtBQUNwQixXQUFPLElBQVA7QUFDRDs7QUFFRCxNQUFJLENBQUMvRCxNQUFNLENBQUMvQixLQUFaLEVBQW1CO0FBQ2pCLFdBQU84RixlQUFlLFdBQXRCO0FBQ0Q7O0FBRUQsU0FBT0EsZUFBZSxDQUFDL0QsTUFBTSxDQUFDL0IsS0FBUCxDQUFhSixJQUFkLENBQWYsSUFBc0MsSUFBN0M7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAxOSBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7YXNjZW5kaW5nLCBleHRlbnQsIGhpc3RvZ3JhbSBhcyBkM0hpc3RvZ3JhbSwgdGlja3N9IGZyb20gJ2QzLWFycmF5JztcbmltcG9ydCBrZXlNaXJyb3IgZnJvbSAna2V5bWlycm9yJztcblxuaW1wb3J0IHtBTExfRklFTERfVFlQRVN9IGZyb20gJ2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzJztcbmltcG9ydCB7bWF5YmVUb0RhdGUsIG5vdE51bGxvclVuZGVmaW5lZH0gZnJvbSAnLi9kYXRhLXV0aWxzJztcbmltcG9ydCAqIGFzIFNjYWxlVXRpbHMgZnJvbSAnLi9kYXRhLXNjYWxlLXV0aWxzJztcbmltcG9ydCB7Z2VuZXJhdGVIYXNoSWR9IGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgY29uc3QgVGltZXN0YW1wU3RlcE1hcCA9IFtcbiAge21heDogMSwgc3RlcDogMC4wNX0sXG4gIHttYXg6IDEwLCBzdGVwOiAwLjF9LFxuICB7bWF4OiAxMDAsIHN0ZXA6IDF9LFxuICB7bWF4OiA1MDAsIHN0ZXA6IDV9LFxuICB7bWF4OiAxMDAwLCBzdGVwOiAxMH0sXG4gIHttYXg6IDUwMDAsIHN0ZXA6IDUwfSxcbiAge21heDogTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLCBzdGVwOiAxMDAwfVxuXTtcblxuZXhwb3J0IGNvbnN0IGhpc3RvZ3JhbUJpbnMgPSAzMDtcbmV4cG9ydCBjb25zdCBlbmxhcmdlZEhpc3RvZ3JhbUJpbnMgPSAxMDA7XG5cbmNvbnN0IGR1cmF0aW9uU2Vjb25kID0gMTAwMDtcbmNvbnN0IGR1cmF0aW9uTWludXRlID0gZHVyYXRpb25TZWNvbmQgKiA2MDtcbmNvbnN0IGR1cmF0aW9uSG91ciA9IGR1cmF0aW9uTWludXRlICogNjA7XG5jb25zdCBkdXJhdGlvbkRheSA9IGR1cmF0aW9uSG91ciAqIDI0O1xuY29uc3QgZHVyYXRpb25XZWVrID0gZHVyYXRpb25EYXkgKiA3O1xuY29uc3QgZHVyYXRpb25ZZWFyID0gZHVyYXRpb25EYXkgKiAzNjU7XG5cbmV4cG9ydCBjb25zdCBGSUxURVJfVFlQRVMgPSBrZXlNaXJyb3Ioe1xuICByYW5nZTogbnVsbCxcbiAgc2VsZWN0OiBudWxsLFxuICB0aW1lUmFuZ2U6IG51bGwsXG4gIG11bHRpU2VsZWN0OiBudWxsXG59KTtcblxuZXhwb3J0IGNvbnN0IFBMT1RfVFlQRVMgPSBrZXlNaXJyb3Ioe1xuICBoaXN0b2dyYW06IG51bGwsXG4gIGxpbmVDaGFydDogbnVsbFxufSk7XG5cbmNvbnN0IFN1cHBvcnRlZFBsb3RUeXBlID0ge1xuICBbRklMVEVSX1RZUEVTLnRpbWVSYW5nZV06IHtcbiAgICBkZWZhdWx0OiAnaGlzdG9ncmFtJyxcbiAgICBbQUxMX0ZJRUxEX1RZUEVTLmludGVnZXJdOiAnbGluZUNoYXJ0JyxcbiAgICBbQUxMX0ZJRUxEX1RZUEVTLnJlYWxdOiAnbGluZUNoYXJ0J1xuICB9LFxuICBbRklMVEVSX1RZUEVTLnJhbmdlXToge1xuICAgIGRlZmF1bHQ6ICdoaXN0b2dyYW0nLFxuICAgIFtBTExfRklFTERfVFlQRVMuaW50ZWdlcl06ICdsaW5lQ2hhcnQnLFxuICAgIFtBTExfRklFTERfVFlQRVMucmVhbF06ICdsaW5lQ2hhcnQnXG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBGSUxURVJfQ09NUE9ORU5UUyA9IHtcbiAgW0ZJTFRFUl9UWVBFUy5zZWxlY3RdOiAnU2luZ2xlU2VsZWN0RmlsdGVyJyxcbiAgW0ZJTFRFUl9UWVBFUy5tdWx0aVNlbGVjdF06ICdNdWx0aVNlbGVjdEZpbHRlcicsXG4gIFtGSUxURVJfVFlQRVMudGltZVJhbmdlXTogJ1RpbWVSYW5nZUZpbHRlcicsXG4gIFtGSUxURVJfVFlQRVMucmFuZ2VdOiAnUmFuZ2VGaWx0ZXInXG59O1xuXG5leHBvcnQgY29uc3QgQkFTRV9TUEVFRCA9IDYwMDtcbmV4cG9ydCBjb25zdCBUSU1FX0FOSU1BVElPTl9TUEVFRCA9IFtcbiAge1xuICAgIGxhYmVsOiAnMC41eCcsXG4gICAgdmFsdWU6IDAuNVxuICB9LFxuICB7XG4gICAgbGFiZWw6ICcxeCcsXG4gICAgdmFsdWU6IDFcbiAgfSxcbiAge1xuICAgIGxhYmVsOiAnMngnLFxuICAgIHZhbHVlOiAyXG4gIH0sXG4gIHtcbiAgICBsYWJlbDogJzR4JyxcbiAgICB2YWx1ZTogNFxuICB9XG5dO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGVmYXVsdEZpbHRlcihkYXRhSWQpIHtcbiAgcmV0dXJuIHtcbiAgICAvLyBsaW5rIHRvIGRhdGFzZXQgSWRcbiAgICBkYXRhSWQsXG4gICAgLy8gc2hvdWxkIGFsbG93IHRvIGVkaXQgZGF0YUlkXG4gICAgZnJlZXplOiBmYWxzZSxcbiAgICBpZDogZ2VuZXJhdGVIYXNoSWQoNCksXG5cbiAgICAvLyB0aW1lIHJhbmdlIGZpbHRlciBzcGVjaWZpY1xuICAgIGZpeGVkRG9tYWluOiBmYWxzZSxcbiAgICBlbmxhcmdlZDogZmFsc2UsXG4gICAgaXNBbmltYXRpbmc6IGZhbHNlLFxuICAgIHNwZWVkOiAxLFxuXG4gICAgLy8gZmllbGQgc3BlY2lmaWNcbiAgICBuYW1lOiBudWxsLFxuICAgIHR5cGU6IG51bGwsXG4gICAgZmllbGRJZHg6IG51bGwsXG4gICAgZG9tYWluOiBudWxsLFxuICAgIHZhbHVlOiBudWxsLFxuXG4gICAgLy8gcGxvdFxuICAgIHBsb3RUeXBlOiBQTE9UX1RZUEVTLmhpc3RvZ3JhbSxcbiAgICB5QXhpczogbnVsbCxcbiAgICBpbnRlcnZhbDogbnVsbFxuICB9O1xufVxuXG4vKipcbiAqIEdldCBkZWZhdWx0IGZpbHRlciBwcm9wIGJhc2VkIG9uIGZpZWxkIHR5cGVcbiAqXG4gKiBAcGFyYW0ge09iamVjdFtdfSBkYXRhXG4gKiBAcGFyYW0ge29iamVjdH0gZmllbGRcbiAqIEByZXR1cm5zIHtvYmplY3R9IGRlZmF1bHQgZmlsdGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRGaWx0ZXJQcm9wcyhkYXRhLCBmaWVsZCkge1xuICBjb25zdCBmaWx0ZXJQcm9wID0ge1xuICAgIC4uLmdldEZpZWxkRG9tYWluKGRhdGEsIGZpZWxkKSxcbiAgICBmaWVsZFR5cGU6IGZpZWxkLnR5cGVcbiAgfTtcblxuICBzd2l0Y2ggKGZpZWxkLnR5cGUpIHtcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5yZWFsOlxuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmludGVnZXI6XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5maWx0ZXJQcm9wLFxuICAgICAgICB2YWx1ZTogZmlsdGVyUHJvcC5kb21haW4sXG4gICAgICAgIHR5cGU6IEZJTFRFUl9UWVBFUy5yYW5nZSxcbiAgICAgICAgdHlwZU9wdGlvbnM6IFtGSUxURVJfVFlQRVMucmFuZ2VdXG4gICAgICB9O1xuXG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMuYm9vbGVhbjpcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLmZpbHRlclByb3AsXG4gICAgICAgIHR5cGU6IEZJTFRFUl9UWVBFUy5zZWxlY3QsXG4gICAgICAgIHZhbHVlOiB0cnVlXG4gICAgICB9O1xuXG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMuc3RyaW5nOlxuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmRhdGU6XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5maWx0ZXJQcm9wLFxuICAgICAgICB0eXBlOiBGSUxURVJfVFlQRVMubXVsdGlTZWxlY3QsXG4gICAgICAgIHZhbHVlOiBbXVxuICAgICAgfTtcblxuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLnRpbWVzdGFtcDpcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLmZpbHRlclByb3AsXG4gICAgICAgIHR5cGU6IEZJTFRFUl9UWVBFUy50aW1lUmFuZ2UsXG4gICAgICAgIGVubGFyZ2VkOiB0cnVlLFxuICAgICAgICBmaXhlZERvbWFpbjogdHJ1ZSxcbiAgICAgICAgdmFsdWU6IGZpbHRlclByb3AuZG9tYWluXG4gICAgICB9O1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB7fTtcbiAgfVxufVxuXG4vKipcbiAqIENhbGN1bGF0ZSBmaWVsZCBkb21haW4gYmFzZWQgb24gZmllbGQgdHlwZSBhbmQgZGF0YVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0W119IGRhdGFcbiAqIEBwYXJhbSB7b2JqZWN0fSBmaWVsZFxuICogQHJldHVybnMge29iamVjdH0gd2l0aCBkb21haW4gYXMga2V5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRGaWVsZERvbWFpbihkYXRhLCBmaWVsZCkge1xuICBjb25zdCBmaWVsZElkeCA9IGZpZWxkLnRhYmxlRmllbGRJbmRleCAtIDE7XG4gIGNvbnN0IGlzVGltZSA9IGZpZWxkLnR5cGUgPT09IEFMTF9GSUVMRF9UWVBFUy50aW1lc3RhbXA7XG4gIGNvbnN0IHZhbHVlQWNjZXNzb3IgPSBtYXliZVRvRGF0ZS5iaW5kKG51bGwsIGlzVGltZSwgZmllbGRJZHgsIGZpZWxkLmZvcm1hdCk7XG4gIGxldCBkb21haW47XG5cbiAgLy8gY29uc29sZS5sb2coJ2RhdGEgYW5kIGZpZWxkIGluIGdldEZpZWxkRG9tYWluJywgZGF0YSwgZmllbGQpO1xuXG4gIHN3aXRjaCAoZmllbGQudHlwZSkge1xuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLnJlYWw6XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMuaW50ZWdlcjpcbiAgICAgIC8vIGNhbGN1bGF0ZSBkb21haW4gYW5kIHN0ZXBcbiAgICAgIHJldHVybiBnZXROdW1lcmljRmllbGREb21haW4oZGF0YSwgdmFsdWVBY2Nlc3Nvcik7XG5cbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5ib29sZWFuOlxuICAgICAgcmV0dXJuIHtkb21haW46IFt0cnVlLCBmYWxzZV19O1xuXG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMuc3RyaW5nOlxuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmRhdGU6XG4gICAgICBkb21haW4gPSBTY2FsZVV0aWxzLmdldE9yZGluYWxEb21haW4oZGF0YSwgdmFsdWVBY2Nlc3Nvcik7XG4gICAgICByZXR1cm4ge2RvbWFpbn07XG5cbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy50aW1lc3RhbXA6XG4gICAgICByZXR1cm4gZ2V0VGltZXN0YW1wRmllbGREb21haW4oZGF0YSwgdmFsdWVBY2Nlc3Nvcik7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHtkb21haW46IFNjYWxlVXRpbHMuZ2V0T3JkaW5hbERvbWFpbihkYXRhLCB2YWx1ZUFjY2Vzc29yKX07XG4gIH1cbn1cblxuLyoqXG4gKiBGaWx0ZXIgZGF0YSBiYXNlZCBvbiBhbiBhcnJheSBvZiBmaWx0ZXJzXG4gKlxuICogQHBhcmFtIHtPYmplY3RbXX0gZGF0YVxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGFJZFxuICogQHBhcmFtIHtPYmplY3RbXX0gZmlsdGVyc1xuICogQHJldHVybnMge09iamVjdFtdfSBkYXRhXG4gKiBAcmV0dXJucyB7TnVtYmVyW119IGZpbHRlcmVkSW5kZXhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlckRhdGEoZGF0YSwgZGF0YUlkLCBmaWx0ZXJzKSB7XG4gIGlmICghZGF0YSB8fCAhZGF0YUlkKSB7XG4gICAgLy8gd2h5IHdvdWxkIHRoZXJlIG5vdCBiZSBhbnkgZGF0YT8gYXJlIHdlIG92ZXIgZG9pbmcgdGhpcz9cbiAgICByZXR1cm4ge2RhdGE6IFtdLCBmaWx0ZXJlZEluZGV4OiBbXX07XG4gIH1cblxuICBpZiAoIWZpbHRlcnMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGEsXG4gICAgICBmaWx0ZXJlZEluZGV4OiBkYXRhLm1hcCgoXywgaSkgPT4gaSksXG4gICAgICBmaWx0ZXJlZEluZGV4Rm9yRG9tYWluOiBkYXRhLm1hcCgoXywgaSkgPT4gaSlcbiAgICB9O1xuICB9XG5cbiAgY29uc3QgYXBwbGllZEZpbHRlcnMgPSBmaWx0ZXJzLmZpbHRlcihcbiAgICBkID0+IGQuZGF0YUlkID09PSBkYXRhSWQgJiYgZC5maWVsZElkeCA+IC0xICYmIGQudmFsdWUgIT09IG51bGxcbiAgKTtcblxuICBjb25zdCBbZHluYW1pY0RvbWFpbkZpbHRlcnMsIGZpeGVkRG9tYWluRmlsdGVyc10gPSBhcHBsaWVkRmlsdGVycy5yZWR1Y2UoXG4gICAgKGFjY3UsIGYpID0+IHtcbiAgICAgIGlmIChmLmRhdGFJZCA9PT0gZGF0YUlkICYmIGYuZmllbGRJZHggPiAtMSAmJiBmLnZhbHVlICE9PSBudWxsKSB7XG4gICAgICAgIChmLmZpeGVkRG9tYWluID8gYWNjdVsxXSA6IGFjY3VbMF0pLnB1c2goZik7XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjdTtcbiAgICB9LFxuICAgIFtbXSwgW11dXG4gICk7XG4gIC8vIGNvbnNvbGUubG9nKGR5bmFtaWNEb21haW5GaWx0ZXJzKVxuICAvLyBjb25zb2xlLmxvZyhmaXhlZERvbWFpbkZpbHRlcnMpXG4gIC8vIHdlIHNhdmUgYSByZWZlcmVuY2Ugb2YgYWxsRGF0YSBpbmRleCBoZXJlIHRvIGFjY2VzcyBkYXRhVG9GZWF0dXJlXG4gIC8vIGluIGdlb2pzb24gYW5kIGhleGdvbklkIGxheWVyXG4gIC8vIGNvbnNvbGUudGltZSgnZmlsdGVyRGF0YScpO1xuXG4gIGNvbnN0IHtmaWx0ZXJlZCwgZmlsdGVyZWRJbmRleCwgZmlsdGVyZWRJbmRleEZvckRvbWFpbn0gPSBkYXRhLnJlZHVjZShcbiAgICAoYWNjdSwgZCwgaSkgPT4ge1xuICAgICAgLy8gZ2VuZXJhdGUgMiBzZXRzIG9mXG4gICAgICAvLyBmaWx0ZXIgZGF0YSB1c2VkIHRvIGNhbGN1bGF0ZSBsYXllciBEb21haW5cbiAgICAgIGNvbnN0IG1hdGNoRm9yRG9tYWluID0gZHluYW1pY0RvbWFpbkZpbHRlcnMuZXZlcnkoZmlsdGVyID0+XG4gICAgICAgIGlzRGF0YU1hdGNoRmlsdGVyKGQsIGZpbHRlciwgaSlcbiAgICAgICk7XG5cbiAgICAgIGlmIChtYXRjaEZvckRvbWFpbikge1xuICAgICAgICBhY2N1LmZpbHRlcmVkSW5kZXhGb3JEb21haW4