UNPKG

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
"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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