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