kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
399 lines (389 loc) • 54.9 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.pointPosResolver = exports.pointPosAccessor = exports.getValueAggrFunc = exports.getFilterDataFunc = exports["default"] = exports.aggregateRequiredColumns = 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 _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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _lodash = _interopRequireDefault(require("lodash.memoize"));
var _baseLayer = _interopRequireDefault(require("./base-layer"));
var _utils = require("@kepler.gl/utils");
var _constants = require("@kepler.gl/constants");
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 _callSuper(t, o, e) { return o = (0, _getPrototypeOf2["default"])(o), (0, _possibleConstructorReturn2["default"])(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2["default"])(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function _superPropGet(t, e, r, o) { var p = (0, _get2["default"])((0, _getPrototypeOf2["default"])(1 & o ? t.prototype : t), e, r); return 2 & o ? function (t) { return p.apply(r, t); } : p; } // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
var pointPosAccessor = exports.pointPosAccessor = function pointPosAccessor(_ref) {
var lat = _ref.lat,
lng = _ref.lng;
return function (dc) {
return function (d) {
return [dc.valueAt(d.index, lng.fieldIdx), dc.valueAt(d.index, lat.fieldIdx)];
};
};
};
var pointPosResolver = exports.pointPosResolver = function pointPosResolver(_ref2) {
var lat = _ref2.lat,
lng = _ref2.lng;
return "".concat(lat.fieldIdx, "-").concat(lng.fieldIdx);
};
var getValueAggrFunc = exports.getValueAggrFunc = function getValueAggrFunc(getPointData) {
return function (field, aggregation) {
return function (points) {
return field ? (0, _utils.aggregate)(points.map(function (p) {
return field.valueAccessor(getPointData(p));
}), aggregation) : points.length;
};
};
};
var getFilterDataFunc = exports.getFilterDataFunc = function getFilterDataFunc(filterRange, getFilterValue) {
return function (pt) {
return getFilterValue(pt).every(function (val, i) {
return val >= filterRange[i][0] && val <= filterRange[i][1];
});
};
};
var getLayerColorRange = function getLayerColorRange(colorRange) {
return colorRange.colors.map(_utils.hexToRgb);
};
var aggregateRequiredColumns = exports.aggregateRequiredColumns = ['lat', 'lng'];
var AggregationLayer = exports["default"] = /*#__PURE__*/function (_Layer) {
function AggregationLayer(props) {
var _this;
(0, _classCallCheck2["default"])(this, AggregationLayer);
_this = _callSuper(this, AggregationLayer, [props]);
(0, _defineProperty2["default"])(_this, "getColorRange", void 0);
_this.getPositionAccessor = function (dataContainer) {
return pointPosAccessor(_this.config.columns)(dataContainer);
};
_this.getColorRange = (0, _lodash["default"])(getLayerColorRange);
// Access data of a point from aggregated bins, depends on how BinSorter works
// Deck.gl's BinSorter puts data in point.source
_this.getPointData = function (pt) {
return pt.source;
};
_this.gpuFilterGetIndex = function (pt) {
return _this.getPointData(pt).index;
};
_this.gpuFilterGetData = function (dataContainer, data, fieldIndex) {
return dataContainer.valueAt(data.index, fieldIndex);
};
return _this;
}
(0, _inherits2["default"])(AggregationLayer, _Layer);
return (0, _createClass2["default"])(AggregationLayer, [{
key: "isAggregated",
get: function get() {
return true;
}
}, {
key: "requiredLayerColumns",
get: function get() {
return aggregateRequiredColumns;
}
}, {
key: "columnPairs",
get: function get() {
return this.defaultPointColumnPairs;
}
}, {
key: "noneLayerDataAffectingProps",
get: function get() {
return [].concat((0, _toConsumableArray2["default"])(_superPropGet(AggregationLayer, "noneLayerDataAffectingProps", this, 1)), ['enable3d', 'colorRange', 'colorDomain', 'sizeRange', 'sizeScale', 'sizeDomain', 'percentile', 'coverage', 'elevationPercentile', 'elevationScale', 'enableElevationZoomFactor', 'fixedHeight']);
}
}, {
key: "visualChannels",
get: function get() {
return {
color: {
aggregation: 'colorAggregation',
channelScaleType: _constants.CHANNEL_SCALES.colorAggr,
defaultMeasure: 'property.pointCount',
domain: 'colorDomain',
field: 'colorField',
key: 'color',
property: 'color',
range: 'colorRange',
scale: 'colorScale'
},
size: {
aggregation: 'sizeAggregation',
channelScaleType: _constants.CHANNEL_SCALES.sizeAggr,
condition: function condition(config) {
return config.visConfig.enable3d;
},
defaultMeasure: 'property.pointCount',
domain: 'sizeDomain',
field: 'sizeField',
key: 'size',
property: 'height',
range: 'sizeRange',
scale: 'sizeScale'
}
};
}
/**
* Get the description of a visualChannel config
* @param key
* @returns
*/
}, {
key: "getVisualChannelDescription",
value: function getVisualChannelDescription(key) {
var _this$visConfigSettin;
var channel = this.visualChannels[key];
if (!channel) return {
label: '',
measure: undefined
};
// e.g. label: Color, measure: Average of ETA
var range = channel.range,
field = channel.field,
defaultMeasure = channel.defaultMeasure,
aggregation = channel.aggregation;
var fieldConfig = this.config[field];
var label = (_this$visConfigSettin = this.visConfigSettings[range]) === null || _this$visConfigSettin === void 0 ? void 0 : _this$visConfigSettin.label;
return {
label: typeof label === 'function' ? label(this.config) : label || '',
measure: fieldConfig && aggregation ? "".concat(this.config.visConfig[aggregation], " of ").concat(fieldConfig.displayName || fieldConfig.name) : defaultMeasure
};
}
}, {
key: "getHoverData",
value: function getHoverData(object, dataContainer, fields) {
if (!object) return object;
var measure = this.config.visConfig.colorAggregation;
// aggregate all fields for the hovered group
var aggregatedData = fields.reduce(function (accu, field) {
accu[field.name] = {
measure: measure,
value: (0, _utils.aggregate)(object.points, measure, function (d) {
return dataContainer.valueAt(d.index, field.fieldIdx);
})
};
return accu;
}, {});
// return aggregated object
return _objectSpread({
aggregatedData: aggregatedData
}, object);
}
}, {
key: "getFilteredItemCount",
value: function getFilteredItemCount() {
// gpu filter not supported
return null;
}
/**
* Aggregation layer handles visual channel aggregation inside deck.gl layer
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}, {
key: "updateLayerVisualChannel",
value: function updateLayerVisualChannel(_ref3, channel) {
var dataContainer = _ref3.dataContainer;
this.validateVisualChannel(channel);
}
/**
* Validate aggregation type on top of basic layer visual channel validation
* @param channel
*/
}, {
key: "validateVisualChannel",
value: function validateVisualChannel(channel) {
// field type decides aggregation type decides scale type
this.validateFieldType(channel);
this.validateAggregationType(channel);
this.validateScale(channel);
}
/**
* Validate aggregation type based on selected field
*/
}, {
key: "validateAggregationType",
value: function validateAggregationType(channel) {
var visualChannel = this.visualChannels[channel];
var field = visualChannel.field,
aggregation = visualChannel.aggregation;
var aggregationOptions = this.getAggregationOptions(channel);
if (!aggregation) {
return;
}
if (!aggregationOptions.length) {
// if field cannot be aggregated, set field to null
this.updateLayerConfig((0, _defineProperty2["default"])({}, field, null));
} else if (!aggregationOptions.includes(this.config.visConfig[aggregation])) {
// current aggregation type is not supported by this field
// set aggregation to the first supported option
this.updateLayerVisConfig((0, _defineProperty2["default"])({}, aggregation, aggregationOptions[0]));
}
}
}, {
key: "getAggregationOptions",
value: function getAggregationOptions(channel) {
var visualChannel = this.visualChannels[channel];
var field = visualChannel.field,
channelScaleType = visualChannel.channelScaleType;
return Object.keys(this.config[field] ? _constants.FIELD_OPTS[this.config[field].type].scale[channelScaleType] : _constants.DEFAULT_AGGREGATION[channelScaleType]);
}
/**
* Get scale options based on current field and aggregation type
* @param channel
* @returns
*/
}, {
key: "getScaleOptions",
value: function getScaleOptions(channel) {
var visualChannel = this.visualChannels[channel];
var field = visualChannel.field,
aggregation = visualChannel.aggregation,
channelScaleType = visualChannel.channelScaleType;
var aggregationType = aggregation ? this.config.visConfig[aggregation] : null;
if (!aggregationType) {
return [];
}
return this.config[field] ?
// scale options based on aggregation
_constants.FIELD_OPTS[this.config[field].type].scale[channelScaleType][aggregationType] :
// default scale options for point count: aggregationType should be count since
// LAYER_VIS_CONFIGS.aggregation.defaultValue is AGGREGATION_TYPES.average,
_constants.DEFAULT_AGGREGATION[channelScaleType][_constants.AGGREGATION_TYPES.count];
}
/**
* Aggregation layer handles visual channel aggregation inside deck.gl layer
*/
}, {
key: "updateLayerDomain",
value: function updateLayerDomain() {
return this;
}
}, {
key: "updateLayerMeta",
value: function updateLayerMeta(dataset, getPosition) {
var dataContainer = dataset.dataContainer;
// get bounds from points
var bounds = this.getPointsBounds(dataContainer, getPosition);
this.updateMeta({
bounds: bounds
});
}
}, {
key: "calculateDataAttribute",
value: function calculateDataAttribute(_ref4, getPosition) {
var filteredIndex = _ref4.filteredIndex;
var data = [];
for (var i = 0; i < filteredIndex.length; i++) {
var index = filteredIndex[i];
var pos = getPosition({
index: index
});
// if doesn't have point lat or lng, do not add the point
// deck.gl can't handle position = null
if (pos.every(Number.isFinite)) {
data.push({
index: index
});
}
}
return data;
}
}, {
key: "formatLayerData",
value: function formatLayerData(datasets, oldLayerData) {
if (this.config.dataId === null) {
return {};
}
var _datasets$this$config = datasets[this.config.dataId],
gpuFilter = _datasets$this$config.gpuFilter,
dataContainer = _datasets$this$config.dataContainer;
var getPosition = this.getPositionAccessor(dataContainer);
var aggregatePoints = getValueAggrFunc(this.getPointData);
var getColorValue = aggregatePoints(this.config.colorField, this.config.visConfig.colorAggregation);
var getElevationValue = aggregatePoints(this.config.sizeField, this.config.visConfig.sizeAggregation);
var hasFilter = Object.values(gpuFilter.filterRange).some(function (arr) {
return arr.some(function (v) {
return v !== 0;
});
});
var getFilterValue = gpuFilter.filterValueAccessor(dataContainer)(this.gpuFilterGetIndex, this.gpuFilterGetData);
var filterData = hasFilter ? getFilterDataFunc(gpuFilter.filterRange, getFilterValue) : undefined;
var _this$updateData = this.updateData(datasets, oldLayerData),
data = _this$updateData.data;
return _objectSpread(_objectSpread({
data: data,
getPosition: getPosition,
_filterData: filterData
}, getColorValue ? {
getColorValue: getColorValue
} : {}), getElevationValue ? {
getElevationValue: getElevationValue
} : {});
}
}, {
key: "getDefaultDeckLayerProps",
value: function getDefaultDeckLayerProps(opts) {
var baseProp = _superPropGet(AggregationLayer, "getDefaultDeckLayerProps", this, 3)([opts]);
return _objectSpread(_objectSpread({}, baseProp), {}, {
highlightColor: _constants.HIGHLIGH_COLOR_3D,
// gpu data filtering is not supported in aggregation layer
extensions: [],
autoHighlight: this.config.visConfig.enable3d
});
}
}, {
key: "getDefaultAggregationLayerProp",
value: function getDefaultAggregationLayerProp(opts) {
var gpuFilter = opts.gpuFilter,
mapState = opts.mapState,
_opts$layerCallbacks = opts.layerCallbacks,
layerCallbacks = _opts$layerCallbacks === void 0 ? {} : _opts$layerCallbacks;
var visConfig = this.config.visConfig;
var eleZoomFactor = this.getElevationZoomFactor(mapState);
var updateTriggers = {
getColorValue: {
colorField: this.config.colorField,
colorAggregation: this.config.visConfig.colorAggregation
},
getElevationValue: {
sizeField: this.config.sizeField,
sizeAggregation: this.config.visConfig.sizeAggregation
},
_filterData: _objectSpread({
filterRange: gpuFilter.filterRange
}, gpuFilter.filterValueUpdateTriggers)
};
return _objectSpread(_objectSpread({}, this.getDefaultDeckLayerProps(opts)), {}, {
coverage: visConfig.coverage,
// color
colorRange: this.getColorRange(visConfig.colorRange),
colorMap: visConfig.colorRange.colorMap,
colorScaleType: this.config.colorScale,
upperPercentile: visConfig.percentile[1],
lowerPercentile: visConfig.percentile[0],
colorAggregation: visConfig.colorAggregation,
// elevation
extruded: visConfig.enable3d,
elevationScale: visConfig.elevationScale * eleZoomFactor,
elevationScaleType: this.config.sizeScale,
elevationRange: visConfig.sizeRange,
elevationFixed: visConfig.fixedHeight,
elevationLowerPercentile: visConfig.elevationPercentile[0],
elevationUpperPercentile: visConfig.elevationPercentile[1],
// updateTriggers
updateTriggers: updateTriggers,
// callbacks
onSetColorDomain: layerCallbacks.onSetLayerDomain
});
}
}]);
}(_baseLayer["default"]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9kYXNoIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfYmFzZUxheWVyIiwiX3V0aWxzIiwiX2NvbnN0YW50cyIsIm93bktleXMiLCJlIiwiciIsInQiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsImRlZmluZVByb3BlcnR5IiwiX2NhbGxTdXBlciIsIl9nZXRQcm90b3R5cGVPZjIiLCJfcG9zc2libGVDb25zdHJ1Y3RvclJldHVybjIiLCJfaXNOYXRpdmVSZWZsZWN0Q29uc3RydWN0IiwiUmVmbGVjdCIsImNvbnN0cnVjdCIsImNvbnN0cnVjdG9yIiwiQm9vbGVhbiIsInByb3RvdHlwZSIsInZhbHVlT2YiLCJjYWxsIiwiX3N1cGVyUHJvcEdldCIsInAiLCJfZ2V0MiIsInBvaW50UG9zQWNjZXNzb3IiLCJleHBvcnRzIiwiX3JlZiIsImxhdCIsImxuZyIsImRjIiwiZCIsInZhbHVlQXQiLCJpbmRleCIsImZpZWxkSWR4IiwicG9pbnRQb3NSZXNvbHZlciIsIl9yZWYyIiwiY29uY2F0IiwiZ2V0VmFsdWVBZ2dyRnVuYyIsImdldFBvaW50RGF0YSIsImZpZWxkIiwiYWdncmVnYXRpb24iLCJwb2ludHMiLCJhZ2dyZWdhdGUiLCJtYXAiLCJ2YWx1ZUFjY2Vzc29yIiwiZ2V0RmlsdGVyRGF0YUZ1bmMiLCJmaWx0ZXJSYW5nZSIsImdldEZpbHRlclZhbHVlIiwicHQiLCJldmVyeSIsInZhbCIsImkiLCJnZXRMYXllckNvbG9yUmFuZ2UiLCJjb2xvclJhbmdlIiwiY29sb3JzIiwiaGV4VG9SZ2IiLCJhZ2dyZWdhdGVSZXF1aXJlZENvbHVtbnMiLCJBZ2dyZWdhdGlvbkxheWVyIiwiX0xheWVyIiwicHJvcHMiLCJfdGhpcyIsIl9jbGFzc0NhbGxDaGVjazIiLCJnZXRQb3NpdGlvbkFjY2Vzc29yIiwiZGF0YUNvbnRhaW5lciIsImNvbmZpZyIsImNvbHVtbnMiLCJnZXRDb2xvclJhbmdlIiwibWVtb2l6ZSIsInNvdXJjZSIsImdwdUZpbHRlckdldEluZGV4IiwiZ3B1RmlsdGVyR2V0RGF0YSIsImRhdGEiLCJmaWVsZEluZGV4IiwiX2luaGVyaXRzMiIsIl9jcmVhdGVDbGFzczIiLCJrZXkiLCJnZXQiLCJkZWZhdWx0UG9pbnRDb2x1bW5QYWlycyIsIl90b0NvbnN1bWFibGVBcnJheTIiLCJjb2xvciIsImNoYW5uZWxTY2FsZVR5cGUiLCJDSEFOTkVMX1NDQUxFUyIsImNvbG9yQWdnciIsImRlZmF1bHRNZWFzdXJlIiwiZG9tYWluIiwicHJvcGVydHkiLCJyYW5nZSIsInNjYWxlIiwic2l6ZSIsInNpemVBZ2dyIiwiY29uZGl0aW9uIiwidmlzQ29uZmlnIiwiZW5hYmxlM2QiLCJ2YWx1ZSIsImdldFZpc3VhbENoYW5uZWxEZXNjcmlwdGlvbiIsIl90aGlzJHZpc0NvbmZpZ1NldHRpbiIsImNoYW5uZWwiLCJ2aXN1YWxDaGFubmVscyIsImxhYmVsIiwibWVhc3VyZSIsInVuZGVmaW5lZCIsImZpZWxkQ29uZmlnIiwidmlzQ29uZmlnU2V0dGluZ3MiLCJkaXNwbGF5TmFtZSIsIm5hbWUiLCJnZXRIb3ZlckRhdGEiLCJvYmplY3QiLCJmaWVsZHMiLCJjb2xvckFnZ3JlZ2F0aW9uIiwiYWdncmVnYXRlZERhdGEiLCJyZWR1Y2UiLCJhY2N1IiwiZ2V0RmlsdGVyZWRJdGVtQ291bnQiLCJ1cGRhdGVMYXllclZpc3VhbENoYW5uZWwiLCJfcmVmMyIsInZhbGlkYXRlVmlzdWFsQ2hhbm5lbCIsInZhbGlkYXRlRmllbGRUeXBlIiwidmFsaWRhdGVBZ2dyZWdhdGlvblR5cGUiLCJ2YWxpZGF0ZVNjYWxlIiwidmlzdWFsQ2hhbm5lbCIsImFnZ3JlZ2F0aW9uT3B0aW9ucyIsImdldEFnZ3JlZ2F0aW9uT3B0aW9ucyIsInVwZGF0ZUxheWVyQ29uZmlnIiwiaW5jbHVkZXMiLCJ1cGRhdGVMYXllclZpc0NvbmZpZyIsIkZJRUxEX09QVFMiLCJ0eXBlIiwiREVGQVVMVF9BR0dSRUdBVElPTiIsImdldFNjYWxlT3B0aW9ucyIsImFnZ3JlZ2F0aW9uVHlwZSIsIkFHR1JFR0FUSU9OX1RZUEVTIiwiY291bnQiLCJ1cGRhdGVMYXllckRvbWFpbiIsInVwZGF0ZUxheWVyTWV0YSIsImRhdGFzZXQiLCJnZXRQb3NpdGlvbiIsImJvdW5kcyIsImdldFBvaW50c0JvdW5kcyIsInVwZGF0ZU1ldGEiLCJjYWxjdWxhdGVEYXRhQXR0cmlidXRlIiwiX3JlZjQiLCJmaWx0ZXJlZEluZGV4IiwicG9zIiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJmb3JtYXRMYXllckRhdGEiLCJkYXRhc2V0cyIsIm9sZExheWVyRGF0YSIsImRhdGFJZCIsIl9kYXRhc2V0cyR0aGlzJGNvbmZpZyIsImdwdUZpbHRlciIsImFnZ3JlZ2F0ZVBvaW50cyIsImdldENvbG9yVmFsdWUiLCJjb2xvckZpZWxkIiwiZ2V0RWxldmF0aW9uVmFsdWUiLCJzaXplRmllbGQiLCJzaXplQWdncmVnYXRpb24iLCJoYXNGaWx0ZXIiLCJ2YWx1ZXMiLCJzb21lIiwiYXJyIiwidiIsImZpbHRlclZhbHVlQWNjZXNzb3IiLCJmaWx0ZXJEYXRhIiwiX3RoaXMkdXBkYXRlRGF0YSIsInVwZGF0ZURhdGEiLCJfZmlsdGVyRGF0YSIsImdldERlZmF1bHREZWNrTGF5ZXJQcm9wcyIsIm9wdHMiLCJiYXNlUHJvcCIsImhpZ2hsaWdodENvbG9yIiwiSElHSExJR0hfQ09MT1JfM0QiLCJleHRlbnNpb25zIiwiYXV0b0hpZ2hsaWdodCIsImdldERlZmF1bHRBZ2dyZWdhdGlvbkxheWVyUHJvcCIsIm1hcFN0YXRlIiwiX29wdHMkbGF5ZXJDYWxsYmFja3MiLCJsYXllckNhbGxiYWNrcyIsImVsZVpvb21GYWN0b3IiLCJnZXRFbGV2YXRpb25ab29tRmFjdG9yIiwidXBkYXRlVHJpZ2dlcnMiLCJmaWx0ZXJWYWx1ZVVwZGF0ZVRyaWdnZXJzIiwiY292ZXJhZ2UiLCJjb2xvck1hcCIsImNvbG9yU2NhbGVUeXBlIiwiY29sb3JTY2FsZSIsInVwcGVyUGVyY2VudGlsZSIsInBlcmNlbnRpbGUiLCJsb3dlclBlcmNlbnRpbGUiLCJleHRydWRlZCIsImVsZXZhdGlvblNjYWxlIiwiZWxldmF0aW9uU2NhbGVUeXBlIiwic2l6ZVNjYWxlIiwiZWxldmF0aW9uUmFuZ2UiLCJzaXplUmFuZ2UiLCJlbGV2YXRpb25GaXhlZCIsImZpeGVkSGVpZ2h0IiwiZWxldmF0aW9uTG93ZXJQZXJjZW50aWxlIiwiZWxldmF0aW9uUGVyY2VudGlsZSIsImVsZXZhdGlvblVwcGVyUGVyY2VudGlsZSIsIm9uU2V0Q29sb3JEb21haW4iLCJvblNldExheWVyRG9tYWluIiwiTGF5ZXIiXSwic291cmNlcyI6WyIuLi9zcmMvYWdncmVnYXRpb24tbGF5ZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0IG1lbW9pemUgZnJvbSAnbG9kYXNoLm1lbW9pemUnO1xuaW1wb3J0IExheWVyLCB7XG4gIExheWVyQmFzZUNvbmZpZyxcbiAgTGF5ZXJCYXNlQ29uZmlnUGFydGlhbCxcbiAgTGF5ZXJDb2xvckNvbmZpZyxcbiAgTGF5ZXJTaXplQ29uZmlnLFxuICBWaXN1YWxDaGFubmVsRGVzY3JpcHRpb24sXG4gIFZpc3VhbENoYW5uZWxzXG59IGZyb20gJy4vYmFzZS1sYXllcic7XG5pbXBvcnQge2hleFRvUmdiLCBhZ2dyZWdhdGUsIERhdGFDb250YWluZXJJbnRlcmZhY2V9IGZyb20gJ0BrZXBsZXIuZ2wvdXRpbHMnO1xuaW1wb3J0IHtcbiAgSElHSExJR0hfQ09MT1JfM0QsXG4gIENIQU5ORUxfU0NBTEVTLFxuICBGSUVMRF9PUFRTLFxuICBERUZBVUxUX0FHR1JFR0FUSU9OLFxuICBBR0dSRUdBVElPTl9UWVBFU1xufSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5pbXBvcnQge0NvbG9yUmFuZ2UsIEZpZWxkLCBMYXllckNvbHVtbiwgTWVyZ2V9IGZyb20gJ0BrZXBsZXIuZ2wvdHlwZXMnO1xuaW1wb3J0IHtLZXBsZXJUYWJsZSwgRGF0YXNldHN9IGZyb20gJ0BrZXBsZXIuZ2wvdGFibGUnO1xuXG50eXBlIEFnZ3JlZ2F0aW9uTGF5ZXJDb2x1bW5zID0ge1xuICBsYXQ6IExheWVyQ29sdW1uO1xuICBsbmc6IExheWVyQ29sdW1uO1xufTtcblxuZXhwb3J0IHR5cGUgQWdncmVnYXRpb25MYXllckRhdGEgPSB7XG4gIGluZGV4OiBudW1iZXI7XG59O1xuXG5leHBvcnQgY29uc3QgcG9pbnRQb3NBY2Nlc3NvciA9XG4gICh7bGF0LCBsbmd9OiBBZ2dyZWdhdGlvbkxheWVyQ29sdW1ucykgPT5cbiAgZGMgPT5cbiAgZCA9PlxuICAgIFtkYy52YWx1ZUF0KGQuaW5kZXgsIGxuZy5maWVsZElkeCksIGRjLnZhbHVlQXQoZC5pbmRleCwgbGF0LmZpZWxkSWR4KV07XG5cbmV4cG9ydCBjb25zdCBwb2ludFBvc1Jlc29sdmVyID0gKHtsYXQsIGxuZ306IEFnZ3JlZ2F0aW9uTGF5ZXJDb2x1bW5zKSA9PlxuICBgJHtsYXQuZmllbGRJZHh9LSR7bG5nLmZpZWxkSWR4fWA7XG5cbmV4cG9ydCBjb25zdCBnZXRWYWx1ZUFnZ3JGdW5jID0gZ2V0UG9pbnREYXRhID0+IChmaWVsZCwgYWdncmVnYXRpb24pID0+IHBvaW50cyA9PlxuICBmaWVsZFxuICAgID8gYWdncmVnYXRlKFxuICAgICAgICBwb2ludHMubWFwKHAgPT4gZmllbGQudmFsdWVBY2Nlc3NvcihnZXRQb2ludERhdGEocCkpKSxcbiAgICAgICAgYWdncmVnYXRpb25cbiAgICAgIClcbiAgICA6IHBvaW50cy5sZW5ndGg7XG5cbmV4cG9ydCBjb25zdCBnZXRGaWx0ZXJEYXRhRnVuYyA9XG4gIChcbiAgICBmaWx0ZXJSYW5nZTogbnVtYmVyW11bXSxcbiAgICBnZXRGaWx0ZXJWYWx1ZTogKGQ6IHVua25vd24pID0+IChudW1iZXIgfCBudW1iZXJbXSlbXVxuICApOiAoKGQ6IHVua25vd24pID0+IGJvb2xlYW4pID0+XG4gIHB0ID0+XG4gICAgZ2V0RmlsdGVyVmFsdWUocHQpLmV2ZXJ5KCh2YWwsIGkpID0+IHZhbCA+PSBmaWx0ZXJSYW5nZVtpXVswXSAmJiB2YWwgPD0gZmlsdGVyUmFuZ2VbaV1bMV0pO1xuXG5jb25zdCBnZXRMYXllckNvbG9yUmFuZ2UgPSAoY29sb3JSYW5nZTogQ29sb3JSYW5nZSkgPT4gY29sb3JSYW5nZS5jb2xvcnMubWFwKGhleFRvUmdiKTtcblxuZXhwb3J0IGNvbnN0IGFnZ3JlZ2F0ZVJlcXVpcmVkQ29sdW1uczogWydsYXQnLCAnbG5nJ10gPSBbJ2xhdCcsICdsbmcnXTtcblxuZXhwb3J0IHR5cGUgQWdncmVnYXRpb25MYXllclZpc3VhbENoYW5uZWxDb25maWcgPSBMYXllckNvbG9yQ29uZmlnICYgTGF5ZXJTaXplQ29uZmlnO1xuZXhwb3J0IHR5cGUgQWdncmVnYXRpb25MYXllckNvbmZpZyA9IE1lcmdlPExheWVyQmFzZUNvbmZpZywge2NvbHVtbnM6IEFnZ3JlZ2F0aW9uTGF5ZXJDb2x1bW5zfT4gJlxuICBBZ2dyZWdhdGlvbkxheWVyVmlzdWFsQ2hhbm5lbENvbmZpZztcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEFnZ3JlZ2F0aW9uTGF5ZXIgZXh0ZW5kcyBMYXllciB7XG4gIGdldENvbG9yUmFuZ2U6IGFueTtcbiAgZGVjbGFyZSBjb25maWc6IEFnZ3JlZ2F0aW9uTGF5ZXJDb25maWc7XG4gIGRlY2xhcmUgZ2V0UG9pbnREYXRhOiAoYW55KSA9PiBhbnk7XG4gIGRlY2xhcmUgZ3B1RmlsdGVyR2V0SW5kZXg6IChhbnkpID0+IG51bWJlcjtcbiAgZGVjbGFyZSBncHVGaWx0ZXJHZXREYXRhOiAoZGF0YUNvbnRhaW5lciwgZGF0YSwgZmllbGRJbmRleCkgPT4gYW55O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3BzOiB7XG4gICAgICBpZD86IHN0cmluZztcbiAgICB9ICYgTGF5ZXJCYXNlQ29uZmlnUGFydGlhbFxuICApIHtcbiAgICBzdXBlcihwcm9wcyk7XG5cbiAgICB0aGlzLmdldFBvc2l0aW9uQWNjZXNzb3IgPSBkYXRhQ29udGFpbmVyID0+XG4gICAgICBwb2ludFBvc0FjY2Vzc29yKHRoaXMuY29uZmlnLmNvbHVtbnMpKGRhdGFDb250YWluZXIpO1xuICAgIHRoaXMuZ2V0Q29sb3JSYW5nZSA9IG1lbW9pemUoZ2V0TGF5ZXJDb2xvclJhbmdlKTtcblxuICAgIC8vIEFjY2VzcyBkYXRhIG9mIGEgcG9pbnQgZnJvbSBhZ2dyZWdhdGVkIGJpbnMsIGRlcGVuZHMgb24gaG93IEJpblNvcnRlciB3b3Jrc1xuICAgIC8vIERlY2suZ2wncyBCaW5Tb3J0ZXIgcHV0cyBkYXRhIGluIHBvaW50LnNvdXJjZVxuICAgIHRoaXMuZ2V0UG9pbnREYXRhID0gcHQgPT4gcHQuc291cmNlO1xuXG4gICAgdGhpcy5ncHVGaWx0ZXJHZXRJbmRleCA9IHB0ID0+IHRoaXMuZ2V0UG9pbnREYXRhKHB0KS5pbmRleDtcbiAgICB0aGlzLmdwdUZpbHRlckdldERhdGEgPSAoZGF0YUNvbnRhaW5lciwgZGF0YSwgZmllbGRJbmRleCkgPT5cbiAgICAgIGRhdGFDb250YWluZXIudmFsdWVBdChkYXRhLmluZGV4LCBmaWVsZEluZGV4KTtcbiAgfVxuXG4gIGdldCBpc0FnZ3JlZ2F0ZWQoKTogdHJ1ZSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBnZXQgcmVxdWlyZWRMYXllckNvbHVtbnMoKSB7XG4gICAgcmV0dXJuIGFnZ3JlZ2F0ZVJlcXVpcmVkQ29sdW1ucztcbiAgfVxuXG4gIGdldCBjb2x1bW5QYWlycygpIHtcbiAgICByZXR1cm4gdGhpcy5kZWZhdWx0UG9pbnRDb2x1bW5QYWlycztcbiAgfVxuXG4gIGdldCBub25lTGF5ZXJEYXRhQWZmZWN0aW5nUHJvcHMoKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgIC4uLnN1cGVyLm5vbmVMYXllckRhdGFBZmZlY3RpbmdQcm9wcyxcbiAgICAgICdlbmFibGUzZCcsXG4gICAgICAnY29sb3JSYW5nZScsXG4gICAgICAnY29sb3JEb21haW4nLFxuICAgICAgJ3NpemVSYW5nZScsXG4gICAgICAnc2l6ZVNjYWxlJyxcbiAgICAgICdzaXplRG9tYWluJyxcbiAgICAgICdwZXJjZW50aWxlJyxcbiAgICAgICdjb3ZlcmFnZScsXG4gICAgICAnZWxldmF0aW9uUGVyY2VudGlsZScsXG4gICAgICAnZWxldmF0aW9uU2NhbGUnLFxuICAgICAgJ2VuYWJsZUVsZXZhdGlvblpvb21GYWN0b3InLFxuICAgICAgJ2ZpeGVkSGVpZ2h0J1xuICAgIF07XG4gIH1cblxuICBnZXQgdmlzdWFsQ2hhbm5lbHMoKTogVmlzdWFsQ2hhbm5lbHMge1xuICAgIHJldHVybiB7XG4gICAgICBjb2xvcjoge1xuICAgICAgICBhZ2dyZWdhdGlvbjogJ2NvbG9yQWdncmVnYXRpb24nLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiBDSEFOTkVMX1NDQUxFUy5jb2xvckFnZ3IsXG4gICAgICAgIGRlZmF1bHRNZWFzdXJlOiAncHJvcGVydHkucG9pbnRDb3VudCcsXG4gICAgICAgIGRvbWFpbjogJ2NvbG9yRG9tYWluJyxcbiAgICAgICAgZmllbGQ6ICdjb2xvckZpZWxkJyxcbiAgICAgICAga2V5OiAnY29sb3InLFxuICAgICAgICBwcm9wZXJ0eTogJ2NvbG9yJyxcbiAgICAgICAgcmFuZ2U6ICdjb2xvclJhbmdlJyxcbiAgICAgICAgc2NhbGU6ICdjb2xvclNjYWxlJ1xuICAgICAgfSxcbiAgICAgIHNpemU6IHtcbiAgICAgICAgYWdncmVnYXRpb246ICdzaXplQWdncmVnYXRpb24nLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiBDSEFOTkVMX1NDQUxFUy5zaXplQWdncixcbiAgICAgICAgY29uZGl0aW9uOiBjb25maWcgPT4gY29uZmlnLnZpc0NvbmZpZy5lbmFibGUzZCxcbiAgICAgICAgZGVmYXVsdE1lYXN1cmU6ICdwcm9wZXJ0eS5wb2ludENvdW50JyxcbiAgICAgICAgZG9tYWluOiAnc2l6ZURvbWFpbicsXG4gICAgICAgIGZpZWxkOiAnc2l6ZUZpZWxkJyxcbiAgICAgICAga2V5OiAnc2l6ZScsXG4gICAgICAgIHByb3BlcnR5OiAnaGVpZ2h0JyxcbiAgICAgICAgcmFuZ2U6ICdzaXplUmFuZ2UnLFxuICAgICAgICBzY2FsZTogJ3NpemVTY2FsZSdcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZGVzY3JpcHRpb24gb2YgYSB2aXN1YWxDaGFubmVsIGNvbmZpZ1xuICAgKiBAcGFyYW0ga2V5XG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBnZXRWaXN1YWxDaGFubmVsRGVzY3JpcHRpb24oa2V5OiBzdHJpbmcpOiBWaXN1YWxDaGFubmVsRGVzY3JpcHRpb24ge1xuICAgIGNvbnN0IGNoYW5uZWwgPSB0aGlzLnZpc3VhbENoYW5uZWxzW2tleV07XG4gICAgaWYgKCFjaGFubmVsKSByZXR1cm4ge2xhYmVsOiAnJywgbWVhc3VyZTogdW5kZWZpbmVkfTtcbiAgICAvLyBlLmcuIGxhYmVsOiBDb2xvciwgbWVhc3VyZTogQXZlcmFnZSBvZiBFVEFcbiAgICBjb25zdCB7cmFuZ2UsIGZpZWxkLCBkZWZhdWx0TWVhc3VyZSwgYWdncmVnYXRpb259ID0gY2hhbm5lbDtcbiAgICBjb25zdCBmaWVsZENvbmZpZyA9IHRoaXMuY29uZmlnW2ZpZWxkXTtcbiAgICBjb25zdCBsYWJlbCA9IHRoaXMudmlzQ29uZmlnU2V0dGluZ3NbcmFuZ2VdPy5sYWJlbDtcblxuICAgIHJldHVybiB7XG4gICAgICBsYWJlbDogdHlwZW9mIGxhYmVsID09PSAnZnVuY3Rpb24nID8gbGFiZWwodGhpcy5jb25maWcpIDogbGFiZWwgfHwgJycsXG4gICAgICBtZWFzdXJlOlxuICAgICAgICBmaWVsZENvbmZpZyAmJiBhZ2dyZWdhdGlvblxuICAgICAgICAgID8gYCR7dGhpcy5jb25maWcudmlzQ29uZmlnW2FnZ3JlZ2F0aW9uXX0gb2YgJHtcbiAgICAgICAgICAgICAgZmllbGRDb25maWcuZGlzcGxheU5hbWUgfHwgZmllbGRDb25maWcubmFtZVxuICAgICAgICAgICAgfWBcbiAgICAgICAgICA6IGRlZmF1bHRNZWFzdXJlXG4gICAgfTtcbiAgfVxuXG4gIGdldEhvdmVyRGF0YShvYmplY3Q6IGFueSwgZGF0YUNvbnRhaW5lcjogRGF0YUNvbnRhaW5lckludGVyZmFjZSwgZmllbGRzOiBGaWVsZFtdKTogYW55IHtcbiAgICBpZiAoIW9iamVjdCkgcmV0dXJuIG9iamVjdDtcbiAgICBjb25zdCBtZWFzdXJlID0gdGhpcy5jb25maWcudmlzQ29uZmlnLmNvbG9yQWdncmVnYXRpb247XG4gICAgLy8gYWdncmVnYXRlIGFsbCBmaWVsZHMgZm9yIHRoZSBob3ZlcmVkIGdyb3VwXG4gICAgY29uc3QgYWdncmVnYXRlZERhdGEgPSBmaWVsZHMucmVkdWNlKChhY2N1LCBmaWVsZCkgPT4ge1xuICAgICAgYWNjdVtmaWVsZC5uYW1lXSA9IHtcbiAgICAgICAgbWVhc3VyZSxcbiAgICAgICAgdmFsdWU6IGFnZ3JlZ2F0ZShvYmplY3QucG9pbnRzLCBtZWFzdXJlLCAoZDoge2luZGV4OiBudW1iZXJ9KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGRhdGFDb250YWluZXIudmFsdWVBdChkLmluZGV4LCBmaWVsZC5maWVsZElkeCk7XG4gICAgICAgIH0pXG4gICAgICB9O1xuICAgICAgcmV0dXJuIGFjY3U7XG4gICAgfSwge30pO1xuXG4gICAgLy8gcmV0dXJuIGFnZ3JlZ2F0ZWQgb2JqZWN0XG4gICAgcmV0dXJuIHthZ2dyZWdhdGVkRGF0YSwgLi4ub2JqZWN0fTtcbiAgfVxuXG4gIGdldEZpbHRlcmVkSXRlbUNvdW50KCkge1xuICAgIC8vIGdwdSBmaWx0ZXIgbm90IHN1cHBvcnRlZFxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEFnZ3JlZ2F0aW9uIGxheWVyIGhhbmRsZXMgdmlzdWFsIGNoYW5uZWwgYWdncmVnYXRpb24gaW5zaWRlIGRlY2suZ2wgbGF5ZXJcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgdXBkYXRlTGF5ZXJWaXN1YWxDaGFubmVsKHtkYXRhQ29udGFpbmVyfSwgY2hhbm5lbCkge1xuICAgIHRoaXMudmFsaWRhdGVWaXN1YWxDaGFubmVsKGNoYW5uZWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIGFnZ3JlZ2F0aW9uIHR5cGUgb24gdG9wIG9mIGJhc2ljIGxheWVyIHZpc3VhbCBjaGFubmVsIHZhbGlkYXRpb25cbiAgICogQHBhcmFtIGNoYW5uZWxcbiAgICovXG4gIHZhbGlkYXRlVmlzdWFsQ2hhbm5lbChjaGFubmVsKSB7XG4gICAgLy8gZmllbGQgdHlwZSBkZWNpZGVzIGFnZ3JlZ2F0aW9uIHR5cGUgZGVjaWRlcyBzY2FsZSB0eXBlXG4gICAgdGhpcy52YWxpZGF0ZUZpZWxkVHlwZShjaGFubmVsKTtcbiAgICB0aGlzLnZhbGlkYXRlQWdncmVnYXRpb25UeXBlKGNoYW5uZWwpO1xuICAgIHRoaXMudmFsaWRhdGVTY2FsZShjaGFubmVsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBhZ2dyZWdhdGlvbiB0eXBlIGJhc2VkIG9uIHNlbGVjdGVkIGZpZWxkXG4gICAqL1xuICB2YWxpZGF0ZUFnZ3JlZ2F0aW9uVHlwZShjaGFubmVsKSB7XG4gICAgY29uc3QgdmlzdWFsQ2hhbm5lbCA9IHRoaXMudmlzdWFsQ2hhbm5lbHNbY2hhbm5lbF07XG4gICAgY29uc3Qge2ZpZWxkLCBhZ2dyZWdhdGlvbn0gPSB2aXN1YWxDaGFubmVsO1xuICAgIGNvbnN0IGFnZ3JlZ2F0aW9uT3B0aW9ucyA9IHRoaXMuZ2V0QWdncmVnYXRpb25PcHRpb25zKGNoYW5uZWwpO1xuXG4gICAgaWYgKCFhZ2dyZWdhdGlvbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghYWdncmVnYXRpb25PcHRpb25zLmxlbmd0aCkge1xuICAgICAgLy8gaWYgZmllbGQgY2Fubm90IGJlIGFnZ3JlZ2F0ZWQsIHNldCBmaWVsZCB0byBudWxsXG4gICAgICB0aGlzLnVwZGF0ZUxheWVyQ29uZmlnKHtbZmllbGRdOiBudWxsfSk7XG4gICAgfSBlbHNlIGlmICghYWdncmVnYXRpb25PcHRpb25zLmluY2x1ZGVzKHRoaXMuY29uZmlnLnZpc0NvbmZpZ1thZ2dyZWdhdGlvbl0pKSB7XG4gICAgICAvLyBjdXJyZW50IGFnZ3JlZ2F0aW9uIHR5cGUgaXMgbm90IHN1cHBvcnRlZCBieSB0aGlzIGZpZWxkXG4gICAgICAvLyBzZXQgYWdncmVnYXRpb24gdG8gdGhlIGZpcnN0IHN1cHBvcnRlZCBvcHRpb25cbiAgICAgIHRoaXMudXBkYXRlTGF5ZXJWaXNDb25maWcoe1thZ2dyZWdhdGlvbl06IGFnZ3JlZ2F0aW9uT3B0aW9uc1swXX0pO1xuICAgIH1cbiAgfVxuXG4gIGdldEFnZ3JlZ2F0aW9uT3B0aW9ucyhjaGFubmVsKSB7XG4gICAgY29uc3QgdmlzdWFsQ2hhbm5lbCA9IHRoaXMudmlzdWFsQ2hhbm5lbHNbY2hhbm5lbF07XG4gICAgY29uc3Qge2ZpZWxkLCBjaGFubmVsU2NhbGVUeXBlfSA9IHZpc3VhbENoYW5uZWw7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMoXG4gICAgICB0aGlzLmNvbmZpZ1tmaWVsZF1cbiAgICAgICAgPyBGSUVMRF9PUFRTW3RoaXMuY29uZmlnW2ZpZWxkXS50eXBlXS5zY2FsZVtjaGFubmVsU2NhbGVUeXBlXVxuICAgICAgICA6IERFRkFVTFRfQUdHUkVHQVRJT05bY2hhbm5lbFNjYWxlVHlwZV1cbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBzY2FsZSBvcHRpb25zIGJhc2VkIG9uIGN1cnJlbnQgZmllbGQgYW5kIGFnZ3JlZ2F0aW9uIHR5cGVcbiAgICogQHBhcmFtIGNoYW5uZWxcbiAgICogQHJldHVybnNcbiAgICovXG4gIGdldFNjYWxlT3B0aW9ucyhjaGFubmVsOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgdmlzdWFsQ2hhbm5lbCA9IHRoaXMudmlzdWFsQ2hhbm5lbHNbY2hhbm5lbF07XG4gICAgY29uc3Qge2ZpZWxkLCBhZ2dyZWdhdGlvbiwgY2hhbm5lbFNjYWxlVHlwZX0gPSB2aXN1YWxDaGFubmVsO1xuICAgIGNvbnN0IGFnZ3JlZ2F0aW9uVHlwZSA9IGFnZ3JlZ2F0aW9uID8gdGhpcy5jb25maWcudmlzQ29uZmlnW2FnZ3JlZ2F0aW9uXSA6IG51bGw7XG5cbiAgICBpZiAoIWFnZ3JlZ2F0aW9uVHlwZSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNvbmZpZ1tmaWVsZF1cbiAgICAgID8gLy8gc2NhbGUgb3B0aW9ucyBiYXNlZCBvbiBhZ2dyZWdhdGlvblxuICAgICAgICBGSUVMRF9PUFRTW3RoaXMuY29uZmlnW2ZpZWxkXS50eXBlXS5zY2FsZVtjaGFubmVsU2NhbGVUeXBlXVthZ2dyZWdhdGlvblR5cGVdXG4gICAgICA6IC8vIGRlZmF1bHQgc2NhbGUgb3B0aW9ucyBmb3IgcG9pbnQgY291bnQ6IGFnZ3JlZ2F0aW9uVHlwZSBzaG91bGQgYmUgY291bnQgc2luY2VcbiAgICAgICAgLy8gTEFZRVJfVklTX0NPTkZJR1MuYWdncmVnYXRpb24uZGVmYXVsdFZhbHVlIGlzIEFHR1JFR0FUSU9OX1RZUEVTLmF2ZXJhZ2UsXG4gICAgICAgIERFRkFVTFRfQUdHUkVHQVRJT05bY2hhbm5lbFNjYWxlVHlwZV1bQUdHUkVHQVRJT05fVFlQRVMuY291bnRdO1xuICB9XG5cbiAgLyoqXG4gICAqIEFnZ3JlZ2F0aW9uIGxheWVyIGhhbmRsZXMgdmlzdWFsIGNoYW5uZWwgYWdncmVnYXRpb24gaW5zaWRlIGRlY2suZ2wgbGF5ZXJcbiAgICovXG4gIHVwZGF0ZUxheWVyRG9tYWluKCk6IEFnZ3JlZ2F0aW9uTGF5ZXIge1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgdXBkYXRlTGF5ZXJNZXRhKGRhdGFzZXQ6IEtlcGxlclRhYmxlLCBnZXRQb3NpdGlvbikge1xuICAgIGNvbnN0IHtkYXRhQ29udGFpbmVyfSA9IGRhdGFzZXQ7XG4gICAgLy8gZ2V0IGJvdW5kcyBmcm9tIHBvaW50c1xuICAgIGNvbnN0IGJvdW5kcyA9IHRoaXMuZ2V0UG9pbnRzQm91bmRzKGRhdGFDb250YWluZXIsIGdldFBvc2l0aW9uKTtcblxuICAgIHRoaXMudXBkYXRlTWV0YSh7Ym91bmRzfSk7XG4gIH1cblxuICBjYWxjdWxhdGVEYXRhQXR0cmlidXRlKHtmaWx0ZXJlZEluZGV4fTogS2VwbGVyVGFibGUsIGdldFBvc2l0aW9uKSB7XG4gICAgY29uc3QgZGF0YTogQWdncmVnYXRpb25MYXllckRhdGFbXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmaWx0ZXJlZEluZGV4Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBpbmRleCA9IGZpbHRlcmVkSW5kZXhbaV07XG4gICAgICBjb25zdCBwb3MgPSBnZXRQb3NpdGlvbih7aW5kZXh9KTtcblxuICAgICAgLy8gaWYgZG9lc24ndCBoYXZlIHBvaW50IGxhdCBvciBsbmcsIGRvIG5vdCBhZGQgdGhlIHBvaW50XG4gICAgICAvLyBkZWNrLmdsIGNhbid0IGhhbmRsZSBwb3NpdGlvbiA9IG51bGxcbiAgICAgIGlmIChwb3MuZXZlcnkoTnVtYmVyLmlzRmluaXRlKSkge1xuICAgICAgICBkYXRhLnB1c2goe1xuICAgICAgICAgIGluZGV4XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgZm9ybWF0TGF5ZXJEYXRhKGRhdGFzZXRzOiBEYXRhc2V0cywgb2xkTGF5ZXJEYXRhKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLmRhdGFJZCA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgICBjb25zdCB7Z3B1RmlsdGVyLCBkYXRhQ29udGFpbmVyfSA9IGRhdGFzZXRzW3RoaXMuY29uZmlnLmRhdGFJZF07XG4gICAgY29uc3QgZ2V0UG9zaXRpb24gPSB0aGlzLmdldFBvc2l0aW9uQWNjZXNzb3IoZGF0YUNvbnRhaW5lcik7XG5cbiAgICBjb25zdCBhZ2dyZWdhdGVQb2ludHMgPSBnZXRWYWx1ZUFnZ3JGdW5jKHRoaXMuZ2V0UG9pbnREYXRhKTtcbiAgICBjb25zdCBnZXRDb2xvclZhbHVlID0gYWdncmVnYXRlUG9pbnRzKFxuICAgICAgdGhpcy5jb25maWcuY29sb3JGaWVsZCxcbiAgICAgIHRoaXMuY29uZmlnLnZpc0NvbmZpZy5jb2xvckFnZ3JlZ2F0aW9uXG4gICAgKTtcblxuICAgIGNvbnN0IGdldEVsZXZhdGlvblZhbHVlID0gYWdncmVnYXRlUG9pbnRzKFxuICAgICAgdGhpcy5jb25maWcuc2l6ZUZpZWxkLFxuICAgICAgdGhpcy5jb25maWcudmlzQ29uZmlnLnNpemVBZ2dyZWdhdGlvblxuICAgICk7XG4gICAgY29uc3QgaGFzRmlsdGVyID0gT2JqZWN0LnZhbHVlcyhncHVGaWx0ZXIuZmlsdGVyUmFuZ2UpLnNvbWUoKGFycjogYW55KSA9PlxuICAgICAgYXJyLnNvbWUodiA9PiB2ICE9PSAwKVxuICAgICk7XG5cbiAgICBjb25zdCBnZXRGaWx0ZXJWYWx1ZSA9IGdwdUZpbHRlci5maWx0ZXJWYWx1ZUFjY2Vzc29yKGRhdGFDb250YWluZXIpKFxuICAgICAgdGhpcy5ncHVGaWx0ZXJHZXRJbmRleCxcbiAgICAgIHRoaXMuZ3B1RmlsdGVyR2V0RGF0YVxuICAgICk7XG4gICAgY29uc3QgZmlsdGVyRGF0YSA9IGhhc0ZpbHRlclxuICAgICAgPyBnZXRGaWx0ZXJEYXRhRnVuYyhncHVGaWx0ZXIuZmlsdGVyUmFuZ2UsIGdldEZpbHRlclZhbHVlKVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCB7ZGF0YX0gPSB0aGlzLnVwZGF0ZURhdGEoZGF0YXNldHMsIG9sZExheWVyRGF0YSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0YSxcbiAgICAgIGdldFBvc2l0aW9uLFxuICAgICAgX2ZpbHRlckRhdGE6IGZpbHRlckRhdGEsXG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAuLi4oZ2V0Q29sb3JWYWx1ZSA/IHtnZXRDb2xvclZhbHVlfSA6IHt9KSxcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgIC4uLihnZXRFbGV2YXRpb25WYWx1ZSA/IHtnZXRFbGV2YXRpb25WYWx1ZX0gOiB7fSlcbiAgICB9O1xuICB9XG5cbiAgZ2V0RGVmYXVsdERlY2tMYXllclByb3BzKG9wdHMpOiBhbnkge1xuICAgIGNvbnN0IGJhc2VQcm9wID0gc3VwZXIuZ2V0RGVmYXVsdERlY2tMYXllclByb3BzKG9wdHMpO1xuICAgIHJldHVybiB7XG4gICAgICAuLi5iYXNlUHJvcCxcbiAgICAgIGhpZ2hsaWdodENvbG9yOiBISUdITElHSF9DT0xPUl8zRCxcbiAgICAgIC8vIGdwdSBkYXRhIGZpbHRlcmluZyBpcyBub3Qgc3VwcG9ydGVkIGluIGFnZ3JlZ2F0aW9uIGxheWVyXG4gICAgICBleHRlbnNpb25zOiBbXSxcbiAgICAgIGF1dG9IaWdobGlnaHQ6IHRoaXMuY29uZmlnLnZpc0NvbmZpZy5lbmFibGUzZFxuICAgIH07XG4gIH1cblxuICBnZXREZWZhdWx0QWdncmVnYXRpb25MYXllclByb3Aob3B0cykge1xuICAgIGNvbnN0IHtncHVGaWx0ZXIsIG1hcFN0YXRlLCBsYXllckNhbGxiYWNrcyA9IHt9fSA9IG9wdHM7XG4gICAgY29uc3Qge3Zpc0NvbmZpZ30gPSB0aGlzLmNvbmZpZztcbiAgICBjb25zdCBlbGVab29tRmFjdG9yID0gdGhpcy5nZXRFbGV2YXRpb25ab29tRmFjdG9yKG1hcFN0YXRlKTtcblxuICAgIGNvbnN0IHVwZGF0ZVRyaWdnZXJzID0ge1xuICAgICAgZ2V0Q29sb3JWYWx1ZToge1xuICAgICAgICBjb2xvckZpZWxkOiB0aGlzLmNvbmZpZy5jb2xvckZpZWxkLFxuICAgICAgICBjb2xvckFnZ3JlZ2F0aW9uOiB0aGlzLmNvbmZpZy52aXNDb25maWcuY29sb3JBZ2dyZWdhdGlvblxuICAgICAgfSxcbiAgICAgIGdldEVsZXZhdGlvblZhbHVlOiB7XG4gICAgICAgIHNpemVGaWVsZDogdGhpcy5jb25maWcuc2l6ZUZpZWxkLFxuICAgICAgICBzaXplQWdncmVnYXRpb246IHRoaXMuY29uZmlnLnZpc0NvbmZpZy5zaXplQWdncmVnYXRpb25cbiAgICAgIH0sXG4gICAgICBfZmlsdGVyRGF0YToge1xuICAgICAgICBmaWx0ZXJSYW5nZTogZ3B1RmlsdGVyLmZpbHRlclJhbmdlLFxuICAgICAgICAuLi5ncHVGaWx0ZXIuZmlsdGVyVmFsdWVVcGRhdGVUcmlnZ2Vyc1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4udGhpcy5nZXREZWZhdWx0RGVja0xheWVyUHJvcHMob3B0cyksXG4gICAgICBjb3ZlcmFnZTogdmlzQ29uZmlnLmNvdmVyYWdlLFxuXG4gICAgICAvLyBjb2xvclxuICAgICAgY29sb3JSYW5nZTogdGhpcy5nZXRDb2xvclJhbmdlKHZpc0NvbmZpZy5jb2xvclJhbmdlKSxcbiAgICAgIGNvbG9yTWFwOiB2aXNDb25maWcuY29sb3JSYW5nZS5jb2xvck1hcCxcbiAgICAgIGNvbG9yU2NhbGVUeXBlOiB0aGlzLmNvbmZpZy5jb2xvclNjYWxlLFxuICAgICAgdXBwZXJQZXJjZW50aWxlOiB2aXNDb25maWcucGVyY2VudGlsZVsxXSxcbiAgICAgIGxvd2VyUGVyY2VudGlsZTogdmlzQ29uZmlnLnBlcmNlbnRpbGVbMF0sXG4gICAgICBjb2xvckFnZ3JlZ2F0aW9uOiB2aXNDb25maWcuY29sb3JBZ2dyZWdhdGlvbixcblxuICAgICAgLy8gZWxldmF0aW9uXG4gICAgICBleHRydWRlZDogdmlzQ29uZmlnLmVuYWJsZTNkLFxuICAgICAgZWxldmF0aW9uU2NhbGU6IHZpc0NvbmZpZy5lbGV2YXRpb25TY2FsZSAqIGVsZVpvb21GYWN0b3IsXG4gICAgICBlbGV2YXRpb25TY2FsZVR5cGU6IHRoaXMuY29uZmlnLnNpemVTY2FsZSxcbiAgICAgIGVsZXZhdGlvblJhbmdlOiB2aXNDb25maWcuc2l6ZVJhbmdlLFxuICAgICAgZWxldmF0aW9uRml4ZWQ6IHZpc0NvbmZpZy5maXhlZEhlaWdodCxcblxuICAgICAgZWxldmF0aW9uTG93ZXJQZXJjZW50aWxlOiB2aXNDb25maWcuZWxldmF0aW9uUGVyY2VudGlsZVswXSxcbiAgICAgIGVsZXZhdGlvblVwcGVyUGVyY2VudGlsZTogdmlzQ29uZmlnLmVsZXZhdGlvblBlcmNlbnRpbGVbMV0sXG5cbiAgICAgIC8vIHVwZGF0ZVRyaWdnZXJzXG4gICAgICB1cGRhdGVUcmlnZ2VycyxcblxuICAgICAgLy8gY2FsbGJhY2tzXG4gICAgICBvblNldENvbG9yRG9tYWluOiBsYXllckNhbGxiYWNrcy5vblNldExheWVyRG9tYWluXG4gICAgfTtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFHQSxJQUFBQSxPQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxVQUFBLEdBQUFGLHNCQUFBLENBQUFDLE9BQUE7QUFRQSxJQUFBRSxNQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxVQUFBLEdBQUFILE9BQUE7QUFNOEIsU0FBQUksUUFBQUMsQ0FBQSxFQUFBQyxDQUFBLFFBQUFDLENBQUEsR0FBQUMsTUFBQSxDQUFBQyxJQUFBLENBQUFKLENBQUEsT0FBQUcsTUFBQSxDQUFBRSxxQkFBQSxRQUFBQyxDQUFBLEdBQUFILE1BQUEsQ0FBQUUscUJBQUEsQ0FBQUwsQ0FBQSxHQUFBQyxDQUFBLEtBQUFLLENBQUEsR0FBQUEsQ0FBQSxDQUFBQyxNQUFBLFdBQUFOLENBQUEsV0FBQUUsTUFBQSxDQUFBSyx3QkFBQSxDQUFBUixDQUFBLEVBQUFDLENBQUEsRUFBQVEsVUFBQSxPQUFBUCxDQUFBLENBQUFRLElBQUEsQ0FBQUMsS0FBQSxDQUFBVCxDQUFBLEVB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