kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
396 lines (394 loc) • 68.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.LayerColorLegendFactory = LayerColorLegendFactory;
exports.LayerDefaultLegend = void 0;
exports.LayerLegendContentFactory = LayerLegendContentFactory;
exports.LayerLegendHeaderFactory = LayerLegendHeaderFactory;
exports.LayerRadiusLegend = void 0;
exports.SingleColorLegendFactory = SingleColorLegendFactory;
exports["default"] = exports.VisualChannelMetric = exports.StyledMapControlLegend = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
var _react = _interopRequireWildcard(require("react"));
var _styledComponents = _interopRequireDefault(require("styled-components"));
var _d3Color = require("d3-color");
var _d3Format = require("d3-format");
var _reactIntl = require("react-intl");
var _colorLegend = _interopRequireWildcard(require("../common/color-legend"));
var _radiusLegend = _interopRequireDefault(require("../common/radius-legend"));
var _constants = require("@kepler.gl/constants");
var _localization = require("@kepler.gl/localization");
var _viewportMercatorProject = require("viewport-mercator-project");
var _icons = require("../common/icons");
var _panelHeaderAction = _interopRequireDefault(require("../side-panel/panel-header-action"));
var _templateObject, _templateObject2, _templateObject3; // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
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; }
var StyledMapControlLegend = exports.StyledMapControlLegend = _styledComponents["default"].div(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2["default"])(["\n padding: 10px ", "px 10px\n ", "px;\n font-size: 11px;\n font-family: ", ";\n border-bottom-color: ", ";\n border-bottom-style: solid;\n border-bottom-width: ", ";\n width: ", "px;\n box-sizing: border-box;\n\n .legend--layer_name {\n font-size: 12px;\n padding-right: ", "px;\n color: ", ";\n font-weight: 500;\n }\n .legend--layer_type {\n color: ", ";\n font-weight: 500;\n font-size: 11px;\n padding-right: ", "px;\n }\n\n .legend--layer_size-title-row {\n display: flex;\n margin-top: 4px;\n padding-right: ", "px;\n align-items: center;\n }\n\n .legend--layer__title {\n }\n\n .legend--layer__item {\n padding-bottom: 4px;\n }\n .legend--layer_by {\n color: ", ";\n margin-top: 4px;\n }\n\n .legend--layer_color_field {\n color: ", ";\n font-weight: 500;\n }\n\n .legend--layer_color-legend {\n margin-top: 6px;\n }\n"])), function (props) {
return props.theme.mapControl.padding;
}, function (props) {
return props.theme.mapControl.padding;
}, function (props) {
return props.theme.fontFamily;
}, function (props) {
return props.theme.panelBorderColor;
}, function (props) {
return props.last ? 0 : '1px';
}, function (props) {
return props.width;
}, function (props) {
return props.theme.mapControl.padding;
}, function (props) {
return props.theme.textColor;
}, function (props) {
return props.theme.subtextColor;
}, function (props) {
return props.theme.mapControl.padding;
}, function (props) {
return props.theme.mapControl.padding;
}, function (props) {
return props.theme.subtextColor;
}, function (props) {
return props.theme.textColorHl;
});
var StyledLegendHeaderRow = _styledComponents["default"].div(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2["default"])(["\n display: flex;\n align-items: center;\n justify-content: space-between;\n"])));
var StyledVisibilityToggle = _styledComponents["default"].div(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2["default"])(["\n cursor: pointer;\n color: ", ";\n display: flex;\n align-items: center;\n margin-left: 8px;\n opacity: ", ";\n\n &:hover {\n color: ", ";\n opacity: 1;\n }\n"])), function (props) {
return props.isVisible ? props.theme.textColor : props.theme.subtextColor;
}, function (props) {
return props.isVisible ? 1 : 0.5;
}, function (props) {
return props.theme.textColorHl;
});
var VisualChannelMetric = exports.VisualChannelMetric = function VisualChannelMetric(_ref) {
var name = _ref.name;
return /*#__PURE__*/_react["default"].createElement("div", {
className: "legend--layer__title"
}, /*#__PURE__*/_react["default"].createElement("span", {
className: "legend--layer_color_field"
}, /*#__PURE__*/_react["default"].createElement(_localization.FormattedMessage, {
id: name
})));
};
var LayerDefaultLegend = exports.LayerDefaultLegend = function LayerDefaultLegend(_ref2) {
var label = _ref2.label,
name = _ref2.name;
return label ? /*#__PURE__*/_react["default"].createElement("div", {
className: "legend--layer_size-schema"
}, /*#__PURE__*/_react["default"].createElement("p", null, /*#__PURE__*/_react["default"].createElement("span", {
className: "legend--layer_by"
}, label ? /*#__PURE__*/_react["default"].createElement(_localization.FormattedMessage, {
id: label
}) : null), /*#__PURE__*/_react["default"].createElement("span", {
className: "legend--layer_by"
}, " by ")), name && /*#__PURE__*/_react["default"].createElement(VisualChannelMetric, {
name: name
})) : null;
};
SingleColorLegendFactory.deps = [_colorLegend.LegendRowFactory];
function SingleColorLegendFactory(LegendRow) {
var SingleColorLegend = function SingleColorLegend(_ref3) {
var color = _ref3.color,
label = _ref3.label;
return /*#__PURE__*/_react["default"].createElement(LegendRow, {
label: label !== null && label !== void 0 ? label : '',
displayLabel: Boolean(label),
color: Array.isArray(color) ? _d3Color.rgb.apply(void 0, (0, _toConsumableArray2["default"])(color)).toString() : color
});
};
SingleColorLegend.displayName = 'SingleColorLegend';
return /*#__PURE__*/_react["default"].memo(SingleColorLegend);
}
LayerColorLegendFactory.deps = [_colorLegend["default"], SingleColorLegendFactory, _panelHeaderAction["default"]];
function LayerColorLegendFactory(ColorLegend, SingleColorLegend, PanelHeaderAction) {
var LayerColorLegend = function LayerColorLegend(_ref4) {
var description = _ref4.description,
config = _ref4.config,
layer = _ref4.layer,
colorChannel = _ref4.colorChannel,
disableEdit = _ref4.disableEdit,
onLayerVisConfigChange = _ref4.onLayerVisConfigChange,
isExport = _ref4.isExport,
mapState = _ref4.mapState,
actionIcons = _ref4.actionIcons;
var intl = (0, _reactIntl.useIntl)();
var enableColorBy = description.measure;
var scale = colorChannel.scale,
field = colorChannel.field,
domain = colorChannel.domain,
range = colorChannel.range,
property = colorChannel.property,
fixed = colorChannel.fixed;
var _map = [scale, field, domain].map(function (k) {
return config[k];
}),
_map2 = (0, _slicedToArray2["default"])(_map, 3),
colorScale = _map2[0],
colorField = _map2[1],
colorDomain = _map2[2];
var isFixed = fixed && config.visConfig[fixed];
var colorRange = config.visConfig[range];
var onUpdateColorLegend = (0, _react.useCallback)(function (colorLegends) {
if (onLayerVisConfigChange) {
onLayerVisConfigChange(layer, (0, _defineProperty2["default"])({}, range, _objectSpread(_objectSpread({}, colorRange), {}, {
colorLegends: colorLegends
})));
}
}, [layer, onLayerVisConfigChange, colorRange, range]);
var _useState = (0, _react.useState)(isExport),
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
isExpanded = _useState2[0],
setIsExpanded = _useState2[1];
var handleToggleExpanded = function handleToggleExpanded() {
return setIsExpanded(!isExpanded);
};
return /*#__PURE__*/_react["default"].createElement("div", {
className: "legend--layer__item"
}, /*#__PURE__*/_react["default"].createElement("div", {
className: "legend--layer_color-schema"
}, /*#__PURE__*/_react["default"].createElement("div", null, enableColorBy ? /*#__PURE__*/_react["default"].createElement("div", {
className: "legend--layer_size-title-row"
}, /*#__PURE__*/_react["default"].createElement(VisualChannelMetric, {
name: enableColorBy
}), !isExport ? /*#__PURE__*/_react["default"].createElement(PanelHeaderAction, {
id: "legend-collapse-button",
onClick: handleToggleExpanded,
IconComponent: isExpanded ? actionIcons.expanded : actionIcons.collapsed
}) : null) : null, /*#__PURE__*/_react["default"].createElement("div", {
className: "legend--layer_color-legend"
}, enableColorBy ? /*#__PURE__*/_react["default"].createElement(ColorLegend, {
layer: layer,
isExpanded: isExpanded,
scaleType: colorScale,
displayLabel: true,
domain: colorDomain,
fieldType: colorField && colorField.type || 'real',
range: colorRange,
onUpdateColorLegend: onUpdateColorLegend,
disableEdit: disableEdit || Boolean(isExport),
isFixed: isFixed,
mapState: mapState,
labelFormat: colorField !== null && colorField !== void 0 && colorField.displayFormat ? (0, _d3Format.format)(colorField === null || colorField === void 0 ? void 0 : colorField.displayFormat) : null
}) : /*#__PURE__*/_react["default"].createElement(SingleColorLegend, {
color: config.visConfig[property] || config[property] || config.color,
label: intl.formatMessage({
id: "mapLegend.layers.".concat(layer.type, ".singleColor.").concat(colorChannel.key),
defaultMessage: intl.formatMessage({
id: "mapLegend.layers.default.singleColor.".concat(colorChannel.key),
defaultMessage: ' ' // mustn't be empty string or id will be used
})
})
})))));
};
LayerColorLegend.displayName = 'LayerColorLegend';
return /*#__PURE__*/_react["default"].memo(LayerColorLegend);
}
function getLayerRadiusScaleMetersToPixelsMultiplier(layer, mapState) {
// @ts-ignore this actually exist
var _getDistanceScales = (0, _viewportMercatorProject.getDistanceScales)(mapState),
metersPerPixel = _getDistanceScales.metersPerPixel;
// if no field size is defined we need to pass fixed radius = false
var fixedRadius = layer.config.visConfig.fixedRadius && Boolean(layer.config.sizeField);
return layer.getRadiusScaleByZoom(mapState, fixedRadius) / metersPerPixel[0];
}
var LayerRadiusLegend = exports.LayerRadiusLegend = /*#__PURE__*/_react["default"].memo(function (_ref5) {
var layer = _ref5.layer,
width = _ref5.width,
visualChannel = _ref5.visualChannel,
mapState = _ref5.mapState;
var description = layer.getVisualChannelDescription(visualChannel.key);
var config = layer.config;
var enableSizeBy = description.measure;
var scale = visualChannel.scale,
field = visualChannel.field,
domain = visualChannel.domain,
range = visualChannel.range;
var _map3 = [scale, field, domain].map(function (k) {
return config[k];
}),
_map4 = (0, _slicedToArray2["default"])(_map3, 3),
sizeScale = _map4[0],
sizeField = _map4[1],
sizeDomain = _map4[2];
var sizeRange = config.visConfig[range];
if (mapState) {
var radiusMultiplier = getLayerRadiusScaleMetersToPixelsMultiplier(layer, mapState);
sizeRange = sizeRange.map(function (v) {
return v * radiusMultiplier;
});
}
return /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement("div", {
className: "legend--layer_size-schema"
}, /*#__PURE__*/_react["default"].createElement("div", null, enableSizeBy ? /*#__PURE__*/_react["default"].createElement(VisualChannelMetric, {
name: enableSizeBy
}) : null, /*#__PURE__*/_react["default"].createElement("div", {
className: "legend--layer_size-legend"
}, enableSizeBy ? /*#__PURE__*/_react["default"].createElement(_radiusLegend["default"], {
scaleType: sizeScale,
domain: sizeDomain,
fieldType: sizeField && sizeField.type || 'real',
range: sizeRange,
width: width
}) : null))));
});
var isColorChannel = function isColorChannel(visualChannel) {
return [_constants.CHANNEL_SCALES.color, _constants.CHANNEL_SCALES.colorAggr].includes(visualChannel.channelScaleType);
};
var isRadiusChannel = function isRadiusChannel(visualChannel) {
return [_constants.CHANNEL_SCALES.radius].includes(visualChannel.channelScaleType);
};
function LayerLegendHeaderFactory() {
var LayerLegendHeader = function LayerLegendHeader(_ref6) {
var options = _ref6.options,
layer = _ref6.layer,
onToggleLayerVisibility = _ref6.onToggleLayerVisibility;
var isVisible = layer.config.isVisible;
var onToggle = (0, _react.useCallback)(function () {
if (onToggleLayerVisibility) {
onToggleLayerVisibility(layer);
}
}, [layer, onToggleLayerVisibility]);
if ((options === null || options === void 0 ? void 0 : options.showLayerName) === false) {
return null;
}
return /*#__PURE__*/_react["default"].createElement(StyledLegendHeaderRow, null, /*#__PURE__*/_react["default"].createElement("div", {
className: "legend--layer_name",
style: {
opacity: isVisible ? 1 : 0.5
}
}, layer.config.label), onToggleLayerVisibility ? /*#__PURE__*/_react["default"].createElement(StyledVisibilityToggle, {
isVisible: isVisible,
onClick: onToggle
}, isVisible ? /*#__PURE__*/_react["default"].createElement(_icons.EyeSeen, {
height: "12px"
}) : /*#__PURE__*/_react["default"].createElement(_icons.EyeUnseen, {
height: "12px"
})) : null);
};
return LayerLegendHeader;
}
var defaultActionIcons = {
expanded: _icons.ArrowDown,
collapsed: _icons.ArrowRight
};
LayerLegendContentFactory.deps = [LayerColorLegendFactory];
function LayerLegendContentFactory(LayerColorLegend) {
var LayerLegendContent = function LayerLegendContent(_ref7) {
var layer = _ref7.layer,
containerW = _ref7.containerW,
mapState = _ref7.mapState,
disableEdit = _ref7.disableEdit,
isExport = _ref7.isExport,
onLayerVisConfigChange = _ref7.onLayerVisConfigChange,
actionIcons = _ref7.actionIcons;
var visualChannels = layer.getLegendVisualChannels();
var channelKeys = Object.values(visualChannels);
var colorChannels = channelKeys.filter(isColorChannel);
var nonColorChannels = channelKeys.filter(function (vc) {
return !isColorChannel(vc);
});
var width = containerW - 2 * _constants.DIMENSIONS.mapControl.padding;
// render color by chanel only
var colorChannelToRender = colorChannels.filter(function (cc) {
var _layer$getVisualChann;
return (!cc.condition || cc.condition(layer.config)) && ((_layer$getVisualChann = layer.getVisualChannelDescription(cc.key)) === null || _layer$getVisualChann === void 0 ? void 0 : _layer$getVisualChann.measure);
});
// if no color by chanel, render rest
if (!colorChannelToRender.length) {
colorChannelToRender = colorChannels.filter(function (cc) {
return !cc.condition || cc.condition(layer.config);
});
}
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, colorChannelToRender.map(function (colorChannel) {
return /*#__PURE__*/_react["default"].createElement(LayerColorLegend, {
key: colorChannel.key,
colorChannel: colorChannel,
config: layer.config,
description: layer.getVisualChannelDescription(colorChannel.key),
layer: layer,
isExport: isExport,
disableEdit: disableEdit,
mapState: mapState,
onLayerVisConfigChange: onLayerVisConfigChange,
actionIcons: actionIcons
});
}), nonColorChannels.map(function (visualChannel) {
var matchCondition = !visualChannel.condition || visualChannel.condition(layer.config);
var enabled = layer.config[visualChannel.field] || visualChannel.defaultMeasure;
if (matchCondition && enabled) {
var description = layer.getVisualChannelDescription(visualChannel.key);
if (isRadiusChannel(visualChannel)) {
return /*#__PURE__*/_react["default"].createElement(LayerRadiusLegend, {
key: visualChannel.key,
layer: layer,
mapState: mapState,
width: width,
visualChannel: visualChannel
});
}
return /*#__PURE__*/_react["default"].createElement(LayerDefaultLegend, {
key: visualChannel.key,
label: description.label,
name: description.measure
});
}
return null;
}));
};
return LayerLegendContent;
}
MapLegendFactory.deps = [LayerLegendHeaderFactory, LayerLegendContentFactory];
function MapLegendFactory(LayerLegendHeader, LayerLegendContent) {
var MapLegend = function MapLegend(_ref8) {
var _ref8$layers = _ref8.layers,
layers = _ref8$layers === void 0 ? [] : _ref8$layers,
width = _ref8.width,
mapState = _ref8.mapState,
options = _ref8.options,
disableEdit = _ref8.disableEdit,
isExport = _ref8.isExport,
onLayerVisConfigChange = _ref8.onLayerVisConfigChange,
onToggleLayerVisibility = _ref8.onToggleLayerVisibility,
_ref8$actionIcons = _ref8.actionIcons,
actionIcons = _ref8$actionIcons === void 0 ? defaultActionIcons : _ref8$actionIcons;
return /*#__PURE__*/_react["default"].createElement("div", {
className: "map-legend"
}, layers.map(function (layer, index) {
if (!layer.isValidToSave() || layer.config.hidden) {
return null;
}
var containerW = width || _constants.DIMENSIONS.mapControl.width;
return /*#__PURE__*/_react["default"].createElement(StyledMapControlLegend, {
className: "legend--layer",
last: index === layers.length - 1,
key: index,
width: containerW
}, /*#__PURE__*/_react["default"].createElement(LayerLegendHeader, {
isExport: isExport,
options: options,
layer: layer,
onToggleLayerVisibility: onToggleLayerVisibility
}), /*#__PURE__*/_react["default"].createElement(LayerLegendContent, {
containerW: containerW,
layer: layer,
mapState: mapState,
disableEdit: disableEdit,
isExport: isExport,
onLayerVisConfigChange: onLayerVisConfigChange,
actionIcons: actionIcons
}));
}));
};
MapLegend.displayName = 'MapLegend';
return MapLegend;
}
var _default = exports["default"] = MapLegendFactory;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfc3R5bGVkQ29tcG9uZW50cyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfZDNDb2xvciIsIl9kM0Zvcm1hdCIsIl9yZWFjdEludGwiLCJfY29sb3JMZWdlbmQiLCJfcmFkaXVzTGVnZW5kIiwiX2NvbnN0YW50cyIsIl9sb2NhbGl6YXRpb24iLCJfdmlld3BvcnRNZXJjYXRvclByb2plY3QiLCJfaWNvbnMiLCJfcGFuZWxIZWFkZXJBY3Rpb24iLCJfdGVtcGxhdGVPYmplY3QiLCJfdGVtcGxhdGVPYmplY3QyIiwiX3RlbXBsYXRlT2JqZWN0MyIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiX3R5cGVvZiIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIm93bktleXMiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsIlN0eWxlZE1hcENvbnRyb2xMZWdlbmQiLCJleHBvcnRzIiwic3R5bGVkIiwiZGl2IiwiX3RhZ2dlZFRlbXBsYXRlTGl0ZXJhbDIiLCJwcm9wcyIsInRoZW1lIiwibWFwQ29udHJvbCIsInBhZGRpbmciLCJmb250RmFtaWx5IiwicGFuZWxCb3JkZXJDb2xvciIsImxhc3QiLCJ3aWR0aCIsInRleHRDb2xvciIsInN1YnRleHRDb2xvciIsInRleHRDb2xvckhsIiwiU3R5bGVkTGVnZW5kSGVhZGVyUm93IiwiU3R5bGVkVmlzaWJpbGl0eVRvZ2dsZSIsImlzVmlzaWJsZSIsIlZpc3VhbENoYW5uZWxNZXRyaWMiLCJfcmVmIiwibmFtZSIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc05hbWUiLCJGb3JtYXR0ZWRNZXNzYWdlIiwiaWQiLCJMYXllckRlZmF1bHRMZWdlbmQiLCJfcmVmMiIsImxhYmVsIiwiU2luZ2xlQ29sb3JMZWdlbmRGYWN0b3J5IiwiZGVwcyIsIkxlZ2VuZFJvd0ZhY3RvcnkiLCJMZWdlbmRSb3ciLCJTaW5nbGVDb2xvckxlZ2VuZCIsIl9yZWYzIiwiY29sb3IiLCJkaXNwbGF5TGFiZWwiLCJCb29sZWFuIiwiQXJyYXkiLCJpc0FycmF5IiwicmdiIiwiX3RvQ29uc3VtYWJsZUFycmF5MiIsInRvU3RyaW5nIiwiZGlzcGxheU5hbWUiLCJSZWFjdCIsIm1lbW8iLCJMYXllckNvbG9yTGVnZW5kRmFjdG9yeSIsIkNvbG9yTGVnZW5kRmFjdG9yeSIsIlBhbmVsSGVhZGVyQWN0aW9uRmFjdG9yeSIsIkNvbG9yTGVnZW5kIiwiUGFuZWxIZWFkZXJBY3Rpb24iLCJMYXllckNvbG9yTGVnZW5kIiwiX3JlZjQiLCJkZXNjcmlwdGlvbiIsImNvbmZpZyIsImxheWVyIiwiY29sb3JDaGFubmVsIiwiZGlzYWJsZUVkaXQiLCJvbkxheWVyVmlzQ29uZmlnQ2hhbmdlIiwiaXNFeHBvcnQiLCJtYXBTdGF0ZSIsImFjdGlvbkljb25zIiwiaW50bCIsInVzZUludGwiLCJlbmFibGVDb2xvckJ5IiwibWVhc3VyZSIsInNjYWxlIiwiZmllbGQiLCJkb21haW4iLCJyYW5nZSIsInByb3BlcnR5IiwiZml4ZWQiLCJfbWFwIiwibWFwIiwiayIsIl9tYXAyIiwiX3NsaWNlZFRvQXJyYXkyIiwiY29sb3JTY2FsZSIsImNvbG9yRmllbGQiLCJjb2xvckRvbWFpbiIsImlzRml4ZWQiLCJ2aXNDb25maWciLCJjb2xvclJhbmdlIiwib25VcGRhdGVDb2xvckxlZ2VuZCIsInVzZUNhbGxiYWNrIiwiY29sb3JMZWdlbmRzIiwiX3VzZVN0YXRlIiwidXNlU3RhdGUiLCJfdXNlU3RhdGUyIiwiaXNFeHBhbmRlZCIsInNldElzRXhwYW5kZWQiLCJoYW5kbGVUb2dnbGVFeHBhbmRlZCIsIm9uQ2xpY2siLCJJY29uQ29tcG9uZW50IiwiZXhwYW5kZWQiLCJjb2xsYXBzZWQiLCJzY2FsZVR5cGUiLCJmaWVsZFR5cGUiLCJ0eXBlIiwibGFiZWxGb3JtYXQiLCJkaXNwbGF5Rm9ybWF0IiwiZDNGb3JtYXQiLCJmb3JtYXRNZXNzYWdlIiwiY29uY2F0Iiwia2V5IiwiZGVmYXVsdE1lc3NhZ2UiLCJnZXRMYXllclJhZGl1c1NjYWxlTWV0ZXJzVG9QaXhlbHNNdWx0aXBsaWVyIiwiX2dldERpc3RhbmNlU2NhbGVzIiwiZ2V0RGlzdGFuY2VTY2FsZXMiLCJtZXRlcnNQZXJQaXhlbCIsImZpeGVkUmFkaXVzIiwic2l6ZUZpZWxkIiwiZ2V0UmFkaXVzU2NhbGVCeVpvb20iLCJMYXllclJhZGl1c0xlZ2VuZCIsIl9yZWY1IiwidmlzdWFsQ2hhbm5lbCIsImdldFZpc3VhbENoYW5uZWxEZXNjcmlwdGlvbiIsImVuYWJsZVNpemVCeSIsIl9tYXAzIiwiX21hcDQiLCJzaXplU2NhbGUiLCJzaXplRG9tYWluIiwic2l6ZVJhbmdlIiwicmFkaXVzTXVsdGlwbGllciIsInYiLCJpc0NvbG9yQ2hhbm5lbCIsIkNIQU5ORUxfU0NBTEVTIiwiY29sb3JBZ2dyIiwiaW5jbHVkZXMiLCJjaGFubmVsU2NhbGVUeXBlIiwiaXNSYWRpdXNDaGFubmVsIiwicmFkaXVzIiwiTGF5ZXJMZWdlbmRIZWFkZXJGYWN0b3J5IiwiTGF5ZXJMZWdlbmRIZWFkZXIiLCJfcmVmNiIsIm9wdGlvbnMiLCJvblRvZ2dsZUxheWVyVmlzaWJpbGl0eSIsIm9uVG9nZ2xlIiwic2hvd0xheWVyTmFtZSIsInN0eWxlIiwib3BhY2l0eSIsIkV5ZVNlZW4iLCJoZWlnaHQiLCJFeWVVbnNlZW4iLCJkZWZhdWx0QWN0aW9uSWNvbnMiLCJBcnJvd0Rvd24iLCJBcnJvd1JpZ2h0IiwiTGF5ZXJMZWdlbmRDb250ZW50RmFjdG9yeSIsIkxheWVyTGVnZW5kQ29udGVudCIsIl9yZWY3IiwiY29udGFpbmVyVyIsInZpc3VhbENoYW5uZWxzIiwiZ2V0TGVnZW5kVmlzdWFsQ2hhbm5lbHMiLCJjaGFubmVsS2V5cyIsInZhbHVlcyIsImNvbG9yQ2hhbm5lbHMiLCJub25Db2xvckNoYW5uZWxzIiwidmMiLCJESU1FTlNJT05TIiwiY29sb3JDaGFubmVsVG9SZW5kZXIiLCJjYyIsIl9sYXllciRnZXRWaXN1YWxDaGFubiIsImNvbmRpdGlvbiIsIkZyYWdtZW50IiwibWF0Y2hDb25kaXRpb24iLCJlbmFibGVkIiwiZGVmYXVsdE1lYXN1cmUiLCJNYXBMZWdlbmRGYWN0b3J5IiwiTWFwTGVnZW5kIiwiX3JlZjgiLCJfcmVmOCRsYXllcnMiLCJsYXllcnMiLCJfcmVmOCRhY3Rpb25JY29ucyIsImluZGV4IiwiaXNWYWxpZFRvU2F2ZSIsImhpZGRlbiIsIl9kZWZhdWx0Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL21hcC9tYXAtbGVnZW5kLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQgUmVhY3QsIHtGQywgdXNlQ2FsbGJhY2ssIHVzZVN0YXRlLCBDb21wb25lbnRUeXBlfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ3N0eWxlZC1jb21wb25lbnRzJztcbmltcG9ydCB7cmdifSBmcm9tICdkMy1jb2xvcic7XG5pbXBvcnQge2Zvcm1hdCBhcyBkM0Zvcm1hdH0gZnJvbSAnZDMtZm9ybWF0JztcbmltcG9ydCB7dXNlSW50bH0gZnJvbSAncmVhY3QtaW50bCc7XG5pbXBvcnQgQ29sb3JMZWdlbmRGYWN0b3J5LCB7TGVnZW5kUm93RmFjdG9yeX0gZnJvbSAnLi4vY29tbW9uL2NvbG9yLWxlZ2VuZCc7XG5pbXBvcnQgUmFkaXVzTGVnZW5kIGZyb20gJy4uL2NvbW1vbi9yYWRpdXMtbGVnZW5kJztcbmltcG9ydCB7Q0hBTk5FTF9TQ0FMRVMsIERJTUVOU0lPTlN9IGZyb20gJ0BrZXBsZXIuZ2wvY29uc3RhbnRzJztcbmltcG9ydCB7Rm9ybWF0dGVkTWVzc2FnZX0gZnJvbSAnQGtlcGxlci5nbC9sb2NhbGl6YXRpb24nO1xuaW1wb3J0IHtMYXllciwgTGF5ZXJCYXNlQ29uZmlnLCBWaXN1YWxDaGFubmVsLCBWaXN1YWxDaGFubmVsRGVzY3JpcHRpb259IGZyb20gJ0BrZXBsZXIuZ2wvbGF5ZXJzJztcbmltcG9ydCB7TGF5ZXJWaXNDb25maWcsIE1hcFN0YXRlLCBSR0JDb2xvcn0gZnJvbSAnQGtlcGxlci5nbC90eXBlcyc7XG5pbXBvcnQge2dldERpc3RhbmNlU2NhbGVzfSBmcm9tICd2aWV3cG9ydC1tZXJjYXRvci1wcm9qZWN0JztcbmltcG9ydCB7QXJyb3dEb3duLCBBcnJvd1JpZ2h0LCBFeWVTZWVuLCBFeWVVbnNlZW59IGZyb20gJy4uL2NvbW1vbi9pY29ucyc7XG5pbXBvcnQgUGFuZWxIZWFkZXJBY3Rpb25GYWN0b3J5IGZyb20gJy4uL3NpZGUtcGFuZWwvcGFuZWwtaGVhZGVyLWFjdGlvbic7XG5cbmludGVyZmFjZSBTdHlsZWRNYXBDb250cm9sTGVnZW5kUHJvcHMge1xuICB3aWR0aD86IG51bWJlcjtcbiAgbGFzdD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjb25zdCBTdHlsZWRNYXBDb250cm9sTGVnZW5kID0gc3R5bGVkLmRpdjxTdHlsZWRNYXBDb250cm9sTGVnZW5kUHJvcHM+YFxuICBwYWRkaW5nOiAxMHB4ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUubWFwQ29udHJvbC5wYWRkaW5nfXB4IDEwcHhcbiAgICAke3Byb3BzID0+IHByb3BzLnRoZW1lLm1hcENvbnRyb2wucGFkZGluZ31weDtcbiAgZm9udC1zaXplOiAxMXB4O1xuICBmb250LWZhbWlseTogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5mb250RmFtaWx5fTtcbiAgYm9yZGVyLWJvdHRvbS1jb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5wYW5lbEJvcmRlckNvbG9yfTtcbiAgYm9yZGVyLWJvdHRvbS1zdHlsZTogc29saWQ7XG4gIGJvcmRlci1ib3R0b20td2lkdGg6ICR7cHJvcHMgPT4gKHByb3BzLmxhc3QgPyAwIDogJzFweCcpfTtcbiAgd2lkdGg6ICR7cHJvcHMgPT4gcHJvcHMud2lkdGh9cHg7XG4gIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG5cbiAgLmxlZ2VuZC0tbGF5ZXJfbmFtZSB7XG4gICAgZm9udC1zaXplOiAxMnB4O1xuICAgIHBhZGRpbmctcmlnaHQ6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUubWFwQ29udHJvbC5wYWRkaW5nfXB4O1xuICAgIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnRleHRDb2xvcn07XG4gICAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgfVxuICAubGVnZW5kLS1sYXllcl90eXBlIHtcbiAgICBjb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5zdWJ0ZXh0Q29sb3J9O1xuICAgIGZvbnQtd2VpZ2h0OiA1MDA7XG4gICAgZm9udC1zaXplOiAxMXB4O1xuICAgIHBhZGRpbmctcmlnaHQ6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUubWFwQ29udHJvbC5wYWRkaW5nfXB4O1xuICB9XG5cbiAgLmxlZ2VuZC0tbGF5ZXJfc2l6ZS10aXRsZS1yb3cge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgbWFyZ2luLXRvcDogNHB4O1xuICAgIHBhZGRpbmctcmlnaHQ6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUubWFwQ29udHJvbC5wYWRkaW5nfXB4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIH1cblxuICAubGVnZW5kLS1sYXllcl9fdGl0bGUge1xuICB9XG5cbiAgLmxlZ2VuZC0tbGF5ZXJfX2l0ZW0ge1xuICAgIHBhZGRpbmctYm90dG9tOiA0cHg7XG4gIH1cbiAgLmxlZ2VuZC0tbGF5ZXJfYnkge1xuICAgIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnN1YnRleHRDb2xvcn07XG4gICAgbWFyZ2luLXRvcDogNHB4O1xuICB9XG5cbiAgLmxlZ2VuZC0tbGF5ZXJfY29sb3JfZmllbGQge1xuICAgIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnRleHRDb2xvckhsfTtcbiAgICBmb250LXdlaWdodDogNTAwO1xuICB9XG5cbiAgLmxlZ2VuZC0tbGF5ZXJfY29sb3ItbGVnZW5kIHtcbiAgICBtYXJnaW4tdG9wOiA2cHg7XG4gIH1cbmA7XG5cbmNvbnN0IFN0eWxlZExlZ2VuZEhlYWRlclJvdyA9IHN0eWxlZC5kaXZgXG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbmA7XG5cbmNvbnN0IFN0eWxlZFZpc2liaWxpdHlUb2dnbGUgPSBzdHlsZWQuZGl2PHtpc1Zpc2libGU6IGJvb2xlYW59PmBcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBjb2xvcjogJHtwcm9wcyA9PiAocHJvcHMuaXNWaXNpYmxlID8gcHJvcHMudGhlbWUudGV4dENvbG9yIDogcHJvcHMudGhlbWUuc3VidGV4dENvbG9yKX07XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIG1hcmdpbi1sZWZ0OiA4cHg7XG4gIG9wYWNpdHk6ICR7cHJvcHMgPT4gKHByb3BzLmlzVmlzaWJsZSA/IDEgOiAwLjUpfTtcblxuICAmOmhvdmVyIHtcbiAgICBjb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS50ZXh0Q29sb3JIbH07XG4gICAgb3BhY2l0eTogMTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IFZpc3VhbENoYW5uZWxNZXRyaWMgPSAoe25hbWV9KSA9PiB7XG4gIHJldHVybiAoXG4gICAgPGRpdiBjbGFzc05hbWU9XCJsZWdlbmQtLWxheWVyX190aXRsZVwiPlxuICAgICAgPHNwYW4gY2xhc3NOYW1lPVwibGVnZW5kLS1sYXllcl9jb2xvcl9maWVsZFwiPlxuICAgICAgICA8Rm9ybWF0dGVkTWVzc2FnZSBpZD17bmFtZX0gLz5cbiAgICAgIDwvc3Bhbj5cbiAgICA8L2Rpdj5cbiAgKTtcbn07XG5cbmV4cG9ydCB0eXBlIExheWVyU2l6ZUxlZ2VuZFByb3BzID0ge1xuICBsYWJlbDogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG59O1xuXG5leHBvcnQgY29uc3QgTGF5ZXJEZWZhdWx0TGVnZW5kOiBSZWFjdC5GQzxMYXllclNpemVMZWdlbmRQcm9wcz4gPSAoe2xhYmVsLCBuYW1lfSkgPT5cbiAgbGFiZWwgPyAoXG4gICAgPGRpdiBjbGFzc05hbWU9XCJsZWdlbmQtLWxheWVyX3NpemUtc2NoZW1hXCI+XG4gICAgICA8cD5cbiAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwibGVnZW5kLS1sYXllcl9ieVwiPntsYWJlbCA/IDxGb3JtYXR0ZWRNZXNzYWdlIGlkPXtsYWJlbH0gLz4gOiBudWxsfTwvc3Bhbj5cbiAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwibGVnZW5kLS1sYXllcl9ieVwiPiBieSA8L3NwYW4+XG4gICAgICA8L3A+XG4gICAgICB7bmFtZSAmJiA8VmlzdWFsQ2hhbm5lbE1ldHJpYyBuYW1lPXtuYW1lfSAvPn1cbiAgICA8L2Rpdj5cbiAgKSA6IG51bGw7XG5cbmV4cG9ydCB0eXBlIFNpbmdsZUNvbG9yTGVnZW5kUHJvcHMgPSB7XG4gIGNvbG9yOiBSR0JDb2xvcjtcbiAgbGFiZWw/OiBzdHJpbmc7XG59O1xuXG5TaW5nbGVDb2xvckxlZ2VuZEZhY3RvcnkuZGVwcyA9IFtMZWdlbmRSb3dGYWN0b3J5XTtcblxuZXhwb3J0IGZ1bmN0aW9uIFNpbmdsZUNvbG9yTGVnZW5kRmFjdG9yeShMZWdlbmRSb3c6IFJldHVyblR5cGU8dHlwZW9mIExlZ2VuZFJvd0ZhY3Rvcnk+KSB7XG4gIGNvbnN0IFNpbmdsZUNvbG9yTGVnZW5kOiBSZWFjdC5GQzxTaW5nbGVDb2xvckxlZ2VuZFByb3BzPiA9ICh7Y29sb3IsIGxhYmVsfSkgPT4gKFxuICAgIDxMZWdlbmRSb3dcbiAgICAgIGxhYmVsPXtsYWJlbCA/PyAnJ31cbiAgICAgIGRpc3BsYXlMYWJlbD17Qm9vbGVhbihsYWJlbCl9XG4gICAgICBjb2xvcj17QXJyYXkuaXNBcnJheShjb2xvcikgPyByZ2IoLi4uY29sb3IpLnRvU3RyaW5nKCkgOiBjb2xvcn1cbiAgICAvPlxuICApO1xuXG4gIFNpbmdsZUNvbG9yTGVnZW5kLmRpc3BsYXlOYW1lID0gJ1NpbmdsZUNvbG9yTGVnZW5kJztcblxuICByZXR1cm4gUmVhY3QubWVtbyhTaW5nbGVDb2xvckxlZ2VuZCk7XG59XG5cbmV4cG9ydCB0eXBlIExheWVyQ29sb3JMZWdlbmRQcm9wcyA9IHtcbiAgZGVzY3JpcHRpb246IFZpc3VhbENoYW5uZWxEZXNjcmlwdGlvbjtcbiAgY29uZmlnOiBMYXllckJhc2VDb25maWc7XG4gIGNvbG9yQ2hhbm5lbDogVmlzdWFsQ2hhbm5lbDtcbiAgb25MYXllclZpc0NvbmZpZ0NoYW5nZT86IChvbGRMYXllcjogTGF5ZXIsIG5ld1Zpc0NvbmZpZzogUGFydGlhbDxMYXllclZpc0NvbmZpZz4pID0+IHZvaWQ7XG4gIGxheWVyOiBMYXllcjtcbiAgZGlzYWJsZUVkaXQ/OiBib29sZWFuO1xuICBpc0V4cG9ydD86IGJvb2xlYW47XG4gIG1hcFN0YXRlPzogTWFwU3RhdGU7XG4gIGFjdGlvbkljb25zOiBNYXBMZWdlbmRJY29ucztcbn07XG5cbkxheWVyQ29sb3JMZWdlbmRGYWN0b3J5LmRlcHMgPSBbXG4gIENvbG9yTGVnZW5kRmFjdG9yeSxcbiAgU2luZ2xlQ29sb3JMZWdlbmRGYWN0b3J5LFxuICBQYW5lbEhlYWRlckFjdGlvbkZhY3Rvcnlcbl07XG5leHBvcnQgZnVuY3Rpb24gTGF5ZXJDb2xvckxlZ2VuZEZhY3RvcnkoXG4gIENvbG9yTGVnZW5kOiBSZXR1cm5UeXBlPHR5cGVvZiBDb2xvckxlZ2VuZEZhY3Rvcnk+LFxuICBTaW5nbGVDb2xvckxlZ2VuZDogUmV0dXJuVHlwZTx0eXBlb2YgU2luZ2xlQ29sb3JMZWdlbmRGYWN0b3J5PixcbiAgUGFuZWxIZWFkZXJBY3Rpb246IFJldHVyblR5cGU8dHlwZW9mIFBhbmVsSGVhZGVyQWN0aW9uRmFjdG9yeT5cbikge1xuICBjb25zdCBMYXllckNvbG9yTGVnZW5kOiBSZWFjdC5GQzxMYXllckNvbG9yTGVnZW5kUHJvcHM+ID0gKHtcbiAgICBkZXNjcmlwdGlvbixcbiAgICBjb25maWcsXG4gICAgbGF5ZXIsXG4gICAgY29sb3JDaGFubmVsLFxuICAgIGRpc2FibGVFZGl0LFxuICAgIG9uTGF5ZXJWaXNDb25maWdDaGFuZ2UsXG4gICAgaXNFeHBvcnQsXG4gICAgbWFwU3RhdGUsXG4gICAgYWN0aW9uSWNvbnNcbiAgfSkgPT4ge1xuICAgIGNvbnN0IGludGwgPSB1c2VJbnRsKCk7XG4gICAgY29uc3QgZW5hYmxlQ29sb3JCeSA9IGRlc2NyaXB0aW9uLm1lYXN1cmU7XG4gICAgY29uc3Qge3NjYWxlLCBmaWVsZCwgZG9tYWluLCByYW5nZSwgcHJvcGVydHksIGZpeGVkfSA9IGNvbG9yQ2hhbm5lbDtcbiAgICBjb25zdCBbY29sb3JTY2FsZSwgY29sb3JGaWVsZCwgY29sb3JEb21haW5dID0gW3NjYWxlLCBmaWVsZCwgZG9tYWluXS5tYXAoayA9PiBjb25maWdba10pO1xuICAgIGNvbnN0IGlzRml4ZWQgPSBmaXhlZCAmJiBjb25maWcudmlzQ29uZmlnW2ZpeGVkXTtcblxuICAgIGNvbnN0IGNvbG9yUmFuZ2UgPSBjb25maWcudmlzQ29uZmlnW3JhbmdlXTtcbiAgICBjb25zdCBvblVwZGF0ZUNvbG9yTGVnZW5kID0gdXNlQ2FsbGJhY2soXG4gICAgICBjb2xvckxlZ2VuZHMgPT4ge1xuICAgICAgICBpZiAob25MYXllclZpc0NvbmZpZ0NoYW5nZSkge1xuICAgICAgICAgIG9uTGF5ZXJWaXNDb25maWdDaGFuZ2UobGF5ZXIsIHtcbiAgICAgICAgICAgIFtyYW5nZV06IHtcbiAgICAgICAgICAgICAgLi4uY29sb3JSYW5nZSxcbiAgICAgICAgICAgICAgY29sb3JMZWdlbmRzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBbbGF5ZXIsIG9uTGF5ZXJWaXNDb25maWdDaGFuZ2UsIGNvbG9yUmFuZ2UsIHJhbmdlXVxuICAgICk7XG4gICAgY29uc3QgW2lzRXhwYW5kZWQsIHNldElzRXhwYW5kZWRdID0gdXNlU3RhdGUoaXNFeHBvcnQpO1xuICAgIGNvbnN0IGhhbmRsZVRvZ2dsZUV4cGFuZGVkID0gKCkgPT4gc2V0SXNFeHBhbmRlZCghaXNFeHBhbmRlZCk7XG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXYgY2xhc3NOYW1lPVwibGVnZW5kLS1sYXllcl9faXRlbVwiPlxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImxlZ2VuZC0tbGF5ZXJfY29sb3Itc2NoZW1hXCI+XG4gICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgIHtlbmFibGVDb2xvckJ5ID8gKFxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImxlZ2VuZC0tbGF5ZXJfc2l6ZS10aXRsZS1yb3dcIj5cbiAgICAgICAgICAgICAgICA8VmlzdWFsQ2hhbm5lbE1ldHJpYyBuYW1lPXtlbmFibGVDb2xvckJ5fSAvPlxuICAgICAgICAgICAgICAgIHshaXNFeHBvcnQgPyAoXG4gICAgICAgICAgICAgICAgICA8UGFuZWxIZWFkZXJBY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgaWQ9XCJsZWdlbmQtY29sbGFwc2UtYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgb25DbGljaz17aGFuZGxlVG9nZ2xlRXhwYW5kZWR9XG4gICAgICAgICAgICAgICAgICAgIEljb25Db21wb25lbnQ9e2lzRXhwYW5kZWQgPyBhY3Rpb25JY29ucy5leHBhbmRlZCA6IGFjdGlvbkljb25zLmNvbGxhcHNlZH1cbiAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgKSA6IG51bGx9XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKSA6IG51bGx9XG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImxlZ2VuZC0tbGF5ZXJfY29sb3ItbGVnZW5kXCI+XG4gICAgICAgICAgICAgIHtlbmFibGVDb2xvckJ5ID8gKFxuICAgICAgICAgICAgICAgIDxDb2xvckxlZ2VuZFxuICAgICAgICAgICAgICAgICAgbGF5ZXI9e2xheWVyfVxuICAgICAgICAgICAgICAgICAgaXNFeHBhbmRlZD17aXNFeHBhbmRlZH1cbiAgICAgICAgICAgICAgICAgIHNjYWxlVHlwZT17Y29sb3JTY2FsZX1cbiAgICAgICAgICAgICAgICAgIGRpc3BsYXlMYWJlbFxuICAgICAgICAgICAgICAgICAgZG9tYWluPXtjb2xvckRvbWFpbn1cbiAgICAgICAgICAgICAgICAgIGZpZWxkVHlwZT17KGNvbG9yRmllbGQgJiYgY29sb3JGaWVsZC50eXBlKSB8fCAncmVhbCd9XG4gICAgICAgICAgICAgICAgICByYW5nZT17Y29sb3JSYW5nZX1cbiAgICAgICAgICAgICAgICAgIG9uVXBkYXRlQ29sb3JMZWdlbmQ9e29uVXBkYXRlQ29sb3JMZWdlbmR9XG4gICAgICAgICAgICAgICAgICBkaXNhYmxlRWRpdD17ZGlzYWJsZUVkaXQgfHwgQm9vbGVhbihpc0V4cG9ydCl9XG4gICAgICAgICAgICAgICAgICBpc0ZpeGVkPXtpc0ZpeGVkfVxuICAgICAgICAgICAgICAgICAgbWFwU3RhdGU9e21hcFN0YXRlfVxuICAgICAgICAgICAgICAgICAgbGFiZWxGb3JtYXQ9e1xuICAgICAgICAgICAgICAgICAgICBjb2xvckZpZWxkPy5kaXNwbGF5Rm9ybWF0ID8gZDNGb3JtYXQoY29sb3JGaWVsZD8uZGlzcGxheUZvcm1hdCkgOiBudWxsXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgKSA6IChcbiAgICAgICAgICAgICAgICA8U2luZ2xlQ29sb3JMZWdlbmRcbiAgICAgICAgICAgICAgICAgIGNvbG9yPXtjb25maWcudmlzQ29uZmlnW3Byb3BlcnR5XSB8fCBjb25maWdbcHJvcGVydHldIHx8IGNvbmZpZy5jb2xvcn1cbiAgICAgICAgICAgICAgICAgIGxhYmVsPXtpbnRsLmZvcm1hdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgICAgICAgICBpZDogYG1hcExlZ2VuZC5sYXllcnMuJHtsYXllci50eXBlfS5zaW5nbGVDb2xvci4ke2NvbG9yQ2hhbm5lbC5rZXl9YCxcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdE1lc3NhZ2U6IGludGwuZm9ybWF0TWVzc2FnZSh7XG4gICAgICAgICAgICAgICAgICAgICAgaWQ6IGBtYXBMZWdlbmQubGF5ZXJzLmRlZmF1bHQuc2luZ2xlQ29sb3IuJHtjb2xvckNoYW5uZWwua2V5fWAsXG4gICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdE1lc3NhZ2U6ICcgJyAvLyBtdXN0bid0IGJlIGVtcHR5IHN0cmluZyBvciBpZCB3aWxsIGJlIHVzZWRcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgIH0pfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICl9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICApO1xuICB9O1xuXG4gIExheWVyQ29sb3JMZWdlbmQuZGlzcGxheU5hbWUgPSAnTGF5ZXJDb2xvckxlZ2VuZCc7XG4gIHJldHVybiBSZWFjdC5tZW1vKExheWVyQ29sb3JMZWdlbmQpO1xufVxuXG5mdW5jdGlvbiBnZXRMYXllclJhZGl1c1NjYWxlTWV0ZXJzVG9QaXhlbHNNdWx0aXBsaWVyKGxheWVyLCBtYXBTdGF0ZSkge1xuICAvLyBAdHMtaWdub3JlIHRoaXMgYWN0dWFsbHkgZXhpc3RcbiAgY29uc3Qge21ldGVyc1BlclBpeGVsfSA9IGdldERpc3RhbmNlU2NhbGVzKG1hcFN0YXRlKTtcbiAgLy8gaWYgbm8gZmllbGQgc2l6ZSBpcyBkZWZpbmVkIHdlIG5lZWQgdG8gcGFzcyBmaXhlZCByYWRpdXMgPSBmYWxzZVxuICBjb25zdCBmaXhlZFJhZGl1cyA9IGxheWVyLmNvbmZpZy52aXNDb25maWcuZml4ZWRSYWRpdXMgJiYgQm9vbGVhbihsYXllci5jb25maWcuc2l6ZUZpZWxkKTtcbiAgcmV0dXJuIGxheWVyLmdldFJhZGl1c1NjYWxlQnlab29tKG1hcFN0YXRlLCBmaXhlZFJhZGl1cykgLyBtZXRlcnNQZXJQaXhlbFswXTtcbn1cblxuZXhwb3J0IHR5cGUgTWFwTGVnZW5kSWNvbnMgPSB7XG4gIGV4cGFuZGVkOiBDb21wb25lbnRUeXBlPGFueT47XG4gIGNvbGxhcHNlZDogQ29tcG9uZW50VHlwZTxhbnk+O1xufTtcblxuZXhwb3J0IHR5cGUgTGF5ZXJSYWRpdXNMZWdlbmRQcm9wcyA9IHtcbiAgbGF5ZXI6IExheWVyO1xuICBtYXBTdGF0ZT86IE1hcFN0YXRlO1xuICB3aWR0aDogbnVtYmVyO1xuICBpc0V4cG9ydD86IGJvb2xlYW47XG4gIHZpc3VhbENoYW5uZWw6IFZpc3VhbENoYW5uZWw7XG59O1xuXG5leHBvcnQgY29uc3QgTGF5ZXJSYWRpdXNMZWdlbmQ6IEZDPExheWVyUmFkaXVzTGVnZW5kUHJvcHM+ID0gUmVhY3QubWVtbyhcbiAgKHtsYXllciwgd2lkdGgsIHZpc3VhbENoYW5uZWwsIG1hcFN0YXRlfSkgPT4ge1xuICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gbGF5ZXIuZ2V0VmlzdWFsQ2hhbm5lbERlc2NyaXB0aW9uKHZpc3VhbENoYW5uZWwua2V5KTtcbiAgICBjb25zdCBjb25maWcgPSBsYXllci5jb25maWc7XG5cbiAgICBjb25zdCBlbmFibGVTaXplQnkgPSBkZXNjcmlwdGlvbi5tZWFzdXJlO1xuICAgIGNvbnN0IHtzY2FsZSwgZmllbGQsIGRvbWFpbiwgcmFuZ2V9ID0gdmlzdWFsQ2hhbm5lbDtcbiAgICBjb25zdCBbc2l6ZVNjYWxlLCBzaXplRmllbGQsIHNpemVEb21haW5dID0gW3NjYWxlLCBmaWVsZCwgZG9tYWluXS5tYXAoayA9PiBjb25maWdba10pO1xuICAgIGxldCBzaXplUmFuZ2UgPSBjb25maWcudmlzQ29uZmlnW3JhbmdlXTtcblxuICAgIGlmIChtYXBTdGF0ZSkge1xuICAgICAgY29uc3QgcmFkaXVzTXVsdGlwbGllciA9IGdldExheWVyUmFkaXVzU2NhbGVNZXRlcnNUb1BpeGVsc011bHRpcGxpZXIobGF5ZXIsIG1hcFN0YXRlKTtcbiAgICAgIHNpemVSYW5nZSA9IHNpemVSYW5nZS5tYXAodiA9PiB2ICogcmFkaXVzTXVsdGlwbGllcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXY+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibGVnZW5kLS1sYXllcl9zaXplLXNjaGVtYVwiPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICB7ZW5hYmxlU2l6ZUJ5ID8gPFZpc3VhbENoYW5uZWxNZXRyaWMgbmFtZT17ZW5hYmxlU2l6ZUJ5fSAvPiA6IG51bGx9XG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImxlZ2VuZC0tbGF5ZXJfc2l6ZS1sZWdlbmRcIj5cbiAgICAgICAgICAgICAge2VuYWJsZVNpemVCeSA/IChcbiAgICAgICAgICAgICAgICA8UmFkaXVzTGVnZW5kXG4gICAgICAgICAgICAgICAgICBzY2FsZVR5cGU9e3NpemVTY2FsZX1cbiAgICAgICAgICAgICAgICAgIGRvbWFpbj17c2l6ZURvbWFpbn1cbiAgICAgICAgICAgICAgICAgIGZpZWxkVHlwZT17KHNpemVGaWVsZCAmJiBzaXplRmllbGQudHlwZSkgfHwgJ3JlYWwnfVxuICAgICAgICAgICAgICAgICAgcmFuZ2U9e3NpemVSYW5nZX1cbiAgICAgICAgICAgICAgICAgIHdpZHRoPXt3aWR0aH1cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICApIDogbnVsbH1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICk7XG4gIH1cbik7XG5cbmNvbnN0IGlzQ29sb3JDaGFubmVsID0gdmlzdWFsQ2hhbm5lbCA9PlxuICBbQ0hBTk5FTF9TQ0FMRVMuY29sb3IsIENIQU5ORUxfU0NBTEVTLmNvbG9yQWdncl0uaW5jbHVkZXModmlzdWFsQ2hhbm5lbC5jaGFubmVsU2NhbGVUeXBlKTtcblxuZXhwb3J0IHR5cGUgTGF5ZXJMZWdlbmRIZWFkZXJQcm9wcyA9IHtcbiAgbGF5ZXI6IExheWVyO1xuICBvcHRpb25zPzoge1xuICAgIHNob3dMYXllck5hbWU/OiBib29sZWFuO1xuICB9O1xuICBpc0V4cG9ydD86IGJvb2xlYW47XG4gIG9uVG9nZ2xlTGF5ZXJWaXNpYmlsaXR5PzogKGxheWVyOiBMYXllcikgPT4gdm9pZDtcbn07XG5cbmNvbnN0IGlzUmFkaXVzQ2hhbm5lbCA9IHZpc3VhbENoYW5uZWwgPT5cbiAgW0NIQU5ORUxfU0NBTEVTLnJhZGl1c10uaW5jbHVkZXModmlzdWFsQ2hhbm5lbC5jaGFubmVsU2NhbGVUeXBlKTtcblxuZXhwb3J0IGZ1bmN0aW9uIExheWVyTGVnZW5kSGVhZGVyRmFjdG9yeSgpIHtcbiAgY29uc3QgTGF5ZXJMZWdlbmRIZWFkZXI6IFJlYWN0LkZDPExheWVyTGVnZW5kSGVhZGVyUHJvcHM+ID0gKHtcbiAgICBvcHRpb25zLFxuICAgIGxheWVyLFxuICAgIG9uVG9nZ2xlTGF5ZXJWaXNpYmlsaXR5XG4gIH0pID0+IHtcbiAgICBjb25zdCBpc1Zpc2libGUgPSBsYXllci5jb25maWcuaXNWaXNpYmxlO1xuICAgIGNvbnN0IG9uVG9nZ2xlID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgICAgaWYgKG9uVG9nZ2xlTGF5ZXJWaXNpYmlsaXR5KSB7XG4gICAgICAgIG9uVG9nZ2xlTGF5ZXJWaXNpYmlsaXR5KGxheWVyKTtcbiAgICAgIH1cbiAgICB9LCBbbGF5ZXIsIG9uVG9nZ2xlTGF5ZXJWaXNpYmlsaXR5XSk7XG5cbiAgICBpZiAob3B0aW9ucz8uc2hvd0xheWVyTmFtZSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiAoXG4gICAgICA8U3R5bGVkTGVnZW5kSGVhZGVyUm93PlxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImxlZ2VuZC0tbGF5ZXJfbmFtZVwiIHN0eWxlPXt7b3BhY2l0eTogaXNWaXNpYmxlID8gMSA6IDAuNX19PlxuICAgICAgICAgIHtsYXllci5jb25maWcubGFiZWx9XG4gICAgICAgIDwvZGl2PlxuICAgICAgICB7b25Ub2dnbGVMYXllclZpc2liaWxpdHkgPyAoXG4gICAgICAgICAgPFN0eWxlZFZpc2liaWxpdHlUb2dnbGUgaXNWaXNpYmxlPXtpc1Zpc2libGV9IG9uQ2xpY2s9e29uVG9nZ2xlfT5cbiAgICAgICAgICAgIHtpc1Zpc2libGUgPyA8RXllU2VlbiBoZWlnaHQ9XCIxMnB4XCIgLz4gOiA8RXllVW5zZWVuIGhlaWdodD1cIjEycHhcIiAvPn1cbiAgICAgICAgICA8L1N0eWxlZFZpc2liaWxpdHlUb2dnbGU+XG4gICAgICAgICkgOiBudWxsfVxuICAgICAgPC9TdHlsZWRMZWdlbmRIZWFkZXJSb3c+XG4gICAgKTtcbiAgfTtcbiAgcmV0dXJuIExheWVyTGVnZW5kSGVhZGVyO1xufVxuXG5jb25zdCBkZWZhdWx0QWN0aW9uSWNvbnMgPSB7XG4gIGV4cGFuZGVkOiBBcnJvd0Rvd24sXG4gIGNvbGxhcHNlZDogQXJyb3dSaWdodFxufTtcblxuZXhwb3J0IHR5cGUgTGF5ZXJMZWdlbmRDb250ZW50UHJvcHMgPSB7XG4gIGxheWVyOiBMYXllcjtcbiAgY29udGFpbmVyVzogbnVtYmVyO1xuICBtYXBTdGF0ZT86IE1hcFN0YXRlO1xuICBkaXNhYmxlRWRpdD86IGJvb2xlYW47XG4gIGlzRXhwb3J0PzogYm9vbGVhbjtcbiAgb25MYXllclZpc0NvbmZpZ0NoYW5nZT86IChvbGRMYXllcjogTGF5ZXIsIG5ld1Zpc0NvbmZpZzogUGFydGlhbDxMYXllclZpc0NvbmZpZz4pID0+IHZvaWQ7XG4gIGFjdGlvbkljb25zOiBNYXBMZWdlbmRJY29ucztcbn07XG5cbkxheWVyTGVnZW5kQ29udGVudEZhY3RvcnkuZGVwcyA9IFtMYXllckNvbG9yTGVnZW5kRmFjdG9yeV07XG5cbmV4cG9ydCBmdW5jdGlvbiBMYXllckxlZ2VuZENvbnRlbnRGYWN0b3J5KFxuICBMYXllckNvbG9yTGVnZW5kOiBSZXR1cm5UeXBlPHR5cGVvZiBMYXllckNvbG9yTGVnZW5kRmFjdG9yeT5cbikge1xuICBjb25zdCBMYXllckxlZ2VuZENvbnRlbnQ6IFJlYWN0LkZDPExheWVyTGVnZW5kQ29udGVudFByb3BzPiA9ICh7XG4gICAgbGF5ZXIsXG4gICAgY29udGFpbmVyVyxcbiAgICBtYXBTdGF0ZSxcbiAgICBkaXNhYmxlRWRpdCxcbiAgICBpc0V4cG9ydCxcbiAgICBvbkxheWVyVmlzQ29uZmlnQ2hhbmdlLFxuICAgIGFjdGlvbkljb25zXG4gIH0pID0+IHtcbiAgICBjb25zdCB2aXN1YWxDaGFubmVscyA9IGxheWVyLmdldExlZ2VuZFZpc3VhbENoYW5uZWxzKCk7XG4gICAgY29uc3QgY2hhbm5lbEtleXMgPSBPYmplY3QudmFsdWVzKHZpc3VhbENoYW5uZWxzKTtcbiAgICBjb25zdCBjb2xvckNoYW5uZWxzID0gY2hhbm5lbEtleXMuZmlsdGVyKGlzQ29sb3JDaGFubmVsKSBhcyBWaXN1YWxDaGFubmVsW107XG4gICAgY29uc3Qgbm9uQ29sb3JDaGFubmVscyA9IGNoYW5uZWxLZXlzLmZpbHRlcih2YyA9PiAhaXNDb2xvckNoYW5uZWwodmMpKTtcbiAgICBjb25zdCB3aWR0aCA9IGNvbnRhaW5lclcgLSAyICogRElNRU5TSU9OUy5tYXBDb250cm9sLnBhZGRpbmc7XG5cbiAgICAvLyByZW5kZXIgY29sb3IgYnkgY2hhbmVsIG9ubHlcbiAgICBsZXQgY29sb3JDaGFubmVsVG9SZW5kZXIgPSBjb2xvckNoYW5uZWxzLmZpbHRlcihcbiAgICAgIGNjID0+XG4gICAgICAgICghY2MuY29uZGl0aW9uIHx8IGNjLmNvbmRpdGlvbihsYXllci5jb25maWcpKSAmJlxuICAgICAgICBsYXllci5nZXRWaXN1YWxDaGFubmVsRGVzY3JpcHRpb24oY2Mua2V5KT8ubWVhc3VyZVxuICAgICk7XG4gICAgLy8gaWYgbm8gY29sb3IgYnkgY2hhbmVsLCByZW5kZXIgcmVzdFxuICAgIGlmICghY29sb3JDaGFubmVsVG9SZW5kZXIubGVuZ3RoKSB7XG4gICAgICBjb2xvckNoYW5uZWxUb1JlbmRlciA9IGNvbG9yQ2hhbm5lbHMuZmlsdGVyKFxuICAgICAgICBjYyA9PiAhY2MuY29uZGl0aW9uIHx8IGNjLmNvbmRpdGlvbihsYXllci5jb25maWcpXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gKFxuICAgICAgPD5cbiAgICAgICAge2NvbG9yQ2hhbm5lbFRvUmVuZGVyLm1hcChjb2xvckNoYW5uZWwgPT4gKFxuICAgICAgICAgIDxMYXllckNvbG9yTGVnZW5kXG4gICAgICAgICAgICBrZXk9e2NvbG9yQ2hhbm5lbC5rZXl9XG4gICAgICAgICAgICBjb2xvckNoYW5uZWw9e2NvbG9yQ2hhbm5lbH1cbiAgICAgICAgICAgIGNvbmZpZz17bGF5ZXIuY29uZmlnfVxuICAgICAgICAgICAgZGVzY3JpcHRpb249e2xheWVyLmdldFZpc3VhbENoYW5uZWxEZXNjcmlwdGlvbihjb2xvckNoYW5uZWwua2V5KX1cbiAgICAgICAgICAgIGxheWVyPXtsYXllcn1cbiAgICAgICAgICAgIGlzRXhwb3J0PXtpc0V4cG9ydH1cbiAgICAgICAgICAgIGRpc2FibGVFZGl0PXtkaXNhYmxlRWRpdH1cbiAgICAgICAgICAgIG1hcFN0YXRlPXttYXBTdGF0ZX1cbiAgICAgICAgICAgIG9uTGF5ZXJWaXNDb25maWdDaGFuZ2U9e29uTGF5ZXJWaXNDb25maWdDaGFuZ2V9XG4gICAgICAgICAgICBhY3Rpb25JY29ucz17YWN0aW9uSWNvbnN9XG4gICAgICAgICAgLz5cbiAgICAgICAgKSl9XG4gICAgICAgIHtub25Db2xvckNoYW5uZWxzLm1hcCgodmlzdWFsQ2hhbm5lbDogVmlzdWFsQ2hhbm5lbCkgPT4ge1xuICAgICAgICAgIGNvbnN0IG1hdGNoQ29uZGl0aW9uID0gIXZpc3VhbENoYW5uZWwuY29uZGl0aW9uIHx8IHZpc3VhbENoYW5uZWwuY29uZGl0aW9uKGxheWVyLmNvbmZpZyk7XG4gICAgICAgICAgY29uc3QgZW5hYmxlZCA9IGxheWVyLmNvbmZpZ1t2aXN1YWxDaGFubmVsLmZpZWxkXSB8fCB2aXN1YWxDaGFubmVsLmRlZmF1bHRNZWFzdXJlO1xuXG4gICAgICAgICAgaWYgKG1hdGNoQ29uZGl0aW9uICYmIGVuYWJsZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gbGF5ZXIuZ2V0VmlzdWFsQ2hhbm5lbERlc2NyaXB0aW9uKHZpc3VhbENoYW5uZWwua2V5KTtcbiAgICAgICAgICAgIGlmIChpc1JhZGl1c0NoYW5uZWwodmlzdWFsQ2hhbm5lbCkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8TGF5ZXJSYWRpdXNMZWdlbmRcbiAgICAgICAgICAgICAgICAgIGtleT17dmlzdWFsQ2hhbm5lbC5rZXl9XG4gICAgICAgICAgICAgICAgICBsYXllcj17bGF5ZXJ9XG4gICAgICAgICAgICAgICAgICBtYXBTdGF0ZT17bWFwU3RhdGV9XG4gICAgICAgICAgICAgICAgICB3aWR0aD17d2lkdGh9XG4gICAgICAgICAgICAgICAgICB2aXN1YWxDaGFubmVsPXt2aXN1YWxDaGFubmVsfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICA8TGF5ZXJEZWZhdWx0TGVnZW5kXG4gICAgICAgICAgICAgICAga2V5PXt2aXN1YWxDaGFubmVsLmtleX1cbiAgICAgICAgICAgICAgICBsYWJlbD17ZGVzY3JpcHRpb24ubGFiZWx9XG4gICAgICAgICAgICAgICAgbmFtZT17ZGVzY3JpcHRpb24ubWVhc3VyZX1cbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9KX1cbiAgICAgIDwvPlxuICAgICk7XG4gIH07XG5cbiAgcmV0dXJuIExheWVyTGVnZW5kQ29udGVudDtcbn1cblxuZXhwb3J0IHR5cGUgTWFwTGVnZW5kUHJvcHMgPSB7XG4gIGxheWVycz86IFJlYWRvbmx5QXJyYXk8TGF5ZXI+O1xuICB3aWR0aD86IG51bWJlcjtcbiAgbWFwU3RhdGU/OiBNYXBTdGF0ZTtcbiAgb3B0aW9ucz86IHtcbiAgICBzaG93TGF5ZXJOYW1lPzogYm9vbGVhbjtcbiAgfTtcbiAgZGlzYWJsZUVkaXQ/OiBib29sZWFuO1xuICBpc0V4cG9ydD86IGJvb2xlYW47XG4gIG9uTGF5ZXJWaXNDb25maWdDaGFuZ2U/OiAob2xkTGF5ZXI6IExheWVyLCBuZXdWaXNDb25maWc6IFBhcnRpYWw8TGF5ZXJWaXNDb25maWc+KSA9PiB2b2lkO1xuICBvblRvZ2dsZUxheWVyVmlzaWJpbGl0eT86IChsYXllcjogTGF5ZXIpID0+IHZvaWQ7XG4gIGFjdGlvbkljb25zPzogTWFwTGVnZW5kSWNvbnM7XG59O1xuXG5NYXBMZWdlbmRGYWN0b3J5LmRlcHMgPSBbTGF5ZXJMZWdlbmRIZWFkZXJGYWN0b3J5LCBMYXllckxlZ2VuZENvbnRlbnRGYWN0b3J5XTtcblxuZnVuY3Rpb24gTWFwTGVnZW5kRmFjdG9yeShcbiAgTGF5ZXJMZWdlbmRIZWFkZXI6IFJldHVyblR5cGU8dHlwZW9mIExheWVyTGVnZW5kSGVhZGVyRmFjdG9yeT4sXG4gIExheWVyTGVnZW5kQ29udGVudDogUmV0dXJuVHlwZTx0eXBlb2YgTGF5ZXJMZWdlbmRDb250ZW50RmFjdG9yeT5cbikge1xuICBjb25zdCBNYXBMZWdlbmQ6IFJlYWN0LkZDPE1hcExlZ2VuZFByb3BzPiA9ICh7XG4gICAgbGF5ZXJzID0gW10sXG4gICAgd2lkdGgsXG4gICAgbWFwU3RhdGUsXG4gICAgb3B0aW9ucyxcbiAgICBkaXNhYmxlRWRpdCxcbiAgICBpc0V4cG9ydCxcbiAgICBvbkxheWVyVmlzQ29uZmlnQ2hhbmdlLFxuICAgIG9uVG9nZ2xlTGF5ZXJWaXNpYmlsaXR5LFxuICAgIGFjdGlvbkljb25zID0gZGVmYXVsdEFjdGlvbkljb25zXG4gIH0pID0+IChcbiAgICA8ZGl2IGNsYXNzTmFtZT1cIm1hcC1sZWdlbmRcIj5cbiAgICAgIHtsYXllcnMubWFwKChsYXllciwgaW5kZXgpID0+IHtcbiAgICAgICAgaWYgKCFsYXllci5pc1ZhbGlkVG9TYXZlKCkgfHwgbGF5ZXIuY29uZmlnLmhpZGRlbikge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lclcgPSB3aWR0aCB8fCBESU1FTlNJT05TLm1hcENvbnRyb2wud2lkdGg7XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICA8U3R5bGVkTWFwQ29udHJvbExlZ2VuZFxuICAgICAgICAgICAgY2xhc3NOYW1lPVwibGVnZW5kLS1sYXllclwiXG4gICAgICAgICAgICBsYXN0PXtpbmRleCA9PT0gbGF5ZXJzLmxlbmd0aCAtIDF9XG4gICAgICAgICAgICBrZXk9e2luZGV4fVxuICAgICAgICAgICAgd2lkdGg9e2NvbnRhaW5lcld9XG4gICAgICAgICAgPlxuICAgICAgICAgICAgPExheWVyTGVnZW5kSGVhZGVyXG4gICAgICAgICAgICAgIGlzRXhwb3J0PXtpc0V4cG9ydH1cbiAgICAgICAgICAgICAgb3B0aW9ucz17b3B0aW9uc31cbiAgICAgICAgICAgICAgbGF5ZXI9e2xheWVyfVxuICAgICAgICAgICAgICBvblRvZ2dsZUxheWVyVmlzaWJpbGl0eT17b25Ub2dnbGVMYXllclZpc2liaWxpdHl9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPExheWVyTGVnZW5kQ29udGVudFxuICAgICAgICAgICAgICBjb250YWluZXJXPXtjb250YWluZXJXfVxuICAgICAgICAgICAgICBsYXllcj17bGF5ZXJ9XG4gICAgICAgICAgICAgIG1hcFN0YXRlPXttYXBTdGF0ZX1cbiAgICAgICAgICAgICAgZGlzYWJsZUVkaXQ9e2Rpc2FibGVFZGl0fVxuICAgICAgICAgICAgICBpc0V4cG9ydD17aXNFeHBvcnR9XG4gICAgICAgICAgICAgIG9uTGF5ZXJWaXNDb25maWdDaGFuZ2U9e29uTGF5ZXJWaXNDb25maWdDaGFuZ2V9XG4gICAgICAgICAgICAgIGFjdGlvbkljb25zPXthY3Rpb25JY29uc31cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9TdHlsZWRNYXBDb250cm9sTGVnZW5kPlxuICAgICAgICApO1xuICAgICAgfSl9XG4gICAgPC9kaXY+XG4gICk7XG5cbiAgTWFwTGVnZW5kLmRpc3BsYXlOYW1lID0gJ01hcExlZ2VuZCc7XG5cbiAgcmV0dXJuIE1hcExlZ2VuZDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgTWFwTGVnZW5kRmFjdG9yeTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEsTUFBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsaUJBQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLFFBQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLFNBQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLFVBQUEsR0FBQUwsT0FBQTtBQUNBLElBQUFNLFlBQUEsR0FBQVAsdUJBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFPLGFBQUEsR0FBQUwsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFRLFVBQUEsR0FBQVIsT0FBQTtBQUNBLElBQUFTLGFBQUEsR0FBQVQsT0FBQTtBQUdBLElBQUFVLHdCQUFBLEdBQUFWLE9BQUE7QUFDQSxJQUFBVyxNQUFBLEdBQUFYLE9BQUE7QUFDQSxJQUFBWSxrQkFBQSxHQUFBVixzQkFBQSxDQUFBRixPQUFBO0FBQXlFLElBQUFhLGVBQUEsRUFBQUMsZ0JBQUEsRUFBQUMsZ0JBQUEsRUFoQnpFO0FBQ0E7QUFBQSxTQUFBQyx5QkFBQUMsQ0FBQSw2QkFBQUMsT0FBQSxtQkFBQUMsQ0FBQSxPQUFBRCxPQUFBLElBQUFFLENBQUEsT0FBQUYsT0FBQSxZQUFBRix3QkFBQSxZQUFBQSx5QkFBQUMsQ0FBQSxXQUFBQSxDQUFBLEdBQUFHLENBQUEsR0FBQUQsQ0FBQSxLQUFBRixDQUFBO0FBQUEsU0FBQWxCLHdCQUFBa0IsQ0FBQSxFQUFBRSxDQUFBLFNBQUFBLENBQUEsSUFBQUYsQ0FBQSxJQUFBQSxDQUFBLENBQUFJLFVBQUEsU0FBQUosQ0FBQSxlQUFBQSxDQUFBLGdCQUFBSyxPQUFBLENBQUFMLENBQUEsMEJBQUFBLENBQUEsc0JBQUFBLENBQUEsUUFBQUcsQ0FBQSxHQUFBSix3QkFBQSxDQUFBRyxDQUFBLE9BQUFDLENBQUEsSUFBQUEsQ0FBQSxDQUFBRyxHQUFBLENBQUFOLENBQUEsVUFBQUcsQ0FBQSxDQUFBSSxHQUFBLENBQUFQLENBQUEsT0FBQVEsQ0FBQSxLQUFBQyxTQUFBLFVBQUFDLENBQUEsR0FBQUMsTUFBQSxDQUFBQyxjQUFBLElBQUFELE1BQUEsQ0FBQUUsd0JBQUEsV0FBQUMsQ0FBQSxJQUFBZCxDQUFBLG9CQUFBYyxDQUFBLE9BQUFDLGNBQUEsQ0FBQUMsSUFBQSxDQUFBaEIsQ0FBQSxFQUFBYyxDQUFBLFNBQUFHLENBQUEsR0FBQVAsQ0FBQSxHQUFBQyxNQUFBLENBQUFFLHdCQUFBLENBQUFiLENBQUEsRUFBQWMsQ0FBQSxVQUFBRyxDQUFBLEtBQUFBLENBQUEsQ0FBQVYsR0FBQSxJQUFBVSxDQUFBLENBQUFDLEdBQUEsSUFBQVAsTUFBQSxDQUFBQyxjQUFBLENBQUFKLENBQUEsRUFBQU0sQ0FBQSxFQUFBRyxDQUFBLElBQUFULENBQUEsQ0FBQU0sQ0FBQSxJQUFBZCxDQUFBLENBQUFjLENBQUEsWUFBQU4sQ0FBQSxjQUFBUixDQUFBLEVBQUFHLENBQUEsSUFBQUEsQ0FBQSxDQUFBZSxHQUFBLENBQUFsQixDQUFBLEVBQUFRLENBQUEsR0FBQUEsQ0FBQTtBQUFBLFNBQUFXLFFBQUFuQixDQUFBLEVBQUFFLENBQUEsUUFBQUMsQ0FBQSxHQUFBUSxNQUFBLENBQUFTLElBQUEsQ0FBQXBCLENBQUEsT0FBQVcsTUFBQSxDQUFBVSxxQkFBQSxRQUFBQyxDQUFBLEdBQUFYLE1BQUEsQ0FBQVUscUJBQUEsQ0FBQXJCLENBQUEsR0FBQUUsQ0FBQSxLQUFBb0IsQ0FBQSxHQUFBQSxDQUFBLENBQUFDLE1BQUEsV0FBQXJCLENBQUEsV0FBQVMsTUFBQSxDQUFBRSx3QkFBQSxDQUFBYixDQUFBLEVBQUFFLENBQUEsRUFBQXNCLFVBQUEsT0FBQXJCLENBQUEsQ0FBQXNCLElBQUEsQ0FBQUMsS0FBQSxDQUFBdkIsQ0FBQSxFQUFBbUIsQ0FBQSxZQUFBbkIsQ0FBQTtBQUFBLFNBQUF3QixjQUFBM0IsQ0FBQSxhQUFBRSxDQUFBLE1BQUFBLENBQUEsR0FBQTBCLFNBQUEsQ0FBQUMsTUFBQSxFQUFBM0IsQ0FBQSxVQUFBQyxDQUFBLFdBQUF5QixTQUFBLENBQUExQixD