kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
428 lines (374 loc) • 49.6 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.featureResolver = exports.featureAccessor = exports.geoJsonRequiredColumns = exports.geojsonVisConfigs = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _lodash = _interopRequireDefault(require("lodash.memoize"));
var _lodash2 = _interopRequireDefault(require("lodash.uniq"));
var _baseLayer = _interopRequireDefault(require("../base-layer"));
var _solidPolygonLayer = _interopRequireDefault(require("../../deckgl-layers/geojson-layer/solid-polygon-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 ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var geojsonVisConfigs = {
opacity: 'opacity',
thickness: {
type: 'number',
defaultValue: 0.5,
label: 'Stroke Width',
isRanged: false,
range: [0, 100],
step: 0.1,
group: 'stroke',
property: 'thickness'
},
colorRange: 'colorRange',
radius: 'radius',
sizeRange: 'strokeWidthRange',
radiusRange: 'radiusRange',
heightRange: 'elevationRange',
elevationScale: 'elevationScale',
'hi-precision': 'hi-precision',
stroked: 'stroked',
filled: 'filled',
enable3d: 'enable3d',
wireframe: 'wireframe'
};
exports.geojsonVisConfigs = geojsonVisConfigs;
var geoJsonRequiredColumns = ['geojson'];
exports.geoJsonRequiredColumns = geoJsonRequiredColumns;
var featureAccessor = function featureAccessor(_ref) {
var geojson = _ref.geojson;
return function (d) {
return d[geojson.fieldIdx];
};
};
exports.featureAccessor = featureAccessor;
var featureResolver = function featureResolver(_ref2) {
var geojson = _ref2.geojson;
return geojson.fieldIdx;
};
exports.featureResolver = featureResolver;
var GeoJsonLayer =
/*#__PURE__*/
function (_Layer) {
(0, _inherits2["default"])(GeoJsonLayer, _Layer);
function GeoJsonLayer(props) {
var _this;
(0, _classCallCheck2["default"])(this, GeoJsonLayer);
_this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(GeoJsonLayer).call(this, props));
_this.dataToFeature = {};
_this.registerVisConfig(geojsonVisConfigs);
_this.getFeature = (0, _lodash["default"])(featureAccessor, featureResolver);
return _this;
}
(0, _createClass2["default"])(GeoJsonLayer, [{
key: "getDefaultLayerConfig",
value: function getDefaultLayerConfig() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return _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'
});
}
}, {
key: "getHoverData",
value: function getHoverData(object, allData) {
// index of allData is saved to feature.properties
return allData[object.properties.index];
} // 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,
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,
columns = _this$config.columns;
var enable3d = visConfig.enable3d,
stroked = visConfig.stroked,
colorRange = visConfig.colorRange,
heightRange = visConfig.heightRange,
sizeRange = visConfig.sizeRange,
radiusRange = visConfig.radiusRange;
var getFeature = this.getFeature(columns); // 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;
});
}
var cScale = colorField && this.getVisChannelScale(colorScale, colorDomain, colorRange.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 cScale ? _this2.getEncodedChannelValue(cScale, allData[d.properties.index], colorField) : d.properties.lineColor || 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, getFeature) {
this.dataToFeature = (0, _geojsonUtils.getGeojsonDataMaps)(allData, getFeature); // calculate layer meta
var allFeatures = Object.values(this.dataToFeature); // get bounds from features
var bounds = (0, _geojsonUtils.getGeojsonBounds)(allFeatures); // get lightSettings from points
var lightSettings = this.getLightSettingsFromBounds(bounds); // if any of the feature has properties.hi-precision set to be true
var fp64 = Boolean(allFeatures.find(function (d) {
return d && d.properties && d.properties['hi-precision'];
}));
var fixedRadius = Boolean(allFeatures.find(function (d) {
return d && d.properties && d.properties.radius;
})); // keep a record of what type of geometry the collection has
var featureTypes = allFeatures.reduce(function (accu, f) {
var geoType = (0, _geojsonUtils.featureToDeckGlGeoType)(f && f.geometry && f.geometry.type);
if (geoType) {
accu[geoType] = true;
}
return accu;
}, {});
this.updateMeta({
bounds: bounds,
lightSettings: lightSettings,
fp64: fp64,
fixedRadius: fixedRadius,
featureTypes: featureTypes
});
}
}, {
key: "renderLayer",
value: function renderLayer(_ref3) {
var data = _ref3.data,
idx = _ref3.idx,
objectHovered = _ref3.objectHovered,
mapState = _ref3.mapState,
interactionConfig = _ref3.interactionConfig;
var _this$meta = this.meta,
fp64 = _this$meta.fp64,
lightSettings = _this$meta.lightSettings,
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,
lineWidthMinPixels: 1,
elevationScale: visConfig.elevationScale,
pointRadiusScale: radiusScale,
fp64: fp64 || visConfig['hi-precision'],
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: this.config.color,
colorField: this.config.colorField,
colorRange: visConfig.colorRange,
colorScale: this.config.colorScale
},
getLineWidth: {
sizeField: this.config.sizeField,
sizeRange: visConfig.sizeRange
},
getRadius: {
radiusField: this.config.radiusField,
radiusRange: visConfig.radiusRange
}
};
return [new _deck.GeoJsonLayer(_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: this.config.highlightColor,
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,
lightSettings: lightSettings,
updateTriggers: updateTriggers,
subLayers: _objectSpread({}, _deck.GeoJsonLayer.defaultProps.subLayers, {
PolygonLayer: _solidPolygonLayer["default"]
})
}))].concat((0, _toConsumableArray2["default"])(this.isLayerHovered(objectHovered) && !visConfig.enable3d ? [new _deck.GeoJsonLayer(_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: "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({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(GeoJsonLayer.prototype), "visualChannels", this), {
size: _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: "findDefaultLayerProps",
value: function findDefaultLayerProps(_ref4) {
var _this3 = this;
var label = _ref4.label,
fields = _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 [];
}
return foundColumns.map(function (columns) {
return {
label: typeof label === 'string' && label.replace(/\.[^/.]+$/, '') || _this3.type,
columns: columns,
isVisible: true
};
});
}
}]);
return GeoJsonLayer;
}(_baseLayer["default"]);
exports["default"] = GeoJsonLayer;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvZ2VvanNvbi1sYXllci9nZW9qc29uLWxheWVyLmpzIl0sIm5hbWVzIjpbImdlb2pzb25WaXNDb25maWdzIiwib3BhY2l0eSIsInRoaWNrbmVzcyIsInR5cGUiLCJkZWZhdWx0VmFsdWUiLCJsYWJlbCIsImlzUmFuZ2VkIiwicmFuZ2UiLCJzdGVwIiwiZ3JvdXAiLCJwcm9wZXJ0eSIsImNvbG9yUmFuZ2UiLCJyYWRpdXMiLCJzaXplUmFuZ2UiLCJyYWRpdXNSYW5nZSIsImhlaWdodFJhbmdlIiwiZWxldmF0aW9uU2NhbGUiLCJzdHJva2VkIiwiZmlsbGVkIiwiZW5hYmxlM2QiLCJ3aXJlZnJhbWUiLCJnZW9Kc29uUmVxdWlyZWRDb2x1bW5zIiwiZmVhdHVyZUFjY2Vzc29yIiwiZ2VvanNvbiIsImQiLCJmaWVsZElkeCIsImZlYXR1cmVSZXNvbHZlciIsIkdlb0pzb25MYXllciIsInByb3BzIiwiZGF0YVRvRmVhdHVyZSIsInJlZ2lzdGVyVmlzQ29uZmlnIiwiZ2V0RmVhdHVyZSIsImhlaWdodEZpZWxkIiwiaGVpZ2h0RG9tYWluIiwiaGVpZ2h0U2NhbGUiLCJyYWRpdXNGaWVsZCIsInJhZGl1c0RvbWFpbiIsInJhZGl1c1NjYWxlIiwib2JqZWN0IiwiYWxsRGF0YSIsInByb3BlcnRpZXMiLCJpbmRleCIsIl8iLCJmaWx0ZXJlZEluZGV4Iiwib2xkTGF5ZXJEYXRhIiwib3B0IiwiY29uZmlnIiwiY29sb3JTY2FsZSIsImNvbG9yRmllbGQiLCJjb2xvckRvbWFpbiIsImNvbG9yIiwic2l6ZVNjYWxlIiwic2l6ZURvbWFpbiIsInNpemVGaWVsZCIsInZpc0NvbmZpZyIsImNvbHVtbnMiLCJ1cGRhdGVMYXllck1ldGEiLCJnZW9qc29uRGF0YSIsImRhdGEiLCJzYW1lRGF0YSIsIm1hcCIsImkiLCJmaWx0ZXIiLCJjU2NhbGUiLCJnZXRWaXNDaGFubmVsU2NhbGUiLCJjb2xvcnMiLCJoZXhUb1JnYiIsInNTY2FsZSIsImVTY2FsZSIsInJTY2FsZSIsImdldEZpbGxDb2xvciIsImdldEVuY29kZWRDaGFubmVsVmFsdWUiLCJmaWxsQ29sb3IiLCJnZXRMaW5lQ29sb3IiLCJsaW5lQ29sb3IiLCJnZXRMaW5lV2lkdGgiLCJsaW5lV2lkdGgiLCJnZXRFbGV2YXRpb24iLCJlbGV2YXRpb24iLCJnZXRSYWRpdXMiLCJhbGxGZWF0dXJlcyIsIk9iamVjdCIsInZhbHVlcyIsImJvdW5kcyIsImxpZ2h0U2V0dGluZ3MiLCJnZXRMaWdodFNldHRpbmdzRnJvbUJvdW5kcyIsImZwNjQiLCJCb29sZWFuIiwiZmluZCIsImZpeGVkUmFkaXVzIiwiZmVhdHVyZVR5cGVzIiwicmVkdWNlIiwiYWNjdSIsImYiLCJnZW9UeXBlIiwiZ2VvbWV0cnkiLCJ1cGRhdGVNZXRhIiwiaWR4Iiwib2JqZWN0SG92ZXJlZCIsIm1hcFN0YXRlIiwiaW50ZXJhY3Rpb25Db25maWciLCJtZXRhIiwiZ2V0UmFkaXVzU2NhbGVCeVpvb20iLCJ6b29tRmFjdG9yIiwiZ2V0Wm9vbUZhY3RvciIsImxheWVyUHJvcHMiLCJsaW5lV2lkdGhTY2FsZSIsImxpbmVXaWR0aE1pblBpeGVscyIsInBvaW50UmFkaXVzU2NhbGUiLCJsaW5lTWl0ZXJMaW1pdCIsInVwZGF0ZVRyaWdnZXJzIiwiRGVja0dMR2VvSnNvbkxheWVyIiwiaWQiLCJwaWNrYWJsZSIsImF1dG9IaWdobGlnaHQiLCJwYXJhbWV0ZXJzIiwiZGVwdGhUZXN0IiwiZHJhZ1JvdGF0ZSIsImV4dHJ1ZGVkIiwic3ViTGF5ZXJzIiwiZGVmYXVsdFByb3BzIiwiUG9seWdvbkxheWVyIiwiSGlnaGxpZ2h0UG9seWdvbkxheWVyIiwiaXNMYXllckhvdmVyZWQiLCJoaWdobGlnaHRDb2xvciIsIkdlb2pzb25MYXllckljb24iLCJzaXplIiwiY29uZGl0aW9uIiwiaGVpZ2h0IiwiZmllbGQiLCJzY2FsZSIsImRvbWFpbiIsImtleSIsImNoYW5uZWxTY2FsZVR5cGUiLCJmaWVsZHMiLCJnZW9qc29uQ29sdW1ucyIsIm5hbWUiLCJkZWZhdWx0Q29sdW1ucyIsIkdFT0pTT05fRklFTERTIiwiZm91bmRDb2x1bW5zIiwiZmluZERlZmF1bHRDb2x1bW5GaWVsZCIsImxlbmd0aCIsInJlcGxhY2UiLCJpc1Zpc2libGUiLCJMYXllciJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTs7QUFDQTs7QUFFQTs7QUFDQTs7QUFDQTs7QUFFQTs7QUFDQTs7QUFLQTs7QUFDQTs7Ozs7O0FBRU8sSUFBTUEsaUJBQWlCLEdBQUc7QUFDL0JDLEVBQUFBLE9BQU8sRUFBRSxTQURzQjtBQUUvQkMsRUFBQUEsU0FBUyxFQUFFO0FBQ1RDLElBQUFBLElBQUksRUFBRSxRQURHO0FBRVRDLElBQUFBLFlBQVksRUFBRSxHQUZMO0FBR1RDLElBQUFBLEtBQUssRUFBRSxjQUhFO0FBSVRDLElBQUFBLFFBQVEsRUFBRSxLQUpEO0FBS1RDLElBQUFBLEtBQUssRUFBRSxDQUFDLENBQUQsRUFBSSxHQUFKLENBTEU7QUFNVEMsSUFBQUEsSUFBSSxFQUFFLEdBTkc7QUFPVEMsSUFBQUEsS0FBSyxFQUFFLFFBUEU7QUFRVEMsSUFBQUEsUUFBUSxFQUFFO0FBUkQsR0FGb0I7QUFZL0JDLEVBQUFBLFVBQVUsRUFBRSxZQVptQjtBQWEvQkMsRUFBQUEsTUFBTSxFQUFFLFFBYnVCO0FBZS9CQyxFQUFBQSxTQUFTLEVBQUUsa0JBZm9CO0FBZ0IvQkMsRUFBQUEsV0FBVyxFQUFFLGFBaEJrQjtBQWlCL0JDLEVBQUFBLFdBQVcsRUFBRSxnQkFqQmtCO0FBa0IvQkMsRUFBQUEsY0FBYyxFQUFFLGdCQWxCZTtBQW9CL0Isa0JBQWdCLGNBcEJlO0FBcUIvQkMsRUFBQUEsT0FBTyxFQUFFLFNBckJzQjtBQXNCL0JDLEVBQUFBLE1BQU0sRUFBRSxRQXRCdUI7QUF1Qi9CQyxFQUFBQSxRQUFRLEVBQUUsVUF2QnFCO0FBd0IvQkMsRUFBQUEsU0FBUyxFQUFFO0FBeEJvQixDQUExQjs7QUEyQkEsSUFBTUMsc0JBQXNCLEdBQUcsQ0FBQyxTQUFELENBQS9COzs7QUFDQSxJQUFNQyxlQUFlLEdBQUcsU0FBbEJBLGVBQWtCO0FBQUEsTUFBRUMsT0FBRixRQUFFQSxPQUFGO0FBQUEsU0FBZSxVQUFBQyxDQUFDO0FBQUEsV0FBSUEsQ0FBQyxDQUFDRCxPQUFPLENBQUNFLFFBQVQsQ0FBTDtBQUFBLEdBQWhCO0FBQUEsQ0FBeEI7Ozs7QUFDQSxJQUFNQyxlQUFlLEdBQUcsU0FBbEJBLGVBQWtCO0FBQUEsTUFBRUgsT0FBRixTQUFFQSxPQUFGO0FBQUEsU0FBZUEsT0FBTyxDQUFDRSxRQUF2QjtBQUFBLENBQXhCOzs7O0lBRWNFLFk7Ozs7O0FBQ25CLHdCQUFZQyxLQUFaLEVBQW1CO0FBQUE7O0FBQUE7QUFDakIsd0hBQU1BLEtBQU47QUFFQSxVQUFLQyxhQUFMLEdBQXFCLEVBQXJCOztBQUNBLFVBQUtDLGlCQUFMLENBQXVCOUIsaUJBQXZCOztBQUNBLFVBQUsrQixVQUFMLEdBQWtCLHdCQUFRVCxlQUFSLEVBQXlCSSxlQUF6QixDQUFsQjtBQUxpQjtBQU1sQjs7Ozs0Q0F1RWlDO0FBQUEsVUFBWkUsS0FBWSx1RUFBSixFQUFJO0FBQ2hDLHlKQUNpQ0EsS0FEakM7QUFHRTtBQUNBSSxRQUFBQSxXQUFXLEVBQUUsSUFKZjtBQUtFQyxRQUFBQSxZQUFZLEVBQUUsQ0FBQyxDQUFELEVBQUksQ0FBSixDQUxoQjtBQU1FQyxRQUFBQSxXQUFXLEVBQUUsUUFOZjtBQVFFO0FBQ0FDLFFBQUFBLFdBQVcsRUFBRSxJQVRmO0FBVUVDLFFBQUFBLFlBQVksRUFBRSxDQUFDLENBQUQsRUFBSSxDQUFKLENBVmhCO0FBV0VDLFFBQUFBLFdBQVcsRUFBRTtBQVhmO0FBYUQ7OztpQ0FFWUMsTSxFQUFRQyxPLEVBQVM7QUFDNUI7QUFDQSxhQUFPQSxPQUFPLENBQUNELE1BQU0sQ0FBQ0UsVUFBUCxDQUFrQkMsS0FBbkIsQ0FBZDtBQUNELEssQ0FFRDs7QUFDQTs7OztvQ0FDZ0JDLEMsRUFBR0gsTyxFQUFTSSxhLEVBQWVDLFksRUFBd0I7QUFBQTs7QUFBQSxVQUFWQyxHQUFVLHVFQUFKLEVBQUk7QUFBQSx5QkFpQjdELEtBQUtDLE1BakJ3RDtBQUFBLFVBRS9EQyxVQUYrRCxnQkFFL0RBLFVBRitEO0FBQUEsVUFHL0RDLFVBSCtELGdCQUcvREEsVUFIK0Q7QUFBQSxVQUkvREMsV0FKK0QsZ0JBSS9EQSxXQUorRDtBQUFBLFVBSy9EQyxLQUwrRCxnQkFLL0RBLEtBTCtEO0FBQUEsVUFNL0RDLFNBTitELGdCQU0vREEsU0FOK0Q7QUFBQSxVQU8vREMsVUFQK0QsZ0JBTy9EQSxVQVArRDtBQUFBLFVBUS9EQyxTQVIrRCxnQkFRL0RBLFNBUitEO0FBQUEsVUFTL0RyQixXQVQrRCxnQkFTL0RBLFdBVCtEO0FBQUEsVUFVL0RDLFlBVitELGdCQVUvREEsWUFWK0Q7QUFBQSxVQVcvREMsV0FYK0QsZ0JBVy9EQSxXQVgrRDtBQUFBLFVBWS9EQyxXQVorRCxnQkFZL0RBLFdBWitEO0FBQUEsVUFhL0RDLFlBYitELGdCQWEvREEsWUFiK0Q7QUFBQSxVQWMvREMsV0FkK0QsZ0JBYy9EQSxXQWQrRDtBQUFBLFVBZS9EaUIsU0FmK0QsZ0JBZS9EQSxTQWYrRDtBQUFBLFVBZ0IvREMsT0FoQitELGdCQWdCL0RBLE9BaEIrRDtBQUFBLFVBb0IvRHBDLFFBcEIrRCxHQTBCN0RtQyxTQTFCNkQsQ0FvQi9EbkMsUUFwQitEO0FBQUEsVUFxQi9ERixPQXJCK0QsR0EwQjdEcUMsU0ExQjZELENBcUIvRHJDLE9BckIrRDtBQUFBLFVBc0IvRE4sVUF0QitELEdBMEI3RDJDLFNBMUI2RCxDQXNCL0QzQyxVQXRCK0Q7QUFBQSxVQXVCL0RJLFdBdkIrRCxHQTBCN0R1QyxTQTFCNkQsQ0F1Qi9EdkMsV0F2QitEO0FBQUEsVUF3Qi9ERixTQXhCK0QsR0EwQjdEeUMsU0ExQjZELENBd0IvRHpDLFNBeEIrRDtBQUFBLFVBeUIvREMsV0F6QitELEdBMEI3RHdDLFNBMUI2RCxDQXlCL0R4QyxXQXpCK0Q7QUE0QmpFLFVBQU1pQixVQUFVLEdBQUcsS0FBS0EsVUFBTCxDQUFnQndCLE9BQWhCLENBQW5CLENBNUJpRSxDQTZCakU7QUFDQTs7QUFDQSxVQUFJLENBQUNYLFlBQUQsSUFBaUJBLFlBQVksQ0FBQ2IsVUFBYixLQUE0QkEsVUFBakQsRUFBNkQ7QUFDM0QsYUFBS3lCLGVBQUwsQ0FBcUJqQixPQUFyQixFQUE4QlIsVUFBOUI7QUFDRDs7QUFFRCxVQUFJMEIsV0FBSjs7QUFFQSxVQUNFYixZQUFZLElBQ1pBLFlBQVksQ0FBQ2MsSUFEYixJQUVBYixHQUFHLENBQUNjLFFBRkosSUFHQWYsWUFBWSxDQUFDYixVQUFiLEtBQTRCQSxVQUo5QixFQUtFO0FBQ0E7QUFDQTtBQUNBMEIsUUFBQUEsV0FBVyxHQUFHYixZQUFZLENBQUNjLElBQTNCO0FBQ0QsT0FURCxNQVNPO0FBQ0w7QUFDQUQsUUFBQUEsV0FBVyxHQUFHZCxhQUFhLENBQ3hCaUIsR0FEVyxDQUNQLFVBQUFDLENBQUM7QUFBQSxpQkFBSSxNQUFJLENBQUNoQyxhQUFMLENBQW1CZ0MsQ0FBbkIsQ0FBSjtBQUFBLFNBRE0sRUFFWEMsTUFGVyxDQUVKLFVBQUF0QyxDQUFDO0FBQUEsaUJBQUlBLENBQUo7QUFBQSxTQUZHLENBQWQ7QUFHRDs7QUFJRCxVQUFNdUMsTUFBTSxHQUNWZixVQUFVLElBQ1YsS0FBS2dCLGtCQUFMLENBQ0VqQixVQURGLEVBRUVFLFdBRkYsRUFHRXRDLFVBQVUsQ0FBQ3NELE1BQVgsQ0FBa0JMLEdBQWxCLENBQXNCTSxvQkFBdEIsQ0FIRixDQUZGLENBdkRpRSxDQStEakU7O0FBQ0EsVUFBTUMsTUFBTSxHQUNWZCxTQUFTLElBQ1RwQyxPQURBLElBRUEsS0FBSytDLGtCQUFMLENBQXdCYixTQUF4QixFQUFtQ0MsVUFBbkMsRUFBK0N2QyxTQUEvQyxDQUhGLENBaEVpRSxDQXFFakU7O0FBQ0EsVUFBTXVELE1BQU0sR0FDVnBDLFdBQVcsSUFDWGIsUUFEQSxJQUVBLEtBQUs2QyxrQkFBTCxDQUF3QjlCLFdBQXhCLEVBQXFDRCxZQUFyQyxFQUFtRGxCLFdBQW5ELENBSEYsQ0F0RWlFLENBMEVqRTtBQUNBOztBQUNBLFVBQU1zRCxNQUFNLEdBQ1ZsQyxXQUFXLElBQ1gsS0FBSzZCLGtCQUFMLENBQXdCM0IsV0FBeEIsRUFBcUNELFlBQXJDLEVBQW1EdEIsV0FBbkQsQ0FGRjtBQUlBLGFBQU87QUFDTDRDLFFBQUFBLElBQUksRUFBRUQsV0FERDtBQUVMMUIsUUFBQUEsVUFBVSxFQUFWQSxVQUZLO0FBR0x1QyxRQUFBQSxZQUFZLEVBQUUsc0JBQUE5QyxDQUFDO0FBQUEsaUJBQ2J1QyxNQUFNLEdBQ0YsTUFBSSxDQUFDUSxzQkFBTCxDQUNFUixNQURGLEVBRUV4QixPQUFPLENBQUNmLENBQUMsQ0FBQ2dCLFVBQUYsQ0FBYUMsS0FBZCxDQUZULEVBR0VPLFVBSEYsQ0FERSxHQU1GeEIsQ0FBQyxDQUFDZ0IsVUFBRixDQUFhZ0MsU0FBYixJQUEwQnRCLEtBUGpCO0FBQUEsU0FIVjtBQVdMdUIsUUFBQUEsWUFBWSxFQUFFLHNCQUFBakQsQ0FBQztBQUFBLGlCQUNidUMsTUFBTSxHQUNGLE1BQUksQ0FBQ1Esc0JBQUwsQ0FDRVIsTUFERixFQUVFeEIsT0FBTyxDQUFDZixDQUFDLENBQUNnQixVQUFGLENBQWFDLEtBQWQsQ0FGVCxFQUdFTyxVQUhGLENBREUsR0FNRnhCLENBQUMsQ0FBQ2dCLFVBQUYsQ0FBYWtDLFNBQWIsSUFBMEJ4QixLQVBqQjtBQUFBLFNBWFY7QUFtQkx5QixRQUFBQSxZQUFZLEVBQUUsc0JBQUFuRCxDQUFDO0FBQUEsaUJBQ2IyQyxNQUFNLEdBQ0YsTUFBSSxDQUFDSSxzQkFBTCxDQUNFSixNQURGLEVBRUU1QixPQUFPLENBQUNmLENBQUMsQ0FBQ2dCLFVBQUYsQ0FBYUMsS0FBZCxDQUZULEVBR0VZLFNBSEYsRUFJRSxDQUpGLENBREUsR0FPRjdCLENBQUMsQ0FBQ2dCLFVBQUYsQ0FBYW9DLFNBQWIsSUFBMEIsQ0FSakI7QUFBQSxTQW5CVjtBQTRCTEMsUUFBQUEsWUFBWSxFQUFFLHNCQUFBckQsQ0FBQztBQUFBLGlCQUNiNEMsTUFBTSxHQUNGLE1BQUksQ0FBQ0csc0JBQUwsQ0FDRUgsTUFERixFQUVFN0IsT0FBTyxDQUFDZixDQUFDLENBQUNnQixVQUFGLENBQWFDLEtBQWQsQ0FGVCxFQUdFVCxXQUhGLEVBSUUsQ0FKRixDQURFLEdBT0ZSLENBQUMsQ0FBQ2dCLFVBQUYsQ0FBYXNDLFNBQWIsSUFBMEIsR0FSakI7QUFBQSxTQTVCVjtBQXFDTEMsUUFBQUEsU0FBUyxFQUFFLG1CQUFBdkQsQ0FBQztBQUFBLGlCQUNWNkMsTUFBTSxHQUNGLE1BQUksQ0FBQ0Usc0JBQUwsQ0FDRUYsTUFERixFQUVFOUIsT0FBTyxDQUFDZixDQUFDLENBQUNnQixVQUFGLENBQWFDLEtBQWQsQ0FGVCxFQUdFTixXQUhGLEVBSUUsQ0FKRixDQURFLEdBT0ZYLENBQUMsQ0FBQ2dCLFVBQUYsQ0FBYTVCLE1BQWIsSUFBdUIsQ0FSakI7QUFBQTtBQXJDUCxPQUFQO0FBK0NEO0FBQ0Q7Ozs7b0NBRWdCMkIsTyxFQUFTUixVLEVBQVk7QUFDbkMsV0FBS0YsYUFBTCxHQUFxQixzQ0FBbUJVLE9BQW5CLEVBQTRCUixVQUE1QixDQUFyQixDQURtQyxDQUduQzs7QUFDQSxVQUFNaUQsV0FBVyxHQUFHQyxNQUFNLENBQUNDLE1BQVAsQ0FBYyxLQUFLckQsYUFBbkIsQ0FBcEIsQ0FKbUMsQ0FNbkM7O0FBQ0EsVUFBTXNELE1BQU0sR0FBRyxvQ0FBaUJILFdBQWpCLENBQWYsQ0FQbUMsQ0FTbkM7O0FBQ0EsVUFBTUksYUFBYSxHQUFHLEtBQUtDLDBCQUFMLENBQWdDRixNQUFoQyxDQUF0QixDQVZtQyxDQVluQzs7QUFDQSxVQUFNRyxJQUFJLEdBQUdDLE9BQU8sQ0FDbEJQLFdBQVcsQ0FBQ1EsSUFBWixDQUFpQixVQUFBaEUsQ0FBQztBQUFBLGVBQUlBLENBQUMsSUFBSUEsQ0FBQyxDQUFDZ0IsVUFBUCxJQUFxQmhCLENBQUMsQ0FBQ2dCLFVBQUYsQ0FBYSxjQUFiLENBQXpCO0FBQUEsT0FBbEIsQ0FEa0IsQ0FBcEI7QUFHQSxVQUFNaUQsV0FBVyxHQUFHRixPQUFPLENBQ3pCUCxXQUFXLENBQUNRLElBQVosQ0FBaUIsVUFBQWhFLENBQUM7QUFBQSxlQUFJQSxDQUFDLElBQUlBLENBQUMsQ0FBQ2dCLFVBQVAsSUFBcUJoQixDQUFDLENBQUNnQixVQUFGLENBQWE1QixNQUF0QztBQUFBLE9BQWxCLENBRHlCLENBQTNCLENBaEJtQyxDQW9CbkM7O0FBQ0EsVUFBTThFLFlBQVksR0FBR1YsV0FBVyxDQUFDVyxNQUFaLENBQW1CLFVBQUNDLElBQUQsRUFBT0MsQ0FBUCxFQUFhO0FBQ25ELFlBQU1DLE9BQU8sR0FBRywwQ0FDZEQsQ0FBQyxJQUFJQSxDQUFDLENBQUNFLFFBQVAsSUFBbUJGLENBQUMsQ0FBQ0UsUUFBRixDQUFXNUYsSUFEaEIsQ0FBaEI7O0FBSUEsWUFBSTJGLE9BQUosRUFBYTtBQUNYRixVQUFBQSxJQUFJLENBQUNFLE9BQUQsQ0FBSixHQUFnQixJQUFoQjtBQUNEOztBQUNELGVBQU9GLElBQVA7QUFDRCxPQVRvQixFQVNsQixFQVRrQixDQUFyQjtBQVdBLFdBQUtJLFVBQUwsQ0FBZ0I7QUFBQ2IsUUFBQUEsTUFBTSxFQUFOQSxNQUFEO0FBQVNDLFFBQUFBLGFBQWEsRUFBYkEsYUFBVDtBQUF3QkUsUUFBQUEsSUFBSSxFQUFKQSxJQUF4QjtBQUE4QkcsUUFBQUEsV0FBVyxFQUFYQSxXQUE5QjtBQUEyQ0MsUUFBQUEsWUFBWSxFQUFaQTtBQUEzQyxPQUFoQjtBQUNEOzs7dUNBRW9FO0FBQUEsVUFBeERoQyxJQUF3RCxTQUF4REEsSUFBd0Q7QUFBQSxVQUFsRHVDLEdBQWtELFNBQWxEQSxHQUFrRDtBQUFBLFVBQTdDQyxhQUE2QyxTQUE3Q0EsYUFBNkM7QUFBQSxVQUE5QkMsUUFBOEIsU0FBOUJBLFFBQThCO0FBQUEsVUFBcEJDLGlCQUFvQixTQUFwQkEsaUJBQW9CO0FBQUEsdUJBQ3hCLEtBQUtDLElBRG1CO0FBQUEsVUFDNURmLElBRDRELGNBQzVEQSxJQUQ0RDtBQUFBLFVBQ3RERixhQURzRCxjQUN0REEsYUFEc0Q7QUFBQSxVQUN2Q0ssV0FEdUMsY0FDdkNBLFdBRHVDO0FBRW5FLFVBQU1wRCxXQUFXLEdBQUcsS0FBS2lFLG9CQUFMLENBQTBCSCxRQUExQixFQUFvQ1YsV0FBcEMsQ0FBcEI7QUFDQSxVQUFNYyxVQUFVLEdBQUcsS0FBS0MsYUFBTCxDQUFtQkwsUUFBbkIsQ0FBbkI7QUFIbUUsVUFJNUQ3QyxTQUo0RCxHQUkvQyxLQUFLUixNQUowQyxDQUk1RFEsU0FKNEQ7QUFNbkUsVUFBTW1ELFVBQVUsR0FBRztBQUNqQjtBQUNBQyxRQUFBQSxjQUFjLEVBQUVwRCxTQUFTLENBQUNwRCxTQUFWLEdBQXNCcUcsVUFBdEIsR0FBbUMsQ0FGbEM7QUFHakJJLFFBQUFBLGtCQUFrQixFQUFFLENBSEg7QUFJakIzRixRQUFBQSxjQUFjLEVBQUVzQyxTQUFTLENBQUN0QyxjQUpUO0FBS2pCNEYsUUFBQUEsZ0JBQWdCLEVBQUV2RSxXQUxEO0FBTWpCaUQsUUFBQUEsSUFBSSxFQUFFQSxJQUFJLElBQUloQyxTQUFTLENBQUMsY0FBRCxDQU5OO0FBT2pCdUQsUUFBQUEsY0FBYyxFQUFFO0FBUEMsT0FBbkI7QUFVQSxVQUFNQyxjQUFjLEdBQUc7QUFDckJqQyxRQUFBQSxZQUFZLEVBQUU7QUFDWjdDLFVBQUFBLFdBQVcsRUFBRSxLQUFLYyxNQUFMLENBQVlkLFdBRGI7QUFFWkUsVUFBQUEsV0FBVyxFQUFFLEtBQUtZLE1BQUwsQ0FBWVosV0FGYjtBQUdabkIsVUFBQUEsV0FBVyxFQUFFdUMsU0FBUyxDQUFDdkM7QUFIWCxTQURPO0FBTXJCdUQsUUFBQUEsWUFBWSxFQUFFO0FBQ1pwQixVQUFBQSxLQUFLLEVBQUUsS0FBS0osTUFBTCxDQUFZSSxLQURQO0FBRVpGLFVBQUFBLFVBQVUsRUFBRSxLQUFLRixNQUFMLENBQVlFLFVBRlo7QUFHWnJDLFVBQUFBLFVBQVUsRUFBRTJDLFNBQVMsQ0FBQzNDLFVBSFY7QUFJWm9DLFVBQUFBLFVBQVUsRUFBRSxLQUFLRCxNQUFMLENBQVlDO0FBSlosU0FOTztBQVlyQjBCLFFBQUFBLFlBQVksRUFBRTtBQUNadkIsVUFBQUEsS0FBSyxFQUFFLEtBQUtKLE1BQUwsQ0FBWUksS0FEUDtBQUVaRixVQUFBQSxVQUFVLEVBQUUsS0FBS0YsTUFBTCxDQUFZRSxVQUZaO0FBR1pyQyxVQUFBQSxVQUFVLEVBQUUyQyxTQUFTLENBQUMzQyxVQUhWO0FBSVpvQyxVQUFBQSxVQUFVLEVBQUUsS0FBS0QsTUFBTCxDQUFZQztBQUpaLFNBWk87QUFrQnJCNEIsUUFBQUEsWUFBWSxFQUFFO0FBQ1p0QixVQUFBQSxTQUFTLEVBQUUsS0FBS1AsTUFBTCxDQUFZTyxTQURYO0FBRVp4QyxVQUFBQSxTQUFTLEVBQUV5QyxTQUFTLENBQUN6QztBQUZULFNBbEJPO0FBc0JyQmtFLFFBQUFBLFNBQVMsRUFBRTtBQUNUNUMsVUFBQUEsV0FBVyxFQUFFLEtBQUtXLE1BQUwsQ0FBWVgsV0FEaEI7QUFFVHJCLFVBQUFBLFdBQVcsRUFBRXdDLFNBQVMsQ0FBQ3hDO0FBRmQ7QUF0QlUsT0FBdkI7QUEyQkEsY0FDRSxJQUFJaUcsa0JBQUosbUJBQ0tOLFVBREw7QUFFRU8sUUFBQUEsRUFBRSxFQUFFLEtBQUtBLEVBRlg7QUFHRWYsUUFBQUEsR0FBRyxFQUFIQSxHQUhGO0FBSUV2QyxRQUFBQSxJQUFJLEVBQUVBLElBQUksQ0FBQ0EsSUFKYjtBQUtFWSxRQUFBQSxZQUFZLEVBQUVaLElBQUksQ0FBQ1ksWUFMckI7QUFNRUcsUUFBQUEsWUFBWSxFQUFFZixJQUFJLENBQUNlLFlBTnJCO0FBT0VFLFFBQUFBLFlBQVksRUFBRWpCLElBQUksQ0FBQ2lCLFlBUHJCO0FBUUVJLFFBQUFBLFNBQVMsRUFBRXJCLElBQUksQ0FBQ3FCLFNBUmxCO0FBU0VGLFFBQUFBLFlBQVksRUFBRW5CLElBQUksQ0FBQ21CLFlBVHJCO0FBVUU7QUFDQW9DLFFBQUFBLFFBQVEsRUFBRSxJQVhaO0FBWUU7QUFDQUMsUUFBQUEsYUFBYSxFQUFFNUQsU0FBUyxDQUFDbkMsUUFiM0I7QUFjRTtBQUNBZ0csUUFBQUEsVUFBVSxFQUFFO0FBQ1ZDLFVBQUFBLFNBQVMsRUFBRTdCLE9BQU8sQ0FBQ2pDLFNBQVMsQ0FBQ25DLFFBQVYsSUFBc0JnRixRQUFRLENBQUNrQixVQUFoQztBQURSLFNBZmQ7QUFrQkVwSCxRQUFBQSxPQUFPLEVBQUVxRCxTQUFTLENBQUNyRCxPQWxCckI7QUFtQkVnQixRQUFBQSxPQUFPLEVBQUVxQyxTQUFTLENBQUNyQyxPQW5CckI7QUFvQkVDLFFBQUFBLE1BQU0sRUFBRW9DLFNBQVMsQ0FBQ3BDLE1BcEJwQjtBQXFCRW9HLFFBQUFBLFFBQVEsRUFBRWhFLFNBQVMsQ0FBQ25DLFFBckJ0QjtBQXNCRUMsUUFBQUEsU0FBUyxFQUFFa0MsU0FBUyxDQUFDbEMsU0F0QnZCO0FBdUJFZ0UsUUFBQUEsYUFBYSxFQUFiQSxhQXZCRjtBQXdCRTBCLFFBQUFBLGNBQWMsRUFBZEEsY0F4QkY7QUEwQkVTLFFBQUFBLFNBQVMsb0JBQ0pSLG1CQUFtQlMsWUFBbkIsQ0FBZ0NELFNBRDVCO0FBRVBFLFVBQUFBLFlBQVksRUFBRUM7QUFGUDtBQTFCWCxTQURGLDZDQWdDTSxLQUFLQyxjQUFMLENBQW9CekIsYUFBcEIsS0FBc0MsQ0FBQzVDLFNBQVMsQ0FBQ25DLFFBQWpELEdBQ0EsQ0FDRSxJQUFJNEYsa0JBQUosbUJBQ0tOLFVBREw7QUFFRU8sUUFBQUEsRUFBRSxZQUFLLEtBQUtBLEVBQVYsYUFGSjtBQUdFdEQsUUFBQUEsSUFBSSxFQUFFLENBQUN3QyxhQUFhLENBQUM1RCxNQUFmLENBSFI7QUFJRXFDLFFBQUFBLFlBQVksRUFBRWpCLElBQUksQ0FBQ2lCLFlBSnJCO0FBS0VJLFFBQUFBLFNBQVMsRUFBRXJCLElBQUksQ0FBQ3FCLFNBTGxCO0FBTUVGLFFBQUFBLFlBQVksRUFBRW5CLElBQUksQ0FBQ21CLFlBTnJCO0FBT0VKLFFBQUFBLFlBQVksRUFBRSxLQUFLM0IsTUFBTCxDQUFZOEUsY0FQNUI7QUFRRXRELFFBQUFBLFlBQVksRUFBRSxLQUFLeEIsTUFBTCxDQUFZOEUsY0FSNUI7QUFTRWQsUUFBQUEsY0FBYyxFQUFkQSxjQVRGO0FBVUU3RixRQUFBQSxPQUFPLEVBQUUsSUFWWDtBQVdFZ0csUUFBQUEsUUFBUSxFQUFFLEtBWFo7QUFZRS9GLFFBQUFBLE1BQU0sRUFBRTtBQVpWLFNBREYsQ0FEQSxHQWlCQSxFQWpETjtBQW1ERDs7O3dCQS9WVTtBQUNULGFBQU8sU0FBUDtBQUNEOzs7d0JBRVU7QUFDVCxhQUFPLFNBQVA7QUFDRDs7O3dCQUVlO0FBQ2QsYUFBTzJHLDRCQUFQO0FBQ0Q7Ozt3QkFFMEI7QUFDekIsYUFBT3hHLHNCQUFQO0FBQ0Q7Ozt3QkFFb0I7QUFDbkI7QUFFRXlHLFFBQUFBLElBQUksb0JBQ0Msd0dBQXFCQSxJQUR0QjtBQUVGcEgsVUFBQUEsUUFBUSxFQUFFLFFBRlI7QUFHRnFILFVBQUFBLFNBQVMsRUFBRSxtQkFBQWpGLE1BQU07QUFBQSxtQkFBSUEsTUFBTSxDQUFDUSxTQUFQLENBQWlCckMsT0FBckI7QUFBQTtBQUhmLFVBRk47QUFPRStHLFFBQUFBLE1BQU0sRUFBRTtBQUNOdEgsVUFBQUEsUUFBUSxFQUFFLFFBREo7QUFFTnVILFVBQUFBLEtBQUssRUFBRSxhQUZEO0FBR05DLFVBQUFBLEtBQUssRUFBRSxhQUhEO0FBSU5DLFVBQUFBLE1BQU0sRUFBRSxjQUpGO0FBS041SCxVQUFBQSxLQUFLLEVBQUUsYUFMRDtBQU1ONkgsVUFBQUEsR0FBRyxFQUFFLFFBTkM7QUFPTkMsVUFBQUEsZ0JBQWdCLEVBQUUsTUFQWjtBQVFOTixVQUFBQSxTQUFTLEVBQUUsbUJBQUFqRixNQUFNO0FBQUEsbUJBQUlBLE1BQU0sQ0FBQ1EsU0FBUCxDQUFpQm5DLFFBQXJCO0FBQUE7QUFSWCxTQVBWO0FBaUJFUCxRQUFBQSxNQUFNLEVBQUU7QUFDTkYsVUFBQUEsUUFBUSxFQUFFLFFBREo7QUFFTnVILFVBQUFBLEtBQUssRUFBRSxhQUZEO0FBR05DLFVBQUFBLEtBQUssRUFBRSxhQUhEO0FBSU5DLFVBQUFBLE1BQU0sRUFBRSxjQUpGO0FBS041SCxVQUFBQSxLQUFLLEVBQUUsYUFMRDtBQU1ONkgsVUFBQUEsR0FBRyxFQUFFLFFBTkM7QUFPTkMsVUFBQUEsZ0JBQWdCLEVBQUU7QUFQWjtBQWpCVjtBQTJCRDs7O2lEQUU2QztBQUFBOztBQUFBLFVBQWhCaEksS0FBZ0IsU0FBaEJBLEtBQWdCO0FBQUEsVUFBVGlJLE1BQVMsU0FBVEEsTUFBUztBQUM1QyxVQUFNQyxjQUFjLEdBQUdELE1BQU0sQ0FDMUJ4RSxNQURvQixDQUNiLFVBQUErQixDQUFDO0FBQUEsZUFBSUEsQ0FBQyxDQUFDMUYsSUFBRixLQUFXLFNBQWY7QUFBQSxPQURZLEVBRXBCeUQsR0FGb0IsQ0FFaEIsVUFBQWlDLENBQUM7QUFBQSxlQUFJQSxDQUFDLENBQUMyQyxJQUFOO0FBQUEsT0FGZSxDQUF2QjtBQUlBLFVBQU1DLGNBQWMsR0FBRztBQUNyQmxILFFBQUFBLE9BQU8sRUFBRSx1RUFBU21ILGdDQUFlbkgsT0FBeEIsdUNBQW9DZ0gsY0FBcEM7QUFEWSxPQUF2QjtBQUlBLFVBQU1JLFlBQVksR0FBRyxLQUFLQyxzQkFBTCxDQUE0QkgsY0FBNUIsRUFBNENILE1BQTVDLENBQXJCOztBQUNBLFVBQUksQ0FBQ0ssWUFBRCxJQUFpQixDQUFDQSxZQUFZLENBQUNFLE1BQW5DLEVBQTJDO0FBQ3pDLGVBQU8sRUFBUDtBQUNEOztBQUVELGFBQU9GLFlBQVksQ0FBQy9FLEdBQWIsQ0FBaUIsVUFBQUwsT0FBTztBQUFBLGVBQUs7QUFDbENsRCxVQUFBQSxLQUFLLEVBQ0YsT0FBT0EsS0FBUCxLQUFpQixRQUFqQixJQUE2QkEsS0FBSyxDQUFDeUksT0FBTixDQUFjLFdBQWQsRUFBMkIsRUFBM0IsQ0FBOUIsSUFDQSxNQUFJLENBQUMzSSxJQUgyQjtBQUlsQ29ELFVBQUFBLE9BQU8sRUFBUEEsT0FKa0M7QUFLbEN3RixVQUFBQSxTQUFTLEVBQUU7QUFMdUIsU0FBTDtBQUFBLE9BQXhCLENBQVA7QUFPRDs7O0VBNUV1Q0MscUIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMTkgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgbWVtb2l6ZSBmcm9tICdsb2Rhc2gubWVtb2l6ZSc7XG5pbXBvcnQgdW5pcSBmcm9tICdsb2Rhc2gudW5pcSc7XG5cbmltcG9ydCBMYXllciBmcm9tICcuLi9iYXNlLWxheWVyJztcbmltcG9ydCBIaWdobGlnaHRQb2x5Z29uTGF5ZXIgZnJvbSAnZGVja2dsLWxheWVycy9nZW9qc29uLWxheWVyL3NvbGlkLXBvbHlnb24tbGF5ZXInO1xuaW1wb3J0IHtHZW9Kc29uTGF5ZXIgYXMgRGVja0dMR2VvSnNvbkxheWVyfSBmcm9tICdkZWNrLmdsJztcblxuaW1wb3J0IHtoZXhUb1JnYn0gZnJvbSAndXRpbHMvY29sb3ItdXRpbHMnO1xuaW1wb3J0IHtcbiAgZ2V0R2VvanNvbkRhdGFNYXBzLFxuICBnZXRHZW9qc29uQm91bmRzLFxuICBmZWF0dXJlVG9EZWNrR2xHZW9UeXBlXG59IGZyb20gJy4vZ2VvanNvbi11dGlscyc7XG5pbXBvcnQgR2VvanNvbkxheWVySWNvbiBmcm9tICcuL2dlb2pzb24tbGF5ZXItaWNvbic7XG5pbXBvcnQge0dFT0pTT05fRklFTERTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5cbmV4cG9ydCBjb25zdCBnZW9qc29uVmlzQ29uZmlncyA9IHtcbiAgb3BhY2l0eTogJ29wYWNpdHknLFxuICB0aGlja25lc3M6IHtcbiAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICBkZWZhdWx0VmFsdWU6IDAuNSxcbiAgICBsYWJlbDogJ1N0cm9rZSBXaWR0aCcsXG4gICAgaXNSYW5nZWQ6IGZhbHNlLFxuICAgIHJhbmdlOiBbMCwgMTAwXSxcbiAgICBzdGVwOiAwLjEsXG4gICAgZ3JvdXA6ICdzdHJva2UnLFxuICAgIHByb3BlcnR5OiAndGhpY2tuZXNzJ1xuICB9LFxuICBjb2xvclJhbmdlOiAnY29sb3JSYW5nZScsXG4gIHJhZGl1czogJ3JhZGl1cycsXG5cbiAgc2l6ZVJhbmdlOiAnc3Ryb2tlV2lkdGhSYW5nZScsXG4gIHJhZGl1c1JhbmdlOiAncmFkaXVzUmFuZ2UnLFxuICBoZWlnaHRSYW5nZTogJ2VsZXZhdGlvblJhbmdlJyxcbiAgZWxldmF0aW9uU2NhbGU6ICdlbGV2YXRpb25TY2FsZScsXG5cbiAgJ2hpLXByZWNpc2lvbic6ICdoaS1wcmVjaXNpb24nLFxuICBzdHJva2VkOiAnc3Ryb2tlZCcsXG4gIGZpbGxlZDogJ2ZpbGxlZCcsXG4gIGVuYWJsZTNkOiAnZW5hYmxlM2QnLFxuICB3aXJlZnJhbWU6ICd3aXJlZnJhbWUnXG59O1xuXG5leHBvcnQgY29uc3QgZ2VvSnNvblJlcXVpcmVkQ29sdW1ucyA9IFsnZ2VvanNvbiddO1xuZXhwb3J0IGNvbnN0IGZlYXR1cmVBY2Nlc3NvciA9ICh7Z2VvanNvbn0pID0+IGQgPT4gZFtnZW9qc29uLmZpZWxkSWR4XTtcbmV4cG9ydCBjb25zdCBmZWF0dXJlUmVzb2x2ZXIgPSAoe2dlb2pzb259KSA9PiBnZW9qc29uLmZpZWxkSWR4O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHZW9Kc29uTGF5ZXIgZXh0ZW5kcyBMYXllciB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpO1xuXG4gICAgdGhpcy5kYXRhVG9GZWF0dXJlID0ge307XG4gICAgdGhpcy5yZWdpc3RlclZpc0NvbmZpZyhnZW9qc29uVmlzQ29uZmlncyk7XG4gICAgdGhpcy5nZXRGZWF0dXJlID0gbWVtb2l6ZShmZWF0dXJlQWNjZXNzb3IsIGZlYXR1cmVSZXNvbHZlcik7XG4gIH1cblxuICBnZXQgdHlwZSgpIHtcbiAgICByZXR1cm4gJ2dlb2pzb24nO1xuICB9XG5cbiAgZ2V0IG5hbWUoKSB7XG4gICAgcmV0dXJuICdQb2x5Z29uJztcbiAgfVxuXG4gIGdldCBsYXllckljb24oKSB7XG4gICAgcmV0dXJuIEdlb2pzb25MYXllckljb247XG4gIH1cblxuICBnZXQgcmVxdWlyZWRMYXllckNvbHVtbnMoKSB7XG4gICAgcmV0dXJuIGdlb0pzb25SZXF1aXJlZENvbHVtbnM7XG4gIH1cblxuICBnZXQgdmlzdWFsQ2hhbm5lbHMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnN1cGVyLnZpc3VhbENoYW5uZWxzLFxuICAgICAgc2l6ZToge1xuICAgICAgICAuLi5zdXBlci52aXN1YWxDaGFubmVscy5zaXplLFxuICAgICAgICBwcm9wZXJ0eTogJ3N0cm9rZScsXG4gICAgICAgIGNvbmRpdGlvbjogY29uZmlnID0+IGNvbmZpZy52aXNDb25maWcuc3Ryb2tlZFxuICAgICAgfSxcbiAgICAgIGhlaWdodDoge1xuICAgICAgICBwcm9wZXJ0eTogJ2hlaWdodCcsXG4gICAgICAgIGZpZWxkOiAnaGVpZ2h0RmllbGQnLFxuICAgICAgICBzY2FsZTogJ2hlaWdodFNjYWxlJyxcbiAgICAgICAgZG9tYWluOiAnaGVpZ2h0RG9tYWluJyxcbiAgICAgICAgcmFuZ2U6ICdoZWlnaHRSYW5nZScsXG4gICAgICAgIGtleTogJ2hlaWdodCcsXG4gICAgICAgIGNoYW5uZWxTY2FsZVR5cGU6ICdzaXplJyxcbiAgICAgICAgY29uZGl0aW9uOiBjb25maWcgPT4gY29uZmlnLnZpc0NvbmZpZy5lbmFibGUzZFxuICAgICAgfSxcbiAgICAgIHJhZGl1czoge1xuICAgICAgICBwcm9wZXJ0eTogJ3JhZGl1cycsXG4gICAgICAgIGZpZWxkOiAncmFkaXVzRmllbGQnLFxuICAgICAgICBzY2FsZTogJ3JhZGl1c1NjYWxlJyxcbiAgICAgICAgZG9tYWluOiAncmFkaXVzRG9tYWluJyxcbiAgICAgICAgcmFuZ2U6ICdyYWRpdXNSYW5nZScsXG4gICAgICAgIGtleTogJ3JhZGl1cycsXG4gICAgICAgIGNoYW5uZWxTY2FsZVR5cGU6ICdyYWRpdXMnXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBmaW5kRGVmYXVsdExheWVyUHJvcHMoe2xhYmVsLCBmaWVsZHN9KSB7XG4gICAgY29uc3QgZ2VvanNvbkNvbHVtbnMgPSBmaWVsZHNcbiAgICAgIC5maWx0ZXIoZiA9PiBmLnR5cGUgPT09ICdnZW9qc29uJylcbiAgICAgIC5tYXAoZiA9PiBmLm5hbWUpO1xuXG4gICAgY29uc3QgZGVmYXVsdENvbHVtbnMgPSB7XG4gICAgICBnZW9qc29uOiB1bmlxKFsuLi5HRU9KU09OX0ZJRUxEUy5nZW9qc29uLCAuLi5nZW9qc29uQ29sdW1uc10pXG4gICAgfTtcblxuICAgIGNvbnN0IGZvdW5kQ29sdW1ucyA9IHRoaXMuZmluZERlZmF1bHRDb2x1bW5GaWVsZChkZWZhdWx0Q29sdW1ucywgZmllbGRzKTtcbiAgICBpZiAoIWZvdW5kQ29sdW1ucyB8fCAhZm91bmRDb2x1bW5zLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHJldHVybiBmb3VuZENvbHVtbnMubWFwKGNvbHVtbnMgPT4gKHtcbiAgICAgIGxhYmVsOlxuICAgICAgICAodHlwZW9mIGxhYmVsID09PSAnc3RyaW5nJyAmJiBsYWJlbC5yZXBsYWNlKC9cXC5bXi8uXSskLywgJycpKSB8fFxuICAgICAgICB0aGlzLnR5cGUsXG4gICAgICBjb2x1bW5zLFxuICAgICAgaXNWaXNpYmxlOiB0cnVlXG4gICAgfSkpO1xuICB9XG5cbiAgZ2V0RGVmYXVsdExheWVyQ29uZmlnKHByb3BzID0ge30pIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uc3VwZXIuZ2V0RGVmYXVsdExheWVyQ29uZmlnKHByb3BzKSxcblxuICAgICAgLy8gYWRkIGhlaWdodCB2aXN1YWwgY2hhbm5lbFxuICAgICAgaGVpZ2h0RmllbGQ6IG51bGwsXG4gICAgICBoZWlnaHREb21haW46IFswLCAxXSxcbiAgICAgIGhlaWdodFNjYWxlOiAnbGluZWFyJyxcblxuICAgICAgLy8gYWRkIHJhZGl1cyB2aXN1YWwgY2hhbm5lbFxuICAgICAgcmFkaXVzRmllbGQ6IG51bGwsXG4gICAgICByYWRpdXNEb21haW46IFswLCAxXSxcbiAgICAgIHJhZGl1c1NjYWxlOiAnbGluZWFyJ1xuICAgIH07XG4gIH1cblxuICBnZXRIb3ZlckRhdGEob2JqZWN0LCBhbGxEYXRhKSB7XG4gICAgLy8gaW5kZXggb2YgYWxsRGF0YSBpcyBzYXZlZCB0byBmZWF0dXJlLnByb3BlcnRpZXNcbiAgICByZXR1cm4gYWxsRGF0YVtvYmplY3QucHJvcGVydGllcy5pbmRleF07XG4gIH1cblxuICAvLyBUT0RPOiBmaXggY29tcGxleGl0eVxuICAvKiBlc2xpbnQtZGlzYWJsZSBjb21wbGV4aXR5ICovXG4gIGZvcm1hdExheWVyRGF0YShfLCBhbGxEYXRhLCBmaWx0ZXJlZEluZGV4LCBvbGRMYXllckRhdGEsIG9wdCA9IHt9KSB7XG4gICAgY29uc3Qge1xuICAgICAgY29sb3JTY2FsZSxcbiAgICAgIGNvbG9yRmllbGQsXG4gICAgICBjb2xvckRvbWFpbixcbiAgICAgIGNvbG9yLFxuICAgICAgc2l6ZVNjYWxlLFxuICAgICAgc2l6ZURvbWFpbixcbiAgICAgIHNpemVGaWVsZCxcbiAgICAgIGhlaWdodEZpZWxkLFxuICAgICAgaGVpZ2h0RG9tYWluLFxuICAgICAgaGVpZ2h0U2NhbGUsXG4gICAgICByYWRpdXNGaWVsZCxcbiAgICAgIHJhZGl1c0RvbWFpbixcbiAgICAgIHJhZGl1c1NjYWxlLFxuICAgICAgdmlzQ29uZmlnLFxuICAgICAgY29sdW1uc1xuICAgIH0gPSB0aGlzLmNvbmZpZztcblxuICAgIGNvbnN0IHtcbiAgICAgIGVuYWJsZTNkLFxuICAgICAgc3Ryb2tlZCxcbiAgICAgIGNvbG9yUmFuZ2UsXG4gICAgICBoZWlnaHRSYW5nZSxcbiAgICAgIHNpemVSYW5nZSxcbiAgICAgIHJhZGl1c1JhbmdlXG4gICAgfSA9IHZpc0NvbmZpZztcblxuICAgIGNvbnN0IGdldEZlYXR1cmUgPSB0aGlzLmdldEZlYXR1cmUoY29sdW1ucyk7XG4gICAgLy8gZ2VvanNvbiBmZWF0dXJlIGFyZSBvYmplY3QsIGlmIGRvZXNuJ3QgZXhpc3RzXG4gICAgLy8gY3JlYXRlIGl0IGFuZCBzYXZlIHRvIGxheWVyXG4gICAgaWYgKCFvbGRMYXllckRhdGEgfHwgb2xkTGF5ZXJEYXRhLmdldEZlYXR1cmUgIT09IGdldEZlYXR1cmUpIHtcbiAgICAgIHRoaXMudXBkYXRlTGF5ZXJNZXRhKGFsbERhdGEsIGdldEZlYXR1cmUpO1xuICAgIH1cblxuICAgIGxldCBnZW9qc29uRGF0YTtcblxuICAgIGlmIChcbiAgICAgIG9sZExheWVyRGF0YSAmJlxuICAgICAgb2xkTGF5ZXJEYXRhLmRhdGEgJiZcbiAgICAgIG9wdC5zYW1lRGF0YSAmJlxuICAgICAgb2xkTGF5ZXJEYXRhLmdldEZlYXR1cmUgPT09IGdldEZlYXR1cmVcbiAgICApIHtcbiAgICAgIC8vIG5vIG5lZWQgdG8gY3JlYXRlIGEgbmV3IGFycmF5IG9mIGRhdGFcbiAgICAgIC8vIHVzZSB1cGRhdGVUcmlnZ2VycyB0byBzZWxlY3RpdmVseSByZS1jYWxjdWxhdGUgYXR0cmlidXRlc1xuICAgICAgZ2VvanNvbkRhdGEgPSBvbGRMYXllckRhdGEuZGF0YTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gZmlsdGVyZWRJbmRleCBpcyBhIHJlZmVyZW5jZSBvZiBpbmRleCBpbiBhbGxEYXRhIHdoaWNoIGNhbiBtYXAgdG8gZmVhdHVyZVxuICAgICAgZ2VvanNvbkRhdGEgPSBmaWx0ZXJlZEluZGV4XG4gICAgICAgIC5tYXAoaSA9PiB0aGlzLmRhdGFUb0ZlYXR1cmVbaV0pXG4gICAgICAgIC5maWx0ZXIoZCA9PiBkKTtcbiAgICB9XG5cbiAgICBcblxuICAgIGNvbnN0IGNTY2FsZSA9XG4gICAgICBjb2xvckZpZWxkICYmXG4gICAgICB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShcbiAgICAgICAgY29sb3JTY2FsZSxcbiAgICAgICAgY29sb3JEb21haW4sXG4gICAgICAgIGNvbG9yUmFuZ2UuY29sb3JzLm1hcChoZXhUb1JnYilcbiAgICAgICk7XG5cbiAgICAvLyBjYWxjdWxhdGUgc3Ryb2tlIHNjYWxlIC0gaWYgc3Ryb2tlZCA9IHRydWVcbiAgICBjb25zdCBzU2NhbGUgPVxuICAgICAgc2l6ZUZpZWxkICYmXG4gICAgICBzdHJva2VkICYmXG4gICAgICB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShzaXplU2NhbGUsIHNpemVEb21haW4sIHNpemVSYW5nZSk7XG5cbiAgICAvLyBjYWxjdWxhdGUgZWxldmF0aW9uIHNjYWxlIC0gaWYgZXh0cnVkZWQgPSB0cnVlXG4gICAgY29uc3QgZVNjYWxlID1cbiAgICAgIGhlaWdodEZpZWxkICYmXG4gICAgICBlbmFibGUzZCAmJlxuICAgICAgdGhpcy5nZXRWaXNDaGFubmVsU2NhbGUoaGVpZ2h0U2NhbGUsIGhlaWdodERvbWFpbiwgaGVpZ2h0UmFuZ2UpO1xuICAgIC8vIGNvbnNvbGUubG9nKCdlU2NhbGUgaW5zaWRlIGZvcm1hdExheWVyRGF0YScsIGVTY2FsZSk7XG4gICAgLy8gcG9pbnQgcmFkaXVzXG4gICAgY29uc3QgclNjYWxlID1cbiAgICAgIHJhZGl1c0ZpZWxkICYmXG4gICAgICB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShyYWRpdXNTY2FsZSwgcmFkaXVzRG9tYWluLCByYWRpdXNSYW5nZSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogZ2VvanNvbkRhdGEsXG4gICAgICBnZXRGZWF0dXJlLFxuICAgICAgZ2V0RmlsbENvbG9yOiBkID0+XG4gICAgICAgIGNTY2FsZVxuICAgICAgICAgID8gdGhpcy5nZXRFbmNvZGVkQ2hhbm5lbFZhbHVlKFxuICAgICAgICAgICAgICBjU2NhbGUsXG4gICAgICAgICAgICAgIGFsbERhdGFbZC5wcm9wZXJ0aWVzLmluZGV4XSxcbiAgICAgICAgICAgICAgY29sb3JGaWVsZFxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogZC5wcm9wZXJ0aWVzLmZpbGxDb2xvciB8fCBjb2xvcixcbiAgICAgIGdldExpbmVDb2xvcjogZCA9PlxuICAgICAgICBjU2NhbGVcbiAgICAgICAgICA/IHRoaXMuZ2V0RW5jb2RlZENoYW5uZWxWYWx1ZShcbiAgICAgICAgICAgICAgY1NjYWxlLFxuICAgICAgICAgICAgICBhbGxEYXRhW2QucHJvcGVydGllcy5pbmRleF0sXG4gICAgICAgICAgICAgIGNvbG9yRmllbGRcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6IGQucHJvcGVydGllcy5saW5lQ29sb3IgfHwgY29sb3IsXG4gICAgICBnZXRMaW5lV2lkdGg6IGQgPT5cbiAgICAgICAgc1NjYWxlXG4gICAgICAgICAgPyB0aGlzLmdldEVuY29kZWRDaGFubmVsVmFsdWUoXG4gICAgICAgICAgICAgIHNTY2FsZSxcbiAgICAgICAgICAgICAgYWxsRGF0YVtkLnByb3BlcnRpZXMuaW5kZXhdLFxuICAgICAgICAgICAgICBzaXplRmllbGQsXG4gICAgICAgICAgICAgIDBcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6IGQucHJvcGVydGllcy5saW5lV2lkdGggfHwgMSxcbiAgICAgIGdldEVsZXZhdGlvbjogZCA9PlxuICAgICAgICBlU2NhbGVcbiAgICAgICAgICA/IHRoaXMuZ2V0RW5jb2RlZENoYW5uZWxWYWx1ZShcbiAgICAgICAgICAgICAgZVNjYWxlLFxuICAgICAgICAgICAgICBhbGxEYXRhW2QucHJvcGVydGllcy5pbmRleF0sXG4gICAgICAgICAgICAgIGhlaWdodEZpZWxkLFxuICAgICAgICAgICAgICAwXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBkLnByb3BlcnRpZXMuZWxldmF0aW9uIHx8IDUwMCxcbiAgICAgIGdldFJhZGl1czogZCA9PlxuICAgICAgICByU2NhbGVcbiAgICAgICAgICA/IHRoaXMuZ2V0RW5jb2RlZENoYW5uZWxWYWx1ZShcbiAgICAgICAgICAgICAgclNjYWxlLFxuICAgICAgICAgICAgICBhbGxEYXRhW2QucHJvcGVydGllcy5pbmRleF0sXG4gICAgICAgICAgICAgIHJhZGl1c0ZpZWxkLFxuICAgICAgICAgICAgICAwXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBkLnByb3BlcnRpZXMucmFkaXVzIHx8IDFcbiAgICB9O1xuICB9XG4gIC8qIGVzbGludC1lbmFibGUgY29tcGxleGl0eSAqL1xuXG4gIHVwZGF0ZUxheWVyTWV0YShhbGxEYXRhLCBnZXRGZWF0dXJlKSB7XG4gICAgdGhpcy5kYXRhVG9GZWF0dXJlID0gZ2V0R2VvanNvbkRhdGFNYXBzKGFsbERhdGEsIGdldEZlYXR1cmUpO1xuXG4gICAgLy8gY2FsY3VsYXRlIGxheWVyIG1ldGFcbiAgICBjb25zdCBhbGxGZWF0dXJlcyA9IE9iamVjdC52YWx1ZXModGhpcy5kYXRhVG9GZWF0dXJlKTtcblxuICAgIC8vIGdldCBib3VuZHMgZnJvbSBmZWF0dXJlc1xuICAgIGNvbnN0IGJvdW5kcyA9IGdldEdlb2pzb25Cb3VuZHMoYWxsRmVhdHVyZXMpO1xuXG4gICAgLy8gZ2V0IGxpZ2h0U2V0dGluZ3MgZnJvbSBwb2ludHNcbiAgICBjb25zdCBsaWdodFNldHRpbmdzID0gdGhpcy5nZXRMaWdodFNldHRpbmdzRnJvbUJvdW5kcyhib3VuZHMpO1xuXG4gICAgLy8gaWYgYW55IG9mIHRoZSBmZWF0dXJlIGhhcyBwcm9wZXJ0aWVzLmhpLXByZWNpc2lvbiBzZXQgdG8gYmUgdHJ1ZVxuICAgIGNvbnN0IGZwNjQgPSBCb29sZWFuKFxuICAgICAgYWxsRmVhdHVyZXMuZmluZChkID0+IGQgJiYgZC5wcm9wZXJ0aWVzICYmIGQucHJvcGVydGllc1snaGktcHJlY2lzaW9uJ10pXG4gICAgKTtcbiAgICBjb25zdCBmaXhlZFJhZGl1cyA9IEJvb2xlYW4oXG4gICAgICBhbGxGZWF0dXJlcy5maW5kKGQgPT4gZCAmJiBkLnByb3BlcnRpZXMgJiYgZC5wcm9wZXJ0aWVzLnJhZGl1cylcbiAgICApO1xuXG4gICAgLy8ga2VlcCBhIHJlY29yZCBvZiB3aGF0IHR5cGUgb2YgZ2VvbWV0cnkgdGhlIGNvbGxlY3Rpb24gaGFzXG4gICAgY29uc3QgZmVhdHVyZVR5cGVzID0gYWxsRmVhdHVyZXMucmVkdWNlKChhY2N1LCBmKSA9PiB7XG4gICAgICBjb25zdCBnZW9UeXBlID0gZmVhdHVyZVRvRGVja0dsR2VvVHlwZShcbiAgICAgICAgZiAmJiBmLmdlb21ldHJ5ICYmIGYuZ2VvbWV0cnkudHlwZVxuICAgICAgKTtcblxuICAgICAgaWYgKGdlb1R5cGUpIHtcbiAgICAgICAgYWNjdVtnZW9UeXBlXSA9IHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjdTtcbiAgICB9LCB7fSk7XG5cbiAgICB0aGlzLnVwZGF0ZU1ldGEoe2JvdW5kcywgbGlnaHRTZXR0aW5ncywgZnA2NCwgZml4ZWRSYWRpdXMsIGZlYXR1cmVUeXBlc30pO1xuICB9XG5cbiAgcmVuZGVyTGF5ZXIoe2RhdGEsIGlkeCwgb2JqZWN0SG92ZXJlZCwgbWFwU3RhdGUsIGludGVyYWN0aW9uQ29uZmlnfSkge1xuICAgIGNvbnN0IHtmcDY0LCBsaWdodFNldHRpbmdzLCBmaXhlZFJhZGl1c30gPSB0aGlzLm1ldGE7XG4gICAgY29uc3QgcmFkaXVzU2NhbGUgPSB0aGlzLmdldFJhZGl1c1NjYWxlQnlab29tKG1hcFN0YXRlLCBmaXhlZFJhZGl1cyk7XG4gICAgY29uc3Qgem9vbUZhY3RvciA9IHRoaXMuZ2V0Wm9vbUZhY3RvcihtYXBTdGF0ZSk7XG4gICAgY29uc3Qge3Zpc0NvbmZpZ30gPSB0aGlzLmNvbmZpZztcblxuICAgIGNvbnN0IGxheWVyUHJvcHMgPSB7XG4gICAgICAvLyBtdWx0aXBsaWVyIGFwcGxpZWQganVzdCBzbyBpdCBiZWluZyBjb25zaXN0ZW50IHdpdGggcHJldmlvdXNseSBzYXZlZCBtYXBzXG4gICAgICBsaW5lV2lkdGhTY2FsZTogdmlzQ29uZmlnLnRoaWNrbmVzcyAqIHpvb21GYWN0b3IgKiA4LFxuICAgICAgbGluZVdpZHRoTWluUGl4ZWxzOiAxLFxuICAgICAgZWxldmF0aW9uU2NhbGU6IHZpc0NvbmZpZy5lbGV2YXRpb25TY2FsZSxcbiAgICAgIHBvaW50UmFkaXVzU2NhbGU6IHJhZGl1c1NjYWxlLFxuICAgICAgZnA2NDogZnA2NCB8fCB2aXNDb25maWdbJ2hpLXByZWNpc2lvbiddLFxuICAgICAgbGluZU1pdGVyTGltaXQ6IDRcbiAgICB9O1xuXG4gICAgY29uc3QgdXBkYXRlVHJpZ2dlcnMgPSB7XG4gICAgICBnZXRFbGV2YXRpb246IHtcbiAgICAgICAgaGVpZ2h0RmllbGQ6IHRoaXMuY29uZmlnLmhlaWdodEZpZWxkLFxuICAgICAgICBoZWlnaHRTY2FsZTogdGhpcy5jb25maWcuaGVpZ2h0U2NhbGUsXG4gICAgICAgIGhlaWdodFJhbmdlOiB2aXNDb25maWcuaGVpZ2h0UmFuZ2VcbiAgICAgIH0sXG4gICAgICBnZXRGaWxsQ29sb3I6IHtcbiAgICAgICAgY29sb3I6IHRoaXMuY29uZmlnLmNvbG9yLFxuICAgICAgICBjb2xvckZpZWxkOiB0aGlzLmNvbmZpZy5jb2xvckZpZWxkLFxuICAgICAgICBjb2xvclJhbmdlOiB2aXNDb25maWcuY29sb3JSYW5nZSxcbiAgICAgICAgY29sb3JTY2FsZTogdGhpcy5jb25maWcuY29sb3JTY2FsZVxuICAgICAgfSxcbiAgICAgIGdldExpbmVDb2xvcjoge1xuICAgICAgICBjb2xvcjogdGhpcy5jb25maWcuY29sb3IsXG4gICAgICAgIGNvbG9yRmllbGQ6IHRoaXMuY29uZmlnLmNvbG9yRmllbGQsXG4gICAgICAgIGNvbG9yUmFuZ2U6IHZpc0NvbmZpZy5jb2xvclJhbmdlLFxuICAgICAgICBjb2xvclNjYWxlOiB0aGlzLmNvbmZpZy5jb2xvclNjYWxlXG4gICAgICB9LFxuICAgICAgZ2V0TGluZVdpZHRoOiB7XG4gICAgICAgIHNpemVGaWVsZDogdGhpcy5jb25maWcuc2l6ZUZpZWxkLFxuICAgICAgICBzaXplUmFuZ2U6IHZpc0NvbmZpZy5zaXplUmFuZ2VcbiAgICAgIH0sXG4gICAgICBnZXRSYWRpdXM6IHtcbiAgICAgICAgcmFkaXVzRmllbGQ6IHRoaXMuY29uZmlnLnJhZGl1c0ZpZWxkLFxuICAgICAgICByYWRpdXNSYW5nZTogdmlzQ29uZmlnLnJhZGl1c1JhbmdlXG4gICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gW1xuICAgICAgbmV3IERlY2tHTEdlb0pzb25MYXllcih7XG4gICAgICAgIC4uLmxheWVyUHJvcHMsXG4gICAgICAgIGlkOiB0aGlzLmlkLFxuICAgICAgICBpZHgsXG4gICAgICAgIGRhdGE6IGRhdGEuZGF0YSxcbiAgICAgICAgZ2V0RmlsbENvbG9yOiBkYXRhLmdldEZpbGxDb2xvcixcbiAgICAgICAgZ2V0TGluZUNvbG9yOiBkYXRhLmdldExpbmVDb2xvcixcbiAgICAgICAgZ2V0TGluZVdpZHRoOiBkYXRhLmdldExpbmVXaWR0aCxcbiAgICAgICAgZ2V0UmFkaXVzOiBkYXRhLmdldFJhZGl1cyxcbiAgICAgICAgZ2V0RWxldmF0aW9uOiBkYXRhLmdldEVsZXZhdGlvbixcbiAgICAgICAgLy8gaGlnaGxpZ2h0XG4gICAgICAgIHBpY2thYmxlOiB0cnVlLFxuICAgICAgICAvLyBoaWdobGlnaHRDb2xvcjogdGhpcy5jb25maWcuaGlnaGxpZ2h0Q29sb3IsXG4gICAgICAgIGF1dG9IaWdobGlnaHQ6IHZpc0NvbmZpZy5lbmFibGUzZCxcbiAgICAgICAgLy8gcGFyYW1ldGVyc1xuICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgZGVwdGhUZXN0OiBCb29sZWFuKHZpc0NvbmZpZy5lbmFibGUzZCB8fCBtYXBTdGF0ZS5kcmFnUm90YXRlKVxuICAgICAgICB9LFxuICAgICAgICBvcGFjaXR5OiB2aXNDb25maWcub3BhY2l0eSxcbiAgICAgICAgc3Ryb2tlZDogdmlzQ29uZmlnLnN0cm9rZWQsXG4gICAgICAgIGZpbGxlZDogdmlzQ29uZmlnLmZpbGxlZCxcbiAgICAgICAgZXh0cnVkZWQ6IHZpc0NvbmZpZy5lbmFibGUzZCxcbiAgICAgICAgd2lyZWZyYW1lOiB2aXNDb25maWcud2lyZWZyYW1lLFxuICAgICAgICBsaWdodFNldHRpbmdzLFxuICAgICAgICB1cGRhdGVUcmlnZ2VycyxcblxuICAgICAgICBzdWJMYXllcnM6IHtcbiAgICAgICAgICAuLi5EZWNrR0xHZW9Kc29uTGF5ZXIuZGVmYXVsdFByb3BzLnN1YkxheWVycyxcbiAgICAgICAgICBQb2x5Z29uTGF5ZXI6IEhpZ2hsaWdodFBvbHlnb25MYXllclxuICAgICAgICB9XG4gICAgICB9KSxcbiAgICAgIC4uLih0aGlzLmlzTGF5ZXJIb3ZlcmVkKG9iamVjdEhvdmVyZWQpICYmICF2aXNDb25maWcuZW5hYmxlM2RcbiAgICAgICAgPyBbXG4gICAgICAgICAgICBuZXcgRGVja0dMR2VvSnNvbkxheWVyKHtcbiAgICAgICAgICAgICAgLi4ubGF5ZXJQcm9wcyxcbiAgICAgICAgICAgICAgaWQ6IGAke3RoaXMuaWR9LWhvdmVyZWRgLFxuICAgICAgICAgICAgICBkYXRhOiBbb2JqZWN0SG92ZXJlZC5vYmplY3RdLFxuICAgICAgICAgICAgICBnZXRMaW5lV2lkdGg6IGRhdGEuZ2V0TGluZVdpZHRoLFxuICAgICAgICAgICAgICBnZXRSYWRpdXM6IGRhdGEuZ2V0UmFkaXVzLFxuICAgICAgICAgICAgICBnZXRFbGV2YXRpb246IGRhdGEuZ2V0RWxldmF0aW9uLFxuICAgICAgICAgICAgICBnZXRMaW5lQ29sb3I6IHRoaXMuY29uZmlnLmhpZ2hsaWdodENvbG9yLFxuICAgICAgICAgICAgICBnZXRGaWxsQ29sb3I6IHRoaXMuY29uZmlnLmhpZ2hsaWdodENvbG9yLFxuICAgICAgICAgICAgICB1cGRhdGVUcmlnZ2VycyxcbiAgICAgICAgICAgICAgc3Ryb2tlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgcGlja2FibGU6IGZhbHNlLFxuICAgICAgICAgICAgICBmaWxsZWQ6IGZhbHNlXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIF1cbiAgICAgICAgOiBbXSlcbiAgICBdO1xuICB9XG59XG4iXX0=