kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
386 lines (383 loc) • 53.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.commonTileVisConfigs = exports.DEFAULT_RADIUS = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
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.throttle"));
var _commonUtils = require("@kepler.gl/common-utils");
var _constants = require("@kepler.gl/constants");
var _table = require("@kepler.gl/table");
var _utils = require("@kepler.gl/utils");
var _baseLayer = _interopRequireDefault(require("../base-layer"));
var _tileUtils = require("./common-tile/tile-utils");
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; }
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; } // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
var DEFAULT_ELEVATION = 500;
var DEFAULT_RADIUS = exports.DEFAULT_RADIUS = 1;
var commonTileVisConfigs = exports.commonTileVisConfigs = {
strokeColor: 'strokeColor',
strokeOpacity: _objectSpread(_objectSpread({}, _constants.LAYER_VIS_CONFIGS.opacity), {}, {
property: 'strokeOpacity'
}),
radius: _objectSpread(_objectSpread({}, _constants.LAYER_VIS_CONFIGS.radius), {}, {
range: [0.1, 100],
step: 0.1,
defaultValue: DEFAULT_RADIUS,
allowCustomValue: false
}),
radiusUnits: {
type: 'boolean',
defaultValue: true,
label: 'Radius in pixels',
group: '',
property: 'radiusUnits',
description: 'Radius in pixels or in meters'
},
enable3d: 'enable3d',
stroked: _objectSpread(_objectSpread({}, _constants.LAYER_VIS_CONFIGS.stroked), {}, {
defaultValue: false
}),
transition: {
type: 'boolean',
defaultValue: false,
label: 'Transition',
group: '',
property: 'transition',
description: 'Smoother transition during animation (enable transition will decrease performance)'
},
heightRange: 'elevationRange',
elevationScale: _objectSpread(_objectSpread({}, _constants.LAYER_VIS_CONFIGS.elevationScale), {}, {
allowCustomValue: false
}),
opacity: 'opacity',
colorRange: 'colorRange',
// TODO: figure out type for radiusByZoom vis config
radiusByZoom: _objectSpread(_objectSpread({}, _constants.LAYER_VIS_CONFIGS.radius), {}, {
defaultValue: {
enabled: false,
stops: null
}
}),
dynamicColor: {
type: 'boolean',
defaultValue: false,
label: 'Dynamic Color',
group: '',
property: 'dynamicColor',
description: 'Use a dynamic color scale based on data visible in the viewport'
}
};
/**
* Abstract tile layer, including common functionality for viewport-based datasets,
* dynamic scales, and tile-based animation
*/
var AbstractTileLayer = exports["default"] = /*#__PURE__*/function (_KeplerLayer) {
function AbstractTileLayer(props) {
var _this;
(0, _classCallCheck2["default"])(this, AbstractTileLayer);
_this = _callSuper(this, AbstractTileLayer, [props]);
(0, _defineProperty2["default"])(_this, "tileDataset", void 0);
(0, _defineProperty2["default"])(_this, "setLayerDomain", undefined);
/**
* Callback to invoke when the viewport changes
*/
(0, _defineProperty2["default"])(_this, "onViewportLoad", function (tiles) {
_this.tileDataset.updateTiles(tiles);
// Update dynamic color domain if required
if (_this.config.visConfig.dynamicColor) {
_this.setDynamicColorDomain();
}
});
(0, _defineProperty2["default"])(_this, "setDynamicColorDomain", (0, _lodash["default"])(function () {
var _this2 = _this,
config = _this2.config,
tileDataset = _this2.tileDataset,
setLayerDomain = _this2.setLayerDomain;
var field = config.colorField;
var colorDomain = config.colorDomain,
colorScale = config.colorScale;
if (!tileDataset || !setLayerDomain || !field) return;
if (colorScale === _constants.SCALE_TYPES.quantize) {
var _tileDataset$getExten = tileDataset.getExtent(field),
_tileDataset$getExten2 = (0, _slicedToArray2["default"])(_tileDataset$getExten, 2),
min = _tileDataset$getExten2[0],
max = _tileDataset$getExten2[1];
if (!Array.isArray(colorDomain) || min !== colorDomain[0] || max !== colorDomain[1]) {
setLayerDomain({
domain: [min, max]
});
}
} else if (colorScale === _constants.SCALE_TYPES.quantile) {
var domain = tileDataset.getQuantileSample(field);
setLayerDomain({
domain: domain
});
} else if (colorScale === _constants.SCALE_TYPES.ordinal) {
var _domain = tileDataset.getUniqueValues(field);
setLayerDomain({
domain: _domain
});
}
}, 500));
_this.registerVisConfig(commonTileVisConfigs);
_this.tileDataset = _this.initTileDataset();
return _this;
}
(0, _inherits2["default"])(AbstractTileLayer, _KeplerLayer);
return (0, _createClass2["default"])(AbstractTileLayer, [{
key: "requireData",
get: function get() {
return true;
}
}, {
key: "requiredLayerColumns",
get: function get() {
return [];
}
}, {
key: "visualChannels",
get: function get() {
return {
color: _objectSpread(_objectSpread({}, _superPropGet(AbstractTileLayer, "visualChannels", this, 1).color), {}, {
accessor: 'getFillColor',
defaultValue: function defaultValue(config) {
return config.color;
}
}),
height: {
property: 'height',
field: 'heightField',
scale: 'heightScale',
domain: 'heightDomain',
range: 'heightRange',
key: 'height',
channelScaleType: 'size',
accessor: 'getElevation',
condition: function condition(config) {
return config.visConfig.enable3d;
},
nullValue: 0,
defaultValue: DEFAULT_ELEVATION
}
};
}
}, {
key: "accessVSFieldValue",
value: function accessVSFieldValue(inputField, indexKey) {
return this.accessRowValue(inputField, indexKey);
}
}, {
key: "getScaleOptions",
value: function getScaleOptions(channelKey) {
if (channelKey === 'color') {
var _field$filterProps;
var channel = this.visualChannels.color;
var _field = this.config[channel.field];
if ((0, _tileUtils.isDomainQuantiles)(_field === null || _field === void 0 || (_field$filterProps = _field.filterProps) === null || _field$filterProps === void 0 ? void 0 : _field$filterProps.domainQuantiles) || this.config.visConfig.dynamicColor ||
// If we've set the scale to quantile, we need to include it - there's a loading
// period in which the visConfig isn't set yet, but if we don't return the right
// scale type we lose it
this.config.colorScale === _constants.SCALE_TYPES.quantile) {
return [_constants.SCALE_TYPES.quantize, _constants.SCALE_TYPES.quantile, _constants.SCALE_TYPES.custom];
}
return [_constants.SCALE_TYPES.quantize, _constants.SCALE_TYPES.custom];
}
return [_constants.SCALE_TYPES.linear];
}
}, {
key: "resetColorDomain",
value: function resetColorDomain() {
var _this$setLayerDomain;
var _this$meta = this.meta,
datasetId = _this$meta.datasetId,
datasets = _this$meta.datasets;
this.updateLayerVisualChannel(datasets === null || datasets === void 0 ? void 0 : datasets[datasetId || ''], 'color');
(_this$setLayerDomain = this.setLayerDomain) === null || _this$setLayerDomain === void 0 || _this$setLayerDomain.call(this, {
domain: this.config.colorDomain
});
}
}, {
key: "updateLayerConfig",
value: function updateLayerConfig(newConfig) {
var _this$config$visConfi,
_newConfig$visConfig$,
_newConfig$visConfig,
_this3 = this;
// When the dynamic color setting changes, we need to recalculate the layer domain
var old = (_this$config$visConfi = this.config.visConfig.dynamicColor) !== null && _this$config$visConfi !== void 0 ? _this$config$visConfi : false;
var next = (_newConfig$visConfig$ = (_newConfig$visConfig = newConfig.visConfig) === null || _newConfig$visConfig === void 0 ? void 0 : _newConfig$visConfig.dynamicColor) !== null && _newConfig$visConfig$ !== void 0 ? _newConfig$visConfig$ : old;
var scaleTypeChanged = newConfig.colorScale && this.config.colorScale !== newConfig.colorScale;
_superPropGet(AbstractTileLayer, "updateLayerConfig", this, 3)([newConfig]);
var colorField = this.config.colorField;
if (colorField) {
// When we switch from dynamic to non-dynamic or vice versa, we need to update
// the color domain. This is downstream from a dispatch call, so we use
// setTimeout to avoid "reducers may not dispatch actions" errors
if (next && (!old || scaleTypeChanged)) {
setTimeout(function () {
return _this3.setDynamicColorDomain();
}, 0);
} else if (old && !next) {
setTimeout(function () {
return _this3.resetColorDomain();
}, 0);
}
}
return this;
}
}, {
key: "animationDomain",
get: function get() {
return this.config.animation.domain;
}
}, {
key: "setInitialLayerConfig",
value: function setInitialLayerConfig(dataset) {
var defaultColorField = (0, _utils.findDefaultColorField)(dataset);
if (defaultColorField) {
this.updateLayerConfig({
colorField: defaultColorField
});
this.updateLayerVisualChannel(dataset, 'color');
}
return this;
}
}, {
key: "getDefaultLayerConfig",
value: function getDefaultLayerConfig(props) {
return _objectSpread(_objectSpread({}, _superPropGet(AbstractTileLayer, "getDefaultLayerConfig", this, 3)([props])), {}, {
colorScale: _constants.SCALE_TYPES.quantize,
// add height visual channel
heightField: null,
heightDomain: [0, 1],
heightScale: 'linear'
});
}
// We can render without columns, so we redefine this method
}, {
key: "shouldRenderLayer",
value: function shouldRenderLayer() {
return Boolean(this.type && this.config.isVisible);
}
}, {
key: "updateAnimationDomainByField",
value: function updateAnimationDomainByField(channel) {
var field = this.config[this.visualChannels[channel].field];
if ((0, _tileUtils.isIndexedField)(field) && field.indexBy.type === _constants.ALL_FIELD_TYPES.timestamp) {
var timeDomain = field.indexBy.timeDomain;
this.updateLayerConfig({
animation: _objectSpread(_objectSpread({}, timeDomain), {}, {
enabled: true,
startTime: timeDomain.domain[0]
})
});
}
}
}, {
key: "updateAnimationDomain",
value: function updateAnimationDomain(domain) {
this.updateLayerConfig({
animation: _objectSpread(_objectSpread({}, this.config.animation), {}, {
domain: domain
})
});
}
}, {
key: "updateLayerDomain",
value: function updateLayerDomain(datasets, newFilter) {
var _this4 = this;
_superPropGet(AbstractTileLayer, "updateLayerDomain", this, 3)([datasets, newFilter]);
if (newFilter) {
// invalidate cachedVisibleDataset when e.g. changing filters
this.tileDataset.invalidateCache();
}
Object.keys(this.visualChannels).forEach(function (channel) {
_this4.updateAnimationDomainByField(channel);
});
return this;
}
}, {
key: "updateLayerVisualChannel",
value: function updateLayerVisualChannel(dataset, channel) {
_superPropGet(AbstractTileLayer, "updateLayerVisualChannel", this, 3)([dataset, channel]);
// create animation if field is indexed by time
this.updateAnimationDomainByField(channel);
}
}, {
key: "formatLayerData",
value: function formatLayerData(datasets, oldLayerData, animationConfig) {
var dataId = this.config.dataId;
if (!(0, _commonUtils.notNullorUndefined)(dataId)) {
return {};
}
var dataset = datasets[dataId];
var dataUpdateTriggers = this.getDataUpdateTriggers(dataset);
var triggerChanged = this.getChangedTriggers(dataUpdateTriggers);
if (triggerChanged && triggerChanged.getMeta) {
this.updateLayerMeta(dataset, datasets);
}
var indexKey = this.config.animation.enabled ? animationConfig.currentTime : null;
var accessors = this.getAttributeAccessors({
dataAccessor: function dataAccessor() {
return function (d) {
return d;
};
},
dataContainer: dataset.dataContainer,
indexKey: indexKey
});
var metadata = dataset === null || dataset === void 0 ? void 0 : dataset.metadata;
var metadataToData = metadata ? {
minZoom: metadata.minZoom,
maxZoom: metadata.maxZoom,
bounds: metadata.bounds
} : {};
return _objectSpread(_objectSpread({}, metadataToData), accessors);
}
}, {
key: "getGpuFilterValueAccessor",
value: function getGpuFilterValueAccessor(_ref) {
var _this5 = this;
var gpuFilter = _ref.gpuFilter,
animationConfig = _ref.animationConfig;
var indexKey = this.config.animation.enabled ? animationConfig.currentTime : null;
var valueAccessor = function valueAccessor(dataContainer, d) {
return function (field) {
return _this5.accessVSFieldValue(field, indexKey)(field, d);
};
};
return gpuFilter.filterValueAccessor(null)(undefined, valueAccessor);
}
}], [{
key: "findDefaultLayerProps",
value: function findDefaultLayerProps(dataset) {
if (!(0, _table.isTileDataset)(dataset)) {
return {
props: []
};
}
var newLayerProp = {
dataId: dataset.id,
label: dataset.label,
isVisible: true
};
return {
props: [newLayerProp]
};
}
}]);
}(_baseLayer["default"]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9kYXNoIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfY29tbW9uVXRpbHMiLCJfY29uc3RhbnRzIiwiX3RhYmxlIiwiX3V0aWxzIiwiX2Jhc2VMYXllciIsIl90aWxlVXRpbHMiLCJfY2FsbFN1cGVyIiwidCIsIm8iLCJlIiwiX2dldFByb3RvdHlwZU9mMiIsIl9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuMiIsIl9pc05hdGl2ZVJlZmxlY3RDb25zdHJ1Y3QiLCJSZWZsZWN0IiwiY29uc3RydWN0IiwiY29uc3RydWN0b3IiLCJhcHBseSIsIkJvb2xlYW4iLCJwcm90b3R5cGUiLCJ2YWx1ZU9mIiwiY2FsbCIsIl9zdXBlclByb3BHZXQiLCJyIiwicCIsIl9nZXQyIiwib3duS2V5cyIsIk9iamVjdCIsImtleXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiZGVmaW5lUHJvcGVydHkiLCJERUZBVUxUX0VMRVZBVElPTiIsIkRFRkFVTFRfUkFESVVTIiwiZXhwb3J0cyIsImNvbW1vblRpbGVWaXNDb25maWdzIiwic3Ryb2tlQ29sb3IiLCJzdHJva2VPcGFjaXR5IiwiTEFZRVJfVklTX0NPTkZJR1MiLCJvcGFjaXR5IiwicHJvcGVydHkiLCJyYWRpdXMiLCJyYW5nZSIsInN0ZXAiLCJkZWZhdWx0VmFsdWUiLCJhbGxvd0N1c3RvbVZhbHVlIiwicmFkaXVzVW5pdHMiLCJ0eXBlIiwibGFiZWwiLCJncm91cCIsImRlc2NyaXB0aW9uIiwiZW5hYmxlM2QiLCJzdHJva2VkIiwidHJhbnNpdGlvbiIsImhlaWdodFJhbmdlIiwiZWxldmF0aW9uU2NhbGUiLCJjb2xvclJhbmdlIiwicmFkaXVzQnlab29tIiwiZW5hYmxlZCIsInN0b3BzIiwiZHluYW1pY0NvbG9yIiwiQWJzdHJhY3RUaWxlTGF5ZXIiLCJfS2VwbGVyTGF5ZXIiLCJwcm9wcyIsIl90aGlzIiwiX2NsYXNzQ2FsbENoZWNrMiIsInVuZGVmaW5lZCIsInRpbGVzIiwidGlsZURhdGFzZXQiLCJ1cGRhdGVUaWxlcyIsImNvbmZpZyIsInZpc0NvbmZpZyIsInNldER5bmFtaWNDb2xvckRvbWFpbiIsInRocm90dGxlIiwiX3RoaXMyIiwic2V0TGF5ZXJEb21haW4iLCJmaWVsZCIsImNvbG9yRmllbGQiLCJjb2xvckRvbWFpbiIsImNvbG9yU2NhbGUiLCJTQ0FMRV9UWVBFUyIsInF1YW50aXplIiwiX3RpbGVEYXRhc2V0JGdldEV4dGVuIiwiZ2V0RXh0ZW50IiwiX3RpbGVEYXRhc2V0JGdldEV4dGVuMiIsIl9zbGljZWRUb0FycmF5MiIsIm1pbiIsIm1heCIsIkFycmF5IiwiaXNBcnJheSIsImRvbWFpbiIsInF1YW50aWxlIiwiZ2V0UXVhbnRpbGVTYW1wbGUiLCJvcmRpbmFsIiwiZ2V0VW5pcXVlVmFsdWVzIiwicmVnaXN0ZXJWaXNDb25maWciLCJpbml0VGlsZURhdGFzZXQiLCJfaW5oZXJpdHMyIiwiX2NyZWF0ZUNsYXNzMiIsImtleSIsImdldCIsImNvbG9yIiwiYWNjZXNzb3IiLCJoZWlnaHQiLCJzY2FsZSIsImNoYW5uZWxTY2FsZVR5cGUiLCJjb25kaXRpb24iLCJudWxsVmFsdWUiLCJ2YWx1ZSIsImFjY2Vzc1ZTRmllbGRWYWx1ZSIsImlucHV0RmllbGQiLCJpbmRleEtleSIsImFjY2Vzc1Jvd1ZhbHVlIiwiZ2V0U2NhbGVPcHRpb25zIiwiY2hhbm5lbEtleSIsIl9maWVsZCRmaWx0ZXJQcm9wcyIsImNoYW5uZWwiLCJ2aXN1YWxDaGFubmVscyIsImlzRG9tYWluUXVhbnRpbGVzIiwiZmlsdGVyUHJvcHMiLCJkb21haW5RdWFudGlsZXMiLCJjdXN0b20iLCJsaW5lYXIiLCJyZXNldENvbG9yRG9tYWluIiwiX3RoaXMkc2V0TGF5ZXJEb21haW4iLCJfdGhpcyRtZXRhIiwibWV0YSIsImRhdGFzZXRJZCIsImRhdGFzZXRzIiwidXBkYXRlTGF5ZXJWaXN1YWxDaGFubmVsIiwidXBkYXRlTGF5ZXJDb25maWciLCJuZXdDb25maWciLCJfdGhpcyRjb25maWckdmlzQ29uZmkiLCJfbmV3Q29uZmlnJHZpc0NvbmZpZyQiLCJfbmV3Q29uZmlnJHZpc0NvbmZpZyIsIl90aGlzMyIsIm9sZCIsIm5leHQiLCJzY2FsZVR5cGVDaGFuZ2VkIiwic2V0VGltZW91dCIsImFuaW1hdGlvbiIsInNldEluaXRpYWxMYXllckNvbmZpZyIsImRhdGFzZXQiLCJkZWZhdWx0Q29sb3JGaWVsZCIsImZpbmREZWZhdWx0Q29sb3JGaWVsZCIsImdldERlZmF1bHRMYXllckNvbmZpZyIsImhlaWdodEZpZWxkIiwiaGVpZ2h0RG9tYWluIiwiaGVpZ2h0U2NhbGUiLCJzaG91bGRSZW5kZXJMYXllciIsImlzVmlzaWJsZSIsInVwZGF0ZUFuaW1hdGlvbkRvbWFpbkJ5RmllbGQiLCJpc0luZGV4ZWRGaWVsZCIsImluZGV4QnkiLCJBTExfRklFTERfVFlQRVMiLCJ0aW1lc3RhbXAiLCJ0aW1lRG9tYWluIiwic3RhcnRUaW1lIiwidXBkYXRlQW5pbWF0aW9uRG9tYWluIiwidXBkYXRlTGF5ZXJEb21haW4iLCJuZXdGaWx0ZXIiLCJfdGhpczQiLCJpbnZhbGlkYXRlQ2FjaGUiLCJmb3JtYXRMYXllckRhdGEiLCJvbGRMYXllckRhdGEiLCJhbmltYXRpb25Db25maWciLCJkYXRhSWQiLCJub3ROdWxsb3JVbmRlZmluZWQiLCJkYXRhVXBkYXRlVHJpZ2dlcnMiLCJnZXREYXRhVXBkYXRlVHJpZ2dlcnMiLCJ0cmlnZ2VyQ2hhbmdlZCIsImdldENoYW5nZWRUcmlnZ2VycyIsImdldE1ldGEiLCJ1cGRhdGVMYXllck1ldGEiLCJjdXJyZW50VGltZSIsImFjY2Vzc29ycyIsImdldEF0dHJpYnV0ZUFjY2Vzc29ycyIsImRhdGFBY2Nlc3NvciIsImQiLCJkYXRhQ29udGFpbmVyIiwibWV0YWRhdGEiLCJtZXRhZGF0YVRvRGF0YSIsIm1pblpvb20iLCJtYXhab29tIiwiYm91bmRzIiwiZ2V0R3B1RmlsdGVyVmFsdWVBY2Nlc3NvciIsIl9yZWYiLCJfdGhpczUiLCJncHVGaWx0ZXIiLCJ2YWx1ZUFjY2Vzc29yIiwiZmlsdGVyVmFsdWVBY2Nlc3NvciIsImZpbmREZWZhdWx0TGF5ZXJQcm9wcyIsImlzVGlsZURhdGFzZXQiLCJuZXdMYXllclByb3AiLCJpZCIsIktlcGxlckxheWVyIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3ZlY3Rvci10aWxlL2Fic3RyYWN0LXRpbGUtbGF5ZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0IHRocm90dGxlIGZyb20gJ2xvZGFzaC50aHJvdHRsZSc7XG5cbmltcG9ydCB7bm90TnVsbG9yVW5kZWZpbmVkfSBmcm9tICdAa2VwbGVyLmdsL2NvbW1vbi11dGlscyc7XG5pbXBvcnQge1NDQUxFX1RZUEVTLCBBTExfRklFTERfVFlQRVMsIExBWUVSX1ZJU19DT05GSUdTfSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5pbXBvcnQge1xuICBpc1RpbGVEYXRhc2V0LFxuICBLZXBsZXJUYWJsZSBhcyBLZXBsZXJEYXRhc2V0LFxuICBEYXRhc2V0cyBhcyBLZXBsZXJEYXRhc2V0cyxcbiAgR3B1RmlsdGVyXG59IGZyb20gJ0BrZXBsZXIuZ2wvdGFibGUnO1xuaW1wb3J0IHtcbiAgQW5pbWF0aW9uQ29uZmlnLFxuICBGaWVsZCxcbiAgQmluZGVkTGF5ZXJDYWxsYmFja3MsXG4gIFZpc0NvbmZpZ0Jvb2xlYW4sXG4gIFZpc0NvbmZpZ1JhbmdlLFxuICBWaXNDb25maWdDb2xvclJhbmdlLFxuICBWaXNDb25maWdOdW1iZXIsXG4gIFZpc0NvbmZpZ0NvbG9yU2VsZWN0LFxuICBMYXllckNvbG9yQ29uZmlnLFxuICBMYXllckhlaWdodENvbmZpZyxcbiAgRmlsdGVyLFxuICBGaWVsZCBhcyBLZXBsZXJGaWVsZCxcbiAgTWFwU3RhdGUsXG4gIE1lcmdlLFxuICBab29tU3RvcHNDb25maWdcbn0gZnJvbSAnQGtlcGxlci5nbC90eXBlcyc7XG5pbXBvcnQge2ZpbmREZWZhdWx0Q29sb3JGaWVsZCwgRGF0YUNvbnRhaW5lckludGVyZmFjZX0gZnJvbSAnQGtlcGxlci5nbC91dGlscyc7XG5cbmltcG9ydCB7XG4gIGRlZmF1bHQgYXMgS2VwbGVyTGF5ZXIsXG4gIExheWVyQmFzZUNvbmZpZyxcbiAgTGF5ZXJCYXNlQ29uZmlnUGFydGlhbCxcbiAgVmlzdWFsQ2hhbm5lbCxcbiAgVmlzdWFsQ2hhbm5lbERvbWFpbixcbiAgVmlzdWFsQ2hhbm5lbEZpZWxkXG59IGZyb20gJy4uL2Jhc2UtbGF5ZXInO1xuaW1wb3J0IFRpbGVEYXRhc2V0IGZyb20gJy4vY29tbW9uLXRpbGUvdGlsZS1kYXRhc2V0JztcbmltcG9ydCB7aXNJbmRleGVkRmllbGQsIGlzRG9tYWluUXVhbnRpbGVzfSBmcm9tICcuL2NvbW1vbi10aWxlL3RpbGUtdXRpbHMnO1xuaW1wb3J0IHtGaW5kRGVmYXVsdExheWVyUHJvcHNSZXR1cm5WYWx1ZX0gZnJvbSAnLi4vbGF5ZXItdXRpbHMnO1xuXG5jb25zdCBERUZBVUxUX0VMRVZBVElPTiA9IDUwMDtcbmV4cG9ydCBjb25zdCBERUZBVUxUX1JBRElVUyA9IDE7XG5cbmV4cG9ydCB0eXBlIEFic3RyYWN0VGlsZUxheWVyVmlzQ29uZmlnU2V0dGluZ3MgPSB7XG4gIHN0cm9rZUNvbG9yOiBWaXNDb25maWdDb2xvclNlbGVjdDtcbiAgc3Ryb2tlT3BhY2l0eTogVmlzQ29uZmlnTnVtYmVyO1xuICByYWRpdXM6IFZpc0NvbmZpZ051bWJlcjtcbiAgcmFkaXVzVW5pdHM6IFZpc0NvbmZpZ0Jvb2xlYW47XG4gIGVuYWJsZTNkOiBWaXNDb25maWdCb29sZWFuO1xuICBzdHJva2VkOiBWaXNDb25maWdCb29sZWFuO1xuICB0cmFuc2l0aW9uOiBWaXNDb25maWdCb29sZWFuO1xuICBoZWlnaHRSYW5nZTogVmlzQ29uZmlnUmFuZ2U7XG4gIGVsZXZhdGlvblNjYWxlOiBWaXNDb25maWdOdW1iZXI7XG4gIG9wYWNpdHk6IFZpc0NvbmZpZ051bWJlcjtcbiAgY29sb3JSYW5nZTogVmlzQ29uZmlnQ29sb3JSYW5nZTtcbiAgLy8gVE9ETzogZmlndXJlIG91dCB0eXBlIGZvciByYWRpdXNCeVpvb20gdmlzIGNvbmZpZ1xuICByYWRpdXNCeVpvb206IGFueTtcbiAgZHluYW1pY0NvbG9yOiBWaXNDb25maWdCb29sZWFuO1xufTtcblxuZXhwb3J0IHR5cGUgTGF5ZXJEYXRhID0ge1xuICBtaW5ab29tPzogbnVtYmVyO1xuICBtYXhab29tPzogbnVtYmVyO1xuICBib3VuZHM/OiBudW1iZXJbXTtcbiAgZ2V0UG9pbnRSYWRpdXM/OiAoKSA9PiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBMYXllck9wdHMgPSB7XG4gIGlkeDogbnVtYmVyO1xuICBtYXBTdGF0ZTogTWFwU3RhdGU7XG4gIGRhdGE6IExheWVyRGF0YTtcbiAgZ3B1RmlsdGVyOiBHcHVGaWx0ZXI7XG4gIGFuaW1hdGlvbkNvbmZpZzogQW5pbWF0aW9uQ29uZmlnO1xuICB0aWxlc2V0RGF0YVVybD86IHN0cmluZyB8IG51bGw7XG4gIGxheWVyQ2FsbGJhY2tzOiBCaW5kZWRMYXllckNhbGxiYWNrcztcbn07XG5cbmV4cG9ydCBjb25zdCBjb21tb25UaWxlVmlzQ29uZmlncyA9IHtcbiAgc3Ryb2tlQ29sb3I6ICdzdHJva2VDb2xvcicgYXMgY29uc3QsXG4gIHN0cm9rZU9wYWNpdHk6IHtcbiAgICAuLi5MQVlFUl9WSVNfQ09ORklHUy5vcGFjaXR5LFxuICAgIHByb3BlcnR5OiAnc3Ryb2tlT3BhY2l0eSdcbiAgfSxcbiAgcmFkaXVzOiB7XG4gICAgLi4uTEFZRVJfVklTX0NPTkZJR1MucmFkaXVzLFxuICAgIHJhbmdlOiBbMC4xLCAxMDBdLFxuICAgIHN0ZXA6IDAuMSxcbiAgICBkZWZhdWx0VmFsdWU6IERFRkFVTFRfUkFESVVTLFxuICAgIGFsbG93Q3VzdG9tVmFsdWU6IGZhbHNlXG4gIH0gYXMgVmlzQ29uZmlnTnVtYmVyLFxuICByYWRpdXNVbml0czoge1xuICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICBkZWZhdWx0VmFsdWU6IHRydWUsXG4gICAgbGFiZWw6ICdSYWRpdXMgaW4gcGl4ZWxzJyxcbiAgICBncm91cDogJycsXG4gICAgcHJvcGVydHk6ICdyYWRpdXNVbml0cycsXG4gICAgZGVzY3JpcHRpb246ICdSYWRpdXMgaW4gcGl4ZWxzIG9yIGluIG1ldGVycydcbiAgfSBhcyBWaXNDb25maWdCb29sZWFuLFxuICBlbmFibGUzZDogJ2VuYWJsZTNkJyBhcyBjb25zdCxcbiAgc3Ryb2tlZDoge1xuICAgIC4uLkxBWUVSX1ZJU19DT05GSUdTLnN0cm9rZWQsXG4gICAgZGVmYXVsdFZhbHVlOiBmYWxzZVxuICB9LFxuICB0cmFuc2l0aW9uOiB7XG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgbGFiZWw6ICdUcmFuc2l0aW9uJyxcbiAgICBncm91cDogJycsXG4gICAgcHJvcGVydHk6ICd0cmFuc2l0aW9uJyxcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdTbW9vdGhlciB0cmFuc2l0aW9uIGR1cmluZyBhbmltYXRpb24gKGVuYWJsZSB0cmFuc2l0aW9uIHdpbGwgZGVjcmVhc2UgcGVyZm9ybWFuY2UpJ1xuICB9IGFzIFZpc0NvbmZpZ0Jvb2xlYW4sXG4gIGhlaWdodFJhbmdlOiAnZWxldmF0aW9uUmFuZ2UnIGFzIGNvbnN0LFxuICBlbGV2YXRpb25TY2FsZTogey4uLkxBWUVSX1ZJU19DT05GSUdTLmVsZXZhdGlvblNjYWxlLCBhbGxvd0N1c3RvbVZhbHVlOiBmYWxzZX0sXG4gIG9wYWNpdHk6ICdvcGFjaXR5JyBhcyBjb25zdCxcbiAgY29sb3JSYW5nZTogJ2NvbG9yUmFuZ2UnIGFzIGNvbnN0LFxuICAvLyBUT0RPOiBmaWd1cmUgb3V0IHR5cGUgZm9yIHJhZGl1c0J5Wm9vbSB2aXMgY29uZmlnXG4gIHJhZGl1c0J5Wm9vbToge1xuICAgIC4uLkxBWUVSX1ZJU19DT05GSUdTLnJhZGl1cyxcbiAgICBkZWZhdWx0VmFsdWU6IHtcbiAgICAgIGVuYWJsZWQ6IGZhbHNlLFxuICAgICAgc3RvcHM6IG51bGxcbiAgICB9IGFzIFpvb21TdG9wc0NvbmZpZ1xuICB9IGFzIGFueSxcbiAgZHluYW1pY0NvbG9yOiB7XG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgbGFiZWw6ICdEeW5hbWljIENvbG9yJyxcbiAgICBncm91cDogJycsXG4gICAgcHJvcGVydHk6ICdkeW5hbWljQ29sb3InLFxuICAgIGRlc2NyaXB0aW9uOiAnVXNlIGEgZHluYW1pYyBjb2xvciBzY2FsZSBiYXNlZCBvbiBkYXRhIHZpc2libGUgaW4gdGhlIHZpZXdwb3J0J1xuICB9IGFzIFZpc0NvbmZpZ0Jvb2xlYW5cbn07XG5cbmV4cG9ydCB0eXBlIEFic3RyYWN0VGlsZUxheWVyQ29uZmlnID0gTWVyZ2U8XG4gIExheWVyQmFzZUNvbmZpZyxcbiAge2NvbG9yRmllbGQ/OiBWaXN1YWxDaGFubmVsRmllbGQ7IGNvbG9yU2NhbGU/OiBzdHJpbmc7IGNvbG9yRG9tYWluPzogVmlzdWFsQ2hhbm5lbERvbWFpbn1cbj47XG5cbi8qKlxuICogQWJzdHJhY3QgdGlsZSBsYXllciwgaW5jbHVkaW5nIGNvbW1vbiBmdW5jdGlvbmFsaXR5IGZvciB2aWV3cG9ydC1iYXNlZCBkYXRhc2V0cyxcbiAqIGR5bmFtaWMgc2NhbGVzLCBhbmQgdGlsZS1iYXNlZCBhbmltYXRpb25cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgQWJzdHJhY3RUaWxlTGF5ZXI8XG4gIC8vIFR5cGUgb2YgdGhlIHRpbGUgaXRzZWxmXG4gIFQsXG4gIC8vIFR5cGUgb2YgdGhlIGl0ZXJhYmxlIGRhdGEgb2JqZWN0XG4gIEkgZXh0ZW5kcyBJdGVyYWJsZTxhbnk+ID0gVCBleHRlbmRzIEl0ZXJhYmxlPGFueT4gPyBUIDogbmV2ZXJcbj4gZXh0ZW5kcyBLZXBsZXJMYXllciB7XG4gIGRlY2xhcmUgY29uZmlnOiBBYnN0cmFjdFRpbGVMYXllckNvbmZpZztcbiAgZGVjbGFyZSB2aXNDb25maWdTZXR0aW5nczogQWJzdHJhY3RUaWxlTGF5ZXJWaXNDb25maWdTZXR0aW5ncztcblxuICBjb25zdHJ1Y3Rvcihwcm9wczogQ29uc3RydWN0b3JQYXJhbWV0ZXJzPHR5cGVvZiBLZXBsZXJMYXllcj5bMF0pIHtcbiAgICBzdXBlcihwcm9wcyk7XG4gICAgdGhpcy5yZWdpc3RlclZpc0NvbmZpZyhjb21tb25UaWxlVmlzQ29uZmlncyk7XG4gICAgdGhpcy50aWxlRGF0YXNldCA9IHRoaXMuaW5pdFRpbGVEYXRhc2V0KCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgdGlsZURhdGFzZXQ6IFRpbGVEYXRhc2V0PFQsIEk+O1xuICBwcm90ZWN0ZWQgc2V0TGF5ZXJEb21haW46IEJpbmRlZExheWVyQ2FsbGJhY2tzWydvblNldExheWVyRG9tYWluJ10gPSB1bmRlZmluZWQ7XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGluaXRUaWxlRGF0YXNldCgpOiBUaWxlRGF0YXNldDxULCBJPjtcblxuICBzdGF0aWMgZmluZERlZmF1bHRMYXllclByb3BzKGRhdGFzZXQ6IEtlcGxlckRhdGFzZXQpOiBGaW5kRGVmYXVsdExheWVyUHJvcHNSZXR1cm5WYWx1ZSB7XG4gICAgaWYgKCFpc1RpbGVEYXRhc2V0KGRhdGFzZXQpKSB7XG4gICAgICByZXR1cm4ge3Byb3BzOiBbXX07XG4gICAgfVxuXG4gICAgY29uc3QgbmV3TGF5ZXJQcm9wID0ge1xuICAgICAgZGF0YUlkOiBkYXRhc2V0LmlkLFxuICAgICAgbGFiZWw6IGRhdGFzZXQubGFiZWwsXG4gICAgICBpc1Zpc2libGU6IHRydWVcbiAgICB9O1xuXG4gICAgcmV0dXJuIHtwcm9wczogW25ld0xheWVyUHJvcF19O1xuICB9XG5cbiAgZ2V0IHJlcXVpcmVEYXRhKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgZ2V0IHJlcXVpcmVkTGF5ZXJDb2x1bW5zKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBnZXQgdmlzdWFsQ2hhbm5lbHMoKTogUmVjb3JkPHN0cmluZywgVmlzdWFsQ2hhbm5lbD4ge1xuICAgIHJldHVybiB7XG4gICAgICBjb2xvcjoge1xuICAgICAgICAuLi5zdXBlci52aXN1YWxDaGFubmVscy5jb2xvcixcbiAgICAgICAgYWNjZXNzb3I6ICdnZXRGaWxsQ29sb3InLFxuICAgICAgICBkZWZhdWx0VmFsdWU6IGNvbmZpZyA9PiBjb25maWcuY29sb3JcbiAgICAgIH0sXG4gICAgICBoZWlnaHQ6IHtcbiAgICAgICAgcHJvcGVydHk6ICdoZWlnaHQnLFxuICAgICAgICBmaWVsZDogJ2hlaWdodEZpZWxkJyxcbiAgICAgICAgc2NhbGU6ICdoZWlnaHRTY2FsZScsXG4gICAgICAgIGRvbWFpbjogJ2hlaWdodERvbWFpbicsXG4gICAgICAgIHJhbmdlOiAnaGVpZ2h0UmFuZ2UnLFxuICAgICAgICBrZXk6ICdoZWlnaHQnLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiAnc2l6ZScsXG4gICAgICAgIGFjY2Vzc29yOiAnZ2V0RWxldmF0aW9uJyxcbiAgICAgICAgY29uZGl0aW9uOiBjb25maWcgPT4gY29uZmlnLnZpc0NvbmZpZy5lbmFibGUzZCxcbiAgICAgICAgbnVsbFZhbHVlOiAwLFxuICAgICAgICBkZWZhdWx0VmFsdWU6IERFRkFVTFRfRUxFVkFUSU9OXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayB0byBpbnZva2Ugd2hlbiB0aGUgdmlld3BvcnQgY2hhbmdlc1xuICAgKi9cbiAgb25WaWV3cG9ydExvYWQgPSAodGlsZXM6IFRbXSk6IHZvaWQgPT4ge1xuICAgIHRoaXMudGlsZURhdGFzZXQudXBkYXRlVGlsZXModGlsZXMpO1xuICAgIC8vIFVwZGF0ZSBkeW5hbWljIGNvbG9yIGRvbWFpbiBpZiByZXF1aXJlZFxuICAgIGlmICh0aGlzLmNvbmZpZy52aXNDb25maWcuZHluYW1pY0NvbG9yKSB7XG4gICAgICB0aGlzLnNldER5bmFtaWNDb2xvckRvbWFpbigpO1xuICAgIH1cbiAgfTtcblxuICBhYnN0cmFjdCBhY2Nlc3NSb3dWYWx1ZShcbiAgICBmaWVsZD86IEtlcGxlckZpZWxkLFxuICAgIGluZGV4S2V5PzogbnVtYmVyIHwgbnVsbFxuICApOiAoZmllbGQ6IEtlcGxlckZpZWxkLCBkYXR1bTogVCBleHRlbmRzIEl0ZXJhYmxlPGluZmVyIFY+ID8gViA6IG5ldmVyKSA9PiBzdHJpbmcgfCBudW1iZXIgfCBudWxsO1xuXG4gIGFjY2Vzc1ZTRmllbGRWYWx1ZShpbnB1dEZpZWxkPzogRmllbGQsIGluZGV4S2V5PzogbnVtYmVyIHwgbnVsbCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuYWNjZXNzUm93VmFsdWUoaW5wdXRGaWVsZCwgaW5kZXhLZXkpO1xuICB9XG5cbiAgZ2V0U2NhbGVPcHRpb25zKGNoYW5uZWxLZXk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICBpZiAoY2hhbm5lbEtleSA9PT0gJ2NvbG9yJykge1xuICAgICAgY29uc3QgY2hhbm5lbCA9IHRoaXMudmlzdWFsQ2hhbm5lbHMuY29sb3I7XG4gICAgICBjb25zdCBmaWVsZCA9IHRoaXMuY29uZmlnW2NoYW5uZWwuZmllbGRdO1xuXG4gICAgICBpZiAoXG4gICAgICAgIGlzRG9tYWluUXVhbnRpbGVzKGZpZWxkPy5maWx0ZXJQcm9wcz8uZG9tYWluUXVhbnRpbGVzKSB8fFxuICAgICAgICB0aGlzLmNvbmZpZy52aXNDb25maWcuZHluYW1pY0NvbG9yIHx8XG4gICAgICAgIC8vIElmIHdlJ3ZlIHNldCB0aGUgc2NhbGUgdG8gcXVhbnRpbGUsIHdlIG5lZWQgdG8gaW5jbHVkZSBpdCAtIHRoZXJlJ3MgYSBsb2FkaW5nXG4gICAgICAgIC8vIHBlcmlvZCBpbiB3aGljaCB0aGUgdmlzQ29uZmlnIGlzbid0IHNldCB5ZXQsIGJ1dCBpZiB3ZSBkb24ndCByZXR1cm4gdGhlIHJpZ2h0XG4gICAgICAgIC8vIHNjYWxlIHR5cGUgd2UgbG9zZSBpdFxuICAgICAgICB0aGlzLmNvbmZpZy5jb2xvclNjYWxlID09PSBTQ0FMRV9UWVBFUy5xdWFudGlsZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBbU0NBTEVfVFlQRVMucXVhbnRpemUsIFNDQUxFX1RZUEVTLnF1YW50aWxlLCBTQ0FMRV9UWVBFUy5jdXN0b21dO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFtTQ0FMRV9UWVBFUy5xdWFudGl6ZSwgU0NBTEVfVFlQRVMuY3VzdG9tXTtcbiAgICB9XG5cbiAgICByZXR1cm4gW1NDQUxFX1RZUEVTLmxpbmVhcl07XG4gIH1cblxuICBzZXREeW5hbWljQ29sb3JEb21haW4gPSB0aHJvdHRsZSgoKTogdm9pZCA9PiB7XG4gICAgY29uc3Qge2NvbmZpZywgdGlsZURhdGFzZXQsIHNldExheWVyRG9tYWlufSA9IHRoaXM7XG4gICAgY29uc3QgZmllbGQgPSBjb25maWcuY29sb3JGaWVsZDtcbiAgICBjb25zdCB7Y29sb3JEb21haW4sIGNvbG9yU2NhbGV9ID0gY29uZmlnO1xuICAgIGlmICghdGlsZURhdGFzZXQgfHwgIXNldExheWVyRG9tYWluIHx8ICFmaWVsZCkgcmV0dXJuO1xuXG4gICAgaWYgKGNvbG9yU2NhbGUgPT09IFNDQUxFX1RZUEVTLnF1YW50aXplKSB7XG4gICAgICBjb25zdCBbbWluLCBtYXhdID0gdGlsZURhdGFzZXQuZ2V0RXh0ZW50KGZpZWxkKTtcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShjb2xvckRvbWFpbikgfHwgbWluICE9PSBjb2xvckRvbWFpblswXSB8fCBtYXggIT09IGNvbG9yRG9tYWluWzFdKSB7XG4gICAgICAgIHNldExheWVyRG9tYWluKHtkb21haW46IFttaW4sIG1heF19KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGNvbG9yU2NhbGUgPT09IFNDQUxFX1RZUEVTLnF1YW50aWxlKSB7XG4gICAgICBjb25zdCBkb21haW4gPSB0aWxlRGF0YXNldC5nZXRRdWFudGlsZVNhbXBsZShmaWVsZCk7XG4gICAgICBzZXRMYXllckRvbWFpbih7ZG9tYWlufSk7XG4gICAgfSBlbHNlIGlmIChjb2xvclNjYWxlID09PSBTQ0FMRV9UWVBFUy5vcmRpbmFsKSB7XG4gICAgICBjb25zdCBkb21haW4gPSB0aWxlRGF0YXNldC5nZXRVbmlxdWVWYWx1ZXMoZmllbGQpO1xuICAgICAgc2V0TGF5ZXJEb21haW4oe2RvbWFpbn0pO1xuICAgIH1cbiAgfSwgNTAwKTtcblxuICByZXNldENvbG9yRG9tYWluKCk6IHZvaWQge1xuICAgIGNvbnN0IHtkYXRhc2V0SWQsIGRhdGFzZXRzfSA9IHRoaXMubWV0YTtcbiAgICB0aGlzLnVwZGF0ZUxheWVyVmlzdWFsQ2hhbm5lbChkYXRhc2V0cz8uW2RhdGFzZXRJZCB8fCAnJ10sICdjb2xvcicpO1xuICAgIHRoaXMuc2V0TGF5ZXJEb21haW4/Lih7ZG9tYWluOiB0aGlzLmNvbmZpZy5jb2xvckRvbWFpbn0pO1xuICB9XG5cbiAgdXBkYXRlTGF5ZXJDb25maWcoXG4gICAgbmV3Q29uZmlnOiBQYXJ0aWFsPExheWVyQmFzZUNvbmZpZz4gJiBQYXJ0aWFsPExheWVyQ29sb3JDb25maWc+XG4gICk6IEFic3RyYWN0VGlsZUxheWVyPFQsIEk+IHtcbiAgICAvLyBXaGVuIHRoZSBkeW5hbWljIGNvbG9yIHNldHRpbmcgY2hhbmdlcywgd2UgbmVlZCB0byByZWNhbGN1bGF0ZSB0aGUgbGF5ZXIgZG9tYWluXG4gICAgY29uc3Qgb2xkID0gdGhpcy5jb25maWcudmlzQ29uZmlnLmR5bmFtaWNDb2xvciA/PyBmYWxzZTtcbiAgICBjb25zdCBuZXh0ID0gbmV3Q29uZmlnLnZpc0NvbmZpZz8uZHluYW1pY0NvbG9yID8/IG9sZDtcbiAgICBjb25zdCBzY2FsZVR5cGVDaGFuZ2VkID1cbiAgICAgIG5ld0NvbmZpZy5jb2xvclNjYWxlICYmIHRoaXMuY29uZmlnLmNvbG9yU2NhbGUgIT09IG5ld0NvbmZpZy5jb2xvclNjYWxlO1xuXG4gICAgc3VwZXIudXBkYXRlTGF5ZXJDb25maWcobmV3Q29uZmlnKTtcbiAgICBjb25zdCB7Y29sb3JGaWVsZH0gPSB0aGlzLmNvbmZpZztcblxuICAgIGlmIChjb2xvckZpZWxkKSB7XG4gICAgICAvLyBXaGVuIHdlIHN3aXRjaCBmcm9tIGR5bmFtaWMgdG8gbm9uLWR5bmFtaWMgb3IgdmljZSB2ZXJzYSwgd2UgbmVlZCB0byB1cGRhdGVcbiAgICAgIC8vIHRoZSBjb2xvciBkb21haW4uIFRoaXMgaXMgZG93bnN0cmVhbSBmcm9tIGEgZGlzcGF0Y2ggY2FsbCwgc28gd2UgdXNlXG4gICAgICAvLyBzZXRUaW1lb3V0IHRvIGF2b2lkIFwicmVkdWNlcnMgbWF5IG5vdCBkaXNwYXRjaCBhY3Rpb25zXCIgZXJyb3JzXG4gICAgICBpZiAobmV4dCAmJiAoIW9sZCB8fCBzY2FsZVR5cGVDaGFuZ2VkKSkge1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuc2V0RHluYW1pY0NvbG9yRG9tYWluKCksIDApO1xuICAgICAgfSBlbHNlIGlmIChvbGQgJiYgIW5leHQpIHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLnJlc2V0Q29sb3JEb21haW4oKSwgMCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBnZXQgYW5pbWF0aW9uRG9tYWluKCk6IFtudW1iZXIsIG51bWJlcl0gfCBudWxsIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuYW5pbWF0aW9uLmRvbWFpbjtcbiAgfVxuXG4gIHNldEluaXRpYWxMYXllckNvbmZpZyhkYXRhc2V0OiBLZXBsZXJEYXRhc2V0KTogQWJzdHJhY3RUaWxlTGF5ZXI8VCwgST4ge1xuICAgIGNvbnN0IGRlZmF1bHRDb2xvckZpZWxkID0gZmluZERlZmF1bHRDb2xvckZpZWxkKGRhdGFzZXQpO1xuXG4gICAgaWYgKGRlZmF1bHRDb2xvckZpZWxkKSB7XG4gICAgICB0aGlzLnVwZGF0ZUxheWVyQ29uZmlnKHtcbiAgICAgICAgY29sb3JGaWVsZDogZGVmYXVsdENvbG9yRmllbGRcbiAgICAgIH0pO1xuICAgICAgdGhpcy51cGRhdGVMYXllclZpc3VhbENoYW5uZWwoZGF0YXNldCwgJ2NvbG9yJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBnZXREZWZhdWx0TGF5ZXJDb25maWcoXG4gICAgcHJvcHM6IExheWVyQmFzZUNvbmZpZ1BhcnRpYWxcbiAgKTogTGF5ZXJCYXNlQ29uZmlnICYgUGFydGlhbDxMYXllckNvbG9yQ29uZmlnICYgTGF5ZXJIZWlnaHRDb25maWc+IHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uc3VwZXIuZ2V0RGVmYXVsdExheWVyQ29uZmlnKHByb3BzKSxcbiAgICAgIGNvbG9yU2NhbGU6IFNDQUxFX1RZUEVTLnF1YW50aXplLFxuXG4gICAgICAvLyBhZGQgaGVpZ2h0IHZpc3VhbCBjaGFubmVsXG4gICAgICBoZWlnaHRGaWVsZDogbnVsbCxcbiAgICAgIGhlaWdodERvbWFpbjogWzAsIDFdLFxuICAgICAgaGVpZ2h0U2NhbGU6ICdsaW5lYXInXG4gICAgfTtcbiAgfVxuXG4gIC8vIFdlIGNhbiByZW5kZXIgd2l0aG91dCBjb2x1bW5zLCBzbyB3ZSByZWRlZmluZSB0aGlzIG1ldGhvZFxuICBzaG91bGRSZW5kZXJMYXllcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gQm9vbGVhbih0aGlzLnR5cGUgJiYgdGhpcy5jb25maWcuaXNWaXNpYmxlKTtcbiAgfVxuXG4gIHVwZGF0ZUFuaW1hdGlvbkRvbWFpbkJ5RmllbGQoY2hhbm5lbDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgZmllbGQgPSB0aGlzLmNvbmZpZ1t0aGlzLnZpc3VhbENoYW5uZWxzW2NoYW5uZWxdLmZpZWxkXTtcblxuICAgIGlmIChpc0luZGV4ZWRGaWVsZChmaWVsZCkgJiYgZmllbGQuaW5kZXhCeS50eXBlID09PSBBTExfRklFTERfVFlQRVMudGltZXN0YW1wKSB7XG4gICAgICBjb25zdCB7dGltZURvbWFpbn0gPSBmaWVsZC5pbmRleEJ5O1xuXG4gICAgICB0aGlzLnVwZGF0ZUxheWVyQ29uZmlnKHtcbiAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgLi4udGltZURvbWFpbixcbiAgICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICAgIHN0YXJ0VGltZTogdGltZURvbWFpbi5kb21haW5bMF1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgdXBkYXRlQW5pbWF0aW9uRG9tYWluKGRvbWFpbjogW251bWJlciwgbnVtYmVyXSB8IG51bGwgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICB0aGlzLnVwZGF0ZUxheWVyQ29uZmlnKHtcbiAgICAgIGFuaW1hdGlvbjoge1xuICAgICAgICAuLi50aGlzLmNvbmZpZy5hbmltYXRpb24sXG4gICAgICAgIGRvbWFpblxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlTGF5ZXJEb21haW4oZGF0YXNldHM6IEtlcGxlckRhdGFzZXRzLCBuZXdGaWx0ZXI/OiBGaWx0ZXIpOiBBYnN0cmFjdFRpbGVMYXllcjxULCBJPiB7XG4gICAgc3VwZXIudXBkYXRlTGF5ZXJEb21haW4oZGF0YXNldHMsIG5ld0ZpbHRlcik7XG4gICAgaWYgKG5ld0ZpbHRlcikge1xuICAgICAgLy8gaW52YWxpZGF0ZSBjYWNoZWRWaXNpYmxlRGF0YXNldCB3aGVuIGUuZy4gY2hhbmdpbmcgZmlsdGVyc1xuICAgICAgdGhpcy50aWxlRGF0YXNldC5pbnZhbGlkYXRlQ2FjaGUoKTtcbiAgICB9XG4gICAgT2JqZWN0LmtleXModGhpcy52aXN1YWxDaGFubmVscykuZm9yRWFjaChjaGFubmVsID0+IHtcbiAgICAgIHRoaXMudXBkYXRlQW5pbWF0aW9uRG9tYWluQnlGaWVsZChjaGFubmVsKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHVwZGF0ZUxheWVyVmlzdWFsQ2hhbm5lbChkYXRhc2V0OiBLZXBsZXJEYXRhc2V0LCBjaGFubmVsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBzdXBlci51cGRhdGVMYXllclZpc3VhbENoYW5uZWwoZGF0YXNldCwgY2hhbm5lbCk7XG5cbiAgICAvLyBjcmVhdGUgYW5pbWF0aW9uIGlmIGZpZWxkIGlzIGluZGV4ZWQgYnkgdGltZVxuICAgIHRoaXMudXBkYXRlQW5pbWF0aW9uRG9tYWluQnlGaWVsZChjaGFubmVsKTtcbiAgfVxuXG4gIGZvcm1hdExheWVyRGF0YShcbiAgICBkYXRhc2V0czogS2VwbGVyRGF0YXNldHMsXG4gICAgb2xkTGF5ZXJEYXRhOiB1bmtub3duLFxuICAgIGFuaW1hdGlvbkNvbmZpZzogQW5pbWF0aW9uQ29uZmlnXG4gICk6IExheWVyRGF0YSB7XG4gICAgY29uc3Qge2RhdGFJZH0gPSB0aGlzLmNvbmZpZztcbiAgICBpZiAoIW5vdE51bGxvclVuZGVmaW5lZChkYXRhSWQpKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuICAgIGNvbnN0IGRhdGFzZXQgPSBkYXRhc2V0c1tkYXRhSWRdO1xuXG4gICAgY29uc3QgZGF0YVVwZGF0ZVRyaWdnZXJzID0gdGhpcy5nZXREYXRhVXBkYXRlVHJpZ2dlcnMoZGF0YXNldCk7XG4gICAgY29uc3QgdHJpZ2dlckNoYW5nZWQgPSB0aGlzLmdldENoYW5nZWRUcmlnZ2VycyhkYXRhVXBkYXRlVHJpZ2dlcnMpO1xuXG4gICAgaWYgKHRyaWdnZXJDaGFuZ2VkICYmIHRyaWdnZXJDaGFuZ2VkLmdldE1ldGEpIHtcbiAgICAgIHRoaXMudXBkYXRlTGF5ZXJNZXRhKGRhdGFzZXQsIGRhdGFzZXRzKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbmRleEtleSA9IHRoaXMuY29uZmlnLmFuaW1hdGlvbi5lbmFibGVkID8gYW5pbWF0aW9uQ29uZmlnLmN1cnJlbnRUaW1lIDogbnVsbDtcbiAgICBjb25zdCBhY2Nlc3NvcnMgPSB0aGlzLmdldEF0dHJpYnV0ZUFjY2Vzc29ycyh7XG4gICAgICBkYXRhQWNjZXNzb3I6ICgpID0+IGQgPT4gZCxcbiAgICAgIGRhdGFDb250YWluZXI6IGRhdGFzZXQuZGF0YUNvbnRhaW5lcixcbiAgICAgIGluZGV4S2V5XG4gICAgfSk7XG5cbiAgICBjb25zdCBtZXRhZGF0YSA9IGRhdGFzZXQ/Lm1ldGFkYXRhIGFzIExheWVyRGF0YSB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBtZXRhZGF0YVRvRGF0YSA9IG1ldGFkYXRhXG4gICAgICA/IHtcbiAgICAgICAgICBtaW5ab29tOiBtZXRhZGF0YS5taW5ab29tLFxuICAgICAgICAgIG1heFpvb206IG1ldGFkYXRhLm1heFpvb20sXG4gICAgICAgICAgYm91bmRzOiBtZXRhZGF0YS5ib3VuZHNcbiAgICAgICAgfVxuICAgICAgOiB7fTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5tZXRhZGF0YVRvRGF0YSxcbiAgICAgIC4uLmFjY2Vzc29yc1xuICAgIH07XG4gIH1cblxuICBnZXRHcHVGaWx0ZXJWYWx1ZUFjY2Vzc29yKHtncHVGaWx0ZXIsIGFuaW1hdGlvbkNvbmZpZ306IExheWVyT3B0cyk6IGFueSB7XG4gICAgY29uc3QgaW5kZXhLZXkgPSB0aGlzLmNvbmZpZy5hbmltYXRpb24uZW5hYmxlZCA/IGFuaW1hdGlvbkNvbmZpZy5jdXJyZW50VGltZSA6IG51bGw7XG4gICAgY29uc3QgdmFsdWVBY2Nlc3NvciA9IChkYXRhQ29udGFpbmVyOiBEYXRhQ29udGFpbmVySW50ZXJmYWNlLCBkKSA9PiBmaWVsZCA9PlxuICAgICAgdGhpcy5hY2Nlc3NWU0ZpZWxkVmFsdWUoZmllbGQsIGluZGV4S2V5KShmaWVsZCwgZCk7XG4gICAgcmV0dXJuIGdwdUZpbHRlci5maWx0ZXJWYWx1ZUFjY2Vzc29yKG51bGwgYXMgYW55KSh1bmRlZmluZWQsIHZhbHVlQWNjZXNzb3IpO1xuICB9XG59XG4iXSwi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