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