UNPKG

kepler.gl.geoiq

Version:

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

303 lines (265 loc) 33.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _deck = require("deck.gl"); var _geoViewport = _interopRequireDefault(require("@mapbox/geo-viewport")); var _d3Array = require("d3-array"); var _dataScaleUtils = require("../../utils/data-scale-utils"); var _utils = require("../layer-utils/utils"); var _colorRanges = require("../../constants/color-ranges"); var _layerFactory = require("../../layers/layer-factory"); var _defaultSettings = require("../../constants/default-settings"); var _clusterUtils = require("../layer-utils/cluster-utils"); 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 defaultRadius = _layerFactory.LAYER_VIS_CONFIGS.clusterRadius.defaultValue; var defaultRadiusRange = _layerFactory.LAYER_VIS_CONFIGS.clusterRadiusRange.defaultValue; var defaultProps = { clusterRadius: defaultRadius, colorDomain: null, colorRange: _colorRanges.DefaultColorRange, colorScale: _defaultSettings.SCALE_TYPES.quantize, radiusRange: defaultRadiusRange, // maybe later... lowerPercentile: 0, upperPercentile: 100, getPosition: function getPosition(x) { return x.position; }, // if want to have color based on customized aggregator, instead of count getColorValue: function getColorValue(points) { return points.length; }, // if want to have radius based on customized aggregator, instead of count getRadiusValue: function getRadiusValue(cell) { return cell.properties.point_count; }, fp64: false }; var ClusterLayer = /*#__PURE__*/ function (_CompositeLayer) { (0, _inherits2["default"])(ClusterLayer, _CompositeLayer); function ClusterLayer() { (0, _classCallCheck2["default"])(this, ClusterLayer); return (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(ClusterLayer).apply(this, arguments)); } (0, _createClass2["default"])(ClusterLayer, [{ key: "initializeState", value: function initializeState() { this.state = { clusters: null, geoJSON: null }; } }, { key: "shouldUpdateState", value: function shouldUpdateState(_ref) { var changeFlags = _ref.changeFlags; return changeFlags.somethingChanged; } }, { key: "updateState", value: function updateState(_ref2) { var context = _ref2.context, oldProps = _ref2.oldProps, props = _ref2.props, changeFlags = _ref2.changeFlags; if (changeFlags.dataChanged || changeFlags.viewportChanged || this.needsReProjectPoints(oldProps, props)) { // project data into clusters, and get clustered data this.processGeoJSON(); this.getClusters(); // this needs clustered data to be set this.getColorValueDomain(); } else if (this.needsReclusterPoints(oldProps, props)) { this.getClusters(); this.getColorValueDomain(); } else if (this.needsRecalculateScaleFunction(oldProps, props)) { this.getColorValueDomain(); } } }, { key: "needsReProjectPoints", value: function needsReProjectPoints(oldProps, props) { return oldProps.clusterRadius !== props.clusterRadius || oldProps.getPosition !== props.getPosition; } }, { key: "needsReclusterPoints", value: function needsReclusterPoints(oldProps, props) { return Math.round(oldProps.zoom) !== Math.round(props.zoom); } }, { key: "needsRecalculateScaleFunction", value: function needsRecalculateScaleFunction(oldProps, props) { return (0, _utils.needsRecalculateColorDomain)(oldProps, props) || (0, _utils.needReCalculateScaleFunction)(oldProps, props) || (0, _utils.needsRecalculateRadiusRange)(oldProps, props) || oldProps.getColorValue !== props.getColorValue; } }, { key: "processGeoJSON", value: function processGeoJSON() { var _this$props = this.props, data = _this$props.data, getPosition = _this$props.getPosition; this.setState({ geoJSON: (0, _clusterUtils.getGeoJSON)(data, getPosition) }); (0, _clusterUtils.clearClustererCache)(); } }, { key: "getClusters", value: function getClusters() { var geoJSON = this.state.geoJSON; var clusterRadius = this.props.clusterRadius; var _this$context = this.context, viewport = _this$context.viewport, _this$context$viewpor = _this$context.viewport, longitude = _this$context$viewpor.longitude, latitude = _this$context$viewpor.latitude, height = _this$context$viewpor.height, width = _this$context$viewpor.width; // zoom needs to be an integer for the different map utils. Also helps with cache key. var zoom = Math.round(viewport.zoom); var bbox = _geoViewport["default"].bounds([longitude, latitude], zoom, [width, height]); var clusters = (0, _clusterUtils.clustersAtZoom)({ bbox: bbox, clusterRadius: clusterRadius, geoJSON: geoJSON, zoom: zoom }); this.setState({ clusters: clusters }); } }, { key: "getColorValueDomain", value: function getColorValueDomain() { var _this$props2 = this.props, colorScale = _this$props2.colorScale, getColorValue = _this$props2.getColorValue, getRadiusValue = _this$props2.getRadiusValue, onSetColorDomain = _this$props2.onSetColorDomain; var clusters = this.state.clusters; var radiusDomain = [0, (0, _d3Array.max)(clusters, getRadiusValue)]; var colorValues = clusters.map(function (d) { return getColorValue(d.properties.points); }); var identity = function identity(d) { return d; }; var colorDomain = colorScale === _defaultSettings.SCALE_TYPES.ordinal ? (0, _dataScaleUtils.getOrdinalDomain)(colorValues, identity) : colorScale === _defaultSettings.SCALE_TYPES.quantile ? (0, _dataScaleUtils.getQuantileDomain)(colorValues, identity, _d3Array.ascending) : (0, _dataScaleUtils.getLinearDomain)(colorValues, identity); this.setState({ colorDomain: colorDomain, radiusDomain: radiusDomain }); (0, _utils.getColorScaleFunction)(this); (0, _utils.getRadiusScaleFunction)(this); onSetColorDomain(colorDomain); } }, { key: "getUpdateTriggers", value: function getUpdateTriggers() { return { getColor: { colorRange: this.props.colorRange, colorDomain: this.props.colorDomain, getColorValue: this.props.getColorValue, colorScale: this.props.colorScale, lowerPercentile: this.props.lowerPercentile, upperPercentile: this.props.upperPercentile }, getRadius: { radiusRange: this.props.radiusRange, radiusDomain: this.props.radiusDomain, getRadiusValue: this.props.getRadiusValue } }; } /* * override default layer method to calculate cell color based on color scale function */ }, { key: "_onGetSublayerColor", value: function _onGetSublayerColor(cell) { var getColorValue = this.props.getColorValue; var _this$state = this.state, colorScaleFunc = _this$state.colorScaleFunc, colorDomain = _this$state.colorDomain; var cv = getColorValue(cell.properties.points); // if cell value is outside domain, set alpha to 0 var color = cv >= colorDomain[0] && cv <= colorDomain[colorDomain.length - 1] ? colorScaleFunc(cv) : [0, 0, 0, 0]; // add final alpha to color color[3] = Number.isFinite(color[3]) ? color[3] : 255; return color; } }, { key: "_onGetSublayerRadius", value: function _onGetSublayerRadius(cell) { var getRadiusValue = this.props.getRadiusValue; var radiusScaleFunc = this.state.radiusScaleFunc; return radiusScaleFunc(getRadiusValue(cell)); } }, { key: "getPickingInfo", value: function getPickingInfo(_ref3) { var info = _ref3.info; var clusters = this.state.clusters; var isPicked = info.picked && info.index > -1; var object = null; if (isPicked) { // add cluster colorValue to object var cluster = clusters[info.index]; var colorValue = this.props.getColorValue(cluster.properties.points); object = _objectSpread({}, cluster.properties, { colorValue: colorValue, radius: this._onGetSublayerRadius(cluster), position: cluster.geometry.coordinates }); } return _objectSpread({}, info, { picked: Boolean(object), // override object with picked cluster property object: object }); } }, { key: "renderLayers", value: function renderLayers() { // for subclassing, override this method to return // customized sub layer props var _this$props3 = this.props, id = _this$props3.id, radiusScale = _this$props3.radiusScale, fp64 = _this$props3.fp64; // base layer props var _this$props4 = this.props, opacity = _this$props4.opacity, pickable = _this$props4.pickable, autoHighlight = _this$props4.autoHighlight, highlightColor = _this$props4.highlightColor; // return props to the sublayer constructor return new _deck.ScatterplotLayer({ id: "".concat(id, "-cluster"), data: this.state.clusters, radiusScale: radiusScale, fp64: fp64, opacity: opacity, pickable: pickable, autoHighlight: autoHighlight, highlightColor: highlightColor, getPosition: function getPosition(d) { return d.geometry.coordinates; }, getRadius: this._onGetSublayerRadius.bind(this), getColor: this._onGetSublayerColor.bind(this), updateTriggers: this.getUpdateTriggers() }); } }]); return ClusterLayer; }(_deck.CompositeLayer); exports["default"] = ClusterLayer; ClusterLayer.layerName = 'ClusterLayer'; ClusterLayer.defaultProps = defaultProps; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNrZ2wtbGF5ZXJzL2NsdXN0ZXItbGF5ZXIvY2x1c3Rlci1sYXllci5qcyJdLCJuYW1lcyI6WyJkZWZhdWx0UmFkaXVzIiwiTEFZRVJfVklTX0NPTkZJR1MiLCJjbHVzdGVyUmFkaXVzIiwiZGVmYXVsdFZhbHVlIiwiZGVmYXVsdFJhZGl1c1JhbmdlIiwiY2x1c3RlclJhZGl1c1JhbmdlIiwiZGVmYXVsdFByb3BzIiwiY29sb3JEb21haW4iLCJjb2xvclJhbmdlIiwiRGVmYXVsdENvbG9yUmFuZ2UiLCJjb2xvclNjYWxlIiwiU0NBTEVfVFlQRVMiLCJxdWFudGl6ZSIsInJhZGl1c1JhbmdlIiwibG93ZXJQZXJjZW50aWxlIiwidXBwZXJQZXJjZW50aWxlIiwiZ2V0UG9zaXRpb24iLCJ4IiwicG9zaXRpb24iLCJnZXRDb2xvclZhbHVlIiwicG9pbnRzIiwibGVuZ3RoIiwiZ2V0UmFkaXVzVmFsdWUiLCJjZWxsIiwicHJvcGVydGllcyIsInBvaW50X2NvdW50IiwiZnA2NCIsIkNsdXN0ZXJMYXllciIsInN0YXRlIiwiY2x1c3RlcnMiLCJnZW9KU09OIiwiY2hhbmdlRmxhZ3MiLCJzb21ldGhpbmdDaGFuZ2VkIiwiY29udGV4dCIsIm9sZFByb3BzIiwicHJvcHMiLCJkYXRhQ2hhbmdlZCIsInZpZXdwb3J0Q2hhbmdlZCIsIm5lZWRzUmVQcm9qZWN0UG9pbnRzIiwicHJvY2Vzc0dlb0pTT04iLCJnZXRDbHVzdGVycyIsImdldENvbG9yVmFsdWVEb21haW4iLCJuZWVkc1JlY2x1c3RlclBvaW50cyIsIm5lZWRzUmVjYWxjdWxhdGVTY2FsZUZ1bmN0aW9uIiwiTWF0aCIsInJvdW5kIiwiem9vbSIsImRhdGEiLCJzZXRTdGF0ZSIsInZpZXdwb3J0IiwibG9uZ2l0dWRlIiwibGF0aXR1ZGUiLCJoZWlnaHQiLCJ3aWR0aCIsImJib3giLCJnZW9WaWV3cG9ydCIsImJvdW5kcyIsIm9uU2V0Q29sb3JEb21haW4iLCJyYWRpdXNEb21haW4iLCJjb2xvclZhbHVlcyIsIm1hcCIsImQiLCJpZGVudGl0eSIsIm9yZGluYWwiLCJxdWFudGlsZSIsImFzY2VuZGluZyIsImdldENvbG9yIiwiZ2V0UmFkaXVzIiwiY29sb3JTY2FsZUZ1bmMiLCJjdiIsImNvbG9yIiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJyYWRpdXNTY2FsZUZ1bmMiLCJpbmZvIiwiaXNQaWNrZWQiLCJwaWNrZWQiLCJpbmRleCIsIm9iamVjdCIsImNsdXN0ZXIiLCJjb2xvclZhbHVlIiwicmFkaXVzIiwiX29uR2V0U3VibGF5ZXJSYWRpdXMiLCJnZW9tZXRyeSIsImNvb3JkaW5hdGVzIiwiQm9vbGVhbiIsImlkIiwicmFkaXVzU2NhbGUiLCJvcGFjaXR5IiwicGlja2FibGUiLCJhdXRvSGlnaGxpZ2h0IiwiaGlnaGxpZ2h0Q29sb3IiLCJTY2F0dGVycGxvdExheWVyIiwiYmluZCIsIl9vbkdldFN1YmxheWVyQ29sb3IiLCJ1cGRhdGVUcmlnZ2VycyIsImdldFVwZGF0ZVRyaWdnZXJzIiwiQ29tcG9zaXRlTGF5ZXIiLCJsYXllck5hbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFLQTs7QUFPQTs7QUFDQTs7QUFDQTs7QUFFQTs7Ozs7O0FBTUEsSUFBTUEsYUFBYSxHQUFHQyxnQ0FBa0JDLGFBQWxCLENBQWdDQyxZQUF0RDtBQUNBLElBQU1DLGtCQUFrQixHQUFHSCxnQ0FBa0JJLGtCQUFsQixDQUFxQ0YsWUFBaEU7QUFFQSxJQUFNRyxZQUFZLEdBQUc7QUFDbkJKLEVBQUFBLGFBQWEsRUFBRUYsYUFESTtBQUVuQk8sRUFBQUEsV0FBVyxFQUFFLElBRk07QUFHbkJDLEVBQUFBLFVBQVUsRUFBRUMsOEJBSE87QUFJbkJDLEVBQUFBLFVBQVUsRUFBRUMsNkJBQVlDLFFBSkw7QUFLbkJDLEVBQUFBLFdBQVcsRUFBRVQsa0JBTE07QUFPbkI7QUFDQVUsRUFBQUEsZUFBZSxFQUFFLENBUkU7QUFTbkJDLEVBQUFBLGVBQWUsRUFB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LFFBQUFBLEVBQUUsWUFBS0EsRUFBTCxhQUR3QjtBQUUxQnZDLFFBQUFBLElBQUksRUFBRSxLQUFLbkIsS0FBTCxDQUFXQyxRQUZTO0FBRzFCMEQsUUFBQUEsV0FBVyxFQUFYQSxXQUgwQjtBQUkxQjdELFFBQUFBLElBQUksRUFBSkEsSUFKMEI7QUFLMUI4RCxRQUFBQSxPQUFPLEVBQVBBLE9BTDBCO0FBTTFCQyxRQUFBQSxRQUFRLEVBQVJBLFFBTjBCO0FBTzFCQyxRQUFBQSxhQUFhLEVBQWJBLGFBUDBCO0FBUTFCQyxRQUFBQSxjQUFjLEVBQWRBLGNBUjBCO0FBUzFCM0UsUUFBQUEsV0FBVyxFQUFFLHFCQUFBNkMsQ0FBQztBQUFBLGlCQUFJQSxDQUFDLENBQUNzQixRQUFGLENBQVdDLFdBQWY7QUFBQSxTQVRZO0FBVTFCakIsUUFBQUEsU0FBUyxFQUFFLEtBQUtlLG9CQUFMLENBQTBCVyxJQUExQixDQUErQixJQUEvQixDQVZlO0FBVzFCM0IsUUFBQUEsUUFBUSxFQUFFLEtBQUs0QixtQkFBTCxDQUF5QkQsSUFBekIsQ0FBOEIsSUFBOUIsQ0FYZ0I7QUFZMUJFLFFBQUFBLGNBQWMsRUFBRSxLQUFLQyxpQkFBTDtBQVpVLE9BQXJCLENBQVA7QUFjRDs7O0VBN011Q0Msb0I7OztBQWdOMUN0RSxZQUFZLENBQUN1RSxTQUFiLEdBQXlCLGNBQXpCO0FBQ0F2RSxZQUFZLENBQUNyQixZQUFiLEdBQTRCQSxZQUE1QiIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAxOSBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7Q29tcG9zaXRlTGF5ZXIsIFNjYXR0ZXJwbG90TGF5ZXJ9IGZyb20gJ2RlY2suZ2wnO1xuaW1wb3J0IGdlb1ZpZXdwb3J0IGZyb20gJ0BtYXBib3gvZ2VvLXZpZXdwb3J0JztcbmltcG9ydCB7YXNjZW5kaW5nLCBtYXh9IGZyb20gJ2QzLWFycmF5JztcbmltcG9ydCB7XG4gIGdldFF1YW50aWxlRG9tYWluLFxuICBnZXRPcmRpbmFsRG9tYWluLFxuICBnZXRMaW5lYXJEb21haW5cbn0gZnJvbSAndXRpbHMvZGF0YS1zY2FsZS11dGlscyc7XG5pbXBvcnQge1xuICBnZXRDb2xvclNjYWxlRnVuY3Rpb24sXG4gIGdldFJhZGl1c1NjYWxlRnVuY3Rpb24sXG4gIG5lZWRzUmVjYWxjdWxhdGVSYWRpdXNSYW5nZSxcbiAgbmVlZHNSZWNhbGN1bGF0ZUNvbG9yRG9tYWluLFxuICBuZWVkUmVDYWxjdWxhdGVTY2FsZUZ1bmN0aW9uXG59IGZyb20gJy4uL2xheWVyLXV0aWxzL3V0aWxzJztcbmltcG9ydCB7RGVmYXVsdENvbG9yUmFuZ2V9IGZyb20gJ2NvbnN0YW50cy9jb2xvci1yYW5nZXMnO1xuaW1wb3J0IHtMQVlFUl9WSVNfQ09ORklHU30gZnJvbSAnbGF5ZXJzL2xheWVyLWZhY3RvcnknO1xuaW1wb3J0IHtTQ0FMRV9UWVBFU30gZnJvbSAnY29uc3RhbnRzL2RlZmF1bHQtc2V0dGluZ3MnO1xuXG5pbXBvcnQge1xuICBjbGVhckNsdXN0ZXJlckNhY2hlLFxuICBjbHVzdGVyc0F0Wm9vbSxcbiAgZ2V0R2VvSlNPTlxufSBmcm9tICcuLi9sYXllci11dGlscy9jbHVzdGVyLXV0aWxzJztcblxuY29uc3QgZGVmYXVsdFJhZGl1cyA9IExBWUVSX1ZJU19DT05GSUdTLmNsdXN0ZXJSYWRpdXMuZGVmYXVsdFZhbHVlO1xuY29uc3QgZGVmYXVsdFJhZGl1c1JhbmdlID0gTEFZRVJfVklTX0NPTkZJR1MuY2x1c3RlclJhZGl1c1JhbmdlLmRlZmF1bHRWYWx1ZTtcblxuY29uc3QgZGVmYXVsdFByb3BzID0ge1xuICBjbHVzdGVyUmFkaXVzOiBkZWZhdWx0UmFkaXVzLFxuICBjb2xvckRvbWFpbjogbnVsbCxcbiAgY29sb3JSYW5nZTogRGVmYXVsdENvbG9yUmFuZ2UsXG4gIGNvbG9yU2NhbGU6IFNDQUxFX1RZUEVTLnF1YW50aXplLFxuICByYWRpdXNSYW5nZTogZGVmYXVsdFJhZGl1c1JhbmdlLFxuXG4gIC8vIG1heWJlIGxhdGVyLi4uXG4gIGxvd2VyUGVyY2VudGlsZTogMCxcbiAgdXBwZXJQZXJjZW50aWxlOiAxMDAsXG5cbiAgZ2V0UG9zaXRpb246IHggPT4geC5wb3NpdGlvbixcblxuICAvLyBpZiB3YW50IHRvIGhhdmUgY29sb3IgYmFzZWQgb24gY3VzdG9taXplZCBhZ2dyZWdhdG9yLCBpbnN0ZWFkIG9mIGNvdW50XG4gIGdldENvbG9yVmFsdWU6IHBvaW50cyA9PiBwb2ludHMubGVuZ3RoLFxuXG4gIC8vICBpZiB3YW50IHRvIGhhdmUgcmFkaXVzIGJhc2VkIG9uIGN1c3RvbWl6ZWQgYWdncmVnYXRvciwgaW5zdGVhZCBvZiBjb3VudFxuICBnZXRSYWRpdXNWYWx1ZTogY2VsbCA9PiBjZWxsLnByb3BlcnRpZXMucG9pbnRfY291bnQsXG4gIGZwNjQ6IGZhbHNlXG59O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDbHVzdGVyTGF5ZXIgZXh0ZW5kcyBDb21wb3NpdGVMYXllciB7XG4gIGluaXRpYWxpemVTdGF0ZSgpIHtcbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgY2x1c3RlcnM6IG51bGwsXG4gICAgICBnZW9KU09OOiBudWxsXG4gICAgfTtcbiAgfVxuXG4gIHNob3VsZFVwZGF0ZVN0YXRlKHtjaGFuZ2VGbGFnc30pIHtcbiAgICByZXR1cm4gY2hhbmdlRmxhZ3Muc29tZXRoaW5nQ2hhbmdlZDtcbiAgfVxuXG4gIHVwZGF0ZVN0YXRlKHtjb250ZXh0LCBvbGRQcm9wcywgcHJvcHMsIGNoYW5nZUZsYWdzfSkge1xuICAgIGlmIChcbiAgICAgIGNoYW5nZUZsYWdzLmRhdGFDaGFuZ2VkIHx8XG4gICAgICBjaGFuZ2VGbGFncy52aWV3cG9ydENoYW5nZWQgfHxcbiAgICAgIHRoaXMubmVlZHNSZVByb2plY3RQb2ludHMob2xkUHJvcHMsIHByb3BzKVxuICAgICkge1xuICAgICAgLy8gcHJvamVjdCBkYXRhIGludG8gY2x1c3RlcnMsIGFuZCBnZXQgY2x1c3RlcmVkIGRhdGFcbiAgICAgIHRoaXMucHJvY2Vzc0dlb0pTT04oKTtcbiAgICAgIHRoaXMuZ2V0Q2x1c3RlcnMoKTtcblxuICAgICAgLy8gdGhpcyBuZWVkcyBjbHVzdGVyZWQgZGF0YSB0byBiZSBzZXRcbiAgICAgIHRoaXMuZ2V0Q29sb3JWYWx1ZURvbWFpbigpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5uZWVkc1JlY2x1c3RlclBvaW50cyhvbGRQcm9wcywgcHJvcHMpKSB7XG4gICAgICB0aGlzLmdldENsdXN0ZXJzKCk7XG4gICAgICB0aGlzLmdldENvbG9yVmFsdWVEb21haW4oKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubmVlZHNSZWNhbGN1bGF0ZVNjYWxlRnVuY3Rpb24ob2xkUHJvcHMsIHByb3BzKSkge1xuICAgICAgdGhpcy5nZXRDb2xvclZhbHVlRG9tYWluKCk7XG4gICAgfVxuICB9XG5cbiAgbmVlZHNSZVByb2plY3RQb2ludHMob2xkUHJvcHMsIHByb3BzKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIG9sZFByb3BzLmNsdXN0ZXJSYWRpdXMgIT09IHByb3BzLmNsdXN0ZXJSYWRpdXMgfHxcbiAgICAgIG9sZFByb3BzLmdldFBvc2l0aW9uICE9PSBwcm9wcy5nZXRQb3NpdGlvblxuICAgICk7XG4gIH1cblxuICBuZWVkc1JlY2x1c3RlclBvaW50cyhvbGRQcm9wcywgcHJvcHMpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChvbGRQcm9wcy56b29tKSAhPT0gTWF0aC5yb3VuZChwcm9wcy56b29tKTtcbiAgfVxuXG4gIG5lZWRzUmVjYWxjdWxhdGVTY2FsZUZ1bmN0aW9uKG9sZFByb3BzLCBwcm9wcykge1xuICAgIHJldHVybiAoXG4gICAgICBuZWVkc1JlY2FsY3VsYXRlQ29sb3JEb21haW4ob2xkUHJvcHMsIHByb3BzKSB8fFxuICAgICAgbmVlZFJlQ2FsY3VsYXRlU2NhbGVGdW5jdGlvbihvbGRQcm9wcywgcHJvcHMpIHx8XG4gICAgICBuZWVkc1JlY2FsY3VsYXRlUmFkaXVzUmFuZ2Uob2xkUHJvcHMsIHByb3BzKSB8fFxuICAgICAgb2xkUHJvcHMuZ2V0Q29sb3JWYWx1ZSAhPT0gcHJvcHMuZ2V0Q29sb3JWYWx1ZVxuICAgICk7XG4gIH1cblxuICBwcm9jZXNzR2VvSlNPTigpIHtcbiAgICBjb25zdCB7ZGF0YSwgZ2V0UG9zaXRpb259ID0gdGhpcy5wcm9wcztcbiAgICB0aGlzLnNldFN0YXRlKHtnZW9KU09OOiBnZXRHZW9KU09OKGRhdGEsIGdldFBvc2l0aW9uKX0pO1xuICAgIGNsZWFyQ2x1c3RlcmVyQ2FjaGUoKTtcbiAgfVxuXG4gIGdldENsdXN0ZXJzKCkge1xuICAgIGNvbnN0IHtnZW9KU09OfSA9IHRoaXMuc3RhdGU7XG4gICAgY29uc3Qge2NsdXN0ZXJSYWRpdXN9ID0gdGhpcy5wcm9wcztcbiAgICBjb25zdCB7XG4gICAgICB2aWV3cG9ydCxcbiAgICAgIHZpZXdwb3J0OiB7bG9uZ2l0dWRlLCBsYXRpdHVkZSwgaGVpZ2h0LCB3aWR0aH1cbiAgICB9ID0gdGhpcy5jb250ZXh0O1xuXG4gICAgLy8gem9vbSBuZWVkcyB0byBiZSBhbiBpbnRlZ2VyIGZvciB0aGUgZGlmZmVyZW50IG1hcCB1dGlscy4gQWxzbyBoZWxwcyB3aXRoIGNhY2hlIGtleS5cbiAgICBjb25zdCB6b29tID0gTWF0aC5yb3VuZCh2aWV3cG9ydC56b29tKTtcbiAgICBjb25zdCBiYm94ID0gZ2VvVmlld3BvcnQuYm91bmRzKFtsb25naXR1ZGUsIGxhdGl0dWRlXSwgem9vbSwgW1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHRcbiAgICBdKTtcblxuICAgIGNvbnN0IGNsdXN0ZXJzID0gY2x1c3RlcnNBdFpvb20oe2Jib3gsIGNsdXN0ZXJSYWRpdXMsIGdlb0pTT04sIHpvb219KTtcblxuICAgIHRoaXMuc2V0U3RhdGUoe2NsdXN0ZXJzfSk7XG4gIH1cblxuICBnZXRDb2xvclZhbHVlRG9tYWluKCkge1xuICAgIGNvbnN0IHtcbiAgICAgIGNvbG9yU2NhbGUsXG4gICAgICBnZXRDb2xvclZhbHVlLFxuICAgICAgZ2V0UmFkaXVzVmFsdWUsXG4gICAgICBvblNldENvbG9yRG9tYWluXG4gICAgfSA9IHRoaXMucHJvcHM7XG4gICAgY29uc3Qge2NsdXN0ZXJzfSA9IHRoaXMuc3RhdGU7XG5cbiAgICBjb25zdCByYWRpdXNEb21haW4gPSBbMCwgbWF4KGNsdXN0ZXJzLCBnZXRSYWRpdXNWYWx1ZSldO1xuXG4gICAgY29uc3QgY29sb3JWYWx1ZXMgPSBjbHVzdGVycy5tYXAoZCA9PiBnZXRDb2xvclZhbHVlKGQucHJvcGVydGllcy5wb2ludHMpKTtcblxuICAgIGNvbnN0IGlkZW50aXR5ID0gZCA9PiBkO1xuXG4gICAgY29uc3QgY29sb3JEb21haW4gPVxuICAgICAgY29sb3JTY2FsZSA9PT0gU0NBTEVfVFlQRVMub3JkaW5hbFxuICAgICAgICA/IGdldE9yZGluYWxEb21haW4oY29sb3JWYWx1ZXMsIGlkZW50aXR5KVxuICAgICAgICA6IGNvbG9yU2NhbGUgPT09IFNDQUxFX1RZUEVTLnF1YW50aWxlXG4gICAgICAgID8gZ2V0UXVhbnRpbGVEb21haW4oY29sb3JWYWx1ZXMsIGlkZW50aXR5LCBhc2NlbmRpbmcpXG4gICAgICAgIDogZ2V0TGluZWFyRG9tYWluKGNvbG9yVmFsdWVzLCBpZGVudGl0eSk7XG5cbiAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgIGNvbG9yRG9tYWluLFxuICAgICAgcmFkaXVzRG9tYWluXG4gICAgfSk7XG5cbiAgICBnZXRDb2xvclNjYWxlRnVuY3Rpb24odGhpcyk7XG4gICAgZ2V0UmFkaXVzU2NhbGVGdW5jdGlvbih0aGlzKTtcblxuICAgIG9uU2V0Q29sb3JEb21haW4oY29sb3JEb21haW4pO1xuICB9XG5cbiAgZ2V0VXBkYXRlVHJpZ2dlcnMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGdldENvbG9yOiB7XG4gICAgICAgIGNvbG9yUmFuZ2U6IHRoaXMucHJvcHMuY29sb3JSYW5nZSxcbiAgICAgICAgY29sb3JEb21haW46IHRoaXMucHJvcHMuY29sb3JEb21haW4sXG4gICAgICAgIGdldENvbG9yVmFsdWU6IHRoaXMucHJvcHMuZ2V0Q29sb3JWYWx1ZSxcbiAgICAgICAgY29sb3JTY2FsZTogdGhpcy5wcm9wcy5jb2xvclNjYWxlLFxuICAgICAgICBsb3dlclBlcmNlbnRpbGU6IHRoaXMucHJvcHMubG93ZXJQZXJjZW50aWxlLFxuICAgICAgICB1cHBlclBlcmNlbnRpbGU6IHRoaXMucHJvcHMudXBwZXJQZXJjZW50aWxlXG4gICAgICB9LFxuICAgICAgZ2V0UmFkaXVzOiB7XG4gICAgICAgIHJhZGl1c1JhbmdlOiB0aGlzLnByb3BzLnJhZGl1c1JhbmdlLFxuICAgICAgICByYWRpdXNEb21haW46IHRoaXMucHJvcHMucmFkaXVzRG9tYWluLFxuICAgICAgICBnZXRSYWRpdXNWYWx1ZTogdGhpcy5wcm9wcy5nZXRSYWRpdXNWYWx1ZVxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvKlxuICAgKiBvdmVycmlkZSBkZWZhdWx0IGxheWVyIG1ldGhvZCB0byBjYWxjdWxhdGUgY2VsbCBjb2xvciBiYXNlZCBvbiBjb2xvciBzY2FsZSBmdW5jdGlvblxuICAgKi9cbiAgX29uR2V0U3VibGF5ZXJDb2xvcihjZWxsKSB7XG4gICAgY29uc3Qge2dldENvbG9yVmFsdWV9ID0gdGhpcy5wcm9wcztcbiAgICBjb25zdCB7Y29sb3JTY2FsZUZ1bmMsIGNvbG9yRG9tYWlufSA9IHRoaXMuc3RhdGU7XG5cbiAgICBjb25zdCBjdiA9IGdldENvbG9yVmFsdWUoY2VsbC5wcm9wZXJ0aWVzLnBvaW50cyk7XG5cbiAgICAvLyBpZiBjZWxsIHZhbHVlIGlzIG91dHNpZGUgZG9tYWluLCBzZXQgYWxwaGEgdG8gMFxuICAgIGNvbnN0IGNvbG9yID1cbiAgICAgIGN2ID49IGNvbG9yRG9tYWluWzBdICYmIGN2IDw9IGNvbG9yRG9tYWluW2NvbG9yRG9tYWluLmxlbmd0aCAtIDFdXG4gICAgICAgID8gY29sb3JTY2FsZUZ1bmMoY3YpXG4gICAgICAgIDogWzAsIDAsIDAsIDBdO1xuXG4gICAgLy8gYWRkIGZpbmFsIGFscGhhIHRvIGNvbG9yXG4gICAgY29sb3JbM10gPSBOdW1iZXIuaXNGaW5pdGUoY29sb3JbM10pID8gY29sb3JbM10gOiAyNTU7XG5cbiAgICByZXR1cm4gY29sb3I7XG4gIH1cblxuICBfb25HZXRTdWJsYXllclJhZGl1cyhjZWxsKSB7XG4gICAgY29uc3Qge2dldFJhZGl1c1ZhbHVlfSA9IHRoaXMucHJvcHM7XG4gICAgY29uc3Qge3JhZGl1c1NjYWxlRnVuY30gPSB0aGlzLnN0YXRlO1xuICAgIHJldHVybiByYWRpdXNTY2FsZUZ1bmMoZ2V0UmFkaXVzVmFsdWUoY2VsbCkpO1xuICB9XG5cbiAgZ2V0UGlja2luZ0luZm8oe2luZm99KSB7XG4gICAgY29uc3Qge2NsdXN0ZXJzfSA9IHRoaXMuc3RhdGU7XG4gICAgY29uc3QgaXNQaWNrZWQgPSBpbmZvLnBpY2tlZCAmJiBpbmZvLmluZGV4ID4gLTE7XG5cbiAgICBsZXQgb2JqZWN0ID0gbnVsbDtcbiAgICBpZiAoaXNQaWNrZWQpIHtcbiAgICAgIC8vIGFkZCBjbHVzdGVyIGNvbG9yVmFsdWUgdG8gb2JqZWN0XG4gICAgICBjb25zdCBjbHVzdGVyID0gY2x1c3RlcnNbaW5mby5pbmRleF07XG4gICAgICBjb25zdCBjb2xvclZhbHVlID0gdGhpcy5wcm9wcy5nZXRDb2xvclZhbHVlKGNsdXN0ZXIucHJvcGVydGllcy5wb2ludHMpO1xuXG4gICAgICBvYmplY3QgPSB7XG4gICAgICAgIC4uLmNsdXN0ZXIucHJvcGVydGllcyxcbiAgICAgICAgY29sb3JWYWx1ZSxcbiAgICAgICAgcmFkaXVzOiB0aGlzLl9vbkdldFN1YmxheWVyUmFkaXVzKGNsdXN0ZXIpLFxuICAgICAgICBwb3NpdGlvbjogY2x1c3Rlci5nZW9tZXRyeS5jb29yZGluYXRlc1xuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uaW5mbyxcbiAgICAgIHBpY2tlZDogQm9vbGVhbihvYmplY3QpLFxuICAgICAgLy8gb3ZlcnJpZGUgb2JqZWN0IHdpdGggcGlja2VkIGNsdXN0ZXIgcHJvcGVydHlcbiAgICAgIG9iamVjdFxuICAgIH07XG4gIH1cblxuICByZW5kZXJMYXllcnMoKSB7XG4gICAgLy8gZm9yIHN1YmNsYXNzaW5nLCBvdmVycmlkZSB0aGlzIG1ldGhvZCB0byByZXR1cm5cbiAgICAvLyBjdXN0b21pemVkIHN1YiBsYXllciBwcm9wc1xuICAgIGNvbnN0IHtpZCwgcmFkaXVzU2NhbGUsIGZwNjR9ID0gdGhpcy5wcm9wcztcblxuICAgIC8vIGJhc2UgbGF5ZXIgcHJvcHNcbiAgICBjb25zdCB7b3BhY2l0eSwgcGlja2FibGUsIGF1dG9IaWdobGlnaHQsIGhpZ2hsaWdodENvbG9yfSA9IHRoaXMucHJvcHM7XG5cbiAgICAvLyByZXR1cm4gcHJvcHMgdG8gdGhlIHN1YmxheWVyIGNvbnN0cnVjdG9yXG4gICAgcmV0dXJuIG5ldyBTY2F0dGVycGxvdExheWVyKHtcbiAgICAgIGlkOiBgJHtpZH0tY2x1c3RlcmAsXG4gICAgICBkYXRhOiB0aGlzLnN0YXRlLmNsdXN0ZXJzLFxuICAgICAgcmFkaXVzU2NhbGUsXG4gICAgICBmcDY0LFxuICAgICAgb3BhY2l0eSxcbiAgICAgIHBpY2thYmxlLFxuICAgICAgYXV0b0hpZ2hsaWdodCxcbiAgICAgIGhpZ2hsaWdodENvbG9yLFxuICAgICAgZ2V0UG9zaXRpb246IGQgPT4gZC5nZW9tZXRyeS5jb29yZGluYXRlcyxcbiAgICAgIGdldFJhZGl1czogdGhpcy5fb25HZXRTdWJsYXllclJhZGl1cy5iaW5kKHRoaXMpLFxuICAgICAgZ2V0Q29sb3I6IHRoaXMuX29uR2V0U3VibGF5ZXJDb2xvci5iaW5kKHRoaXMpLFxuICAgICAgdXBkYXRlVHJpZ2dlcnM6IHRoaXMuZ2V0VXBkYXRlVHJpZ2dlcnMoKVxuICAgIH0pO1xuICB9XG59XG5cbkNsdXN0ZXJMYXllci5sYXllck5hbWUgPSAnQ2x1c3RlckxheWVyJztcbkNsdXN0ZXJMYXllci5kZWZhdWx0UHJvcHMgPSBkZWZhdWx0UHJvcHM7XG4iXX0=