UNPKG

kepler.gl.geoiq

Version:

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

307 lines (266 loc) 34.2 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 _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); 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(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 _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 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 = exports["default"] = /*#__PURE__*/function (_CompositeLayer) { (0, _inherits2["default"])(ClusterLayer, _CompositeLayer); var _super = _createSuper(ClusterLayer); function ClusterLayer() { (0, _classCallCheck2["default"])(this, ClusterLayer); return _super.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(_objectSpread({}, cluster.properties), {}, { colorValue: colorValue, radius: this._onGetSublayerRadius(cluster), position: cluster.geometry.coordinates }); } return _objectSpread(_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); ClusterLayer.layerName = 'ClusterLayer'; ClusterLayer.defaultProps = defaultProps; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNrZ2wtbGF5ZXJzL2NsdXN0ZXItbGF5ZXIvY2x1c3Rlci1sYXllci5qcyJdLCJuYW1lcyI6WyJkZWZhdWx0UmFkaXVzIiwiTEFZRVJfVklTX0NPTkZJR1MiLCJjbHVzdGVyUmFkaXVzIiwiZGVmYXVsdFZhbHVlIiwiZGVmYXVsdFJhZGl1c1JhbmdlIiwiY2x1c3RlclJhZGl1c1JhbmdlIiwiZGVmYXVsdFByb3BzIiwiY29sb3JEb21haW4iLCJjb2xvclJhbmdlIiwiRGVmYXVsdENvbG9yUmFuZ2UiLCJjb2xvclNjYWxlIiwiU0NBTEVfVFlQRVMiLCJxdWFudGl6ZSIsInJhZGl1c1JhbmdlIiwibG93ZXJQZXJjZW50aWxlIiwidXBwZXJQZXJjZW50aWxlIiwiZ2V0UG9zaXRpb24iLCJ4IiwicG9zaXRpb24iLCJnZXRDb2xvclZhbHVlIiwicG9pbnRzIiwibGVuZ3RoIiwiZ2V0UmFkaXVzVmFsdWUiLCJjZWxsIiwicHJvcGVydGllcyIsInBvaW50X2NvdW50IiwiZnA2NCIsIkNsdXN0ZXJMYXllciIsInN0YXRlIiwiY2x1c3RlcnMiLCJnZW9KU09OIiwiY2hhbmdlRmxhZ3MiLCJzb21ldGhpbmdDaGFuZ2VkIiwiY29udGV4dCIsIm9sZFByb3BzIiwicHJvcHMiLCJkYXRhQ2hhbmdlZCIsIm5lZWRzUmVQcm9qZWN0UG9pbnRzIiwicHJvY2Vzc0dlb0pTT04iLCJnZXRDbHVzdGVycyIsImdldENvbG9yVmFsdWVEb21haW4iLCJuZWVkc1JlY2x1c3RlclBvaW50cyIsIm5lZWRzUmVjYWxjdWxhdGVTY2FsZUZ1bmN0aW9uIiwiTWF0aCIsInJvdW5kIiwiem9vbSIsImRhdGEiLCJzZXRTdGF0ZSIsInZpZXdwb3J0IiwibG9uZ2l0dWRlIiwibGF0aXR1ZGUiLCJoZWlnaHQiLCJ3aWR0aCIsImJib3giLCJnZW9WaWV3cG9ydCIsImJvdW5kcyIsIm9uU2V0Q29sb3JEb21haW4iLCJyYWRpdXNEb21haW4iLCJjb2xvclZhbHVlcyIsIm1hcCIsImQiLCJpZGVudGl0eSIsIm9yZGluYWwiLCJxdWFudGlsZSIsImFzY2VuZGluZyIsImdldENvbG9yIiwiZ2V0UmFkaXVzIiwiY29sb3JTY2FsZUZ1bmMiLCJjdiIsImNvbG9yIiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJyYWRpdXNTY2FsZUZ1bmMiLCJpbmZvIiwiaXNQaWNrZWQiLCJwaWNrZWQiLCJpbmRleCIsIm9iamVjdCIsImNsdXN0ZXIiLCJjb2xvclZhbHVlIiwicmFkaXVzIiwiX29uR2V0U3VibGF5ZXJSYWRpdXMiLCJnZW9tZXRyeSIsImNvb3JkaW5hdGVzIiwiQm9vbGVhbiIsImlkIiwicmFkaXVzU2NhbGUiLCJvcGFjaXR5IiwicGlja2FibGUiLCJhdXRvSGlnaGxpZ2h0IiwiaGlnaGxpZ2h0Q29sb3IiLCJTY2F0dGVycGxvdExheWVyIiwiYmluZCIsIl9vbkdldFN1YmxheWVyQ29sb3IiLCJ1cGRhdGVUcmlnZ2VycyIsImdldFVwZGF0ZVRyaWdnZXJzIiwiQ29tcG9zaXRlTGF5ZXIiLCJsYXllck5hbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFLQTs7QUFPQTs7QUFDQTs7QUFDQTs7QUFFQTs7Ozs7Ozs7OztBQU1BLElBQU1BLGFBQWEsR0FBR0MsZ0NBQWtCQyxhQUFsQixDQUFnQ0MsWUFBdEQ7QUFDQSxJQUFNQyxrQkFBa0IsR0FBR0gsZ0NBQWtCSSxrQkFBbEIsQ0FBcUNGLFlBQWhFO0FBRUEsSUFBTUcsWUFBWSxHQUFHO0FBQ25CSixFQUFBQSxhQUFhLEVBQUVGLGFBREk7QUFFbkJPLEVBQUFBLFdBQVcsRUFBRSxJQUZNO0FBR25CQyxFQUFBQSxVQUFVLEVBQUVDLDhCQUhPO0FBSW5CQyxFQUFBQSxVQUFVLEVBQUVDLDZCQUFZQyxRQUpMO0FBS25CQyxFQUFBQSxXQUFXLEVBQUVULGtCQUxNO0FBT25CO0FBQ0FVLEVBQUFBLGVBQWUsRUFBRSxDQVJFO0FBU25CQyxFQUFBQSxlQUFlLEVBQUUsR0FURTtBQVduQkMs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QUExQixnQkFBMEJBLGFBQTFCO0FBQUEsVUFBeUNDLGNBQXpDLGdCQUF5Q0EsY0FBekMsQ0FOYSxDQVFiOztBQUNBLGFBQU8sSUFBSUMsc0JBQUosQ0FBcUI7QUFDMUJOLFFBQUFBLEVBQUUsWUFBS0EsRUFBTCxhQUR3QjtBQUUxQnZDLFFBQUFBLElBQUksRUFBRSxLQUFLbEIsS0FBTCxDQUFXQyxRQUZTO0FBRzFCeUQsUUFBQUEsV0FBVyxFQUFYQSxXQUgwQjtBQUkxQjVELFFBQUFBLElBQUksRUFBSkEsSUFKMEI7QUFLMUI2RCxRQUFBQSxPQUFPLEVBQVBBLE9BTDBCO0FBTTFCQyxRQUFBQSxRQUFRLEVBQVJBLFFBTjBCO0FBTzFCQyxRQUFBQSxhQUFhLEVBQWJBLGFBUDBCO0FBUTFCQyxRQUFBQSxjQUFjLEVBQWRBLGNBUjBCO0FBUzFCMUUsUUFBQUEsV0FBVyxFQUFFLHFCQUFBNEMsQ0FBQztBQUFBLGlCQUFJQSxDQUFDLENBQUNzQixRQUFGLENBQVdDLFdBQWY7QUFBQSxTQVRZO0FBVTFCakIsUUFBQUEsU0FBUyxFQUFFLEtBQUtlLG9CQUFMLENBQTBCVyxJQUExQixDQUErQixJQUEvQixDQVZlO0FBVzFCM0IsUUFBQUEsUUFBUSxFQUFFLEtBQUs0QixtQkFBTCxDQUF5QkQsSUFBekIsQ0FBOEIsSUFBOUIsQ0FYZ0I7QUFZMUJFLFFBQUFBLGNBQWMsRUFBRSxLQUFLQyxpQkFBTDtBQVpVLE9BQXJCLENBQVA7QUFjRDs7O0VBN011Q0Msb0I7O0FBZ04xQ3JFLFlBQVksQ0FBQ3NFLFNBQWIsR0FBeUIsY0FBekI7QUFDQXRFLFlBQVksQ0FBQ3JCLFlBQWIsR0FBNEJBLFlBQTVCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDIzIFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtDb21wb3NpdGVMYXllciwgU2NhdHRlcnBsb3RMYXllcn0gZnJvbSAnZGVjay5nbCc7XG5pbXBvcnQgZ2VvVmlld3BvcnQgZnJvbSAnQG1hcGJveC9nZW8tdmlld3BvcnQnO1xuaW1wb3J0IHthc2NlbmRpbmcsIG1heH0gZnJvbSAnZDMtYXJyYXknO1xuaW1wb3J0IHtcbiAgZ2V0UXVhbnRpbGVEb21haW4sXG4gIGdldE9yZGluYWxEb21haW4sXG4gIGdldExpbmVhckRvbWFpblxufSBmcm9tICd1dGlscy9kYXRhLXNjYWxlLXV0aWxzJztcbmltcG9ydCB7XG4gIGdldENvbG9yU2NhbGVGdW5jdGlvbixcbiAgZ2V0UmFkaXVzU2NhbGVGdW5jdGlvbixcbiAgbmVlZHNSZWNhbGN1bGF0ZVJhZGl1c1JhbmdlLFxuICBuZWVkc1JlY2FsY3VsYXRlQ29sb3JEb21haW4sXG4gIG5lZWRSZUNhbGN1bGF0ZVNjYWxlRnVuY3Rpb25cbn0gZnJvbSAnLi4vbGF5ZXItdXRpbHMvdXRpbHMnO1xuaW1wb3J0IHtEZWZhdWx0Q29sb3JSYW5nZX0gZnJvbSAnY29uc3RhbnRzL2NvbG9yLXJhbmdlcyc7XG5pbXBvcnQge0xBWUVSX1ZJU19DT05GSUdTfSBmcm9tICdsYXllcnMvbGF5ZXItZmFjdG9yeSc7XG5pbXBvcnQge1NDQUxFX1RZUEVTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5cbmltcG9ydCB7XG4gIGNsZWFyQ2x1c3RlcmVyQ2FjaGUsXG4gIGNsdXN0ZXJzQXRab29tLFxuICBnZXRHZW9KU09OXG59IGZyb20gJy4uL2xheWVyLXV0aWxzL2NsdXN0ZXItdXRpbHMnO1xuXG5jb25zdCBkZWZhdWx0UmFkaXVzID0gTEFZRVJfVklTX0NPTkZJR1MuY2x1c3RlclJhZGl1cy5kZWZhdWx0VmFsdWU7XG5jb25zdCBkZWZhdWx0UmFkaXVzUmFuZ2UgPSBMQVlFUl9WSVNfQ09ORklHUy5jbHVzdGVyUmFkaXVzUmFuZ2UuZGVmYXVsdFZhbHVlO1xuXG5jb25zdCBkZWZhdWx0UHJvcHMgPSB7XG4gIGNsdXN0ZXJSYWRpdXM6IGRlZmF1bHRSYWRpdXMsXG4gIGNvbG9yRG9tYWluOiBudWxsLFxuICBjb2xvclJhbmdlOiBEZWZhdWx0Q29sb3JSYW5nZSxcbiAgY29sb3JTY2FsZTogU0NBTEVfVFlQRVMucXVhbnRpemUsXG4gIHJhZGl1c1JhbmdlOiBkZWZhdWx0UmFkaXVzUmFuZ2UsXG5cbiAgLy8gbWF5YmUgbGF0ZXIuLi5cbiAgbG93ZXJQZXJjZW50aWxlOiAwLFxuICB1cHBlclBlcmNlbnRpbGU6IDEwMCxcblxuICBnZXRQb3NpdGlvbjogeCA9PiB4LnBvc2l0aW9uLFxuXG4gIC8vIGlmIHdhbnQgdG8gaGF2ZSBjb2xvciBiYXNlZCBvbiBjdXN0b21pemVkIGFnZ3JlZ2F0b3IsIGluc3RlYWQgb2YgY291bnRcbiAgZ2V0Q29sb3JWYWx1ZTogcG9pbnRzID0+IHBvaW50cy5sZW5ndGgsXG5cbiAgLy8gIGlmIHdhbnQgdG8gaGF2ZSByYWRpdXMgYmFzZWQgb24gY3VzdG9taXplZCBhZ2dyZWdhdG9yLCBpbnN0ZWFkIG9mIGNvdW50XG4gIGdldFJhZGl1c1ZhbHVlOiBjZWxsID0+IGNlbGwucHJvcGVydGllcy5wb2ludF9jb3VudCxcbiAgZnA2NDogZmFsc2Vcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENsdXN0ZXJMYXllciBleHRlbmRzIENvbXBvc2l0ZUxheWVyIHtcbiAgaW5pdGlhbGl6ZVN0YXRlKCkge1xuICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICBjbHVzdGVyczogbnVsbCxcbiAgICAgIGdlb0pTT046IG51bGxcbiAgICB9O1xuICB9XG5cbiAgc2hvdWxkVXBkYXRlU3RhdGUoe2NoYW5nZUZsYWdzfSkge1xuICAgIHJldHVybiBjaGFuZ2VGbGFncy5zb21ldGhpbmdDaGFuZ2VkO1xuICB9XG5cbiAgdXBkYXRlU3RhdGUoe2NvbnRleHQsIG9sZFByb3BzLCBwcm9wcywgY2hhbmdlRmxhZ3N9KSB7XG4gICAgaWYgKFxuICAgICAgY2hhbmdlRmxhZ3MuZGF0YUNoYW5nZWQgfHxcbiAgICAgIC8vIGNoYW5nZUZsYWdzLnZpZXdwb3J0Q2hhbmdlZCB8fFxuICAgICAgdGhpcy5uZWVkc1JlUHJvamVjdFBvaW50cyhvbGRQcm9wcywgcHJvcHMpXG4gICAgKSB7XG4gICAgICAvLyBwcm9qZWN0IGRhdGEgaW50byBjbHVzdGVycywgYW5kIGdldCBjbHVzdGVyZWQgZGF0YVxuICAgICAgdGhpcy5wcm9jZXNzR2VvSlNPTigpO1xuICAgICAgdGhpcy5nZXRDbHVzdGVycygpO1xuXG4gICAgICAvLyB0aGlzIG5lZWRzIGNsdXN0ZXJlZCBkYXRhIHRvIGJlIHNldFxuICAgICAgdGhpcy5nZXRDb2xvclZhbHVlRG9tYWluKCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLm5lZWRzUmVjbHVzdGVyUG9pbnRzKG9sZFByb3BzLCBwcm9wcykpIHtcbiAgICAgIHRoaXMuZ2V0Q2x1c3RlcnMoKTtcbiAgICAgIHRoaXMuZ2V0Q29sb3JWYWx1ZURvbWFpbigpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5uZWVkc1JlY2FsY3VsYXRlU2NhbGVGdW5jdGlvbihvbGRQcm9wcywgcHJvcHMpKSB7XG4gICAgICB0aGlzLmdldENvbG9yVmFsdWVEb21haW4oKTtcbiAgICB9XG4gIH1cblxuICBuZWVkc1JlUHJvamVjdFBvaW50cyhvbGRQcm9wcywgcHJvcHMpIHtcbiAgICByZXR1cm4gKFxuICAgICAgb2xkUHJvcHMuY2x1c3RlclJhZGl1cyAhPT0gcHJvcHMuY2x1c3RlclJhZGl1cyB8fFxuICAgICAgb2xkUHJvcHMuZ2V0UG9zaXRpb24gIT09IHByb3BzLmdldFBvc2l0aW9uXG4gICAgKTtcbiAgfVxuXG4gIG5lZWRzUmVjbHVzdGVyUG9pbnRzKG9sZFByb3BzLCBwcm9wcykge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKG9sZFByb3BzLnpvb20pICE9PSBNYXRoLnJvdW5kKHByb3BzLnpvb20pO1xuICB9XG5cbiAgbmVlZHNSZWNhbGN1bGF0ZVNjYWxlRnVuY3Rpb24ob2xkUHJvcHMsIHByb3BzKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIG5lZWRzUmVjYWxjdWxhdGVDb2xvckRvbWFpbihvbGRQcm9wcywgcHJvcHMpIHx8XG4gICAgICBuZWVkUmVDYWxjdWxhdGVTY2FsZUZ1bmN0aW9uKG9sZFByb3BzLCBwcm9wcykgfHxcbiAgICAgIG5lZWRzUmVjYWxjdWxhdGVSYWRpdXNSYW5nZShvbGRQcm9wcywgcHJvcHMpIHx8XG4gICAgICBvbGRQcm9wcy5nZXRDb2xvclZhbHVlICE9PSBwcm9wcy5nZXRDb2xvclZhbHVlXG4gICAgKTtcbiAgfVxuXG4gIHByb2Nlc3NHZW9KU09OKCkge1xuICAgIGNvbnN0IHtkYXRhLCBnZXRQb3NpdGlvbn0gPSB0aGlzLnByb3BzO1xuICAgIHRoaXMuc2V0U3RhdGUoe2dlb0pTT046IGdldEdlb0pTT04oZGF0YSwgZ2V0UG9zaXRpb24pfSk7XG4gICAgY2xlYXJDbHVzdGVyZXJDYWNoZSgpO1xuICB9XG5cbiAgZ2V0Q2x1c3RlcnMoKSB7XG4gICAgY29uc3Qge2dlb0pTT059ID0gdGhpcy5zdGF0ZTtcbiAgICBjb25zdCB7Y2x1c3RlclJhZGl1c30gPSB0aGlzLnByb3BzO1xuICAgIGNvbnN0IHtcbiAgICAgIHZpZXdwb3J0LFxuICAgICAgdmlld3BvcnQ6IHtsb25naXR1ZGUsIGxhdGl0dWRlLCBoZWlnaHQsIHdpZHRofVxuICAgIH0gPSB0aGlzLmNvbnRleHQ7XG5cbiAgICAvLyB6b29tIG5lZWRzIHRvIGJlIGFuIGludGVnZXIgZm9yIHRoZSBkaWZmZXJlbnQgbWFwIHV0aWxzLiBBbHNvIGhlbHBzIHdpdGggY2FjaGUga2V5LlxuICAgIGNvbnN0IHpvb20gPSBNYXRoLnJvdW5kKHZpZXdwb3J0Lnpvb20pO1xuICAgIGNvbnN0IGJib3ggPSBnZW9WaWV3cG9ydC5ib3VuZHMoW2xvbmdpdHVkZSwgbGF0aXR1ZGVdLCB6b29tLCBbXG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodFxuICAgIF0pO1xuXG4gICAgY29uc3QgY2x1c3RlcnMgPSBjbHVzdGVyc0F0Wm9vbSh7YmJveCwgY2x1c3RlclJhZGl1cywgZ2VvSlNPTiwgem9vbX0pO1xuXG4gICAgdGhpcy5zZXRTdGF0ZSh7Y2x1c3RlcnN9KTtcbiAgfVxuXG4gIGdldENvbG9yVmFsdWVEb21haW4oKSB7XG4gICAgY29uc3Qge1xuICAgICAgY29sb3JTY2FsZSxcbiAgICAgIGdldENvbG9yVmFsdWUsXG4gICAgICBnZXRSYWRpdXNWYWx1ZSxcbiAgICAgIG9uU2V0Q29sb3JEb21haW5cbiAgICB9ID0gdGhpcy5wcm9wcztcbiAgICBjb25zdCB7Y2x1c3RlcnN9ID0gdGhpcy5zdGF0ZTtcblxuICAgIGNvbnN0IHJhZGl1c0RvbWFpbiA9IFswLCBtYXgoY2x1c3RlcnMsIGdldFJhZGl1c1ZhbHVlKV07XG5cbiAgICBjb25zdCBjb2xvclZhbHVlcyA9IGNsdXN0ZXJzLm1hcChkID0+IGdldENvbG9yVmFsdWUoZC5wcm9wZXJ0aWVzLnBvaW50cykpO1xuXG4gICAgY29uc3QgaWRlbnRpdHkgPSBkID0+IGQ7XG5cbiAgICBjb25zdCBjb2xvckRvbWFpbiA9XG4gICAgICBjb2xvclNjYWxlID09PSBTQ0FMRV9UWVBFUy5vcmRpbmFsXG4gICAgICAgID8gZ2V0T3JkaW5hbERvbWFpbihjb2xvclZhbHVlcywgaWRlbnRpdHkpXG4gICAgICAgIDogY29sb3JTY2FsZSA9PT0gU0NBTEVfVFlQRVMucXVhbnRpbGVcbiAgICAgICAgPyBnZXRRdWFudGlsZURvbWFpbihjb2xvclZhbHVlcywgaWRlbnRpdHksIGFzY2VuZGluZylcbiAgICAgICAgOiBnZXRMaW5lYXJEb21haW4oY29sb3JWYWx1ZXMsIGlkZW50aXR5KTtcblxuICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgY29sb3JEb21haW4sXG4gICAgICByYWRpdXNEb21haW5cbiAgICB9KTtcblxuICAgIGdldENvbG9yU2NhbGVGdW5jdGlvbih0aGlzKTtcbiAgICBnZXRSYWRpdXNTY2FsZUZ1bmN0aW9uKHRoaXMpO1xuXG4gICAgb25TZXRDb2xvckRvbWFpbihjb2xvckRvbWFpbik7XG4gIH1cblxuICBnZXRVcGRhdGVUcmlnZ2VycygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZ2V0Q29sb3I6IHtcbiAgICAgICAgY29sb3JSYW5nZTogdGhpcy5wcm9wcy5jb2xvclJhbmdlLFxuICAgICAgICBjb2xvckRvbWFpbjogdGhpcy5wcm9wcy5jb2xvckRvbWFpbixcbiAgICAgICAgZ2V0Q29sb3JWYWx1ZTogdGhpcy5wcm9wcy5nZXRDb2xvclZhbHVlLFxuICAgICAgICBjb2xvclNjYWxlOiB0aGlzLnByb3BzLmNvbG9yU2NhbGUsXG4gICAgICAgIGxvd2VyUGVyY2VudGlsZTogdGhpcy5wcm9wcy5sb3dlclBlcmNlbnRpbGUsXG4gICAgICAgIHVwcGVyUGVyY2VudGlsZTogdGhpcy5wcm9wcy51cHBlclBlcmNlbnRpbGVcbiAgICAgIH0sXG4gICAgICBnZXRSYWRpdXM6IHtcbiAgICAgICAgcmFkaXVzUmFuZ2U6IHRoaXMucHJvcHMucmFkaXVzUmFuZ2UsXG4gICAgICAgIHJhZGl1c0RvbWFpbjogdGhpcy5wcm9wcy5yYWRpdXNEb21haW4sXG4gICAgICAgIGdldFJhZGl1c1ZhbHVlOiB0aGlzLnByb3BzLmdldFJhZGl1c1ZhbHVlXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qXG4gICAqIG92ZXJyaWRlIGRlZmF1bHQgbGF5ZXIgbWV0aG9kIHRvIGNhbGN1bGF0ZSBjZWxsIGNvbG9yIGJhc2VkIG9uIGNvbG9yIHNjYWxlIGZ1bmN0aW9uXG4gICAqL1xuICBfb25HZXRTdWJsYXllckNvbG9yKGNlbGwpIHtcbiAgICBjb25zdCB7Z2V0Q29sb3JWYWx1ZX0gPSB0aGlzLnByb3BzO1xuICAgIGNvbnN0IHtjb2xvclNjYWxlRnVuYywgY29sb3JEb21haW59ID0gdGhpcy5zdGF0ZTtcblxuICAgIGNvbnN0IGN2ID0gZ2V0Q29sb3JWYWx1ZShjZWxsLnByb3BlcnRpZXMucG9pbnRzKTtcblxuICAgIC8vIGlmIGNlbGwgdmFsdWUgaXMgb3V0c2lkZSBkb21haW4sIHNldCBhbHBoYSB0byAwXG4gICAgY29uc3QgY29sb3IgPVxuICAgICAgY3YgPj0gY29sb3JEb21haW5bMF0gJiYgY3YgPD0gY29sb3JEb21haW5bY29sb3JEb21haW4ubGVuZ3RoIC0gMV1cbiAgICAgICAgPyBjb2xvclNjYWxlRnVuYyhjdilcbiAgICAgICAgOiBbMCwgMCwgMCwgMF07XG5cbiAgICAvLyBhZGQgZmluYWwgYWxwaGEgdG8gY29sb3JcbiAgICBjb2xvclszXSA9IE51bWJlci5pc0Zpbml0ZShjb2xvclszXSkgPyBjb2xvclszXSA6IDI1NTtcblxuICAgIHJldHVybiBjb2xvcjtcbiAgfVxuXG4gIF9vbkdldFN1YmxheWVyUmFkaXVzKGNlbGwpIHtcbiAgICBjb25zdCB7Z2V0UmFkaXVzVmFsdWV9ID0gdGhpcy5wcm9wcztcbiAgICBjb25zdCB7cmFkaXVzU2NhbGVGdW5jfSA9IHRoaXMuc3RhdGU7XG4gICAgcmV0dXJuIHJhZGl1c1NjYWxlRnVuYyhnZXRSYWRpdXNWYWx1ZShjZWxsKSk7XG4gIH1cblxuICBnZXRQaWNraW5nSW5mbyh7aW5mb30pIHtcbiAgICBjb25zdCB7Y2x1c3RlcnN9ID0gdGhpcy5zdGF0ZTtcbiAgICBjb25zdCBpc1BpY2tlZCA9IGluZm8ucGlja2VkICYmIGluZm8uaW5kZXggPiAtMTtcblxuICAgIGxldCBvYmplY3QgPSBudWxsO1xuICAgIGlmIChpc1BpY2tlZCkge1xuICAgICAgLy8gYWRkIGNsdXN0ZXIgY29sb3JWYWx1ZSB0byBvYmplY3RcbiAgICAgIGNvbnN0IGNsdXN0ZXIgPSBjbHVzdGVyc1tpbmZvLmluZGV4XTtcbiAgICAgIGNvbnN0IGNvbG9yVmFsdWUgPSB0aGlzLnByb3BzLmdldENvbG9yVmFsdWUoY2x1c3Rlci5wcm9wZXJ0aWVzLnBvaW50cyk7XG5cbiAgICAgIG9iamVjdCA9IHtcbiAgICAgICAgLi4uY2x1c3Rlci5wcm9wZXJ0aWVzLFxuICAgICAgICBjb2xvclZhbHVlLFxuICAgICAgICByYWRpdXM6IHRoaXMuX29uR2V0U3VibGF5ZXJSYWRpdXMoY2x1c3RlciksXG4gICAgICAgIHBvc2l0aW9uOiBjbHVzdGVyLmdlb21ldHJ5LmNvb3JkaW5hdGVzXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAuLi5pbmZvLFxuICAgICAgcGlja2VkOiBCb29sZWFuKG9iamVjdCksXG4gICAgICAvLyBvdmVycmlkZSBvYmplY3Qgd2l0aCBwaWNrZWQgY2x1c3RlciBwcm9wZXJ0eVxuICAgICAgb2JqZWN0XG4gICAgfTtcbiAgfVxuXG4gIHJlbmRlckxheWVycygpIHtcbiAgICAvLyBmb3Igc3ViY2xhc3NpbmcsIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIHJldHVyblxuICAgIC8vIGN1c3RvbWl6ZWQgc3ViIGxheWVyIHByb3BzXG4gICAgY29uc3Qge2lkLCByYWRpdXNTY2FsZSwgZnA2NH0gPSB0aGlzLnByb3BzO1xuXG4gICAgLy8gYmFzZSBsYXllciBwcm9wc1xuICAgIGNvbnN0IHtvcGFjaXR5LCBwaWNrYWJsZSwgYXV0b0hpZ2hsaWdodCwgaGlnaGxpZ2h0Q29sb3J9ID0gdGhpcy5wcm9wcztcblxuICAgIC8vIHJldHVybiBwcm9wcyB0byB0aGUgc3VibGF5ZXIgY29uc3RydWN0b3JcbiAgICByZXR1cm4gbmV3IFNjYXR0ZXJwbG90TGF5ZXIoe1xuICAgICAgaWQ6IGAke2lkfS1jbHVzdGVyYCxcbiAgICAgIGRhdGE6IHRoaXMuc3RhdGUuY2x1c3RlcnMsXG4gICAgICByYWRpdXNTY2FsZSxcbiAgICAgIGZwNjQsXG4gICAgICBvcGFjaXR5LFxuICAgICAgcGlja2FibGUsXG4gICAgICBhdXRvSGlnaGxpZ2h0LFxuICAgICAgaGlnaGxpZ2h0Q29sb3IsXG4gICAgICBnZXRQb3NpdGlvbjogZCA9PiBkLmdlb21ldHJ5LmNvb3JkaW5hdGVzLFxuICAgICAgZ2V0UmFkaXVzOiB0aGlzLl9vbkdldFN1YmxheWVyUmFkaXVzLmJpbmQodGhpcyksXG4gICAgICBnZXRDb2xvcjogdGhpcy5fb25HZXRTdWJsYXllckNvbG9yLmJpbmQodGhpcyksXG4gICAgICB1cGRhdGVUcmlnZ2VyczogdGhpcy5nZXRVcGRhdGVUcmlnZ2VycygpXG4gICAgfSk7XG4gIH1cbn1cblxuQ2x1c3RlckxheWVyLmxheWVyTmFtZSA9ICdDbHVzdGVyTGF5ZXInO1xuQ2x1c3RlckxheWVyLmRlZmF1bHRQcm9wcyA9IGRlZmF1bHRQcm9wcztcbiJdfQ==