UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

798 lines (791 loc) 106 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultElevationDimension = exports.defaultDimensions = exports.defaultColorDimension = exports.defaultAggregation = exports["default"] = exports.DECK_AGGREGATION_MAP = void 0; exports.getAggregatedData = getAggregatedData; exports.getDimensionScale = getDimensionScale; exports.getDimensionSortedBins = getDimensionSortedBins; exports.getDimensionValueDomain = getDimensionValueDomain; exports.getGetValue = getGetValue; exports.getScaleFunctor = getScaleFunctor; exports.getValueFunc = getValueFunc; var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _window = require("global/window"); var _utils = require("@kepler.gl/utils"); var _constants = require("@kepler.gl/constants"); 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; } 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; } 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; } } }; } 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; } } 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; } // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project /* eslint-disable guard-for-in */ var AGGREGATION_OPERATION = { SUM: 'SUM', MEAN: 'MEAN', MIN: 'MIN', MAX: 'MAX', COUNT: 'COUNT' }; var MAX_32_BIT_FLOAT = 3.402823466e38; var defaultGetValue = function defaultGetValue(points) { return points.length; }; var defaultGetPoints = function defaultGetPoints(bin) { return bin.points; }; var defaultGetIndex = function defaultGetIndex(bin) { return bin.index; }; var ascending = function ascending(a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; }; function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } function getQuantileDomain(data, valueAccessor) { return data.map(valueAccessor).sort(ascending); } function getOrdinalDomain(data, valueAccessor) { return (0, _toConsumableArray2["default"])(new Set(data.map(valueAccessor))); } var BinSorter = /*#__PURE__*/function () { function BinSorter() { var bins = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; (0, _classCallCheck2["default"])(this, BinSorter); (0, _defineProperty2["default"])(this, "maxCount", void 0); (0, _defineProperty2["default"])(this, "maxValue", void 0); (0, _defineProperty2["default"])(this, "minValue", void 0); (0, _defineProperty2["default"])(this, "totalCount", void 0); (0, _defineProperty2["default"])(this, "aggregatedBins", void 0); (0, _defineProperty2["default"])(this, "sortedBins", void 0); (0, _defineProperty2["default"])(this, "binMap", void 0); this.aggregatedBins = this._getAggregatedBins(bins, props); this._updateMinMaxValues(); this.binMap = this._getBinMap(); } return (0, _createClass2["default"])(BinSorter, [{ key: "_getAggregatedBins", value: function _getAggregatedBins(bins, props) { var _props$getValue = props.getValue, getValue = _props$getValue === void 0 ? defaultGetValue : _props$getValue, _props$getPoints = props.getPoints, getPoints = _props$getPoints === void 0 ? defaultGetPoints : _props$getPoints, _props$getIndex = props.getIndex, getIndex = _props$getIndex === void 0 ? defaultGetIndex : _props$getIndex, filterData = props.filterData; var hasFilter = typeof filterData === 'function'; var aggregatedBins = []; var index = 0; for (var binIndex = 0; binIndex < bins.length; binIndex++) { var bin = bins[binIndex]; var points = getPoints(bin); var i = getIndex(bin); var filteredPoints = hasFilter ? points.filter(filterData) : points; bin.filteredPoints = hasFilter ? filteredPoints : null; var value = filteredPoints.length ? getValue(filteredPoints) : null; if (value !== null && value !== undefined) { aggregatedBins[index] = { i: Number.isFinite(i) ? i : binIndex, value: value, counts: filteredPoints.length }; index++; } } return aggregatedBins; } }, { key: "_updateMinMaxValues", value: function _updateMinMaxValues() { var maxCount = 0; var maxValue = -MAX_32_BIT_FLOAT; var minValue = MAX_32_BIT_FLOAT; var totalCount = 0; var _iterator = _createForOfIteratorHelper(this.aggregatedBins), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var x = _step.value; maxCount = maxCount > x.counts ? maxCount : x.counts; maxValue = maxValue > x.value ? maxValue : x.value; minValue = minValue < x.value ? minValue : x.value; totalCount += x.counts; } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } if (this.aggregatedBins.length === 0) { maxValue = 0; minValue = 0; } this.maxCount = maxCount; this.maxValue = maxValue; this.minValue = minValue; this.totalCount = totalCount; } }, { key: "_getBinMap", value: function _getBinMap() { var binMap = {}; var _iterator2 = _createForOfIteratorHelper(this.aggregatedBins), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var bin = _step2.value; binMap[bin.i] = bin; } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } return binMap; } }, { key: "_percentileToIndex", value: function _percentileToIndex(percentileRange) { var len = this.sortedBins.length; if (len < 2) return [0, 0]; var _percentileRange$map = percentileRange.map(function (n) { return clamp(n, 0, 100); }), _percentileRange$map2 = (0, _slicedToArray2["default"])(_percentileRange$map, 2), lower = _percentileRange$map2[0], upper = _percentileRange$map2[1]; return [Math.ceil(lower / 100 * (len - 1)), Math.floor(upper / 100 * (len - 1))]; } }, { key: "getValueDomainByScale", value: function getValueDomainByScale(scale) { var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [], _ref2 = (0, _slicedToArray2["default"])(_ref, 2), _ref2$ = _ref2[0], lower = _ref2$ === void 0 ? 0 : _ref2$, _ref2$2 = _ref2[1], upper = _ref2$2 === void 0 ? 100 : _ref2$2; if (!this.sortedBins) { this.sortedBins = this.aggregatedBins.sort(function (a, b) { return ascending(a.value, b.value); }); } if (!this.sortedBins.length) return []; var indexEdge = this._percentileToIndex([lower, upper]); return this._getScaleDomain(scale, indexEdge); } }, { key: "_getScaleDomain", value: function _getScaleDomain(scaleType, _ref3) { var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2), lowerIdx = _ref4[0], upperIdx = _ref4[1]; var bins = this.sortedBins; switch (scaleType) { case 'quantize': case 'linear': return [bins[lowerIdx].value, bins[upperIdx].value]; case 'quantile': return getQuantileDomain(bins.slice(lowerIdx, upperIdx + 1), function (d) { return d.value; }); case 'ordinal': return getOrdinalDomain(bins, function (d) { return d.value; }); default: return [bins[lowerIdx].value, bins[upperIdx].value]; } } }, { key: "getValueRange", value: function getValueRange(percentileRange) { if (!this.sortedBins) { this.sortedBins = this.aggregatedBins.sort(function (a, b) { return ascending(a.value, b.value); }); } if (!this.sortedBins.length) return []; var lowerIdx = 0; var upperIdx = this.sortedBins.length - 1; if (Array.isArray(percentileRange)) { var idxRange = this._percentileToIndex(percentileRange); lowerIdx = idxRange[0]; upperIdx = idxRange[1]; } return [this.sortedBins[lowerIdx].value, this.sortedBins[upperIdx].value]; } }]); }(); var DECK_AGGREGATION_MAP = exports.DECK_AGGREGATION_MAP = (0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])({}, AGGREGATION_OPERATION.SUM, _constants.AGGREGATION_TYPES.sum), AGGREGATION_OPERATION.MEAN, _constants.AGGREGATION_TYPES.average), AGGREGATION_OPERATION.MIN, _constants.AGGREGATION_TYPES.minimum), AGGREGATION_OPERATION.MAX, _constants.AGGREGATION_TYPES.maximum); function getValueFunc(aggregation, accessor) { if (!aggregation || !AGGREGATION_OPERATION[aggregation.toUpperCase()]) { _window.console.warn("Aggregation ".concat(aggregation, " is not supported")); } var op = AGGREGATION_OPERATION[aggregation.toUpperCase()] || AGGREGATION_OPERATION.SUM; var keplerOp = DECK_AGGREGATION_MAP[op]; return function (pts) { return (0, _utils.aggregate)(pts.map(accessor), keplerOp); }; } function getScaleFunctor(scaleType) { if (!scaleType || !_constants.SCALE_FUNC[scaleType]) { _window.console.warn("Scale ".concat(scaleType, " is not supported")); } return _constants.SCALE_FUNC[scaleType] || _constants.SCALE_FUNC.quantize; } function nop() { return; } function getGetValue(step, props, dimensionUpdater) { var key = dimensionUpdater.key; var _step$triggers = step.triggers, value = _step$triggers.value, weight = _step$triggers.weight, aggregation = _step$triggers.aggregation; var getValue = props[value.prop]; if (getValue === null) { // If `getValue` is not provided from props, build it with aggregation and weight. getValue = getValueFunc(props[aggregation.prop], props[weight.prop]); } if (getValue) { this._setDimensionState(key, { getValue: getValue }); } } function getDimensionSortedBins(step, props, dimensionUpdater) { var key = dimensionUpdater.key; var getValue = this.state.dimensions[key].getValue; var sortedBins = new BinSorter(this.state.layerData.data || [], { getValue: getValue, filterData: props._filterData }); this._setDimensionState(key, { sortedBins: sortedBins }); } function getDimensionValueDomain(step, props, dimensionUpdater) { var key = dimensionUpdater.key; var _step$triggers2 = step.triggers, lowerPercentile = _step$triggers2.lowerPercentile, upperPercentile = _step$triggers2.upperPercentile, scaleType = _step$triggers2.scaleType; if (!this.state.dimensions[key].sortedBins) { // the previous step should set sortedBins, if not, something went wrong return; } var valueDomain = // for log and sqrt scale, returns linear domain by default // TODO: support other scale function domain in bin sorter this.state.dimensions[key].sortedBins.getValueDomainByScale(props[scaleType.prop], [props[lowerPercentile.prop], props[upperPercentile.prop]]); if (props.colorScaleType === 'custom' && props.colorMap) { // for custom scale, return custom breaks as value domain directly valueDomain = props.colorMap.reduce(function (prev, cur) { return Number.isFinite(cur[0]) ? prev.concat(cur[0]) : prev; }, []); } this._setDimensionState(key, { valueDomain: valueDomain }); } function getDimensionScale(step, props, dimensionUpdater) { var key = dimensionUpdater.key; var _step$triggers3 = step.triggers, domain = _step$triggers3.domain, range = _step$triggers3.range, scaleType = _step$triggers3.scaleType, fixed = _step$triggers3.fixed; var onSet = step.onSet; if (!this.state.dimensions[key].valueDomain) { // the previous step should set valueDomain, if not, something went wrong return; } var dimensionRange = props[range.prop]; var dimensionDomain = props[domain.prop] || this.state.dimensions[key].valueDomain; var dimensionFixed = Boolean(fixed && props[fixed.prop]); var scaleFunctor = getScaleFunctor(scaleType && props[scaleType.prop])(); var scaleFunc = scaleFunctor.domain(dimensionDomain).range(dimensionFixed ? dimensionDomain : dimensionRange); scaleFunc.scaleType = props.colorScaleType; if ((0, _typeof2["default"])(onSet) === 'object' && typeof props[onSet.props] === 'function') { var sortedBins = this.state.dimensions[key].sortedBins; if (sortedBins) { props[onSet.props]({ domain: scaleFunc.domain(), aggregatedBins: sortedBins.binMap }); } } this._setDimensionState(key, { scaleFunc: scaleFunc }); } function normalizeResult() { var result = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; // support previous hexagonAggregator API if (result.hexagons) { return Object.assign({ data: result.hexagons }, result); } else if (result.layerData) { return Object.assign({ data: result.layerData }, result); } return result; } function getAggregatedData(step, props, aggregation, aggregationParams) { var aggr = step.triggers.aggregator; var aggregator = props[aggr.prop]; // result should contain a data array and other props // result = {data: [], ...other props} var result = aggregator(props, aggregationParams); this.setState({ layerData: normalizeResult(result) }); } var defaultAggregation = exports.defaultAggregation = { key: 'position', updateSteps: [{ key: 'aggregate', triggers: { cellSize: { prop: 'cellSize' }, position: { prop: 'getPosition', updateTrigger: 'getPosition' }, aggregator: { prop: 'gridAggregator' } }, updater: getAggregatedData }] }; function getSubLayerAccessor(dimensionState, dimension) { return function (cell) { var sortedBins = dimensionState.sortedBins, scaleFunc = dimensionState.scaleFunc; var bin = sortedBins.binMap[cell.index]; if (bin && bin.counts === 0) { // no points left in bin after filtering return dimension.nullValue; } var cv = bin && bin.value; var domain = scaleFunc.domain(); var isValueInDomain = scaleFunc.scaleType === 'custom' ? cv >= sortedBins.minValue && cv <= sortedBins.maxValue : cv >= domain[0] && cv <= domain[domain.length - 1]; // if cell value is outside domain, set alpha to 0 return isValueInDomain ? scaleFunc(cv) : dimension.nullValue; }; } var defaultColorDimension = exports.defaultColorDimension = { key: 'fillColor', accessor: 'getFillColor', getPickingInfo: function getPickingInfo(dimensionState, cell) { if (!cell) { return {}; } var sortedBins = dimensionState.sortedBins; var colorValue = sortedBins.binMap[cell.index] && sortedBins.binMap[cell.index].value; return { colorValue: colorValue }; }, nullValue: [0, 0, 0, 0], updateSteps: [{ key: 'getValue', triggers: { value: { prop: 'getColorValue', updateTrigger: 'getColorValue' }, weight: { prop: 'getColorWeight', updateTrigger: 'getColorWeight' }, aggregation: { prop: 'colorAggregation' } }, updater: getGetValue }, { key: 'getBins', triggers: { _filterData: { prop: '_filterData', updateTrigger: '_filterData' } }, updater: getDimensionSortedBins }, { key: 'getDomain', triggers: { lowerPercentile: { prop: 'lowerPercentile' }, upperPercentile: { prop: 'upperPercentile' }, scaleType: { prop: 'colorScaleType' } }, updater: getDimensionValueDomain }, { key: 'getScaleFunc', triggers: { domain: { prop: 'colorDomain' }, range: { prop: 'colorRange' }, scaleType: { prop: 'colorScaleType' } }, onSet: { props: 'onSetColorDomain' }, updater: getDimensionScale }], getSubLayerAccessor: getSubLayerAccessor }; var defaultElevationDimension = exports.defaultElevationDimension = { key: 'elevation', accessor: 'getElevation', getPickingInfo: function getPickingInfo(dimensionState, cell) { if (!cell) { return {}; } var sortedBins = dimensionState.sortedBins; var elevationValue = sortedBins.binMap[cell.index] && sortedBins.binMap[cell.index].value; return { elevationValue: elevationValue }; }, nullValue: -1, updateSteps: [{ key: 'getValue', triggers: { value: { prop: 'getElevationValue', updateTrigger: 'getElevationValue' }, weight: { prop: 'getElevationWeight', updateTrigger: 'getElevationWeight' }, aggregation: { prop: 'elevationAggregation' } }, updater: getGetValue }, { key: 'getBins', triggers: { _filterData: { prop: '_filterData', updateTrigger: '_filterData' } }, updater: getDimensionSortedBins }, { key: 'getDomain', triggers: { lowerPercentile: { prop: 'elevationLowerPercentile' }, upperPercentile: { prop: 'elevationUpperPercentile' }, scaleType: { prop: 'elevationScaleType' } }, updater: getDimensionValueDomain }, { key: 'getScaleFunc', triggers: { fixed: { prop: 'elevationFixed' }, domain: { prop: 'elevationDomain' }, range: { prop: 'elevationRange' }, scaleType: { prop: 'elevationScaleType' } }, onSet: { props: 'onSetElevationDomain' }, updater: getDimensionScale }], getSubLayerAccessor: getSubLayerAccessor }; var _defaultDimensions = exports.defaultDimensions = [defaultColorDimension, defaultElevationDimension]; var CPUAggregator = exports["default"] = /*#__PURE__*/function () { function CPUAggregator() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _classCallCheck2["default"])(this, CPUAggregator); (0, _defineProperty2["default"])(this, "state", void 0); (0, _defineProperty2["default"])(this, "dimensionUpdaters", void 0); (0, _defineProperty2["default"])(this, "aggregationUpdater", void 0); this.state = _objectSpread({ layerData: {}, dimensions: { // color: { // getValue: null, // domain: null, // sortedBins: null, // scaleFunc: nop // }, // elevation: { // getValue: null, // domain: null, // sortedBins: null, // scaleFunc: nop // } } }, opts.initialState); this.dimensionUpdaters = {}; this.aggregationUpdater = opts.aggregation || defaultAggregation; this._addDimension(opts.dimensions || _defaultDimensions); } return (0, _createClass2["default"])(CPUAggregator, [{ key: "updateAllDimensions", value: function updateAllDimensions(props) { var dimensionChanges = []; // update all dimensions for (var dim in this.dimensionUpdaters) { var updaters = this._accumulateUpdaters(0, props, this.dimensionUpdaters[dim]); dimensionChanges = dimensionChanges.concat(updaters); } dimensionChanges.forEach(function (f) { return typeof f === 'function' && f(); }); } }, { key: "updateAggregation", value: function updateAggregation(props, aggregationParams) { var updaters = this._accumulateUpdaters(0, props, this.aggregationUpdater); updaters.forEach(function (f) { return typeof f === 'function' && f(aggregationParams); }); } }, { key: "updateState", value: function updateState(opts, aggregationParams) { var oldProps = opts.oldProps, props = opts.props, changeFlags = opts.changeFlags; var dimensionChanges = []; if (changeFlags.dataChanged) { // if data changed update everything this.updateAggregation(props, aggregationParams); this.updateAllDimensions(props); return this.state; } var aggregationChanges = this._getAggregationChanges(oldProps, props, changeFlags); if (aggregationChanges && aggregationChanges.length) { // get aggregatedData aggregationChanges.forEach(function (f) { return typeof f === 'function' && f(aggregationParams); }); this.updateAllDimensions(props); } else { // only update dimensions dimensionChanges = this._getDimensionChanges(oldProps, props, changeFlags) || []; dimensionChanges.forEach(function (f) { return typeof f === 'function' && f(); }); } return this.state; } // Update private state }, { key: "setState", value: function setState(updateObject) { this.state = Object.assign({}, this.state, updateObject); } // Update private state.dimensions }, { key: "_setDimensionState", value: function _setDimensionState(key, updateObject) { this.setState({ dimensions: Object.assign({}, this.state.dimensions, (0, _defineProperty2["default"])({}, key, Object.assign({}, this.state.dimensions[key], updateObject))) }); } }, { key: "_addAggregation", value: function _addAggregation(aggregation) { this.aggregationUpdater = aggregation; } }, { key: "_addDimension", value: function _addDimension() { var _this = this; var dimensions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; dimensions.forEach(function (dimension) { var key = dimension.key; _this.dimensionUpdaters[key] = dimension; }); } }, { key: "_needUpdateStep", value: function _needUpdateStep(dimensionStep, oldProps, props, changeFlags) { // whether need to update current dimension step // dimension step is the value, domain, scaleFunction of each dimension // each step is an object with properties links to layer prop and whether the prop is // controlled by updateTriggers return Object.values(dimensionStep.triggers).some(function (item) { if (item.updateTrigger) { // check based on updateTriggers change first return changeFlags.updateTriggersChanged && (changeFlags.updateTriggersChanged.all || changeFlags.updateTriggersChanged[item.updateTrigger]); } // fallback to direct comparison return oldProps[item.prop] !== props[item.prop]; }); } }, { key: "_accumulateUpdaters", value: function _accumulateUpdaters(step, props, dimension) { var updaters = []; for (var i = step; i < dimension.updateSteps.length; i++) { var updater = dimension.updateSteps[i].updater; if (typeof updater === 'function') { updaters.push(updater.bind(this, dimension.updateSteps[i], props, dimension)); } } return updaters; } }, { key: "_getAllUpdaters", value: function _getAllUpdaters(dimension, oldProps, props, changeFlags) { var _this2 = this; var updaters = []; var needUpdateStep = dimension.updateSteps.findIndex(function (step) { return _this2._needUpdateStep(step, oldProps, props, changeFlags); }); if (needUpdateStep > -1) { updaters = updaters.concat(this._accumulateUpdaters(needUpdateStep, props, dimension)); } return updaters; } }, { key: "_getAggregationChanges", value: function _getAggregationChanges(oldProps, props, changeFlags) { var updaters = this._getAllUpdaters(this.aggregationUpdater, oldProps, props, changeFlags); return updaters.length ? updaters : null; } }, { key: "_getDimensionChanges", value: function _getDimensionChanges(oldProps, props, changeFlags) { var updaters = []; // get dimension to be updated for (var key in this.dimensionUpdaters) { // return the first triggered updater for each dimension var dimension = this.dimensionUpdaters[key]; var dimensionUpdaters = this._getAllUpdaters(dimension, oldProps, props, changeFlags); updaters = updaters.concat(dimensionUpdaters); } return updaters.length ? updaters : null; } }, { key: "getUpdateTriggers", value: function getUpdateTriggers(props) { var _this3 = this; var _updateTriggers = props.updateTriggers || {}; var updateTriggers = {}; var _loop = function _loop() { var _this3$dimensionUpdat = _this3.dimensionUpdaters[key], accessor = _this3$dimensionUpdat.accessor, updateSteps = _this3$dimensionUpdat.updateSteps; // fold dimension triggers into each accessor updateTriggers[accessor] = {}; updateSteps.forEach(function (step) { Object.values(step.triggers || []).forEach(function (_ref5) { var prop = _ref5.prop, updateTrigger = _ref5.updateTrigger; if (updateTrigger) { // if prop is based on updateTrigger e.g. getColorValue, getColorWeight // and updateTriggers is passed in from layer prop // fold the updateTriggers into accessor var fromProp = _updateTriggers[updateTrigger]; if ((0, _typeof2["default"])(fromProp) === 'object' && !Array.isArray(fromProp)) { // if updateTrigger is an object spread it Object.assign(updateTriggers[accessor], fromProp); } else if (fromProp !== undefined) { updateTriggers[accessor][prop] = fromProp; } } else { // if prop is not based on updateTrigger updateTriggers[accessor][prop] = props[prop]; } }); }); }; for (var key in this.dimensionUpdaters) { _loop(); } return updateTriggers; } }, { key: "getPickingInfo", value: function getPickingInfo(_ref6, layerProps) { var _this$state$layerData; var info = _ref6.info; var isPicked = info.picked && info.index > -1; var object = null; var cell = isPicked ? (_this$state$layerData = this.state.layerData.data) === null || _this$state$layerData === void 0 ? void 0 : _this$state$layerData[info.index] : null; if (cell) { var binInfo = {}; for (var key in this.dimensionUpdaters) { var _getPickingInfo = this.dimensionUpdaters[key].getPickingInfo; if (typeof _getPickingInfo === 'function') { binInfo = Object.assign({}, binInfo, _getPickingInfo(this.state.dimensions[key], cell, layerProps)); } } object = Object.assign(binInfo, cell, { points: cell.filteredPoints || cell.points }); } // add bin and to info return Object.assign(info, { picked: Boolean(object), // override object with picked cell object: object }); } }, { key: "getAccessor", value: function getAccessor(dimensionKey, layerProps) { if (!Object.prototype.hasOwnProperty.call(this.dimensionUpdaters, dimensionKey)) { return nop; } return this.dimensionUpdaters[dimensionKey].getSubLayerAccessor(this.state.dimensions[dimensionKey], this.dimensionUpdaters[dimensionKey], layerProps); } }], [{ key: "defaultDimensions", value: function defaultDimensions() { return _defaultDimensions; } }]); }(); (0, _defineProperty2["default"])(CPUAggregator, "getDimensionScale", void 0); CPUAggregator.getDimensionScale = getDimensionScale; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfd2luZG93IiwicmVxdWlyZSIsIl91dGlscyIsIl9jb25zdGFudHMiLCJvd25LZXlzIiwiZSIsInIiLCJ0IiwiT2JqZWN0Iiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJkZWZpbmVQcm9wZXJ0eSIsIl9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyIiwiU3ltYm9sIiwiaXRlcmF0b3IiLCJBcnJheSIsImlzQXJyYXkiLCJfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkiLCJfbiIsIkYiLCJzIiwibiIsImRvbmUiLCJ2YWx1ZSIsImYiLCJUeXBlRXJyb3IiLCJhIiwidSIsImNhbGwiLCJuZXh0IiwiX2FycmF5TGlrZVRvQXJyYXkiLCJ0b1N0cmluZyIsInNsaWNlIiwiY29uc3RydWN0b3IiLCJuYW1lIiwiZnJvbSIsInRlc3QiLCJBR0dSRUdBVElPTl9PUEVSQVRJT04iLCJTVU0iLCJNRUFOIiwiTUlOIiwiTUFYIiwiQ09VTlQiLCJNQVhfMzJfQklUX0ZMT0FUIiwiZGVmYXVsdEdldFZhbHVlIiwicG9pbnRzIiwiZGVmYXVsdEdldFBvaW50cyIsImJpbiIsImRlZmF1bHRHZXRJbmRleCIsImluZGV4IiwiYXNjZW5kaW5nIiwiYiIsIk5hTiIsImNsYW1wIiwibWluIiwibWF4IiwiTWF0aCIsImdldFF1YW50aWxlRG9tYWluIiwiZGF0YSIsInZhbHVlQWNjZXNzb3IiLCJtYXAiLCJzb3J0IiwiZ2V0T3JkaW5hbERvbWFpbiIsIl90b0NvbnN1bWFibGVBcnJheTIiLCJTZXQiLCJCaW5Tb3J0ZXIiLCJiaW5zIiwidW5kZWZpbmVkIiwicHJvcHMiLCJfY2xhc3NDYWxsQ2hlY2syIiwiYWdncmVnYXRlZEJpbnMiLCJfZ2V0QWdncmVnYXRlZEJpbnMiLCJfdXBkYXRlTWluTWF4VmFsdWVzIiwiYmluTWFwIiwiX2dldEJpbk1hcCIsIl9jcmVhdGVDbGFzczIiLCJrZXkiLCJfcHJvcHMkZ2V0VmFsdWUiLCJnZXRWYWx1ZSIsIl9wcm9wcyRnZXRQb2ludHMiLCJnZXRQb2ludHMiLCJfcHJvcHMkZ2V0SW5kZXgiLCJnZXRJbmRleCIsImZpbHRlckRhdGEiLCJoYXNGaWx0ZXIiLCJiaW5JbmRleCIsImkiLCJmaWx0ZXJlZFBvaW50cyIsIk51bWJlciIsImlzRmluaXRlIiwiY291bnRzIiwibWF4Q291bnQiLCJtYXhWYWx1ZSIsIm1pblZhbHVlIiwidG90YWxDb3VudCIsIl9pdGVyYXRvciIsIl9zdGVwIiwieCIsImVyciIsIl9pdGVyYXRvcjIiLCJfc3RlcDIiLCJfcGVyY2VudGlsZVRvSW5kZXgiLCJwZXJjZW50aWxlUmFuZ2UiLCJsZW4iLCJzb3J0ZWRCaW5zIiwiX3BlcmNlbnRpbGVSYW5nZSRtYXAiLCJfcGVyY2VudGlsZVJhbmdlJG1hcDIiLCJfc2xpY2VkVG9BcnJheTIiLCJsb3dlciIsInVwcGVyIiwiY2VpbCIsImZsb29yIiwiZ2V0VmFsdWVEb21haW5CeVNjYWxlIiwic2NhbGUiLCJfcmVmIiwiX3JlZjIiLCJfcmVmMiQiLCJfcmVmMiQyIiwiaW5kZXhFZGdlIiwiX2dldFNjYWxlRG9tYWluIiwic2NhbGVUeXBlIiwiX3JlZjMiLCJfcmVmNCIsImxvd2VySWR4IiwidXBwZXJJZHgiLCJkIiwiZ2V0VmFsdWVSYW5nZSIsImlkeFJhbmdlIiwiREVDS19BR0dSRUdBVElPTl9NQVAiLCJleHBvcnRzIiwiQUdHUkVHQVRJT05fVFlQRVMiLCJzdW0iLCJhdmVyYWdlIiwibWluaW11bSIsIm1heGltdW0iLCJnZXRWYWx1ZUZ1bmMiLCJhZ2dyZWdhdGlvbiIsImFjY2Vzc29yIiwidG9VcHBlckNhc2UiLCJDb25zb2xlIiwid2FybiIsImNvbmNhdCIsIm9wIiwia2VwbGVyT3AiLCJwdHMiLCJhZ2dyZWdhdGUiLCJnZXRTY2FsZUZ1bmN0b3IiLCJTQ0FMRV9GVU5DIiwicXVhbnRpemUiLCJub3AiLCJnZXRHZXRWYWx1ZSIsInN0ZXAiLCJkaW1lbnNpb25VcGRhdGVyIiwiX3N0ZXAkdHJpZ2dlcnMiLCJ0cmlnZ2VycyIsIndlaWdodCIsInByb3AiLCJfc2V0RGltZW5zaW9uU3RhdGUiLCJnZXREaW1lbnNpb25Tb3J0ZWRCaW5zIiwic3RhdGUiLCJkaW1lbnNpb25zIiwibGF5ZXJEYXRhIiwiX2ZpbHRlckRhdGEiLCJnZXREaW1lbnNpb25WYWx1ZURvbWFpbiIsIl9zdGVwJHRyaWdnZXJzMiIsImxvd2VyUGVyY2VudGlsZSIsInVwcGVyUGVyY2VudGlsZSIsInZhbHVlRG9tYWluIiwiY29sb3JTY2FsZVR5cGUiLCJjb2xvck1hcCIsInJlZHVjZSIsInByZXYiLCJjdXIiLCJnZXREaW1lbnNpb25TY2FsZSIsIl9zdGVwJHRyaWdnZXJzMyIsImRvbWFpbiIsInJhbmdlIiwiZml4ZWQiLCJvblNldCIsImRpbWVuc2lvblJhbmdlIiwiZGltZW5zaW9uRG9tYWluIiwiZGltZW5zaW9uRml4ZWQiLCJCb29sZWFuIiwic2NhbGVGdW5jdG9yIiwic2NhbGVGdW5jIiwiX3R5cGVvZjIiLCJub3JtYWxpemVSZXN1bHQiLCJyZXN1bHQiLCJoZXhhZ29ucyIsImFzc2lnbiIsImdldEFnZ3JlZ2F0ZWREYXRhIiwiYWdncmVnYXRpb25QYXJhbXMiLCJhZ2dyIiwiYWdncmVnYXRvciIsInNldFN0YXRlIiwiZGVmYXVsdEFnZ3JlZ2F0aW9uIiwidXBkYXRlU3RlcHMiLCJjZWxsU2l6ZSIsInBvc2l0aW9uIiwidXBkYXRlVHJpZ2dlciIsInVwZGF0ZXIiLCJnZXRTdWJMYXllckFjY2Vzc29yIiwiZGltZW5zaW9uU3RhdGUiLCJkaW1lbnNpb24iLCJjZWxsIiwibnVsbFZhbHVlIiwiY3YiLCJpc1ZhbHVlSW5Eb21haW4iLCJkZWZhdWx0Q29sb3JEaW1lbnNpb24iLCJnZXRQaWNraW5nSW5mbyIsImNvbG9yVmFsdWUiLCJkZWZhdWx0RWxldmF0aW9uRGltZW5zaW9uIiwiZWxldmF0aW9uVmFsdWUiLCJkZWZhdWx0RGltZW5zaW9ucyIsIkNQVUFnZ3JlZ2F0b3IiLCJvcHRzIiwiaW5pdGlhbFN0YXRlIiwiZGltZW5zaW9uVXBkYXRlcnMiLCJhZ2dyZWdhdGlvblVwZGF0ZXIiLCJfYWRkRGltZW5zaW9uIiwidXBkYXRlQWxsRGltZW5zaW9ucyIsImRpbWVuc2lvbkNoYW5nZXMiLCJkaW0iLCJ1cGRhdGVycyIsIl9hY2N1bXVsYXRlVXBkYXRlcnMiLCJ1cGRhdGVBZ2dyZWdhdGlvbiIsInVwZGF0ZVN0YXRlIiwib2xkUHJvcHMiLCJjaGFuZ2VGbGFncyIsImRhdGFDaGFuZ2VkIiwiYWdncmVnYXRpb25DaGFuZ2VzIiwiX2dldEFnZ3JlZ2F0aW9uQ2hhbmdlcyIsIl9nZXREaW1lbnNpb25DaGFuZ2VzIiwidXBkYXRlT2JqZWN0IiwiX2FkZEFnZ3JlZ2F0aW9uIiwiX3RoaXMiLCJfbmVlZFVwZGF0ZVN0ZXAiLCJkaW1lbnNpb25TdGVwIiwidmFsdWVzIiwic29tZSIsIml0ZW0iLCJ1cGRhdGVUcmlnZ2Vyc0NoYW5nZWQiLCJhbGwiLCJiaW5kIiwiX2dldEFsbFVwZGF0ZXJzIiwiX3RoaXMyIiwibmVlZFVwZGF0ZVN0ZXAiLCJmaW5kSW5kZXgiLCJnZXRVcGRhdGVUcmlnZ2VycyIsIl90aGlzMyIsIl91cGRhdGVUcmlnZ2VycyIsInVwZGF0ZVRyaWdnZXJzIiwiX2xvb3AiLCJfdGhpczMkZGltZW5zaW9uVXBkYXQiLCJfcmVmNSIsImZyb21Qcm9wIiwiX3JlZjYiLCJsYXllclByb3BzIiwiX3RoaXMkc3RhdGUkbGF5ZXJEYXRhIiwiaW5mbyIsImlzUGlja2VkIiwicGlja2VkIiwib2JqZWN0IiwiYmluSW5mbyIsImdldEFjY2Vzc29yIiwiZGltZW5zaW9uS2V5IiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvbGF5ZXItdXRpbHMvY3B1LWFnZ3JlZ2F0b3IudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuLyogZXNsaW50LWRpc2FibGUgZ3VhcmQtZm9yLWluICovXG5pbXBvcnQge2NvbnNvbGUgYXMgQ29uc29sZX0gZnJvbSAnZ2xvYmFsL3dpbmRvdyc7XG5cbmltcG9ydCB7YWdncmVnYXRlfSBmcm9tICdAa2VwbGVyLmdsL3V0aWxzJztcbmltcG9ydCB7QUdHUkVHQVRJT05fVFlQRVMsIFNDQUxFX0ZVTkN9IGZyb20gJ0BrZXBsZXIuZ2wvY29uc3RhbnRzJztcbmltcG9ydCB7UkdCQUNvbG9yfSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcbmltcG9ydCB0eXBlIENsdXN0ZXJCdWlsZGVyIGZyb20gJy4vY2x1c3Rlci11dGlscyc7XG5cbmNvbnN0IEFHR1JFR0FUSU9OX09QRVJBVElPTiA9IHtcbiAgU1VNOiAnU1VNJyBhcyBjb25zdCxcbiAgTUVBTjogJ01FQU4nIGFzIGNvbnN0LFxuICBNSU46ICdNSU4nIGFzIGNvbnN0LFxuICBNQVg6ICdNQVgnIGFzIGNvbnN0LFxuICBDT1VOVDogJ0NPVU5UJyBhcyBjb25zdFxufTtcblxuY29uc3QgTUFYXzMyX0JJVF9GTE9BVCA9IDMuNDAyODIzNDY2ZTM4O1xuXG5pbnRlcmZhY2UgQmluIHtcbiAgcG9pbnRzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdO1xuICBmaWx0ZXJlZFBvaW50cz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+W10gfCBudWxsO1xuICBpbmRleD86IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIEFnZ3JlZ2F0ZWRCaW4ge1xuICBpOiBudW1iZXI7XG4gIHZhbHVlOiBudW1iZXI7XG4gIGNvdW50czogbnVtYmVyO1xufVxuXG5jb25zdCBkZWZhdWx0R2V0VmFsdWUgPSAocG9pbnRzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdKSA9PiBwb2ludHMubGVuZ3RoO1xuY29uc3QgZGVmYXVsdEdldFBvaW50cyA9IChiaW46IEJpbikgPT4gYmluLnBvaW50cztcbmNvbnN0IGRlZmF1bHRHZXRJbmRleCA9IChiaW46IEJpbikgPT4gYmluLmluZGV4O1xuY29uc3QgYXNjZW5kaW5nID0gKGE6IG51bWJlciwgYjogbnVtYmVyKSA9PiAoYSA8IGIgPyAtMSA6IGEgPiBiID8gMSA6IGEgPj0gYiA/IDAgOiBOYU4pO1xuXG5mdW5jdGlvbiBjbGFtcCh2YWx1ZTogbnVtYmVyLCBtaW46IG51bWJlciwgbWF4OiBudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgubWF4KG1pbiwgTWF0aC5taW4obWF4LCB2YWx1ZSkpO1xufVxuXG5mdW5jdGlvbiBnZXRRdWFudGlsZURvbWFpbihkYXRhOiBBZ2dyZWdhdGVkQmluW10sIHZhbHVlQWNjZXNzb3I6IChkOiBBZ2dyZWdhdGVkQmluKSA9PiBudW1iZXIpIHtcbiAgcmV0dXJuIGRhdGEubWFwKHZhbHVlQWNjZXNzb3IpLnNvcnQoYXNjZW5kaW5nKTtcbn1cblxuZnVuY3Rpb24gZ2V0T3JkaW5hbERvbWFpbihkYXRhOiBBZ2dyZWdhdGVkQmluW10sIHZhbHVlQWNjZXNzb3I6IChkOiBBZ2dyZWdhdGVkQmluKSA9PiBudW1iZXIpIHtcbiAgcmV0dXJuIFsuLi5uZXcgU2V0KGRhdGEubWFwKHZhbHVlQWNjZXNzb3IpKV07XG59XG5cbmNsYXNzIEJpblNvcnRlciB7XG4gIG1heENvdW50ITogbnVtYmVyO1xuICBtYXhWYWx1ZSE6IG51bWJlcjtcbiAgbWluVmFsdWUhOiBudW1iZXI7XG4gIHRvdGFsQ291bnQhOiBudW1iZXI7XG4gIGFnZ3JlZ2F0ZWRCaW5zOiBBZ2dyZWdhdGVkQmluW107XG4gIHNvcnRlZEJpbnMhOiBBZ2dyZWdhdGVkQmluW107XG4gIGJpbk1hcDogUmVjb3JkPG51bWJlciwgQWdncmVnYXRlZEJpbj47XG5cbiAgY29uc3RydWN0b3IoYmluczogQmluW10gPSBbXSwgcHJvcHM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fSkge1xuICAgIHRoaXMuYWdncmVnYXRlZEJpbnMgPSB0aGlzLl9nZXRBZ2dyZWdhdGVkQmlucyhiaW5zLCBwcm9wcyk7XG4gICAgdGhpcy5fdXBkYXRlTWluTWF4VmFsdWVzKCk7XG4gICAgdGhpcy5iaW5NYXAgPSB0aGlzLl9nZXRCaW5NYXAoKTtcbiAgfVxuXG4gIF9nZXRBZ2dyZWdhdGVkQmlucyhiaW5zOiBCaW5bXSwgcHJvcHM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBBZ2dyZWdhdGVkQmluW10ge1xuICAgIGNvbnN0IHtcbiAgICAgIGdldFZhbHVlID0gZGVmYXVsdEdldFZhbHVlLFxuICAgICAgZ2V0UG9pbnRzID0gZGVmYXVsdEdldFBvaW50cyxcbiAgICAgIGdldEluZGV4ID0gZGVmYXVsdEdldEluZGV4LFxuICAgICAgZmlsdGVyRGF0YVxuICAgIH0gPSBwcm9wcztcbiAgICBjb25zdCBoYXNGaWx0ZXIgPSB0eXBlb2YgZmlsdGVyRGF0YSA9PT0gJ2Z1bmN0aW9uJztcbiAgICBjb25zdCBhZ2dyZWdhdGVkQmluczogQWdncmVnYXRlZEJpbltdID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcbiAgICBmb3IgKGxldCBiaW5JbmRleCA9IDA7IGJpbkluZGV4IDwgYmlucy5sZW5ndGg7IGJpbkluZGV4KyspIHtcbiAgICAgIGNvbnN0IGJpbiA9IGJpbnNbYmluSW5kZXhdO1xuICAgICAgY29uc3QgcG9pbnRzID0gZ2V0UG9pbnRzKGJpbik7XG4gICAgICBjb25zdCBpID0gZ2V0SW5kZXgoYmluKTtcbiAgICAgIGNvbnN0IGZpbHRlcmVkUG9pbnRzID0gaGFzRmlsdGVyID8gcG9pbnRzLmZpbHRlcihmaWx0ZXJEYXRhKSA6IHBvaW50cztcbiAgICAgIGJpbi5maWx0ZXJlZFBvaW50cyA9IGhhc0ZpbHRlciA/IGZpbHRlcmVkUG9pbnRzIDogbnVsbDtcbiAgICAgIGNvbnN0IHZhbHVlID0gZmlsdGVyZWRQb2ludHMubGVuZ3RoID8gZ2V0VmFsdWUoZmlsdGVyZWRQb2ludHMpIDogbnVsbDtcbiAgICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGFnZ3JlZ2F0ZWRCaW5zW2luZGV4XSA9IHtcbiAgICAgICAgICBpOiBOdW1iZXIuaXNGaW5pdGUoaSkgPyBpIDogYmluSW5kZXgsXG4gICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgY291bnRzOiBmaWx0ZXJlZFBvaW50cy5sZW5ndGhcbiAgICAgICAgfTtcbiAgICAgICAgaW5kZXgrKztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFnZ3JlZ2F0ZWRCaW5zO1xuICB9XG5cbiAgX3VwZGF0ZU1pbk1heFZhbHVlcygpIHtcbiAgICBsZXQgbWF4Q291bnQgPSAwO1xuICAgIGxldCBtYXhWYWx1ZSA9IC1NQVhfMzJfQklUX0ZMT0FUO1xuICAgIGxldCBtaW5WYWx1ZSA9IE1BWF8zMl9CSVRfRkxPQVQ7XG4gICAgbGV0IHRvdGFsQ291bnQgPSAwO1xuICAgIGZvciAoY29uc3QgeCBvZiB0aGlzLmFnZ3JlZ2F0ZWRCaW5zKSB7XG4gICAgICBtYXhDb3VudCA9IG1heENvdW50ID4geC5jb3VudHMgPyBtYXhDb3VudCA6IHguY291bnRzO1xuICAgICAgbWF4VmFsdWUgPSBtYXhWYWx1ZSA+IHgudmFsdWUgPyBtYXhWYWx1ZSA6IHgudmFsdWU7XG4gICAgICBtaW5WYWx1ZSA9IG1pblZhbHVlIDwgeC52YWx1ZSA/IG1pblZhbHVlIDogeC52YWx1ZTtcbiAgICAgIHRvdGFsQ291bnQgKz0geC5jb3VudHM7XG4gICAgfVxuICAgIGlmICh0aGlzLmFnZ3JlZ2F0ZWRCaW5zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgbWF4VmFsdWUgPSAwO1xuICAgICAgbWluVmFsdWUgPSAwO1xuICAgIH1cbiAgICB0aGlzLm1heENvdW50ID0gbWF4Q291bnQ7XG4gICAgdGhpcy5tYXhWYWx1ZSA9IG1heFZhbHVlO1xuICAgIHRoaXMubWluVmFsdWUgPSBtaW5WYWx1ZTtcbiAgICB0aGlzLnRvdGFsQ291bnQgPSB0b3RhbENvdW50O1xuICB9XG5cbiAgX2dldEJpbk1hcCgpIHtcbiAgICBjb25zdCBiaW5NYXAgPSB7fTtcbiAgICBmb3IgKGNvbnN0IGJpbiBvZiB0aGlzLmFnZ3JlZ2F0ZWRCaW5zKSB7XG4gICAgICBiaW5NYXBbYmluLmldID0gYmluO1xuICAgIH1cbiAgICByZXR1cm4gYmluTWFwO1xuICB9XG5cbiAgX3BlcmNlbnRpbGVUb0luZGV4KHBlcmNlbnRpbGVSYW5nZTogbnVtYmVyW10pIHtcbiAgICBjb25zdCBsZW4gPSB0aGlzLnNvcnRlZEJpbnMubGVuZ3RoO1xuICAgIGlmIChsZW4gPCAyKSByZXR1cm4gWzAsIDBdO1xuICAgIGNvbnN0IFtsb3dlciwgdXBwZXJdID0gcGVyY2VudGlsZVJhbmdlLm1hcChuID0+IGNsYW1wKG4sIDAsIDEwMCkpO1xuICAgIHJldHVybiBbTWF0aC5jZWlsKChsb3dlciAvIDEwMCkgKiAobGVuIC0gMSkpLCBNYXRoLmZsb29yKCh1cHBlciAvIDEwMCkgKiAobGVuIC0gMSkpXTtcbiAgfVxuXG4gIGdldFZhbHVlRG9tYWluQnlTY2FsZShzY2FsZTogc3RyaW5nLCBbbG93ZXIgPSAwLCB1cHBlciA9IDEwMF06IG51bWJlcltdID0gW10pIHtcbiAgICBpZiAoIXRoaXMuc29ydGVkQmlucykge1xuICAgICAgdGhpcy5zb3J0ZWRCaW5zID0gdGhpcy5hZ2dyZWdhdGVkQmlucy5zb3J0KChhLCBiKSA9PiBhc2NlbmRpbmcoYS52YWx1ZSwgYi52YWx1ZSkpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuc29ydGVkQmlucy5sZW5ndGgpIHJldHVybiBbXTtcbiAgICBjb25zdCBpbmRleEVkZ2UgPSB0aGlzLl9wZXJjZW50aWxlVG9JbmRleChbbG93ZXIsIHVwcGVyXSk7XG4gICAgcmV0dXJuIHRoaXMuX2dldFNjYWxlRG9tYWluKHNjYWxlLCBpbmRleEVkZ2UpO1xuICB9XG5cbiAgX2dldFNjYWxlRG9tYWluKHNjYWxlVHlwZTogc3RyaW5nLCBbbG93ZXJJZHgsIHVwcGVySWR4XTogbnVtYmVyW10pIHtcbiAgICBjb25zdCBiaW5zID0gdGhpcy5zb3J0ZWRCaW5zO1xuICAgIHN3aXRjaCAoc2NhbGVUeXBlKSB7XG4gICAgICBjYXNlICdxdWFudGl6ZSc6XG4gICAgICBjYXNlICdsaW5lYXInOlxuICAgICAgICByZXR1cm4gW2JpbnNbbG93ZXJJZHhdLnZhbHVlLCBiaW5zW3VwcGVySWR4XS52YWx1ZV07XG4gICAgICBjYXNlICdxdWFudGlsZSc6XG4gICAgICAgIHJldHVybiBnZXRRdWFudGlsZURvbWFpbihiaW5zLnNsaWNlKGxvd2VySWR4LCB1cHBlcklkeCArIDEpLCBkID0+IGQudmFsdWUpO1xuICAgICAgY2FzZSAnb3JkaW5hbCc6XG4gICAgICAgIHJldHVybiBnZXRPcmRpbmFsRG9tYWluKGJpbnMsIGQgPT4gZC52YWx1ZSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gW2JpbnNbbG93ZXJJZHhdLnZhbHVlLCBiaW5zW3VwcGVySWR4XS52YWx1ZV07XG4gICAgfVxuICB9XG5cbiAgZ2V0VmFsdWVSYW5nZShwZXJjZW50aWxlUmFuZ2U/OiBudW1iZXJbXSkge1xuICAgIGlmICghdGhpcy5zb3J0ZWRCaW5zKSB7XG4gICAgICB0aGlzLnNvcnRlZEJpbnMgPSB0aGlzLmFnZ3JlZ2F0ZWRCaW5zLnNvcnQoKGEsIGIpID0+IGFzY2VuZGluZyhhLnZhbHVlLCBiLnZhbHVlKSk7XG4gICAgfVxuICAgIGlmICghdGhpcy5zb3J0ZWRCaW5zLmxlbmd0aCkgcmV0dXJuIFtdO1xuICAgIGxldCBsb3dlcklkeCA9IDA7XG4gICAgbGV0IHVwcGVySWR4ID0gdGhpcy5zb3J0ZWRCaW5zLmxlbmd0aCAtIDE7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocGVyY2VudGlsZVJhbmdlKSkge1xuICAgICAgY29uc3QgaWR4UmFuZ2UgPSB0aGlzLl9wZXJjZW50aWxlVG9JbmRleChwZXJjZW50aWxlUmFuZ2UpO1xuICAgICAgbG93ZXJJZHggPSBpZHhSYW5nZVswXTtcbiAgICAgIHVwcGVySWR4ID0gaWR4UmFuZ2VbMV07XG4gICAgfVxuICAgIHJldHVybiBbdGhpcy5zb3J0ZWRCaW5zW2xvd2VySWR4XS52YWx1ZSwgdGhpcy5zb3J0ZWRCaW5zW3VwcGVySWR4XS52YWx1ZV07XG4gIH1cbn1cblxuZXhwb3J0IHR5cGUgVXBkYXRlclR5cGUgPSAodGhpczogQ1BVQWdncmVnYXRvciwgc3RlcCwgcHJvcHMsIGRpbWVuc2lvblVwZGF0ZXIpID0+IHZvaWQ7XG5leHBvcnQgdHlwZSBCaW5kZWRVcGRhdGVyVHlwZSA9ICgpID0+IHZvaWQ7XG5leHBvcnQgdHlwZSBBZ2dyZWdhdGVkVXBkYXRlclR5cGUgPSAoXG4gIHRoaXM6IENQVUFnZ3JlZ2F0b3IsXG4gIHN0ZXAsXG4gIHByb3BzLFxuICBhZ2dyZWdhdGlvbixcbiAgYWdncmVnYXRpb25QYXJhbXNcbikgPT4gdm9pZDtcbmV4cG9ydCB0eXBlIEJpbmRlZEFnZ3JlZ2F0ZWRVcGRhdGVyVHlwZSA9IChhZ2dyZWdhdGlvblBhcmFtcykgPT4gdm9pZDtcblxuZXhwb3J0IHR5cGUgVXBkYXRlU3RlcHNUeXBlID0ge1xuICBrZXk6IHN0cmluZztcbiAgdHJpZ2dlcnM6IHtcbiAgICBba2V5OiBzdHJpbmddOiB7XG4gICAgICBwcm9wOiBzdHJpbmc7XG4gICAgICB1cGRhdGVUcmlnZ2VyPzogc3RyaW5nO1xuICAgIH07XG4gIH07XG4gIG9uU2V0Pzoge1xuICAgIHByb3BzOiBzdHJpbmc7XG4gIH07XG4gIHVwZGF0ZXI6IFVwZGF0ZXJUeXBlO1xufTtcblxuZXhwb3J0IHR5cGUgRGltZW5zaW9uVHlwZTxWYWx1ZVR5cGUgPSBhbnk+ID0ge1xuICBrZXk6IHN0cmluZztcbiAgYWNjZXNzb3I6IHN0cmluZztcbiAgZ2V0UGlja2luZ0luZm86IChkaW1lbnNpb25TdGF0ZSwgY2VsbCwgbGF5ZXJQcm9wcz8pID0+IGFueTtcbiAgbnVsbFZhbHVlOiBWYWx1ZVR5cGU7XG4gIHVwZGF0ZVN0ZXBzOiBVcGRhdGVTdGVwc1R5cGVbXTtcbiAgZ2V0U3ViTGF5ZXJBY2Nlc3Nvcjtcbn07XG5cbmV4cG9ydCB0eXBlIEFnZ3JlZ2F0aW9uVXBkYXRlU3RlcHNUeXBlID0ge1xuICBrZXk6IHN0cmluZztcbiAgdHJpZ2dlcnM6IHtcbiAgICBba2V5OiBzdHJpbmddOiB7XG4gICAgICBwcm9wOiBzdHJpbmc7XG4gICAgICB1cGRhdGVUcmlnZ2VyPzogc3RyaW5nO1xuICAgIH07XG4gIH07XG4gIHVwZGF0ZXI6IEFnZ3JlZ2F0ZWRVcGRhdGVyVHlwZTtcbn07XG5cbmV4cG9ydCB0eXBlIEFnZ3JlZ2F0aW9uVHlwZSA9IHtcbiAga2V5OiBzdHJpbmc7XG4gIHVwZGF0ZVN0ZXBzOiBBZ2dyZWdhdGlvblVwZGF0ZVN0ZXBzVHlwZVtdO1xufTtcblxuZXhwb3J0IGNvbnN0IERFQ0tfQUdHUkVHQVRJT05fTUFQID0ge1xuICBbQUdHUkVHQVRJT05fT1BFUkFUSU9OLlNVTV06IEFHR1JFR0FUSU9OX1RZUEVTLnN1bSxcbiAgW0FHR1JFR0FUSU9OX09QRVJBVElPTi5NRUFOXTogQUdHUkVHQVRJT05fVFlQRVMuYXZlcmFnZSxcbiAgW0FHR1JFR0FUSU9OX09QRVJBVElPTi5NSU5dOiBBR0dSRUdBVElPTl9UWVBFUy5taW5pbXVtLFxuICBbQUdHUkVHQVRJT05fT1BFUkFUSU9OLk1BWF06IEFHR1JFR0FUSU9OX1RZUEVTLm1heGltdW1cbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRWYWx1ZUZ1bmMoXG4gIGFnZ3JlZ2F0aW9uOiBzdHJpbmcsXG4gIGFjY2Vzc29yOiAoZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IG51bWJlclxuKSB7XG4gIGlmICghYWdncmVnYXRpb24gfHwgIUFHR1JFR0FUSU9OX09QRVJBVElPTlthZ2dyZWdhdGlvbi50b1VwcGVyQ2FzZSgpXSkge1xuICAgIENvbnNvbGUud2FybihgQWdncmVnYXRpb24gJHthZ2dyZWdhdGlvbn0gaXMgbm90IHN1cHBvcnRlZGApO1xuICB9XG5cbiAgY29uc3Qgb3AgPSBBR0dSRUdBVElPTl9PUEVSQVRJT05bYWdncmVnYXRpb24udG9VcHBlckNhc2UoKV0gfHwgQUdHUkVHQVRJT05fT1BFUkFUSU9OLlNVTTtcbiAgY29uc3Qga2VwbGVyT3AgPSBERUNLX0FHR1JFR0FUSU9OX01BUFtvcF07XG5cbiAgcmV0dXJuIHB0cyA9PiBhZ2dyZWdhdGUocHRzLm1hcChhY2Nlc3NvciksIGtlcGxlck9wKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNjYWxlRnVuY3RvcihzY2FsZVR5cGU6IHN0cmluZykge1xuICBpZiAoIXNjYWxlVHlwZSB8fCAhU0NBTEVfRlVOQ1tzY2FsZVR5cGVdKSB7XG4gICAgQ29uc29sZS53YXJuKGBTY2FsZSAke3NjYWxlVHlwZX0gaXMgbm90IHN1cHBvcnRlZGApO1xuICB9XG4gIHJldHVybiBTQ0FMRV9GVU5DW3NjYWxlVHlwZV0gfHwgU0NBTEVfRlVOQy5xdWFudGl6ZTtcbn1cblxuZnVuY3Rpb24gbm9wKCkge1xuICByZXR1cm47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRHZXRWYWx1ZSh0aGlzOiBDUFVBZ2dyZWdhdG9yLCBzdGVwLCBwcm9wcywgZGltZW5zaW9uVXBkYXRlcikge1xuICBjb25zdCB7a2V5fSA9IGRpbWVuc2lvblVwZGF0ZXI7XG4gIGNvbnN0IHt2YWx1ZSwgd2VpZ2h0LCBhZ2dyZWdhdGlvbn0gPSBzdGVwLnRyaWdnZXJzO1xuXG4gIGxldCBnZXRWYWx1ZSA9IHByb3BzW3ZhbHVlLnByb3BdO1xuXG4gIGlmIChnZXRWYWx1ZSA9PT0gbnVsbCkge1xuICAgIC8vIElmIGBnZXRWYWx1ZWAgaXMgbm90IHByb3ZpZGVkIGZyb20gcHJvcHMsIGJ1aWxkIGl0IHdpdGggYWdncmVnYXRpb24gYW5kIHdlaWdodC5cbiAgICBnZXRWYWx1ZSA9IGdldFZhbHVlRnVuYyhwcm9wc1thZ2dyZWdhdGlvbi5wcm9wXSwgcHJvcHNbd2VpZ2h0LnByb3BdKTtcbiAgfVxuXG4gIGlmIChnZXRWYWx1ZSkge1xuICAgIHRoaXMuX3NldERpbWVuc2lvblN0YXRlKGtleSwge2dldFZhbHVlfSk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldERpbWVuc2lvblNvcnRlZEJpbnModGhpczogQ1BVQWdncmVnYXRvciwgc3RlcCwgcHJvcHMsIGRpbWVuc2lvblVwZGF0ZXIpIHtcbiAgY29uc3Qge2tleX0gPSBkaW1lbnNpb25VcGRhdGVyO1xuICBjb25zdCB7Z2V0VmFsdWV9ID0gdGhpcy5zdGF0ZS5kaW1lbnNpb25zW2tleV07XG4gIGNvbnN0IHNvcnRlZEJpbnMgPSBuZXcgQmluU29ydGVyKCh0aGlzLnN0YXRlLmxheWVyRGF0YS5kYXRhIHx8IFtdKSBhcyB1bmtub3duIGFzIEJpbltdLCB7XG4gICAgZ2V0VmFsdWUsXG4gICAgZmlsdGVyRGF0YTogcHJvcHMuX2ZpbHRlckRhdGFcbiAgfSk7XG4gIHRoaXMuX3NldERpbWVuc2lvblN0YXRlKGtleSwge3NvcnRlZEJpbnN9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldERpbWVuc2lvblZhbHVlRG9tYWluKHRoaXM6IENQVUFnZ3JlZ2F0b3IsIHN0ZXAsIHByb3BzLCBkaW1lbnNpb25VcGRhdGVyKSB7XG4gIGNvbnN0IHtrZXl9ID0gZGltZW5zaW9uVXBkYXRlcjtcbiAgY29uc3Qge1xuICAgIHRyaWdnZXJzOiB7bG93ZXJQZXJjZW50aWxlLCB1cHBlclBlcmNlbnRpbGUsIHNjYWxlVHlwZX1cbiAgfSA9IHN0ZXA7XG5cbiAgaWYgKCF0aGlzLnN0YXRlLmRpbWVuc2lvbnNba2V5XS5zb3J0ZWRCaW5zKSB7XG4gICAgLy8gdGhlIHByZXZpb3VzIHN0ZXAgc2hvdWxkIHNldCBzb3J0ZWRCaW5zLCBpZiBub3QsIHNvbWV0aGluZyB3ZW50IHdyb25nXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbGV0IHZhbHVlRG9tYWluID1cbiAgICAvLyBmb3IgbG9nIGFuZCBzcXJ0IHNjYWxlLCByZXR1cm5zIGxpbmVhciBkb21haW4gYnkgZGVmYXVsdFxuICAgIC8vIFRPRE86IHN1cHBvcnQgb3RoZXIgc2NhbGUgZnVuY3Rpb24gZG9tYWluIGluIGJpbiBzb3J0ZXJcbiAgICB0aGlzLnN0YXRlLmRpbWVuc2lvbnNba2V5XS5zb3J0ZWRCaW5zLmdldFZhbHVlRG9tYWluQnlTY2FsZShwcm9wc1tzY2FsZVR5cGUucHJvcF0sIFtcbiAgICAgIHByb3BzW2xvd2VyUGVyY2VudGlsZS5wcm9wXSxcbiAgICAgIHByb3BzW3VwcGVyUGVyY2VudGlsZS5wcm9wXVxuICAgIF0pO1xuXG4gIGlmIChwcm9wcy5jb2xvclNjYWxlVHlwZSA9PT0gJ2N1c3RvbScgJiYgcHJvcHMuY29sb3JNYXApIHtcbiAgICAvLyBmb3IgY3VzdG9tIHNjYWxlLCByZXR1cm4gY3VzdG9tIGJyZWFrcyBhcyB2YWx1ZSBkb21haW4gZGlyZWN0bHlcbiAgICB2YWx1ZURvbWFpbiA9IHByb3BzLmNvbG9yTWFwLnJlZHVjZShcbiAgICAgIChwcmV2LCBjdXIpID0+IChOdW1iZXIuaXNGaW5pdGUoY3VyWzBdKSA/IHByZXYuY29uY2F0KGN1clswXSkgOiBwcmV2KSxcbiAgICAgIFtdXG4gICAgKTtcbiAgfVxuXG4gIHRoaXMuX3NldERpbWVuc2lvblN0YXRlKGtleSwge3ZhbHVlRG9tYWlufSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREaW1lbnNpb25TY2FsZSh0aGlzOiBDUFVBZ2dyZWdhdG9yLCBzdGVwLCBwcm9wcywgZGltZW5zaW9uVXBkYXRlcikge1xuICBjb25zdCB7a2V5fSA9IGRpbWVuc2lvblVwZGF0ZXI7XG4gIGNvbnN0IHtkb21haW4sIHJhbmdlLCBzY2FsZVR5cGUsIGZpeGVkfSA9IHN0ZXAudHJpZ2dlcnM7XG4gIGNvbnN0IHtvblNldH0gPSBzdGVwO1xuICBpZiAoIXRoaXMuc3RhdGUuZGltZW5zaW9uc1trZXldLnZhbHVlRG9tYWluKSB7XG4gICAgLy8gdGhlIHByZXZpb3VzIHN0ZXAgc2hvdWxkIHNldCB2YWx1ZURvbWFpbiwgaWYgbm90LCBzb21ldGhpbmcgd2VudCB3cm9uZ1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGRpbWVuc2lvblJhbmdlID0gcHJvcHNbcmFuZ2UucHJvcF07XG4gIGNvbnN0IGRpbWVuc2lvbkRvbWFpbiA9IHByb3BzW2RvbWFpbi5wcm9wXSB8fCB0aGlzLnN0YXRlLmRpbWVuc2lvbnNba2V5XS52YWx1ZURvbWFpbjtcbiAgY29uc3QgZGltZW5zaW9uRml4ZWQgPSBCb29sZWFuKGZpeGVkICYmIHByb3BzW2ZpeGVkLnByb3BdKTtcblxuICBjb25zdCBzY2FsZUZ1bmN0b3IgPSBnZXRTY2FsZUZ1bmN0b3Ioc2NhbGVUeXBlICYmIHByb3BzW3NjYWxlVHlwZS5wcm9wXSkoKTtcblxuICBjb25zdCBzY2FsZUZ1bmMgPSBzY2FsZUZ1bmN0b3JcbiAgICAuZG9tYWluKGRpbWVuc2lvbkRvbWFpbilcbiAgICAucmFuZ2UoZGltZW5zaW9uRml4ZWQgPyBkaW1lbnNpb25Eb21haW4gOiBkaW1lbnNpb25SYW5nZSk7XG4gIHNjYWxlRnVuYy5zY2FsZVR5cGUgPSBwcm9wcy5jb2xvclNjYWxlVHlwZTtcblxuICBpZiAodHlwZW9mIG9uU2V0ID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgcHJvcHNbb25TZXQucHJvcHNdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY29uc3Qgc29ydGVkQmlucyA9IHRoaXMuc3RhdGUuZGltZW5zaW9uc1trZXldLnNvcnRlZEJpbnM7XG4gICAgaWYgKHNvcnRlZEJpbnMpIHtcbiAgICAgIHByb3BzW29uU2V0LnByb3BzXSh7ZG9tYWluOiBzY2FsZUZ1bmMuZG9tYWluKCksIGFnZ3JlZ2F0ZWRCaW5zOiBzb3J0ZWRCaW5zLmJpbk1hcH0pO1xuICAgIH1cbiAgfVxuICB0aGlzLl9zZXREaW1lbnNpb25TdGF0ZShrZXksIHtzY2FsZUZ1bmN9KTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplUmVzdWx0KFxuICByZXN1bHQ6IHtcbiAgICBoZXhhZ29ucz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107XG4gICAgbGF5ZXJEYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5bXTtcbiAgICBkYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5bXTtcbiAgfSA9IHt9XG4pIHtcbiAgLy8gc3VwcG9ydCBwcmV2aW91cyBoZXhhZ29uQWdncmVnYXRvciBBUElcbiAgaWYgKHJlc3VsdC5oZXhhZ29ucykge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHtkYXRhOiByZXN1bHQuaGV4YWdvbnN9LCByZXN1bHQpO1xuICB9IGVsc2UgaWYgKHJlc3VsdC5sYXllckRhdGEpIHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7ZGF0YTogcmVzdWx0LmxheWVyRGF0YX0sIHJlc3VsdCk7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWdncmVnYXRlZERhdGEoXG4gIHRoaXM6IENQVUFnZ3JlZ2F0b3IsXG4gIHN0ZXAsXG4gIHByb3B