UNPKG

kepler.gl

Version:

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

395 lines (346 loc) 43.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.pointVisConfigs = exports.pointOptionalColumns = exports.pointRequiredColumns = exports.pointPosAccessor = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _extensions = require("@deck.gl/extensions"); var _layers = require("@deck.gl/layers"); var _baseLayer = _interopRequireDefault(require("../base-layer")); var _colorUtils = require("../../utils/color-utils"); var _pointLayerIcon = _interopRequireDefault(require("./point-layer-icon")); var _defaultSettings = require("../../constants/default-settings"); var _layerTextLabel = require("../layer-text-label"); 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 pointPosAccessor = function pointPosAccessor(_ref) { var lat = _ref.lat, lng = _ref.lng, altitude = _ref.altitude; return function (d) { return [// lng d.data[lng.fieldIdx], // lat d.data[lat.fieldIdx], altitude && altitude.fieldIdx > -1 ? d.data[altitude.fieldIdx] : 0]; }; }; exports.pointPosAccessor = pointPosAccessor; var pointRequiredColumns = ['lat', 'lng']; exports.pointRequiredColumns = pointRequiredColumns; var pointOptionalColumns = ['altitude']; exports.pointOptionalColumns = pointOptionalColumns; var brushingExtension = new _extensions.BrushingExtension(); var pointVisConfigs = { radius: 'radius', fixedRadius: 'fixedRadius', opacity: 'opacity', outline: 'outline', thickness: 'thickness', strokeColor: 'strokeColor', colorRange: 'colorRange', strokeColorRange: 'strokeColorRange', radiusRange: 'radiusRange', filled: { type: 'boolean', label: 'layer.fillColor', defaultValue: true, property: 'filled' } }; exports.pointVisConfigs = pointVisConfigs; var PointLayer = /*#__PURE__*/ function (_Layer) { (0, _inherits2["default"])(PointLayer, _Layer); function PointLayer(props) { var _this; (0, _classCallCheck2["default"])(this, PointLayer); _this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(PointLayer).call(this, props)); _this.registerVisConfig(pointVisConfigs); _this.getPositionAccessor = function () { return pointPosAccessor(_this.config.columns); }; return _this; } (0, _createClass2["default"])(PointLayer, [{ key: "getDefaultLayerConfig", value: function getDefaultLayerConfig() { var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return _objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(PointLayer.prototype), "getDefaultLayerConfig", this).call(this, props), { // add stroke color visual channel strokeColorField: null, strokeColorDomain: [0, 1], strokeColorScale: 'quantile' }); } }, { key: "calculateDataAttribute", value: function calculateDataAttribute(_ref2, getPosition) { var allData = _ref2.allData, filteredIndex = _ref2.filteredIndex; var data = []; for (var i = 0; i < filteredIndex.length; i++) { var index = filteredIndex[i]; var pos = getPosition({ data: allData[index] }); // if doesn't have point lat or lng, do not add the point // deck.gl can't handle position = null if (pos.every(Number.isFinite)) { data.push({ data: allData[index], position: pos, // index is important for filter index: index }); } } return data; } }, { key: "formatLayerData", value: function formatLayerData(datasets, oldLayerData) { var _this2 = this; var _this$config = this.config, colorScale = _this$config.colorScale, colorDomain = _this$config.colorDomain, colorField = _this$config.colorField, strokeColorField = _this$config.strokeColorField, strokeColorScale = _this$config.strokeColorScale, strokeColorDomain = _this$config.strokeColorDomain, color = _this$config.color, sizeField = _this$config.sizeField, sizeScale = _this$config.sizeScale, sizeDomain = _this$config.sizeDomain, textLabel = _this$config.textLabel, _this$config$visConfi = _this$config.visConfig, radiusRange = _this$config$visConfi.radiusRange, fixedRadius = _this$config$visConfi.fixedRadius, colorRange = _this$config$visConfi.colorRange, strokeColorRange = _this$config$visConfi.strokeColorRange, strokeColor = _this$config$visConfi.strokeColor; var gpuFilter = datasets[this.config.dataId].gpuFilter; var _this$updateData = this.updateData(datasets, oldLayerData), data = _this$updateData.data, triggerChanged = _this$updateData.triggerChanged; var getPosition = this.getPositionAccessor(); // point color var cScale = colorField && this.getVisChannelScale(colorScale, colorDomain, colorRange.colors.map(_colorUtils.hexToRgb)); // stroke color var scScale = strokeColorField && this.getVisChannelScale(strokeColorScale, strokeColorDomain, strokeColorRange.colors.map(_colorUtils.hexToRgb)); // point radius var rScale = sizeField && this.getVisChannelScale(sizeScale, sizeDomain, radiusRange, fixedRadius); var getRadius = rScale ? function (d) { return _this2.getEncodedChannelValue(rScale, d.data, sizeField, 0); } : 1; var getFillColor = cScale ? function (d) { return _this2.getEncodedChannelValue(cScale, d.data, colorField); } : color; var getLineColor = scScale ? function (d) { return _this2.getEncodedChannelValue(scScale, d.data, strokeColorField); } : strokeColor || color; // get all distinct characters in the text labels var textLabels = (0, _layerTextLabel.formatTextLabelData)({ textLabel: textLabel, triggerChanged: triggerChanged, oldLayerData: oldLayerData, data: data }); return { data: data, getPosition: getPosition, getFillColor: getFillColor, getLineColor: getLineColor, getFilterValue: gpuFilter.filterValueAccessor(), getRadius: getRadius, textLabels: textLabels }; } /* eslint-enable complexity */ }, { key: "updateLayerMeta", value: function updateLayerMeta(allData) { var getPosition = this.getPositionAccessor(); var bounds = this.getPointsBounds(allData, function (d) { return getPosition({ data: d }); }); this.updateMeta({ bounds: bounds }); } }, { key: "renderLayer", value: function renderLayer(opts) { var data = opts.data, gpuFilter = opts.gpuFilter, objectHovered = opts.objectHovered, mapState = opts.mapState, interactionConfig = opts.interactionConfig; var radiusScale = this.getRadiusScaleByZoom(mapState); var layerProps = _objectSpread({ stroked: this.config.visConfig.outline, filled: this.config.visConfig.filled, lineWidthScale: this.config.visConfig.thickness, radiusScale: radiusScale }, this.config.visConfig.fixedRadius ? {} : { radiusMaxPixels: 500 }); var updateTriggers = { getPosition: this.config.columns, getRadius: { sizeField: this.config.sizeField, radiusRange: this.config.visConfig.radiusRange, fixedRadius: this.config.visConfig.fixedRadius, sizeScale: this.config.sizeScale }, getFillColor: { color: this.config.color, colorField: this.config.colorField, colorRange: this.config.visConfig.colorRange, colorScale: this.config.colorScale }, getLineColor: { color: this.config.visConfig.strokeColor, colorField: this.config.strokeColorField, colorRange: this.config.visConfig.strokeColorRange, colorScale: this.config.strokeColorScale }, getFilterValue: gpuFilter.filterValueUpdateTriggers }; var defaultLayerProps = this.getDefaultDeckLayerProps(opts); var brushingProps = this.getBrushingExtensionProps(interactionConfig); var getPixelOffset = (0, _layerTextLabel.getTextOffsetByRadius)(radiusScale, data.getRadius, mapState); var extensions = [].concat((0, _toConsumableArray2["default"])(defaultLayerProps.extensions), [brushingExtension]); var sharedProps = _objectSpread({ getFilterValue: data.getFilterValue, extensions: extensions, filterRange: defaultLayerProps.filterRange }, brushingProps); return [new _layers.ScatterplotLayer(_objectSpread({}, defaultLayerProps, {}, brushingProps, {}, layerProps, {}, data, { parameters: { // circles will be flat on the map when the altitude column is not used depthTest: this.config.columns.altitude.fieldIdx > -1 }, lineWidthUnits: 'pixels', updateTriggers: updateTriggers, extensions: extensions }))].concat((0, _toConsumableArray2["default"])(this.isLayerHovered(objectHovered) ? [new _layers.ScatterplotLayer(_objectSpread({}, this.getDefaultHoverLayerProps(), {}, layerProps, { data: [objectHovered.object], getLineColor: this.config.highlightColor, getFillColor: this.config.highlightColor, getRadius: data.getRadius, getPosition: data.getPosition }))] : []), (0, _toConsumableArray2["default"])(this.renderTextLabelLayer({ getPosition: data.getPosition, sharedProps: sharedProps, getPixelOffset: getPixelOffset, updateTriggers: updateTriggers }, opts))); } }, { key: "type", get: function get() { return 'point'; } }, { key: "isAggregated", get: function get() { return false; } }, { key: "layerIcon", get: function get() { return _pointLayerIcon["default"]; } }, { key: "requiredLayerColumns", get: function get() { return pointRequiredColumns; } }, { key: "optionalColumns", get: function get() { return pointOptionalColumns; } }, { key: "columnPairs", get: function get() { return this.defaultPointColumnPairs; } }, { key: "noneLayerDataAffectingProps", get: function get() { return [].concat((0, _toConsumableArray2["default"])((0, _get2["default"])((0, _getPrototypeOf2["default"])(PointLayer.prototype), "noneLayerDataAffectingProps", this)), ['radius']); } }, { key: "visualChannels", get: function get() { return { color: _objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(PointLayer.prototype), "visualChannels", this).color, { condition: function condition(config) { return config.visConfig.filled; } }), strokeColor: { property: 'strokeColor', field: 'strokeColorField', scale: 'strokeColorScale', domain: 'strokeColorDomain', range: 'strokeColorRange', key: 'strokeColor', channelScaleType: _defaultSettings.CHANNEL_SCALES.color, condition: function condition(config) { return config.visConfig.outline; } }, size: _objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(PointLayer.prototype), "visualChannels", this).size, { range: 'radiusRange', property: 'radius', channelScaleType: 'radius' }) }; } }], [{ key: "findDefaultLayerProps", value: function findDefaultLayerProps(_ref3) { var _ref3$fieldPairs = _ref3.fieldPairs, fieldPairs = _ref3$fieldPairs === void 0 ? [] : _ref3$fieldPairs; var props = []; // Make layer for each pair fieldPairs.forEach(function (pair) { // find fields for tableFieldIndex var latField = pair.pair.lat; var lngField = pair.pair.lng; var layerName = pair.defaultName; var prop = { label: layerName.length ? layerName : 'Point' }; // default layer color for begintrip and dropoff point if (latField.value in _defaultSettings.DEFAULT_LAYER_COLOR) { prop.color = (0, _colorUtils.hexToRgb)(_defaultSettings.DEFAULT_LAYER_COLOR[latField.value]); } // set the first layer to be visible if (props.length === 0) { prop.isVisible = true; } prop.columns = { lat: latField, lng: lngField, altitude: { value: null, fieldIdx: -1, optional: true } }; props.push(prop); }); return { props: props }; } }]); return PointLayer; }(_baseLayer["default"]); exports["default"] = PointLayer; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvcG9pbnQtbGF5ZXIvcG9pbnQtbGF5ZXIuanMiXSwibmFtZXMiOlsicG9pbnRQb3NBY2Nlc3NvciIsImxhdCIsImxuZyIsImFsdGl0dWRlIiwiZCIsImRhdGEiLCJmaWVsZElkeCIsInBvaW50UmVxdWlyZWRDb2x1bW5zIiwicG9pbnRPcHRpb25hbENvbHVtbnMiLCJicnVzaGluZ0V4dGVuc2lvbiIsIkJydXNoaW5nRXh0ZW5zaW9uIiwicG9pbnRWaXNDb25maWdzIiwicmFkaXVzIiwiZml4ZWRSYWRpdXMiLCJvcGFjaXR5Iiwib3V0bGluZSIsInRoaWNrbmVzcyIsInN0cm9rZUNvbG9yIiwiY29sb3JSYW5nZSIsInN0cm9rZUNvbG9yUmFuZ2UiLCJyYWRpdXNSYW5nZSIsImZpbGxlZCIsInR5cGUiLCJsYWJlbCIsImRlZmF1bHRWYWx1ZSIsInByb3BlcnR5IiwiUG9pbnRMYXllciIsInByb3BzIiwicmVnaXN0ZXJWaXNDb25maWciLCJnZXRQb3NpdGlvbkFjY2Vzc29yIiwiY29uZmlnIiwiY29sdW1ucyIsInN0cm9rZUNvbG9yRmllbGQiLCJzdHJva2VDb2xvckRvbWFpbiIsInN0cm9rZUNvbG9yU2NhbGUiLCJnZXRQb3NpdGlvbiIsImFsbERhdGEiLCJmaWx0ZXJlZEluZGV4IiwiaSIsImxlbmd0aCIsImluZGV4IiwicG9zIiwiZXZlcnkiLCJOdW1iZXIiLCJpc0Zpbml0ZSIsInB1c2giLCJwb3NpdGlvbiIsImRhdGFzZXRzIiwib2xkTGF5ZXJEYXRhIiwiY29sb3JTY2FsZSIsImNvbG9yRG9tYWluIiwiY29sb3JGaWVsZCIsImNvbG9yIiwic2l6ZUZpZWxkIiwic2l6ZVNjYWxlIiwic2l6ZURvbWFpbiIsInRleHRMYWJlbCIsInZpc0NvbmZpZyIsImdwdUZpbHRlciIsImRhdGFJZCIsInVwZGF0ZURhdGEiLCJ0cmlnZ2VyQ2hhbmdlZCIsImNTY2FsZSIsImdldFZpc0NoYW5uZWxTY2FsZSIsImNvbG9ycyIsIm1hcCIsImhleFRvUmdiIiwic2NTY2FsZSIsInJTY2FsZSIsImdldFJhZGl1cyIsImdldEVuY29kZWRDaGFubmVsVmFsdWUiLCJnZXRGaWxsQ29sb3IiLCJnZXRMaW5lQ29sb3IiLCJ0ZXh0TGFiZWxzIiwiZ2V0RmlsdGVyVmFsdWUiLCJmaWx0ZXJWYWx1ZUFjY2Vzc29yIiwiYm91bmRzIiwiZ2V0UG9pbnRzQm91bmRzIiwidXBkYXRlTWV0YSIsIm9wdHMiLCJvYmplY3RIb3ZlcmVkIiwibWFwU3RhdGUiLCJpbnRlcmFjdGlvbkNvbmZpZyIsInJhZGl1c1NjYWxlIiwiZ2V0UmFkaXVzU2NhbGVCeVpvb20iLCJsYXllclByb3BzIiwic3Ryb2tlZCIsImxpbmVXaWR0aFNjYWxlIiwicmFkaXVzTWF4UGl4ZWxzIiwidXBkYXRlVHJpZ2dlcnMiLCJmaWx0ZXJWYWx1ZVVwZGF0ZVRyaWdnZXJzIiwiZGVmYXVsdExheWVyUHJvcHMiLCJnZXREZWZhdWx0RGVja0xheWVyUHJvcHMiLCJicnVzaGluZ1Byb3BzIiwiZ2V0QnJ1c2hpbmdFeHRlbnNpb25Qcm9wcyIsImdldFBpeGVsT2Zmc2V0IiwiZXh0ZW5zaW9ucyIsInNoYXJlZFByb3BzIiwiZmlsdGVyUmFuZ2UiLCJTY2F0dGVycGxvdExheWVyIiwicGFyYW1ldGVycyIsImRlcHRoVGVzdCIsImxpbmVXaWR0aFVuaXRzIiwiaXNMYXllckhvdmVyZWQiLCJnZXREZWZhdWx0SG92ZXJMYXllclByb3BzIiwib2JqZWN0IiwiaGlnaGxpZ2h0Q29sb3IiLCJyZW5kZXJUZXh0TGFiZWxMYXllciIsIlBvaW50TGF5ZXJJY29uIiwiZGVmYXVsdFBvaW50Q29sdW1uUGFpcnMiLCJjb25kaXRpb24iLCJmaWVsZCIsInNjYWxlIiwiZG9tYWluIiwicmFuZ2UiLCJrZXkiLCJjaGFubmVsU2NhbGVUeXBlIiwiQ0hBTk5FTF9TQ0FMRVMiLCJzaXplIiwiZmllbGRQYWlycyIsImZvckVhY2giLCJwYWlyIiwibGF0RmllbGQiLCJsbmdGaWVsZCIsImxheWVyTmFtZSIsImRlZmF1bHROYW1lIiwicHJvcCIsInZhbHVlIiwiREVGQVVMVF9MQVlFUl9DT0xPUiIsImlzVmlzaWJsZSIsIm9wdGlvbmFsIiwiTGF5ZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkE7O0FBQ0E7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUE7Ozs7OztBQUVPLElBQU1BLGdCQUFnQixHQUFHLFNBQW5CQSxnQkFBbUI7QUFBQSxNQUFFQyxHQUFGLFFBQUVBLEdBQUY7QUFBQSxNQUFPQyxHQUFQLFFBQU9BLEdBQVA7QUFBQSxNQUFZQyxRQUFaLFFBQVlBLFFBQVo7QUFBQSxTQUEwQixVQUFBQyxDQUFDO0FBQUEsV0FBSSxDQUM3RDtBQUNBQSxJQUFBQSxDQUFDLENBQUNDLElBQUYsQ0FBT0gsR0FBRyxDQUFDSSxRQUFYLENBRjZELEVBRzdEO0FBQ0FGLElBQUFBLENBQUMsQ0FBQ0MsSUFBRixDQUFPSixHQUFHLENBQUNLLFFBQVgsQ0FKNkQsRUFLN0RILFFBQVEsSUFBSUEsUUFBUSxDQUFDRyxRQUFULEdBQW9CLENBQUMsQ0FBakMsR0FBcUNGLENBQUMsQ0FBQ0MsSUFBRixDQUFPRixRQUFRLENBQUNHLFFBQWhCLENBQXJDLEdBQWlFLENBTEosQ0FBSjtBQUFBLEdBQTNCO0FBQUEsQ0FBekI7OztBQVFBLElBQU1DLG9CQUFvQixHQUFHLENBQUMsS0FBRCxFQUFRLEtBQVIsQ0FBN0I7O0FBQ0EsSUFBTUMsb0JBQW9CLEdBQUcsQ0FBQyxVQUFELENBQTdCOztBQUVQLElBQU1DLGlCQUFpQixHQUFHLElBQUlDLDZCQUFKLEVBQTFCO0FBRU8sSUFBTUMsZUFBZSxHQUFHO0FBQzdCQyxFQUFBQSxNQUFNLEVBQUUsUUFEcUI7QUFFN0JDLEVBQUFBLFdBQVcsRUFBRSxhQUZnQjtBQUc3QkMsRUFBQUEsT0FBTyxFQUFFLFNBSG9CO0FBSTdCQyxFQUFBQSxPQUFPLEVBQUUsU0FKb0I7QUFLN0JDLEVBQUFBLFNBQVMsRUFBRSxXQUxrQjtBQU03QkMsRUFBQUEsV0FBVyxFQUFFLGFBTmdCO0FB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cUN3RyxxQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAyMCBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7QnJ1c2hpbmdFeHRlbnNpb259IGZyb20gJ0BkZWNrLmdsL2V4dGVuc2lvbnMnO1xuaW1wb3J0IHtTY2F0dGVycGxvdExheWVyfSBmcm9tICdAZGVjay5nbC9sYXllcnMnO1xuXG5pbXBvcnQgTGF5ZXIgZnJvbSAnLi4vYmFzZS1sYXllcic7XG5pbXBvcnQge2hleFRvUmdifSBmcm9tICd1dGlscy9jb2xvci11dGlscyc7XG5pbXBvcnQgUG9pbnRMYXllckljb24gZnJvbSAnLi9wb2ludC1sYXllci1pY29uJztcbmltcG9ydCB7REVGQVVMVF9MQVlFUl9DT0xPUiwgQ0hBTk5FTF9TQ0FMRVN9IGZyb20gJ2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzJztcblxuaW1wb3J0IHtnZXRUZXh0T2Zmc2V0QnlSYWRpdXMsIGZvcm1hdFRleHRMYWJlbERhdGF9IGZyb20gJy4uL2xheWVyLXRleHQtbGFiZWwnO1xuXG5leHBvcnQgY29uc3QgcG9pbnRQb3NBY2Nlc3NvciA9ICh7bGF0LCBsbmcsIGFsdGl0dWRlfSkgPT4gZCA9PiBbXG4gIC8vIGxuZ1xuICBkLmRhdGFbbG5nLmZpZWxkSWR4XSxcbiAgLy8gbGF0XG4gIGQuZGF0YVtsYXQuZmllbGRJZHhdLFxuICBhbHRpdHVkZSAmJiBhbHRpdHVkZS5maWVsZElkeCA+IC0xID8gZC5kYXRhW2FsdGl0dWRlLmZpZWxkSWR4XSA6IDBcbl07XG5cbmV4cG9ydCBjb25zdCBwb2ludFJlcXVpcmVkQ29sdW1ucyA9IFsnbGF0JywgJ2xuZyddO1xuZXhwb3J0IGNvbnN0IHBvaW50T3B0aW9uYWxDb2x1bW5zID0gWydhbHRpdHVkZSddO1xuXG5jb25zdCBicnVzaGluZ0V4dGVuc2lvbiA9IG5ldyBCcnVzaGluZ0V4dGVuc2lvbigpO1xuXG5leHBvcnQgY29uc3QgcG9pbnRWaXNDb25maWdzID0ge1xuICByYWRpdXM6ICdyYWRpdXMnLFxuICBmaXhlZFJhZGl1czogJ2ZpeGVkUmFkaXVzJyxcbiAgb3BhY2l0eTogJ29wYWNpdHknLFxuICBvdXRsaW5lOiAnb3V0bGluZScsXG4gIHRoaWNrbmVzczogJ3RoaWNrbmVzcycsXG4gIHN0cm9rZUNvbG9yOiAnc3Ryb2tlQ29sb3InLFxuICBjb2xvclJhbmdlOiAnY29sb3JSYW5nZScsXG4gIHN0cm9rZUNvbG9yUmFuZ2U6ICdzdHJva2VDb2xvclJhbmdlJyxcbiAgcmFkaXVzUmFuZ2U6ICdyYWRpdXNSYW5nZScsXG4gIGZpbGxlZDoge1xuICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICBsYWJlbDogJ2xheWVyLmZpbGxDb2xvcicsXG4gICAgZGVmYXVsdFZhbHVlOiB0cnVlLFxuICAgIHByb3BlcnR5OiAnZmlsbGVkJ1xuICB9XG59O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQb2ludExheWVyIGV4dGVuZHMgTGF5ZXIge1xuICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgIHN1cGVyKHByb3BzKTtcblxuICAgIHRoaXMucmVnaXN0ZXJWaXNDb25maWcocG9pbnRWaXNDb25maWdzKTtcbiAgICB0aGlzLmdldFBvc2l0aW9uQWNjZXNzb3IgPSAoKSA9PiBwb2ludFBvc0FjY2Vzc29yKHRoaXMuY29uZmlnLmNvbHVtbnMpO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdwb2ludCc7XG4gIH1cblxuICBnZXQgaXNBZ2dyZWdhdGVkKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGdldCBsYXllckljb24oKSB7XG4gICAgcmV0dXJuIFBvaW50TGF5ZXJJY29uO1xuICB9XG4gIGdldCByZXF1aXJlZExheWVyQ29sdW1ucygpIHtcbiAgICByZXR1cm4gcG9pbnRSZXF1aXJlZENvbHVtbnM7XG4gIH1cblxuICBnZXQgb3B0aW9uYWxDb2x1bW5zKCkge1xuICAgIHJldHVybiBwb2ludE9wdGlvbmFsQ29sdW1ucztcbiAgfVxuXG4gIGdldCBjb2x1bW5QYWlycygpIHtcbiAgICByZXR1cm4gdGhpcy5kZWZhdWx0UG9pbnRDb2x1bW5QYWlycztcbiAgfVxuXG4gIGdldCBub25lTGF5ZXJEYXRhQWZmZWN0aW5nUHJvcHMoKSB7XG4gICAgcmV0dXJuIFsuLi5zdXBlci5ub25lTGF5ZXJEYXRhQWZmZWN0aW5nUHJvcHMsICdyYWRpdXMnXTtcbiAgfVxuXG4gIGdldCB2aXN1YWxDaGFubmVscygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY29sb3I6IHtcbiAgICAgICAgLi4uc3VwZXIudmlzdWFsQ2hhbm5lbHMuY29sb3IsXG4gICAgICAgIGNvbmRpdGlvbjogY29uZmlnID0+IGNvbmZpZy52aXNDb25maWcuZmlsbGVkXG4gICAgICB9LFxuICAgICAgc3Ryb2tlQ29sb3I6IHtcbiAgICAgICAgcHJvcGVydHk6ICdzdHJva2VDb2xvcicsXG4gICAgICAgIGZpZWxkOiAnc3Ryb2tlQ29sb3JGaWVsZCcsXG4gICAgICAgIHNjYWxlOiAnc3Ryb2tlQ29sb3JTY2FsZScsXG4gICAgICAgIGRvbWFpbjogJ3N0cm9rZUNvbG9yRG9tYWluJyxcbiAgICAgICAgcmFuZ2U6ICdzdHJva2VDb2xvclJhbmdlJyxcbiAgICAgICAga2V5OiAnc3Ryb2tlQ29sb3InLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiBDSEFOTkVMX1NDQUxFUy5jb2xvcixcbiAgICAgICAgY29uZGl0aW9uOiBjb25maWcgPT4gY29uZmlnLnZpc0NvbmZpZy5vdXRsaW5lXG4gICAgICB9LFxuICAgICAgc2l6ZToge1xuICAgICAgICAuLi5zdXBlci52aXN1YWxDaGFubmVscy5zaXplLFxuICAgICAgICByYW5nZTogJ3JhZGl1c1JhbmdlJyxcbiAgICAgICAgcHJvcGVydHk6ICdyYWRpdXMnLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiAncmFkaXVzJ1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgZmluZERlZmF1bHRMYXllclByb3BzKHtmaWVsZFBhaXJzID0gW119KSB7XG4gICAgY29uc3QgcHJvcHMgPSBbXTtcblxuICAgIC8vIE1ha2UgbGF5ZXIgZm9yIGVhY2ggcGFpclxuICAgIGZpZWxkUGFpcnMuZm9yRWFjaChwYWlyID0+IHtcbiAgICAgIC8vIGZpbmQgZmllbGRzIGZvciB0YWJsZUZpZWxkSW5kZXhcbiAgICAgIGNvbnN0IGxhdEZpZWxkID0gcGFpci5wYWlyLmxhdDtcbiAgICAgIGNvbnN0IGxuZ0ZpZWxkID0gcGFpci5wYWlyLmxuZztcbiAgICAgIGNvbnN0IGxheWVyTmFtZSA9IHBhaXIuZGVmYXVsdE5hbWU7XG5cbiAgICAgIGNvbnN0IHByb3AgPSB7XG4gICAgICAgIGxhYmVsOiBsYXllck5hbWUubGVuZ3RoID8gbGF5ZXJOYW1lIDogJ1BvaW50J1xuICAgICAgfTtcblxuICAgICAgLy8gZGVmYXVsdCBsYXllciBjb2xvciBmb3IgYmVnaW50cmlwIGFuZCBkcm9wb2ZmIHBvaW50XG4gICAgICBpZiAobGF0RmllbGQudmFsdWUgaW4gREVGQVVMVF9MQVlFUl9DT0xPUikge1xuICAgICAgICBwcm9wLmNvbG9yID0gaGV4VG9SZ2IoREVGQVVMVF9MQVlFUl9DT0xPUltsYXRGaWVsZC52YWx1ZV0pO1xuICAgICAgfVxuXG4gICAgICAvLyBzZXQgdGhlIGZpcnN0IGxheWVyIHRvIGJlIHZpc2libGVcbiAgICAgIGlmIChwcm9wcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcHJvcC5pc1Zpc2libGUgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBwcm9wLmNvbHVtbnMgPSB7XG4gICAgICAgIGxhdDogbGF0RmllbGQsXG4gICAgICAgIGxuZzogbG5nRmllbGQsXG4gICAgICAgIGFsdGl0dWRlOiB7dmFsdWU6IG51bGwsIGZpZWxkSWR4OiAtMSwgb3B0aW9uYWw6IHRydWV9XG4gICAgICB9O1xuXG4gICAgICBwcm9wcy5wdXNoKHByb3ApO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHtwcm9wc307XG4gIH1cblxuICBnZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMgPSB7fSkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdXBlci5nZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMpLFxuXG4gICAgICAvLyBhZGQgc3Ryb2tlIGNvbG9yIHZpc3VhbCBjaGFubmVsXG4gICAgICBzdHJva2VDb2xvckZpZWxkOiBudWxsLFxuICAgICAgc3Ryb2tlQ29sb3JEb21haW46IFswLCAxXSxcbiAgICAgIHN0cm9rZUNvbG9yU2NhbGU6ICdxdWFudGlsZSdcbiAgICB9O1xuICB9XG5cbiAgY2FsY3VsYXRlRGF0YUF0dHJpYnV0ZSh7YWxsRGF0YSwgZmlsdGVyZWRJbmRleH0sIGdldFBvc2l0aW9uKSB7XG4gICAgY29uc3QgZGF0YSA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmaWx0ZXJlZEluZGV4Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBpbmRleCA9IGZpbHRlcmVkSW5kZXhbaV07XG4gICAgICBjb25zdCBwb3MgPSBnZXRQb3NpdGlvbih7ZGF0YTogYWxsRGF0YVtpbmRleF19KTtcblxuICAgICAgLy8gaWYgZG9lc24ndCBoYXZlIHBvaW50IGxhdCBvciBsbmcsIGRvIG5vdCBhZGQgdGhlIHBvaW50XG4gICAgICAvLyBkZWNrLmdsIGNhbid0IGhhbmRsZSBwb3NpdGlvbiA9IG51bGxcbiAgICAgIGlmIChwb3MuZXZlcnkoTnVtYmVyLmlzRmluaXRlKSkge1xuICAgICAgICBkYXRhLnB1c2goe1xuICAgICAgICAgIGRhdGE6IGFsbERhdGFbaW5kZXhdLFxuICAgICAgICAgIHBvc2l0aW9uOiBwb3MsXG4gICAgICAgICAgLy8gaW5kZXggaXMgaW1wb3J0YW50IGZvciBmaWx0ZXJcbiAgICAgICAgICBpbmRleFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICBmb3JtYXRMYXllckRhdGEoZGF0YXNldHMsIG9sZExheWVyRGF0YSkge1xuICAgIGNvbnN0IHtcbiAgICAgIGNvbG9yU2NhbGUsXG4gICAgICBjb2xvckRvbWFpbixcbiAgICAgIGNvbG9yRmllbGQsXG4gICAgICBzdHJva2VDb2xvckZpZWxkLFxuICAgICAgc3Ryb2tlQ29sb3JTY2FsZSxcbiAgICAgIHN0cm9rZUNvbG9yRG9tYWluLFxuICAgICAgY29sb3IsXG4gICAgICBzaXplRmllbGQsXG4gICAgICBzaXplU2NhbGUsXG4gICAgICBzaXplRG9tYWluLFxuICAgICAgdGV4dExhYmVsLFxuICAgICAgdmlzQ29uZmlnOiB7cmFkaXVzUmFuZ2UsIGZpeGVkUmFkaXVzLCBjb2xvclJhbmdlLCBzdHJva2VDb2xvclJhbmdlLCBzdHJva2VDb2xvcn1cbiAgICB9ID0gdGhpcy5jb25maWc7XG5cbiAgICBjb25zdCB7Z3B1RmlsdGVyfSA9IGRhdGFzZXRzW3RoaXMuY29uZmlnLmRhdGFJZF07XG4gICAgY29uc3Qge2RhdGEsIHRyaWdnZXJDaGFuZ2VkfSA9IHRoaXMudXBkYXRlRGF0YShkYXRhc2V0cywgb2xkTGF5ZXJEYXRhKTtcbiAgICBjb25zdCBnZXRQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb25BY2Nlc3NvcigpO1xuICAgIC8vIHBvaW50IGNvbG9yXG5cbiAgICBjb25zdCBjU2NhbGUgPVxuICAgICAgY29sb3JGaWVsZCAmJlxuICAgICAgdGhpcy5nZXRWaXNDaGFubmVsU2NhbGUoY29sb3JTY2FsZSwgY29sb3JEb21haW4sIGNvbG9yUmFuZ2UuY29sb3JzLm1hcChoZXhUb1JnYikpO1xuXG4gICAgLy8gc3Ryb2tlIGNvbG9yXG4gICAgY29uc3Qgc2NTY2FsZSA9XG4gICAgICBzdHJva2VDb2xvckZpZWxkICYmXG4gICAgICB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShcbiAgICAgICAgc3Ryb2tlQ29sb3JTY2FsZSxcbiAgICAgICAgc3Ryb2tlQ29sb3JEb21haW4sXG4gICAgICAgIHN0cm9rZUNvbG9yUmFuZ2UuY29sb3JzLm1hcChoZXhUb1JnYilcbiAgICAgICk7XG5cbiAgICAvLyBwb2ludCByYWRpdXNcbiAgICBjb25zdCByU2NhbGUgPVxuICAgICAgc2l6ZUZpZWxkICYmIHRoaXMuZ2V0VmlzQ2hhbm5lbFNjYWxlKHNpemVTY2FsZSwgc2l6ZURvbWFpbiwgcmFkaXVzUmFuZ2UsIGZpeGVkUmFkaXVzKTtcblxuICAgIGNvbnN0IGdldFJhZGl1cyA9IHJTY2FsZSA/IGQgPT4gdGhpcy5nZXRFbmNvZGVkQ2hhbm5lbFZhbHVlKHJTY2FsZSwgZC5kYXRhLCBzaXplRmllbGQsIDApIDogMTtcblxuICAgIGNvbnN0IGdldEZpbGxDb2xvciA9IGNTY2FsZVxuICAgICAgPyBkID0+IHRoaXMuZ2V0RW5jb2RlZENoYW5uZWxWYWx1ZShjU2NhbGUsIGQuZGF0YSwgY29sb3JGaWVsZClcbiAgICAgIDogY29sb3I7XG5cbiAgICBjb25zdCBnZXRMaW5lQ29sb3IgPSBzY1NjYWxlXG4gICAgICA/IGQgPT4gdGhpcy5nZXRFbmNvZGVkQ2hhbm5lbFZhbHVlKHNjU2NhbGUsIGQuZGF0YSwgc3Ryb2tlQ29sb3JGaWVsZClcbiAgICAgIDogc3Ryb2tlQ29sb3IgfHwgY29sb3I7XG5cbiAgICAvLyBnZXQgYWxsIGRpc3RpbmN0IGNoYXJhY3RlcnMgaW4gdGhlIHRleHQgbGFiZWxzXG4gICAgY29uc3QgdGV4dExhYmVscyA9IGZvcm1hdFRleHRMYWJlbERhdGEoe1xuICAgICAgdGV4dExhYmVsLFxuICAgICAgdHJpZ2dlckNoYW5nZWQsXG4gICAgICBvbGRMYXllckRhdGEsXG4gICAgICBkYXRhXG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0YSxcbiAgICAgIGdldFBvc2l0aW9uLFxuICAgICAgZ2V0RmlsbENvbG9yLFxuICAgICAgZ2V0TGluZUNvbG9yLFxuICAgICAgZ2V0RmlsdGVyVmFsdWU6IGdwdUZpbHRlci5maWx0ZXJWYWx1ZUFjY2Vzc29yKCksXG4gICAgICBnZXRSYWRpdXMsXG4gICAgICB0ZXh0TGFiZWxzXG4gICAgfTtcbiAgfVxuICAvKiBlc2xpbnQtZW5hYmxlIGNvbXBsZXhpdHkgKi9cblxuICB1cGRhdGVMYXllck1ldGEoYWxsRGF0YSkge1xuICAgIGNvbnN0IGdldFBvc2l0aW9uID0gdGhpcy5nZXRQb3NpdGlvbkFjY2Vzc29yKCk7XG4gICAgY29uc3QgYm91bmRzID0gdGhpcy5nZXRQb2ludHNCb3VuZHMoYWxsRGF0YSwgZCA9PiBnZXRQb3NpdGlvbih7ZGF0YTogZH0pKTtcbiAgICB0aGlzLnVwZGF0ZU1ldGEoe2JvdW5kc30pO1xuICB9XG5cbiAgcmVuZGVyTGF5ZXIob3B0cykge1xuICAgIGNvbnN0IHtkYXRhLCBncHVGaWx0ZXIsIG9iamVjdEhvdmVyZWQsIG1hcFN0YXRlLCBpbnRlcmFjdGlvbkNvbmZpZ30gPSBvcHRzO1xuXG4gICAgY29uc3QgcmFkaXVzU2NhbGUgPSB0aGlzLmdldFJhZGl1c1NjYWxlQnlab29tKG1hcFN0YXRlKTtcblxuICAgIGNvbnN0IGxheWVyUHJvcHMgPSB7XG4gICAgICBzdHJva2VkOiB0aGlzLmNvbmZpZy52aXNDb25maWcub3V0bGluZSxcbiAgICAgIGZpbGxlZDogdGhpcy5jb25maWcudmlzQ29uZmlnLmZpbGxlZCxcbiAgICAgIGxpbmVXaWR0aFNjYWxlOiB0aGlzLmNvbmZpZy52aXNDb25maWcudGhpY2tuZXNzLFxuICAgICAgcmFkaXVzU2NhbGUsXG4gICAgICAuLi4odGhpcy5jb25maWcudmlzQ29uZmlnLmZpeGVkUmFkaXVzID8ge30gOiB7cmFkaXVzTWF4UGl4ZWxzOiA1MDB9KVxuICAgIH07XG5cbiAgICBjb25zdCB1cGRhdGVUcmlnZ2VycyA9IHtcbiAgICAgIGdldFBvc2l0aW9uOiB0aGlzLmNvbmZpZy5jb2x1bW5zLFxuICAgICAgZ2V0UmFkaXVzOiB7XG4gICAgICAgIHNpemVGaWVsZDogdGhpcy5jb25maWcuc2l6ZUZpZWxkLFxuICAgICAgICByYWRpdXNSYW5nZTogdGhpcy5jb25maWcudmlzQ29uZmlnLnJhZGl1c1JhbmdlLFxuICAgICAgICBmaXhlZFJhZGl1czogdGhpcy5jb25maWcudmlzQ29uZmlnLmZpeGVkUmFkaXVzLFxuICAgICAgICBzaXplU2NhbGU6IHRoaXMuY29uZmlnLnNpemVTY2FsZVxuICAgICAgfSxcbiAgICAgIGdldEZpbGxDb2xvcjoge1xuICAgICAgICBjb2xvcjogdGhpcy5jb25maWcuY29sb3IsXG4gICAgICAgIGNvbG9yRmllbGQ6IHRoaXMuY29uZmlnLmNvbG9yRmllbGQsXG4gICAgICAgIGNvbG9yUmFuZ2U6IHRoaXMuY29uZmlnLnZpc0NvbmZpZy5jb2xvclJhbmdlLFxuICAgICAgICBjb2xvclNjYWxlOiB0aGlzLmNvbmZpZy5jb2xvclNjYWxlXG4gICAgICB9LFxuICAgICAgZ2V0TGluZUNvbG9yOiB7XG4gICAgICAgIGNvbG9yOiB0aGlzLmNvbmZpZy52aXNDb25maWcuc3Ryb2tlQ29sb3IsXG4gICAgICAgIGNvbG9yRmllbGQ6IHRoaXMuY29uZmlnLnN0cm9rZUNvbG9yRmllbGQsXG4gICAgICAgIGNvbG9yUmFuZ2U6IHRoaXMuY29uZmlnLnZpc0NvbmZpZy5zdHJva2VDb2xvclJhbmdlLFxuICAgICAgICBjb2xvclNjYWxlOiB0aGlzLmNvbmZpZy5zdHJva2VDb2xvclNjYWxlXG4gICAgICB9LFxuICAgICAgZ2V0RmlsdGVyVmFsdWU6IGdwdUZpbHRlci5maWx0ZXJWYWx1ZVVwZGF0ZVRyaWdnZXJzXG4gICAgfTtcblxuICAgIGNvbnN0IGRlZmF1bHRMYXllclByb3BzID0gdGhpcy5nZXREZWZhdWx0RGVja0xheWVyUHJvcHMob3B0cyk7XG4gICAgY29uc3QgYnJ1c2hpbmdQcm9wcyA9IHRoaXMuZ2V0QnJ1c2hpbmdFeHRlbnNpb25Qcm9wcyhpbnRlcmFjdGlvbkNvbmZpZyk7XG4gICAgY29uc3QgZ2V0UGl4ZWxPZmZzZXQgPSBnZXRUZXh0T2Zmc2V0QnlSYWRpdXMocmFkaXVzU2NhbGUsIGRhdGEuZ2V0UmFkaXVzLCBtYXBTdGF0ZSk7XG4gICAgY29uc3QgZXh0ZW5zaW9ucyA9IFsuLi5kZWZhdWx0TGF5ZXJQcm9wcy5leHRlbnNpb25zLCBicnVzaGluZ0V4dGVuc2lvbl07XG5cbiAgICBjb25zdCBzaGFyZWRQcm9wcyA9IHtcbiAgICAgIGdldEZpbHRlclZhbHVlOiBkYXRhLmdldEZpbHRlclZhbHVlLFxuICAgICAgZXh0ZW5zaW9ucyxcbiAgICAgIGZpbHRlclJhbmdlOiBkZWZhdWx0TGF5ZXJQcm9wcy5maWx0ZXJSYW5nZSxcbiAgICAgIC4uLmJydXNoaW5nUHJvcHNcbiAgICB9O1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIG5ldyBTY2F0dGVycGxvdExheWVyKHtcbiAgICAgICAgLi4uZGVmYXVsdExheWVyUHJvcHMsXG4gICAgICAgIC4uLmJydXNoaW5nUHJvcHMsXG4gICAgICAgIC4uLmxheWVyUHJvcHMsXG4gICAgICAgIC4uLmRhdGEsXG4gICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAvLyBjaXJjbGVzIHdpbGwgYmUgZmxhdCBvbiB0aGUgbWFwIHdoZW4gdGhlIGFsdGl0dWRlIGNvbHVtbiBpcyBub3QgdXNlZFxuICAgICAgICAgIGRlcHRoVGVzdDogdGhpcy5jb25maWcuY29sdW1ucy5hbHRpdHVkZS5maWVsZElkeCA+IC0xXG4gICAgICAgIH0sXG4gICAgICAgIGxpbmVXaWR0aFVuaXRzOiAncGl4ZWxzJyxcbiAgICAgICAgdXBkYXRlVHJpZ2dlcnMsXG4gICAgICAgIGV4dGVuc2lvbnNcbiAgICAgIH0pLFxuICAgICAgLy8gaG92ZXIgbGF5ZXJcbiAgICAgIC4uLih0aGlzLmlzTGF5ZXJIb3ZlcmVkKG9iamVjdEhvdmVyZWQpXG4gICAgICAgID8gW1xuICAgICAgICAgICAgbmV3IFNjYXR0ZXJwbG90TGF5ZXIoe1xuICAgICAgICAgICAgICAuLi50aGlzLmdldERlZmF1bHRIb3ZlckxheWVyUHJvcHMoKSxcbiAgICAgICAgICAgICAgLi4ubGF5ZXJQcm9wcyxcbiAgICAgICAgICAgICAgZGF0YTogW29iamVjdEhvdmVyZWQub2JqZWN0XSxcbiAgICAgICAgICAgICAgZ2V0TGluZUNvbG9yOiB0aGlzLmNvbmZpZy5oaWdobGlnaHRDb2xvcixcbiAgICAgICAgICAgICAgZ2V0RmlsbENvbG9yOiB0aGlzLmNvbmZpZy5oaWdobGlnaHRDb2xvcixcbiAgICAgICAgICAgICAgZ2V0UmFkaXVzOiBkYXRhLmdldFJhZGl1cyxcbiAgICAgICAgICAgICAgZ2V0UG9zaXRpb246IGRhdGEuZ2V0UG9zaXRpb25cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgXVxuICAgICAgICA6IFtdKSxcbiAgICAgIC8vIHRleHQgbGFiZWwgbGF5ZXJcbiAgICAgIC4uLnRoaXMucmVuZGVyVGV4dExhYmVsTGF5ZXIoXG4gICAgICAgIHtcbiAgICAgICAgICBnZXRQb3NpdGlvbjogZGF0YS5nZXRQb3NpdGlvbixcbiAgICAgICAgICBzaGFyZWRQcm9wcyxcbiAgICAgICAgICBnZXRQaXhlbE9mZnNldCxcbiAgICAgICAgICB1cGRhdGVUcmlnZ2Vyc1xuICAgICAgICB9LFxuICAgICAgICBvcHRzXG4gICAgICApXG4gICAgXTtcbiAgfVxufVxuIl19