kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
399 lines (389 loc) • 55.1 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 _memoize = _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 typeof val === 'number' ? val >= filterRange[i][0] && val <= filterRange[i][1] : false;
});
};
};
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, _memoize["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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWVtb2l6ZSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX2Jhc2VMYXllciIsIl91dGlscyIsIl9jb25zdGFudHMiLCJvd25LZXlzIiwiZSIsInIiLCJ0IiwiT2JqZWN0Iiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJkZWZpbmVQcm9wZXJ0eSIsIl9jYWxsU3VwZXIiLCJfZ2V0UHJvdG90eXBlT2YyIiwiX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4yIiwiX2lzTmF0aXZlUmVmbGVjdENvbnN0cnVjdCIsIlJlZmxlY3QiLCJjb25zdHJ1Y3QiLCJjb25zdHJ1Y3RvciIsIkJvb2xlYW4iLCJwcm90b3R5cGUiLCJ2YWx1ZU9mIiwiY2FsbCIsIl9zdXBlclByb3BHZXQiLCJwIiwiX2dldDIiLCJwb2ludFBvc0FjY2Vzc29yIiwiZXhwb3J0cyIsIl9yZWYiLCJsYXQiLCJsbmciLCJkYyIsImQiLCJ2YWx1ZUF0IiwiaW5kZXgiLCJmaWVsZElkeCIsInBvaW50UG9zUmVzb2x2ZXIiLCJfcmVmMiIsImNvbmNhdCIsImdldFZhbHVlQWdnckZ1bmMiLCJnZXRQb2ludERhdGEiLCJmaWVsZCIsImFnZ3JlZ2F0aW9uIiwicG9pbnRzIiwiYWdncmVnYXRlIiwibWFwIiwidmFsdWVBY2Nlc3NvciIsImdldEZpbHRlckRhdGFGdW5jIiwiZmlsdGVyUmFuZ2UiLCJnZXRGaWx0ZXJWYWx1ZSIsInB0IiwiZXZlcnkiLCJ2YWwiLCJpIiwiZ2V0TGF5ZXJDb2xvclJhbmdlIiwiY29sb3JSYW5nZSIsImNvbG9ycyIsImhleFRvUmdiIiwiYWdncmVnYXRlUmVxdWlyZWRDb2x1bW5zIiwiQWdncmVnYXRpb25MYXllciIsIl9MYXllciIsInByb3BzIiwiX3RoaXMiLCJfY2xhc3NDYWxsQ2hlY2syIiwiZ2V0UG9zaXRpb25BY2Nlc3NvciIsImRhdGFDb250YWluZXIiLCJjb25maWciLCJjb2x1bW5zIiwiZ2V0Q29sb3JSYW5nZSIsIm1lbW9pemUiLCJzb3VyY2UiLCJncHVGaWx0ZXJHZXRJbmRleCIsImdwdUZpbHRlckdldERhdGEiLCJkYXRhIiwiZmllbGRJbmRleCIsIl9pbmhlcml0czIiLCJfY3JlYXRlQ2xhc3MyIiwia2V5IiwiZ2V0IiwiZGVmYXVsdFBvaW50Q29sdW1uUGFpcnMiLCJfdG9Db25zdW1hYmxlQXJyYXkyIiwiY29sb3IiLCJjaGFubmVsU2NhbGVUeXBlIiwiQ0hBTk5FTF9TQ0FMRVMiLCJjb2xvckFnZ3IiLCJkZWZhdWx0TWVhc3VyZSIsImRvbWFpbiIsInByb3BlcnR5IiwicmFuZ2UiLCJzY2FsZSIsInNpemUiLCJzaXplQWdnciIsImNvbmRpdGlvbiIsInZpc0NvbmZpZyIsImVuYWJsZTNkIiwidmFsdWUiLCJnZXRWaXN1YWxDaGFubmVsRGVzY3JpcHRpb24iLCJfdGhpcyR2aXNDb25maWdTZXR0aW4iLCJjaGFubmVsIiwidmlzdWFsQ2hhbm5lbHMiLCJsYWJlbCIsIm1lYXN1cmUiLCJ1bmRlZmluZWQiLCJmaWVsZENvbmZpZyIsInZpc0NvbmZpZ1NldHRpbmdzIiwiZGlzcGxheU5hbWUiLCJuYW1lIiwiZ2V0SG92ZXJEYXRhIiwib2JqZWN0IiwiZmllbGRzIiwiY29sb3JBZ2dyZWdhdGlvbiIsImFnZ3JlZ2F0ZWREYXRhIiwicmVkdWNlIiwiYWNjdSIsImdldEZpbHRlcmVkSXRlbUNvdW50IiwidXBkYXRlTGF5ZXJWaXN1YWxDaGFubmVsIiwiX3JlZjMiLCJ2YWxpZGF0ZVZpc3VhbENoYW5uZWwiLCJ2YWxpZGF0ZUZpZWxkVHlwZSIsInZhbGlkYXRlQWdncmVnYXRpb25UeXBlIiwidmFsaWRhdGVTY2FsZSIsInZpc3VhbENoYW5uZWwiLCJhZ2dyZWdhdGlvbk9wdGlvbnMiLCJnZXRBZ2dyZWdhdGlvbk9wdGlvbnMiLCJ1cGRhdGVMYXllckNvbmZpZyIsImluY2x1ZGVzIiwidXBkYXRlTGF5ZXJWaXNDb25maWciLCJGSUVMRF9PUFRTIiwidHlwZSIsIkRFRkFVTFRfQUdHUkVHQVRJT04iLCJnZXRTY2FsZU9wdGlvbnMiLCJhZ2dyZWdhdGlvblR5cGUiLCJBR0dSRUdBVElPTl9UWVBFUyIsImNvdW50IiwidXBkYXRlTGF5ZXJEb21haW4iLCJ1cGRhdGVMYXllck1ldGEiLCJkYXRhc2V0IiwiZ2V0UG9zaXRpb24iLCJib3VuZHMiLCJnZXRQb2ludHNCb3VuZHMiLCJ1cGRhdGVNZXRhIiwiY2FsY3VsYXRlRGF0YUF0dHJpYnV0ZSIsIl9yZWY0IiwiZmlsdGVyZWRJbmRleCIsInBvcyIsIk51bWJlciIsImlzRmluaXRlIiwiZm9ybWF0TGF5ZXJEYXRhIiwiZGF0YXNldHMiLCJvbGRMYXllckRhdGEiLCJkYXRhSWQiLCJfZGF0YXNldHMkdGhpcyRjb25maWciLCJncHVGaWx0ZXIiLCJhZ2dyZWdhdGVQb2ludHMiLCJnZXRDb2xvclZhbHVlIiwiY29sb3JGaWVsZCIsImdldEVsZXZhdGlvblZhbHVlIiwic2l6ZUZpZWxkIiwic2l6ZUFnZ3JlZ2F0aW9uIiwiaGFzRmlsdGVyIiwidmFsdWVzIiwic29tZSIsImFyciIsInYiLCJmaWx0ZXJWYWx1ZUFjY2Vzc29yIiwiZmlsdGVyRGF0YSIsIl90aGlzJHVwZGF0ZURhdGEiLCJ1cGRhdGVEYXRhIiwiX2ZpbHRlckRhdGEiLCJnZXREZWZhdWx0RGVja0xheWVyUHJvcHMiLCJvcHRzIiwiYmFzZVByb3AiLCJoaWdobGlnaHRDb2xvciIsIkhJR0hMSUdIX0NPTE9SXzNEIiwiZXh0ZW5zaW9ucyIsImF1dG9IaWdobGlnaHQiLCJnZXREZWZhdWx0QWdncmVnYXRpb25MYXllclByb3AiLCJtYXBTdGF0ZSIsIl9vcHRzJGxheWVyQ2FsbGJhY2tzIiwibGF5ZXJDYWxsYmFja3MiLCJlbGVab29tRmFjdG9yIiwiZ2V0RWxldmF0aW9uWm9vbUZhY3RvciIsInVwZGF0ZVRyaWdnZXJzIiwiZmlsdGVyVmFsdWVVcGRhdGVUcmlnZ2VycyIsImNvdmVyYWdlIiwiY29sb3JNYXAiLCJjb2xvclNjYWxlVHlwZSIsImNvbG9yU2NhbGUiLCJ1cHBlclBlcmNlbnRpbGUiLCJwZXJjZW50aWxlIiwibG93ZXJQZXJjZW50aWxlIiwiZXh0cnVkZWQiLCJlbGV2YXRpb25TY2FsZSIsImVsZXZhdGlvblNjYWxlVHlwZSIsInNpemVTY2FsZSIsImVsZXZhdGlvblJhbmdlIiwic2l6ZVJhbmdlIiwiZWxldmF0aW9uRml4ZWQiLCJmaXhlZEhlaWdodCIsImVsZXZhdGlvbkxvd2VyUGVyY2VudGlsZSIsImVsZXZhdGlvblBlcmNlbnRpbGUiLCJlbGV2YXRpb25VcHBlclBlcmNlbnRpbGUiLCJvblNldENvbG9yRG9tYWluIiwib25TZXRMYXllckRvbWFpbiIsIkxheWVyIl0sInNvdXJjZXMiOlsiLi4vc3JjL2FnZ3JlZ2F0aW9uLWxheWVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCBtZW1vaXplIGZyb20gJ2xvZGFzaC9tZW1vaXplJztcbmltcG9ydCBMYXllciwge1xuICBMYXllckJhc2VDb25maWcsXG4gIExheWVyQmFzZUNvbmZpZ1BhcnRpYWwsXG4gIExheWVyQ29sb3JDb25maWcsXG4gIExheWVyU2l6ZUNvbmZpZyxcbiAgVmlzdWFsQ2hhbm5lbERlc2NyaXB0aW9uLFxuICBWaXN1YWxDaGFubmVsc1xufSBmcm9tICcuL2Jhc2UtbGF5ZXInO1xuaW1wb3J0IHtoZXhUb1JnYiwgYWdncmVnYXRlLCBEYXRhQ29udGFpbmVySW50ZXJmYWNlfSBmcm9tICdAa2VwbGVyLmdsL3V0aWxzJztcbmltcG9ydCB7XG4gIEhJR0hMSUdIX0NPTE9SXzNELFxuICBDSEFOTkVMX1NDQUxFUyxcbiAgRklFTERfT1BUUyxcbiAgREVGQVVMVF9BR0dSRUdBVElPTixcbiAgQUdHUkVHQVRJT05fVFlQRVNcbn0gZnJvbSAnQGtlcGxlci5nbC9jb25zdGFudHMnO1xuaW1wb3J0IHtDb2xvclJhbmdlLCBGaWVsZCwgTGF5ZXJDb2x1bW4sIE1lcmdlfSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcbmltcG9ydCB7S2VwbGVyVGFibGUsIERhdGFzZXRzfSBmcm9tICdAa2VwbGVyLmdsL3RhYmxlJztcblxudHlwZSBBZ2dyZWdhdGlvbkxheWVyQ29sdW1ucyA9IHtcbiAgbGF0OiBMYXllckNvbHVtbjtcbiAgbG5nOiBMYXllckNvbHVtbjtcbn07XG5cbmV4cG9ydCB0eXBlIEFnZ3JlZ2F0aW9uTGF5ZXJEYXRhID0ge1xuICBpbmRleDogbnVtYmVyO1xufTtcblxuZXhwb3J0IGNvbnN0IHBvaW50UG9zQWNjZXNzb3IgPVxuICAoe2xhdCwgbG5nfTogQWdncmVnYXRpb25MYXllckNvbHVtbnMpID0+XG4gIGRjID0+XG4gIGQgPT5cbiAgICBbZGMudmFsdWVBdChkLmluZGV4LCBsbmcuZmllbGRJZHgpLCBkYy52YWx1ZUF0KGQuaW5kZXgsIGxhdC5maWVsZElkeCldO1xuXG5leHBvcnQgY29uc3QgcG9pbnRQb3NSZXNvbHZlciA9ICh7bGF0LCBsbmd9OiBBZ2dyZWdhdGlvbkxheWVyQ29sdW1ucykgPT5cbiAgYCR7bGF0LmZpZWxkSWR4fS0ke2xuZy5maWVsZElkeH1gO1xuXG5leHBvcnQgY29uc3QgZ2V0VmFsdWVBZ2dyRnVuYyA9IGdldFBvaW50RGF0YSA9PiAoZmllbGQsIGFnZ3JlZ2F0aW9uKSA9PiBwb2ludHMgPT5cbiAgZmllbGRcbiAgICA/IGFnZ3JlZ2F0ZShcbiAgICAgICAgcG9pbnRzLm1hcChwID0+IGZpZWxkLnZhbHVlQWNjZXNzb3IoZ2V0UG9pbnREYXRhKHApKSksXG4gICAgICAgIGFnZ3JlZ2F0aW9uXG4gICAgICApXG4gICAgOiBwb2ludHMubGVuZ3RoO1xuXG5leHBvcnQgY29uc3QgZ2V0RmlsdGVyRGF0YUZ1bmMgPVxuICAoXG4gICAgZmlsdGVyUmFuZ2U6IG51bWJlcltdW10sXG4gICAgZ2V0RmlsdGVyVmFsdWU6IChkOiB1bmtub3duKSA9PiAobnVtYmVyIHwgbnVtYmVyW10pW11cbiAgKTogKChkOiB1bmtub3duKSA9PiBib29sZWFuKSA9PlxuICBwdCA9PlxuICAgIGdldEZpbHRlclZhbHVlKHB0KS5ldmVyeSgodmFsLCBpKSA9PiB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ251bWJlcicgPyB2YWwgPj0gZmlsdGVyUmFuZ2VbaV1bMF0gJiYgdmFsIDw9IGZpbHRlclJhbmdlW2ldWzFdIDogZmFsc2U7XG4gICAgfSk7XG5cbmNvbnN0IGdldExheWVyQ29sb3JSYW5nZSA9IChjb2xvclJhbmdlOiBDb2xvclJhbmdlKSA9PiBjb2xvclJhbmdlLmNvbG9ycy5tYXAoaGV4VG9SZ2IpO1xuXG5leHBvcnQgY29uc3QgYWdncmVnYXRlUmVxdWlyZWRDb2x1bW5zOiBbJ2xhdCcsICdsbmcnXSA9IFsnbGF0JywgJ2xuZyddO1xuXG5leHBvcnQgdHlwZSBBZ2dyZWdhdGlvbkxheWVyVmlzdWFsQ2hhbm5lbENvbmZpZyA9IExheWVyQ29sb3JDb25maWcgJiBMYXllclNpemVDb25maWc7XG5leHBvcnQgdHlwZSBBZ2dyZWdhdGlvbkxheWVyQ29uZmlnID0gTWVyZ2U8TGF5ZXJCYXNlQ29uZmlnLCB7Y29sdW1uczogQWdncmVnYXRpb25MYXllckNvbHVtbnN9PiAmXG4gIEFnZ3JlZ2F0aW9uTGF5ZXJWaXN1YWxDaGFubmVsQ29uZmlnO1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWdncmVnYXRpb25MYXllciBleHRlbmRzIExheWVyIHtcbiAgZ2V0Q29sb3JSYW5nZTogYW55O1xuICBkZWNsYXJlIGNvbmZpZzogQWdncmVnYXRpb25MYXllckNvbmZpZztcbiAgZGVjbGFyZSBnZXRQb2ludERhdGE6IChhbnkpID0+IGFueTtcbiAgZGVjbGFyZSBncHVGaWx0ZXJHZXRJbmRleDogKGFueSkgPT4gbnVtYmVyO1xuICBkZWNsYXJlIGdwdUZpbHRlckdldERhdGE6IChkYXRhQ29udGFpbmVyLCBkYXRhLCBmaWVsZEluZGV4KSA9PiBhbnk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvcHM6IHtcbiAgICAgIGlkPzogc3RyaW5nO1xuICAgIH0gJiBMYXllckJhc2VDb25maWdQYXJ0aWFsXG4gICkge1xuICAgIHN1cGVyKHByb3BzKTtcblxuICAgIHRoaXMuZ2V0UG9zaXRpb25BY2Nlc3NvciA9IGRhdGFDb250YWluZXIgPT5cbiAgICAgIHBvaW50UG9zQWNjZXNzb3IodGhpcy5jb25maWcuY29sdW1ucykoZGF0YUNvbnRhaW5lcik7XG4gICAgdGhpcy5nZXRDb2xvclJhbmdlID0gbWVtb2l6ZShnZXRMYXllckNvbG9yUmFuZ2UpO1xuXG4gICAgLy8gQWNjZXNzIGRhdGEgb2YgYSBwb2ludCBmcm9tIGFnZ3JlZ2F0ZWQgYmlucywgZGVwZW5kcyBvbiBob3cgQmluU29ydGVyIHdvcmtzXG4gICAgLy8gRGVjay5nbCdzIEJpblNvcnRlciBwdXRzIGRhdGEgaW4gcG9pbnQuc291cmNlXG4gICAgdGhpcy5nZXRQb2ludERhdGEgPSBwdCA9PiBwdC5zb3VyY2U7XG5cbiAgICB0aGlzLmdwdUZpbHRlckdldEluZGV4ID0gcHQgPT4gdGhpcy5nZXRQb2ludERhdGEocHQpLmluZGV4O1xuICAgIHRoaXMuZ3B1RmlsdGVyR2V0RGF0YSA9IChkYXRhQ29udGFpbmVyLCBkYXRhLCBmaWVsZEluZGV4KSA9PlxuICAgICAgZGF0YUNvbnRhaW5lci52YWx1ZUF0KGRhdGEuaW5kZXgsIGZpZWxkSW5kZXgpO1xuICB9XG5cbiAgZ2V0IGlzQWdncmVnYXRlZCgpOiB0cnVlIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGdldCByZXF1aXJlZExheWVyQ29sdW1ucygpIHtcbiAgICByZXR1cm4gYWdncmVnYXRlUmVxdWlyZWRDb2x1bW5zO1xuICB9XG5cbiAgZ2V0IGNvbHVtblBhaXJzKCkge1xuICAgIHJldHVybiB0aGlzLmRlZmF1bHRQb2ludENvbHVtblBhaXJzO1xuICB9XG5cbiAgZ2V0IG5vbmVMYXllckRhdGFBZmZlY3RpbmdQcm9wcygpIHtcbiAgICByZXR1cm4gW1xuICAgICAgLi4uc3VwZXIubm9uZUxheWVyRGF0YUFmZmVjdGluZ1Byb3BzLFxuICAgICAgJ2VuYWJsZTNkJyxcbiAgICAgICdjb2xvclJhbmdlJyxcbiAgICAgICdjb2xvckRvbWFpbicsXG4gICAgICAnc2l6ZVJhbmdlJyxcbiAgICAgICdzaXplU2NhbGUnLFxuICAgICAgJ3NpemVEb21haW4nLFxuICAgICAgJ3BlcmNlbnRpbGUnLFxuICAgICAgJ2NvdmVyYWdlJyxcbiAgICAgICdlbGV2YXRpb25QZXJjZW50aWxlJyxcbiAgICAgICdlbGV2YXRpb25TY2FsZScsXG4gICAgICAnZW5hYmxlRWxldmF0aW9uWm9vbUZhY3RvcicsXG4gICAgICAnZml4ZWRIZWlnaHQnXG4gICAgXTtcbiAgfVxuXG4gIGdldCB2aXN1YWxDaGFubmVscygpOiBWaXN1YWxDaGFubmVscyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbG9yOiB7XG4gICAgICAgIGFnZ3JlZ2F0aW9uOiAnY29sb3JBZ2dyZWdhdGlvbicsXG4gICAgICAgIGNoYW5uZWxTY2FsZVR5cGU6IENIQU5ORUxfU0NBTEVTLmNvbG9yQWdncixcbiAgICAgICAgZGVmYXVsdE1lYXN1cmU6ICdwcm9wZXJ0eS5wb2ludENvdW50JyxcbiAgICAgICAgZG9tYWluOiAnY29sb3JEb21haW4nLFxuICAgICAgICBmaWVsZDogJ2NvbG9yRmllbGQnLFxuICAgICAgICBrZXk6ICdjb2xvcicsXG4gICAgICAgIHByb3BlcnR5OiAnY29sb3InLFxuICAgICAgICByYW5nZTogJ2NvbG9yUmFuZ2UnLFxuICAgICAgICBzY2FsZTogJ2NvbG9yU2NhbGUnXG4gICAgICB9LFxuICAgICAgc2l6ZToge1xuICAgICAgICBhZ2dyZWdhdGlvbjogJ3NpemVBZ2dyZWdhdGlvbicsXG4gICAgICAgIGNoYW5uZWxTY2FsZVR5cGU6IENIQU5ORUxfU0NBTEVTLnNpemVBZ2dyLFxuICAgICAgICBjb25kaXRpb246IGNvbmZpZyA9PiBjb25maWcudmlzQ29uZmlnLmVuYWJsZTNkLFxuICAgICAgICBkZWZhdWx0TWVhc3VyZTogJ3Byb3BlcnR5LnBvaW50Q291bnQnLFxuICAgICAgICBkb21haW46ICdzaXplRG9tYWluJyxcbiAgICAgICAgZmllbGQ6ICdzaXplRmllbGQnLFxuICAgICAgICBrZXk6ICdzaXplJyxcbiAgICAgICAgcHJvcGVydHk6ICdoZWlnaHQnLFxuICAgICAgICByYW5nZTogJ3NpemVSYW5nZScsXG4gICAgICAgIHNjYWxlOiAnc2l6ZVNjYWxlJ1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBkZXNjcmlwdGlvbiBvZiBhIHZpc3VhbENoYW5uZWwgY29uZmlnXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHJldHVybnNcbiAgICovXG4gIGdldFZpc3VhbENoYW5uZWxEZXNjcmlwdGlvbihrZXk6IHN0cmluZyk6IFZpc3VhbENoYW5uZWxEZXNjcmlwdGlvbiB7XG4gICAgY29uc3QgY2hhbm5lbCA9IHRoaXMudmlzdWFsQ2hhbm5lbHNba2V5XTtcbiAgICBpZiAoIWNoYW5uZWwpIHJldHVybiB7bGFiZWw6ICcnLCBtZWFzdXJlOiB1bmRlZmluZWR9O1xuICAgIC8vIGUuZy4gbGFiZWw6IENvbG9yLCBtZWFzdXJlOiBBdmVyYWdlIG9mIEVUQVxuICAgIGNvbnN0IHtyYW5nZSwgZmllbGQsIGRlZmF1bHRNZWFzdXJlLCBhZ2dyZWdhdGlvbn0gPSBjaGFubmVsO1xuICAgIGNvbnN0IGZpZWxkQ29uZmlnID0gdGhpcy5jb25maWdbZmllbGRdO1xuICAgIGNvbnN0IGxhYmVsID0gdGhpcy52aXNDb25maWdTZXR0aW5nc1tyYW5nZV0/LmxhYmVsO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxhYmVsOiB0eXBlb2YgbGFiZWwgPT09ICdmdW5jdGlvbicgPyBsYWJlbCh0aGlzLmNvbmZpZykgOiBsYWJlbCB8fCAnJyxcbiAgICAgIG1lYXN1cmU6XG4gICAgICAgIGZpZWxkQ29uZmlnICYmIGFnZ3JlZ2F0aW9uXG4gICAgICAgICAgPyBgJHt0aGlzLmNvbmZpZy52aXNDb25maWdbYWdncmVnYXRpb25dfSBvZiAke1xuICAgICAgICAgICAgICBmaWVsZENvbmZpZy5kaXNwbGF5TmFtZSB8fCBmaWVsZENvbmZpZy5uYW1lXG4gICAgICAgICAgICB9YFxuICAgICAgICAgIDogZGVmYXVsdE1lYXN1cmVcbiAgICB9O1xuICB9XG5cbiAgZ2V0SG92ZXJEYXRhKG9iamVjdDogYW55LCBkYXRhQ29udGFpbmVyOiBEYXRhQ29udGFpbmVySW50ZXJmYWNlLCBmaWVsZHM6IEZpZWxkW10pOiBhbnkge1xuICAgIGlmICghb2JqZWN0KSByZXR1cm4gb2JqZWN0O1xuICAgIGNvbnN0IG1lYXN1cmUgPSB0aGlzLmNvbmZpZy52aXNDb25maWcuY29sb3JBZ2dyZWdhdGlvbjtcbiAgICAvLyBhZ2dyZWdhdGUgYWxsIGZpZWxkcyBmb3IgdGhlIGhvdmVyZWQgZ3JvdXBcbiAgICBjb25zdCBhZ2dyZWdhdGVkRGF0YSA9IGZpZWxkcy5yZWR1Y2UoKGFjY3UsIGZpZWxkKSA9PiB7XG4gICAgICBhY2N1W2ZpZWxkLm5hbWVdID0ge1xuICAgICAgICBtZWFzdXJlLFxuICAgICAgICB2YWx1ZTogYWdncmVnYXRlKG9iamVjdC5wb2ludHMsIG1lYXN1cmUsIChkOiB7aW5kZXg6IG51bWJlcn0pID0+IHtcbiAgICAgICAgICByZXR1cm4gZGF0YUNvbnRhaW5lci52YWx1ZUF0KGQuaW5kZXgsIGZpZWxkLmZpZWxkSWR4KTtcbiAgICAgICAgfSlcbiAgICAgIH07XG4gICAgICByZXR1cm4gYWNjdTtcbiAgICB9LCB7fSk7XG5cbiAgICAvLyByZXR1cm4gYWdncmVnYXRlZCBvYmplY3RcbiAgICByZXR1cm4ge2FnZ3JlZ2F0ZWREYXRhLCAuLi5vYmplY3R9O1xuICB9XG5cbiAgZ2V0RmlsdGVyZWRJdGVtQ291bnQoKSB7XG4gICAgLy8gZ3B1IGZpbHRlciBub3Qgc3VwcG9ydGVkXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQWdncmVnYXRpb24gbGF5ZXIgaGFuZGxlcyB2aXN1YWwgY2hhbm5lbCBhZ2dyZWdhdGlvbiBpbnNpZGUgZGVjay5nbCBsYXllclxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICB1cGRhdGVMYXllclZpc3VhbENoYW5uZWwoe2RhdGFDb250YWluZXJ9LCBjaGFubmVsKSB7XG4gICAgdGhpcy52YWxpZGF0ZVZpc3VhbENoYW5uZWwoY2hhbm5lbCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgYWdncmVnYXRpb24gdHlwZSBvbiB0b3Agb2YgYmFzaWMgbGF5ZXIgdmlzdWFsIGNoYW5uZWwgdmFsaWRhdGlvblxuICAgKiBAcGFyYW0gY2hhbm5lbFxuICAgKi9cbiAgdmFsaWRhdGVWaXN1YWxDaGFubmVsKGNoYW5uZWwpIHtcbiAgICAvLyBmaWVsZCB0eXBlIGRlY2lkZXMgYWdncmVnYXRpb24gdHlwZSBkZWNpZGVzIHNjYWxlIHR5cGVcbiAgICB0aGlzLnZhbGlkYXRlRmllbGRUeXBlKGNoYW5uZWwpO1xuICAgIHRoaXMudmFsaWRhdGVBZ2dyZWdhdGlvblR5cGUoY2hhbm5lbCk7XG4gICAgdGhpcy52YWxpZGF0ZVNjYWxlKGNoYW5uZWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIGFnZ3JlZ2F0aW9uIHR5cGUgYmFzZWQgb24gc2VsZWN0ZWQgZmllbGRcbiAgICovXG4gIHZhbGlkYXRlQWdncmVnYXRpb25UeXBlKGNoYW5uZWwpIHtcbiAgICBjb25zdCB2aXN1YWxDaGFubmVsID0gdGhpcy52aXN1YWxDaGFubmVsc1tjaGFubmVsXTtcbiAgICBjb25zdCB7ZmllbGQsIGFnZ3JlZ2F0aW9ufSA9IHZpc3VhbENoYW5uZWw7XG4gICAgY29uc3QgYWdncmVnYXRpb25PcHRpb25zID0gdGhpcy5nZXRBZ2dyZWdhdGlvbk9wdGlvbnMoY2hhbm5lbCk7XG5cbiAgICBpZiAoIWFnZ3JlZ2F0aW9uKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFhZ2dyZWdhdGlvbk9wdGlvbnMubGVuZ3RoKSB7XG4gICAgICAvLyBpZiBmaWVsZCBjYW5ub3QgYmUgYWdncmVnYXRlZCwgc2V0IGZpZWxkIHRvIG51bGxcbiAgICAgIHRoaXMudXBkYXRlTGF5ZXJDb25maWcoe1tmaWVsZF06IG51bGx9KTtcbiAgICB9IGVsc2UgaWYgKCFhZ2dyZWdhdGlvbk9wdGlvbnMuaW5jbHVkZXModGhpcy5jb25maWcudmlzQ29uZmlnW2FnZ3JlZ2F0aW9uXSkpIHtcbiAgICAgIC8vIGN1cnJlbnQgYWdncmVnYXRpb24gdHlwZSBpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoaXMgZmllbGRcbiAgICAgIC8vIHNldCBhZ2dyZWdhdGlvbiB0byB0aGUgZmlyc3Qgc3VwcG9ydGVkIG9wdGlvblxuICAgICAgdGhpcy51cGRhdGVMYXllclZpc0NvbmZpZyh7W2FnZ3JlZ2F0aW9uXTogYWdncmVnYXRpb25PcHRpb25zWzBdfSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0QWdncmVnYXRpb25PcHRpb25zKGNoYW5uZWwpIHtcbiAgICBjb25zdCB2aXN1YWxDaGFubmVsID0gdGhpcy52aXN1YWxDaGFubmVsc1tjaGFubmVsXTtcbiAgICBjb25zdCB7ZmllbGQsIGNoYW5uZWxTY2FsZVR5cGV9ID0gdmlzdWFsQ2hhbm5lbDtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhcbiAgICAgIHRoaXMuY29uZmlnW2ZpZWxkXVxuICAgICAgICA/IEZJRUxEX09QVFNbdGhpcy5jb25maWdbZmllbGRdLnR5cGVdLnNjYWxlW2NoYW5uZWxTY2FsZVR5cGVdXG4gICAgICAgIDogREVGQVVMVF9BR0dSRUdBVElPTltjaGFubmVsU2NhbGVUeXBlXVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHNjYWxlIG9wdGlvbnMgYmFzZWQgb24gY3VycmVudCBmaWVsZCBhbmQgYWdncmVnYXRpb24gdHlwZVxuICAgKiBAcGFyYW0gY2hhbm5lbFxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgZ2V0U2NhbGVPcHRpb25zKGNoYW5uZWw6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCB2aXN1YWxDaGFubmVsID0gdGhpcy52aXN1YWxDaGFubmVsc1tjaGFubmVsXTtcbiAgICBjb25zdCB7ZmllbGQsIGFnZ3JlZ2F0aW9uLCBjaGFubmVsU2NhbGVUeXBlfSA9IHZpc3VhbENoYW5uZWw7XG4gICAgY29uc3QgYWdncmVnYXRpb25UeXBlID0gYWdncmVnYXRpb24gPyB0aGlzLmNvbmZpZy52aXNDb25maWdbYWdncmVnYXRpb25dIDogbnVsbDtcblxuICAgIGlmICghYWdncmVnYXRpb25UeXBlKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnW2ZpZWxkXVxuICAgICAgPyAvLyBzY2FsZSBvcHRpb25zIGJhc2VkIG9uIGFnZ3JlZ2F0aW9uXG4gICAgICAgIEZJRUxEX09QVFNbdGhpcy5jb25maWdbZmllbGRdLnR5cGVdLnNjYWxlW2NoYW5uZWxTY2FsZVR5cGVdW2FnZ3JlZ2F0aW9uVHlwZV1cbiAgICAgIDogLy8gZGVmYXVsdCBzY2FsZSBvcHRpb25zIGZvciBwb2ludCBjb3VudDogYWdncmVnYXRpb25UeXBlIHNob3VsZCBiZSBjb3VudCBzaW5jZVxuICAgICAgICAvLyBMQVlFUl9WSVNfQ09ORklHUy5hZ2dyZWdhdGlvbi5kZWZhdWx0VmFsdWUgaXMgQUdHUkVHQVRJT05fVFlQRVMuYXZlcmFnZSxcbiAgICAgICAgREVGQVVMVF9BR0dSRUdBVElPTltjaGFubmVsU2NhbGVUeXBlXVtBR0dSRUdBVElPTl9UWVBFUy5jb3VudF07XG4gIH1cblxuICAvKipcbiAgICogQWdncmVnYXRpb24gbGF5ZXIgaGFuZGxlcyB2aXN1YWwgY2hhbm5lbCBhZ2dyZWdhdGlvbiBpbnNpZGUgZGVjay5nbCBsYXllclxuICAgKi9cbiAgdXBkYXRlTGF5ZXJEb21haW4oKTogQWdncmVnYXRpb25MYXllciB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICB1cGRhdGVMYXllck1ldGEoZGF0YXNldDogS2VwbGVyVGFibGUsIGdldFBvc2l0aW9uKSB7XG4gICAgY29uc3Qge2RhdGFDb250YWluZXJ9ID0gZGF0YXNldDtcbiAgICAvLyBnZXQgYm91bmRzIGZyb20gcG9pbnRzXG4gICAgY29uc3QgYm91bmRzID0gdGhpcy5nZXRQb2ludHNCb3VuZHMoZGF0YUNvbnRhaW5lciwgZ2V0UG9zaXRpb24pO1xuXG4gICAgdGhpcy51cGRhdGVNZXRhKHtib3VuZHN9KTtcbiAgfVxuXG4gIGNhbGN1bGF0ZURhdGFBdHRyaWJ1dGUoe2ZpbHRlcmVkSW5kZXh9OiBLZXBsZXJUYWJsZSwgZ2V0UG9zaXRpb24pIHtcbiAgICBjb25zdCBkYXRhOiBBZ2dyZWdhdGlvbkxheWVyRGF0YVtdID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZpbHRlcmVkSW5kZXgubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGluZGV4ID0gZmlsdGVyZWRJbmRleFtpXTtcbiAgICAgIGNvbnN0IHBvcyA9IGdldFBvc2l0aW9uKHtpbmRleH0pO1xuXG4gICAgICAvLyBpZiBkb2Vzbid0IGhhdmUgcG9pbnQgbGF0IG9yIGxuZywgZG8gbm90IGFkZCB0aGUgcG9pbnRcbiAgICAgIC8vIGRlY2suZ2wgY2FuJ3QgaGFuZGxlIHBvc2l0aW9uID0gbnVsbFxuICAgICAgaWYgKHBvcy5ldmVyeShOdW1iZXIuaXNGaW5pdGUpKSB7XG4gICAgICAgIGRhdGEucHVzaCh7XG4gICAgICAgICAgaW5kZXhcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICBmb3JtYXRMYXllckRhdGEoZGF0YXNldHM6IERhdGFzZXRzLCBvbGRMYXllckRhdGEpIHtcbiAgICBpZiAodGhpcy5jb25maWcuZGF0YUlkID09PSBudWxsKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuICAgIGNvbnN0IHtncHVGaWx0ZXIsIGRhdGFDb250YWluZXJ9ID0gZGF0YXNldHNbdGhpcy5jb25maWcuZGF0YUlkXTtcbiAgICBjb25zdCBnZXRQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb25BY2Nlc3NvcihkYXRhQ29udGFpbmVyKTtcblxuICAgIGNvbnN0IGFnZ3JlZ2F0ZVBvaW50cyA9IGdldFZhbHVlQWdnckZ1bmModGhpcy5nZXRQb2ludERhdGEpO1xuICAgIGNvbnN0IGdldENvbG9yVmFsdWUgPSBhZ2dyZWdhdGVQb2ludHMoXG4gICAgICB0aGlzLmNvbmZpZy5jb2xvckZpZWxkLFxuICAgICAgdGhpcy5jb25maWcudmlzQ29uZmlnLmNvbG9yQWdncmVnYXRpb25cbiAgICApO1xuXG4gICAgY29uc3QgZ2V0RWxldmF0aW9uVmFsdWUgPSBhZ2dyZWdhdGVQb2ludHMoXG4gICAgICB0aGlzLmNvbmZpZy5zaXplRmllbGQsXG4gICAgICB0aGlzLmNvbmZpZy52aXNDb25maWcuc2l6ZUFnZ3JlZ2F0aW9uXG4gICAgKTtcbiAgICBjb25zdCBoYXNGaWx0ZXIgPSBPYmplY3QudmFsdWVzKGdwdUZpbHRlci5maWx0ZXJSYW5nZSkuc29tZSgoYXJyOiBhbnkpID0+XG4gICAgICBhcnIuc29tZSh2ID0+IHYgIT09IDApXG4gICAgKTtcblxuICAgIGNvbnN0IGdldEZpbHRlclZhbHVlID0gZ3B1RmlsdGVyLmZpbHRlclZhbHVlQWNjZXNzb3IoZGF0YUNvbnRhaW5lcikoXG4gICAgICB0aGlzLmdwdUZpbHRlckdldEluZGV4LFxuICAgICAgdGhpcy5ncHVGaWx0ZXJHZXREYXRhXG4gICAgKTtcbiAgICBjb25zdCBmaWx0ZXJEYXRhID0gaGFzRmlsdGVyXG4gICAgICA/IGdldEZpbHRlckRhdGFGdW5jKGdwdUZpbHRlci5maWx0ZXJSYW5nZSwgZ2V0RmlsdGVyVmFsdWUpXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IHtkYXRhfSA9IHRoaXMudXBkYXRlRGF0YShkYXRhc2V0cywgb2xkTGF5ZXJEYXRhKTtcblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhLFxuICAgICAgZ2V0UG9zaXRpb24sXG4gICAgICBfZmlsdGVyRGF0YTogZmlsdGVyRGF0YSxcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgIC4uLihnZXRDb2xvclZhbHVlID8ge2dldENvbG9yVmFsdWV9IDoge30pLFxuICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgLi4uKGdldEVsZXZhdGlvblZhbHVlID8ge2dldEVsZXZhdGlvblZhbHVlfSA6IHt9KVxuICAgIH07XG4gIH1cblxuICBnZXREZWZhdWx0RGVja0xheWVyUHJvcHMob3B0cyk6IGFueSB7XG4gICAgY29uc3QgYmFzZVByb3AgPSBzdXBlci5nZXREZWZhdWx0RGVja0xheWVyUHJvcHMob3B0cyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmJhc2VQcm9wLFxuICAgICAgaGlnaGxpZ2h0Q29sb3I6IEhJR0hMSUdIX0NPTE9SXzNELFxuICAgICAgLy8gZ3B1IGRhdGEgZmlsdGVyaW5nIGlzIG5vdCBzdXBwb3J0ZWQgaW4gYWdncmVnYXRpb24gbGF5ZXJcbiAgICAgIGV4dGVuc2lvbnM6IFtdLFxuICAgICAgYXV0b0hpZ2hsaWdodDogdGhpcy5jb25maWcudmlzQ29uZmlnLmVuYWJsZTNkXG4gICAgfTtcbiAgfVxuXG4gIGdldERlZmF1bHRBZ2dyZWdhdGlvbkxheWVyUHJvcChvcHRzKSB7XG4gICAgY29uc3Qge2dwdUZpbHRlciwgbWFwU3RhdGUsIGxheWVyQ2FsbGJhY2tzID0ge319ID0gb3B0cztcbiAgICBjb25zdCB7dmlzQ29uZmlnfSA9IHRoaXMuY29uZmlnO1xuICAgIGNvbnN0IGVsZVpvb21GYWN0b3IgPSB0aGlzLmdldEVsZXZhdGlvblpvb21GYWN0b3IobWFwU3RhdGUpO1xuXG4gICAgY29uc3QgdXBkYXRlVHJpZ2dlcnMgPSB7XG4gICAgICBnZXRDb2xvclZhbHVlOiB7XG4gICAgICAgIGNvbG9yRmllbGQ6IHRoaXMuY29uZmlnLmNvbG9yRmllbGQsXG4gICAgICAgIGNvbG9yQWdncmVnYXRpb246IHRoaXMuY29uZmlnLnZpc0NvbmZpZy5jb2xvckFnZ3JlZ2F0aW9uXG4gICAgICB9LFxuICAgICAgZ2V0RWxldmF0aW9uVmFsdWU6IHtcbiAgICAgICAgc2l6ZUZpZWxkOiB0aGlzLmNvbmZpZy5zaXplRmllbGQsXG4gICAgICAgIHNpemVBZ2dyZWdhdGlvbjogdGhpcy5jb25maWcudmlzQ29uZmlnLnNpemVBZ2dyZWdhdGlvblxuICAgICAgfSxcbiAgICAgIF9maWx0ZXJEYXRhOiB7XG4gICAgICAgIGZpbHRlclJhbmdlOiBncHVGaWx0ZXIuZmlsdGVyUmFuZ2UsXG4gICAgICAgIC4uLmdwdUZpbHRlci5maWx0ZXJWYWx1ZVVwZGF0ZVRyaWdnZXJzXG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmdldERlZmF1bHREZWNrTGF5ZXJQcm9wcyhvcHRzKSxcbiAgICAgIGNvdmVyYWdlOiB2aXNDb25maWcuY292ZXJhZ2UsXG5cbiAgICAgIC8vIGNvbG9yXG4gICAgICBjb2xvclJhbmdlOiB0aGlzLmdldENvbG9yUmFuZ2UodmlzQ29uZmlnLmNvbG9yUmFuZ2UpLFxuICAgICAgY29sb3JNYXA6IHZpc0NvbmZpZy5jb2xvclJhbmdlLmNvbG9yTWFwLFxuICAgICAgY29sb3JTY2FsZVR5cGU6IHRoaXMuY29uZmlnLmNvbG9yU2NhbGUsXG4gICAgICB1cHBlclBlcmNlbnRpbGU6IHZpc0NvbmZpZy5wZXJjZW50aWxlWzFdLFxuICAgICAgbG93ZXJQZXJjZW50aWxlOiB2aXNDb25maWcucGVyY2VudGlsZVswXSxcbiAgICAgIGNvbG9yQWdncmVnYXRpb246IHZpc0NvbmZpZy5jb2xvckFnZ3JlZ2F0aW9uLFxuXG4gICAgICAvLyBlbGV2YXRpb25cbiAgICAgIGV4dHJ1ZGVkOiB2aXNDb25maWcuZW5hYmxlM2QsXG4gICAgICBlbGV2YXRpb25TY2FsZTogdmlzQ29uZmlnLmVsZXZhdGlvblNjYWxlICogZWxlWm9vbUZhY3RvcixcbiAgICAgIGVsZXZhdGlvblNjYWxlVHlwZTogdGhpcy5jb25maWcuc2l6ZVNjYWxlLFxuICAgICAgZWxldmF0aW9uUmFuZ2U6IHZpc0NvbmZpZy5zaXplUmFuZ2UsXG4gICAgICBlbGV2YXRpb25GaXhlZDogdmlzQ29uZmlnLmZpeGVkSGVpZ2h0LFxuXG4gICAgICBlbGV2YXRpb25Mb3dlclBlcmNlbnRpbGU6IHZpc0NvbmZpZy5lbGV2YXRpb25QZXJjZW50aWxlWzBdLFxuICAgICAgZWxldmF0aW9uVXBwZXJQZXJjZW50aWxlOiB2aXNDb25maWcuZWxldmF0aW9uUGVyY2VudGlsZVsxXSxcblxuICAgICAgLy8gdXBkYXRlVHJpZ2dlcnNcbiAgICAgIHVwZGF0ZVRyaWdnZXJzLFxuXG4gICAgICAvLyBjYWxsYmFja3NcbiAgICAgIG9uU2V0Q29sb3JEb21haW46IGxheWVyQ2FsbGJhY2tzLm9uU2V0TGF5ZXJEb21haW5cbiAgICB9O1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQUdBLElBQUFBLFFBQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLFVBQUEsR0FBQUYsc0JBQUEsQ0FBQUMsT0FBQTtBQVFBLElBQUFFLE1BQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLFVBQUEsR0FBQUgsT0FBQTtBQU04QixTQUFBSSxRQUFBQyxDQUFBLEVBQUFDLENBQUEsUUFBQUMsQ0FBQSxHQUFBQyxNQUFBLENBQUFDLElBQUEsQ0FBQUosQ0FBQSxPQUFBRyxNQUFBLENBQUFFLHFCQUFBLFFBQUFDLENBQUEsR0FBQUgsTUFBQSxDQUFBRSxxQkFBQSxDQUFBTCxDQUFBLEdBQUFDLENBQUEsS0FBQUssQ0FBQSxHQUFBQSxDQUFBLENBQUFDLE1BQUEsV0FBQU4sQ0FBQSxXQUFBRSxNQUFBLENBQUFLLHdCQUFBLENBQUFSLENBQUEsRUFBQUMsQ0FB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