UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

353 lines (351 loc) 59.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.AiAssistantConfig = AiAssistantConfig; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral")); var _react = _interopRequireWildcard(require("react")); var _styledComponents = _interopRequireDefault(require("styled-components")); var _reactRedux = require("react-redux"); var _components = require("@kepler.gl/components"); var _apiKey = _interopRequireDefault(require("../icons/api-key")); var _models = require("../config/models"); var _usehooksTs = require("usehooks-ts"); var _core = require("@openassistant/core"); var _actions = require("../actions"); var _reactIntl = require("react-intl"); var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8; // 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; } var SectionTitle = _styledComponents["default"].div(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2["default"])(["\n font-size: ", ";\n color: ", ";\n text-transform: capitalize;\n"])), function (props) { return props.theme.inputFontSize; }, function (props) { return props.theme.effectPanelTextSecondary1; }); var StyledAiAssistantConfig = _styledComponents["default"].div(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2["default"])(["\n padding: 12px;\n font-size: ", ";\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: 100%;\n height: 100%;\n\n .api-key-input {\n box-shadow: ", ";\n width: 100%;\n .api-key-input__icon {\n position: absolute;\n height: ", "px;\n width: 30px;\n padding-left: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: ", ";\n }\n\n input {\n padding: 4px 36px;\n height: ", "px;\n caret-color: unset;\n }\n }\n"])), function (props) { return props.theme.primaryBtnFontSizeDefault; }, function (props) { return props.theme.boxShadow; }, function (props) { return props.theme.geocoderInputHeight; }, function (props) { return props.theme.subtextColor; }, function (props) { return props.theme.geocoderInputHeight; }); // Ollama model input wrapper: checkbox + 'Input Model Name:' + input // all children element have width based on the content var OllamaModelInputWrapper = _styledComponents["default"].div(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2["default"])(["\n display: flex;\n flex-direction: row;\n gap: 4px;\n align-items: center;\n"]))); var StyledWrapper = _styledComponents["default"].div(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2["default"])(["\n display: flex;\n justify-content: space-between;\n align-items: center;\n"]))); var StyledItemSelector = (0, _styledComponents["default"])(_components.ItemSelector)(_templateObject5 || (_templateObject5 = (0, _taggedTemplateLiteral2["default"])(["\n .item-selector__dropdown {\n padding-left: 10px;\n border-radius: 4px;\n }\n .active {\n border-color: ", ";\n border-radius: 4px 4px 0px 0px !important;\n }\n width: 100%;\n"])), function (props) { return props.theme.activeColor; }); var StyleSliderWrapper = _styledComponents["default"].div(_templateObject6 || (_templateObject6 = (0, _taggedTemplateLiteral2["default"])(["\n width: 100%;\n align-self: flex-start;\n height: 32px;\n display: flex;\n align-items: center;\n .kg-range-slider__input {\n height: 32px;\n text-align: center;\n padding: 3px 6px;\n }\n .kg-slider {\n padding-left: 6px;\n }\n .kg-range-slider {\n padding: 0px !important;\n }\n"]))); var StyledButton = _styledComponents["default"].div(_templateObject7 || (_templateObject7 = (0, _taggedTemplateLiteral2["default"])(["\n width: 100%;\n align-self: flex-start;\n margin-top: 12px;\n\n button div {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-right: 4px;\n }\n"]))); var StyleErrorMessage = _styledComponents["default"].div(_templateObject8 || (_templateObject8 = (0, _taggedTemplateLiteral2["default"])(["\n font-size: ", ";\n background-color: ", ";\n border-radius: 4px;\n padding: 4px 8px;\n color: ", ";\n"])), function (props) { return props.theme.primaryBtnFontSizeDefault; }, function (props) { return props.theme.errorColor; }, function (props) { return props.theme.errorTextColor; }); var RangeSlider = _components.appInjector.get(_components.RangeSliderFactory); function AiAssistantConfig() { var dispatch = (0, _reactRedux.useDispatch)(); var aiAssistantConfig = (0, _reactRedux.useSelector)(function (state) { return state.demo.aiAssistant.config; }); var intl = (0, _reactIntl.useIntl)(); var _useLocalStorage = (0, _usehooksTs.useLocalStorage)('ai-assistant-provider', aiAssistantConfig.provider || 'openai'), _useLocalStorage2 = (0, _slicedToArray2["default"])(_useLocalStorage, 2), provider = _useLocalStorage2[0], setProvider = _useLocalStorage2[1]; var _useLocalStorage3 = (0, _usehooksTs.useLocalStorage)('ai-assistant-model', aiAssistantConfig.model || _models.PROVIDER_MODELS[provider][0]), _useLocalStorage4 = (0, _slicedToArray2["default"])(_useLocalStorage3, 2), model = _useLocalStorage4[0], setModel = _useLocalStorage4[1]; var _useLocalStorage5 = (0, _usehooksTs.useLocalStorage)('ai-assistant-api-key', aiAssistantConfig.apiKey || ''), _useLocalStorage6 = (0, _slicedToArray2["default"])(_useLocalStorage5, 2), apiKey = _useLocalStorage6[0], setApiKey = _useLocalStorage6[1]; var _useLocalStorage7 = (0, _usehooksTs.useLocalStorage)('ai-assistant-temperature', aiAssistantConfig.temperature || 0.0), _useLocalStorage8 = (0, _slicedToArray2["default"])(_useLocalStorage7, 2), temperature = _useLocalStorage8[0], setTemperature = _useLocalStorage8[1]; var _useLocalStorage9 = (0, _usehooksTs.useLocalStorage)('ai-assistant-top-p', aiAssistantConfig.topP || 1.0), _useLocalStorage10 = (0, _slicedToArray2["default"])(_useLocalStorage9, 2), topP = _useLocalStorage10[0], setTopP = _useLocalStorage10[1]; var _useLocalStorage11 = (0, _usehooksTs.useLocalStorage)('ai-assistant-base-url', aiAssistantConfig.baseUrl || _models.PROVIDER_DEFAULT_BASE_URLS[provider]), _useLocalStorage12 = (0, _slicedToArray2["default"])(_useLocalStorage11, 2), baseUrl = _useLocalStorage12[0], setBaseUrl = _useLocalStorage12[1]; var _useLocalStorage13 = (0, _usehooksTs.useLocalStorage)('ai-assistant-mapbox-token', aiAssistantConfig.mapboxToken || ''), _useLocalStorage14 = (0, _slicedToArray2["default"])(_useLocalStorage13, 2), mapboxToken = _useLocalStorage14[0], setMapboxToken = _useLocalStorage14[1]; var _useState = (0, _react.useState)(false), _useState2 = (0, _slicedToArray2["default"])(_useState, 2), ollamaModelInputChecked = _useState2[0], setOllamaModelInputChecked = _useState2[1]; var _useState3 = (0, _react.useState)(''), _useState4 = (0, _slicedToArray2["default"])(_useState3, 2), ollamaModelInputValue = _useState4[0], setOllamaModelInputValue = _useState4[1]; var _useState5 = (0, _react.useState)(false), _useState6 = (0, _slicedToArray2["default"])(_useState5, 2), connectionError = _useState6[0], setConnectionError = _useState6[1]; var _useState7 = (0, _react.useState)(''), _useState8 = (0, _slicedToArray2["default"])(_useState7, 2), errorMessage = _useState8[0], setErrorMessage = _useState8[1]; var _useState9 = (0, _react.useState)(false), _useState10 = (0, _slicedToArray2["default"])(_useState9, 2), isRunning = _useState10[0], setIsRunning = _useState10[1]; var onAiProviderSelect = function onAiProviderSelect(value) { if (typeof value === 'string') { setProvider(value); setModel(_models.PROVIDER_MODELS[value][0]); setBaseUrl(_models.PROVIDER_DEFAULT_BASE_URLS[value]); setConnectionError(false); setErrorMessage(''); } }; var onLLMModelSelect = function onLLMModelSelect(value) { if (typeof value === 'string') { setModel(value); } }; var onApiKeyChange = function onApiKeyChange(e) { setApiKey(e.target.value); // reset previous key error if any setConnectionError(false); setErrorMessage(''); }; var onTemperatureChange = function onTemperatureChange(value) { setTemperature(value[1]); }; var onTopPChange = function onTopPChange(value) { setTopP(value[1]); }; var onBaseUrlChange = function onBaseUrlChange(e) { setBaseUrl(e.target.value); setConnectionError(false); setErrorMessage(''); }; var onMapboxTokenChange = function onMapboxTokenChange(e) { setMapboxToken(e.target.value); }; var onOllamaModelInputChecked = function onOllamaModelInputChecked(e) { setOllamaModelInputChecked(e.target.checked); if (!e.target.checked) { // use model from selector setModel(''); } }; var onOllamaModelInputValueChange = function onOllamaModelInputValueChange(e) { setOllamaModelInputValue(e.target.value); setModel(e.target.value); }; var onStartChat = /*#__PURE__*/function () { var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() { var timeoutPromise, AssistantModel, success, _errorMessage; return _regenerator["default"].wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: setIsRunning(true); _context.prev = 1; timeoutPromise = new Promise(function (_, reject) { setTimeout(function () { return reject(new Error('Connection timeout after 15 seconds')); }, 15000); }); _context.next = 5; return (0, _core.GetAssistantModelByProvider)({ provider: provider }); case 5: AssistantModel = _context.sent; if (!(!AssistantModel || !AssistantModel.configure || !AssistantModel.testConnection)) { _context.next = 8; break; } throw new Error('Failed to initialize AI model'); case 8: // configure model AssistantModel.configure({ model: model, baseURL: baseUrl || _models.PROVIDER_DEFAULT_BASE_URLS[provider], apiKey: apiKey, temperature: Number(temperature), topP: Number(topP) }); _context.next = 11; return Promise.race([AssistantModel.testConnection(apiKey, model), timeoutPromise]); case 11: success = _context.sent; _errorMessage = !success ? provider === 'ollama' ? 'Connection failed: maybe invalid Base URL' : 'Connection failed: maybe invalid API Key or Base URL' : ''; setConnectionError(!success); setErrorMessage(_errorMessage); dispatch((0, _actions.updateAiAssistantConfig)({ provider: provider, model: model, apiKey: apiKey, baseUrl: baseUrl || _models.PROVIDER_DEFAULT_BASE_URLS[provider], isReady: success, temperature: temperature, topP: topP, mapboxToken: mapboxToken })); _context.next = 22; break; case 18: _context.prev = 18; _context.t0 = _context["catch"](1); setConnectionError(true); setErrorMessage(_context.t0 instanceof Error ? _context.t0.message : 'Connection failed'); case 22: _context.prev = 22; setIsRunning(false); return _context.finish(22); case 25: case "end": return _context.stop(); } }, _callee, null, [[1, 18, 22, 25]]); })); return function onStartChat() { return _ref.apply(this, arguments); }; }(); return /*#__PURE__*/_react["default"].createElement(StyledAiAssistantConfig, { className: "ai-assistant-config__type" }, /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, { id: "aiAssistantManager.aiProvider" }))), /*#__PURE__*/_react["default"].createElement(StyledWrapper, null, /*#__PURE__*/_react["default"].createElement(StyledItemSelector, { selectedItems: provider, options: Object.keys(_models.PROVIDER_MODELS), multiSelect: false, disabled: false, onChange: onAiProviderSelect, filterOption: "name", getOptionValue: function getOptionValue(op) { return op; }, displayOption: function displayOption(op) { return op; }, searchable: false, showArrow: true })), /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, { id: "aiAssistantManager.llmModel.title" }))), (provider === 'ollama' && !ollamaModelInputChecked || provider !== 'ollama') && /*#__PURE__*/_react["default"].createElement(StyledWrapper, null, /*#__PURE__*/_react["default"].createElement(StyledItemSelector, { selectedItems: model, options: _models.PROVIDER_MODELS[provider], multiSelect: false, disabled: provider === 'ollama' ? ollamaModelInputChecked : false, placeholder: "Select LLM Model", onChange: onLLMModelSelect, filterOption: "name", getOptionValue: function getOptionValue(op) { return op; }, displayOption: function displayOption(op) { return op; }, searchable: false, showArrow: true })), provider === 'ollama' && /*#__PURE__*/_react["default"].createElement(OllamaModelInputWrapper, null, /*#__PURE__*/_react["default"].createElement("div", { style: { width: '250px' } }, /*#__PURE__*/_react["default"].createElement(_components.Checkbox, { id: "ollama-model-input", label: "Input Model Name", onChange: onOllamaModelInputChecked, checked: ollamaModelInputChecked })), /*#__PURE__*/_react["default"].createElement(_components.Input, { type: "text", onChange: onOllamaModelInputValueChange, placeholder: "Enter Model Name", value: ollamaModelInputValue, disabled: !ollamaModelInputChecked })), provider !== 'ollama' && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, { id: "aiAssistantManager.apiKey.title" }))), /*#__PURE__*/_react["default"].createElement("div", { className: "api-key-input" }, /*#__PURE__*/_react["default"].createElement("div", { className: "api-key-input__icon" }, /*#__PURE__*/_react["default"].createElement(_apiKey["default"], { height: "20px" })), /*#__PURE__*/_react["default"].createElement(_components.Input, { type: "text", onChange: onApiKeyChange, placeholder: intl.formatMessage({ id: 'aiAssistantManager.apiKey.placeholder' }), value: apiKey }))), /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, { id: "aiAssistantManager.baseUrl.title" }))), /*#__PURE__*/_react["default"].createElement("div", { className: "api-key-input" }, /*#__PURE__*/_react["default"].createElement("div", { className: "api-key-input__icon" }, /*#__PURE__*/_react["default"].createElement(_apiKey["default"], { height: "20px" })), /*#__PURE__*/_react["default"].createElement(_components.Input, { type: "text", onChange: onBaseUrlChange, placeholder: _models.PROVIDER_DEFAULT_BASE_URLS[provider], value: baseUrl })), connectionError && /*#__PURE__*/_react["default"].createElement(StyleErrorMessage, { className: "error-message" }, errorMessage), /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, { id: "aiAssistantManager.temperature.title" }))), /*#__PURE__*/_react["default"].createElement(StyleSliderWrapper, null, /*#__PURE__*/_react["default"].createElement(RangeSlider, { showInput: true, isRanged: false, value0: 0, value1: temperature, onChange: onTemperatureChange, range: [0, 2], step: 0.1 })), /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, { id: "aiAssistantManager.topP.title" }))), /*#__PURE__*/_react["default"].createElement(StyleSliderWrapper, null, /*#__PURE__*/_react["default"].createElement(RangeSlider, { showInput: true, isRanged: false, value0: 0, value1: topP, onChange: onTopPChange, range: [0, 1], step: 0.1 })), /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, "Mapbox Token (optional for route/isochrone)")), /*#__PURE__*/_react["default"].createElement("div", { className: "api-key-input" }, /*#__PURE__*/_react["default"].createElement("div", { className: "api-key-input__icon" }, /*#__PURE__*/_react["default"].createElement(_apiKey["default"], { height: "20px" })), /*#__PURE__*/_react["default"].createElement(_components.Input, { type: "text", onChange: onMapboxTokenChange, placeholder: "Enter your Mapbox Token", value: mapboxToken }))), /*#__PURE__*/_react["default"].createElement(StyledButton, null, /*#__PURE__*/_react["default"].createElement(_components.Button, { onClick: onStartChat, width: '100%' }, isRunning && /*#__PURE__*/_react["default"].createElement(_components.LoadingSpinner, { size: 12 }), /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, { id: "aiAssistantManager.startChat" })))); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfc3R5bGVkQ29tcG9uZW50cyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfcmVhY3RSZWR1eCIsIl9jb21wb25lbnRzIiwiX2FwaUtleSIsIl9tb2RlbHMiLCJfdXNlaG9va3NUcyIsIl9jb3JlIiwiX2FjdGlvbnMiLCJfcmVhY3RJbnRsIiwiX3RlbXBsYXRlT2JqZWN0IiwiX3RlbXBsYXRlT2JqZWN0MiIsIl90ZW1wbGF0ZU9iamVjdDMiLCJfdGVtcGxhdGVPYmplY3Q0IiwiX3RlbXBsYXRlT2JqZWN0NSIsIl90ZW1wbGF0ZU9iamVjdDYiLCJfdGVtcGxhdGVPYmplY3Q3IiwiX3RlbXBsYXRlT2JqZWN0OCIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiX3R5cGVvZiIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIlNlY3Rpb25UaXRsZSIsInN0eWxlZCIsImRpdiIsIl90YWdnZWRUZW1wbGF0ZUxpdGVyYWwyIiwicHJvcHMiLCJ0aGVtZSIsImlucHV0Rm9udFNpemUiLCJlZmZlY3RQYW5lbFRleHRTZWNvbmRhcnkxIiwiU3R5bGVkQWlBc3Npc3RhbnRDb25maWciLCJwcmltYXJ5QnRuRm9udFNpemVEZWZhdWx0IiwiYm94U2hhZG93IiwiZ2VvY29kZXJJbnB1dEhlaWdodCIsInN1YnRleHRDb2xvciIsIk9sbGFtYU1vZGVsSW5wdXRXcmFwcGVyIiwiU3R5bGVkV3JhcHBlciIsIlN0eWxlZEl0ZW1TZWxlY3RvciIsIkl0ZW1TZWxlY3RvciIsImFjdGl2ZUNvbG9yIiwiU3R5bGVTbGlkZXJXcmFwcGVyIiwiU3R5bGVkQnV0dG9uIiwiU3R5bGVFcnJvck1lc3NhZ2UiLCJlcnJvckNvbG9yIiwiZXJyb3JUZXh0Q29sb3IiLCJSYW5nZVNsaWRlciIsImFwcEluamVjdG9yIiwiUmFuZ2VTbGlkZXJGYWN0b3J5IiwiQWlBc3Npc3RhbnRDb25maWciLCJkaXNwYXRjaCIsInVzZURpc3BhdGNoIiwiYWlBc3Npc3RhbnRDb25maWciLCJ1c2VTZWxlY3RvciIsInN0YXRlIiwiZGVtbyIsImFpQXNzaXN0YW50IiwiY29uZmlnIiwiaW50bCIsInVzZUludGwiLCJfdXNlTG9jYWxTdG9yYWdlIiwidXNlTG9jYWxTdG9yYWdlIiwicHJvdmlkZXIiLCJfdXNlTG9jYWxTdG9yYWdlMiIsIl9zbGljZWRUb0FycmF5MiIsInNldFByb3ZpZGVyIiwiX3VzZUxvY2FsU3RvcmFnZTMiLCJtb2RlbCIsIlBST1ZJREVSX01PREVMUyIsIl91c2VMb2NhbFN0b3JhZ2U0Iiwic2V0TW9kZWwiLCJfdXNlTG9jYWxTdG9yYWdlNSIsImFwaUtleSIsIl91c2VMb2NhbFN0b3JhZ2U2Iiwic2V0QXBpS2V5IiwiX3VzZUxvY2FsU3RvcmFnZTciLCJ0ZW1wZXJhdHVyZSIsIl91c2VMb2NhbFN0b3JhZ2U4Iiwic2V0VGVtcGVyYXR1cmUiLCJfdXNlTG9jYWxTdG9yYWdlOSIsInRvcFAiLCJfdXNlTG9jYWxTdG9yYWdlMTAiLCJzZXRUb3BQIiwiX3VzZUxvY2FsU3RvcmFnZTExIiwiYmFzZVVybCIsIlBST1ZJREVSX0RFRkFVTFRfQkFTRV9VUkxTIiwiX3VzZUxvY2FsU3RvcmFnZTEyIiwic2V0QmFzZVVybCIsIl91c2VMb2NhbFN0b3JhZ2UxMyIsIm1hcGJveFRva2VuIiwiX3VzZUxvY2FsU3RvcmFnZTE0Iiwic2V0TWFwYm94VG9rZW4iLCJfdXNlU3RhdGUiLCJ1c2VTdGF0ZSIsIl91c2VTdGF0ZTIiLCJvbGxhbWFNb2RlbElucHV0Q2hlY2tlZCIsInNldE9sbGFtYU1vZGVsSW5wdXRDaGVja2VkIiwiX3VzZVN0YXRlMyIsIl91c2VTdGF0ZTQiLCJvbGxhbWFNb2RlbElucHV0VmFsdWUiLCJzZXRPbGxhbWFNb2RlbElucHV0VmFsdWUiLCJfdXNlU3RhdGU1IiwiX3VzZVN0YXRlNiIsImNvbm5lY3Rpb25FcnJvciIsInNldENvbm5lY3Rpb25FcnJvciIsIl91c2VTdGF0ZTciLCJfdXNlU3RhdGU4IiwiZXJyb3JNZXNzYWdlIiwic2V0RXJyb3JNZXNzYWdlIiwiX3VzZVN0YXRlOSIsIl91c2VTdGF0ZTEwIiwiaXNSdW5uaW5nIiwic2V0SXNSdW5uaW5nIiwib25BaVByb3ZpZGVyU2VsZWN0IiwidmFsdWUiLCJvbkxMTU1vZGVsU2VsZWN0Iiwib25BcGlLZXlDaGFuZ2UiLCJ0YXJnZXQiLCJvblRlbXBlcmF0dXJlQ2hhbmdlIiwib25Ub3BQQ2hhbmdlIiwib25CYXNlVXJsQ2hhbmdlIiwib25NYXBib3hUb2tlbkNoYW5nZSIsIm9uT2xsYW1hTW9kZWxJbnB1dENoZWNrZWQiLCJjaGVja2VkIiwib25PbGxhbWFNb2RlbElucHV0VmFsdWVDaGFuZ2UiLCJvblN0YXJ0Q2hhdCIsIl9yZWYiLCJfYXN5bmNUb0dlbmVyYXRvcjIiLCJfcmVnZW5lcmF0b3IiLCJtYXJrIiwiX2NhbGxlZSIsInRpbWVvdXRQcm9taXNlIiwiQXNzaXN0YW50TW9kZWwiLCJzdWNjZXNzIiwiX2Vycm9yTWVzc2FnZSIsIndyYXAiLCJfY2FsbGVlJCIsIl9jb250ZXh0IiwicHJldiIsIm5leHQiLCJQcm9taXNlIiwiXyIsInJlamVjdCIsInNldFRpbWVvdXQiLCJFcnJvciIsIkdldEFzc2lzdGFudE1vZGVsQnlQcm92aWRlciIsInNlbnQiLCJjb25maWd1cmUiLCJ0ZXN0Q29ubmVjdGlvbiIsImJhc2VVUkwiLCJOdW1iZXIiLCJyYWNlIiwidXBkYXRlQWlBc3Npc3RhbnRDb25maWciLCJpc1JlYWR5IiwidDAiLCJtZXNzYWdlIiwiZmluaXNoIiwic3RvcCIsImFwcGx5IiwiYXJndW1lbnRzIiwiY3JlYXRlRWxlbWVudCIsImNsYXNzTmFtZSIsIlBhbmVsTGFiZWxXcmFwcGVyIiwiRm9ybWF0dGVkTWVzc2FnZSIsImlkIiwic2VsZWN0ZWRJdGVtcyIsIm9wdGlvbnMiLCJrZXlzIiwibXVsdGlTZWxlY3QiLCJkaXNhYmxlZCIsIm9uQ2hhbmdlIiwiZmlsdGVyT3B0aW9uIiwiZ2V0T3B0aW9uVmFsdWUiLCJvcCIsImRpc3BsYXlPcHRpb24iLCJzZWFyY2hhYmxlIiwic2hvd0Fycm93IiwicGxhY2Vob2xkZXIiLCJzdHlsZSIsIndpZHRoIiwiQ2hlY2tib3giLCJsYWJlbCIsIklucHV0IiwidHlwZSIsIkZyYWdtZW50IiwiaGVpZ2h0IiwiZm9ybWF0TWVzc2FnZSIsInNob3dJbnB1dCIsImlzUmFuZ2VkIiwidmFsdWUwIiwidmFsdWUxIiwicmFuZ2UiLCJzdGVwIiwiQnV0dG9uIiwib25DbGljayIsIkxvYWRpbmdTcGlubmVyIiwic2l6ZSJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21wb25lbnRzL2FpLWFzc2lzdGFudC1jb25maWcudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCBSZWFjdCwge3VzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ3N0eWxlZC1jb21wb25lbnRzJztcbmltcG9ydCB7dXNlU2VsZWN0b3IsIHVzZURpc3BhdGNofSBmcm9tICdyZWFjdC1yZWR1eCc7XG5pbXBvcnQge1xuICBJbnB1dCxcbiAgUGFuZWxMYWJlbFdyYXBwZXIsXG4gIEl0ZW1TZWxlY3RvcixcbiAgUmFuZ2VTbGlkZXJGYWN0b3J5LFxuICBCdXR0b24sXG4gIExvYWRpbmdTcGlubmVyLFxuICBhcHBJbmplY3RvcixcbiAgQ2hlY2tib3hcbn0gZnJvbSAnQGtlcGxlci5nbC9jb21wb25lbnRzJztcbmltcG9ydCB7U3RhdGV9IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCBBcGlLZXkgZnJvbSAnLi4vaWNvbnMvYXBpLWtleSc7XG5pbXBvcnQge1BST1ZJREVSX01PREVMUywgUFJPVklERVJfREVGQVVMVF9CQVNFX1VSTFN9IGZyb20gJy4uL2NvbmZpZy9tb2RlbHMnO1xuaW1wb3J0IHt1c2VMb2NhbFN0b3JhZ2V9IGZyb20gJ3VzZWhvb2tzLXRzJztcbmltcG9ydCB7R2V0QXNzaXN0YW50TW9kZWxCeVByb3ZpZGVyfSBmcm9tICdAb3BlbmFzc2lzdGFudC9jb3JlJztcbmltcG9ydCB7dXBkYXRlQWlBc3Npc3RhbnRDb25maWd9IGZyb20gJy4uL2FjdGlvbnMnO1xuaW1wb3J0IHtGb3JtYXR0ZWRNZXNzYWdlLCB1c2VJbnRsfSBmcm9tICdyZWFjdC1pbnRsJztcblxuY29uc3QgU2VjdGlvblRpdGxlID0gc3R5bGVkLmRpdmBcbiAgZm9udC1zaXplOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmlucHV0Rm9udFNpemV9O1xuICBjb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5lZmZlY3RQYW5lbFRleHRTZWNvbmRhcnkxfTtcbiAgdGV4dC10cmFuc2Zvcm06IGNhcGl0YWxpemU7XG5gO1xuXG5jb25zdCBTdHlsZWRBaUFzc2lzdGFudENvbmZpZyA9IHN0eWxlZC5kaXZgXG4gIHBhZGRpbmc6IDEycHg7XG4gIGZvbnQtc2l6ZTogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5wcmltYXJ5QnRuRm9udFNpemVEZWZhdWx0fTtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgZ2FwOiAxMnB4O1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xuXG4gIC5hcGkta2V5LWlucHV0IHtcbiAgICBib3gtc2hhZG93OiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmJveFNoYWRvd307XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgLmFwaS1rZXktaW5wdXRfX2ljb24ge1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgaGVpZ2h0OiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmdlb2NvZGVySW5wdXRIZWlnaHR9cHg7XG4gICAgICB3aWR0aDogMzBweDtcbiAgICAgIHBhZGRpbmctbGVmdDogNnB4O1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnN1YnRleHRDb2xvcn07XG4gICAgfVxuXG4gICAgaW5wdXQge1xuICAgICAgcGFkZGluZzogNHB4IDM2cHg7XG4gICAgICBoZWlnaHQ6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuZ2VvY29kZXJJbnB1dEhlaWdodH1weDtcbiAgICAgIGNhcmV0LWNvbG9yOiB1bnNldDtcbiAgICB9XG4gIH1cbmA7XG5cbi8vIE9sbGFtYSBtb2RlbCBpbnB1dCB3cmFwcGVyOiBjaGVja2JveCArICdJbnB1dCBNb2RlbCBOYW1lOicgKyBpbnB1dFxuLy8gYWxsIGNoaWxkcmVuIGVsZW1lbnQgaGF2ZSB3aWR0aCBiYXNlZCBvbiB0aGUgY29udGVudFxuY29uc3QgT2xsYW1hTW9kZWxJbnB1dFdyYXBwZXIgPSBzdHlsZWQuZGl2YFxuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBnYXA6IDRweDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbmA7XG5cbmNvbnN0IFN0eWxlZFdyYXBwZXIgPSBzdHlsZWQuZGl2YFxuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG5gO1xuXG5jb25zdCBTdHlsZWRJdGVtU2VsZWN0b3IgPSBzdHlsZWQoSXRlbVNlbGVjdG9yKWBcbiAgLml0ZW0tc2VsZWN0b3JfX2Ryb3Bkb3duIHtcbiAgICBwYWRkaW5nLWxlZnQ6IDEwcHg7XG4gICAgYm9yZGVyLXJhZGl1czogNHB4O1xuICB9XG4gIC5hY3RpdmUge1xuICAgIGJvcmRlci1jb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5hY3RpdmVDb2xvcn07XG4gICAgYm9yZGVyLXJhZGl1czogNHB4IDRweCAwcHggMHB4ICFpbXBvcnRhbnQ7XG4gIH1cbiAgd2lkdGg6IDEwMCU7XG5gO1xuXG5jb25zdCBTdHlsZVNsaWRlcldyYXBwZXIgPSBzdHlsZWQuZGl2YFxuICB3aWR0aDogMTAwJTtcbiAgYWxpZ24tc2VsZjogZmxleC1zdGFydDtcbiAgaGVpZ2h0OiAzMnB4O1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAua2ctcmFuZ2Utc2xpZGVyX19pbnB1dCB7XG4gICAgaGVpZ2h0OiAzMnB4O1xuICAgIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgICBwYWRkaW5nOiAzcHggNnB4O1xuICB9XG4gIC5rZy1zbGlkZXIge1xuICAgIHBhZGRpbmctbGVmdDogNnB4O1xuICB9XG4gIC5rZy1yYW5nZS1zbGlkZXIge1xuICAgIHBhZGRpbmc6IDBweCAhaW1wb3J0YW50O1xuICB9XG5gO1xuXG5jb25zdCBTdHlsZWRCdXR0b24gPSBzdHlsZWQuZGl2YFxuICB3aWR0aDogMTAwJTtcbiAgYWxpZ24tc2VsZjogZmxleC1zdGFydDtcbiAgbWFyZ2luLXRvcDogMTJweDtcblxuICBidXR0b24gZGl2IHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgZ2FwOiA0cHg7XG4gICAgbWFyZ2luLXJpZ2h0OiA0cHg7XG4gIH1cbmA7XG5cbmNvbnN0IFN0eWxlRXJyb3JNZXNzYWdlID0gc3R5bGVkLmRpdmBcbiAgZm9udC1zaXplOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnByaW1hcnlCdG5Gb250U2l6ZURlZmF1bHR9O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmVycm9yQ29sb3J9O1xuICBib3JkZXItcmFkaXVzOiA0cHg7XG4gIHBhZGRpbmc6IDRweCA4cHg7XG4gIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmVycm9yVGV4dENvbG9yfTtcbmA7XG5cbmNvbnN0IFJhbmdlU2xpZGVyID0gYXBwSW5qZWN0b3IuZ2V0KFJhbmdlU2xpZGVyRmFjdG9yeSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBBaUFzc2lzdGFudENvbmZpZygpIHtcbiAgY29uc3QgZGlzcGF0Y2ggPSB1c2VEaXNwYXRjaCgpO1xuICBjb25zdCBhaUFzc2lzdGFudENvbmZpZyA9IHVzZVNlbGVjdG9yKChzdGF0ZTogU3RhdGUpID0+IHN0YXRlLmRlbW8uYWlBc3Npc3RhbnQuY29uZmlnKTtcbiAgY29uc3QgaW50bCA9IHVzZUludGwoKTtcblxuICBjb25zdCBbcHJvdmlkZXIsIHNldFByb3ZpZGVyXSA9IHVzZUxvY2FsU3RvcmFnZShcbiAgICAnYWktYXNzaXN0YW50LXByb3ZpZGVyJyxcbiAgICBhaUFzc2lzdGFudENvbmZpZy5wcm92aWRlciB8fCAnb3BlbmFpJ1xuICApO1xuICBjb25zdCBbbW9kZWwsIHNldE1vZGVsXSA9IHVzZUxvY2FsU3RvcmFnZShcbiAgICAnYWktYXNzaXN0YW50LW1vZGVsJyxcbiAgICBhaUFzc2lzdGFudENvbmZpZy5tb2RlbCB8fCBQUk9WSURFUl9NT0RFTFNbcHJvdmlkZXJdWzBdXG4gICk7XG4gIGNvbnN0IFthcGlLZXksIHNldEFwaUtleV0gPSB1c2VMb2NhbFN0b3JhZ2UoXG4gICAgJ2FpLWFzc2lzdGFudC1hcGkta2V5JyxcbiAgICBhaUFzc2lzdGFudENvbmZpZy5hcGlLZXkgfHwgJydcbiAgKTtcbiAgY29uc3QgW3RlbXBlcmF0dXJlLCBzZXRUZW1wZXJhdHVyZV0gPSB1c2VMb2NhbFN0b3JhZ2UoXG4gICAgJ2FpLWFzc2lzdGFudC10ZW1wZXJhdHVyZScsXG4gICAgYWlBc3Npc3RhbnRDb25maWcudGVtcGVyYXR1cmUgfHwgMC4wXG4gICk7XG4gIGNvbnN0IFt0b3BQLCBzZXRUb3BQXSA9IHVzZUxvY2FsU3RvcmFnZSgnYWktYXNzaXN0YW50LXRvcC1wJywgYWlBc3Npc3RhbnRDb25maWcudG9wUCB8fCAxLjApO1xuICBjb25zdCBbYmFzZVVybCwgc2V0QmFzZVVybF0gPSB1c2VMb2NhbFN0b3JhZ2UoXG4gICAgJ2FpLWFzc2lzdGFudC1iYXNlLXVybCcsXG4gICAgYWlBc3Npc3RhbnRDb25maWcuYmFzZVVybCB8fCBQUk9WSURFUl9ERUZBVUxUX0JBU0VfVVJMU1twcm92aWRlcl1cbiAgKTtcbiAgY29uc3QgW21hcGJveFRva2VuLCBzZXRNYXBib3hUb2tlbl0gPSB1c2VMb2NhbFN0b3JhZ2UoXG4gICAgJ2FpLWFzc2lzdGFudC1tYXBib3gtdG9rZW4nLFxuICAgIGFpQXNzaXN0YW50Q29uZmlnLm1hcGJveFRva2VuIHx8ICcnXG4gICk7XG4gIGNvbnN0IFtvbGxhbWFNb2RlbElucHV0Q2hlY2tlZCwgc2V0T2xsYW1hTW9kZWxJbnB1dENoZWNrZWRdID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbb2xsYW1hTW9kZWxJbnB1dFZhbHVlLCBzZXRPbGxhbWFNb2RlbElucHV0VmFsdWVdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbY29ubmVjdGlvbkVycm9yLCBzZXRDb25uZWN0aW9uRXJyb3JdID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbZXJyb3JNZXNzYWdlLCBzZXRFcnJvck1lc3NhZ2VdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXNSdW5uaW5nLCBzZXRJc1J1bm5pbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuXG4gIGNvbnN0IG9uQWlQcm92aWRlclNlbGVjdCA9ICh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG9iamVjdCB8IG51bGwpID0+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgc2V0UHJvdmlkZXIodmFsdWUpO1xuICAgICAgc2V0TW9kZWwoUFJPVklERVJfTU9ERUxTW3ZhbHVlXVswXSk7XG4gICAgICBzZXRCYXNlVXJsKFBST1ZJREVSX0RFRkFVTFRfQkFTRV9VUkxTW3ZhbHVlXSk7XG4gICAgICBzZXRDb25uZWN0aW9uRXJyb3IoZmFsc2UpO1xuICAgICAgc2V0RXJyb3JNZXNzYWdlKCcnKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3Qgb25MTE1Nb2RlbFNlbGVjdCA9ICh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG9iamVjdCB8IG51bGwpID0+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgc2V0TW9kZWwodmFsdWUpO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCBvbkFwaUtleUNoYW5nZSA9IChlOiBSZWFjdC5DaGFuZ2VFdmVudDxIVE1MSW5wdXRFbGVtZW50PikgPT4ge1xuICAgIHNldEFwaUtleShlLnRhcmdldC52YWx1ZSk7XG4gICAgLy8gcmVzZXQgcHJldmlvdXMga2V5IGVycm9yIGlmIGFueVxuICAgIHNldENvbm5lY3Rpb25FcnJvcihmYWxzZSk7XG4gICAgc2V0RXJyb3JNZXNzYWdlKCcnKTtcbiAgfTtcblxuICBjb25zdCBvblRlbXBlcmF0dXJlQ2hhbmdlID0gKHZhbHVlOiBudW1iZXJbXSkgPT4ge1xuICAgIHNldFRlbXBlcmF0dXJlKHZhbHVlWzFdKTtcbiAgfTtcblxuICBjb25zdCBvblRvcFBDaGFuZ2UgPSAodmFsdWU6IG51bWJlcltdKSA9PiB7XG4gICAgc2V0VG9wUCh2YWx1ZVsxXSk7XG4gIH07XG5cbiAgY29uc3Qgb25CYXNlVXJsQ2hhbmdlID0gKGU6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB7XG4gICAgc2V0QmFzZVVybChlLnRhcmdldC52YWx1ZSk7XG4gICAgc2V0Q29ubmVjdGlvbkVycm9yKGZhbHNlKTtcbiAgICBzZXRFcnJvck1lc3NhZ2UoJycpO1xuICB9O1xuXG4gIGNvbnN0IG9uTWFwYm94VG9rZW5DaGFuZ2UgPSAoZTogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHtcbiAgICBzZXRNYXBib3hUb2tlbihlLnRhcmdldC52YWx1ZSk7XG4gIH07XG5cbiAgY29uc3Qgb25PbGxhbWFNb2RlbElucHV0Q2hlY2tlZCA9IChlOiBSZWFjdC5DaGFuZ2VFdmVudDxIVE1MSW5wdXRFbGVtZW50PikgPT4ge1xuICAgIHNldE9sbGFtYU1vZGVsSW5wdXRDaGVja2VkKGUudGFyZ2V0LmNoZWNrZWQpO1xuICAgIGlmICghZS50YXJnZXQuY2hlY2tlZCkge1xuICAgICAgLy8gdXNlIG1vZGVsIGZyb20gc2VsZWN0b3JcbiAgICAgIHNldE1vZGVsKCcnKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3Qgb25PbGxhbWFNb2RlbElucHV0VmFsdWVDaGFuZ2UgPSAoZTogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHtcbiAgICBzZXRPbGxhbWFNb2RlbElucHV0VmFsdWUoZS50YXJnZXQudmFsdWUpO1xuICAgIHNldE1vZGVsKGUudGFyZ2V0LnZhbHVlKTtcbiAgfTtcblxuICBjb25zdCBvblN0YXJ0Q2hhdCA9IGFzeW5jICgpID0+IHtcbiAgICBzZXRJc1J1bm5pbmcodHJ1ZSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRpbWVvdXRQcm9taXNlID0gbmV3IFByb21pc2UoKF8sIHJlamVjdCkgPT4ge1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHJlamVjdChuZXcgRXJyb3IoJ0Nvbm5lY3Rpb24gdGltZW91dCBhZnRlciAxNSBzZWNvbmRzJykpLCAxNTAwMCk7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgQXNzaXN0YW50TW9kZWwgPSBhd2FpdCBHZXRBc3Npc3RhbnRNb2RlbEJ5UHJvdmlkZXIoe1xuICAgICAgICBwcm92aWRlcjogcHJvdmlkZXJcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoIUFzc2lzdGFudE1vZGVsIHx8ICFBc3Npc3RhbnRNb2RlbC5jb25maWd1cmUgfHwgIUFzc2lzdGFudE1vZGVsLnRlc3RDb25uZWN0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgQUkgbW9kZWwnKTtcbiAgICAgIH1cblxuICAgICAgLy8gY29uZmlndXJlIG1vZGVsXG4gICAgICBBc3Npc3RhbnRNb2RlbC5jb25maWd1cmUoe1xuICAgICAgICBtb2RlbDogbW9kZWwsXG4gICAgICAgIGJhc2VVUkw6IGJhc2VVcmwgfHwgUFJPVklERVJfREVGQVVMVF9CQVNFX1VSTFNbcHJvdmlkZXJdLFxuICAgICAgICBhcGlLZXk6IGFwaUtleSxcbiAgICAgICAgdGVtcGVyYXR1cmU6IE51bWJlcih0ZW1wZXJhdHVyZSksXG4gICAgICAgIHRvcFA6IE51bWJlcih0b3BQKVxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHN1Y2Nlc3MgPSAoYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgQXNzaXN0YW50TW9kZWwudGVzdENvbm5lY3Rpb24oYXBpS2V5LCBtb2RlbCksXG4gICAgICAgIHRpbWVvdXRQcm9taXNlXG4gICAgICBdKSkgYXMgYm9vbGVhbjtcblxuICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gIXN1Y2Nlc3NcbiAgICAgICAgPyBwcm92aWRlciA9PT0gJ29sbGFtYSdcbiAgICAgICAgICA/ICdDb25uZWN0aW9uIGZhaWxlZDogbWF5YmUgaW52YWxpZCBCYXNlIFVSTCdcbiAgICAgICAgICA6ICdDb25uZWN0aW9uIGZhaWxlZDogbWF5YmUgaW52YWxpZCBBUEkgS2V5IG9yIEJhc2UgVVJMJ1xuICAgICAgICA6ICcnO1xuICAgICAgc2V0Q29ubmVjdGlvbkVycm9yKCFzdWNjZXNzKTtcbiAgICAgIHNldEVycm9yTWVzc2FnZShlcnJvck1lc3NhZ2UpO1xuICAgICAgZGlzcGF0Y2goXG4gICAgICAgIHVwZGF0ZUFpQXNzaXN0YW50Q29uZmlnKHtcbiAgICAgICAgICBwcm92aWRlcjogcHJvdmlkZXIsXG4gICAgICAgICAgbW9kZWw6IG1vZGVsLFxuICAgICAgICAgIGFwaUtleTogYXBpS2V5LFxuICAgICAgICAgIGJhc2VVcmw6IGJhc2VVcmwgfHwgUFJPVklERVJfREVGQVVMVF9CQVNFX1VSTFNbcHJvdmlkZXJdLFxuICAgICAgICAgIGlzUmVhZHk6IHN1Y2Nlc3MsXG4gICAgICAgICAgdGVtcGVyYXR1cmU6IHRlbXBlcmF0dXJlLFxuICAgICAgICAgIHRvcFA6IHRvcFAsXG4gICAgICAgICAgbWFwYm94VG9rZW46IG1hcGJveFRva2VuXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBzZXRDb25uZWN0aW9uRXJyb3IodHJ1ZSk7XG4gICAgICBzZXRFcnJvck1lc3NhZ2UoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiAnQ29ubmVjdGlvbiBmYWlsZWQnKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgc2V0SXNSdW5uaW5nKGZhbHNlKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIChcbiAgICA8U3R5bGVkQWlBc3Npc3RhbnRDb25maWcgY2xhc3NOYW1lPVwiYWktYXNzaXN0YW50LWNvbmZpZ19fdHlwZVwiPlxuICAgICAgPFBhbmVsTGFiZWxXcmFwcGVyPlxuICAgICAgICA8U2VjdGlvblRpdGxlPlxuICAgICAgICAgIDxGb3JtYXR0ZWRNZXNzYWdlIGlkPVwiYWlBc3Npc3RhbnRNYW5hZ2VyLmFpUHJvdmlkZXJcIiAvPlxuICAgICAgICA8L1NlY3Rpb25UaXRsZT5cbiAgICAgIDwvUGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICA8U3R5bGVkV3JhcHBlcj5cbiAgICAgICAgPFN0eWxlZEl0ZW1TZWxlY3RvclxuICAgICAgICAgIHNlbGVjdGVkSXRlbXM9e3Byb3ZpZGVyfVxuICAgICAgICAgIG9wdGlvbnM9e09iamVjdC5rZXlzKFBST1ZJREVSX01PREVMUyl9XG4gICAgICAgICAgbXVsdGlTZWxlY3Q9e2ZhbHNlfVxuICAgICAgICAgIGRpc2FibGVkPXtmYWxzZX1cbiAgICAgICAgICBvbkNoYW5nZT17b25BaVByb3ZpZGVyU2VsZWN0fVxuICAgICAgICAgIGZpbHRlck9wdGlvbj1cIm5hbWVcIlxuICAgICAgICAgIGdldE9wdGlvblZhbHVlPXtvcCA9PiBvcH1cbiAgICAgICAgICBkaXNwbGF5T3B0aW9uPXtvcCA9PiBvcH1cbiAgICAgICAgICBzZWFyY2hhYmxlPXtmYWxzZX1cbiAgICAgICAgICBzaG93QXJyb3c9e3RydWV9XG4gICAgICAgIC8+XG4gICAgICA8L1N0eWxlZFdyYXBwZXI+XG4gICAgICA8UGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgIDxTZWN0aW9uVGl0bGU+XG4gICAgICAgICAgPEZvcm1hdHRlZE1lc3NhZ2UgaWQ9XCJhaUFzc2lzdGFudE1hbmFnZXIubGxtTW9kZWwudGl0bGVcIiAvPlxuICAgICAgICA8L1NlY3Rpb25UaXRsZT5cbiAgICAgIDwvUGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICB7KChwcm92aWRlciA9PT0gJ29sbGFtYScgJiYgIW9sbGFtYU1vZGVsSW5wdXRDaGVja2VkKSB8fCBwcm92aWRlciAhPT0gJ29sbGFtYScpICYmIChcbiAgICAgICAgPFN0eWxlZFdyYXBwZXI+XG4gICAgICAgICAgPFN0eWxlZEl0ZW1TZWxlY3RvclxuICAgICAgICAgICAgc2VsZWN0ZWRJdGVtcz17bW9kZWx9XG4gICAgICAgICAgICBvcHRpb25zPXtQUk9WSURFUl9NT0RFTFNbcHJvdmlkZXJdfVxuICAgICAgICAgICAgbXVsdGlTZWxlY3Q9e2ZhbHNlfVxuICAgICAgICAgICAgZGlzYWJsZWQ9e3Byb3ZpZGVyID09PSAnb2xsYW1hJyA/IG9sbGFtYU1vZGVsSW5wdXRDaGVja2VkIDogZmFsc2V9XG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlNlbGVjdCBMTE0gTW9kZWxcIlxuICAgICAgICAgICAgb25DaGFuZ2U9e29uTExNTW9kZWxTZWxlY3R9XG4gICAgICAgICAgICBmaWx0ZXJPcHRpb249XCJuYW1lXCJcbiAgICAgICAgICAgIGdldE9wdGlvblZhbHVlPXtvcCA9PiBvcH1cbiAgICAgICAgICAgIGRpc3BsYXlPcHRpb249e29wID0+IG9wfVxuICAgICAgICAgICAgc2VhcmNoYWJsZT17ZmFsc2V9XG4gICAgICAgICAgICBzaG93QXJyb3c9e3RydWV9XG4gICAgICAgICAgLz5cbiAgICAgICAgPC9TdHlsZWRXcmFwcGVyPlxuICAgICAgKX1cbiAgICAgIHtwcm92aWRlciA9PT0gJ29sbGFtYScgJiYgKFxuICAgICAgICA8T2xsYW1hTW9kZWxJbnB1dFdyYXBwZXI+XG4gICAgICAgICAgPGRpdiBzdHlsZT17e3dpZHRoOiAnMjUwcHgnfX0+XG4gICAgICAgICAgICA8Q2hlY2tib3hcbiAgICAgICAgICAgICAgaWQ9XCJvbGxhbWEtbW9kZWwtaW5wdXRcIlxuICAgICAgICAgICAgICBsYWJlbD1cIklucHV0IE1vZGVsIE5hbWVcIlxuICAgICAgICAgICAgICBvbkNoYW5nZT17b25PbGxhbWFNb2RlbElucHV0Q2hlY2tlZH1cbiAgICAgICAgICAgICAgY2hlY2tlZD17b2xsYW1hTW9kZWxJbnB1dENoZWNrZWR9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxJbnB1dFxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgb25DaGFuZ2U9e29uT2xsYW1hTW9kZWxJbnB1dFZhbHVlQ2hhbmdlfVxuICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJFbnRlciBNb2RlbCBOYW1lXCJcbiAgICAgICAgICAgIHZhbHVlPXtvbGxhbWFNb2RlbElucHV0VmFsdWV9XG4gICAgICAgICAgICBkaXNhYmxlZD17IW9sbGFtYU1vZGVsSW5wdXRDaGVja2VkfVxuICAgICAgICAgIC8+XG4gICAgICAgIDwvT2xsYW1hTW9kZWxJbnB1dFdyYXBwZXI+XG4gICAgICApfVxuICAgICAge3Byb3ZpZGVyICE9PSAnb2xsYW1hJyAmJiAoXG4gICAgICAgIDw+XG4gICAgICAgICAgPFBhbmVsTGFiZWxXcmFwcGVyPlxuICAgICAgICAgICAgPFNlY3Rpb25UaXRsZT5cbiAgICAgICAgICAgICAgPEZvcm1hdHRlZE1lc3NhZ2UgaWQ9XCJhaUFzc2lzdGFudE1hbmFnZXIuYXBpS2V5LnRpdGxlXCIgLz5cbiAgICAgICAgICAgIDwvU2VjdGlvblRpdGxlPlxuICAgICAgICAgIDwvUGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJhcGkta2V5LWlucHV0XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImFwaS1rZXktaW5wdXRfX2ljb25cIj5cbiAgICAgICAgICAgICAgPEFwaUtleSBoZWlnaHQ9XCIyMHB4XCIgLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPElucHV0XG4gICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgb25DaGFuZ2U9e29uQXBpS2V5Q2hhbmdlfVxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj17aW50bC5mb3JtYXRNZXNzYWdlKHtpZDogJ2FpQXNzaXN0YW50TWFuYWdlci5hcGlLZXkucGxhY2Vob2xkZXInfSl9XG4gICAgICAgICAgICAgIHZhbHVlPXthcGlLZXl9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8Lz5cbiAgICAgICl9XG4gICAgICA8UGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgIDxTZWN0aW9uVGl0bGU+XG4gICAgICAgICAgPEZvcm1hdHRlZE1lc3NhZ2UgaWQ9XCJhaUFzc2lzdGFudE1hbmFnZXIuYmFzZVVybC50aXRsZVwiIC8+XG4gICAgICAgIDwvU2VjdGlvblRpdGxlPlxuICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYXBpLWtleS1pbnB1dFwiPlxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImFwaS1rZXktaW5wdXRfX2ljb25cIj5cbiAgICAgICAgICA8QXBpS2V5IGhlaWdodD1cIjIwcHhcIiAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPElucHV0XG4gICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgIG9uQ2hhbmdlPXtvbkJhc2VVcmxDaGFuZ2V9XG4gICAgICAgICAgcGxhY2Vob2xkZXI9e1BST1ZJREVSX0RFRkFVTFRfQkFTRV9VUkxTW3Byb3ZpZGVyXX1cbiAgICAgICAgICB2YWx1ZT17YmFzZVVybH1cbiAgICAgICAgLz5cbiAgICAgIDwvZGl2PlxuICAgICAge2Nvbm5lY3Rpb25FcnJvciAmJiAoXG4gICAgICAgIDxTdHlsZUVycm9yTWVzc2FnZSBjbGFzc05hbWU9XCJlcnJvci1tZXNzYWdlXCI+e2Vycm9yTWVzc2FnZX08L1N0eWxlRXJyb3JNZXNzYWdlPlxuICAgICAgKX1cbiAgICAgIDxQYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgPFNlY3Rpb25UaXRsZT5cbiAgICAgICAgICA8Rm9ybWF0dGVkTWVzc2FnZSBpZD1cImFpQXNzaXN0YW50TWFuYWdlci50ZW1wZXJhdHVyZS50aXRsZVwiIC8+XG4gICAgICAgIDwvU2VjdGlvblRpdGxlPlxuICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgIDxTdHlsZVNsaWRlcldyYXBwZXI+XG4gICAgICAgIDxSYW5nZVNsaWRlclxuICAgICAgICAgIHNob3dJbnB1dD17dHJ1ZX1cbiAgICAgICAgICBpc1JhbmdlZD17ZmFsc2V9XG4gICAgICAgICAgdmFsdWUwPXswfVxuICAgICAgICAgIHZhbHVlMT17dGVtcGVyYXR1cmV9XG4gICAgICAgICAgb25DaGFuZ2U9e29uVGVtcGVyYXR1cmVDaGFuZ2V9XG4gICAgICAgICAgcmFuZ2U9e1swLCAyXX1cbiAgICAgICAgICBzdGVwPXswLjF9XG4gICAgICAgIC8+XG4gICAgICA8L1N0eWxlU2xpZGVyV3JhcHBlcj5cbiAgICAgIDxQYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgPFNlY3Rpb25UaXRsZT5cbiAgICAgICAgICA8Rm9ybWF0dGVkTWVzc2FnZSBpZD1cImFpQXNzaXN0YW50TWFuYWdlci50b3BQLnRpdGxlXCIgLz5cbiAgICAgICAgPC9TZWN0aW9uVGl0bGU+XG4gICAgICA8L1BhbmVsTGFiZWxXcmFwcGVyPlxuICAgICAgPFN0eWxlU2xpZGVyV3JhcHBlcj5cbiAgICAgICAgPFJhbmdlU2xpZGVyXG4gICAgICAgICAgc2hvd0lucHV0PXt0cnVlfVxuICAgICAgICAgIGlzUmFuZ2VkPXtmYWxzZX1cbiAgICAgICAgICB2YWx1ZTA9ezB9XG4gICAgICAgICAgdmFsdWUxPXt0b3BQfVxuICAgICAgICAgIG9uQ2hhbmdlPXtvblRvcFBDaGFuZ2V9XG4gICAgICAgICAgcmFuZ2U9e1swLCAxXX1cbiAgICAgICAgICBzdGVwPXswLjF9XG4gICAgICAgIC8+XG4gICAgICA8L1N0eWxlU2xpZGVyV3JhcHBlcj5cbiAgICAgIDw+XG4gICAgICAgIDxQYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgICA8U2VjdGlvblRpdGxlPk1hcGJveCBUb2tlbiAob3B0aW9uYWwgZm9yIHJvdXRlL2lzb2Nocm9uZSk8L1NlY3Rpb25UaXRsZT5cbiAgICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJhcGkta2V5LWlucHV0XCI+XG4gICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJhcGkta2V5LWlucHV0X19pY29uXCI+XG4gICAgICAgICAgICA8QXBpS2V5IGhlaWdodD1cIjIwcHhcIiAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxJbnB1dFxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgb25DaGFuZ2U9e29uTWFwYm94VG9rZW5DaGFuZ2V9XG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkVudGVyIHlvdXIgTWFwYm94IFRva2VuXCJcbiAgICAgICAgICAgIHZhbHVlPXttYXBib3hUb2tlbn1cbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvPlxuICAgICAgPFN0eWxlZEJ1dHRvbj5cbiAgICAgICAgPEJ1dHRvbiBvbkNsaWNrPXtvblN0YXJ0Q2hhdH0gd2lkdGg9eycxMDAlJ30+XG4gICAgICAgICAge2lzUnVubmluZyAmJiA8TG9hZGluZ1NwaW5uZXIgc2l6ZT17MTJ9IC8+fVxuICAgICAgICAgIDxGb3JtYXR0ZWRNZXNzYWdlIGlkPVwiYWlBc3Npc3RhbnRNYW5hZ2VyLnN0YXJ0Q2hhdFwiIC8+XG4gICAgICAgIDwvQnV0dG9uPlxuICAgICAgPC9TdHlsZWRCdXR0b24+XG4gICAgPC9TdHlsZWRBaUFzc2lzdGFudENvbmZpZz5cbiAgKTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEsTUFBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsaUJBQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLFdBQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLFdBQUEsR0FBQUosT0FBQTtBQVdBLElBQUFLLE9BQUEsR0FBQUgsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFNLE9BQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLFdBQUEsR0FBQVAsT0FBQTtBQUNBLElBQUFRLEtBQUEsR0FBQVIsT0FBQTtBQUNBLElBQUFTLFFBQUEsR0FBQVQsT0FBQTtBQUNBLElBQUFVLFVBQUEsR0FBQVYsT0FBQTtBQUFxRCxJQUFBVyxlQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBdEJyRDtBQUNBO0FBQUEsU0FBQUMseUJBQUFDLENBQUEsNkJBQUFDLE9BQUEsbUJBQUFDLENBQUEsT0FBQUQsT0FBQSxJQUFBRSxDQUFBLE9BQUFGLE9BQUEsWUFBQUYsd0JBQUEsWUFBQUEseUJBQUFDLENBQUEsV0FBQUEsQ0FBQSxHQUFBRyxDQUFBLEdBQUFELENBQUEsS0FBQUYsQ0FBQTtBQUFBLFNBQUFyQix3QkFBQXFCLENBQUEsRUFBQUUsQ0FBQSxTQUFBQSxDQUFBLElBQUFGLENBQUEsSUFBQUEsQ0FBQSxDQUFBSSxVQUFBLFNBQUFKLENBQUEsZUFBQUEsQ0FBQSxnQkFBQUssT0FBQSxDQUFBTCxDQUFBLDBCQUFBQSxDQUFBLHNCQUFBQSxDQUFBLFFBQUFHLENBQUEsR0FBQUosd0JBQUEsQ0FBQUcsQ0FBQSxPQUFBQyxDQUFBLElBQUFBLENBQUEsQ0FBQUcsR0FBQSxDQUFBTixDQUFBLFVBQUFHLENBQUEsQ0FBQUksR0FBQSxDQUFBUCxDQUFBLE9BQUFRLENBQUEsS0FBQUMsU0FBQSxVQUFBQyxDQUFBLEdBQUFDLE1BQUEsQ0FBQUMsY0FBQSxJQUFBRCxNQUFBLENBQUFFLHdCQUFBLFdBQUFDLENBQUEsSUFBQWQsQ0FBQSxvQkFBQWMsQ0FBQSxPQUFBQyxjQUFBLENBQUFDLElBQUEsQ0FBQWhCLENBQUEsRUFBQWMsQ0FBQSxTQUFBRyxDQUFBLEdBQUFQLENBQUEsR0FBQUMsTUFBQSxDQUFBRSx3QkFBQSxDQUFBYixDQUFBLEVBQUFjLENBQUEsVUFBQUcsQ0FBQSxLQUFBQSxDQUFBLENBQUFWLEdBQUEsSUFBQVUsQ0FBQSxDQUFBQyxHQUFBLElBQUFQLE1BQUEsQ0FBQUMsY0FBQSxDQUFBSixDQUFBLEVBQUFNLENBQUEsRUFBQUcsQ0FBQSxJQUFBVCxDQUFBLENBQUFNLENBQUEsSUFBQWQsQ0FBQSxDQUFBYyxDQUFBLFlBQUFOLENBQUEsY0FBQVIsQ0FBQSxFQUFBRyxDQUFBLElBQUFBLENBQUEsQ0FBQWUsR0FBQSxDQUFBbEIsQ0FBQSxFQUFBUSxDQUFBLEdBQUFBLENBQUE7QUF1QkEsSUFBTVcsWUFBWSxHQUFHQyw0QkFBTSxDQUFDQyxHQUFHLENBQUE5QixlQUFBLEtBQUFBLGVBQUEsT0FBQStCLHVCQUFBLDBGQUNoQixVQUFBQyxLQUFLO0VBQUEsT0FBSUEsS0FBSyxDQUFDQyxLQUFLLENBQUNDLGFBQWE7QUFBQSxHQUN0QyxVQUFBRixLQUFLO0VBQUEsT0FBSUEsS0FBSyxDQUFDQyxLQUFLLENBQUNFLHlCQUF5QjtBQUFBLEVBRXhEO0FBRUQsSUFBTUMsdUJBQXVCLEdBQUdQLDRCQUFNLENBQUNDLEdBQUcsQ0FBQTdCLGdCQUFBLEtBQUFBLGdCQUFBLE9BQUE4Qix1QkFBQSx3aUJBRTNCLFVBQUFDLEtBQUs7RUFBQSxPQUFJQSxLQUFLLENBQUNDLEtBQUssQ0FBQ0kseUJBQXlCO0FBQUEsR0FRM0MsVUFBQUwsS0FBSztFQUFBLE9BQUlBLEtBQUssQ0FBQ0MsS0FBSyxDQUFDSyxTQUFTO0FBQUEsR0FJaEMsVUFBQU4sS0FBSztFQUFBLE9BQUlBLEtBQUssQ0FBQ0MsS0FBSyxDQUFDTSxtQkFBbUI7QUFBQSxHQU16QyxVQUFBUCxLQUFLO0VBQUEsT0FBSUEsS0FBSyxDQUFDQyxLQUFLLENBQUNPLFlBQVk7QUFBQSxHQUtoQyxVQUFBUixLQUFLO0VBQUEsT0FBSUEsS0FBSyxDQUFDQyxLQUFLLENBQUNNLG1CQUFtQjtBQUFBLEVBSXZEOztBQUVEO0FBQ0E7QUFDQSxJQUFNRSx1QkFBdUIsR0FBR1osNEJBQU0sQ0FBQ0MsR0FBRyxDQUFBNUIsZ0JBQUEsS0FBQUEsZ0JBQUEsT0FBQTZCLHVCQUFBLHFHQUt6QztBQUVELElBQU1XLGFBQWEsR0FBR2IsNEJBQU0sQ0FBQ0MsR0FBRyxDQUFBM0IsZ0JBQUEsS0FBQUEsZ0JBQUEsT0FBQTRCLHVCQUFBLG1HQUkvQjtBQUVELElBQU1ZLGtCQUFrQixHQUFHLElBQUFkLDRCQUFNLEVBQUNlLHdCQUFZLENBQUMsQ0FBQXhDLGdCQUFBLEtBQUFBLGdCQUFBLE9BQUEyQix1QkFBQSx1TkFNM0IsVUFBQUMsS0FBSztFQUFBLE9BQUlBLEtBQUssQ0FBQ0MsS0FBSyxDQUFDWSxXQUFXO0FBQUEsRUFJbkQ7QUFFRCxJQUFNQyxrQkFBa0IsR0FBR2pCLDRCQUFNLENBQUNDLEdBQUcsQ0FBQXpCLGdCQUFBLEtBQUFBLGdCQUFBLE9BQUEwQix1QkFBQSx1VUFpQnBDO0FBRUQsSUFBTWdCLFlBQVksR0FBR2xCLDRCQUFNLENBQUNDLEdBQUcsQ0FBQXhCLGdCQUFBLEtBQUFBLGdCQUFBLE9BQUF5Qix1QkFBQSxrTUFXOUI7QUFFRCxJQUFNaUIsaUJBQWlCLEdBQUduQiw0QkFBTSxDQUFDQyxHQUFHLENBQUF2QixnQkFBQSxLQUFBQSxnQkFBQSxPQUFBd0IsdUJBQUEsa0lBQ3JCLFVBQUFDLEtBQUs7RUFBQSxPQUFJQSxLQUFLLENBQUNDLEtBQUssQ0FBQ0kseUJBQXlCO0FBQUEsR0FDdkMsVUFBQUwsS0FBSztFQUFBLE9BQUlBLEtBQUssQ0FBQ0MsS0FBSyxDQUFDZ0IsVUFBVTtBQUFBLEdBRzFDLFVBQUFqQixLQUFLO0VBQUEsT0FBSUEsS0FBSyxDQUFDQyxLQUFLLENBQUNpQixjQUFjO0FBQUEsRUFDN0M7QUFFRCxJQUFNQyxXQUFXLEdBQUdDLHVCQUFXLENBQUNwQyxHQUFHLENBQUNxQyw4QkFBa0IsQ0FBQztBQUVoRCxTQUFTQyxpQkFBaUJBLENBQUEsRUFBRztFQUNsQyxJQUFNQyxRQUFRLEdBQUcsSUFBQUMsdUJBQVcsRUFBQyxDQUFDO0VBQzlCLElBQU1DLGlCQUFpQixHQUFHLElBQUFDLHVCQUFXLEVBQUMsVUFBQ0MsS0FBWTtJQUFBLE9BQUtBLEtBQUssQ0FBQ0MsSUFBSSxDQUFDQyxXQUFXLENBQUNDLE1BQU07RUFBQSxFQUFDO0VBQ3RGLElBQU1DLElBQUksR0FBRyxJQUFBQyxrQkFBTyxFQUFDLENBQUM7RUFFdEIsSUFBQUMsZ0JBQUEsR0FBZ0MsSUFBQUMsMkJBQWUsRUFDN0MsdUJBQXVCLEVBQ3ZCVCxpQkFBaUIsQ0FBQ1UsUUFBUSxJQUFJLFFBQ2hDLENBQUM7SUFBQUMsaUJBQUEsT0FBQUMsZUFBQSxhQUFBSixnQkFBQTtJQUhNRSxRQUFRLEdBQUFDLGlCQUFBO0lBQUVFLFdBQVcsR0FBQUYsaUJBQUE7RUFJNUIsSUFBQUcsaUJBQUEsR0FBMEIsSUFBQUwsMkJBQWUsRUFDdkMsb0JBQW9CLEVBQ3BCVCxpQkFBaUIsQ0FBQ2UsS0FBSyxJQUFJQyx1QkFBZSxDQUFDTixRQUFRLENBQUMsQ0FBQyxDQUFDLENBQ3hELENBQUM7SUFBQU8saUJBQUEsT0FBQUwsZUFBQSxhQUFBRSxpQkFBQTtJQUhNQyxLQUFLLEdBQUFFLGlCQUFBO0lBQUVDLFFBQVEsR0FBQUQsaUJBQUE7RUFJdEIsSUFBQUUsaUJBQUEsR0FBNEIsSUFBQVYsMkJBQWUsRUFDekMsc0JBQXNCLEVBQ3RCVCxpQkFBaUIsQ0FBQ29CLE1BQU0sSUFBSSxFQUM5QixDQUFDO0lBQUFDLGlCQUFBLE9BQUFULGVBQUEsYUFBQU8saUJBQUE7SUFITUMsTUFBTSxHQUFBQyxpQkFBQTtJQUFFQyxTQUFTLEdBQUFELGlCQUFBO0VBSXhCLElBQUFFLGlCQUFBLEdBQXNDLElBQUFkLDJCQUFlLEVBQ25ELDBCQUEwQixFQUMxQlQsaUJBQWlCLENBQUN3QixXQUFXLElBQUksR0FDbkMsQ0FBQztJQUFBQyxpQkFBQSxPQUFBYixlQUFBLGFBQUFXLGlCQUFBO0lBSE1DLFdBQVcsR0FBQUMsaUJBQUE7SUFBRUMsY0FBYyxHQUFBRCxpQkFBQTtFQUlsQyxJQUFBRSxpQkFBQSxHQUF3QixJQUFBbEIsMkJBQWUsRUFBQyxvQkFBb0IsRUFBRVQsaUJBQWlCLENBQUM0QixJQUFJLElBQUksR0FBRyxDQUFDO0lBQUFDLGtCQUFBLE9BQUFqQixlQUFBLGFBQUFlLGlCQUFBO0lBQXJGQyxJQUFJLEdBQUFDLGtCQUFBO0lBQUVDLE9BQU8sR0FBQUQsa0JBQUE7RUFDcEIsSUFBQUUsa0JBQUEsR0FBOEIsSUFBQXRCLDJCQUFlLEVBQzNDLHVCQUF1QixFQUN2QlQsaUJBQWlCLENBQUNnQyxPQUFPLElBQUlDLGtDQUEwQixDQUFDdkIsUUFBUSxDQUNsRSxDQUFDO0lBQUF3QixrQkFBQSxPQUFBdEIsZUFBQSxhQUFBbUIsa0JBQUE7SUFITUMsT0FBTyxHQUFBRSxrQkFBQTtJQUFFQyxVQUFVLEdBQUFELGtCQUFBO0VBSTFCLElBQUFFLGtCQUFBLEdBQXNDLElBQUEzQiwyQkFBZSxFQUNuRCwyQkFBMkIsRUFDM0JULGlCQUFpQixDQUFDcUMsV0FBVyxJQUFJLEVBQ25DLENBQUM7SUFBQUMsa0JBQUEsT0FBQTFCLGVBQUEsYUFBQXdCLGtCQUFBO0lBSE1DLFdBQVcsR0FBQUMsa0JBQUE7SUFBRUMsY0FBYyxHQUFBRCxrQkFBQTtFQUlsQyxJQUFBRSxTQUFBLEdBQThELElBQUFDLGVBQVEsRUFBQyxLQUFLLENBQUM7SUFBQUMsVUFBQSxPQUFBOUIsZUFBQSxhQUFBNEIsU0FBQTtJQUF0RUcsdUJBQXVCLEdBQUFELFVBQUE7SUFBRUUsMEJBQTBCLEdBQUFGLFVBQUE7RUFDMUQsSUFBQUcsVUFBQSxHQUEwRCxJQUFBSixlQUFRLEVBQUMsRUFBRSxDQUFDO0lBQUFLLFVBQUEsT0FBQWxDLGVBQUEsYUFBQWlDLFVBQUE7SUFBL0RFLHFCQUFxQixHQUFBRCxVQUFBO0lBQUVFLHdCQUF3QixHQUFBRixVQUFBO0VBQ3RELElBQUFHLFVBQUEsR0FBOEMsSUFBQVIsZUFBUSxFQUFDLEtBQUssQ0FBQztJQUFBUyxVQUFBLE9BQUF0QyxlQUFBLGFBQUFxQyxVQUFBO0lBQXRERSxlQUFlLEdBQUFELFVBQUE7SUFBRUUsa0JBQWtCLEdBQUFGLFVBQUE7RUFDMUMsSUFBQUcsVUFBQSxHQUF3QyxJQUFBWixlQUFRLEVBQUMsRUFBRSxDQUFDO0lBQUFhLFVBQUEsT0FBQTFDLGVBQUEsYUFBQXlDLFVBQUE7SUFBN0NFLFlBQVksR0FBQUQsVUFBQTtJQUFFRSxlQUFlLEdBQUFGLFVBQUE7RUFDcEMsSUFBQUcsVUFBQSxHQUFrQyxJQUFBaEIsZUFBUSxFQUFDLEtBQUssQ0FBQztJQUFBaUIsV0FBQSxPQUFBOUMsZUFBQSxhQUFBNkMsVUFBQTtJQUExQ0UsU0FBUyxHQUFBRCxXQUFBO0lBQUVFLFlBQVksR0FBQUYsV0FBQTtFQUU5QixJQUFNRyxrQkFBa0IsR0FBRyxTQUFyQkEsa0JBQWtCQSxDQUFJQyxLQUFnRCxFQUFLO0lBQy9FLElBQUksT0FBT0EsS0FBSyxLQUFLLFFBQVEsRUFBRTtNQUM3QmpELFdBQVcsQ0FBQ2lELEtBQUssQ0FBQztNQUNsQjVDLFFBQVEsQ0FBQ0YsdUJBQWUsQ0FBQzhDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO01BQ25DM0IsVUFBVSxDQUFDRixrQ0FBMEIsQ0FBQzZCLEtBQUssQ0FBQyxDQUFDO01BQzdDVixrQkFBa0IsQ0FBQyxLQUFLLENBQUM7TUFDekJJLGVBQWUsQ0FBQyxFQUFFLENBQUM7SUFDckI7RUFDRixDQUFDO0VBRUQsSUFBTU8sZ0JBQWdCLEdBQUcsU0FBbkJBLGdCQUFnQkEsQ0FBSUQsS0FBZ0QsRUFBSztJQUM3RSxJQUFJLE9BQU9BLEtBQUssS0FBSyxRQUFRLEVBQUU7TUFDN0I1QyxRQUFRLENBQUM0QyxLQUFLLENBQUM7SUFDakI7RUFDRixDQUFDO0VBRUQsSUFBTUUsY0FBYyxHQUFHLFNBQWpCQSxjQUFjQSxDQUFJaEgsQ0FBc0MsRUFBSztJQUNqRXNFLFNBQVMsQ0FBQ3RFLENBQUMsQ0FBQ2lILE1BQU0sQ0FBQ0gsS0FBSyxDQUFDO0lBQ3pCO0lBQ0FWLGtCQUFrQixDQUFDLEtBQUssQ0FBQztJQUN6QkksZUFBZSxDQUFDLEVBQUUsQ0FBQztFQUNyQixDQUFDO0VBRUQsSUFBTVUsbUJBQW1CLEdBQUcsU0FBdEJBLG1CQUFtQkEsQ0FBSUosS0FBZSxFQUFLO0lBQy9DcEMsY0FBYyxDQUFDb0MsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0VBQzFCLENBQUM7RUFFRCxJQUFNSyxZQUFZLEdBQUcsU0FBZkEsWUFBWUEsQ0FBSUwsS0FBZSxFQUFLO0lBQ3hDaEMsT0FBTyxDQUFDZ0MsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0VBQ25CLENBQUM7RUFFRCxJQUFNTSxlQUFlLEdBQUcsU0FBbEJBLGVBQWVBLENBQUlwSCxDQUFzQyxFQUFLO0lBQ2xFbUYsVUFBVSxDQUFDbkYsQ0FBQyxDQUFDaUgsTUFBTSxDQUFDSCxLQUFLLENBQUM7SUFDMUJWLGtCQUFrQixDQUFDLEtBQUssQ0FBQztJQUN6QkksZUFBZSxDQUFDLEVBQUUsQ0FBQztFQUNyQixDQUFDO0VBRUQsSUFBTWEsbUJBQW1CLEdBQUcsU0FBdEJBLG1CQUFtQkEsQ0FBSXJILENBQXNDLEVBQUs7SUFDdEV1RixjQUFjLENBQUN2RixDQUFDLENBQUNpSCxNQUFNLENBQUNILEtBQUssQ0FBQztFQUNoQyxDQUFDO0VBRUQsSUFBTVEseUJBQXlCLEdBQUcsU0FBNUJBLHlCQUF5QkEsQ0FBSXRILENBQXNDLEVBQUs7SUFDNUU0RiwwQk