UNPKG

kepler.gl

Version:

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

269 lines (226 loc) 29 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.heatmapVisConfigs = exports.pointColResolver = exports.pointPosAccessor = exports.MAX_ZOOM_LEVEL = void 0; var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get")); 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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _reselect = require("reselect"); var _lodash = _interopRequireDefault(require("lodash.memoize")); var _defaultSettings = require("../../constants/default-settings"); var _colorUtils = require("../../utils/color-utils"); var _mapboxglLayer = _interopRequireDefault(require("../mapboxgl-layer")); var _heatmapLayerIcon = _interopRequireDefault(require("./heatmap-layer-icon")); 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; } 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 MAX_ZOOM_LEVEL = 18; exports.MAX_ZOOM_LEVEL = MAX_ZOOM_LEVEL; var pointPosAccessor = function pointPosAccessor(_ref) { var lat = _ref.lat, lng = _ref.lng; return function (dc) { return function (d) { return [dc.valueAt(d.index, lng.fieldIdx), dc.valueAt(d.index, lat.fieldIdx)]; }; }; }; exports.pointPosAccessor = pointPosAccessor; var pointColResolver = function pointColResolver(_ref2) { var lat = _ref2.lat, lng = _ref2.lng; return "".concat(lat.fieldIdx, "-").concat(lng.fieldIdx); }; exports.pointColResolver = pointColResolver; var heatmapVisConfigs = { opacity: 'opacity', colorRange: 'colorRange', radius: 'heatmapRadius' }; /** * * @param {Object} colorRange * @return {Array} [ * 0, "rgba(33,102,172,0)", * 0.2, "rgb(103,169,207)", * 0.4, "rgb(209,229,240)", * 0.6, "rgb(253,219,199)", * 0.8, "rgb(239,138,98)", * 1, "rgb(178,24,43)" * ] */ exports.heatmapVisConfigs = heatmapVisConfigs; var heatmapDensity = function heatmapDensity(colorRange) { var scaleFunction = _defaultSettings.SCALE_FUNC.quantize; var colors = ['#000000'].concat((0, _toConsumableArray2["default"])(colorRange.colors)); var scale = scaleFunction().domain([0, 1]).range(colors); var colorDensity = scale.range().reduce(function (bands, level) { var invert = scale.invertExtent(level); return [].concat((0, _toConsumableArray2["default"])(bands), [invert[0], // first value in the range "rgb(".concat((0, _colorUtils.hexToRgb)(level).join(','), ")") // color ]); }, []); colorDensity[1] = 'rgba(0,0,0,0)'; return colorDensity; }; var HeatmapLayer = /*#__PURE__*/function (_MapboxGLLayer) { (0, _inherits2["default"])(HeatmapLayer, _MapboxGLLayer); var _super = _createSuper(HeatmapLayer); function HeatmapLayer(props) { var _this; (0, _classCallCheck2["default"])(this, HeatmapLayer); _this = _super.call(this, props); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "columnsSelector", function (config) { return pointColResolver(config.columns); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "visConfigSelector", function (config) { return config.visConfig; }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "weightFieldSelector", function (config) { return config.weightField ? config.weightField.name : null; }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "weightDomainSelector", function (config) { return config.weightDomain; }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "paintSelector", (0, _reselect.createSelector)(_this.visConfigSelector, _this.weightFieldSelector, _this.weightDomainSelector, function (visConfig, weightField, weightDomain) { return { 'heatmap-weight': weightField ? ['interpolate', ['linear'], ['get', weightField], weightDomain[0], 0, weightDomain[1], 1] : 1, 'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, MAX_ZOOM_LEVEL, 3], 'heatmap-color': ['interpolate', ['linear'], ['heatmap-density']].concat((0, _toConsumableArray2["default"])(heatmapDensity(visConfig.colorRange))), 'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, MAX_ZOOM_LEVEL, visConfig.radius // radius ], 'heatmap-opacity': visConfig.opacity }; })); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "computeHeatmapConfiguration", (0, _reselect.createSelector)(_this.sourceSelector, _this.filterSelector, _this.paintSelector, function (source, filter, paint) { return _objectSpread({ type: 'heatmap', id: _this.id, source: source, layout: { visibility: 'visible' }, maxzoom: MAX_ZOOM_LEVEL, paint: paint }, _this.isValidFilter(filter) ? { filter: filter } : {}); })); _this.registerVisConfig(heatmapVisConfigs); _this.getPosition = (0, _lodash["default"])(pointPosAccessor, pointColResolver); return _this; } (0, _createClass2["default"])(HeatmapLayer, [{ key: "type", get: function get() { return 'heatmap'; } }, { key: "visualChannels", get: function get() { return { weight: { property: 'weight', field: 'weightField', scale: 'weightScale', domain: 'weightDomain', key: 'weight', // supportedFieldTypes can be determined by channelScaleType // or specified here defaultMeasure: 'property.density', supportedFieldTypes: [_defaultSettings.ALL_FIELD_TYPES.real, _defaultSettings.ALL_FIELD_TYPES.integer], channelScaleType: _defaultSettings.CHANNEL_SCALES.size } }; } }, { key: "layerIcon", get: function get() { return _heatmapLayerIcon["default"]; } }, { key: "getVisualChannelDescription", value: function getVisualChannelDescription(channel) { return channel === 'color' ? { label: 'property.color', measure: 'property.density' } : { label: 'property.weight', measure: this.config.weightField ? this.config.weightField.name : 'property.density' }; } }, { key: "getDefaultLayerConfig", value: function getDefaultLayerConfig() { var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; // mapbox heatmap layer color is always based on density // no need to set colorField, colorDomain and colorScale /* eslint-disable no-unused-vars */ var _get$call$weightField = _objectSpread(_objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(HeatmapLayer.prototype), "getDefaultLayerConfig", this).call(this, props)), {}, { weightField: null, weightDomain: [0, 1], weightScale: 'linear' }), colorField = _get$call$weightField.colorField, colorDomain = _get$call$weightField.colorDomain, colorScale = _get$call$weightField.colorScale, layerConfig = (0, _objectWithoutProperties2["default"])(_get$call$weightField, ["colorField", "colorDomain", "colorScale"]); /* eslint-enable no-unused-vars */ return layerConfig; } }, { key: "getPositionAccessor", value: function getPositionAccessor(dataContainer) { return this.getPosition(this.config.columns)(dataContainer); } }, { key: "updateLayerMeta", value: function updateLayerMeta(dataContainer) { var getPosition = this.getPositionAccessor(dataContainer); var bounds = this.getPointsBounds(dataContainer, getPosition); this.updateMeta({ bounds: bounds }); } }, { key: "getGeometry", value: function getGeometry(position) { return position.every(Number.isFinite) ? { type: 'Point', coordinates: position } : null; } }, { key: "formatLayerData", value: function formatLayerData(datasets, oldLayerData) { var weightField = this.config.weightField; var dataContainer = datasets[this.config.dataId].dataContainer; var getPosition = this.getPositionAccessor(dataContainer); var _this$updateData = this.updateData(datasets, oldLayerData), data = _this$updateData.data; var newConfig = this.computeHeatmapConfiguration(this.config, datasets); newConfig.id = this.id; return { columns: this.config.columns, config: newConfig, data: data, weightField: weightField, getPosition: getPosition }; } }]); return HeatmapLayer; }(_mapboxglLayer["default"]); var _default = HeatmapLayer; exports["default"] = _default; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvaGVhdG1hcC1sYXllci9oZWF0bWFwLWxheWVyLmpzIl0sIm5hbWVzIjpbIk1BWF9aT09NX0xFVkVMIiwicG9pbnRQb3NBY2Nlc3NvciIsImxhdCIsImxuZyIsImRjIiwiZCIsInZhbHVlQXQiLCJpbmRleCIsImZpZWxkSWR4IiwicG9pbnRDb2xSZXNvbHZlciIsImhlYXRtYXBWaXNDb25maWdzIiwib3BhY2l0eSIsImNvbG9yUmFuZ2UiLCJyYWRpdXMiLCJoZWF0bWFwRGVuc2l0eSIsInNjYWxlRnVuY3Rpb24iLCJTQ0FMRV9GVU5DIiwicXVhbnRpemUiLCJjb2xvcnMiLCJzY2FsZSIsImRvbWFpbiIsInJhbmdlIiwiY29sb3JEZW5zaXR5IiwicmVkdWNlIiwiYmFuZHMiLCJsZXZlbCIsImludmVydCIsImludmVydEV4dGVudCIsImpvaW4iLCJIZWF0bWFwTGF5ZXIiLCJwcm9wcyIsImNvbmZpZyIsImNvbHVtbnMiLCJ2aXNDb25maWciLCJ3ZWlnaHRGaWVsZCIsIm5hbWUiLCJ3ZWlnaHREb21haW4iLCJ2aXNDb25maWdTZWxlY3RvciIsIndlaWdodEZpZWxkU2VsZWN0b3IiLCJ3ZWlnaHREb21haW5TZWxlY3RvciIsInNvdXJjZVNlbGVjdG9yIiwiZmlsdGVyU2VsZWN0b3IiLCJwYWludFNlbGVjdG9yIiwic291cmNlIiwiZmlsdGVyIiwicGFpbnQiLCJ0eXBlIiwiaWQiLCJsYXlvdXQiLCJ2aXNpYmlsaXR5IiwibWF4em9vbSIsImlzVmFsaWRGaWx0ZXIiLCJyZWdpc3RlclZpc0NvbmZpZyIsImdldFBvc2l0aW9uIiwid2VpZ2h0IiwicHJvcGVydHkiLCJmaWVsZCIsImtleSIsImRlZmF1bHRNZWFzdXJlIiwic3VwcG9ydGVkRmllbGRUeXBlcyIsIkFMTF9GSUVMRF9UWVBFUyIsInJlYWwiLCJpbnRlZ2VyIiwiY2hhbm5lbFNjYWxlVHlwZSIsIkNIQU5ORUxfU0NBTEVTIiwic2l6ZSIsIkhlYXRtYXBMYXllckljb24iLCJjaGFubmVsIiwibGFiZWwiLCJtZWFzdXJlIiwid2VpZ2h0U2NhbGUiLCJjb2xvckZpZWxkIiwiY29sb3JEb21haW4iLCJjb2xvclNjYWxlIiwibGF5ZXJDb25maWciLCJkYXRhQ29udGFpbmVyIiwiZ2V0UG9zaXRpb25BY2Nlc3NvciIsImJvdW5kcyIsImdldFBvaW50c0JvdW5kcyIsInVwZGF0ZU1ldGEiLCJwb3NpdGlvbiIsImV2ZXJ5IiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJjb29yZGluYXRlcyIsImRhdGFzZXRzIiwib2xkTGF5ZXJEYXRhIiwiZGF0YUlkIiwidXBkYXRlRGF0YSIsImRhdGEiLCJuZXdDb25maWciLCJjb21wdXRlSGVhdG1hcENvbmZpZ3VyYXRpb24iLCJNYXBib3hHTExheWVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7OztBQUVPLElBQU1BLGNBQWMsR0FBRyxFQUF2Qjs7O0FBRUEsSUFBTUMsZ0JBQWdCLEdBQUcsU0FBbkJBLGdCQUFtQjtBQUFBLE1BQUVDLEdBQUYsUUFBRUEsR0FBRjtBQUFBLE1BQU9DLEdBQVAsUUFBT0EsR0FBUDtBQUFBLFNBQWdCLFVBQUFDLEVBQUU7QUFBQSxXQUFJLFVBQUFDLENBQUM7QUFBQSxhQUFJLENBQ3pERCxFQUFFLENBQUNFLE9BQUgsQ0FBV0QsQ0FBQyxDQUFDRSxLQUFiLEVBQW9CSixHQUFHLENBQUNLLFFBQXhCLENBRHlELEVBRXpESixFQUFFLENBQUNFLE9BQUgsQ0FBV0QsQ0FBQyxDQUFDRSxLQUFiLEVBQW9CTCxHQUFHLENBQUNNLFFBQXhCLENBRnlELENBQUo7QUFBQSxLQUFMO0FBQUEsR0FBbEI7QUFBQSxDQUF6Qjs7OztBQUtBLElBQU1DLGdCQUFnQixHQUFHLFNBQW5CQSxnQkFBbUI7QUFBQSxNQUFFUCxHQUFGLFNBQUVBLEdBQUY7QUFBQSxNQUFPQyxHQUFQLFNBQU9BLEdBQVA7QUFBQSxtQkFBbUJELEdBQUcs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QUFBLFdBQVcsRUFBWEE7QUFMSyxPQUFQO0FBT0Q7OztFQW5Kd0J1Qyx5Qjs7ZUFzSlovRCxZIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDIxIFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtjcmVhdGVTZWxlY3Rvcn0gZnJvbSAncmVzZWxlY3QnO1xuaW1wb3J0IG1lbW9pemUgZnJvbSAnbG9kYXNoLm1lbW9pemUnO1xuaW1wb3J0IHtDSEFOTkVMX1NDQUxFUywgU0NBTEVfRlVOQywgQUxMX0ZJRUxEX1RZUEVTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5pbXBvcnQge2hleFRvUmdifSBmcm9tICd1dGlscy9jb2xvci11dGlscyc7XG5pbXBvcnQgTWFwYm94R0xMYXllciBmcm9tICcuLi9tYXBib3hnbC1sYXllcic7XG5pbXBvcnQgSGVhdG1hcExheWVySWNvbiBmcm9tICcuL2hlYXRtYXAtbGF5ZXItaWNvbic7XG5cbmV4cG9ydCBjb25zdCBNQVhfWk9PTV9MRVZFTCA9IDE4O1xuXG5leHBvcnQgY29uc3QgcG9pbnRQb3NBY2Nlc3NvciA9ICh7bGF0LCBsbmd9KSA9PiBkYyA9PiBkID0+IFtcbiAgZGMudmFsdWVBdChkLmluZGV4LCBsbmcuZmllbGRJZHgpLFxuICBkYy52YWx1ZUF0KGQuaW5kZXgsIGxhdC5maWVsZElkeClcbl07XG5cbmV4cG9ydCBjb25zdCBwb2ludENvbFJlc29sdmVyID0gKHtsYXQsIGxuZ30pID0+IGAke2xhdC5maWVsZElkeH0tJHtsbmcuZmllbGRJZHh9YDtcblxuZXhwb3J0IGNvbnN0IGhlYXRtYXBWaXNDb25maWdzID0ge1xuICBvcGFjaXR5OiAnb3BhY2l0eScsXG4gIGNvbG9yUmFuZ2U6ICdjb2xvclJhbmdlJyxcbiAgcmFkaXVzOiAnaGVhdG1hcFJhZGl1cydcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjb2xvclJhbmdlXG4gKiBAcmV0dXJuIHtBcnJheX0gW1xuICogIDAsIFwicmdiYSgzMywxMDIsMTcyLDApXCIsXG4gKiAgMC4yLCBcInJnYigxMDMsMTY5LDIwNylcIixcbiAqICAwLjQsIFwicmdiKDIwOSwyMjksMjQwKVwiLFxuICogIDAuNiwgXCJyZ2IoMjUzLDIxOSwxOTkpXCIsXG4gKiAgMC44LCBcInJnYigyMzksMTM4LDk4KVwiLFxuICogIDEsIFwicmdiKDE3OCwyNCw0MylcIlxuICogXVxuICovXG5jb25zdCBoZWF0bWFwRGVuc2l0eSA9IGNvbG9yUmFuZ2UgPT4ge1xuICBjb25zdCBzY2FsZUZ1bmN0aW9uID0gU0NBTEVfRlVOQy5xdWFudGl6ZTtcblxuICBjb25zdCBjb2xvcnMgPSBbJyMwMDAwMDAnLCAuLi5jb2xvclJhbmdlLmNvbG9yc107XG5cbiAgY29uc3Qgc2NhbGUgPSBzY2FsZUZ1bmN0aW9uKClcbiAgICAuZG9tYWluKFswLCAxXSlcbiAgICAucmFuZ2UoY29sb3JzKTtcblxuICBjb25zdCBjb2xvckRlbnNpdHkgPSBzY2FsZS5yYW5nZSgpLnJlZHVjZSgoYmFuZHMsIGxldmVsKSA9PiB7XG4gICAgY29uc3QgaW52ZXJ0ID0gc2NhbGUuaW52ZXJ0RXh0ZW50KGxldmVsKTtcbiAgICByZXR1cm4gW1xuICAgICAgLi4uYmFuZHMsXG4gICAgICBpbnZlcnRbMF0sIC8vIGZpcnN0IHZhbHVlIGluIHRoZSByYW5nZVxuICAgICAgYHJnYigke2hleFRvUmdiKGxldmVsKS5qb2luKCcsJyl9KWAgLy8gY29sb3JcbiAgICBdO1xuICB9LCBbXSk7XG4gIGNvbG9yRGVuc2l0eVsxXSA9ICdyZ2JhKDAsMCwwLDApJztcbiAgcmV0dXJuIGNvbG9yRGVuc2l0eTtcbn07XG5cbmNsYXNzIEhlYXRtYXBMYXllciBleHRlbmRzIE1hcGJveEdMTGF5ZXIge1xuICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgIHN1cGVyKHByb3BzKTtcbiAgICB0aGlzLnJlZ2lzdGVyVmlzQ29uZmlnKGhlYXRtYXBWaXNDb25maWdzKTtcbiAgICB0aGlzLmdldFBvc2l0aW9uID0gbWVtb2l6ZShwb2ludFBvc0FjY2Vzc29yLCBwb2ludENvbFJlc29sdmVyKTtcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIHJldHVybiAnaGVhdG1hcCc7XG4gIH1cblxuICBnZXQgdmlzdWFsQ2hhbm5lbHMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHdlaWdodDoge1xuICAgICAgICBwcm9wZXJ0eTogJ3dlaWdodCcsXG4gICAgICAgIGZpZWxkOiAnd2VpZ2h0RmllbGQnLFxuICAgICAgICBzY2FsZTogJ3dlaWdodFNjYWxlJyxcbiAgICAgICAgZG9tYWluOiAnd2VpZ2h0RG9tYWluJyxcbiAgICAgICAga2V5OiAnd2VpZ2h0JyxcbiAgICAgICAgLy8gc3VwcG9ydGVkRmllbGRUeXBlcyBjYW4gYmUgZGV0ZXJtaW5lZCBieSBjaGFubmVsU2NhbGVUeXBlXG4gICAgICAgIC8vIG9yIHNwZWNpZmllZCBoZXJlXG4gICAgICAgIGRlZmF1bHRNZWFzdXJlOiAncHJvcGVydHkuZGVuc2l0eScsXG4gICAgICAgIHN1cHBvcnRlZEZpZWxkVHlwZXM6IFtBTExfRklFTERfVFlQRVMucmVhbCwgQUxMX0ZJRUxEX1RZUEVTLmludGVnZXJdLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiBDSEFOTkVMX1NDQUxFUy5zaXplXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIGdldCBsYXllckljb24oKSB7XG4gICAgcmV0dXJuIEhlYXRtYXBMYXllckljb247XG4gIH1cblxuICBnZXRWaXN1YWxDaGFubmVsRGVzY3JpcHRpb24oY2hhbm5lbCkge1xuICAgIHJldHVybiBjaGFubmVsID09PSAnY29sb3InXG4gICAgICA/IHtcbiAgICAgICAgICBsYWJlbDogJ3Byb3BlcnR5LmNvbG9yJyxcbiAgICAgICAgICBtZWFzdXJlOiAncHJvcGVydHkuZGVuc2l0eSdcbiAgICAgICAgfVxuICAgICAgOiB7XG4gICAgICAgICAgbGFiZWw6ICdwcm9wZXJ0eS53ZWlnaHQnLFxuICAgICAgICAgIG1lYXN1cmU6IHRoaXMuY29uZmlnLndlaWdodEZpZWxkID8gdGhpcy5jb25maWcud2VpZ2h0RmllbGQubmFtZSA6ICdwcm9wZXJ0eS5kZW5zaXR5J1xuICAgICAgICB9O1xuICB9XG5cbiAgZ2V0RGVmYXVsdExheWVyQ29uZmlnKHByb3BzID0ge30pIHtcbiAgICAvLyBtYXBib3ggaGVhdG1hcCBsYXllciBjb2xvciBpcyBhbHdheXMgYmFzZWQgb24gZGVuc2l0eVxuICAgIC8vIG5vIG5lZWQgdG8gc2V0IGNvbG9yRmllbGQsIGNvbG9yRG9tYWluIGFuZCBjb2xvclNjYWxlXG4gICAgLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICBjb25zdCB7Y29sb3JGaWVsZCwgY29sb3JEb21haW4sIGNvbG9yU2NhbGUsIC4uLmxheWVyQ29uZmlnfSA9IHtcbiAgICAgIC4uLnN1cGVyLmdldERlZmF1bHRMYXllckNvbmZpZyhwcm9wcyksXG5cbiAgICAgIHdlaWdodEZpZWxkOiBudWxsLFxuICAgICAgd2VpZ2h0RG9tYWluOiBbMCwgMV0sXG4gICAgICB3ZWlnaHRTY2FsZTogJ2xpbmVhcidcbiAgICB9O1xuICAgIC8qIGVzbGludC1lbmFibGUgbm8tdW51c2VkLXZhcnMgKi9cblxuICAgIHJldHVybiBsYXllckNvbmZpZztcbiAgfVxuXG4gIGdldFBvc2l0aW9uQWNjZXNzb3IoZGF0YUNvbnRhaW5lcikge1xuICAgIHJldHVybiB0aGlzLmdldFBvc2l0aW9uKHRoaXMuY29uZmlnLmNvbHVtbnMpKGRhdGFDb250YWluZXIpO1xuICB9XG5cbiAgdXBkYXRlTGF5ZXJNZXRhKGRhdGFDb250YWluZXIpIHtcbiAgICBjb25zdCBnZXRQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb25BY2Nlc3NvcihkYXRhQ29udGFpbmVyKTtcbiAgICBjb25zdCBib3VuZHMgPSB0aGlzLmdldFBvaW50c0JvdW5kcyhkYXRhQ29udGFpbmVyLCBnZXRQb3NpdGlvbik7XG4gICAgdGhpcy51cGRhdGVNZXRhKHtib3VuZHN9KTtcbiAgfVxuXG4gIGNvbHVtbnNTZWxlY3RvciA9IGNvbmZpZyA9PiBwb2ludENvbFJlc29sdmVyKGNvbmZpZy5jb2x1bW5zKTtcbiAgdmlzQ29uZmlnU2VsZWN0b3IgPSBjb25maWcgPT4gY29uZmlnLnZpc0NvbmZpZztcbiAgd2VpZ2h0RmllbGRTZWxlY3RvciA9IGNvbmZpZyA9PiAoY29uZmlnLndlaWdodEZpZWxkID8gY29uZmlnLndlaWdodEZpZWxkLm5hbWUgOiBudWxsKTtcbiAgd2VpZ2h0RG9tYWluU2VsZWN0b3IgPSBjb25maWcgPT4gY29uZmlnLndlaWdodERvbWFpbjtcblxuICBwYWludFNlbGVjdG9yID0gY3JlYXRlU2VsZWN0b3IoXG4gICAgdGhpcy52aXNDb25maWdTZWxlY3RvcixcbiAgICB0aGlzLndlaWdodEZpZWxkU2VsZWN0b3IsXG4gICAgdGhpcy53ZWlnaHREb21haW5TZWxlY3RvcixcbiAgICAodmlzQ29uZmlnLCB3ZWlnaHRGaWVsZCwgd2VpZ2h0RG9tYWluKSA9PiAoe1xuICAgICAgJ2hlYXRtYXAtd2VpZ2h0Jzogd2VpZ2h0RmllbGRcbiAgICAgICAgPyBbJ2ludGVycG9sYXRlJywgWydsaW5lYXInXSwgWydnZXQnLCB3ZWlnaHRGaWVsZF0sIHdlaWdodERvbWFpblswXSwgMCwgd2VpZ2h0RG9tYWluWzFdLCAxXVxuICAgICAgICA6IDEsXG4gICAgICAnaGVhdG1hcC1pbnRlbnNpdHknOiBbJ2ludGVycG9sYXRlJywgWydsaW5lYXInXSwgWyd6b29tJ10sIDAsIDEsIE1BWF9aT09NX0xFVkVMLCAzXSxcbiAgICAgICdoZWF0bWFwLWNvbG9yJzogW1xuICAgICAgICAnaW50ZXJwb2xhdGUnLFxuICAgICAgICBbJ2xpbmVhciddLFxuICAgICAgICBbJ2hlYXRtYXAtZGVuc2l0eSddLFxuICAgICAgICAuLi5oZWF0bWFwRGVuc2l0eSh2aXNDb25maWcuY29sb3JSYW5nZSlcbiAgICAgIF0sXG4gICAgICAnaGVhdG1hcC1yYWRpdXMnOiBbXG4gICAgICAgICdpbnRlcnBvbGF0ZScsXG4gICAgICAgIFsnbGluZWFyJ10sXG4gICAgICAgIFsnem9vbSddLFxuICAgICAgICAwLFxuICAgICAgICAyLFxuICAgICAgICBNQVhfWk9PTV9MRVZFTCxcbiAgICAgICAgdmlzQ29uZmlnLnJhZGl1cyAvLyByYWRpdXNcbiAgICAgIF0sXG4gICAgICAnaGVhdG1hcC1vcGFjaXR5JzogdmlzQ29uZmlnLm9wYWNpdHlcbiAgICB9KVxuICApO1xuXG4gIGNvbXB1dGVIZWF0bWFwQ29uZmlndXJhdGlvbiA9IGNyZWF0ZVNlbGVjdG9yKFxuICAgIHRoaXMuc291cmNlU2VsZWN0b3IsXG4gICAgdGhpcy5maWx0ZXJTZWxlY3RvcixcbiAgICB0aGlzLnBhaW50U2VsZWN0b3IsXG4gICAgKHNvdXJjZSwgZmlsdGVyLCBwYWludCkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogJ2hlYXRtYXAnLFxuICAgICAgICBpZDogdGhpcy5pZCxcbiAgICAgICAgc291cmNlLFxuICAgICAgICBsYXlvdXQ6IHtcbiAgICAgICAgICB2aXNpYmlsaXR5OiAndmlzaWJsZSdcbiAgICAgICAgfSxcbiAgICAgICAgbWF4em9vbTogTUFYX1pPT01fTEVWRUwsXG4gICAgICAgIHBhaW50LFxuICAgICAgICAuLi4odGhpcy5pc1ZhbGlkRmlsdGVyKGZpbHRlcikgPyB7ZmlsdGVyfSA6IHt9KVxuICAgICAgfTtcbiAgICB9XG4gICk7XG5cbiAgZ2V0R2VvbWV0cnkocG9zaXRpb24pIHtcbiAgICByZXR1cm4gcG9zaXRpb24uZXZlcnkoTnVtYmVyLmlzRmluaXRlKVxuICAgICAgPyB7XG4gICAgICAgICAgdHlwZTogJ1BvaW50JyxcbiAgICAgICAgICBjb29yZGluYXRlczogcG9zaXRpb25cbiAgICAgICAgfVxuICAgICAgOiBudWxsO1xuICB9XG5cbiAgZm9ybWF0TGF5ZXJEYXRhKGRhdGFzZXRzLCBvbGRMYXllckRhdGEpIHtcbiAgICBjb25zdCB7d2VpZ2h0RmllbGR9ID0gdGhpcy5jb25maWc7XG4gICAgY29uc3Qge2RhdGFDb250YWluZXJ9ID0gZGF0YXNldHNbdGhpcy5jb25maWcuZGF0YUlkXTtcbiAgICBjb25zdCBnZXRQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb25BY2Nlc3NvcihkYXRhQ29udGFpbmVyKTtcbiAgICBjb25zdCB7ZGF0YX0gPSB0aGlzLnVwZGF0ZURhdGEoZGF0YXNldHMsIG9sZExheWVyRGF0YSk7XG5cbiAgICBjb25zdCBuZXdDb25maWcgPSB0aGlzLmNvbXB1dGVIZWF0bWFwQ29uZmlndXJhdGlvbih0aGlzLmNvbmZpZywgZGF0YXNldHMpO1xuICAgIG5ld0NvbmZpZy5pZCA9IHRoaXMuaWQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29sdW1uczogdGhpcy5jb25maWcuY29sdW1ucyxcbiAgICAgIGNvbmZpZzogbmV3Q29uZmlnLFxuICAgICAgZGF0YSxcbiAgICAgIHdlaWdodEZpZWxkLFxuICAgICAgZ2V0UG9zaXRpb25cbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEhlYXRtYXBMYXllcjtcbiJdfQ==