kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
462 lines (406 loc) • 54.7 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.geojsonVisConfigs = exports.geoJsonRequiredColumns = exports.featureResolver = exports.featureAccessor = exports["default"] = 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 _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 _baseLayer = _interopRequireWildcard(require("../base-layer"));
var _deck = require("deck.gl");
var _colorUtils = require("../../utils/color-utils");
var _geojsonUtils = require("./geojson-utils");
var _geojsonLayerIcon = _interopRequireDefault(require("./geojson-layer-icon"));
var _defaultSettings = require("../../constants/default-settings");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
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 geojsonVisConfigs = exports.geojsonVisConfigs = {
opacity: 'opacity',
thickness: {
type: 'number',
defaultValue: 0.5,
label: 'Stroke Width',
isRanged: false,
range: [0, 100],
step: 0.1,
group: 'stroke',
property: 'thickness'
},
strokeColor: 'strokeColor',
colorRange: 'colorRange',
strokeColorRange: 'strokeColorRange',
radius: 'radius',
sizeRange: 'strokeWidthRange',
radiusRange: 'radiusRange',
heightRange: 'elevationRange',
elevationScale: 'elevationScale',
stroked: 'stroked',
filled: 'filled',
enable3d: 'enable3d',
wireframe: 'wireframe'
};
var geoJsonRequiredColumns = exports.geoJsonRequiredColumns = ['geojson'];
var featureAccessor = exports.featureAccessor = function featureAccessor(_ref) {
var geojson = _ref.geojson;
return function (d) {
return d[geojson.fieldIdx];
};
};
var featureResolver = exports.featureResolver = function featureResolver(_ref2) {
var geojson = _ref2.geojson;
return geojson.fieldIdx;
};
var GeoJsonLayer = exports["default"] = /*#__PURE__*/function (_Layer) {
(0, _inherits2["default"])(GeoJsonLayer, _Layer);
var _super = _createSuper(GeoJsonLayer);
function GeoJsonLayer(props) {
var _this;
(0, _classCallCheck2["default"])(this, GeoJsonLayer);
_this = _super.call(this, props);
_this.dataToFeature = [];
_this.registerVisConfig(geojsonVisConfigs);
_this.getFeature = (0, _lodash["default"])(featureAccessor, featureResolver);
return _this;
}
(0, _createClass2["default"])(GeoJsonLayer, [{
key: "type",
get: function get() {
return 'geojson';
}
}, {
key: "name",
get: function get() {
return 'Polygon';
}
}, {
key: "layerIcon",
get: function get() {
return _geojsonLayerIcon["default"];
}
}, {
key: "requiredLayerColumns",
get: function get() {
return geoJsonRequiredColumns;
}
}, {
key: "visualChannels",
get: function get() {
return _objectSpread(_objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(GeoJsonLayer.prototype), "visualChannels", this)), {}, {
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.stroked;
}
},
size: _objectSpread(_objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(GeoJsonLayer.prototype), "visualChannels", this).size), {}, {
property: 'stroke',
condition: function condition(config) {
return config.visConfig.stroked;
}
}),
height: {
property: 'height',
field: 'heightField',
scale: 'heightScale',
domain: 'heightDomain',
range: 'heightRange',
key: 'height',
channelScaleType: 'size',
condition: function condition(config) {
return config.visConfig.enable3d;
}
},
radius: {
property: 'radius',
field: 'radiusField',
scale: 'radiusScale',
domain: 'radiusDomain',
range: 'radiusRange',
key: 'radius',
channelScaleType: 'radius'
}
});
}
}, {
key: "getPositionAccessor",
value: function getPositionAccessor() {
return this.getFeature(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"])(GeoJsonLayer.prototype), "getDefaultLayerConfig", this).call(this, props)), {}, {
// add height visual channel
heightField: null,
heightDomain: [0, 1],
heightScale: 'linear',
// add radius visual channel
radiusField: null,
radiusDomain: [0, 1],
radiusScale: 'linear',
// add stroke color visual channel
strokeColorField: null,
strokeColorDomain: [0, 1],
strokeColorScale: 'quantile'
});
}
}, {
key: "getHoverData",
value: function getHoverData(object) {
// index of allData is saved to feature.properties
return object;
} // 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,
colorField = _this$config.colorField,
colorDomain = _this$config.colorDomain,
strokeColorField = _this$config.strokeColorField,
strokeColorScale = _this$config.strokeColorScale,
strokeColorDomain = _this$config.strokeColorDomain,
color = _this$config.color,
sizeScale = _this$config.sizeScale,
sizeDomain = _this$config.sizeDomain,
sizeField = _this$config.sizeField,
heightField = _this$config.heightField,
heightDomain = _this$config.heightDomain,
heightScale = _this$config.heightScale,
radiusField = _this$config.radiusField,
radiusDomain = _this$config.radiusDomain,
radiusScale = _this$config.radiusScale,
visConfig = _this$config.visConfig;
var enable3d = visConfig.enable3d,
stroked = visConfig.stroked,
colorRange = visConfig.colorRange,
heightRange = visConfig.heightRange,
sizeRange = visConfig.sizeRange,
radiusRange = visConfig.radiusRange,
strokeColorRange = visConfig.strokeColorRange,
strokeColor = visConfig.strokeColor;
var getFeature = this.getPositionAccessor(this.config.column); // geojson feature are object, if doesn't exists
// create it and save to layer
if (!oldLayerData || oldLayerData.getFeature !== getFeature) {
this.updateLayerMeta(allData, getFeature);
}
var geojsonData;
if (oldLayerData && oldLayerData.data && opt.sameData && oldLayerData.getFeature === getFeature) {
// no need to create a new array of data
// use updateTriggers to selectively re-calculate attributes
geojsonData = oldLayerData.data;
} else {
// filteredIndex is a reference of index in allData which can map to feature
geojsonData = filteredIndex.map(function (i) {
return _this2.dataToFeature[i];
}).filter(function (d) {
return d;
});
} // 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)); // calculate stroke scale - if stroked = true
var sScale = sizeField && stroked && this.getVisChannelScale(sizeScale, sizeDomain, sizeRange); // calculate elevation scale - if extruded = true
var eScale = heightField && enable3d && this.getVisChannelScale(heightScale, heightDomain, heightRange); // console.log('eScale inside formatLayerData', eScale);
// point radius
var rScale = radiusField && this.getVisChannelScale(radiusScale, radiusDomain, radiusRange);
return {
data: geojsonData,
getFeature: getFeature,
getFillColor: function getFillColor(d) {
return cScale ? _this2.getEncodedChannelValue(cScale, allData[d.properties.index], colorField) : d.properties.fillColor || color;
},
getLineColor: function getLineColor(d) {
return scScale ? _this2.getEncodedChannelValue(scScale, allData[d.properties.index], strokeColorField) : d.properties.lineColor || strokeColor || color;
},
getLineWidth: function getLineWidth(d) {
return sScale ? _this2.getEncodedChannelValue(sScale, allData[d.properties.index], sizeField, 0) : d.properties.lineWidth || 1;
},
getElevation: function getElevation(d) {
return eScale ? _this2.getEncodedChannelValue(eScale, allData[d.properties.index], heightField, 0) : d.properties.elevation || 500;
},
getRadius: function getRadius(d) {
return rScale ? _this2.getEncodedChannelValue(rScale, allData[d.properties.index], radiusField, 0) : d.properties.radius || 1;
}
};
}
/* eslint-enable complexity */
}, {
key: "updateLayerMeta",
value: function updateLayerMeta(allData) {
var getFeature = this.getPositionAccessor();
this.dataToFeature = (0, _geojsonUtils.getGeojsonDataMaps)(allData, getFeature); // get bounds from features
var bounds = (0, _geojsonUtils.getGeojsonBounds)(this.dataToFeature); // if any of the feature has properties.radius set to be true
var fixedRadius = Boolean(this.dataToFeature.find(function (d) {
return d && d.properties && d.properties.radius;
})); // keep a record of what type of geometry the collection has
var featureTypes = (0, _geojsonUtils.getGeojsonFeatureTypes)(this.dataToFeature);
this.updateMeta({
bounds: bounds,
fixedRadius: fixedRadius,
featureTypes: featureTypes
});
}
}, {
key: "setInitialLayerConfig",
value: function setInitialLayerConfig(allData) {
this.updateLayerMeta(allData);
var featureTypes = this.meta.featureTypes; // default settings is stroke: true, filled: false
if (featureTypes && featureTypes.polygon) {
// set both fill and stroke to true
return this.updateLayerVisConfig({
filled: true,
stroked: true,
strokeColor: _baseLayer.colorMaker.next().value
});
} else if (featureTypes && featureTypes.point) {
// set fill to true if detect point
return this.updateLayerVisConfig({
filled: true,
stroked: false
});
}
return this;
}
}, {
key: "renderLayer",
value: function renderLayer(_ref3) {
var data = _ref3.data,
idx = _ref3.idx,
objectHovered = _ref3.objectHovered,
mapState = _ref3.mapState,
interactionConfig = _ref3.interactionConfig;
var fixedRadius = this.meta.fixedRadius;
var radiusScale = this.getRadiusScaleByZoom(mapState, fixedRadius);
var zoomFactor = this.getZoomFactor(mapState);
var visConfig = this.config.visConfig;
var layerProps = {
// multiplier applied just so it being consistent with previously saved maps
lineWidthScale: visConfig.thickness * zoomFactor * 8,
elevationScale: visConfig.elevationScale,
pointRadiusScale: radiusScale,
lineMiterLimit: 4
};
var updateTriggers = {
getElevation: {
heightField: this.config.heightField,
heightScale: this.config.heightScale,
heightRange: visConfig.heightRange
},
getFillColor: {
color: this.config.color,
colorField: this.config.colorField,
colorRange: visConfig.colorRange,
colorScale: this.config.colorScale
},
getLineColor: {
color: visConfig.strokeColor,
colorField: this.config.strokeColorField,
colorRange: visConfig.strokeColorRange,
colorScale: this.config.strokeColorScale
},
getLineWidth: {
sizeField: this.config.sizeField,
sizeRange: visConfig.sizeRange
},
getRadius: {
radiusField: this.config.radiusField,
radiusRange: visConfig.radiusRange
}
};
return [new _deck.GeoJsonLayer(_objectSpread(_objectSpread({}, layerProps), {}, {
id: this.id,
idx: idx,
data: data.data,
getFillColor: data.getFillColor,
getLineColor: data.getLineColor,
getLineWidth: data.getLineWidth,
getRadius: data.getRadius,
getElevation: data.getElevation,
// highlight
pickable: true,
highlightColor: _defaultSettings.HIGHLIGH_COLOR_3D,
autoHighlight: visConfig.enable3d,
// parameters
parameters: {
depthTest: Boolean(visConfig.enable3d || mapState.dragRotate)
},
opacity: visConfig.opacity,
stroked: visConfig.stroked,
filled: visConfig.filled,
extruded: visConfig.enable3d,
wireframe: visConfig.wireframe,
lineMiterLimit: 2,
rounded: true,
updateTriggers: updateTriggers
}))].concat((0, _toConsumableArray2["default"])(this.isLayerHovered(objectHovered) && !visConfig.enable3d ? [new _deck.GeoJsonLayer(_objectSpread(_objectSpread({}, layerProps), {}, {
id: "".concat(this.id, "-hovered"),
data: [objectHovered.object],
getLineWidth: data.getLineWidth,
getRadius: data.getRadius,
getElevation: data.getElevation,
getLineColor: this.config.highlightColor,
getFillColor: this.config.highlightColor,
updateTriggers: updateTriggers,
stroked: true,
pickable: false,
filled: false
}))] : []));
}
}], [{
key: "findDefaultLayerProps",
value: function findDefaultLayerProps(_ref4) {
var _this3 = this;
var label = _ref4.label,
_ref4$fields = _ref4.fields,
fields = _ref4$fields === void 0 ? [] : _ref4$fields;
var geojsonColumns = fields.filter(function (f) {
return f.type === 'geojson';
}).map(function (f) {
return f.name;
});
var defaultColumns = {
geojson: (0, _lodash2["default"])([].concat((0, _toConsumableArray2["default"])(_defaultSettings.GEOJSON_FIELDS.geojson), (0, _toConsumableArray2["default"])(geojsonColumns)))
};
var foundColumns = this.findDefaultColumnField(defaultColumns, fields);
if (!foundColumns || !foundColumns.length) {
return {
props: []
};
}
return {
props: foundColumns.map(function (columns) {
return {
label: typeof label === 'string' && label.replace(/\.[^/.]+$/, '') || _this3.type,
columns: columns,
isVisible: true
};
})
};
}
}]);
return GeoJsonLayer;
}(_baseLayer["default"]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvZ2VvanNvbi1sYXllci9nZW9qc29uLWxheWVyLmpzIl0sIm5hbWVzIjpbImdlb2pzb25WaXNDb25maWdzIiwib3BhY2l0eSIsInRoaWNrbmVzcyIsInR5cGUiLCJkZWZhdWx0VmFsdWUiLCJsYWJlbCIsImlzUmFuZ2VkIiwicmFuZ2UiLCJzdGVwIiwiZ3JvdXAiLCJwcm9wZXJ0eSIsInN0cm9rZUNvbG9yIiwiY29sb3JSYW5nZSIsInN0cm9rZUNvbG9yUmFuZ2UiLCJyYWRpdXMiLCJzaXplUmFuZ2UiLCJyYWRpdXNSYW5nZSIsImhlaWdodFJhbmdlIiwiZWxldmF0aW9uU2NhbGUiLCJzdHJva2VkIiwiZmlsbGVkIiwiZW5hYmxlM2QiLCJ3aXJlZnJhbWUiLCJnZW9Kc29uUmVxdWlyZWRDb2x1bW5zIiwiZmVhdHVyZUFjY2Vzc29yIiwiZ2VvanNvbiIsImQiLCJmaWVsZElkeCIsImZlYXR1cmVSZXNvbHZlciIsIkdlb0pzb25MYXllciIsInByb3BzIiwiZGF0YVRvRmVhdHVyZSIsInJlZ2lzdGVyVmlzQ29uZmlnIiwiZ2V0RmVhdHVyZSIsIkdlb2pzb25MYXllckljb24iLCJmaWVsZCIsInNjYWxlIiwiZG9tYWluIiwia2V5IiwiY2hhbm5lbFNjYWxlVHlwZSIsIkNIQU5ORUxfU0NBTEVTIiwiY29sb3IiLCJjb25kaXRpb24iLCJjb25maWciLCJ2aXNDb25maWciLCJzaXplIiwiaGVpZ2h0IiwiY29sdW1ucyIsImhlaWdodEZpZWxkIiwiaGVpZ2h0RG9tYWluIiwiaGVpZ2h0U2NhbGUiLCJyYWRpdXNGaWVsZCIsInJhZGl1c0RvbWFpbiIsInJhZGl1c1NjYWxlIiwic3Ryb2tlQ29sb3JGaWVsZCIsInN0cm9rZUNvbG9yRG9tYWluIiwic3Ryb2tlQ29sb3JTY2FsZSIsIm9iamVjdCIsIl8iLCJhbGxEYXRhIiwiZmlsdGVyZWRJbmRleCIsIm9sZExheWVyRGF0YSIsIm9wdCIsImNvbG9yU2NhbGUiLCJjb2xvckZpZWxkIiwiY29sb3JEb21haW4iLCJzaXplU2NhbGUiLCJzaXplRG9tYWluIiwic2l6ZUZpZWxkIiwiZ2V0UG9zaXRpb25BY2Nlc3NvciIsImNvbHVtbiIsInVwZGF0ZUxheWVyTWV0YSIsImdlb2pzb25EYXRhIiwiZGF0YSIsInNhbWVEYXRhIiwibWFwIiwiaSIsImZpbHRlciIsImNTY2FsZSIsImdldFZpc0NoYW5uZWxTY2FsZSIsImNvbG9ycyIsImhleFRvUmdiIiwic2NTY2FsZSIsInNTY2FsZSIsImVTY2FsZSIsInJTY2FsZSIsImdldEZpbGxDb2xvciIsImdldEVuY29kZWRDaGFubmVsVmFsdWUiLCJwcm9wZXJ0aWVzIiwiaW5kZXgiLCJmaWxsQ29sb3IiLCJnZXRMaW5lQ29sb3IiLCJsaW5lQ29sb3IiLCJnZXRMaW5lV2lkdGgiLCJsaW5lV2lkdGgiLCJnZXRFbGV2YXRpb24iLCJlbGV2YXRpb24iLCJnZXRSYWRpdXMiLCJib3VuZHMiLCJmaXhlZFJhZGl1cyIsIkJvb2xlYW4iLCJmaW5kIiwiZmVhdHVyZVR5cGVzIiwidXBkYXRlTWV0YSIsIm1ldGEiLCJwb2x5Z29uIiwidXBkYXRlTGF5ZXJWaXNDb25maWciLCJjb2xvck1ha2VyIiwibmV4dCIsInZhbHVlIiwicG9pbnQiLCJpZHgiLCJvYmplY3RIb3ZlcmVkIiwibWFwU3RhdGUiLCJpbnRlcmFjdGlvbkNvbmZpZyIsImdldFJhZGl1c1NjYWxlQnlab29tIiwiem9vbUZhY3RvciIsImdldFpvb21GYWN0b3IiLCJsYXllclByb3BzIiwibGluZVdpZHRoU2NhbGUiLCJwb2ludFJhZGl1c1NjYWxlIiwibGluZU1pdGVyTGltaXQiLCJ1cGRhdGVUcmlnZ2VycyIsIkRlY2tHTEdlb0pzb25MYXllciIsImlkIiwicGlja2FibGUiLCJoaWdobGlnaHRDb2xvciIsIkhJR0hMSUdIX0NPTE9SXzNEIiwiYXV0b0hpZ2hsaWdodCIsInBhcmFtZXRlcnMiLCJkZXB0aFRlc3QiLCJkcmFnUm90YXRlIiwiZXh0cnVkZWQiLCJyb3VuZGVkIiwiaXNMYXllckhvdmVyZWQiLCJmaWVsZHMiLCJnZW9qc29uQ29sdW1ucyIsImYiLCJuYW1lIiwiZGVmYXVsdENvbHVtbnMiLCJHRU9KU09OX0ZJRUxEUyIsImZvdW5kQ29sdW1ucyIsImZpbmREZWZhdWx0Q29sdW1uRmllbGQiLCJsZW5ndGgiLCJyZXBsYWNlIiwiaXNWaXNpYmxlIiwiTGF5ZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTs7QUFDQTs7QUFFQTs7QUFDQTs7QUFFQTs7QUFDQTs7QUFLQTs7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUFNTyxJQUFNQSxpQkFBaUIsK0JBQUc7QUFDL0JDLEVBQUFBLE9BQU8sRUFBRSxTQURzQjtBQUUvQkMsRUFBQUEsU0FBUyxFQUFFO0FBQ1RDLElBQUFBLElBQUksRUFBRSxRQURHO0FBRVRDLElBQUFBLFlBQVksRUFBRSxHQUZMO0FBR1RDLElBQUFBLEtBQUssRUFBRSxjQUhFO0FBSVRDLElBQUFBLFFBQVEsRUFBRSxLQUpEO0FBS1RDLElBQUFBLEtBQUssRUFBRSxDQUFDLENBQUQsRUFBSSxHQUFKLENBTEU7QUFNVEMsSUFBQUEsSUFBSSxFQUFFLEdBTkc7QUFPVEMsSUFBQUEsS0FBSyxFQUFFLFFBUEU7QUFRVEMsSUFBQUEsUUFBUSxFQUFFO0FBUkQsR0FGb0I7QUFZL0JDLEVBQUFBLFdBQVcsRUFBRSxhQVprQjtBQWEvQkMsRUFBQUEsVUFBVSxFQUFFLFlBYm1CO0FBYy9CQyxFQUFBQSxnQkFBZ0IsRUFBRSxrQkFkYTtBQWUvQkMsRUFBQUEsTUFBTSxFQUFFLFFBZnVCO0FBaUIvQkMsRUFBQUEsU0FBUyxFQUFFLGtCQWpCb0I7QUFrQi9CQyxFQUFBQSxXQUFXLEVBQUUsYUFsQmtCO0FBbUIvQkMsRUFBQUEsV0FBVyxFQUFFLGdCQW5Ca0I7QUFvQi9CQyxFQUFBQSxjQUFjLEVBQUUsZ0JBcEJlO0FBcUIvQkMsRUFBQUEsT0FBTyxFQUFFLFNBckJzQjtBQXNCL0JDLEVBQUFBLE1BQU0sRUFBRSxRQXRCdUI7QUF1Qi9CQyxFQUFBQSxRQUFRLEVBQUUs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QURZLE9BQXZCO0FBSUEsVUFBTUssWUFBWSxHQUFHLEtBQUtDLHNCQUFMLENBQTRCSCxjQUE1QixFQUE0Q0osTUFBNUMsQ0FBckI7O0FBQ0EsVUFBSSxDQUFDTSxZQUFELElBQWlCLENBQUNBLFlBQVksQ0FBQ0UsTUFBbkMsRUFBMkM7QUFDekMsZUFBTztBQUFDakgsVUFBQUEsS0FBSyxFQUFFO0FBQVIsU0FBUDtBQUNEOztBQUVELGFBQU87QUFDTEEsUUFBQUEsS0FBSyxFQUFFK0csWUFBWSxDQUFDbEUsR0FBYixDQUFpQixVQUFBNUIsT0FBTztBQUFBLGlCQUFLO0FBQ2xDMUMsWUFBQUEsS0FBSyxFQUNGLE9BQU9BLEtBQVAsS0FBaUIsUUFBakIsSUFBNkJBLEtBQUssQ0FBQzJJLE9BQU4sQ0FBYyxXQUFkLEVBQTJCLEVBQTNCLENBQTlCLElBQ0EsTUFBSSxDQUFDN0ksSUFIMkI7QUFJbEM0QyxZQUFBQSxPQUFPLEVBQVBBLE9BSmtDO0FBS2xDa0csWUFBQUEsU0FBUyxFQUFFO0FBTHVCLFdBQUw7QUFBQSxTQUF4QjtBQURGLE9BQVA7QUFTRDs7O0VBNUZ1Q0MscUIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMjMgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgbWVtb2l6ZSBmcm9tICdsb2Rhc2gubWVtb2l6ZSc7XG5pbXBvcnQgdW5pcSBmcm9tICdsb2Rhc2gudW5pcSc7XG5cbmltcG9ydCBMYXllciwge2NvbG9yTWFrZXJ9IGZyb20gJy4uL2Jhc2UtbGF5ZXInO1xuaW1wb3J0IHtHZW9Kc29uTGF5ZXIgYXMgRGVja0dMR2VvSnNvbkxheWVyfSBmcm9tICdkZWNrLmdsJztcblxuaW1wb3J0IHtoZXhUb1JnYn0gZnJvbSAndXRpbHMvY29sb3ItdXRpbHMnO1xuaW1wb3J0IHtcbiAgZ2V0R2VvanNvbkRhdGFNYXBzLFxuICBnZXRHZW9qc29uQm91bmRzLFxuICBnZXRHZW9qc29uRmVhdHVyZVR5cGVzXG59IGZyb20gJy4vZ2VvanNvbi11dGlscyc7XG5pbXBvcnQgR2VvanNvbkxheWVySWNvbiBmcm9tICcuL2dlb2pzb24tbGF5ZXItaWNvbic7XG5pbXBvcnQge1xuICBHRU9KU09OX0ZJRUxEUyxcbiAgSElHSExJR0hfQ09MT1JfM0QsXG4gIENIQU5ORUxfU0NBTEVTXG59IGZyb20gJ2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzJztcblxuZXhwb3J0IGNvbnN0IGdlb2pzb25WaXNDb25maWdzID0ge1xuICBvcGFjaXR5OiAnb3BhY2l0eScsXG4gIHRoaWNrbmVzczoge1xuICAgIHR5cGU6ICdudW1iZXInLFxuICAgIGRlZmF1bHRWYWx1ZTogMC41LFxuICAgIGxhYmVsOiAnU3Ryb2tlIFdpZHRoJyxcbiAgICBpc1JhbmdlZDogZmFsc2UsXG4gICAgcmFuZ2U6IFswLCAxMDBdLFxuICAgIHN0ZXA6IDAuMSxcbiAgICBncm91cDogJ3N0cm9rZScsXG4gICAgcHJvcGVydHk6ICd0aGlja25lc3MnXG4gIH0sXG4gIHN0cm9rZUNvbG9yOiAnc3Ryb2tlQ29sb3InLFxuICBjb2xvclJhbmdlOiAnY29sb3JSYW5nZScsXG4gIHN0cm9rZUNvbG9yUmFuZ2U6ICdzdHJva2VDb2xvclJhbmdlJyxcbiAgcmFkaXVzOiAncmFkaXVzJyxcblxuICBzaXplUmFuZ2U6ICdzdHJva2VXaWR0aFJhbmdlJyxcbiAgcmFkaXVzUmFuZ2U6ICdyYWRpdXNSYW5nZScsXG4gIGhlaWdodFJhbmdlOiAnZWxldmF0aW9uUmFuZ2UnLFxuICBlbGV2YXRpb25TY2FsZTogJ2VsZXZhdGlvblNjYWxlJyxcbiAgc3Ryb2tlZDogJ3N0cm9rZWQnLFxuICBmaWxsZWQ6ICdmaWxsZWQnLFxuICBlbmFibGUzZDogJ2VuYWJsZTNkJyxcbiAgd2lyZWZyYW1lOiAnd2lyZWZyYW1lJ1xufTtcblxuZXhwb3J0IGNvbnN0IGdlb0pzb25SZXF1aXJlZENvbHVtbnMgPSBbJ2dlb2pzb24nXTtcbmV4cG9ydCBjb25zdCBmZWF0dXJlQWNjZXNzb3IgPSAoe2dlb2pzb259KSA9PiBkID0+IGRbZ2VvanNvbi5maWVsZElkeF07XG5leHBvcnQgY29uc3QgZmVhdHVyZVJlc29sdmVyID0gKHtnZW9qc29ufSkgPT4gZ2VvanNvbi5maWVsZElkeDtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2VvSnNvbkxheWVyIGV4dGVuZHMgTGF5ZXIge1xuICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgIHN1cGVyKHByb3BzKTtcblxuICAgIHRoaXMuZGF0YVRvRmVhdHVyZSA9IFtdO1xuICAgIHRoaXMucmVnaXN0ZXJWaXNDb25maWcoZ2VvanNvblZpc0NvbmZpZ3MpO1xuICAgIHRoaXMuZ2V0RmVhdHVyZSA9IG1lbW9pemUoZmVhdHVyZUFjY2Vzc29yLCBmZWF0dXJlUmVzb2x2ZXIpO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdnZW9qc29uJztcbiAgfVxuXG4gIGdldCBuYW1lKCkge1xuICAgIHJldHVybiAnUG9seWdvbic7XG4gIH1cblxuICBnZXQgbGF5ZXJJY29uKCkge1xuICAgIHJldHVybiBHZW9qc29uTGF5ZXJJY29uO1xuICB9XG5cbiAgZ2V0IHJlcXVpcmVkTGF5ZXJDb2x1bW5zKCkge1xuICAgIHJldHVybiBnZW9Kc29uUmVxdWlyZWRDb2x1bW5zO1xuICB9XG5cbiAgZ2V0IHZpc3VhbENoYW5uZWxzKCkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdXBlci52aXN1YWxDaGFubmVscyxcbiAgICAgIHN0cm9rZUNvbG9yOiB7XG4gICAgICAgIHByb3BlcnR5OiAnc3Ryb2tlQ29sb3InLFxuICAgICAgICBmaWVsZDogJ3N0cm9rZUNvbG9yRmllbGQnLFxuICAgICAgICBzY2FsZTogJ3N0cm9rZUNvbG9yU2NhbGUnLFxuICAgICAgICBkb21haW46ICdzdHJva2VDb2xvckRvbWFpbicsXG4gICAgICAgIHJhbmdlOiAnc3Ryb2tlQ29sb3JSYW5nZScsXG4gICAgICAgIGtleTogJ3N0cm9rZUNvbG9yJyxcbiAgICAgICAgY2hhbm5lbFNjYWxlVHlwZTogQ0hBTk5FTF9TQ0FMRVMuY29sb3IsXG4gICAgICAgIGNvbmRpdGlvbjogY29uZmlnID0+IGNvbmZpZy52aXNDb25maWcuc3Ryb2tlZFxuICAgICAgfSxcbiAgICAgIHNpemU6IHtcbiAgICAgICAgLi4uc3VwZXIudmlzdWFsQ2hhbm5lbHMuc2l6ZSxcbiAgICAgICAgcHJvcGVydHk6ICdzdHJva2UnLFxuICAgICAgICBjb25kaXRpb246IGNvbmZpZyA9PiBjb25maWcudmlzQ29uZmlnLnN0cm9rZWRcbiAgICAgIH0sXG4gICAgICBoZWlnaHQ6IHtcbiAgICAgICAgcHJvcGVydHk6ICdoZWlnaHQnLFxuICAgICAgICBmaWVsZDogJ2hlaWdodEZpZWxkJyxcbiAgICAgICAgc2NhbGU6ICdoZWlnaHRTY2FsZScsXG4gICAgICAgIGRvbWFpbjogJ2hlaWdodERvbWFpbicsXG4gICAgICAgIHJhbmdlOiAnaGVpZ2h0UmFuZ2UnLFxuICAgICAgICBrZXk6ICdoZWlnaHQnLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiAnc2l6ZScsXG4gICAgICAgIGNvbmRpdGlvbjogY29uZmlnID0+IGNvbmZpZy52aXNDb25maWcuZW5hYmxlM2RcbiAgICAgIH0sXG4gICAgICByYWRpdXM6IHtcbiAgICAgICAgcHJvcGVydHk6ICdyYWRpdXMnLFxuICAgICAgICBmaWVsZDogJ3JhZGl1c0ZpZWxkJyxcbiAgICAgICAgc2NhbGU6ICdyYWRpdXNTY2FsZScsXG4gICAgICAgIGRvbWFpbjogJ3JhZGl1c0RvbWFpbicsXG4gICAgICAgIHJhbmdlOiAncmFkaXVzUmFuZ2UnLFxuICAgICAgICBrZXk6ICdyYWRpdXMnLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiAncmFkaXVzJ1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBnZXRQb3NpdGlvbkFjY2Vzc29yKCkge1xuICAgIHJldHVybiB0aGlzLmdldEZlYXR1cmUodGhpcy5jb25maWcuY29sdW1ucyk7XG4gIH1cblxuICBzdGF0aWMgZmluZERlZmF1bHRMYXllclByb3BzKHtsYWJlbCwgZmllbGRzID0gW119KSB7XG4gICAgY29uc3QgZ2VvanNvbkNvbHVtbnMgPSBmaWVsZHNcbiAgICAgIC5maWx0ZXIoZiA9PiBmLnR5cGUgPT09ICdnZW9qc29uJylcbiAgICAgIC5tYXAoZiA9PiBmLm5hbWUpO1xuXG4gICAgY29uc3QgZGVmYXVsdENvbHVtbnMgPSB7XG4gICAgICBnZW9qc29uOiB1bmlxKFsuLi5HRU9KU09OX0ZJRUxEUy5nZW9qc29uLCAuLi5nZW9qc29uQ29sdW1uc10pXG4gICAgfTtcblxuICAgIGNvbnN0IGZvdW5kQ29sdW1ucyA9IHRoaXMuZmluZERlZmF1bHRDb2x1bW5GaWVsZChkZWZhdWx0Q29sdW1ucywgZmllbGRzKTtcbiAgICBpZiAoIWZvdW5kQ29sdW1ucyB8fCAhZm91bmRDb2x1bW5zLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHtwcm9wczogW119O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBwcm9wczogZm91bmRDb2x1bW5zLm1hcChjb2x1bW5zID0+ICh7XG4gICAgICAgIGxhYmVsOlxuICAgICAgICAgICh0eXBlb2YgbGFiZWwgPT09ICdzdHJpbmcnICYmIGxhYmVsLnJlcGxhY2UoL1xcLlteLy5dKyQvLCAnJykpIHx8XG4gICAgICAgICAgdGhpcy50eXBlLFxuICAgICAgICBjb2x1bW5zLFxuICAgICAgICBpc1Zpc2libGU6IHRydWVcbiAgICAgIH0pKVxuICAgIH07XG4gIH1cblxuICBnZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMgPSB7fSkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdXBlci5nZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMpLFxuXG4gICAgICAvLyBhZGQgaGVpZ2h0IHZpc3VhbCBjaGFubmVsXG4gICAgICBoZWlnaHRGaWVsZDogbnVsbCxcbiAgICAgIGhlaWdodERvbWFpbjogWzAsIDFdLFxuICAgICAgaGVpZ2h0U2NhbGU6ICdsaW5lYXInLFxuXG4gICAgICAvLyBhZGQgcmFkaXVzIHZpc3VhbCBjaGFubmVsXG4gICAgICByYWRpdXNGaWVsZDogbnVsbCxcbiAgICAgIHJhZGl1c0RvbWFpbjogWzAsIDFdLFxuICAgICAgcmFkaXVzU2NhbGU6ICdsaW5lYXInLFxuXG4gICAgICAvLyBhZGQgc3Ryb2tlIGNvbG9yIHZpc3VhbCBjaGFubmVsXG4gICAgICBzdHJva2VDb2xvckZpZWxkOiBudWxsLFxuICAgICAgc3Ryb2tlQ29sb3JEb21haW46IFswLCAxXSxcbiAgICAgIHN0cm9rZUNvbG9yU2NhbGU6ICdxdWFudGlsZSdcbiAgICB9O1xuICB9XG5cbiAgZ2V0SG92ZXJEYXRhKG9iamVjdCkge1xuICAgIC8vIGluZGV4IG9mIGFsbERhdGEgaXMgc2F2ZWQgdG8gZmVhdHVyZS5wcm9wZXJ0aWVzXG4gICAgcmV0dXJuIG9iamVjdDtcbiAgfVxuXG4gIC8vIFRPRE86IGZpeCBjb21wbGV4aXR5XG4gIC8qIGVzbGludC1kaXNhYmxlIGNvbXBsZXhpdHkgKi9cbiAgZm9ybWF0TGF5ZXJEYXRhKF8sIGFsbERhdGEsIGZpbHRlcmVkSW5kZXgsIG9sZExheWVyRGF0YSwgb3B0ID0ge30pIHtcbiAgICBjb25zdCB7XG4gICAgICBjb2xvclNjYWxlLFxuICAgICAgY29sb3JGaWVsZCxcbiAgICAgIGNvbG9yRG9tYWluLFxuICAgICAgc3Ryb2tlQ29sb3JGaWVsZCxcbiAgICAgIHN0cm9rZUNvbG9yU2NhbGUsXG4gICAgICBzdHJva2VDb2xvckRvbWFpbixcbiAgICAgIGNvbG9yLFxuICAgICAgc2l6ZVNjYWxlLFxuICAgICAgc2l6ZURvbWFpbixcbiAgICAgIHNpemVGaWVsZCxcbiAgICAgIGhlaWdodEZpZWxkLFxuICAgICAgaGVpZ2h0RG9tYWluLFxuICAgICAgaGVpZ2h0U2NhbGUsXG4gICAgICByYWRpdXNGaWVsZCxcbiAgICAgIHJhZGl1c0RvbWFpbixcbiAgICAgIHJhZGl1c1NjYWxlLFxuICAgICAgdmlzQ29uZmlnXG4gICAgfSA9IHRoaXMuY29uZmlnO1xuXG4gICAgY29uc3Qge1xuICAgICAgZW5hYmxlM2QsXG4gICAgICBzdHJva2VkLFxuICAgICAgY29sb3JSYW5nZSxcbiAgICAgIGhlaWdodFJhbmdlLFxuICAgICAgc2l6ZVJhbmdlLFxuICAgICAgcmFkaXVzUmFuZ2UsXG4gICAgICBzdHJva2VDb2xvclJhbmdlLFxuICAgICAgc3Ryb2tlQ29sb3JcbiAgICB9ID0gdmlzQ29uZmlnO1xuXG4gICAgY29uc3QgZ2V0RmVhdHVyZSA9IHRoaXMuZ2V0UG9zaXRpb25BY2Nlc3Nvcih0aGlzLmNvbmZpZy5jb2x1bW4pO1xuXG4gICAgLy8gZ2VvanNvbiBmZWF0dXJlIGFyZSBvYmplY3QsIGlmIGRvZXNuJ3QgZXhpc3RzXG4gICAgLy8gY3JlYXRlIGl0IGFuZCBzYXZlIHRvIGxheWVyXG4gICAgaWYgKCFvbGRMYXllckRhdGEgfHwgb2xkTGF5ZXJEYXRhLmdldEZlYXR1cmUgIT09IGdldEZlYXR1cmUpIHtcbiAgICAgIHRoaXMudXBkYXRlTGF5ZXJNZXRhKGFsbERhdGEsIGdldEZlYXR1cmUpO1xuICAgIH1cblxuICAgIGxldCBnZW9qc29uRGF0YTtcblxuICAgIGlmIChcbiAgICAgIG9sZExheWVyRGF0YSAmJlxuICAgICAgb2xkTGF5ZXJEYXRhLmRhdGEgJiZcbiAgICAgIG9wdC5zYW1lRGF0YSAmJlxuICAgICAgb2xkTGF5ZXJEYXRhLmdldEZlYXR1cmUgPT09IGdldEZlYXR1cmVcbiAgICApIHtcbiAgICAgIC8vIG5vIG5lZWQgdG8gY3JlYXRlIGEgbmV3IGFycmF5IG9mIGRhdGFcbiAgICAgIC8vIHVzZSB1cGRhdGVUcmlnZ2VycyB0byBzZWxlY3RpdmVseSByZS1jYWxjdWxhdGUgYXR0cmlidXRlc1xuICAgICAgZ2VvanNvbkRhdGEgPSBvbGRMYXllckRhdGEuZGF0YTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gZmlsdGVyZWRJbmRleCBpcyBhIHJlZmVyZW5jZSBvZiBpbmRleCBpbiBhbGxEYXRhIHdoaWNoIGNhbiBtYXAgdG8gZmVhdHVyZVxuICAgICAgZ2VvanNvbkRhdGEgPSBmaWx0ZXJlZEluZGV4XG4gICAgICAgIC5tYXAoaSA9PiB0aGlzLmRhdGFUb0ZlYXR1cmVbaV0pXG4gICAgICAgIC5maWx0ZXIoZCA9PiBkKTtcbiAgICB9XG5cbiAgICAvLyBmaWxsIGNvbG9yXG4gICAgY29uc3QgY1NjYWxlID1cbiAgICAgIGNvbG9yRmllbGQgJiZcbiAgICAgIHRoaXMuZ2V0VmlzQ2hhbm5lbFNjYWxlKFxuICAgICAgICBjb2xvclNjYWxlLFxuICAgICAgICBjb2xvckRvbWFpbixcbiAgICAgICAgY29sb3JSYW5nZS5jb2xvcnMubWFwKGhleFRvUmdiKVxuICAgICAgKTtcblxuICAgIC8vIHN0cm9rZSBjb2xvclxuICAgIGNvbnN0IHNjU2NhbGUgPVxuICAgICAgc3Ryb2tlQ29sb3JGaWVsZCAmJlxuICAgICAgdGhpcy5nZXRWaXNDaGFubmVsU2NhbGUoXG4gICAgICAgIHN0cm9rZUNvbG9yU2NhbGUsXG4gICAgICAgIHN0cm9rZUNvbG9yRG9tYWluLFxuICAgICAgICBzdHJva2VDb2xvclJhbmdlLmNvbG9ycy5tYXAoaGV4VG9SZ2IpXG4gICAgICApO1xuICAgIC8vIGNhbGN1bGF0ZSBzdHJva2Ugc2NhbGUgLSBpZiBzdHJva2VkID0gdHJ1ZVxuICAgIGNvbnN0IHNTY2FsZSA9XG4gICAgICBzaXplRmllbGQgJiZcbiAgICAgIHN0cm9rZWQgJiZcbiAgICAgIHRoaXMuZ2V0VmlzQ2hhbm5lbFNjYWxlKHNpemVTY2FsZSwgc2l6ZURvbWFpbiwgc2l6ZVJhbmdlKTtcblxuICAgIC8vIGNhbGN1bGF0ZSBlbGV2YXRpb24gc2NhbGUgLSBpZiBleHRydWRlZCA9IHRydWVcbiAgICBjb25zdCBlU2NhbGUgPVxuICAgICAgaGVpZ2h0RmllbGQgJiZcbiAgICAgIGVuYWJsZTNkICYmXG4gICAgICB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShoZWlnaHRTY2FsZSwgaGVpZ2h0RG9tYWluLCBoZWlnaHRSYW5nZSk7XG4gICAgLy8gY29uc29sZS5sb2coJ2VTY2FsZSBpbnNpZGUgZm9ybWF0TGF5ZXJEYXRhJywgZVNjYWxlKTtcbiAgICAvLyBwb2ludCByYWRpdXNcbiAgICBjb25zdCByU2NhbGUgPVxuICAgICAgcmFkaXVzRmllbGQgJiZcbiAgICAgIHRoaXMuZ2V0VmlzQ2hhbm5lbFNjYWxlKHJhZGl1c1NjYWxlLCByYWRpdXNEb21haW4sIHJhZGl1c1JhbmdlKTtcblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiBnZW9qc29uRGF0YSxcbiAgICAgIGdldEZlYXR1cmUsXG4gICAgICBnZXRGaWxsQ29sb3I6IGQgPT5cbiAgICAgICAgY1NjYWxlXG4gICAgICAgICAgPyB0aGlzLmdldEVuY29kZWRDaGFubmVsVmFsdWUoXG4gICAgICAgICAgICAgIGNTY2FsZSxcbiAgICAgICAgICAgICAgYWxsRGF0YVtkLnByb3BlcnRpZXMuaW5kZXhdLFxuICAgICAgICAgICAgICBjb2xvckZpZWxkXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBkLnByb3BlcnRpZXMuZmlsbENvbG9yIHx8IGNvbG9yLFxuICAgICAgZ2V0TGluZUNvbG9yOiBkID0+XG4gICAgICAgIHNjU2NhbGVcbiAgICAgICAgICA/IHRoaXMuZ2V0RW5jb2RlZENoYW5uZWxWYWx1ZShcbiAgICAgICAgICAgICAgc2NTY2FsZSxcbiAgICAgICAgICAgICAgYWxsRGF0YVtkLnByb3BlcnRpZXMuaW5kZXhdLFxuICAgICAgICAgICAgICBzdHJva2VDb2xvckZpZWxkXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBkLnByb3BlcnRpZXMubGluZUNvbG9yIHx8IHN0cm9rZUNvbG9yIHx8IGNvbG9yLFxuICAgICAgZ2V0TGluZVdpZHRoOiBkID0+XG4gICAgICAgIHNTY2FsZVxuICAgICAgICAgID8gdGhpcy5nZXRFbmNvZGVkQ2hhbm5lbFZhbHVlKFxuICAgICAgICAgICAgICBzU2NhbGUsXG4gICAgICAgICAgICAgIGFsbERhdGFbZC5wcm9wZXJ0aWVzLmluZGV4XSxcbiAgICAgICAgICAgICAgc2l6ZUZpZWxkLFxuICAgICAgICAgICAgICAwXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBkLnByb3BlcnRpZXMubGluZVdpZHRoIHx8IDEsXG4gICAgICBnZXRFbGV2YXRpb246IGQgPT5cbiAgICAgICAgZVNjYWxlXG4gICAgICAgICAgPyB0aGlzLmdldEVuY29kZWRDaGFubmVsVmFsdWUoXG4gICAgICAgICAgICAgIGVTY2FsZSxcbiAgICAgICAgICAgICAgYWxsRGF0YVtkLnByb3BlcnRpZXMuaW5kZXhdLFxuICAgICAgICAgICAgICBoZWlnaHRGaWVsZCxcbiAgICAgICAgICAgICAgMFxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogZC5wcm9wZXJ0aWVzLmVsZXZhdGlvbiB8fCA1MDAsXG4gICAgICBnZXRSYWRpdXM6IGQgPT5cbiAgICAgICAgclNjYWxlXG4gICAgICAgICAgPyB0aGlzLmdldEVuY29kZWRDaGFubmVsVmFsdWUoXG4gICAgICAgICAgICAgIHJTY2FsZSxcbiAgICAgICAgICAgICAgYWxsRGF0YVtkLnByb3BlcnRpZXMuaW5kZXhdLFxuICAgICAgICAgICAgICByYWRpdXNGaWVsZCxcbiAgICAgICAgICAgICAgMFxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogZC5wcm9wZXJ0aWVzLnJhZGl1cyB8fCAxXG4gICAgfTtcbiAgfVxuICAvKiBlc2xpbnQtZW5hYmxlIGNvbXBsZXhpdHkgKi9cblxuICB1cGRhdGVMYXllck1ldGEoYWxsRGF0YSkge1xuICAgIGNvbnN0IGdldEZlYXR1cmUgPSB0aGlzLmdldFBvc2l0aW9uQWNjZXNzb3IoKTtcbiAgICB0aGlzLmRhdGFUb0ZlYXR1cmUgPSBnZXRHZW9qc29uRGF0YU1hcHMoYWxsRGF0YSwgZ2V0RmVhdHVyZSk7XG5cbiAgICAvLyBnZXQgYm91bmRzIGZyb20gZmVhdHVyZXNcbiAgICBjb25zdCBib3VuZHMgPSBnZXRHZW9qc29uQm91bmRzKHRoaXMuZGF0YVRvRmVhdHVyZSk7XG5cbiAgICAvLyBpZiBhbnkgb2YgdGhlIGZlYXR1cmUgaGFzIHByb3BlcnRpZXMucmFkaXVzIHNldCB0byBiZSB0cnVlXG4gICAgY29uc3QgZml4ZWRSYWRpdXMgPSBCb29sZWFuKFxuICAgICAgdGhpcy5kYXRhVG9GZWF0dXJlLmZpbmQoZCA9PiBkICYmIGQucHJvcGVydGllcyAmJiBkLnByb3BlcnRpZXMucmFkaXVzKVxuICAgICk7XG5cbiAgICAvLyBrZWVwIGEgcmVjb3JkIG9mIHdoYXQgdHlwZSBvZiBnZW9tZXRyeSB0aGUgY29sbGVjdGlvbiBoYXNcbiAgICBjb25zdCBmZWF0dXJlVHlwZXMgPSBnZXRHZW9qc29uRmVhdHVyZVR5cGVzKHRoaXMuZGF0YVRvRmVhdHVyZSk7XG5cbiAgICB0aGlzLnVwZGF0ZU1ldGEoe2JvdW5kcywgZml4ZWRSYWRpdXMsIGZlYXR1cmVUeXBlc30pO1xuICB9XG5cbiAgc2V0SW5pdGlhbExheWVyQ29uZmlnKGFsbERhdGEpIHtcbiAgICB0aGlzLnVwZGF0ZUxheWVyTWV0YShhbGxEYXRhKTtcblxuICAgIGNvbnN0IHtmZWF0dXJlVHlwZXN9ID0gdGhpcy5tZXRhO1xuIC