kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
252 lines (215 loc) • 28.2 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.heatmapVisConfigs = 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 _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _reselect = require("reselect");
var _defaultSettings = require("../../constants/default-settings");
var _colorUtils = require("../../utils/color-utils");
var _mapboxUtils = require("../mapbox-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; }
var MAX_ZOOM_LEVEL = 18;
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 shouldRebuild = function shouldRebuild(sameData, sameConfig) {
return !(sameData && sameConfig);
};
var HeatmapLayer =
/*#__PURE__*/
function (_MapboxGLLayer) {
(0, _inherits2["default"])(HeatmapLayer, _MapboxGLLayer);
function HeatmapLayer(props) {
var _this;
(0, _classCallCheck2["default"])(this, HeatmapLayer);
_this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(HeatmapLayer).call(this, props));
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "isSameData", function (_ref, config) {
var allData = _ref.allData,
filteredIndex = _ref.filteredIndex,
oldLayerData = _ref.oldLayerData,
_ref$opt = _ref.opt,
opt = _ref$opt === void 0 ? {} : _ref$opt;
return Boolean(oldLayerData && oldLayerData.columns === config.columns && opt.sameData);
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "isSameConfig", function (_ref2) {
var oldLayerData = _ref2.oldLayerData,
config = _ref2.config;
// columns must use the same filedIdx
// this is a fast way to compare columns object
var columns = config.columns,
weightField = config.weightField;
if (!oldLayerData) {
return false;
}
var sameColumns = columns === oldLayerData.columns;
var sameWeightField = weightField === oldLayerData.weightField;
return sameColumns && sameWeightField;
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "datasetSelector", function (config) {
return config.dataId;
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "isVisibleSelector", function (config) {
return config.isVisible;
});
(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), "computeHeatmapConfiguration", (0, _reselect.createSelector)(_this.datasetSelector, _this.isVisibleSelector, _this.visConfigSelector, _this.weightFieldSelector, _this.weightDomainSelector, function (datasetId, isVisible, visConfig, weightField, weightDomain) {
var layer = {
type: 'heatmap',
id: _this.id,
source: datasetId,
layout: {
visibility: isVisible ? 'visible' : 'none'
},
maxzoom: MAX_ZOOM_LEVEL,
paint: {
'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
}
};
return layer;
}));
_this.registerVisConfig(heatmapVisConfigs);
return _this;
}
(0, _createClass2["default"])(HeatmapLayer, [{
key: "getVisualChannelDescription",
value: function getVisualChannelDescription(channel) {
return channel === 'color' ? {
label: 'color',
measure: 'Density'
} : {
label: 'weight',
measure: this.config.weightField ? this.config.weightField.name : '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({}, (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: "formatLayerData",
value: function formatLayerData(_, allData, filteredIndex, oldLayerData) {
var opt = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
var options = {
allData: allData,
filteredIndex: filteredIndex,
oldLayerData: oldLayerData,
opt: opt,
config: this.config
};
var weightField = this.config.weightField;
var isSameData = this.isSameData(options, this.config);
var isSameConfig = this.isSameConfig(options);
var data = !shouldRebuild(isSameData, isSameConfig) ? null : (0, _mapboxUtils.geojsonFromPoints)(allData, filteredIndex, this.config.columns, weightField ? [weightField] : []);
var newConfig = this.computeHeatmapConfiguration(this.config);
newConfig.id = this.id;
return {
columns: this.config.columns,
config: newConfig,
data: data,
weightField: weightField
};
}
}, {
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: '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"];
}
}]);
return HeatmapLayer;
}(_mapboxglLayer["default"]);
var _default = HeatmapLayer;
exports["default"] = _default;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvaGVhdG1hcC1sYXllci9oZWF0bWFwLWxheWVyLmpzIl0sIm5hbWVzIjpbIk1BWF9aT09NX0xFVkVMIiwiaGVhdG1hcFZpc0NvbmZpZ3MiLCJvcGFjaXR5IiwiY29sb3JSYW5nZSIsInJhZGl1cyIsImhlYXRtYXBEZW5zaXR5Iiwic2NhbGVGdW5jdGlvbiIsIlNDQUxFX0ZVTkMiLCJxdWFudGl6ZSIsImNvbG9ycyIsInNjYWxlIiwiZG9tYWluIiwicmFuZ2UiLCJjb2xvckRlbnNpdHkiLCJyZWR1Y2UiLCJiYW5kcyIsImxldmVsIiwiaW52ZXJ0IiwiaW52ZXJ0RXh0ZW50Iiwiam9pbiIsInNob3VsZFJlYnVpbGQiLCJzYW1lRGF0YSIsInNhbWVDb25maWciLCJIZWF0bWFwTGF5ZXIiLCJwcm9wcyIsImNvbmZpZyIsImFsbERhdGEiLCJmaWx0ZXJlZEluZGV4Iiwib2xkTGF5ZXJEYXRhIiwib3B0IiwiQm9vbGVhbiIsImNvbHVtbnMiLCJ3ZWlnaHRGaWVsZCIsInNhbWVDb2x1bW5zIiwic2FtZVdlaWdodEZpZWxkIiwiZGF0YUlkIiwiaXNWaXNpYmxlIiwidmlzQ29uZmlnIiwibmFtZSIsIndlaWdodERvbWFpbiIsImRhdGFzZXRTZWxlY3RvciIsImlzVmlzaWJsZVNlbGVjdG9yIiwidmlzQ29uZmlnU2VsZWN0b3IiLCJ3ZWlnaHRGaWVsZFNlbGVjdG9yIiwid2VpZ2h0RG9tYWluU2VsZWN0b3IiLCJkYXRhc2V0SWQiLCJsYXllciIsInR5cGUiLCJpZCIsInNvdXJjZSIsImxheW91dCIsInZpc2liaWxpdHkiLCJtYXh6b29tIiwicGFpbnQiLCJyZWdpc3RlclZpc0NvbmZpZyIsImNoYW5uZWwiLCJsYWJlbCIsIm1lYXN1cmUiLCJ3ZWlnaHRTY2FsZSIsImNvbG9yRmllbGQiLCJjb2xvckRvbWFpbiIsImNvbG9yU2NhbGUiLCJsYXllckNvbmZpZyIsIl8iLCJvcHRpb25zIiwiaXNTYW1lRGF0YSIsImlzU2FtZUNvbmZpZyIsImRhdGEiLCJuZXdDb25maWciLCJjb21wdXRlSGVhdG1hcENvbmZpZ3VyYXRpb24iLCJ3ZWlnaHQiLCJwcm9wZXJ0eSIsImZpZWxkIiwia2V5IiwiZGVmYXVsdE1lYXN1cmUiLCJzdXBwb3J0ZWRGaWVsZFR5cGVzIiwiQUxMX0ZJRUxEX1RZUEVTIiwicmVhbCIsImludGVnZXIiLCJjaGFubmVsU2NhbGVUeXBlIiwiQ0hBTk5FTF9TQ0FMRVMiLCJzaXplIiwiSGVhdG1hcExheWVySWNvbiIsIk1hcGJveEdMTGF5ZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7QUFFQSxJQUFNQSxjQUFjLEdBQUcsRUFBdkI7QUFFTyxJQUFNQyxpQkFBaUIsR0FBRztBQUMvQkMsRUFBQUEsT0FBTyxFQUFFLFNBRHNCO0FBRS9CQyxFQUFBQSxVQUFVLEVBQUUsWUFGbUI7QUFHL0JDLEVBQUFBLE1BQU0sRUFBRTtBQUh1QixDQUExQjtBQU1QOzs7Ozs7Ozs7Ozs7Ozs7QUFZQSxJQUFNQyxjQUFjLEdBQUcsU0FBakJBLGNBQWlCLENBQUNGLFVBQUQsRUFBZ0I7QUFDckMsTUFBTUcsYUFBYSxHQUFHQyw0QkFBV0MsUUFBakM7QUFFQSxNQUFNQyxNQUFNLElBQUksU0FBSiw2Q0FBa0JOLFVBQVUsQ0FBQ00sTUFBN0IsRUFBWjtBQUVBLE1BQU1DLEtBQUssR0FBR0osYUFBYSxHQUN4QkssTUFEVyxDQUNKLENBQUMsQ0FBRCxFQUFJLENBQUosQ0FESSxFQUVYQyxLQUZXLENBRUxILE1BRkssQ0FBZDtBQUlBLE1BQU1JLFlBQVksR0FBR0gsS0FBSyxDQUFDRSxLQUFOLEdBQWNFLE1BQWQsQ0FBcUIsVUFBQ0MsS0FBRCxFQUFRQyxLQUFSLEVBQWtCO0FBQzFELFFBQU1DLE1BQU0sR0FBR1AsS0FBSyxDQUFDUSxZQUFOLENBQW1CRixLQUFuQixDQUFmO0FBQ0EseURBQ0tELEtBREwsSUFFRUUsTUFBTSxDQUFDLENBQUQsQ0FG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QUFILEdBQW1CLEVBSmhDLENBRkY7QUFTQSxVQUFNb0MsU0FBUyxHQUFHLEtBQUtDLDJCQUFMLENBQWlDLEtBQUs1QyxNQUF0QyxDQUFsQjtBQUNBMkMsTUFBQUEsU0FBUyxDQUFDcEIsRUFBVixHQUFlLEtBQUtBLEVBQXBCO0FBRUEsYUFBTztBQUNMakIsUUFBQUEsT0FBTyxFQUFFLEtBQUtOLE1BQUwsQ0FBWU0sT0FEaEI7QUFFTE4sUUFBQUEsTUFBTSxFQUFFMkMsU0FGSDtBQUdMRCxRQUFBQSxJQUFJLEVBQUpBLElBSEs7QUFJTG5DLFFBQUFBLFdBQVcsRUFBWEE7QUFKSyxPQUFQO0FBTUQ7Ozt3QkFyS1U7QUFDVCxhQUFPLFNBQVA7QUFDRDs7O3dCQUVvQjtBQUNuQixhQUFPO0FBQ0xzQyxRQUFBQSxNQUFNLEVBQUU7QUFDTkMsVUFBQUEsUUFBUSxFQUFFLFFBREo7QUFFTkMsVUFBQUEsS0FBSyxFQUFFLGFBRkQ7QUFHTjlELFVBQUFBLEtBQUssRUFBRSxhQUhEO0FBSU5DLFVBQUFBLE1BQU0sRUFBRSxjQUpGO0FBS044RCxVQUFBQSxHQUFHLEVBQUUsUUFMQztBQU1OO0FBQ0E7QUFDQUMsVUFBQUEsY0FBYyxFQUFFLFNBUlY7QUFTTkMsVUFBQUEsbUJBQW1CLEVBQUUsQ0FBQ0MsaUNBQWdCQyxJQUFqQixFQUF1QkQsaUNBQWdCRSxPQUF2QyxDQVRmO0FBVU5DLFVBQUFBLGdCQUFnQixFQUFFQyxnQ0FBZUM7QUFWM0I7QUFESCxPQUFQO0FBY0Q7Ozt3QkFFZTtBQUNkLGFBQU9DLDRCQUFQO0FBQ0Q7OztFQTdCd0JDLHlCOztlQThLWjVELFkiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMTkgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQge2NyZWF0ZVNlbGVjdG9yfSBmcm9tICdyZXNlbGVjdCc7XG5pbXBvcnQge0NIQU5ORUxfU0NBTEVTLCBTQ0FMRV9GVU5DLCBBTExfRklFTERfVFlQRVN9IGZyb20gJ2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzJztcbmltcG9ydCB7aGV4VG9SZ2J9IGZyb20gJ3V0aWxzL2NvbG9yLXV0aWxzJztcbmltcG9ydCB7Z2VvanNvbkZyb21Qb2ludHN9IGZyb20gJy4uL21hcGJveC11dGlscyc7XG5pbXBvcnQgTWFwYm94R0xMYXllciBmcm9tICcuLi9tYXBib3hnbC1sYXllcic7XG5pbXBvcnQgSGVhdG1hcExheWVySWNvbiBmcm9tICcuL2hlYXRtYXAtbGF5ZXItaWNvbic7XG5cbmNvbnN0IE1BWF9aT09NX0xFVkVMID0gMTg7XG5cbmV4cG9ydCBjb25zdCBoZWF0bWFwVmlzQ29uZmlncyA9IHtcbiAgb3BhY2l0eTogJ29wYWNpdHknLFxuICBjb2xvclJhbmdlOiAnY29sb3JSYW5nZScsXG4gIHJhZGl1czogJ2hlYXRtYXBSYWRpdXMnXG59O1xuXG4vKipcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY29sb3JSYW5nZVxuICogQHJldHVybiB7QXJyYXl9IFtcbiAqICAwLCBcInJnYmEoMzMsMTAyLDE3MiwwKVwiLFxuICogIDAuMiwgXCJyZ2IoMTAzLDE2OSwyMDcpXCIsXG4gKiAgMC40LCBcInJnYigyMDksMjI5LDI0MClcIixcbiAqICAwLjYsIFwicmdiKDI1MywyMTksMTk5KVwiLFxuICogIDAuOCwgXCJyZ2IoMjM5LDEzOCw5OClcIixcbiAqICAxLCBcInJnYigxNzgsMjQsNDMpXCJcbiAqIF1cbiAqL1xuY29uc3QgaGVhdG1hcERlbnNpdHkgPSAoY29sb3JSYW5nZSkgPT4ge1xuICBjb25zdCBzY2FsZUZ1bmN0aW9uID0gU0NBTEVfRlVOQy5xdWFudGl6ZTtcblxuICBjb25zdCBjb2xvcnMgPSBbJyMwMDAwMDAnLCAuLi5jb2xvclJhbmdlLmNvbG9yc107XG5cbiAgY29uc3Qgc2NhbGUgPSBzY2FsZUZ1bmN0aW9uKClcbiAgICAuZG9tYWluKFswLCAxXSlcbiAgICAucmFuZ2UoY29sb3JzKTtcblxuICBjb25zdCBjb2xvckRlbnNpdHkgPSBzY2FsZS5yYW5nZSgpLnJlZHVjZSgoYmFuZHMsIGxldmVsKSA9PiB7XG4gICAgY29uc3QgaW52ZXJ0ID0gc2NhbGUuaW52ZXJ0RXh0ZW50KGxldmVsKTtcbiAgICByZXR1cm4gW1xuICAgICAgLi4uYmFuZHMsXG4gICAgICBpbnZlcnRbMF0sIC8vIGZpcnN0IHZhbHVlIGluIHRoZSByYW5nZVxuICAgICAgYHJnYigke2hleFRvUmdiKGxldmVsKS5qb2luKCcsJyl9KWAgLy8gY29sb3JcbiAgICBdXG4gIH0sIFtdKTtcbiAgY29sb3JEZW5zaXR5WzFdID0gJ3JnYmEoMCwwLDAsMCknO1xuICByZXR1cm4gY29sb3JEZW5zaXR5O1xufTtcblxuY29uc3Qgc2hvdWxkUmVidWlsZCA9IChzYW1lRGF0YSwgc2FtZUNvbmZpZykgPT4gIShzYW1lRGF0YSAmJiBzYW1lQ29uZmlnKTtcblxuY2xhc3MgSGVhdG1hcExheWVyIGV4dGVuZHMgTWFwYm94R0xMYXllciB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpO1xuICAgIHRoaXMucmVnaXN0ZXJWaXNDb25maWcoaGVhdG1hcFZpc0NvbmZpZ3MpO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdoZWF0bWFwJztcbiAgfVxuXG4gIGdldCB2aXN1YWxDaGFubmVscygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgd2VpZ2h0OiB7XG4gICAgICAgIHByb3BlcnR5OiAnd2VpZ2h0JyxcbiAgICAgICAgZmllbGQ6ICd3ZWlnaHRGaWVsZCcsXG4gICAgICAgIHNjYWxlOiAnd2VpZ2h0U2NhbGUnLFxuICAgICAgICBkb21haW46ICd3ZWlnaHREb21haW4nLFxuICAgICAgICBrZXk6ICd3ZWlnaHQnLFxuICAgICAgICAvLyBzdXBwb3J0ZWRGaWVsZFR5cGVzIGNhbiBiZSBkZXRlcm1pbmVkIGJ5IGNoYW5uZWxTY2FsZVR5cGVcbiAgICAgICAgLy8gb3Igc3BlY2lmaWVkIGhlcmVcbiAgICAgICAgZGVmYXVsdE1lYXN1cmU6ICdkZW5zaXR5JyxcbiAgICAgICAgc3VwcG9ydGVkRmllbGRUeXBlczogW0FMTF9GSUVMRF9UWVBFUy5yZWFsLCBBTExfRklFTERfVFlQRVMuaW50ZWdlcl0sXG4gICAgICAgIGNoYW5uZWxTY2FsZVR5cGU6IENIQU5ORUxfU0NBTEVTLnNpemVcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgZ2V0IGxheWVySWNvbigpIHtcbiAgICByZXR1cm4gSGVhdG1hcExheWVySWNvbjtcbiAgfVxuXG4gIGdldFZpc3VhbENoYW5uZWxEZXNjcmlwdGlvbihjaGFubmVsKSB7XG4gICAgcmV0dXJuIGNoYW5uZWwgPT09ICdjb2xvcicgPyB7XG4gICAgICBsYWJlbDogJ2NvbG9yJyxcbiAgICAgIG1lYXN1cmU6ICdEZW5zaXR5J1xuICAgIH0gOiB7XG4gICAgICBsYWJlbDogJ3dlaWdodCcsXG4gICAgICBtZWFzdXJlOiB0aGlzLmNvbmZpZy53ZWlnaHRGaWVsZCA/IHRoaXMuY29uZmlnLndlaWdodEZpZWxkLm5hbWUgOiAnRGVuc2l0eSdcbiAgICB9XG4gIH1cblxuICBnZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMgPSB7fSkge1xuXG4gICAgLy8gbWFwYm94IGhlYXRtYXAgbGF5ZXIgY29sb3IgaXMgYWx3YXlzIGJhc2VkIG9uIGRlbnNpdHlcbiAgICAvLyBubyBuZWVkIHRvIHNldCBjb2xvckZpZWxkLCBjb2xvckRvbWFpbiBhbmQgY29sb3JTY2FsZVxuICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG4gICAgY29uc3Qge2NvbG9yRmllbGQsIGNvbG9yRG9tYWluLCBjb2xvclNjYWxlLCAuLi5sYXllckNvbmZpZ30gPSB7XG4gICAgICAuLi5zdXBlci5nZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMpLFxuXG4gICAgICB3ZWlnaHRGaWVsZDogbnVsbCxcbiAgICAgIHdlaWdodERvbWFpbjogWzAsIDFdLFxuICAgICAgd2VpZ2h0U2NhbGU6ICdsaW5lYXInXG4gICAgfTtcbiAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLXVudXNlZC12YXJzICovXG5cbiAgICByZXR1cm4gbGF5ZXJDb25maWc7XG4gIH1cblxuICBpc1NhbWVEYXRhID0gKHthbGxEYXRhLCBmaWx0ZXJlZEluZGV4LCBvbGRMYXllckRhdGEsIG9wdCA9IHt9fSwgY29uZmlnKSA9PiB7XG4gICAgcmV0dXJuIEJvb2xlYW4ob2xkTGF5ZXJEYXRhICYmIG9sZExheWVyRGF0YS5jb2x1bW5zID09PSBjb25maWcuY29sdW1ucyAmJlxuICAgICAgb3B0LnNhbWVEYXRhXG4gICAgKTtcbiAgfTtcblxuICBpc1NhbWVDb25maWcgPSAoe29sZExheWVyRGF0YSwgY29uZmlnfSkgPT4ge1xuICAgIC8vIGNvbHVtbnMgbXVzdCB1c2UgdGhlIHNhbWUgZmlsZWRJZHhcbiAgICAvLyB0aGlzIGlzIGEgZmFzdCB3YXkgdG8gY29tcGFyZSBjb2x1bW5zIG9iamVjdFxuICAgIGNvbnN0IHtcbiAgICAgIGNvbHVtbnMsXG4gICAgICB3ZWlnaHRGaWVsZFxuICAgIH0gPSBjb25maWc7XG5cbiAgICBpZiAoIW9sZExheWVyRGF0YSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IHNhbWVDb2x1bW5zID0gY29sdW1ucyA9PT0gb2xkTGF5ZXJEYXRhLmNvbHVtbnM7XG4gICAgY29uc3Qgc2FtZVdlaWdodEZpZWxkID0gd2VpZ2h0RmllbGQgPT09IG9sZExheWVyRGF0YS53ZWlnaHRGaWVsZDtcbiAgICByZXR1cm4gc2FtZUNvbHVtbnMgJiYgc2FtZVdlaWdodEZpZWxkO1xuICB9O1xuXG4gIGRhdGFzZXRTZWxlY3RvciA9IGNvbmZpZyA9PiBjb25maWcuZGF0YUlkO1xuICBpc1Zpc2libGVTZWxlY3RvciA9IGNvbmZpZyA9PiBjb25maWcuaXNWaXNpYmxlO1xuICB2aXNDb25maWdTZWxlY3RvciA9IGNvbmZpZyA9PiBjb25maWcudmlzQ29uZmlnO1xuICB3ZWlnaHRGaWVsZFNlbGVjdG9yID0gY29uZmlnID0+IGNvbmZpZy53ZWlnaHRGaWVsZCA/IGNvbmZpZy53ZWlnaHRGaWVsZC5uYW1lIDogbnVsbDtcbiAgd2VpZ2h0RG9tYWluU2VsZWN0b3IgPSBjb25maWcgPT4gY29uZmlnLndlaWdodERvbWFpbjtcblxuICBjb21wdXRlSGVhdG1hcENvbmZpZ3VyYXRpb24gPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmRhdGFzZXRTZWxlY3RvcixcbiAgICB0aGlzLmlzVmlzaWJsZVNlbGVjdG9yLFxuICAgIHRoaXMudmlzQ29uZmlnU2VsZWN0b3IsXG4gICAgdGhpcy53ZWlnaHRGaWVsZFNlbGVjdG9yLFxuICAgIHRoaXMud2VpZ2h0RG9tYWluU2VsZWN0b3IsXG5cbiAgICAoZGF0YXNldElkLCBpc1Zpc2libGUsIHZpc0NvbmZpZywgd2VpZ2h0RmllbGQsIHdlaWdodERvbWFpbikgPT4ge1xuXG4gICAgICBjb25zdCBsYXllciA9IHtcbiAgICAgICAgdHlwZTogJ2hlYXRtYXAnLFxuICAgICAgICBpZDogdGhpcy5pZCxcbiAgICAgICAgc291cmNlOiBkYXRhc2V0SWQsXG4gICAgICAgIGxheW91dDoge1xuICAgICAgICAgIHZpc2liaWxpdHk6IGlzVmlzaWJsZSA/ICd2aXNpYmxlJyA6ICdub25lJ1xuICAgICAgICB9LFxuICAgICAgICBtYXh6b29tOiBNQVhfWk9PTV9MRVZFTCxcbiAgICAgICAgcGFpbnQ6IHtcbiAgICAgICAgICAnaGVhdG1hcC13ZWlnaHQnOiB3ZWlnaHRGaWVsZCA/IFtcbiAgICAgICAgICAgICdpbnRlcnBvbGF0ZScsXG4gICAgICAgICAgICBbJ2xpbmVhciddLFxuICAgICAgICAgICAgWydnZXQnLCB3ZWlnaHRGaWVsZF0sXG4gICAgICAgICAgICB3ZWlnaHREb21haW5bMF0sIDAsXG4gICAgICAgICAgICB3ZWlnaHREb21haW5bMV0sIDFcbiAgICAgICAgICBdIDogMSxcbiAgICAgICAgICAnaGVhdG1hcC1pbnRlbnNpdHknOiBbXG4gICAgICAgICAgICAnaW50ZXJwb2xhdGUnLFxuICAgICAgICAgICAgWydsaW5lYXInXSxcbiAgICAgICAgICAgIFsnem9vbSddLFxuICAgICAgICAgICAgMCwgMSxcbiAgICAgICAgICAgIE1BWF9aT09NX0xFVkVMLCAzXG4gICAgICAgICAgXSxcbiAgICAgICAgICAnaGVhdG1hcC1jb2xvcic6IFtcbiAgICAgICAgICAgICdpbnRlcnBvbGF0ZScsXG4gICAgICAgICAgICBbJ2xpbmVhciddLFxuICAgICAgICAgICAgWydoZWF0bWFwLWRlbnNpdHknXSxcbiAgICAgICAgICAgIC4uLmhlYXRtYXBEZW5zaXR5KHZpc0NvbmZpZy5jb2xvclJhbmdlKVxuICAgICAgICAgIF0sXG4gICAgICAgICAgJ2hlYXRtYXAtcmFkaXVzJzogW1xuICAgICAgICAgICAgJ2ludGVycG9sYXRlJyxcbiAgICAgICAgICAgIFsnbGluZWFyJ10sXG4gICAgICAgICAgICBbJ3pvb20nXSxcbiAgICAgICAgICAgIDAsIDIsXG4gICAgICAgICAgICBNQVhfWk9PTV9MRVZFTCwgdmlzQ29uZmlnLnJhZGl1cyAvLyByYWRpdXNcbiAgICAgICAgICBdLFxuICAgICAgICAgICdoZWF0bWFwLW9wYWNpdHknOiB2aXNDb25maWcub3BhY2l0eVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfVxuICApO1xuXG4gIGZvcm1hdExheWVyRGF0YShfLCBhbGxEYXRhLCBmaWx0ZXJlZEluZGV4LCBvbGRMYXllckRhdGEsIG9wdCA9IHt9KSB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgIGFsbERhdGEsXG4gICAgICBmaWx0ZXJlZEluZGV4LFxuICAgICAgb2xkTGF5ZXJEYXRhLFxuICAgICAgb3B0LFxuICAgICAgY29uZmlnOiB0aGlzLmNvbmZpZ1xuICAgIH07XG5cbiAgICBjb25zdCB7d2VpZ2h0RmllbGR9ID0gdGhpcy5jb25maWc7XG4gICAgY29uc3QgaXNTYW1lRGF0YSA9IHRoaXMuaXNTYW1lRGF0YShvcHRpb25zLCB0aGlzLmNvbmZpZyk7XG4gICAgY29uc3QgaXNTYW1lQ29uZmlnID0gdGhpcy5pc1NhbWVDb25maWcob3B0aW9ucyk7XG5cbiAgICBjb25zdCBkYXRhID0gIXNob3VsZFJlYnVpbGQoaXNTYW1lRGF0YSwgaXNTYW1lQ29uZmlnKSA/XG4gICAgICBudWxsIDpcbiAgICAgIGdlb2pzb25Gcm9tUG9pbnRzKFxuICAgICAgICBhbGxEYXRhLFxuICAgICAgICBmaWx0ZXJlZEluZGV4LFxuICAgICAgICB0aGlzLmNvbmZpZy5jb2x1bW5zLFxuICAgICAgICB3ZWlnaHRGaWVsZCA/IFt3ZWlnaHRGaWVsZF0gOiBbXVxuICAgICAgKTtcblxuICAgIGNvbnN0IG5ld0NvbmZpZyA9IHRoaXMuY29tcHV0ZUhlYXRtYXBDb25maWd1cmF0aW9uKHRoaXMuY29uZmlnKTtcbiAgICBuZXdDb25maWcuaWQgPSB0aGlzLmlkO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbHVtbnM6IHRoaXMuY29uZmlnLmNvbHVtbnMsXG4gICAgICBjb25maWc6IG5ld0NvbmZpZyxcbiAgICAgIGRhdGEsXG4gICAgICB3ZWlnaHRGaWVsZFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgSGVhdG1hcExheWVyO1xuIl19