kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
524 lines (450 loc) • 55.4 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.MapControl = void 0;
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 _getPrototypeOf3 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _reselect = require("reselect");
var _styledComponents = _interopRequireDefault(require("styled-components"));
var _reactGeosuggest = _interopRequireDefault(require("react-geosuggest"));
var _styledComponents2 = require("../common/styled-components");
var _mapLayerSelector = _interopRequireDefault(require("../common/map-layer-selector"));
var _logo = _interopRequireDefault(require("../common/logo"));
var _mapLegend = _interopRequireDefault(require("./map-legend"));
var _icons = require("../common/icons");
require("./geo-suggest.css");
function _templateObject7() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n display: flex;\n justify-content: space-between;\n background-color: ", ";\n height: 32px;\n padding: 6px 12px;\n font-size: 11px;\n color: ", ";\n\n button {\n width: 18px;\n height: 18px;\n }\n"]);
_templateObject7 = function _templateObject7() {
return data;
};
return data;
}
function _templateObject6() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n ", "\n"]);
_templateObject6 = function _templateObject6() {
return data;
};
return data;
}
function _templateObject5() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n ", " max-height: 500px;\n min-height: 100px;\n overflow: auto;\n"]);
_templateObject5 = function _templateObject5() {
return data;
};
return data;
}
function _templateObject4() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n background-color: ", ";\n flex-grow: 1;\n z-index: 1;\n p {\n margin-bottom: 0;\n }\n"]);
_templateObject4 = function _templateObject4() {
return data;
};
return data;
}
function _templateObject3() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n align-items: center;\n background-color: ", ";\n border-radius: 18px;\n border: 0;\n box-shadow: 0 6px 12px 0 rgba(0, 0, 0, 0.16);\n color: ", ";\n cursor: pointer;\n display: flex;\n height: 36px;\n justify-content: center;\n margin: 0;\n outline: none;\n padding: 0;\n transition: ", ";\n width: 36px;\n\n :focus {\n outline: none;\n }\n\n :hover {\n cursor: pointer;\n background-color: ", ";\n color: ", ";\n }\n"]);
_templateObject3 = function _templateObject3() {
return data;
};
return data;
}
function _templateObject2() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n padding: 4px 0;\n display: flex;\n justify-content: flex-end;\n"]);
_templateObject2 = function _templateObject2() {
return data;
};
return data;
}
function _templateObject() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n right: 0;\n width: ", "px;\n padding: ", "px;\n z-index: 1;\n top: ", "px;\n position: absolute;\n"]);
_templateObject = function _templateObject() {
return data;
};
return data;
}
var StyledMapControl = _styledComponents["default"].div(_templateObject(), function (props) {
return props.theme.mapControl.width;
}, function (props) {
return props.theme.mapControl.padding;
}, function (props) {
return props.top;
});
var StyledMapControlAction = _styledComponents["default"].div(_templateObject2());
var StyledMapControlButton = _styledComponents["default"].div(_templateObject3(), function (props) {
return props.active ? props.theme.secondaryBtnActBgd : props.theme.secondaryBtnBgd;
}, function (props) {
return props.active ? props.theme.secondaryBtnActColor : props.theme.secondaryBtnColor;
}, function (props) {
return props.theme.transition;
}, function (props) {
return props.theme.secondaryBtnActBgd;
}, function (props) {
return props.theme.secondaryBtnActColor;
});
var StyledMapControlPanel = _styledComponents["default"].div(_templateObject4(), function (props) {
return props.theme.mapPanelBackgroundColor;
});
var StyledMapControlPanelContent = _styledComponents["default"].div(_templateObject5(), function (props) {
return props.theme.dropdownScrollBar;
});
var StyledMapSearchPanelContent = _styledComponents["default"].div(_templateObject6(), function (props) {
return props.theme.dropdownScrollBar;
});
var StyledMapControlPanelHeader = _styledComponents["default"].div(_templateObject7(), function (props) {
return props.theme.mapPanelHeaderBackgroundColor;
}, function (props) {
return props.theme.secondaryBtnColor;
});
/**
* Generates all layers available for the current map
* TODO: this may be moved into map-container or map-control or even at the reducer level
* @param layers
* @param mapLayers
* @returns {[id, label, isVisible]}
*/
var layerSelector = function layerSelector(layers, mapLayers) {
var availableItems = Object.keys(layers).reduce(function (availableLayers, currentLayerId) {
// is available ? if yes add to available list
var currentLayer = layers[currentLayerId]; // if maplayers exists we need to make sure currentlayer
// is contained in mapLayers in order to add onto availableLayers
// otherwise we add all layers
var layerConfig = mapLayers ? mapLayers[currentLayer.id] : currentLayer.config;
var mustBeAdded = mapLayers && mapLayers[currentLayer.id] ? mapLayers[currentLayer.id].isAvailable : layerConfig.isVisible;
return mustBeAdded ? [].concat((0, _toConsumableArray2["default"])(availableLayers), [{
id: currentLayer.id,
name: currentLayer.config.label,
isVisible: mapLayers && mapLayers[currentLayer.id] ? mapLayers[currentLayer.id].isVisible : layerConfig.isVisible,
layer: currentLayer
}]) : availableLayers;
}, []);
return availableItems;
};
var MapControl =
/*#__PURE__*/
function (_Component) {
(0, _inherits2["default"])(MapControl, _Component);
function MapControl() {
var _getPrototypeOf2;
var _this;
(0, _classCallCheck2["default"])(this, MapControl);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = (0, _possibleConstructorReturn2["default"])(this, (_getPrototypeOf2 = (0, _getPrototypeOf3["default"])(MapControl)).call.apply(_getPrototypeOf2, [this].concat(args)));
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "layerSelector", function (state) {
return state.layers;
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "mapLayersSelector", function (state) {
return state.mapLayers;
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "initialDataSelector", (0, _reselect.createSelector)(_this.layerSelector, _this.mapLayersSelector, layerSelector));
return _this;
}
(0, _createClass2["default"])(MapControl, [{
key: "render",
value: function render() {
var items = this.initialDataSelector(this.props);
if (!items) {
return null;
}
var _this$props = this.props,
dragRotate = _this$props.dragRotate,
isSplit = _this$props.isSplit,
isExport = _this$props.isExport,
mapIndex = _this$props.mapIndex,
mapControls = _this$props.mapControls,
onTogglePerspective = _this$props.onTogglePerspective,
onToggleSplitMap = _this$props.onToggleSplitMap,
onMapToggleLayer = _this$props.onMapToggleLayer,
onToggleMapControl = _this$props.onToggleMapControl,
scale = _this$props.scale,
fitBounds = _this$props.fitBounds;
var _mapControls$visibleL = mapControls.visibleLayers,
visibleLayers = _mapControls$visibleL === void 0 ? {} : _mapControls$visibleL,
_mapControls$mapLegen = mapControls.mapLegend,
mapLegend = _mapControls$mapLegen === void 0 ? {} : _mapControls$mapLegen,
_mapControls$toggle3d = mapControls.toggle3d,
toggle3d = _mapControls$toggle3d === void 0 ? {} : _mapControls$toggle3d,
_mapControls$splitMap = mapControls.splitMap,
splitMap = _mapControls$splitMap === void 0 ? {} : _mapControls$splitMap,
_mapControls$searchMa = mapControls.searchMap,
searchMap = _mapControls$searchMa === void 0 ? {} : _mapControls$searchMa;
return _react["default"].createElement(StyledMapControl, {
className: "map-control"
}, splitMap.show ? _react["default"].createElement(ActionPanel, {
key: 0
}, _react["default"].createElement(StyledMapControlButton, {
active: isSplit,
onClick: function onClick(e) {
e.preventDefault();
onToggleSplitMap(isSplit ? mapIndex : undefined);
},
key: "split-".concat(isSplit),
className: "map-control-button split-map",
"data-tip": true,
"data-for": "action-toggle"
}, isSplit ? _react["default"].createElement(_icons.Delete, {
height: "18px"
}) : _react["default"].createElement(_icons.Split, {
height: "18px"
}), _react["default"].createElement(MapLegendTooltip, {
id: "action-toggle",
message: isSplit ? 'Close current panel' : 'Switch to dual map view'
}))) : null, isSplit && visibleLayers.show ? _react["default"].createElement(ActionPanel, {
key: 1
}, _react["default"].createElement(LayerSelectorPanel, {
items: items,
onMapToggleLayer: onMapToggleLayer,
isActive: visibleLayers.active,
toggleMenuPanel: function toggleMenuPanel() {
return onToggleMapControl('visibleLayers');
}
})) : null, toggle3d.show ? _react["default"].createElement(ActionPanel, {
key: 2
}, _react["default"].createElement(StyledMapControlButton, {
onClick: function onClick(e) {
e.preventDefault();
onTogglePerspective();
},
active: dragRotate,
"data-tip": true,
"data-for": "action-3d"
}, _react["default"].createElement(_icons.Cube3d, {
height: "22px"
}), _react["default"].createElement(MapLegendTooltip, {
id: "action-3d",
message: dragRotate ? 'Disable 3D Map' : '3D Map'
}))) : null, mapLegend.show ? _react["default"].createElement(ActionPanel, {
key: 3
}, _react["default"].createElement(MapLegendPanel, {
items: items,
scale: scale,
isExport: isExport,
onMapToggleLayer: onMapToggleLayer,
isActive: mapLegend.active,
toggleMenuPanel: function toggleMenuPanel() {
return onToggleMapControl('mapLegend');
}
})) : null, searchMap.show ? _react["default"].createElement(ActionPanel, {
key: 4
}, _react["default"].createElement(SearchMap, {
isActive: searchMap.active,
fitBounds: fitBounds,
toggleMenuPanel: function toggleMenuPanel() {
return onToggleMapControl('searchMap');
}
})) : null);
}
}]);
return MapControl;
}(_react.Component);
exports.MapControl = MapControl;
(0, _defineProperty2["default"])(MapControl, "propTypes", {
datasets: _propTypes["default"].object.isRequired,
dragRotate: _propTypes["default"].bool.isRequired,
isSplit: _propTypes["default"].bool.isRequired,
layers: _propTypes["default"].arrayOf(_propTypes["default"].object),
mapIndex: _propTypes["default"].number.isRequired,
mapControls: _propTypes["default"].object.isRequired,
onToggleFullScreen: _propTypes["default"].func.isRequired,
onTogglePerspective: _propTypes["default"].func.isRequired,
onToggleSplitMap: _propTypes["default"].func.isRequired,
onToggleMapControl: _propTypes["default"].func.isRequired,
onMapToggleLayer: _propTypes["default"].func.isRequired,
top: _propTypes["default"].number.isRequired,
// optional
scale: _propTypes["default"].number,
mapLayers: _propTypes["default"].object
});
(0, _defineProperty2["default"])(MapControl, "defaultProps", {
isSplit: false,
top: 0
});
var MapControlPanel = function MapControlPanel(_ref) {
var children = _ref.children,
header = _ref.header,
onClick = _ref.onClick,
_ref$scale = _ref.scale,
scale = _ref$scale === void 0 ? 1 : _ref$scale,
isExport = _ref.isExport;
return _react["default"].createElement(StyledMapControlPanel, {
style: {
transform: "scale(".concat(scale, ") translate(calc(-").concat(25 * (scale - 1), "% - ").concat(10 * scale, "px), calc(").concat(25 * (scale - 1), "% + ").concat(10 * scale, "px))")
}
}, _react["default"].createElement(StyledMapControlPanelHeader, {
style: {
position: 'relative'
}
}, isExport ? _react["default"].createElement(_logo["default"], {
version: false,
appName: "kepler.gl"
}) : _react["default"].createElement("span", {
style: {
verticalAlign: 'middle'
}
}, header), isExport ? null : _react["default"].createElement(_styledComponents2.IconRoundSmall, null, _react["default"].createElement(_icons.Close, {
height: "16px",
onClick: onClick
}))), _react["default"].createElement(StyledMapControlPanelContent, null, children));
};
var MapSearchPanel = function MapSearchPanel(_ref2) {
var children = _ref2.children,
header = _ref2.header,
onClick = _ref2.onClick,
_ref2$scale = _ref2.scale,
scale = _ref2$scale === void 0 ? 1 : _ref2$scale,
isExport = _ref2.isExport;
return _react["default"].createElement(StyledMapControlPanel, {
style: {
transform: "scale(".concat(scale, ") translate(calc(-").concat(25 * (scale - 1), "% - ").concat(10 * scale, "px), calc(").concat(25 * (scale - 1), "% + ").concat(10 * scale, "px))")
}
}, _react["default"].createElement(StyledMapControlPanelHeader, {
style: {
position: 'relative'
}
}, isExport ? _react["default"].createElement(_logo["default"], {
version: false,
appName: "kepler.gl"
}) : _react["default"].createElement("span", {
style: {
verticalAlign: 'middle'
}
}, header), isExport ? null : _react["default"].createElement(_styledComponents2.IconRoundSmall, null, _react["default"].createElement(_icons.Close, {
height: "16px",
onClick: onClick
}))), _react["default"].createElement(StyledMapSearchPanelContent, null, children));
};
var MapLegendPanel = function MapLegendPanel(_ref3) {
var items = _ref3.items,
isActive = _ref3.isActive,
scale = _ref3.scale,
toggleMenuPanel = _ref3.toggleMenuPanel,
isExport = _ref3.isExport;
return !isActive ? _react["default"].createElement(StyledMapControlButton, {
key: 2,
"data-tip": true,
"data-for": "show-legend",
className: "map-control-button show-legend",
onClick: function onClick(e) {
e.preventDefault();
toggleMenuPanel();
}
}, _react["default"].createElement(_icons.Legend, {
height: "22px"
}), _react["default"].createElement(MapLegendTooltip, {
id: "show-legend",
message: 'show legend'
})) : _react["default"].createElement(MapControlPanel, {
scale: scale,
header: 'Layer Legend',
onClick: toggleMenuPanel,
isExport: isExport
}, _react["default"].createElement(_mapLegend["default"], {
layers: items.filter(function (item) {
return item.isVisible;
}).map(function (item) {
return item.layer;
})
}));
};
var SearchMap = function SearchMap(_ref4) {
var isActive = _ref4.isActive,
fitBounds = _ref4.fitBounds,
toggleMenuPanel = _ref4.toggleMenuPanel;
return !isActive ? _react["default"].createElement(StyledMapControlButton, {
key: 4,
"data-tip": true,
"data-for": "show-search",
className: "map-control-button show-search",
onClick: function onClick(e) {
e.preventDefault();
toggleMenuPanel();
}
}, _react["default"].createElement(_icons.Search, {
height: "22px"
}), _react["default"].createElement(MapLegendTooltip, {
id: "search-map",
message: 'search map'
})) : _react["default"].createElement(MapSearchPanel, {
header: 'Search Map',
onClick: toggleMenuPanel
}, _react["default"].createElement(_reactGeosuggest["default"], {
className: 'geosuggest',
inputClassName: 'geosuggest__input',
style: {
suggestItem: {
fontSize: 'x-small'
}
},
placeholder: 'Search map',
minLength: 1,
onSuggestSelect: function onSuggestSelect(suggest) {
return _onSuggestSelect(suggest, fitBounds);
}
}));
};
var _onSuggestSelect = function _onSuggestSelect(suggest, fitBounds) {
var minLat = suggest.gmaps.geometry.viewport.pa.g;
var minLng = suggest.gmaps.geometry.viewport.ka.g;
var maxLat = suggest.gmaps.geometry.viewport.pa.h;
var maxLng = suggest.gmaps.geometry.viewport.ka.h;
fitBounds([minLng, minLat, maxLng, maxLat]);
};
var LayerSelectorPanel = function LayerSelectorPanel(_ref5) {
var items = _ref5.items,
onMapToggleLayer = _ref5.onMapToggleLayer,
isActive = _ref5.isActive,
toggleMenuPanel = _ref5.toggleMenuPanel;
return !isActive ? _react["default"].createElement(StyledMapControlButton, {
key: 1,
onClick: function onClick(e) {
e.preventDefault();
toggleMenuPanel();
},
className: "map-control-button toggle-layer",
"data-tip": true,
"data-for": "toggle-layer"
}, _react["default"].createElement(_icons.Layers, {
height: "22px"
}), _react["default"].createElement(MapLegendTooltip, {
id: "toggle-layer",
message: isActive ? 'Hide layer panel' : 'Show layer panel'
})) : _react["default"].createElement(MapControlPanel, {
header: "Visible layers",
onClick: toggleMenuPanel
}, _react["default"].createElement(_mapLayerSelector["default"], {
layers: items,
onMapToggleLayer: onMapToggleLayer
}));
};
var ActionPanel = function ActionPanel(_ref6) {
var children = _ref6.children;
return _react["default"].createElement(StyledMapControlAction, null, children);
};
var MapLegendTooltip = function MapLegendTooltip(_ref7) {
var id = _ref7.id,
message = _ref7.message;
return _react["default"].createElement(_styledComponents2.Tooltip, {
id: id,
place: "left",
effect: "solid"
}, _react["default"].createElement("span", null, message));
};
var MapControlFactory = function MapControlFactory() {
return MapControl;
};
var _default = MapControlFactory;
exports["default"] = _default;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21wb25lbnRzL21hcC9tYXAtY29udHJvbC5qcyJdLCJuYW1lcyI6WyJTdHlsZWRNYXBDb250cm9sIiwic3R5bGVkIiwiZGl2IiwicHJvcHMiLCJ0aGVtZSIsIm1hcENvbnRyb2wiLCJ3aWR0aCIsInBhZGRpbmciLCJ0b3AiLCJTdHlsZWRNYXBDb250cm9sQWN0aW9uIiwiU3R5bGVkTWFwQ29udHJvbEJ1dHRvbiIsImFjdGl2ZSIsInNlY29uZGFyeUJ0bkFjdEJnZCIsInNlY29uZGFyeUJ0bkJnZCIsInNlY29uZGFyeUJ0bkFjdENvbG9yIiwic2Vjb25kYXJ5QnRuQ29sb3IiLCJ0cmFuc2l0aW9uIiwiU3R5bGVkTWFwQ29udHJvbFBhbmVsIiwibWFwUGFuZWxCYWNrZ3JvdW5kQ29sb3IiLCJTdHlsZWRNYXBDb250cm9sUGFuZWxDb250ZW50IiwiZHJvcGRvd25TY3JvbGxCYXIiLCJTdHlsZWRNYXBTZWFyY2hQYW5lbENvbnRlbnQiLCJTdHlsZWRNYXBDb250cm9sUGFuZWxIZWFkZXIiLCJtYXBQYW5lbEhlYWRlckJhY2tncm91bmRDb2xvciIsImxheWVyU2VsZWN0b3IiLCJsYXllcnMiLCJtYXBMYXllcnMiLCJhdmFpbGFibGVJdGVtcyIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJhdmFpbGFibGVMYXllcnMiLCJjdXJyZW50TGF5ZXJJZCIsImN1cnJlbnRMYXllciIsImxheWVyQ29uZmlnIiwiaWQiLCJjb25maWciLCJtdXN0QmVBZGRlZCIsImlzQXZhaWxhYmxlIiwiaXNWaXNpYmxlIiwibmFtZSIsImxhYmVsIiwibGF5ZXIiLCJNYXBDb250cm9sIiwic3RhdGUiLCJtYXBMYXllcnNTZWxlY3RvciIsIml0ZW1zIiwiaW5pdGlhbERhdGFTZWxlY3RvciIsImRyYWdSb3RhdGUiLCJpc1NwbGl0IiwiaXNFeHBvcnQiLCJtYXBJbmRleCIsIm1hcENvbnRyb2xzIiwib25Ub2dnbGVQZXJzcGVjdGl2ZSIsIm9uVG9nZ2xlU3BsaXRNYXAiLCJvbk1hcFRvZ2dsZUxheWVyIiwib25Ub2dnbGVNYXBDb250cm9sIiwic2NhbGUiLCJmaXRCb3VuZHMiLCJ2aXNpYmxlTGF5ZXJzIiwibWFwTGVnZW5kIiwidG9nZ2xlM2QiLCJzcGxpdE1hcCIsInNlYXJjaE1hcCIsInNob3ciLCJlIiwicHJldmVudERlZmF1bHQiLCJ1bmRlZmluZWQiLCJDb21wb25lbnQiLCJkYXRhc2V0cyIsIlByb3BUeXBlcyIsIm9iamVjdCIsImlzUmVxdWlyZWQiLCJib29sIiwiYXJyYXlPZiIsIm51bWJlciIsIm9uVG9nZ2xlRnVsbFNjcmVlbiIsImZ1bmMiLCJNYXBDb250cm9sUGFuZWwiLCJjaGlsZHJlbiIsImhlYWRlciIsIm9uQ2xpY2siLCJ0cmFuc2Zvcm0iLCJwb3NpdGlvbiIsInZlcnRpY2FsQWxpZ24iLCJNYXBTZWFyY2hQYW5lbCIsIk1hcExlZ2VuZFBhbmVsIiwiaXNBY3RpdmUiLCJ0b2dnbGVNZW51UGFuZWwiLCJmaWx0ZXIiLCJpdGVtIiwibWFwIiwiU2VhcmNoTWFwIiwic3VnZ2VzdEl0ZW0iLCJmb250U2l6ZSIsInN1Z2dlc3QiLCJvblN1Z2dlc3RTZWxlY3QiLCJtaW5MYXQiLCJnbWFwcyIsImdlb21ldHJ5Iiwidmlld3BvcnQiLCJwYSIsImciLCJtaW5MbmciLCJrYSIsIm1heExhdCIsImgiLCJtYXhMbmciLCJMYXllclNlbGVjdG9yUGFuZWwiLCJBY3Rpb25QYW5lbCIsIk1hcExlZ2VuZFRvb2x0aXAiLCJtZXNzYWdlIiwiTWFwQ29udHJvbEZhY3RvcnkiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQVNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSxJQUFNQSxnQkFBZ0IsR0FBR0MsNkJBQU9DLEdBQVYsb0JB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WjtBQU9FLG9CQVBGO0FBUUUsZ0JBQVM7QUFSWCxLQVVFLGdDQUFDLGFBQUQ7QUFBUSxJQUFBLE1BQU0sRUFBQztBQUFmLElBVkYsRUFXRSxnQ0FBQyxnQkFBRDtBQUNFLElBQUEsRUFBRSxFQUFDLGNBREw7QUFFRSxJQUFBLE9BQU8sRUFBRUQsUUFBUSxHQUFHLGtCQUFILEdBQXdCO0FBRjNDLElBWEYsQ0FERixHQWtCRSxnQ0FBQyxlQUFEO0FBQWlCLElBQUEsTUFBTSxFQUFDLGdCQUF4QjtBQUF5QyxJQUFBLE9BQU8sRUFBRUM7QUFBbEQsS0FDRSxnQ0FBQyw0QkFBRDtBQUFrQixJQUFBLE1BQU0sRUFBRTFDLEtBQTFCO0FBQWlDLElBQUEsZ0JBQWdCLEVBQUVTO0FBQW5ELElBREYsQ0F4QnVCO0FBQUEsQ0FBM0I7O0FBNkJBLElBQU1zRCxXQUFXLEdBQUcsU0FBZEEsV0FBYztBQUFBLE1BQUU5QixRQUFGLFNBQUVBLFFBQUY7QUFBQSxTQUNsQixnQ0FBQyxzQkFBRCxRQUF5QkEsUUFBekIsQ0FEa0I7QUFBQSxDQUFwQjs7QUFJQSxJQUFNK0IsZ0JBQWdCLEdBQUcsU0FBbkJBLGdCQUFtQjtBQUFBLE1BQUUzRSxFQUFGLFNBQUVBLEVBQUY7QUFBQSxNQUFNNEUsT0FBTixTQUFNQSxPQUFOO0FBQUEsU0FDdkIsZ0NBQUMsMEJBQUQ7QUFBUyxJQUFBLEVBQUUsRUFBRTVFLEVBQWI7QUFBaUIsSUFBQSxLQUFLLEVBQUMsTUFBdkI7QUFBOEIsSUFBQSxNQUFNLEVBQUM7QUFBckMsS0FDRSw4Q0FBTzRFLE9BQVAsQ0FERixDQUR1QjtBQUFBLENBQXpCOztBQU1BLElBQU1DLGlCQUFpQixHQUFHLFNBQXBCQSxpQkFBb0I7QUFBQSxTQUFNckUsVUFBTjtBQUFBLENBQTFCOztlQUVlcUUsaUIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMTkgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgUmVhY3QsIHtDb21wb25lbnR9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBQcm9wVHlwZXMgZnJvbSAncHJvcC10eXBlcyc7XG5pbXBvcnQge2NyZWF0ZVNlbGVjdG9yfSBmcm9tICdyZXNlbGVjdCc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ3N0eWxlZC1jb21wb25lbnRzJztcbmltcG9ydCBHZW9zdWdnZXN0IGZyb20gJ3JlYWN0LWdlb3N1Z2dlc3QnO1xuaW1wb3J0IHtUb29sdGlwLCBJY29uUm91bmRTbWFsbH0gZnJvbSAnY29tcG9uZW50cy9jb21tb24vc3R5bGVkLWNvbXBvbmVudHMnO1xuaW1wb3J0IE1hcExheWVyU2VsZWN0b3IgZnJvbSAnY29tcG9uZW50cy9jb21tb24vbWFwLWxheWVyLXNlbGVjdG9yJztcbmltcG9ydCBLZXBsZXJHbExvZ28gZnJvbSAnY29tcG9uZW50cy9jb21tb24vbG9nbyc7XG5pbXBvcnQgTWFwTGVnZW5kIGZyb20gJy4vbWFwLWxlZ2VuZCc7XG5pbXBvcnQge1xuICBDbG9zZSxcbiAgU3BsaXQsXG4gIExlZ2VuZCxcbiAgQ3ViZTNkLFxuICBEZWxldGUsXG4gIExheWVycyxcbiAgU2VhcmNoXG59IGZyb20gJ2NvbXBvbmVudHMvY29tbW9uL2ljb25zJztcbmltcG9ydCAnLi9nZW8tc3VnZ2VzdC5jc3MnO1xuXG5jb25zdCBTdHlsZWRNYXBDb250cm9sID0gc3R5bGVkLmRpdmBcbiAgcmlnaHQ6IDA7XG4gIHdpZHRoOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLm1hcENvbnRyb2wud2lkdGh9cHg7XG4gIHBhZGRpbmc6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUubWFwQ29udHJvbC5wYWRkaW5nfXB4O1xuICB6LWluZGV4OiAxO1xuICB0b3A6ICR7cHJvcHMgPT4gcHJvcHMudG9wfXB4O1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG5gO1xuXG5jb25zdCBTdHlsZWRNYXBDb250cm9sQWN0aW9uID0gc3R5bGVkLmRpdmBcbiAgcGFkZGluZzogNHB4IDA7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7XG5gO1xuXG5jb25zdCBTdHlsZWRNYXBDb250cm9sQnV0dG9uID0gc3R5bGVkLmRpdmBcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgYmFja2dyb3VuZC1jb2xvcjogJHtwcm9wcyA9PlxuICAgIHByb3BzLmFjdGl2ZVxuICAgICAgPyBwcm9wcy50aGVtZS5zZWNvbmRhcnlCdG5BY3RCZ2RcbiAgICAgIDogcHJvcHMudGhlbWUuc2Vjb25kYXJ5QnRuQmdkfTtcbiAgYm9yZGVyLXJhZGl1czogMThweDtcbiAgYm9yZGVyOiAwO1xuICBib3gtc2hhZG93OiAwIDZweCAxMnB4IDAgcmdiYSgwLCAwLCAwLCAwLjE2KTtcbiAgY29sb3I6ICR7cHJvcHMgPT5cbiAgICBwcm9wcy5hY3RpdmVcbiAgICAgID8gcHJvcHMudGhlbWUuc2Vjb25kYXJ5QnRuQWN0Q29sb3JcbiAgICAgIDogcHJvcHMudGhlbWUuc2Vjb25kYXJ5QnRuQ29sb3J9O1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGhlaWdodDogMzZweDtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIG1hcmdpbjogMDtcbiAgb3V0bGluZTogbm9uZTtcbiAgcGFkZGluZzogMDtcbiAgdHJhbnNpdGlvbjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS50cmFuc2l0aW9ufTtcbiAgd2lkdGg6IDM2cHg7XG5cbiAgOmZvY3VzIHtcbiAgICBvdXRsaW5lOiBub25lO1xuICB9XG5cbiAgOmhvdmVyIHtcbiAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5zZWNvbmRhcnlCdG5BY3RCZ2R9O1xuICAgIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnNlY29uZGFyeUJ0bkFjdENvbG9yfTtcbiAgfVxuYDtcblxuY29uc3QgU3R5bGVkTWFwQ29udHJvbFBhbmVsID0gc3R5bGVkLmRpdmBcbiAgYmFja2dyb3VuZC1jb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5tYXBQYW5lbEJhY2tncm91bmRDb2xvcn07XG4gIGZsZXgtZ3JvdzogMTtcbiAgei1pbmRleDogMTtcbiAgcCB7XG4gICAgbWFyZ2luLWJvdHRvbTogMDtcbiAgfVxuYDtcblxuY29uc3QgU3R5bGVkTWFwQ29udHJvbFBhbmVsQ29udGVudCA9IHN0eWxlZC5kaXZgXG4gICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuZHJvcGRvd25TY3JvbGxCYXJ9IG1heC1oZWlnaHQ6IDUwMHB4O1xuICBtaW4taGVpZ2h0OiAxMDBweDtcbiAgb3ZlcmZsb3c6IGF1dG87XG5gO1xuXG5jb25zdCBTdHlsZWRNYXBTZWFyY2hQYW5lbENvbnRlbnQgPSBzdHlsZWQuZGl2YFxuICAke3Byb3BzID0+IHByb3BzLnRoZW1lLmRyb3Bkb3duU2Nyb2xsQmFyfVxuYDtcblxuY29uc3QgU3R5bGVkTWFwQ29udHJvbFBhbmVsSGVhZGVyID0gc3R5bGVkLmRpdmBcbiAgZGlzcGxheTogZmxleDtcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLm1hcFBhbmVsSGVhZGVyQmFja2dyb3VuZENvbG9yfTtcbiAgaGVpZ2h0OiAzMnB4O1xuICBwYWRkaW5nOiA2cHggMTJweDtcbiAgZm9udC1zaXplOiAxMXB4O1xuICBjb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5zZWNvbmRhcnlCdG5Db2xvcn07XG5cbiAgYnV0dG9uIHtcbiAgICB3aWR0aDogMThweDtcbiAgICBoZWlnaHQ6IDE4cHg7XG4gIH1cbmA7XG5cbi8qKlxuICogR2VuZXJhdGVzIGFsbCBsYXllcnMgYXZhaWxhYmxlIGZvciB0aGUgY3VycmVudCBtYXBcbiAqIFRPRE86IHRoaXMgbWF5IGJlIG1vdmVkIGludG8gbWFwLWNvbnRhaW5lciBvciBtYXAtY29udHJvbCBvciBldmVuIGF0IHRoZSByZWR1Y2VyIGxldmVsXG4gKiBAcGFyYW0gbGF5ZXJzXG4gKiBAcGFyYW0gbWFwTGF5ZXJzXG4gKiBAcmV0dXJucyB7W2lkLCBsYWJlbCwgaXNWaXNpYmxlXX1cbiAqL1xuY29uc3QgbGF5ZXJTZWxlY3RvciA9IChsYXllcnMsIG1hcExheWVycykgPT4ge1xuICBjb25zdCBhdmFpbGFibGVJdGVtcyA9IE9iamVjdC5rZXlzKGxheWVycykucmVkdWNlKFxuICAgIChhdmFpbGFibGVMYXllcnMsIGN1cnJlbnRMYXllcklkKSA9PiB7XG4gICAgICAvLyBpcyBhdmFpbGFibGUgPyBpZiB5ZXMgYWRkIHRvIGF2YWlsYWJsZSBsaXN0XG4gICAgICBjb25zdCBjdXJyZW50TGF5ZXIgPSBsYXllcnNbY3VycmVudExheWVySWRdO1xuICAgICAgLy8gaWYgbWFwbGF5ZXJzIGV4aXN0cyB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSBjdXJyZW50bGF5ZXJcbiAgICAgIC8vIGlzIGNvbnRhaW5lZCBpbiBtYXBMYXllcnMgaW4gb3JkZXIgdG8gYWRkIG9udG8gYXZhaWxhYmxlTGF5ZXJzXG4gICAgICAvLyBvdGhlcndpc2Ugd2UgYWRkIGFsbCBsYXllcnNcblxuICAgICAgY29uc3QgbGF5ZXJDb25maWcgPSBtYXBMYXllcnNcbiAgICAgICAgPyBtYXBMYXllcnNbY3VycmVudExheWVyLmlkXVxuICAgICAgICA6IGN1cnJlbnRMYXllci5jb25maWc7XG5cbiAgICAgIGNvbnN0IG11c3RCZUFkZGVkID1cbiAgICAgICAgbWFwTGF5ZXJzICYmIG1hcExheWVyc1tjdXJyZW50TGF5ZXIuaWRdXG4gICAgICAgICAgPyBtYXBMYXllcnNbY3VycmVudExheWVyLmlkXS5pc0F2YWlsYWJsZVxuICAgICAgICAgIDogbGF5ZXJDb25maWcuaXNWaXNpYmxlO1xuXG4gICAgICByZXR1cm4gbXVzdEJlQWRkZWRcbiAgICAgICAgPyBbXG4gICAgICAgICAgICAuLi5hdmFpbGFibGVMYXllcnMsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGlkOiBjdXJyZW50TGF5ZXIuaWQsXG4gICAgICAgICAgICAgIG5hbWU6IGN1cnJlbnRMYXllci5jb25maWcubGFiZWwsXG4gICAgICAgICAgICAgIGlzVmlzaWJsZTpcbiAgICAgICAgICAgICAgICBtYXBMYXllcnMgJiYgbWFwTGF5ZXJzW2N1cnJlbnRMYXllci5pZF1cbiAgICAgICAgICAgICAgICAgID8gbWFwTGF5ZXJzW2N1cnJlbnRMYXllci5pZF0uaXNWaXNpYmxlXG4gICAgICAgICAgICAgICAgICA6IGxheWVyQ29uZmlnLmlzVmlzaWJsZSxcbiAgICAgICAgICAgICAgbGF5ZXI6IGN1cnJlbnRMYXllclxuICAgICAgICAgICAgfVxuICAgICAgICAgIF1cbiAgICAgICAgOiBhdmFpbGFibGVMYXllcnM7XG4gICAgfSxcbiAgICBbXVxuICApO1xuXG4gIHJldHVybiBhdmFpbGFibGVJdGVtcztcbn07XG5cbmV4cG9ydCBjbGFzcyBNYXBDb250cm9sIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgc3RhdGljIHByb3BUeXBlcyA9IHtcbiAgICBkYXRhc2V0czogUHJvcFR5cGVzLm9iamVjdC5pc1JlcXVpcmVkLFxuICAgIGRyYWdSb3RhdGU6IFByb3BUeXBlcy5ib29sLmlzUmVxdWlyZWQsXG4gICAgaXNTcGxpdDogUHJvcFR5cGVzLmJvb2wuaXNSZXF1aXJlZCxcbiAgICBsYXllcnM6IFByb3BUeXBlcy5hcnJheU9mKFByb3BUeXBlcy5vYmplY3QpLFxuICAgIG1hcEluZGV4OiBQcm9wVHlwZXMubnVtYmVyLmlzUmVxdWlyZWQsXG4gICAgbWFwQ29udHJvbHM6IFByb3BUeXBlcy5vYmplY3QuaXNSZXF1aXJlZCxcbiAgICBvblRvZ2dsZUZ1bGxTY3JlZW46IFByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG4gICAgb25Ub2dnbGVQZXJzcGVjdGl2ZTogUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcbiAgICBvblRvZ2dsZVNwbGl0TWFwOiBQcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuICAgIG9uVG9nZ2xlTWFwQ29udHJvbDogUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcbiAgICBvbk1hcFRvZ2dsZUxheWVyOiBQcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuICAgIHRvcDogUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuXG4gICAgLy8gb3B0aW9uYWxcbiAgICBzY2FsZTogUHJvcFR5cGVzLm51bWJlcixcbiAgICBtYXBMYXllcnM6IFByb3BUeXBlcy5vYmplY3RcbiAgfTtcblxuICBzdGF0aWMgZGVmYXVsdFByb3BzID0ge1xuICAgIGlzU3BsaXQ6IGZhbHNlLFxuICAgIHRvcDogMFxuICB9O1xuXG4gIGxheWVyU2VsZWN0b3IgPSBzdGF0ZSA9PiBzdGF0ZS5sYXllcnM7XG4gIG1hcExheWVyc1NlbGVjdG9yID0gc3RhdGUgPT4gc3RhdGUubWFwTGF5ZXJzO1xuXG4gIGluaXRpYWxEYXRhU2VsZWN0b3IgPSBjcmVhdGVTZWxlY3RvcihcbiAgICB0aGlzLmxheWVyU2VsZWN0b3IsXG4gICAgdGhpcy5tYXBMYXllcnNTZWxlY3RvcixcbiAgICBsYXllclNlbGVjdG9yXG4gICk7XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5pbml0aWFsRGF0YVNlbGVjdG9yKHRoaXMucHJvcHMpO1xuXG4gICAgaWYgKCFpdGVtcykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3Qge1xuICAgICAgZHJhZ1JvdGF0ZSxcbiAgICAgIGlzU3BsaXQsXG4gICAgICBpc0V4cG9ydCxcbiAgICAgIG1hcEluZGV4LFxuICAgICAgbWFwQ29udHJvbHMsXG4gICAgICBvblRvZ2dsZVBlcnNwZWN0aXZlLFxuICAgICAgb25Ub2dnbGVTcGxpdE1hcCxcbiAgICAgIG9uTWFwVG9nZ2xlTGF5ZXIsXG4gICAgICBvblRvZ2dsZU1hcENvbnRyb2wsXG4gICAgICBzY2FsZSxcbiAgICAgIGZpdEJvdW5kc1xuICAgIH0gPSB0aGlzLnByb3BzO1xuXG4gICAgY29uc3Qge1xuICAgICAgdmlzaWJsZUxheWVycyA9IHt9LFxuICAgICAgbWFwTGVnZW5kID0ge30sXG4gICAgICB0b2dnbGUzZCA9IHt9LFxuICAgICAgc3BsaXRNYXAgPSB7fSxcbiAgICAgIHNlYXJjaE1hcCA9IHt9XG4gICAgfSA9IG1hcENvbnRyb2xzO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIDxTdHlsZWRNYXBDb250cm9sIGNsYXNzTmFtZT1cIm1hcC1jb250cm9sXCI+XG4gICAgICAgIHsvKiBTcGxpdCBNYXAgKi99XG4gICAgICAgIHtzcGxpdE1hcC5zaG93ID8gKFxuICAgICAgICAgIDxBY3Rpb25QYW5lbCBrZXk9ezB9PlxuICAgICAgICAgICAgPFN0eWxlZE1hcENvbnRyb2xCdXR0b25cbiAgICAgICAgICAgICAgYWN0aXZlPXtpc1NwbGl0fVxuICAgICAgICAgICAgICBvbkNsaWNrPXtlID0+IHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgb25Ub2dnbGVTcGxpdE1hcChpc1NwbGl0ID8gbWFwSW5kZXggOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICBrZXk9e2BzcGxpdC0ke2lzU3BsaXR9YH1cbiAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibWFwLWNvbnRyb2wtYnV0dG9uIHNwbGl0LW1hcFwiXG4gICAgICAgICAgICAgIGRhdGEtdGlwXG4gICAgICAgICAgICAgIGRhdGEtZm9yPVwiYWN0aW9uLXRvZ2dsZVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHtpc1NwbGl0ID8gPERlbGV0ZSBoZWlnaHQ9XCIxOHB4XCIgLz4gOiA8U3BsaXQgaGVpZ2h0PVwiMThweFwiIC8+fVxuICAgICAgICAgICAgICA8TWFwTGVnZW5kVG9vbHRpcFxuICAgICAgICAgICAgICAgIGlkPVwiYWN0aW9uLXRvZ2dsZVwiXG4gICAgICAgICAgICAgICAgbWVzc2FnZT17XG4gICAgICAgICAgICAgICAgICBpc1NwbGl0ID8gJ0Nsb3NlIGN1cnJlbnQgcGFuZWwnIDogJ1N3aXRjaCB0byBkdWFsIG1hcCB2aWV3J1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDwvU3R5bGVkTWFwQ29udHJvbEJ1dHRvbj5cbiAgICAgICAgICA8L0FjdGlvblBhbmVsPlxuICAgICAgICApIDogbnVsbH1cblxuICAgICAgICB7LyogTWFwIExheWVycyAqL31cbiAgICAgICAge2lzU3BsaXQgJiYgdmlzaWJsZUxheWVycy5zaG93ID8gKFxuICAgICAgICAgIDxBY3Rpb25QYW5lbCBrZXk9ezF9PlxuICAgICAgICAgICAgPExheWVyU2VsZWN0b3JQYW5lbFxuICAgICAgICAgICAgICBpdGVtcz17aXRlbXN9XG4gICAgICAgICAgICAgIG9uTWFwVG9nZ2xlTGF5ZXI9e29uTWFwVG9nZ2xlTGF5ZXJ9XG4gICAgICAgICAgICAgIGlzQWN0aXZlPXt2aXNpYmxlTGF5ZXJzLmFjdGl2ZX1cbiAgICAgICAgICAgICAgdG9nZ2xlTWVudVBhbmVsPXsoKSA9PiBvblRvZ2dsZU1hcENvbnRyb2woJ3Zpc2libGVMYXllcnMnKX1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9BY3Rpb25QYW5lbD5cbiAgICAgICAgKSA6IG51bGx9XG5cbiAgICAgICAgey8qIDNEIE1hcCAqL31cbiAgICAgICAge3RvZ2dsZTNkLnNob3cgPyAoXG4gICAgICAgICAgPEFjdGlvblBhbmVsIGtleT17Mn0+XG4gICAgICAgICAgICA8U3R5bGVkTWFwQ29udHJvbEJ1dHRvblxuICAgICAgICAgICAgICBvbkNsaWNrPXtlID0+IHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgb25Ub2dnbGVQZXJzcGVjdGl2ZSgpO1xuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICBhY3RpdmU9e2RyYWdSb3RhdGV9XG4gICAgICAgICAgICAgIGRhdGEtdGlwXG4gICAgICAgICAgICAgIGRhdGEtZm9yPVwiYWN0aW9uLTNkXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPEN1YmUzZCBoZWlnaHQ9XCIyMnB4XCIgLz5cbiAgICAgICAgICAgICAgey8qIE5vIGljb24gc2luY2Ugd2UgYXJlIGluamVjdGluZyB0aHJvdWdoIGNzcyAudGhyZWVELW1hcCBjbGFzcyovfVxuICAgICAgICAgICAgICA8TWFwTGVnZW5kVG9vbHRpcFxuICAgICAgICAgICAgICAgIGlkPVwiYWN0aW9uLTNkXCJcbiAgICAgICAgICAgICAgICBtZXNzYWdlPXtkcmFnUm90YXRlID8gJ0Rpc2FibGUgM0QgTWFwJyA6ICczRCBNYXAnfVxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgPC9TdHlsZWRNYXBDb250cm9sQnV0dG9uPlxuICAgICAgICAgIDwvQWN0aW9uUGFuZWw+XG4gICAgICAgICkgOiBudWxsfVxuXG4gICAgICAgIHsvKiBNYXAgTGVnZW5kICovfVxuICAgICAgICB7bWFwTGVnZW5kLnNob3cgPyAoXG4gICAgICAgICAgPEFjdGlvblBhbmVsIGtleT17M30+XG4gICAgICAgICAgICA8TWFwTGVnZW5kUGFuZWxcbiAgICAgICAgICAgICAgaXRlbXM9e2l0ZW1zfVxuICAgICAgICAgICAgICBzY2FsZT17c2NhbGV9XG4gICAgICAgICAgICAgIGlzRXhwb3J0PXtpc0V4cG9ydH1cbiAgICAgICAgICAgICAgb25NYXBUb2dnbGVMYXllcj17b25NYXBUb2dnbGVMYXllcn1cbiAgICAgICAgICAgICAgaXNBY3RpdmU9e21hcExlZ2VuZC5hY3RpdmV9XG4gICAgICAgICAgICAgIHRvZ2dsZU1lbnVQYW5lbD17KCkgPT4gb25Ub2dnbGVNYXBDb250cm9sKCdtYXBMZWdlbmQnKX1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9BY3Rpb25QYW5lbD5cbiAgICAgICAgKSA6IG51bGx9XG5cbiAgICAgICAgey8qIE1hcCBMZWdlbmQgKi99XG4gICAgICAgIHtzZWFyY2hNYXAuc2hvdyA/IChcbiAgICAgICAgICA8QWN0aW9uUGFuZWwga2V5PXs0fT5cbiAgICAgICAgICAgIDxTZWFyY2hNYXBcbiAgICAgICAgICAgICAgaXNBY3RpdmU9e3NlYXJjaE1hcC5hY3RpdmV9XG4gICAgICAgICAgICAgIGZpdEJvdW5kcz17Zml0Qm91bmRzfVxuICAgICAgICAgICAgICB0b2dnbGVNZW51UGFuZWw9eygpID0+IG9uVG9nZ2xlTWFwQ29udHJvbCgnc2VhcmNoTWFwJyl9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvQWN0aW9uUGFuZWw+XG4gICAgICAgICkgOiBudWxsfVxuICAgICAgPC9TdHlsZWRNYXBDb250cm9sPlxuICAgICk7XG4gIH1cbn1cblxuY29uc3QgTWFwQ29udHJvbFBhbmVsID0gKHtjaGlsZHJlbiwgaGVhZGVyLCBvbkNsaWNrLCBzY2FsZSA9IDEsIGlzRXhwb3J0fSkgPT4gKFxuICA8U3R5bGVkTWFwQ29udHJvbFBhbmVsXG4gICAgc3R5bGU9e3tcbiAgICAgIHRyYW5zZm9ybTogYHNjYWxlKCR7c2NhbGV9KSB0cmFuc2xhdGUoY2FsYygtJHsyNSAqIChzY2FsZSAtIDEpfSUgLSAkezEwICpcbiAgICAgICAgc2NhbGV9cHgpLCBjYWxjKCR7MjUgKiAoc2NhbGUgLSAxKX0lICsgJHsxMCAqIHNjYWxlfXB4KSlgXG4gICAgfX1cbiAgPlxuICAgIDxTdHlsZWRNYXBDb250cm9sUGFuZWxIZWFkZXIgc3R5bGU9e3twb3NpdGlvbjogJ3JlbGF0aXZlJ319PlxuICAgICAge2lzRXhwb3J0ID8gKFxuICAgICAgICA8S2VwbGVyR2xMb2dvIHZlcnNpb249e2ZhbHNlfSBhcHBOYW1lPVwia2VwbGVyLmdsXCIgLz5cbiAgICAgICkgOiAoXG4gICAgICAgIDxzcGFuIHN0eWxlPXt7dmVydGljYWxBbGlnbjogJ21pZGRsZSd9fT57aGVhZGVyfTwvc3Bhbj5cbiAgICAgICl9XG4gICAgICB7aXNFeHBvcnQgPyBudWxsIDogKFxuICAgICAgICA8SWNvblJvdW5kU21hbGw+XG4gICAgICAgICAgPENsb3NlIGhlaWdodD1cIjE2cHhcIiBvbkNsaWNrPXtvbkNsaWNrfSAvPlxuICAgICAgICA8L0ljb25Sb3VuZFNtYWxsPlxuICAgICAgKX1cbiAgI