UNPKG

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
"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