UNPKG

kepler.gl.geoiq

Version:

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

485 lines (420 loc) 58.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.pointVisConfigs = exports.pointRequiredColumns = exports.pointPosResolver = exports.pointPosAccessor = exports.pointOptionalColumns = exports.pointLabelResolver = exports.pointLabelAccessor = exports["default"] = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); 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 _lodash = _interopRequireDefault(require("lodash.memoize")); var _lodash2 = _interopRequireDefault(require("lodash.uniq")); var _deck = require("deck.gl"); var _baseLayer = _interopRequireDefault(require("../base-layer")); var _scatterplotBrushingLayer = _interopRequireDefault(require("../../deckgl-layers/scatterplot-brushing-layer/scatterplot-brushing-layer")); var _colorUtils = require("../../utils/color-utils"); var _pointLayerIcon = _interopRequireDefault(require("./point-layer-icon")); var _defaultSettings = require("../../constants/default-settings"); var _viewportMercatorProject = require("viewport-mercator-project"); var _dataUtils = require("../../utils/data-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 pointPosAccessor = exports.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]; }; }; var pointPosResolver = exports.pointPosResolver = function pointPosResolver(_ref2) { var lat = _ref2.lat, lng = _ref2.lng, altitude = _ref2.altitude; return "".concat(lat.fieldIdx, "-").concat(lng.fieldIdx, "-").concat(altitude ? altitude.fieldIdx : 'z'); }; var pointLabelAccessor = exports.pointLabelAccessor = function pointLabelAccessor(textLabel) { return function (d) { var val = d.data[textLabel.field.tableFieldIndex - 1]; return (0, _dataUtils.notNullorUndefined)(val) ? String(val) : ''; }; }; var pointLabelResolver = exports.pointLabelResolver = function pointLabelResolver(textLabel) { return textLabel.field && textLabel.field.tableFieldIndex; }; var pointRequiredColumns = exports.pointRequiredColumns = ['lat', 'lng']; var pointOptionalColumns = exports.pointOptionalColumns = ['altitude']; var pointVisConfigs = exports.pointVisConfigs = { radius: 'radius', fixedRadius: 'fixedRadius', opacity: 'opacity', outline: 'outline', thickness: 'thickness', strokeColor: 'strokeColor', colorRange: 'colorRange', strokeColorRange: 'strokeColorRange', radiusRange: 'radiusRange', filled: { type: 'boolean', label: 'Fill Color', defaultValue: true, property: 'filled' } }; var PointLayer = exports["default"] = /*#__PURE__*/function (_Layer) { (0, _inherits2["default"])(PointLayer, _Layer); var _super = _createSuper(PointLayer); function PointLayer(props) { var _this; (0, _classCallCheck2["default"])(this, PointLayer); _this = _super.call(this, props); _this.registerVisConfig(pointVisConfigs); _this.getPosition = (0, _lodash["default"])(pointPosAccessor, pointPosResolver); _this.getText = [(0, _lodash["default"])(pointLabelAccessor, pointLabelResolver)]; return _this; } (0, _createClass2["default"])(PointLayer, [{ key: "type", get: function get() { return 'point'; } }, { 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(_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(_objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(PointLayer.prototype), "visualChannels", this).size), {}, { range: 'radiusRange', property: 'radius', channelScaleType: 'radius' }) }; } }, { key: "getPositionAccessor", value: function getPositionAccessor() { return this.getPosition(this.config.columns); } }, { key: "getDefaultLayerConfig", value: function getDefaultLayerConfig() { var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return _objectSpread(_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' }); } // TODO: fix complexity /* eslint-disable complexity */ }, { key: "formatLayerData", value: function formatLayerData(_, allData, filteredIndex, oldLayerData) { var _this2 = this; var opt = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; 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; // fill 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 getPosition = this.getPositionAccessor(); if (!oldLayerData || oldLayerData.getPosition !== getPosition) { this.updateLayerMeta(allData, getPosition); } var data; if (oldLayerData && oldLayerData.data && opt.sameData && oldLayerData.getPosition === getPosition) { data = oldLayerData.data; } else { data = filteredIndex.reduce(function (accu, index) { 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)) { return accu; } accu.push({ data: allData[index] }); return accu; }, []); } // get all distinct characters in the text labels 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; // TODO: this should be cleaned up in the gpu-data-filter branch var textLabels = textLabel.map(function (tl, i) { if (!tl.field) { // if no field selected, return { getText: null, characterSet: [] }; } if (!_this2.getText[i]) { _this2.getText[i] = (0, _lodash["default"])(pointLabelAccessor, pointLabelResolver); } var getText = _this2.getText[i](tl); var characterSet; if (oldLayerData && Array.isArray(oldLayerData.textLabels) && oldLayerData.textLabels[i] && opt.sameData && oldLayerData.textLabels[i].getText === getText) { characterSet = oldLayerData.textLabels[i].characterSet; } else { var allLabels = tl.field ? data.map(getText) : []; characterSet = (0, _lodash2["default"])(allLabels.join('')); } return { characterSet: characterSet, getText: getText }; }); return { data: data, getPosition: getPosition, getFillColor: getFillColor, getLineColor: getLineColor, 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: "getTextOffset", value: function getTextOffset(config, radiusScale, getRadius, mapState) { var distanceScale = (0, _viewportMercatorProject.getDistanceScales)(mapState); var xMult = config.anchor === 'middle' ? 0 : config.anchor === 'start' ? 1 : -1; var yMult = config.alignment === 'center' ? 0 : config.alignment === 'bottom' ? 1 : -1; var sizeOffset = config.alignment === 'center' ? 0 : config.alignment === 'bottom' ? config.size : config.size; var pixelRadius = radiusScale * distanceScale.pixelsPerMeter[0]; var padding = 20; return typeof getRadius === 'function' ? function (d) { return [xMult * (getRadius(d) * pixelRadius + padding), yMult * (getRadius(d) * pixelRadius + padding + sizeOffset)]; } : [xMult * (getRadius * pixelRadius + padding), yMult * (getRadius * pixelRadius + padding + sizeOffset)]; } }, { key: "renderLayer", value: function renderLayer(_ref3) { var _this3 = this; var data = _ref3.data, idx = _ref3.idx, layerInteraction = _ref3.layerInteraction, objectHovered = _ref3.objectHovered, mapState = _ref3.mapState, interactionConfig = _ref3.interactionConfig; var enableBrushing = interactionConfig.brush.enabled; var radiusScale = this.getRadiusScaleByZoom(mapState); var layerProps = _objectSpread({ // TODO: support setting stroke and fill simultaneously stroked: this.config.visConfig.outline, filled: this.config.visConfig.filled, radiusMinPixels: 0, lineWidthMinPixels: this.config.visConfig.thickness, radiusScale: radiusScale }, this.config.visConfig.fixedRadius ? {} : { radiusMaxPixels: 500 }); var interaction = { autoHighlight: !enableBrushing, enableBrushing: enableBrushing, brushRadius: interactionConfig.brush.config.size * 1000, highlightColor: this.config.highlightColor }; var textLabel = this.config.textLabel; var updateTriggers = { getPosition: { columns: 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 } }; return [new _scatterplotBrushingLayer["default"](_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, layerProps), layerInteraction), data), interaction), {}, { idx: idx, id: this.id, opacity: this.config.visConfig.opacity, pickable: true, parameters: { // circles will be flat on the map when the altitude column is not used depthTest: this.config.columns.altitude.fieldIdx > -1 }, updateTriggers: updateTriggers }))].concat((0, _toConsumableArray2["default"])(this.isLayerHovered(objectHovered) ? [new _scatterplotBrushingLayer["default"](_objectSpread(_objectSpread({}, layerProps), {}, { id: "".concat(this.id, "-hovered"), data: [objectHovered.object], getLineColor: this.config.highlightColor, getFillColor: this.config.highlightColor, getRadius: data.getRadius, getPosition: data.getPosition, pickable: false }))] : []), (0, _toConsumableArray2["default"])(data.textLabels.reduce(function (accu, d, i) { if (d.getText) { accu.push(new _deck.TextLayer(_objectSpread(_objectSpread({}, layerInteraction), {}, { id: "".concat(_this3.id, "-label-").concat(textLabel[i].field.name), data: data.data, getPosition: data.getPosition, getText: d.getText, characterSet: d.characterSet, getPixelOffset: _this3.getTextOffset(textLabel[i], radiusScale, data.getRadius, mapState), getSize: 1, sizeScale: textLabel[i].size, getTextAnchor: textLabel[i].anchor, getAlignmentBaseline: textLabel[i].alignment, getColor: textLabel[i].color, parameters: { // text will always show on top of all layers depthTest: false }, updateTriggers: { getPosition: _this3.config.columns, getText: textLabel[i].field.name, getPixelOffset: _objectSpread(_objectSpread({}, updateTriggers.getRadius), {}, { mapState: mapState, anchor: textLabel[i].anchor, alignment: textLabel[i].alignment }), getTextAnchor: textLabel[i].anchor, getAlignmentBaseline: textLabel[i].alignment, getColor: textLabel[i].color } }))); } return accu; }, []))); } }], [{ key: "findDefaultLayerProps", value: function findDefaultLayerProps(_ref4) { var _ref4$fieldPairs = _ref4.fieldPairs, fieldPairs = _ref4$fieldPairs === void 0 ? [] : _ref4$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"]); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvcG9pbnQtbGF5ZXIvcG9pbnQtbGF5ZXIuanMiXSwibmFtZXMiOlsicG9pbnRQb3NBY2Nlc3NvciIsImxhdCIsImxuZyIsImFsdGl0dWRlIiwiZCIsImRhdGEiLCJmaWVsZElkeCIsInBvaW50UG9zUmVzb2x2ZXIiLCJwb2ludExhYmVsQWNjZXNzb3IiLCJ0ZXh0TGFiZWwiLCJ2YWwiLCJmaWVsZCIsInRhYmxlRmllbGRJbmRleCIsIlN0cmluZyIsInBvaW50TGFiZWxSZXNvbHZlciIsInBvaW50UmVxdWlyZWRDb2x1bW5zIiwicG9pbnRPcHRpb25hbENvbHVtbnMiLCJwb2ludFZpc0NvbmZpZ3MiLCJyYWRpdXMiLCJmaXhlZFJhZGl1cyIsIm9wYWNpdHkiLCJvdXRsaW5lIiwidGhpY2tuZXNzIiwic3Ryb2tlQ29sb3IiLCJjb2xvclJhbmdlIiwic3Ryb2tlQ29sb3JSYW5nZSIsInJhZGl1c1JhbmdlIiwiZmlsbGVkIiwidHlwZSIsImxhYmVsIiwiZGVmYXVsdFZhbHVlIiwicHJvcGVydHkiLCJQb2ludExheWVyIiwicHJvcHMiLCJyZWdpc3RlclZpc0NvbmZpZyIsImdldFBvc2l0aW9uIiwiZ2V0VGV4dCIsIlBvaW50TGF5ZXJJY29uIiwiZGVmYXVsdFBvaW50Q29sdW1uUGFpcnMiLCJjb2xvciIsImNvbmRpdGlvbiIsImNvbmZpZyIsInZpc0NvbmZpZyIsInNjYWxlIiwiZG9tYWluIiwicmFuZ2UiLCJrZXkiLCJjaGFubmVsU2NhbGVUeXBlIiwiQ0hBTk5FTF9TQ0FMRVMiLCJzaXplIiwiY29sdW1ucyIsInN0cm9rZUNvbG9yRmllbGQiLCJzdHJva2VDb2xvckRvbWFpbiIsInN0cm9rZUNvbG9yU2NhbGUiLCJfIiwiYWxsRGF0YSIsImZpbHRlcmVkSW5kZXgiLCJvbGRMYXllckRhdGEiLCJvcHQiLCJjb2xvclNjYWxlIiwiY29sb3JEb21haW4iLCJjb2xvckZpZWxkIiwic2l6ZUZpZWxkIiwic2l6ZVNjYWxlIiwic2l6ZURvbWFpbiIsImNTY2FsZSIsImdldFZpc0NoYW5uZWxTY2FsZSIsImNvbG9ycyIsIm1hcCIsImhleFRvUmdiIiwic2NTY2FsZSIsInJTY2FsZSIsImdldFBvc2l0aW9uQWNjZXNzb3IiLCJ1cGRhdGVMYXllck1ldGEiLCJzYW1lRGF0YSIsInJlZHVjZSIsImFjY3UiLCJpbmRleCIsInBvcyIsImV2ZXJ5IiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJwdXNoIiwiZ2V0UmFkaXVzIiwiZ2V0RW5jb2RlZENoYW5uZWxWYWx1ZSIsImdldEZpbGxDb2xvciIsImdldExpbmVDb2xvciIsInRleHRMYWJlbHMiLCJ0bCIsImkiLCJjaGFyYWN0ZXJTZXQiLCJBcnJheSIsImlzQXJyYXkiLCJhbGxMYWJlbHMiLCJqb2luIiwiYm91bmRzIiwiZ2V0UG9pbnRzQm91bmRzIiwidXBkYXRlTWV0YSIsInJhZGl1c1NjYWxlIiwibWFwU3RhdGUiLCJkaXN0YW5jZVNjYWxlIiwieE11bHQiLCJhbmNob3IiLCJ5TXVsdCIsImFsaWdubWVudCIsInNpemVPZmZzZXQiLCJwaXhlbFJhZGl1cyIsInBpeGVsc1Blck1ldGVyIiwicGFkZGluZyIsImlkeCIsImxheWVySW50ZXJhY3Rpb24iLCJvYmplY3RIb3ZlcmVkIiwiaW50ZXJhY3Rpb25Db25maWciLCJlbmFibGVCcnVzaGluZyIsImJydXNoIiwiZW5hYmxlZCIsImdldFJhZGl1c1NjYWxlQnlab29tIiwibGF5ZXJQcm9wcyIsInN0cm9rZWQiLCJyYWRpdXNNaW5QaXhlbHMiLCJsaW5lV2lkdGhNaW5QaXhlbHMiLCJyYWRpdXNNYXhQaXhlbHMiLCJpbnRlcmFjdGlvbiIsImF1dG9IaWdobGlnaHQiLCJicnVzaFJhZGl1cyIsImhpZ2hsaWdodENvbG9yIiwidXBkYXRlVHJpZ2dlcnMiLCJTY2F0dGVycGxvdEJydXNoaW5nTGF5ZXIiLCJpZCIsInBpY2thYmxlIiwicGFyYW1ldGVycyIsImRlcHRoVGVzdCIsImlzTGF5ZXJIb3ZlcmVkIiwib2JqZWN0IiwiVGV4dExheWVyIiwibmFtZSIsImdldFBpeGVsT2Zmc2V0IiwiZ2V0VGV4dE9mZnNldCIsImdldFNpemUiLCJnZXRUZXh0QW5jaG9yIiwiZ2V0QWxpZ25tZW50QmFzZWxpbmUiLCJnZXRDb2xvciIsImZpZWxkUGFpcnMiLCJmb3JFYWNoIiwicGFpciIsImxhdEZpZWxkIiwibG5nRmllbGQiLCJsYXllck5hbWUiLCJkZWZhdWx0TmFtZSIsInByb3AiLCJsZW5ndGgiLCJ2YWx1ZSIsIkRFRkFVTFRfTEFZRVJfQ09MT1IiLCJpc1Zpc2libGUiLCJvcHRpb25hbCIsIkxheWVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOztBQUNBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7Ozs7O0FBRU8sSUFBTUEsZ0JBQWdCLDhCQUFHLFNBQW5CQSxnQkFBbUI7QUFBQSxNQUFFQyxHQUFGLFFBQUVBLEdBQUY7QUFBQSxNQUFPQyxHQUFQLFFBQU9BLEdBQVA7QUFBQSxNQUFZQyxRQUFaLFFBQVlBLFFBQVo7QUFBQSxTQUEwQixVQUFBQyxDQUFDO0FBQUEsV0FBSSxDQUM3RDtBQUNBQSxJQUFBQSxDQUFDLENBQUNDLElBQUYsQ0FBT0gsR0FBRyxDQUFDSSxRQUFYLENBRjZELEVBRzdEO0FBQ0FGLElBQUFBLENBQUMsQ0FBQ0MsSUFBRixDQUFPSixHQUFHLENBQUNLLFFBQVgsQ0FKNkQsRUFLN0RILFFBQVEsSUFBSUEsUUFBUSxDQUFDRyxRQUFULEdBQW9CLENBQUMsQ0FBakMsR0FBcUNGLENBQUMsQ0FBQ0MsSUFBRixDQUFPRixRQUFRLENBQUNHLFFBQWhCLENBQXJDLEdBQWlFLENBTEosQ0FBSjtBQUFBLEdBQTNCO0FBQUEsQ0FBekI7O0FBUUEsSUFBTUMsZ0JBQWdCLDhCQUFHLFNBQW5CQSxnQkFBbUI7QUFBQSxNQUFFTixHQUFGLFNBQUVBLEdBQUY7QUFBQSxNQUFPQyxHQUFQLFNBQU9BLEdBQVA7QUFBQSxNQUFZQyxRQUFaLFNBQVlBLFFBQVo7QUFBQSxt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ZTtBQUNiakQsVUFBQUEsR0FBRyxFQUFFZ0osUUFEUTtBQUViL0ksVUFBQUEsR0FBRyxFQUFFZ0osUUFGUTtBQUdiL0ksVUFBQUEsUUFBUSxFQUFFO0FBQUNvSixZQUFBQSxLQUFLLEVBQUUsSUFBUjtBQUFjakosWUFBQUEsUUFBUSxFQUFFLENBQUMsQ0FBekI7QUFBNEJvSixZQUFBQSxRQUFRLEVBQUU7QUFBdEM7QUFIRyxTQUFmO0FBTUF6SCxRQUFBQSxLQUFLLENBQUNpRCxJQUFOLENBQVdtRSxJQUFYO0FBQ0QsT0EzQkQ7QUE2QkEsYUFBTztBQUFDcEgsUUFBQUEsS0FBSyxFQUFMQTtBQUFELE9BQVA7QUFDRDs7O0VBL0ZxQzBILHFCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDIzIFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IG1lbW9pemUgZnJvbSAnbG9kYXNoLm1lbW9pemUnO1xuaW1wb3J0IHVuaXEgZnJvbSAnbG9kYXNoLnVuaXEnO1xuaW1wb3J0IHtUZXh0TGF5ZXJ9IGZyb20gJ2RlY2suZ2wnO1xuXG5pbXBvcnQgTGF5ZXIgZnJvbSAnLi4vYmFzZS1sYXllcic7XG5pbXBvcnQgU2NhdHRlcnBsb3RCcnVzaGluZ0xheWVyIGZyb20gJ2RlY2tnbC1sYXllcnMvc2NhdHRlcnBsb3QtYnJ1c2hpbmctbGF5ZXIvc2NhdHRlcnBsb3QtYnJ1c2hpbmctbGF5ZXInO1xuaW1wb3J0IHtoZXhUb1JnYn0gZnJvbSAndXRpbHMvY29sb3ItdXRpbHMnO1xuaW1wb3J0IFBvaW50TGF5ZXJJY29uIGZyb20gJy4vcG9pbnQtbGF5ZXItaWNvbic7XG5pbXBvcnQge0RFRkFVTFRfTEFZRVJfQ09MT1IsIENIQU5ORUxfU0NBTEVTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5pbXBvcnQge2dldERpc3RhbmNlU2NhbGVzfSBmcm9tICd2aWV3cG9ydC1tZXJjYXRvci1wcm9qZWN0JztcbmltcG9ydCB7bm90TnVsbG9yVW5kZWZpbmVkfSBmcm9tICd1dGlscy9kYXRhLXV0aWxzJztcblxuZXhwb3J0IGNvbnN0IHBvaW50UG9zQWNjZXNzb3IgPSAoe2xhdCwgbG5nLCBhbHRpdHVkZX0pID0+IGQgPT4gW1xuICAvLyBsbmdcbiAgZC5kYXRhW2xuZy5maWVsZElkeF0sXG4gIC8vIGxhdFxuICBkLmRhdGFbbGF0LmZpZWxkSWR4XSxcbiAgYWx0aXR1ZGUgJiYgYWx0aXR1ZGUuZmllbGRJZHggPiAtMSA/IGQuZGF0YVthbHRpdHVkZS5maWVsZElkeF0gOiAwXG5dO1xuXG5leHBvcnQgY29uc3QgcG9pbnRQb3NSZXNvbHZlciA9ICh7bGF0LCBsbmcsIGFsdGl0dWRlfSkgPT5cbiAgYCR7bGF0LmZpZWxkSWR4fS0ke2xuZy5maWVsZElkeH0tJHthbHRpdHVkZSA/IGFsdGl0dWRlLmZpZWxkSWR4IDogJ3onfWA7XG5cbmV4cG9ydCBjb25zdCBwb2ludExhYmVsQWNjZXNzb3IgPSB0ZXh0TGFiZWwgPT4gZCA9PiB7XG4gIGNvbnN0IHZhbCA9IGQuZGF0YVt0ZXh0TGFiZWwuZmllbGQudGFibGVGaWVsZEluZGV4IC0gMV07XG4gIHJldHVybiBub3ROdWxsb3JVbmRlZmluZWQodmFsKSA/IFN0cmluZyh2YWwpIDogJyc7XG59O1xuXG5leHBvcnQgY29uc3QgcG9pbnRMYWJlbFJlc29sdmVyID0gdGV4dExhYmVsID0+XG4gIHRleHRMYWJlbC5maWVsZCAmJiB0ZXh0TGFiZWwuZmllbGQudGFibGVGaWVsZEluZGV4O1xuXG5leHBvcnQgY29uc3QgcG9pbnRSZXF1aXJlZENvbHVtbnMgPSBbJ2xhdCcsICdsbmcnXTtcbmV4cG9ydCBjb25zdCBwb2ludE9wdGlvbmFsQ29sdW1ucyA9IFsnYWx0aXR1ZGUnXTtcblxuZXhwb3J0IGNvbnN0IHBvaW50VmlzQ29uZmlncyA9IHtcbiAgcmFkaXVzOiAncmFkaXVzJyxcbiAgZml4ZWRSYWRpdXM6ICdmaXhlZFJhZGl1cycsXG4gIG9wYWNpdHk6ICdvcGFjaXR5JyxcbiAgb3V0bGluZTogJ291dGxpbmUnLFxuICB0aGlja25lc3M6ICd0aGlja25lc3MnLFxuICBzdHJva2VDb2xvcjogJ3N0cm9rZUNvbG9yJyxcbiAgY29sb3JSYW5nZTogJ2NvbG9yUmFuZ2UnLFxuICBzdHJva2VDb2xvclJhbmdlOiAnc3Ryb2tlQ29sb3JSYW5nZScsXG4gIHJhZGl1c1JhbmdlOiAncmFkaXVzUmFuZ2UnLFxuICBmaWxsZWQ6IHtcbiAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgbGFiZWw6ICdGaWxsIENvbG9yJyxcbiAgICBkZWZhdWx0VmFsdWU6IHRydWUsXG4gICAgcHJvcGVydHk6ICdmaWxsZWQnXG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBvaW50TGF5ZXIgZXh0ZW5kcyBMYXllciB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpO1xuXG4gICAgdGhpcy5yZWdpc3RlclZpc0NvbmZpZyhwb2ludFZpc0NvbmZpZ3MpO1xuICAgIHRoaXMuZ2V0UG9zaXRpb24gPSBtZW1vaXplKHBvaW50UG9zQWNjZXNzb3IsIHBvaW50UG9zUmVzb2x2ZXIpO1xuICAgIHRoaXMuZ2V0VGV4dCA9IFttZW1vaXplKHBvaW50TGFiZWxBY2Nlc3NvciwgcG9pbnRMYWJlbFJlc29sdmVyKV07XG4gIH1cblxuICBnZXQgdHlwZSgpIHtcbiAgICByZXR1cm4gJ3BvaW50JztcbiAgfVxuXG4gIGdldCBsYXllckljb24oKSB7XG4gICAgcmV0dXJuIFBvaW50TGF5ZXJJY29uO1xuICB9XG4gIGdldCByZXF1aXJlZExheWVyQ29sdW1ucygpIHtcbiAgICByZXR1cm4gcG9pbnRSZXF1aXJlZENvbHVtbnM7XG4gIH1cblxuICBnZXQgb3B0aW9uYWxDb2x1bW5zKCkge1xuICAgIHJldHVybiBwb2ludE9wdGlvbmFsQ29sdW1ucztcbiAgfVxuXG4gIGdldCBjb2x1bW5QYWlycygpIHtcbiAgICByZXR1cm4gdGhpcy5kZWZhdWx0UG9pbnRDb2x1bW5QYWlycztcbiAgfVxuXG4gIGdldCBub25lTGF5ZXJEYXRhQWZmZWN0aW5nUHJvcHMoKSB7XG4gICAgcmV0dXJuIFsuLi5zdXBlci5ub25lTGF5ZXJEYXRhQWZmZWN0aW5nUHJvcHMsICdyYWRpdXMnXTtcbiAgfVxuXG4gIGdldCB2aXN1YWxDaGFubmVscygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY29sb3I6IHtcbiAgICAgICAgLi4uc3VwZXIudmlzdWFsQ2hhbm5lbHMuY29sb3IsXG4gICAgICAgIGNvbmRpdGlvbjogY29uZmlnID0+IGNvbmZpZy52aXNDb25maWcuZmlsbGVkXG4gICAgICB9LFxuICAgICAgc3Ryb2tlQ29sb3I6IHtcbiAgICAgICAgcHJvcGVydHk6ICdzdHJva2VDb2xvcicsXG4gICAgICAgIGZpZWxkOiAnc3Ryb2tlQ29sb3JGaWVsZCcsXG4gICAgICAgIHNjYWxlOiAnc3Ryb2tlQ29sb3JTY2FsZScsXG4gICAgICAgIGRvbWFpbjogJ3N0cm9rZUNvbG9yRG9tYWluJyxcbiAgICAgICAgcmFuZ2U6ICdzdHJva2VDb2xvclJhbmdlJyxcbiAgICAgICAga2V5OiAnc3Ryb2tlQ29sb3InLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiBDSEFOTkVMX1NDQUxFUy5jb2xvcixcbiAgICAgICAgY29uZGl0aW9uOiBjb25maWcgPT4gY29uZmlnLnZpc0NvbmZpZy5vdXRsaW5lXG4gICAgICB9LFxuICAgICAgc2l6ZToge1xuICAgICAgICAuLi5zdXBlci52aXN1YWxDaGFubmVscy5zaXplLFxuICAgICAgICByYW5nZTogJ3JhZGl1c1JhbmdlJyxcbiAgICAgICAgcHJvcGVydHk6ICdyYWRpdXMnLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiAncmFkaXVzJ1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBnZXRQb3NpdGlvbkFjY2Vzc29yKCkge1xuICAgIHJldHVybiB0aGlzLmdldFBvc2l0aW9uKHRoaXMuY29uZmlnLmNvbHVtbnMpO1xuICB9XG5cbiAgc3RhdGljIGZpbmREZWZhdWx0TGF5ZXJQcm9wcyh7ZmllbGRQYWlycyA9IFtdfSkge1xuICAgIGNvbnN0IHByb3BzID0gW107XG5cbiAgICAvLyBNYWtlIGxheWVyIGZvciBlYWNoIHBhaXJcbiAgICBmaWVsZFBhaXJzLmZvckVhY2gocGFpciA9PiB7XG4gICAgICAvLyBmaW5kIGZpZWxkcyBmb3IgdGFibGVGaWVsZEluZGV4XG4gICAgICBjb25zdCBsYXRGaWVsZCA9IHBhaXIucGFpci5sYXQ7XG4gICAgICBjb25zdCBsbmdGaWVsZCA9IHBhaXIucGFpci5sbmc7XG4gICAgICBjb25zdCBsYXllck5hbWUgPSBwYWlyLmRlZmF1bHROYW1lO1xuXG4gICAgICBjb25zdCBwcm9wID0ge1xuICAgICAgICBsYWJlbDogbGF5ZXJOYW1lLmxlbmd0aCA/IGxheWVyTmFtZSA6ICdQb2ludCdcbiAgICAgIH07XG5cbiAgICAgIC8vIGRlZmF1bHQgbGF5ZXIgY29sb3IgZm9yIGJlZ2ludHJpcCBhbmQgZHJvcG9mZiBwb2ludFxuICAgICAgaWYgKGxhdEZpZWxkLnZhbHVlIGluIERFRkFVTFRfTEFZRVJfQ09MT1IpIHtcbiAgICAgICAgcHJvcC5jb2xvciA9IGhleFRvUmdiKERFRkFVTFRfTEFZRVJfQ09MT1JbbGF0RmllbGQudmFsdWVdKTtcbiAgICAgIH1cblxuICAgICAgLy8gc2V0IHRoZSBmaXJzdCBsYXllciB0byBiZSB2aXNpYmxlXG4gICAgICBpZiAocHJvcHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHByb3AuaXNWaXNpYmxlID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgcHJvcC5jb2x1bW5zID0ge1xuICAgICAgICBsYXQ6IGxhdEZpZWxkLFxuICAgICAgICBsbmc6IGxuZ0ZpZWxkLFxuICAgICAgICBhbHRpdHVkZToge3ZhbHVlOiBudWxsLCBmaWVsZElkeDogLTEsIG9wdGlvbmFsOiB0cnVlfVxuICAgICAgfTtcblxuICAgICAgcHJvcHMucHVzaChwcm9wKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB7cHJvcHN9O1xuICB9XG5cbiAgZ2V0RGVmYXVsdExheWVyQ29uZmlnKHByb3BzID0ge30pIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uc3VwZXIuZ2V0RGVmYXVsdExheWVyQ29uZmlnKHByb3BzKSxcblxuICAgICAgLy8gYWRkIHN0cm9rZSBjb2xvciB2aXN1YWwgY2hhbm5lbFxuICAgICAgc3Ryb2tlQ29sb3JGaWVsZDogbnVsbCxcbiAgICAgIHN0cm9rZUNvbG9yRG9tYWluOiBbMCwgMV0sXG4gICAgICBzdHJva2VDb2xvclNjYWxlOiAncXVhbnRpbGUnXG4gICAgfTtcbiAgfVxuXG4gIC8vIFRPRE86IGZpeCBjb21wbGV4aXR5XG4gIC8qIGVzbGludC1kaXNhYmxlIGNvbXBsZXhpdHkgKi9cbiAgZm9ybWF0TGF5ZXJEYXRhKF8sIGFsbERhdGEsIGZpbHRlcmVkSW5kZXgsIG9sZExheWVyRGF0YSwgb3B0ID0ge30pIHtcbiAgICBjb25zdCB7XG4gICAgICBjb2xvclNjYWxlLFxuICAgICAgY29sb3JEb21haW4sXG4gICAgICBjb2xvckZpZWxkLFxuICAgICAgc3Ryb2tlQ29sb3JGaWVsZCxcbiAgICAgIHN0cm9rZUNvbG9yU2NhbGUsXG4gICAgICBzdHJva2VDb2xvckRvbWFpbixcbiAgICAgIGNvbG9yLFxuICAgICAgc2l6ZUZpZWxkLFxuICAgICAgc2l6ZVNjYWxlLFxuICAgICAgc2l6ZURvbWFpbixcbiAgICAgIHRleHRMYWJlbCxcbiAgICAgIHZpc0NvbmZpZzoge1xuICAgICAgICByYWRpdXNSYW5nZSxcbiAgICAgICAgZml4ZWRSYWRpdXMsXG4gICAgICAgIGNvbG9yUmFuZ2UsXG4gICAgICAgIHN0cm9rZUNvbG9yUmFuZ2UsXG4gICAgICAgIHN0cm9rZUNvbG9yXG4gICAgICB9XG4gICAgfSA9IHRoaXMuY29uZmlnO1xuXG4gICAgLy8gZmlsbCBjb2xvclxuICAgIGNvbnN0IGNTY2FsZSA9XG4gICAgICBjb2xvckZpZWxkICYmXG4gICAgICB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShcbiAgICAgICAgY29sb3JTY2FsZSxcbiAgICAgICAgY29sb3JEb21haW4sXG4gICAgICAgIGNvbG9yUmFuZ2UuY29sb3JzLm1hcChoZXhUb1JnYilcbiAgICAgICk7XG5cbiAgICAvLyBzdHJva2UgY29sb3JcbiAgICBjb25zdCBzY1NjYWxlID1cbiAgICAgIHN0cm9rZUNvbG9yRmllbGQgJiZcbiAgICAgIHRoaXMuZ2V0VmlzQ2hhbm5lbFNjYWxlKFxuICAgICAgICBzdHJva2VDb2xvclNjYWxlLFxuICAgICAgICBzdHJva2VDb2xvckRvbWFpbixcbiAgICAgICAgc3Ryb2tlQ29sb3JSYW5nZS5jb2xvcnMubWFwKGhleFRvUmdiKVxuICAgICAgKTtcblxuICAgIC8vIHBvaW50IHJhZGl1c1xuICAgIGNvbnN0IHJTY2FsZSA9XG4gICAgICBzaXplRmllbGQgJiZcbiAgICAgIHRoaXMuZ2V0VmlzQ2hhbm5lbFNjYWxlKHNpemVTY2FsZSwgc2l6ZURvbWFpbiwgcmFkaXVzUmFuZ2UsIGZpeGVkUmFkaXVzKTtcblxuICAgIGNvbnN0IGdldFBvc2l0aW9uID0gdGhpcy5nZXRQb3NpdGlvbkFjY2Vzc29yKCk7XG5cbiAgICBpZiAoIW9sZExheWVyRGF0YSB8fCBvbGRMYXllckRhdGEuZ2V0UG9zaXRpb24gIT09IGdldFBvc2l0aW9uKSB7XG4gICAgICB0aGlzLnVwZGF0ZUxheWVyTWV0YShhbGxEYXRhLCBnZXRQb3NpdGlvbik7XG4gICAgfVxuXG4gICAgbGV0IGRhdGE7XG4gICAgaWYgKFxuICAgICAgb2xkTGF5ZXJEYXRhICYmXG4gICAgICBvbGRMYXllckRhdGEuZGF0YSAmJlxuICAgICAgb3B0LnNhbWVEYXRhICYmXG4gICAgICBvbGRMYXllckRhdGEuZ2V0UG9zaXRpb24gPT09IGdldFBvc2l0aW9uXG4gICAgKSB7XG4gICAgICBkYXRhID0gb2xkTGF5ZXJEYXRhLmRhdGE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRhdGEgPSBmaWx0ZXJlZEluZGV4LnJlZHVjZSgoYWNjdSwgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgcG9zID0gZ2V0UG9zaXRpb24oe2RhdGE6IGFsbERhdGFbaW5kZXhdfSk7XG5cbiAgICAgICAgLy8gaWYgZG9lc24ndCBoYXZlIHBvaW50IGxhdCBvciBsbmcsIGRvIG5vdCBhZGQgdGhlIHBvaW50XG4gICAgICAgIC8vIGRlY2suZ2wgY2FuJ3QgaGFuZGxlIHBvc2l0aW9uID0gbnVsbFxuICAgICAgICBpZiAoIXBvcy5ldmVyeShOdW1iZXIuaXNGaW5pdGUpKSB7XG4gICAgICAgICAgcmV0dXJuIGFjY3U7XG4gICAgICAgIH1cblxuICAgICAgICBhY2N1LnB1c2goe1xuICAgICAgICAgIGRhdGE6IGFsbERhdGFbaW5kZXhdXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBhY2N1O1xuICAgICAgfSwgW10pO1xuICAgIH1cblxuICAgIC8vIGdldCBhbGwgZGlzdGluY3QgY2hhcmFjdGVycyBpbiB0aGUgdGV4dCBsYWJlbHNcbiAgICBjb25zdCBnZXRSYWRpdXMgPSByU2NhbGVcbiAgICAgID8gZCA9PiB0aGlzLmdldEVuY29kZWRDaGFubmVsVmFsdWUoclNjYWxlLCBkLmRhdGEsIHNpemVGaWVsZCwgMClcbiAgICAgIDogMTtcblxuICAgIGNvbnN0IGdldEZpbGxDb2xvciA9IGNTY2FsZVxuICAgICAgPyBkID0+IHRoaXMuZ2V0RW5jb2RlZENoYW5uZWxWYWx1ZShjU2NhbGUsIGQuZGF0YSwgY29sb3JGaWVsZClcbiAgICAgIDogY29sb3I7XG5cbiAgICBjb25zdCBnZXRMaW5lQ29sb3IgPSBzY1NjYWxlXG4gICAgICA/IGQgPT4gdGhpcy5nZXRFbmNvZGVkQ2hhbm5lbFZhbHVlKHNjU2NhbGUsIGQuZGF0YSwgc3Ryb2tlQ29sb3JGaWVsZClcbiAgICAgIDogc3Ryb2tlQ29sb3IgfHwgY29sb3I7XG5cbiAgICAvLyBUT0RPOiB0aGlzIHNob3VsZCBiZSBjbGVhbmVkIHVwIGluIHRoZSBncHUtZGF0YS1maWx0ZXIgYnJhbmNoXG4gICAgY29uc3QgdGV4dExhYmVscyA9IHRleHRMYWJlbC5tYXAoKHRsLCBpKSA9PiB7XG4gICAgICBpZiAoIXRsLmZpZWxkKSB7XG4gICAgICAgIC8vIGlmIG5vIGZpZWxkIHNlbGVjdGVkLFxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGdldFRleHQ6IG51bGwsXG4gICAgICAgICAgY2hhcmFjdGVyU2V0OiBbXVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgaWYgKCF0aGlzLmdldFRleHRbaV0pIHtcbiAgICAgICAgdGhpcy5nZXRUZXh0W2ldID0gbWVtb2l6ZShwb2ludExhYmVsQWNjZXNzb3IsIHBvaW50TGFiZWxSZXNvbHZlcik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGdldFRleHQgPSB0aGlzLmdldFRleHRbaV0odGwpO1xuICAgICAgbGV0IGNoYXJhY3RlclNldDtcblxuICAgICAgaWYgKFxuICAgICAgICBvbGRMYXl