kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
455 lines (402 loc) • 49.9 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.defaultRadius = exports.defaultLineWidth = exports.defaultElevation = exports.featureAccessor = exports.geoJsonRequiredColumns = exports.geojsonVisConfigs = void 0;
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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _lodash = _interopRequireDefault(require("lodash.uniq"));
var _typeAnalyzer = require("type-analyzer");
var _baseLayer = _interopRequireWildcard(require("../base-layer"));
var _layers = require("@deck.gl/layers");
var _geojsonUtils = require("./geojson-utils");
var _geojsonLayerIcon = _interopRequireDefault(require("./geojson-layer-icon"));
var _defaultSettings = require("../../constants/default-settings");
var _layerFactory = require("../layer-factory");
var _SUPPORTED_ANALYZER_T;
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; } }
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 SUPPORTED_ANALYZER_TYPES = (_SUPPORTED_ANALYZER_T = {}, (0, _defineProperty2["default"])(_SUPPORTED_ANALYZER_T, _typeAnalyzer.DATA_TYPES.GEOMETRY, true), (0, _defineProperty2["default"])(_SUPPORTED_ANALYZER_T, _typeAnalyzer.DATA_TYPES.GEOMETRY_FROM_STRING, true), (0, _defineProperty2["default"])(_SUPPORTED_ANALYZER_T, _typeAnalyzer.DATA_TYPES.PAIR_GEOMETRY_FROM_STRING, true), _SUPPORTED_ANALYZER_T);
var geojsonVisConfigs = {
opacity: 'opacity',
strokeOpacity: _objectSpread(_objectSpread({}, _layerFactory.LAYER_VIS_CONFIGS.opacity), {}, {
property: 'strokeOpacity'
}),
thickness: _objectSpread(_objectSpread({}, _layerFactory.LAYER_VIS_CONFIGS.thickness), {}, {
defaultValue: 0.5
}),
strokeColor: 'strokeColor',
colorRange: 'colorRange',
strokeColorRange: 'strokeColorRange',
radius: 'radius',
sizeRange: 'strokeWidthRange',
radiusRange: 'radiusRange',
heightRange: 'elevationRange',
elevationScale: 'elevationScale',
enableElevationZoomFactor: 'enableElevationZoomFactor',
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 (dc) {
return function (d) {
return dc.valueAt(d.index, geojson.fieldIdx);
};
};
}; // access feature properties from geojson sub layer
exports.featureAccessor = featureAccessor;
var defaultElevation = 500;
exports.defaultElevation = defaultElevation;
var defaultLineWidth = 1;
exports.defaultLineWidth = defaultLineWidth;
var defaultRadius = 1;
exports.defaultRadius = defaultRadius;
var GeoJsonLayer = /*#__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.getPositionAccessor = function (dataContainer) {
return featureAccessor(_this.config.columns)(dataContainer);
};
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() {
var visualChannels = (0, _get2["default"])((0, _getPrototypeOf2["default"])(GeoJsonLayer.prototype), "visualChannels", this);
return {
color: _objectSpread(_objectSpread({}, visualChannels.color), {}, {
accessor: 'getFillColor',
condition: function condition(config) {
return config.visConfig.filled;
},
nullValue: visualChannels.color.nullValue,
getAttributeValue: function getAttributeValue(config) {
return function (d) {
return d.properties.fillColor || config.color;
};
},
// used this to get updateTriggers
defaultValue: function defaultValue(config) {
return config.color;
}
}),
strokeColor: {
property: 'strokeColor',
field: 'strokeColorField',
scale: 'strokeColorScale',
domain: 'strokeColorDomain',
range: 'strokeColorRange',
key: 'strokeColor',
channelScaleType: _defaultSettings.CHANNEL_SCALES.color,
accessor: 'getLineColor',
condition: function condition(config) {
return config.visConfig.stroked;
},
nullValue: visualChannels.color.nullValue,
getAttributeValue: function getAttributeValue(config) {
return function (d) {
return d.properties.lineColor || config.visConfig.strokeColor || config.color;
};
},
// used this to get updateTriggers
defaultValue: function defaultValue(config) {
return config.visConfig.strokeColor || config.color;
}
},
size: _objectSpread(_objectSpread({}, visualChannels.size), {}, {
property: 'stroke',
accessor: 'getLineWidth',
condition: function condition(config) {
return config.visConfig.stroked;
},
nullValue: 0,
getAttributeValue: function getAttributeValue() {
return function (d) {
return d.properties.lineWidth || defaultLineWidth;
};
}
}),
height: {
property: 'height',
field: 'heightField',
scale: 'heightScale',
domain: 'heightDomain',
range: 'heightRange',
key: 'height',
channelScaleType: _defaultSettings.CHANNEL_SCALES.size,
accessor: 'getElevation',
condition: function condition(config) {
return config.visConfig.enable3d;
},
nullValue: 0,
getAttributeValue: function getAttributeValue() {
return function (d) {
return d.properties.elevation || defaultElevation;
};
}
},
radius: {
property: 'radius',
field: 'radiusField',
scale: 'radiusScale',
domain: 'radiusDomain',
range: 'radiusRange',
key: 'radius',
channelScaleType: _defaultSettings.CHANNEL_SCALES.radius,
accessor: 'getRadius',
nullValue: 0,
getAttributeValue: function getAttributeValue() {
return function (d) {
return d.properties.radius || defaultRadius;
};
}
}
};
}
}, {
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, dataContainer) {
// index of dataContainer is saved to feature.properties
return dataContainer.row(object.properties.index);
}
}, {
key: "calculateDataAttribute",
value: function calculateDataAttribute(_ref2, getPosition) {
var _this2 = this;
var dataContainer = _ref2.dataContainer,
filteredIndex = _ref2.filteredIndex;
return filteredIndex.map(function (i) {
return _this2.dataToFeature[i];
}).filter(function (d) {
return d;
});
}
}, {
key: "formatLayerData",
value: function formatLayerData(datasets, oldLayerData) {
var _datasets$this$config = datasets[this.config.dataId],
gpuFilter = _datasets$this$config.gpuFilter,
dataContainer = _datasets$this$config.dataContainer;
var _this$updateData = this.updateData(datasets, oldLayerData),
data = _this$updateData.data;
var customFilterValueAccessor = function customFilterValueAccessor(dc, d, fieldIndex) {
return dc.valueAt(d.properties.index, fieldIndex);
};
var indexAccessor = function indexAccessor(f) {
return f.properties.index;
};
var dataAccessor = function dataAccessor(dc) {
return function (d) {
return {
index: d.properties.index
};
};
};
var accessors = this.getAttributeAccessors({
dataAccessor: dataAccessor,
dataContainer: dataContainer
});
return _objectSpread({
data: data,
getFilterValue: gpuFilter.filterValueAccessor(dataContainer)(indexAccessor, customFilterValueAccessor)
}, accessors);
}
}, {
key: "updateLayerMeta",
value: function updateLayerMeta(dataContainer) {
var getFeature = this.getPositionAccessor(dataContainer);
this.dataToFeature = (0, _geojsonUtils.getGeojsonDataMaps)(dataContainer, 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(_ref3) {
var dataContainer = _ref3.dataContainer;
this.updateLayerMeta(dataContainer);
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(opts) {
var data = opts.data,
gpuFilter = opts.gpuFilter,
objectHovered = opts.objectHovered,
mapState = opts.mapState,
interactionConfig = opts.interactionConfig;
var _this$meta = this.meta,
fixedRadius = _this$meta.fixedRadius,
featureTypes = _this$meta.featureTypes;
var radiusScale = this.getRadiusScaleByZoom(mapState, fixedRadius);
var zoomFactor = this.getZoomFactor(mapState);
var eleZoomFactor = this.getElevationZoomFactor(mapState);
var visConfig = this.config.visConfig;
var layerProps = {
lineWidthScale: visConfig.thickness * zoomFactor * 8,
elevationScale: visConfig.elevationScale * eleZoomFactor,
pointRadiusScale: radiusScale,
lineMiterLimit: 4
};
var updateTriggers = _objectSpread(_objectSpread({}, this.getVisualChannelUpdateTriggers()), {}, {
getFilterValue: gpuFilter.filterValueUpdateTriggers
});
var defaultLayerProps = this.getDefaultDeckLayerProps(opts);
var opaOverwrite = {
opacity: visConfig.strokeOpacity
};
var pickable = interactionConfig.tooltip.enabled;
var hoveredObject = this.hasHoveredObject(objectHovered);
return [new _layers.GeoJsonLayer(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, defaultLayerProps), layerProps), data), {}, {
pickable: pickable,
highlightColor: _defaultSettings.HIGHLIGH_COLOR_3D,
autoHighlight: visConfig.enable3d && pickable,
stroked: visConfig.stroked,
filled: visConfig.filled,
extruded: visConfig.enable3d,
wireframe: visConfig.wireframe,
wrapLongitude: false,
lineMiterLimit: 2,
rounded: true,
updateTriggers: updateTriggers,
_subLayerProps: _objectSpread(_objectSpread(_objectSpread({}, featureTypes.polygon ? {
'polygons-stroke': opaOverwrite
} : {}), featureTypes.line ? {
'line-strings': opaOverwrite
} : {}), featureTypes.point ? {
points: {
lineOpacity: visConfig.strokeOpacity
}
} : {})
}))].concat((0, _toConsumableArray2["default"])(hoveredObject && !visConfig.enable3d ? [new _layers.GeoJsonLayer(_objectSpread(_objectSpread(_objectSpread({}, this.getDefaultHoverLayerProps()), layerProps), {}, {
wrapLongitude: false,
data: [hoveredObject],
getLineWidth: data.getLineWidth,
getRadius: data.getRadius,
getElevation: data.getElevation,
getLineColor: this.config.highlightColor,
getFillColor: this.config.highlightColor,
// always draw outline
stroked: true,
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' && SUPPORTED_ANALYZER_TYPES[f.analyzerType];
}).map(function (f) {
return f.name;
});
var defaultColumns = {
geojson: (0, _lodash["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"]);
exports["default"] = GeoJsonLayer;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvZ2VvanNvbi1sYXllci9nZW9qc29uLWxheWVyLmpzIl0sIm5hbWVzIjpbIlNVUFBPUlRFRF9BTkFMWVpFUl9UWVBFUyIsIkRBVEFfVFlQRVMiLCJHRU9NRVRSWSIsIkdFT01FVFJZX0ZST01fU1RSSU5HIiwiUEFJUl9HRU9NRVRSWV9GUk9NX1NUUklORyIsImdlb2pzb25WaXNDb25maWdzIiwib3BhY2l0eSIsInN0cm9rZU9wYWNpdHkiLCJMQVlFUl9WSVNfQ09ORklHUyIsInByb3BlcnR5IiwidGhpY2tuZXNzIiwiZGVmYXVsdFZhbHVlIiwic3Ryb2tlQ29sb3IiLCJjb2xvclJhbmdlIiwic3Ryb2tlQ29sb3JSYW5nZSIsInJhZGl1cyIsInNpemVSYW5nZSIsInJhZGl1c1JhbmdlIiwiaGVpZ2h0UmFuZ2UiLCJlbGV2YXRpb25TY2FsZSIsImVuYWJsZUVsZXZhdGlvblpvb21GYWN0b3IiLCJzdHJva2VkIiwiZmlsbGVkIiwiZW5hYmxlM2QiLCJ3aXJlZnJhbWUiLCJnZW9Kc29uUmVxdWlyZWRDb2x1bW5zIiwiZmVhdHVyZUFjY2Vzc29yIiwiZ2VvanNvbiIsImRjIiwiZCIsInZhbHVlQXQiLCJpbmRleCIsImZpZWxkSWR4IiwiZGVmYXVsdEVsZXZhdGlvbiIsImRlZmF1bHRMaW5lV2lkdGgiLCJkZWZhdWx0UmFkaXVzIiwiR2VvSnNvbkxheWVyIiwicHJvcHMiLCJkYXRhVG9GZWF0dXJlIiwicmVnaXN0ZXJWaXNDb25maWciLCJnZXRQb3NpdGlvbkFjY2Vzc29yIiwiZGF0YUNvbnRhaW5lciIsImNvbmZpZyIsImNvbHVtbnMiLCJHZW9qc29uTGF5ZXJJY29uIiwidmlzdWFsQ2hhbm5lbHMiLCJjb2xvciIsImFjY2Vzc29yIiwiY29uZGl0aW9uIiwidmlzQ29uZmlnIiwibnVsbFZhbHVlIiwiZ2V0QXR0cmlidXRlVmFsdWUiLCJwcm9wZXJ0aWVzIiwiZmlsbENvbG9yIiwiZmllbGQiLCJzY2FsZSIsImRvbWFpbiIsInJhbmdlIiwia2V5IiwiY2hhbm5lbFNjYWxlVHlwZSIsIkNIQU5ORUxfU0NBTEVTIiwibGluZUNvbG9yIiwic2l6ZSIsImxpbmVXaWR0aCIsImhlaWdodCIsImVsZXZhdGlvbiIsImhlaWdodEZpZWxkIiwiaGVpZ2h0RG9tYWluIiwiaGVpZ2h0U2NhbGUiLCJyYWRpdXNGaWVsZCIsInJhZGl1c0RvbWFpbiIsInJhZGl1c1NjYWxlIiwic3Ryb2tlQ29sb3JGaWVsZCIsInN0cm9rZUNvbG9yRG9tYWluIiwic3Ryb2tlQ29sb3JTY2FsZSIsIm9iamVjdCIsInJvdyIsImdldFBvc2l0aW9uIiwiZmlsdGVyZWRJbmRleCIsIm1hcCIsImkiLCJmaWx0ZXIiLCJkYXRhc2V0cyIsIm9sZExheWVyRGF0YSIsImRhdGFJZCIsImdwdUZpbHRlciIsInVwZGF0ZURhdGEiLCJkYXRhIiwiY3VzdG9tRmlsdGVyVmFsdWVBY2Nlc3NvciIsImZpZWxkSW5kZXgiLCJpbmRleEFjY2Vzc29yIiwiZiIsImRhdGFBY2Nlc3NvciIsImFjY2Vzc29ycyIsImdldEF0dHJpYnV0ZUFjY2Vzc29ycyIsImdldEZpbHRlclZhbHVlIiwiZmlsdGVyVmFsdWVBY2Nlc3NvciIsImdldEZlYXR1cmUiLCJib3VuZHMiLCJmaXhlZFJhZGl1cyIsIkJvb2xlYW4iLCJmaW5kIiwiZmVhdHVyZVR5cGVzIiwidXBkYXRlTWV0YSIsInVwZGF0ZUxheWVyTWV0YSIsIm1ldGEiLCJwb2x5Z29uIiwidXBkYXRlTGF5ZXJWaXNDb25maWciLCJjb2xvck1ha2VyIiwibmV4dCIsInZhbHVlIiwicG9pbnQiLCJvcHRzIiwib2JqZWN0SG92ZXJlZCIsIm1hcFN0YXRlIiwiaW50ZXJhY3Rpb25Db25maWciLCJnZXRSYWRpdXNTY2FsZUJ5Wm9vbSIsInpvb21GYWN0b3IiLCJnZXRab29tRmFjdG9yIiwiZWxlWm9vbUZhY3RvciIsImdldEVsZXZhdGlvblpvb21GYWN0b3IiLCJsYXllclByb3BzIiwibGluZVdpZHRoU2NhbGUiLCJwb2ludFJhZGl1c1NjYWxlIiwibGluZU1pdGVyTGltaXQiLCJ1cGRhdGVUcmlnZ2VycyIsImdldFZpc3VhbENoYW5uZWxVcGRhdGVUcmlnZ2VycyIsImZpbHRlclZhbHVlVXBkYXRlVHJpZ2dlcnMiLCJkZWZhdWx0TGF5ZXJQcm9wcyIsImdldERlZmF1bHREZWNrTGF5ZXJQcm9wcyIsIm9wYU92ZXJ3cml0ZSIsInBpY2thYmxlIiwidG9vbHRpcCIsImVuYWJsZWQiLCJob3ZlcmVkT2JqZWN0IiwiaGFzSG92ZXJlZE9iamVjdCIsIkRlY2tHTEdlb0pzb25MYXllciIsImhpZ2hsaWdodENvbG9yIiwiSElHSExJR0hfQ09MT1JfM0QiLCJhdXRvSGlnaGxpZ2h0IiwiZXh0cnVkZWQiLCJ3cmFwTG9uZ2l0dWRlIiwicm91bmRlZCIsIl9zdWJMYXllclByb3BzIiwibGluZSIsInBvaW50cyIsImxpbmVPcGFjaXR5IiwiZ2V0RGVmYXVsdEhvdmVyTGF5ZXJQcm9wcyIsImdldExpbmVXaWR0aCIsImdldFJhZGl1cyIsImdldEVsZXZhdGlvbiIsImdldExpbmVDb2xvciIsImdldEZpbGxDb2xvciIsImxhYmVsIiwiZmllbGRzIiwiZ2VvanNvbkNvbHVtbnMiLCJ0eXBlIiwiYW5hbHl6ZXJUeXBlIiwibmFtZSIsImRlZmF1bHRDb2x1bW5zIiwiR0VPSlNPTl9GSUVMRFMiLCJmb3VuZENvbHVtbnMiLCJmaW5kRGVmYXVsdENvbHVtbkZpZWxkIiwibGVuZ3RoIiwicmVwbGFjZSIsImlzVmlzaWJsZSIsIkxheWVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkE7O0FBQ0E7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7OztBQUVBLElBQU1BLHdCQUF3Qix3RkFDM0JDLHlCQUFXQyxRQURnQixFQUNMLElBREssMkRBRTNCRCx5QkFBV0Usb0JBRmdCLEVBRU8sSUFGUCwyREFHM0JGLHlCQUFXRyx5QkFIZ0IsRUFHWSxJQUhaLHlCQUE5QjtBQU1PLElBQU1DLGlCQUFpQixHQUFHO0FBQy9C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QUFJQSxDQUFDLENBQUNpRSxJQUFGLEtBQVcsU0FBWCxJQUF3QjVKLHdCQUF3QixDQUFDMkYsQ0FBQyxDQUFDa0UsWUFBSCxDQUFwRDtBQUFBLE9BRFksRUFFcEI5RSxHQUZvQixDQUVoQixVQUFBWSxDQUFDO0FBQUEsZUFBSUEsQ0FBQyxDQUFDbUUsSUFBTjtBQUFBLE9BRmUsQ0FBdkI7QUFJQSxVQUFNQyxjQUFjLEdBQUc7QUFDckJwSSxRQUFBQSxPQUFPLEVBQUUsc0VBQVNxSSxnQ0FBZXJJLE9BQXhCLHVDQUFvQ2dJLGNBQXBDO0FBRFksT0FBdkI7QUFJQSxVQUFNTSxZQUFZLEdBQUcsS0FBS0Msc0JBQUwsQ0FBNEJILGNBQTVCLEVBQTRDTCxNQUE1QyxDQUFyQjs7QUFDQSxVQUFJLENBQUNPLFlBQUQsSUFBaUIsQ0FBQ0EsWUFBWSxDQUFDRSxNQUFuQyxFQUEyQztBQUN6QyxlQUFPO0FBQUM5SCxVQUFBQSxLQUFLLEVBQUU7QUFBUixTQUFQO0FBQ0Q7O0FBRUQsYUFBTztBQUNMQSxRQUFBQSxLQUFLLEVBQUU0SCxZQUFZLENBQUNsRixHQUFiLENBQWlCLFVBQUFwQyxPQUFPO0FBQUEsaUJBQUs7QUFDbEM4RyxZQUFBQSxLQUFLLEVBQUcsT0FBT0EsS0FBUCxLQUFpQixRQUFqQixJQUE2QkEsS0FBSyxDQUFDVyxPQUFOLENBQWMsV0FBZCxFQUEyQixFQUEzQixDQUE5QixJQUFpRSxNQUFJLENBQUNSLElBRDNDO0FBRWxDakgsWUFBQUEsT0FBTyxFQUFQQSxPQUZrQztBQUdsQzBILFlBQUFBLFNBQVMsRUFBRTtBQUh1QixXQUFMO0FBQUEsU0FBeEI7QUFERixPQUFQO0FBT0Q7OztFQTlHdUNDLHFCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDIxIFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHVuaXEgZnJvbSAnbG9kYXNoLnVuaXEnO1xuaW1wb3J0IHtEQVRBX1RZUEVTfSBmcm9tICd0eXBlLWFuYWx5emVyJztcblxuaW1wb3J0IExheWVyLCB7Y29sb3JNYWtlcn0gZnJvbSAnLi4vYmFzZS1sYXllcic7XG5pbXBvcnQge0dlb0pzb25MYXllciBhcyBEZWNrR0xHZW9Kc29uTGF5ZXJ9IGZyb20gJ0BkZWNrLmdsL2xheWVycyc7XG5pbXBvcnQge2dldEdlb2pzb25EYXRhTWFwcywgZ2V0R2VvanNvbkJvdW5kcywgZ2V0R2VvanNvbkZlYXR1cmVUeXBlc30gZnJvbSAnLi9nZW9qc29uLXV0aWxzJztcbmltcG9ydCBHZW9qc29uTGF5ZXJJY29uIGZyb20gJy4vZ2VvanNvbi1sYXllci1pY29uJztcbmltcG9ydCB7R0VPSlNPTl9GSUVMRFMsIEhJR0hMSUdIX0NPTE9SXzNELCBDSEFOTkVMX1NDQUxFU30gZnJvbSAnY29uc3RhbnRzL2RlZmF1bHQtc2V0dGluZ3MnO1xuaW1wb3J0IHtMQVlFUl9WSVNfQ09ORklHU30gZnJvbSAnbGF5ZXJzL2xheWVyLWZhY3RvcnknO1xuXG5jb25zdCBTVVBQT1JURURfQU5BTFlaRVJfVFlQRVMgPSB7XG4gIFtEQVRBX1RZUEVTLkdFT01FVFJZXTogdHJ1ZSxcbiAgW0RBVEFfVFlQRVMuR0VPTUVUUllfRlJPTV9TVFJJTkddOiB0cnVlLFxuICBbREFUQV9UWVBFUy5QQUlSX0dFT01FVFJZX0ZST01fU1RSSU5HXTogdHJ1ZVxufTtcblxuZXhwb3J0IGNvbnN0IGdlb2pzb25WaXNDb25maWdzID0ge1xuICBvcGFjaXR5OiAnb3BhY2l0eScsXG4gIHN0cm9rZU9wYWNpdHk6IHtcbiAgICAuLi5MQVlFUl9WSVNfQ09ORklHUy5vcGFjaXR5LFxuICAgIHByb3BlcnR5OiAnc3Ryb2tlT3BhY2l0eSdcbiAgfSxcbiAgdGhpY2tuZXNzOiB7XG4gICAgLi4uTEFZRVJfVklTX0NPTkZJR1MudGhpY2tuZXNzLFxuICAgIGRlZmF1bHRWYWx1ZTogMC41XG4gIH0sXG4gIHN0cm9rZUNvbG9yOiAnc3Ryb2tlQ29sb3InLFxuICBjb2xvclJhbmdlOiAnY29sb3JSYW5nZScsXG4gIHN0cm9rZUNvbG9yUmFuZ2U6ICdzdHJva2VDb2xvclJhbmdlJyxcbiAgcmFkaXVzOiAncmFkaXVzJyxcblxuICBzaXplUmFuZ2U6ICdzdHJva2VXaWR0aFJhbmdlJyxcbiAgcmFkaXVzUmFuZ2U6ICdyYWRpdXNSYW5nZScsXG4gIGhlaWdodFJhbmdlOiAnZWxldmF0aW9uUmFuZ2UnLFxuICBlbGV2YXRpb25TY2FsZTogJ2VsZXZhdGlvblNjYWxlJyxcbiAgZW5hYmxlRWxldmF0aW9uWm9vbUZhY3RvcjogJ2VuYWJsZUVsZXZhdGlvblpvb21GYWN0b3InLFxuICBzdHJva2VkOiAnc3Ryb2tlZCcsXG4gIGZpbGxlZDogJ2ZpbGxlZCcsXG4gIGVuYWJsZTNkOiAnZW5hYmxlM2QnLFxuICB3aXJlZnJhbWU6ICd3aXJlZnJhbWUnXG59O1xuXG5leHBvcnQgY29uc3QgZ2VvSnNvblJlcXVpcmVkQ29sdW1ucyA9IFsnZ2VvanNvbiddO1xuZXhwb3J0IGNvbnN0IGZlYXR1cmVBY2Nlc3NvciA9ICh7Z2VvanNvbn0pID0+IGRjID0+IGQgPT4gZGMudmFsdWVBdChkLmluZGV4LCBnZW9qc29uLmZpZWxkSWR4KTtcblxuLy8gYWNjZXNzIGZlYXR1cmUgcHJvcGVydGllcyBmcm9tIGdlb2pzb24gc3ViIGxheWVyXG5leHBvcnQgY29uc3QgZGVmYXVsdEVsZXZhdGlvbiA9IDUwMDtcbmV4cG9ydCBjb25zdCBkZWZhdWx0TGluZVdpZHRoID0gMTtcbmV4cG9ydCBjb25zdCBkZWZhdWx0UmFkaXVzID0gMTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2VvSnNvbkxheWVyIGV4dGVuZHMgTGF5ZXIge1xuICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgIHN1cGVyKHByb3BzKTtcblxuICAgIHRoaXMuZGF0YVRvRmVhdHVyZSA9IFtdO1xuICAgIHRoaXMucmVnaXN0ZXJWaXNDb25maWcoZ2VvanNvblZpc0NvbmZpZ3MpO1xuICAgIHRoaXMuZ2V0UG9zaXRpb25BY2Nlc3NvciA9IGRhdGFDb250YWluZXIgPT4gZmVhdHVyZUFjY2Vzc29yKHRoaXMuY29uZmlnLmNvbHVtbnMpKGRhdGFDb250YWluZXIpO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdnZW9qc29uJztcbiAgfVxuXG4gIGdldCBuYW1lKCkge1xuICAgIHJldHVybiAnUG9seWdvbic7XG4gIH1cblxuICBnZXQgbGF5ZXJJY29uKCkge1xuICAgIHJldHVybiBHZW9qc29uTGF5ZXJJY29uO1xuICB9XG5cbiAgZ2V0IHJlcXVpcmVkTGF5ZXJDb2x1bW5zKCkge1xuICAgIHJldHVybiBnZW9Kc29uUmVxdWlyZWRDb2x1bW5zO1xuICB9XG5cbiAgZ2V0IHZpc3VhbENoYW5uZWxzKCkge1xuICAgIGNvbnN0IHZpc3VhbENoYW5uZWxzID0gc3VwZXIudmlzdWFsQ2hhbm5lbHM7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbG9yOiB7XG4gICAgICAgIC4uLnZpc3VhbENoYW5uZWxzLmNvbG9yLFxuICAgICAgICBhY2Nlc3NvcjogJ2dldEZpbGxDb2xvcicsXG4gICAgICAgIGNvbmRpdGlvbjogY29uZmlnID0+IGNvbmZpZy52aXNDb25maWcuZmlsbGVkLFxuICAgICAgICBudWxsVmFsdWU6IHZpc3VhbENoYW5uZWxzLmNvbG9yLm51bGxWYWx1ZSxcbiAgICAgICAgZ2V0QXR0cmlidXRlVmFsdWU6IGNvbmZpZyA9PiBkID0+IGQucHJvcGVydGllcy5maWxsQ29sb3IgfHwgY29uZmlnLmNvbG9yLFxuICAgICAgICAvLyB1c2VkIHRoaXMgdG8gZ2V0IHVwZGF0ZVRyaWdnZXJzXG4gICAgICAgIGRlZmF1bHRWYWx1ZTogY29uZmlnID0+IGNvbmZpZy5jb2xvclxuICAgICAgfSxcbiAgICAgIHN0cm9rZUNvbG9yOiB7XG4gICAgICAgIHByb3BlcnR5OiAnc3Ryb2tlQ29sb3InLFxuICAgICAgICBmaWVsZDogJ3N0cm9rZUNvbG9yRmllbGQnLFxuICAgICAgICBzY2FsZTogJ3N0cm9rZUNvbG9yU2NhbGUnLFxuICAgICAgICBkb21haW46ICdzdHJva2VDb2xvckRvbWFpbicsXG4gICAgICAgIHJhbmdlOiAnc3Ryb2tlQ29sb3JSYW5nZScsXG4gICAgICAgIGtleTogJ3N0cm9rZUNvbG9yJyxcbiAgICAgICAgY2hhbm5lbFNjYWxlVHlwZTogQ0hBTk5FTF9TQ0FMRVMuY29sb3IsXG4gICAgICAgIGFjY2Vzc29yOiAnZ2V0TGluZUNvbG9yJyxcbiAgICAgICAgY29uZGl0aW9uOiBjb25maWcgPT4gY29uZmlnLnZpc0NvbmZpZy5zdHJva2VkLFxuICAgICAgICBudWxsVmFsdWU6IHZpc3VhbENoYW5uZWxzLmNvbG9yLm51bGxWYWx1ZSxcbiAgICAgICAgZ2V0QXR0cmlidXRlVmFsdWU6IGNvbmZpZyA9PiBkID0+XG4gICAgICAgICAgZC5wcm9wZXJ0aWVzLmxpbmVDb2xvciB8fCBjb25maWcudmlzQ29uZmlnLnN0cm9rZUNvbG9yIHx8IGNvbmZpZy5jb2xvcixcbiAgICAgICAgLy8gdXNlZCB0aGlzIHRvIGdldCB1cGRhdGVUcmlnZ2Vyc1xuICAgICAgICBkZWZhdWx0VmFsdWU6IGNvbmZpZyA9PiBjb25maWcudmlzQ29uZmlnLnN0cm9rZUNvbG9yIHx8IGNvbmZpZy5jb2xvclxuICAgICAgfSxcbiAgICAgIHNpemU6IHtcbiAgICAgICAgLi4udmlzdWFsQ2hhbm5lbHMuc2l6ZSxcbiAgICAgICAgcHJvcGVydHk6ICdzdHJva2UnLFxuICAgICAgICBhY2Nlc3NvcjogJ2dldExpbmVXaWR0aCcsXG4gICAgICAgIGNvbmRpdGlvbjogY29uZmlnID0+IGNvbmZpZy52aXNDb25maWcuc3Ryb2tlZCxcbiAgICAgICAgbnVsbFZhbHVlOiAwLFxuICAgICAgICBnZXRBdHRyaWJ1dGVWYWx1ZTogKCkgPT4gZCA9PiBkLnByb3BlcnRpZXMubGluZVdpZHRoIHx8IGRlZmF1bHRMaW5lV2lkdGhcbiAgICAgIH0sXG4gICAgICBoZWlnaHQ6IHtcbiAgICAgICAgcHJvcGVydHk6ICdoZWlnaHQnLFxuICAgICAgICBmaWVsZDogJ2hlaWdodEZpZWxkJyxcbiAgICAgICAgc2NhbGU6ICdoZWlnaHRTY2FsZScsXG4gICAgICAgIGRvbWFpbjogJ2hlaWdodERvbWFpbicsXG4gICAgICAgIHJhbmdlOiAnaGVpZ2h0UmFuZ2UnLFxuICAgICAgICBrZXk6ICdoZWlnaHQnLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiBDSEFOTkVMX1NDQUxFUy5zaXplLFxuICAgICAgICBhY2Nlc3NvcjogJ2dldEVsZXZhdGlvbicsXG4gICAgICAgIGNvbmRpdGlvbjogY29uZmlnID0+IGNvbmZpZy52aXNDb25maWcuZW5hYmxlM2QsXG4gICAgICAgIG51bGxWYWx1ZTogMCxcbiAgICAgICAgZ2V0QXR0cmlidXRlVmFsdWU6ICgpID0+IGQgPT4gZC5wcm9wZXJ0aWVzLmVsZXZhdGlvbiB8fCBkZWZhdWx0RWxldmF0aW9uXG4gICAgICB9LFxuICAgICAgcmFkaXVzOiB7XG4gICAgICAgIHByb3BlcnR5OiAncmFkaXVzJyxcbiAgICAgICAgZmllbGQ6ICdyYWRpdXNGaWVsZCcsXG4gICAgICAgIHNjYWxlOiAncmFkaXVzU2NhbGUnLFxuICAgICAgICBkb21haW46ICdyYWRpdXNEb21haW4nLFxuICAgICAgICByYW5nZTogJ3JhZGl1c1JhbmdlJyxcbiAgICAgICAga2V5OiAncmFkaXVzJyxcbiAgICAgICAgY2hhbm5lbFNjYWxlVHlwZTogQ0hBTk5FTF9TQ0FMRVMucmFkaXVzLFxuICAgICAgICBhY2Nlc3NvcjogJ2dldFJhZGl1cycsXG4gICAgICAgIG51bGxWYWx1ZTogMCxcbiAgICAgICAgZ2V0QXR0cmlidXRlVmFsdWU6ICgpID0+IGQgPT4gZC5wcm9wZXJ0aWVzLnJhZGl1cyB8fCBkZWZhdWx0UmFkaXVzXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBmaW5kRGVmYXVsdExheWVyUHJvcHMoe2xhYmVsLCBmaWVsZHMgPSBbXX0pIHtcbiAgICBjb25zdCBnZW9qc29uQ29sdW1ucyA9IGZpZWxkc1xuICAgICAgLmZpbHRlcihmID0+IGYudHlwZSA9PT0gJ2dlb2pzb24nICYmIFNVUFBPUlRFRF9BTkFMWVpFUl9UWVBFU1tmLmFuYWx5emVyVHlwZV0pXG4gICAgICAubWFwKGYgPT4gZi5uYW1lKTtcblxuICAgIGNvbnN0IGRlZmF1bHRDb2x1bW5zID0ge1xuICAgICAgZ2VvanNvbjogdW5pcShbLi4uR0VPSlNPTl9GSUVMRFMuZ2VvanNvbiwgLi4uZ2VvanNvbkNvbHVtbnNdKVxuICAgIH07XG5cbiAgICBjb25zdCBmb3VuZENvbHVtbnMgPSB0aGlzLmZpbmREZWZhdWx0Q29sdW1uRmllbGQoZGVmYXVsdENvbHVtbnMsIGZpZWxkcyk7XG4gICAgaWYgKCFmb3VuZENvbHVtbnMgfHwgIWZvdW5kQ29sdW1ucy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB7cHJvcHM6IFtdfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcHJvcHM6IGZvdW5kQ29sdW1ucy5tYXAoY29sdW1ucyA9PiAoe1xuICAgICAgICBsYWJlbDogKHR5cGVvZiBsYWJlbCA9PT0gJ3N0cmluZycgJiYgbGFiZWwucmVwbGFjZSgvXFwuW14vLl0rJC8sICcnKSkgfHwgdGhpcy50eXBlLFxuICAgICAgICBjb2x1bW5zLFxuICAgICAgICBpc1Zpc2libGU6IHRydWVcbiAgICAgIH0pKVxuICAgIH07XG4gIH1cblxuICBnZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMgPSB7fSkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdXBlci5nZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMpLFxuXG4gICAgICAvLyBhZGQgaGVpZ2h0IHZpc3VhbCBjaGFubmVsXG4gICAgICBoZWlnaHRGaWVsZDogbnVsbCxcbiAgICAgIGhlaWdodERvbWFpbjogWzAsIDFdLFxuICAgICAgaGVpZ2h0U2NhbGU6ICdsaW5lYXInLFxuXG4gICAgICAvLyBhZGQgcmFkaXVzIHZpc3VhbCBjaGFubmVsXG4gICAgICByYWRpdXNGaWVsZDogbnVsbCxcbiAgICAgIHJhZGl1c0RvbWFpbjogWzAsIDFdLFxuICAgICAgcmFkaXVzU2NhbGU6ICdsaW5lYXInLFxuXG4gICAgICAvLyBhZGQgc3Ryb2tlIGNvbG9yIHZpc3VhbCBjaGFubmVsXG4gICAgICBzdHJva2VDb2xvckZpZWxkOiBudWxsLFxuICAgICAgc3Ryb2tlQ29sb3JEb21haW46IFswLCAxXSxcbiAgICAgIHN0cm9rZUNvbG9yU2NhbGU6ICdxdWFudGlsZSdcbiAgICB9O1xuICB9XG5cbiAgZ2V0SG92ZXJEYXRhKG9iamVjdCwgZGF0YUNvbnRhaW5lcikge1xuICAgIC8vIGluZGV4IG9mIGRhdGFDb250YWluZXIgaXMgc2F2ZWQgdG8gZmVhdHVyZS5wcm9wZXJ0aWVzXG4gICAgcmV0dXJuIGRhdGFDb250YWluZXIucm93KG9iamVjdC5wcm9wZXJ0aWVzLmluZGV4KTtcbiAgfVxuXG4gIGNhbGN1bGF0ZURhdGFBdHRyaWJ1dGUoe2RhdGFDb250YWluZXIsIGZpbHRlcmVkSW5kZXh9LCBnZXRQb3NpdGlvbikge1xuICAgIHJldHVybiBmaWx0ZXJlZEluZGV4Lm1hcChpID0+IHRoaXMuZGF0YVRvRmVhdHVyZVtpXSkuZmlsdGVyKGQgPT4gZCk7XG4gIH1cblxuICBmb3JtYXRMYXllckRhdGEoZGF0YXNldHMsIG9sZExheWVyRGF0YSkge1xuICAgIGNvbnN0IHtncHVGaWx0ZXIsIGRhdGFDb250YWluZXJ9ID0gZGF0YXNldHNbdGhpcy5jb25maWcuZGF0YUlkXTtcbiAgICBjb25zdCB7ZGF0YX0gPSB0aGlzLnVwZGF0ZURhdGEoZGF0YXNldHMsIG9sZExheWVyRGF0YSk7XG5cbiAgICBjb25zdCBjdXN0b21GaWx0ZXJWYWx1ZUFjY2Vzc29yID0gKGRjLCBkLCBmaWVsZEluZGV4KSA9PiB7XG4gICAgICByZXR1cm4gZGMudmFsdWVBdChkLnByb3BlcnRpZXMuaW5kZXgsIGZpZWxkSW5kZXgpO1xuICAgIH07XG4gICAgY29uc3QgaW5kZXhBY2Nlc3NvciA9IGYgPT4gZi5wcm9wZXJ0aWVzLmluZGV4O1xuXG4gICAgY29uc3QgZGF0YUFjY2Vzc29yID0gZGMgPT4gZCA9PiAoe2luZGV4OiBkLnByb3BlcnRpZXMuaW5kZXh9KTtcbiAgICBjb25zdCBhY2Nlc3NvcnMgPSB0aGlzLmdldEF0dHJpYnV0ZUFjY2Vzc29ycyh7ZGF0YUFjY2Vzc29yLCBkYXRhQ29udGFpbmVyfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0YSxcbiAgICAgIGdldEZpbHRlclZhbHVlOiBncHVGaWx0ZXIuZmlsdGVyVmFsdWVBY2Nlc3NvcihkYXRhQ29udGFpbmVyKShcbiAgICAgICAgaW5kZXhBY2Nlc3NvcixcbiAgICAgICAgY3VzdG9tRmlsdGVyVmFsdWVBY2Nlc3NvclxuICAgICAgKSxcbiAgICAgIC4uLmFjY2Vzc29yc1xuICAgIH07XG4gIH1cblxuICB1cGRhdGVMYXllck1ldGEoZGF0YUNvbnRhaW5lcikge1xuICAgIGNvbnN0IGdldEZlYXR1cmUgPSB0aGlzLmdldFBvc2l0aW9uQWNjZXNzb3IoZGF0YUNvbnRhaW5lcik7XG4gICAgdGhpcy5kYXRhVG9GZWF0dXJlID0gZ2V0R2VvanNvbkRhdGFNYXBzKGRhdGFDb250YWluZXIsIGdldEZlYXR1cmUpO1xuXG4gICAgLy8gZ2V0IGJvdW5kcyBmcm9tIGZlYXR1cmVzXG4gICAgY29uc3QgYm91bmRzID0gZ2V0R2VvanNvbkJvdW5kcyh0aGlzLmRhdGFUb0ZlYXR1cmUpO1xuICAgIC8vIGlmIGFueSBvZiB0aGUgZmVhdHVyZSBoYXMgcHJvcGVydGllcy5yYWRpdXMgc2V0IHRvIGJlIHRydWVcbiAgICBjb25zdCBmaXhlZFJhZGl1cyA9IEJvb2xlYW4oXG4gICAgICB0aGlzLmRhdGFUb0ZlYXR1cmUuZmluZChkID0+IGQgJiYgZC5wcm9wZXJ0aWVzICYmIGQucHJvcGVydGllcy5yYWRpdXMpXG4gICAgKTtcblxuICAgIC8vIGtlZXAgYSByZWNvcmQgb2Ygd2hhdCB0eXBlIG9mIGdlb21ldHJ5IHRoZSBjb2xsZWN0aW9uIGhhc1xuICAgIGNvbnN0IGZlYXR1cmVUeXBlcyA9IGdldEdlb2pzb25GZWF0dXJlVHlwZXModGhpcy5kYXRhVG9GZWF0dXJlKTtcblxuICAgIHRoaXMudXBkYXRlTWV0YSh7Ym91bmRzLCBmaXhlZFJhZGl1cywgZmVhdHVyZVR5cGVzfSk7XG4gIH1cblxuICBzZXRJbml0aWFsTGF5ZXJDb25maWcoe2RhdGFDb250YWluZXJ9KSB7XG4gICAgdGhpcy51cGRhdGVMYXllck1ldGEoZGF0YUNvbnRhaW5lcik7XG5cbiAgICBjb25zdCB7ZmVhdHVyZVR5cGVzfSA9IHRoaXMubWV0YTtcbiAgICAvLyBkZWZhdWx0IHNldHRpbmdzIGlzIHN0cm9rZTogdHJ1ZSwgZmlsbGVkOiBmYWxzZVxuICAgIGlmIChmZWF0dXJlVHlwZXMgJiYgZmVhdHVyZVR5cGVzLnBvbHlnb24pIHtcbiAgICAgIC8vIHNldCBib3RoIGZpbGwgYW5kIHN0cm9rZSB0byB0cnVlXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVMYXllclZpc0NvbmZpZyh7XG4gICAgICAgIGZpbGxlZDogdHJ1ZSxcbiAgICAgICAgc3Ryb2tlZDogdHJ1ZSxcbiAgICAgICAgc3Ryb2tlQ29sb3I6IGNvbG9yTWFrZXIubmV4dCgpLnZhbHVlXG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGZlYXR1cmVUeXBlcyAmJiBmZWF0dXJlVHlwZXMucG9pbnQpIHtcbiAgICAgIC8vIHNldCBmaWxsIHRvIHRydWUgaWYgZGV0ZWN0IHBvaW50XG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVMYXllclZpc0NvbmZpZyh7ZmlsbGVkOiB0cnVlLCBzdHJva2VkOiBmYWxzZX0pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcmVuZGVyTGF5ZXIob3B0cykge1xuICAgIGNvbnN0IHtkYXRhLCBncHVGaWx0ZXIsIG9iamVjdEhvdmVyZWQsIG1hcFN0YXRlLCBpbnRlcmFjdGlvbkNvbmZpZ30gPSBvcHRzO1xuXG4gICAgY29uc3Qge2ZpeGVkUmFkaXVzLCBmZWF0dXJlVHlwZXN9ID0gdGhpcy5tZXRhO1xuICAgIGNvbnN0IHJhZGl1c1NjYWxlID0gdGhpcy5nZXRSYWRpdXNTY2FsZUJ5Wm9vbShtYXBTdGF0ZSwgZml4ZWRSYWRpdXMpO1xuICAgIGNvbnN0IHpvb21GYWN0b3IgPSB0aGlzLmdldFpvb21GYWN0b3IobWFwU3RhdGUpO1xuICAgIGNvbnN0IGVsZVpvb21GYWN0b3IgPSB0aGlzLmdldEVsZXZhdGlvblpvb21GYWN0b3IobWFwU3RhdGUpO1xuXG4gICAgY29uc3Qge3Zpc0NvbmZpZ30gPSB0aGlzLmNvbmZpZztcblxuICAgIGNvbnN0IGxheWVyUHJvcHMgPSB7XG4gICAgICBsaW5lV2lkdGhTY2FsZTogdmlzQ29uZmlnLnRoaWNrbmVzcyAqIHpvb21GYWN0b3IgKiA4LFxuICAgICAgZWxldmF0aW9uU2NhbGU6IHZpc0NvbmZpZy5lbGV2YXRpb25TY2FsZSAqIGVsZVpvb21GYWN0b3IsXG4gICAgICBwb2ludFJhZGl1c1NjYWxlOiByYWRpdXNTY2FsZSxcbiAgICAgIGxpbmVNaXRlckxpbWl0OiA0XG4gICAgfTtcblxuICAgIGNvbnN0IHVwZGF0ZVRyaWdnZXJzID0ge1xuICAgICAgLi4udGhpcy5nZXRWaXN1YWxDaGFubmVsVXBkYXRlVHJpZ2dlcnMoKSxcbiAgICAgIGdldEZpbHRlclZhbHVlOiBncHVGaWx0ZXIuZmlsdGVyVmFsdWVVcGRhdGVUcmlnZ2Vyc1xuICAgIH07XG5cbiAgICBjb25zdCBkZWZhdWx0TGF5ZXJQcm9wcyA9IHRoaXMuZ2V0RGVmYXVsdERlY2tMYXllclByb3BzKG9wdHMpO1xuICAgIGNvbnN0IG9wYU92ZXJ3cml0ZSA9IHtcbiAgICAgIG9wYWNpdHk6IHZpc0NvbmZpZy5zdHJva2VPcGFjaXR5XG4gICAgfTtcblxuICAgIGNvbnN0IHBpY2thYmxlID0gaW50ZXJhY3Rpb25Db25maWcudG9vbHRpcC5lbmFibGVkO1xuICAgIGNvbnN0IGhvdmVyZWRPYmplY3QgPSB0aGlzLmhhc0hvdmVyZWRPYmplY3Qob2JqZWN0SG92ZXJlZCk7XG5cbiAgICByZXR1cm4gW1xuICAgICAgbmV3IERlY2tHTEdlb0pzb25MYXllcih7XG4gICAgICAgIC4uLmRlZmF1bHRMYXllclByb3BzLFxuICAgICAgICAuLi5sYXllclByb3BzLFxuICAgICAgICAuLi5kYXRhLFxuICAgICAgICBwaWNrYWJsZSxcbiAgICAgICAgaGlnaGxpZ2h0Q29sb3I6IEhJR0hMSUdIX0NPTE9SXzNELFxuICAgICAgICBhdXRvSGlnaGxpZ2h0OiB2aXNDb25maWcuZW5hYmxlM2QgJiYgcGlja2FibGUsXG4gICAgICAgIHN0cm9rZWQ6IHZpc0NvbmZpZy5zdHJva2VkLFxuICAgICAgICBmaWxsZWQ6IHZpc0NvbmZpZy5maWxsZWQsXG4gICAgICAgIGV4dHJ1ZGVkOiB2aXNDb25maWcuZW5hYmxlM2QsXG4gICAgICAgIHdpcmVmcmFtZTogdmlzQ29uZmlnLndpcmVmcmFtZSxcbiAgICAgICAgd3JhcExvbmdpdHVkZTogZmFsc2UsXG4gICAgICAgIGxpbmVNaXRlckxpbWl0OiAyLFxuICAgICAgICByb3VuZGVkOiB0cnVlLFxuICAgICAgICB1cGRhdGVUcmlnZ2VycyxcbiAgICAgICAgX3N1YkxheWVyUHJvcHM6IHtcbiAgICAgICAgICAuLi4oZmVhdHVyZVR5cGVzLnBvbHlnb24gPyB7J3BvbHlnb25zLXN0cm9rZSc6IG9wYU92ZXJ3cml0ZX0gOiB7fSksXG4gICAgICAgICAgLi4uKGZlYXR1cmVUeXBlcy5saW5lID8geydsaW5lLXN0cmluZ3MnOiBvcGFPdmVyd3JpdGV9IDoge30pLFxuICAgICAgICAgIC4uLihmZWF0dXJlVHlwZXMucG9pbnRcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIHBvaW50czoge1xuICAgICAgICAgICAgICAgICAgbGluZU9wYWNpdHk6IHZpc0NvbmZpZy5zdHJva2VPcGFjaXR5XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA6IHt9KVxuICAgICAgICB9XG4gICAgICB9KSxcbiAgICAgIC4uLihob3ZlcmVkT2JqZWN0ICYmICF2aXNDb25maWcuZW5hYmxlM2RcbiAgICAgICAgPyBbXG4gICAgICAgICAgICBuZXcgRGVja0dMR2VvSnNvbkxheWVyKHtcbiAgICAgICAgICAgICAgLi4udGhpcy5nZXREZWZhdWx0SG92ZXJMYXllclByb3BzKCksXG4gICAgICAgICAgICAgIC4uLmxheWVyUHJvcHMsXG4gICAgICAgICAgICAgIHdyYXBMb25naXR1ZGU6IGZhbHNlLFxuICAgICAgICAgICAgICBkYXRhOiBbaG92ZXJlZE9iamVjdF0sXG4gICAgICAgICAgICAgIGdldExpbmVXaWR0aDogZGF0YS5nZXRMaW5lV2lkdGgsXG4gICAgICAgICAgICAgIGdldFJhZGl1czogZGF0YS5nZXRSYWRpdXMsXG4gICAgICAgICAgICAgIGdldEVsZXZhdGlvbjogZGF0YS5nZXRFbGV2YXRpb24sXG4gICAgICAgICAgICAgIGdldExpbmVDb2xvcjogdGhpcy5jb25maWcuaGlnaGxpZ2h0Q29sb3IsXG4gICAgICAgICAgICAgIGdldEZpbGxDb2xvcjogdGhpcy5jb25maWcuaGlnaGxpZ2h0Q29sb3IsXG4gICAgICAgICAgICAgIC8vIGFsd2F5cyBkcmF3IG91dGxpbmVcbiAgICAgICAgICAgICAgc3Ryb2tlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgZmlsbGVkOiBmYWxzZVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICBdXG4gICAgICAgIDogW10pXG4gICAgXTtcbiAgfVxufVxuIl19