kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
337 lines (335 loc) • 57.9 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.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 = _interopRequireDefault(require("../config/models.json"));
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["default"][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 || 'http://localhost:11434/api'),
_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["default"][value][0]);
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);
});
AssistantModel = (0, _core.GetAssistantModelByProvider)({
provider: provider
});
_context.next = 6;
return Promise.race([AssistantModel === null || AssistantModel === void 0 ? void 0 : AssistantModel.testConnection(apiKey, model), timeoutPromise]);
case 6:
success = _context.sent;
_errorMessage = !success ? provider === 'ollama' ? 'Connection failed: maybe invalid Ollama Base URL' : 'Connection failed: maybe invalid API Key' : '';
setConnectionError(!success);
setErrorMessage(_errorMessage);
dispatch((0, _actions.updateAiAssistantConfig)({
provider: provider,
model: model,
apiKey: apiKey,
baseUrl: baseUrl,
isReady: success,
temperature: temperature,
topP: topP,
mapboxToken: mapboxToken
}));
_context.next = 17;
break;
case 13:
_context.prev = 13;
_context.t0 = _context["catch"](1);
setConnectionError(true);
setErrorMessage(_context.t0 instanceof Error ? _context.t0.message : 'Connection failed');
case 17:
_context.prev = 17;
setIsRunning(false);
return _context.finish(17);
case 20:
case "end":
return _context.stop();
}
}, _callee, null, [[1, 13, 17, 20]]);
}));
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["default"]),
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["default"][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.placeholder"
}))), /*#__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(_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.baseUrl.placeholder"
}))), /*#__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: intl.formatMessage({
id: 'aiAssistantManager.baseUrl.placeholder'
}),
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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfc3R5bGVkQ29tcG9uZW50cyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfcmVhY3RSZWR1eCIsIl9jb21wb25lbnRzIiwiX2FwaUtleSIsIl9tb2RlbHMiLCJfdXNlaG9va3NUcyIsIl9jb3JlIiwiX2FjdGlvbnMiLCJfcmVhY3RJbnRsIiwiX3RlbXBsYXRlT2JqZWN0IiwiX3RlbXBsYXRlT2JqZWN0MiIsIl90ZW1wbGF0ZU9iamVjdDMiLCJfdGVtcGxhdGVPYmplY3Q0IiwiX3RlbXBsYXRlT2JqZWN0NSIsIl90ZW1wbGF0ZU9iamVjdDYiLCJfdGVtcGxhdGVPYmplY3Q3IiwiX3RlbXBsYXRlT2JqZWN0OCIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiX3R5cGVvZiIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIlNlY3Rpb25UaXRsZSIsInN0eWxlZCIsImRpdiIsIl90YWdnZWRUZW1wbGF0ZUxpdGVyYWwyIiwicHJvcHMiLCJ0aGVtZSIsImlucHV0Rm9udFNpemUiLCJlZmZlY3RQYW5lbFRleHRTZWNvbmRhcnkxIiwiU3R5bGVkQWlBc3Npc3RhbnRDb25maWciLCJwcmltYXJ5QnRuRm9udFNpemVEZWZhdWx0IiwiYm94U2hhZG93IiwiZ2VvY29kZXJJbnB1dEhlaWdodCIsInN1YnRleHRDb2xvciIsIk9sbGFtYU1vZGVsSW5wdXRXcmFwcGVyIiwiU3R5bGVkV3JhcHBlciIsIlN0eWxlZEl0ZW1TZWxlY3RvciIsIkl0ZW1TZWxlY3RvciIsImFjdGl2ZUNvbG9yIiwiU3R5bGVTbGlkZXJXcmFwcGVyIiwiU3R5bGVkQnV0dG9uIiwiU3R5bGVFcnJvck1lc3NhZ2UiLCJlcnJvckNvbG9yIiwiZXJyb3JUZXh0Q29sb3IiLCJSYW5nZVNsaWRlciIsImFwcEluamVjdG9yIiwiUmFuZ2VTbGlkZXJGYWN0b3J5IiwiQWlBc3Npc3RhbnRDb25maWciLCJkaXNwYXRjaCIsInVzZURpc3BhdGNoIiwiYWlBc3Npc3RhbnRDb25maWciLCJ1c2VTZWxlY3RvciIsInN0YXRlIiwiZGVtbyIsImFpQXNzaXN0YW50IiwiY29uZmlnIiwiaW50bCIsInVzZUludGwiLCJfdXNlTG9jYWxTdG9yYWdlIiwidXNlTG9jYWxTdG9yYWdlIiwicHJvdmlkZXIiLCJfdXNlTG9jYWxTdG9yYWdlMiIsIl9zbGljZWRUb0FycmF5MiIsInNldFByb3ZpZGVyIiwiX3VzZUxvY2FsU3RvcmFnZTMiLCJtb2RlbCIsIlBST1ZJREVSX01PREVMUyIsIl91c2VMb2NhbFN0b3JhZ2U0Iiwic2V0TW9kZWwiLCJfdXNlTG9jYWxTdG9yYWdlNSIsImFwaUtleSIsIl91c2VMb2NhbFN0b3JhZ2U2Iiwic2V0QXBpS2V5IiwiX3VzZUxvY2FsU3RvcmFnZTciLCJ0ZW1wZXJhdHVyZSIsIl91c2VMb2NhbFN0b3JhZ2U4Iiwic2V0VGVtcGVyYXR1cmUiLCJfdXNlTG9jYWxTdG9yYWdlOSIsInRvcFAiLCJfdXNlTG9jYWxTdG9yYWdlMTAiLCJzZXRUb3BQIiwiX3VzZUxvY2FsU3RvcmFnZTExIiwiYmFzZVVybCIsIl91c2VMb2NhbFN0b3JhZ2UxMiIsInNldEJhc2VVcmwiLCJfdXNlTG9jYWxTdG9yYWdlMTMiLCJtYXBib3hUb2tlbiIsIl91c2VMb2NhbFN0b3JhZ2UxNCIsInNldE1hcGJveFRva2VuIiwiX3VzZVN0YXRlIiwidXNlU3RhdGUiLCJfdXNlU3RhdGUyIiwib2xsYW1hTW9kZWxJbnB1dENoZWNrZWQiLCJzZXRPbGxhbWFNb2RlbElucHV0Q2hlY2tlZCIsIl91c2VTdGF0ZTMiLCJfdXNlU3RhdGU0Iiwib2xsYW1hTW9kZWxJbnB1dFZhbHVlIiwic2V0T2xsYW1hTW9kZWxJbnB1dFZhbHVlIiwiX3VzZVN0YXRlNSIsIl91c2VTdGF0ZTYiLCJjb25uZWN0aW9uRXJyb3IiLCJzZXRDb25uZWN0aW9uRXJyb3IiLCJfdXNlU3RhdGU3IiwiX3VzZVN0YXRlOCIsImVycm9yTWVzc2FnZSIsInNldEVycm9yTWVzc2FnZSIsIl91c2VTdGF0ZTkiLCJfdXNlU3RhdGUxMCIsImlzUnVubmluZyIsInNldElzUnVubmluZyIsIm9uQWlQcm92aWRlclNlbGVjdCIsInZhbHVlIiwib25MTE1Nb2RlbFNlbGVjdCIsIm9uQXBpS2V5Q2hhbmdlIiwidGFyZ2V0Iiwib25UZW1wZXJhdHVyZUNoYW5nZSIsIm9uVG9wUENoYW5nZSIsIm9uQmFzZVVybENoYW5nZSIsIm9uTWFwYm94VG9rZW5DaGFuZ2UiLCJvbk9sbGFtYU1vZGVsSW5wdXRDaGVja2VkIiwiY2hlY2tlZCIsIm9uT2xsYW1hTW9kZWxJbnB1dFZhbHVlQ2hhbmdlIiwib25TdGFydENoYXQiLCJfcmVmIiwiX2FzeW5jVG9HZW5lcmF0b3IyIiwiX3JlZ2VuZXJhdG9yIiwibWFyayIsIl9jYWxsZWUiLCJ0aW1lb3V0UHJvbWlzZSIsIkFzc2lzdGFudE1vZGVsIiwic3VjY2VzcyIsIl9lcnJvck1lc3NhZ2UiLCJ3cmFwIiwiX2NhbGxlZSQiLCJfY29udGV4dCIsInByZXYiLCJuZXh0IiwiUHJvbWlzZSIsIl8iLCJyZWplY3QiLCJzZXRUaW1lb3V0IiwiRXJyb3IiLCJHZXRBc3Npc3RhbnRNb2RlbEJ5UHJvdmlkZXIiLCJyYWNlIiwidGVzdENvbm5lY3Rpb24iLCJzZW50IiwidXBkYXRlQWlBc3Npc3RhbnRDb25maWciLCJpc1JlYWR5IiwidDAiLCJtZXNzYWdlIiwiZmluaXNoIiwic3RvcCIsImFwcGx5IiwiYXJndW1lbnRzIiwiY3JlYXRlRWxlbWVudCIsImNsYXNzTmFtZSIsIlBhbmVsTGFiZWxXcmFwcGVyIiwiRm9ybWF0dGVkTWVzc2FnZSIsImlkIiwic2VsZWN0ZWRJdGVtcyIsIm9wdGlvbnMiLCJrZXlzIiwibXVsdGlTZWxlY3QiLCJkaXNhYmxlZCIsIm9uQ2hhbmdlIiwiZmlsdGVyT3B0aW9uIiwiZ2V0T3B0aW9uVmFsdWUiLCJvcCIsImRpc3BsYXlPcHRpb24iLCJzZWFyY2hhYmxlIiwic2hvd0Fycm93IiwicGxhY2Vob2xkZXIiLCJzdHlsZSIsIndpZHRoIiwiQ2hlY2tib3giLCJsYWJlbCIsIklucHV0IiwidHlwZSIsIkZyYWdtZW50IiwiaGVpZ2h0IiwiZm9ybWF0TWVzc2FnZSIsInNob3dJbnB1dCIsImlzUmFuZ2VkIiwidmFsdWUwIiwidmFsdWUxIiwicmFuZ2UiLCJzdGVwIiwiQnV0dG9uIiwib25DbGljayIsIkxvYWRpbmdTcGlubmVyIiwic2l6ZSJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21wb25lbnRzL2FpLWFzc2lzdGFudC1jb25maWcudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCBSZWFjdCwge3VzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ3N0eWxlZC1jb21wb25lbnRzJztcbmltcG9ydCB7dXNlU2VsZWN0b3IsIHVzZURpc3BhdGNofSBmcm9tICdyZWFjdC1yZWR1eCc7XG5pbXBvcnQge1xuICBJbnB1dCxcbiAgUGFuZWxMYWJlbFdyYXBwZXIsXG4gIEl0ZW1TZWxlY3RvcixcbiAgUmFuZ2VTbGlkZXJGYWN0b3J5LFxuICBCdXR0b24sXG4gIExvYWRpbmdTcGlubmVyLFxuICBhcHBJbmplY3RvcixcbiAgQ2hlY2tib3hcbn0gZnJvbSAnQGtlcGxlci5nbC9jb21wb25lbnRzJztcbmltcG9ydCB7U3RhdGV9IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCBBcGlLZXkgZnJvbSAnLi4vaWNvbnMvYXBpLWtleSc7XG5pbXBvcnQgUFJPVklERVJfTU9ERUxTIGZyb20gJy4uL2NvbmZpZy9tb2RlbHMuanNvbic7XG5pbXBvcnQge3VzZUxvY2FsU3RvcmFnZX0gZnJvbSAndXNlaG9va3MtdHMnO1xuaW1wb3J0IHtHZXRBc3Npc3RhbnRNb2RlbEJ5UHJvdmlkZXJ9IGZyb20gJ0BvcGVuYXNzaXN0YW50L2NvcmUnO1xuaW1wb3J0IHt1cGRhdGVBaUFzc2lzdGFudENvbmZpZ30gZnJvbSAnLi4vYWN0aW9ucyc7XG5pbXBvcnQge0Zvcm1hdHRlZE1lc3NhZ2UsIHVzZUludGx9IGZyb20gJ3JlYWN0LWludGwnO1xuXG5jb25zdCBTZWN0aW9uVGl0bGUgPSBzdHlsZWQuZGl2YFxuICBmb250LXNpemU6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuaW5wdXRGb250U2l6ZX07XG4gIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmVmZmVjdFBhbmVsVGV4dFNlY29uZGFyeTF9O1xuICB0ZXh0LXRyYW5zZm9ybTogY2FwaXRhbGl6ZTtcbmA7XG5cbmNvbnN0IFN0eWxlZEFpQXNzaXN0YW50Q29uZmlnID0gc3R5bGVkLmRpdmBcbiAgcGFkZGluZzogMTJweDtcbiAgZm9udC1zaXplOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnByaW1hcnlCdG5Gb250U2l6ZURlZmF1bHR9O1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBnYXA6IDEycHg7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG5cbiAgLmFwaS1rZXktaW5wdXQge1xuICAgIGJveC1zaGFkb3c6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuYm94U2hhZG93fTtcbiAgICB3aWR0aDogMTAwJTtcbiAgICAuYXBpLWtleS1pbnB1dF9faWNvbiB7XG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICBoZWlnaHQ6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuZ2VvY29kZXJJbnB1dEhlaWdodH1weDtcbiAgICAgIHdpZHRoOiAzMHB4O1xuICAgICAgcGFkZGluZy1sZWZ0OiA2cHg7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgICAgY29sb3I6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuc3VidGV4dENvbG9yfTtcbiAgICB9XG5cbiAgICBpbnB1dCB7XG4gICAgICBwYWRkaW5nOiA0cHggMzZweDtcbiAgICAgIGhlaWdodDogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5nZW9jb2RlcklucHV0SGVpZ2h0fXB4O1xuICAgICAgY2FyZXQtY29sb3I6IHVuc2V0O1xuICAgIH1cbiAgfVxuYDtcblxuLy8gT2xsYW1hIG1vZGVsIGlucHV0IHdyYXBwZXI6IGNoZWNrYm94ICsgJ0lucHV0IE1vZGVsIE5hbWU6JyArIGlucHV0XG4vLyBhbGwgY2hpbGRyZW4gZWxlbWVudCBoYXZlIHdpZHRoIGJhc2VkIG9uIHRoZSBjb250ZW50XG5jb25zdCBPbGxhbWFNb2RlbElucHV0V3JhcHBlciA9IHN0eWxlZC5kaXZgXG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGdhcDogNHB4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuYDtcblxuY29uc3QgU3R5bGVkV3JhcHBlciA9IHN0eWxlZC5kaXZgXG4gIGRpc3BsYXk6IGZsZXg7XG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbmA7XG5cbmNvbnN0IFN0eWxlZEl0ZW1TZWxlY3RvciA9IHN0eWxlZChJdGVtU2VsZWN0b3IpYFxuICAuaXRlbS1zZWxlY3Rvcl9fZHJvcGRvd24ge1xuICAgIHBhZGRpbmctbGVmdDogMTBweDtcbiAgICBib3JkZXItcmFkaXVzOiA0cHg7XG4gIH1cbiAgLmFjdGl2ZSB7XG4gICAgYm9yZGVyLWNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmFjdGl2ZUNvbG9yfTtcbiAgICBib3JkZXItcmFkaXVzOiA0cHggNHB4IDBweCAwcHggIWltcG9ydGFudDtcbiAgfVxuICB3aWR0aDogMTAwJTtcbmA7XG5cbmNvbnN0IFN0eWxlU2xpZGVyV3JhcHBlciA9IHN0eWxlZC5kaXZgXG4gIHdpZHRoOiAxMDAlO1xuICBhbGlnbi1zZWxmOiBmbGV4LXN0YXJ0O1xuICBoZWlnaHQ6IDMycHg7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIC5rZy1yYW5nZS1zbGlkZXJfX2lucHV0IHtcbiAgICBoZWlnaHQ6IDMycHg7XG4gICAgdGV4dC1hbGlnbjogY2VudGVyO1xuICAgIHBhZGRpbmc6IDNweCA2cHg7XG4gIH1cbiAgLmtnLXNsaWRlciB7XG4gICAgcGFkZGluZy1sZWZ0OiA2cHg7XG4gIH1cbiAgLmtnLXJhbmdlLXNsaWRlciB7XG4gICAgcGFkZGluZzogMHB4ICFpbXBvcnRhbnQ7XG4gIH1cbmA7XG5cbmNvbnN0IFN0eWxlZEJ1dHRvbiA9IHN0eWxlZC5kaXZgXG4gIHdpZHRoOiAxMDAlO1xuICBhbGlnbi1zZWxmOiBmbGV4LXN0YXJ0O1xuICBtYXJnaW4tdG9wOiAxMnB4O1xuXG4gIGJ1dHRvbiBkaXYge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBnYXA6IDRweDtcbiAgICBtYXJnaW4tcmlnaHQ6IDRweDtcbiAgfVxuYDtcblxuY29uc3QgU3R5bGVFcnJvck1lc3NhZ2UgPSBzdHlsZWQuZGl2YFxuICBmb250LXNpemU6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUucHJpbWFyeUJ0bkZvbnRTaXplRGVmYXVsdH07XG4gIGJhY2tncm91bmQtY29sb3I6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuZXJyb3JDb2xvcn07XG4gIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgcGFkZGluZzogNHB4IDhweDtcbiAgY29sb3I6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuZXJyb3JUZXh0Q29sb3J9O1xuYDtcblxuY29uc3QgUmFuZ2VTbGlkZXIgPSBhcHBJbmplY3Rvci5nZXQoUmFuZ2VTbGlkZXJGYWN0b3J5KTtcblxuZXhwb3J0IGZ1bmN0aW9uIEFpQXNzaXN0YW50Q29uZmlnKCkge1xuICBjb25zdCBkaXNwYXRjaCA9IHVzZURpc3BhdGNoKCk7XG4gIGNvbnN0IGFpQXNzaXN0YW50Q29uZmlnID0gdXNlU2VsZWN0b3IoKHN0YXRlOiBTdGF0ZSkgPT4gc3RhdGUuZGVtby5haUFzc2lzdGFudC5jb25maWcpO1xuICBjb25zdCBpbnRsID0gdXNlSW50bCgpO1xuXG4gIGNvbnN0IFtwcm92aWRlciwgc2V0UHJvdmlkZXJdID0gdXNlTG9jYWxTdG9yYWdlKFxuICAgICdhaS1hc3Npc3RhbnQtcHJvdmlkZXInLFxuICAgIGFpQXNzaXN0YW50Q29uZmlnLnByb3ZpZGVyIHx8ICdvcGVuYWknXG4gICk7XG4gIGNvbnN0IFttb2RlbCwgc2V0TW9kZWxdID0gdXNlTG9jYWxTdG9yYWdlKFxuICAgICdhaS1hc3Npc3RhbnQtbW9kZWwnLFxuICAgIGFpQXNzaXN0YW50Q29uZmlnLm1vZGVsIHx8IFBST1ZJREVSX01PREVMU1twcm92aWRlcl1bMF1cbiAgKTtcbiAgY29uc3QgW2FwaUtleSwgc2V0QXBpS2V5XSA9IHVzZUxvY2FsU3RvcmFnZShcbiAgICAnYWktYXNzaXN0YW50LWFwaS1rZXknLFxuICAgIGFpQXNzaXN0YW50Q29uZmlnLmFwaUtleSB8fCAnJ1xuICApO1xuICBjb25zdCBbdGVtcGVyYXR1cmUsIHNldFRlbXBlcmF0dXJlXSA9IHVzZUxvY2FsU3RvcmFnZShcbiAgICAnYWktYXNzaXN0YW50LXRlbXBlcmF0dXJlJyxcbiAgICBhaUFzc2lzdGFudENvbmZpZy50ZW1wZXJhdHVyZSB8fCAwLjBcbiAgKTtcbiAgY29uc3QgW3RvcFAsIHNldFRvcFBdID0gdXNlTG9jYWxTdG9yYWdlKCdhaS1hc3Npc3RhbnQtdG9wLXAnLCBhaUFzc2lzdGFudENvbmZpZy50b3BQIHx8IDEuMCk7XG4gIGNvbnN0IFtiYXNlVXJsLCBzZXRCYXNlVXJsXSA9IHVzZUxvY2FsU3RvcmFnZShcbiAgICAnYWktYXNzaXN0YW50LWJhc2UtdXJsJyxcbiAgICBhaUFzc2lzdGFudENvbmZpZy5iYXNlVXJsIHx8ICdodHRwOi8vbG9jYWxob3N0OjExNDM0L2FwaSdcbiAgKTtcbiAgY29uc3QgW21hcGJveFRva2VuLCBzZXRNYXBib3hUb2tlbl0gPSB1c2VMb2NhbFN0b3JhZ2UoXG4gICAgJ2FpLWFzc2lzdGFudC1tYXBib3gtdG9rZW4nLFxuICAgIGFpQXNzaXN0YW50Q29uZmlnLm1hcGJveFRva2VuIHx8ICcnXG4gICk7XG4gIGNvbnN0IFtvbGxhbWFNb2RlbElucHV0Q2hlY2tlZCwgc2V0T2xsYW1hTW9kZWxJbnB1dENoZWNrZWRdID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbb2xsYW1hTW9kZWxJbnB1dFZhbHVlLCBzZXRPbGxhbWFNb2RlbElucHV0VmFsdWVdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbY29ubmVjdGlvbkVycm9yLCBzZXRDb25uZWN0aW9uRXJyb3JdID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbZXJyb3JNZXNzYWdlLCBzZXRFcnJvck1lc3NhZ2VdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXNSdW5uaW5nLCBzZXRJc1J1bm5pbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuXG4gIGNvbnN0IG9uQWlQcm92aWRlclNlbGVjdCA9ICh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG9iamVjdCB8IG51bGwpID0+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgc2V0UHJvdmlkZXIodmFsdWUpO1xuICAgICAgc2V0TW9kZWwoUFJPVklERVJfTU9ERUxTW3ZhbHVlXVswXSk7XG4gICAgICBzZXRDb25uZWN0aW9uRXJyb3IoZmFsc2UpO1xuICAgICAgc2V0RXJyb3JNZXNzYWdlKCcnKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3Qgb25MTE1Nb2RlbFNlbGVjdCA9ICh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG9iamVjdCB8IG51bGwpID0+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgc2V0TW9kZWwodmFsdWUpO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCBvbkFwaUtleUNoYW5nZSA9IChlOiBSZWFjdC5DaGFuZ2VFdmVudDxIVE1MSW5wdXRFbGVtZW50PikgPT4ge1xuICAgIHNldEFwaUtleShlLnRhcmdldC52YWx1ZSk7XG4gICAgLy8gcmVzZXQgcHJldmlvdXMga2V5IGVycm9yIGlmIGFueVxuICAgIHNldENvbm5lY3Rpb25FcnJvcihmYWxzZSk7XG4gICAgc2V0RXJyb3JNZXNzYWdlKCcnKTtcbiAgfTtcblxuICBjb25zdCBvblRlbXBlcmF0dXJlQ2hhbmdlID0gKHZhbHVlOiBudW1iZXJbXSkgPT4ge1xuICAgIHNldFRlbXBlcmF0dXJlKHZhbHVlWzFdKTtcbiAgfTtcblxuICBjb25zdCBvblRvcFBDaGFuZ2UgPSAodmFsdWU6IG51bWJlcltdKSA9PiB7XG4gICAgc2V0VG9wUCh2YWx1ZVsxXSk7XG4gIH07XG5cbiAgY29uc3Qgb25CYXNlVXJsQ2hhbmdlID0gKGU6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB7XG4gICAgc2V0QmFzZVVybChlLnRhcmdldC52YWx1ZSk7XG4gICAgc2V0Q29ubmVjdGlvbkVycm9yKGZhbHNlKTtcbiAgICBzZXRFcnJvck1lc3NhZ2UoJycpO1xuICB9O1xuXG4gIGNvbnN0IG9uTWFwYm94VG9rZW5DaGFuZ2UgPSAoZTogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHtcbiAgICBzZXRNYXBib3hUb2tlbihlLnRhcmdldC52YWx1ZSk7XG4gIH07XG5cbiAgY29uc3Qgb25PbGxhbWFNb2RlbElucHV0Q2hlY2tlZCA9IChlOiBSZWFjdC5DaGFuZ2VFdmVudDxIVE1MSW5wdXRFbGVtZW50PikgPT4ge1xuICAgIHNldE9sbGFtYU1vZGVsSW5wdXRDaGVja2VkKGUudGFyZ2V0LmNoZWNrZWQpO1xuICAgIGlmICghZS50YXJnZXQuY2hlY2tlZCkge1xuICAgICAgLy8gdXNlIG1vZGVsIGZyb20gc2VsZWN0b3JcbiAgICAgIHNldE1vZGVsKCcnKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3Qgb25PbGxhbWFNb2RlbElucHV0VmFsdWVDaGFuZ2UgPSAoZTogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHtcbiAgICBzZXRPbGxhbWFNb2RlbElucHV0VmFsdWUoZS50YXJnZXQudmFsdWUpO1xuICAgIHNldE1vZGVsKGUudGFyZ2V0LnZhbHVlKTtcbiAgfTtcblxuICBjb25zdCBvblN0YXJ0Q2hhdCA9IGFzeW5jICgpID0+IHtcbiAgICBzZXRJc1J1bm5pbmcodHJ1ZSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRpbWVvdXRQcm9taXNlID0gbmV3IFByb21pc2UoKF8sIHJlamVjdCkgPT4ge1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHJlamVjdChuZXcgRXJyb3IoJ0Nvbm5lY3Rpb24gdGltZW91dCBhZnRlciAxNSBzZWNvbmRzJykpLCAxNTAwMCk7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgQXNzaXN0YW50TW9kZWwgPSBHZXRBc3Npc3RhbnRNb2RlbEJ5UHJvdmlkZXIoe1xuICAgICAgICBwcm92aWRlcjogcHJvdmlkZXJcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzdWNjZXNzID0gKGF3YWl0IFByb21pc2UucmFjZShbXG4gICAgICAgIEFzc2lzdGFudE1vZGVsPy50ZXN0Q29ubmVjdGlvbihhcGlLZXksIG1vZGVsKSxcbiAgICAgICAgdGltZW91dFByb21pc2VcbiAgICAgIF0pKSBhcyBib29sZWFuO1xuXG4gICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSAhc3VjY2Vzc1xuICAgICAgICA/IHByb3ZpZGVyID09PSAnb2xsYW1hJ1xuICAgICAgICAgID8gJ0Nvbm5lY3Rpb24gZmFpbGVkOiBtYXliZSBpbnZhbGlkIE9sbGFtYSBCYXNlIFVSTCdcbiAgICAgICAgICA6ICdDb25uZWN0aW9uIGZhaWxlZDogbWF5YmUgaW52YWxpZCBBUEkgS2V5J1xuICAgICAgICA6ICcnO1xuICAgICAgc2V0Q29ubmVjdGlvbkVycm9yKCFzdWNjZXNzKTtcbiAgICAgIHNldEVycm9yTWVzc2FnZShlcnJvck1lc3NhZ2UpO1xuICAgICAgZGlzcGF0Y2goXG4gICAgICAgIHVwZGF0ZUFpQXNzaXN0YW50Q29uZmlnKHtcbiAgICAgICAgICBwcm92aWRlcjogcHJvdmlkZXIsXG4gICAgICAgICAgbW9kZWw6IG1vZGVsLFxuICAgICAgICAgIGFwaUtleTogYXBpS2V5LFxuICAgICAgICAgIGJhc2VVcmw6IGJhc2VVcmwsXG4gICAgICAgICAgaXNSZWFkeTogc3VjY2VzcyxcbiAgICAgICAgICB0ZW1wZXJhdHVyZTogdGVtcGVyYXR1cmUsXG4gICAgICAgICAgdG9wUDogdG9wUCxcbiAgICAgICAgICBtYXBib3hUb2tlbjogbWFwYm94VG9rZW5cbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHNldENvbm5lY3Rpb25FcnJvcih0cnVlKTtcbiAgICAgIHNldEVycm9yTWVzc2FnZShlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6ICdDb25uZWN0aW9uIGZhaWxlZCcpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBzZXRJc1J1bm5pbmcoZmFsc2UpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gKFxuICAgIDxTdHlsZWRBaUFzc2lzdGFudENvbmZpZyBjbGFzc05hbWU9XCJhaS1hc3Npc3RhbnQtY29uZmlnX190eXBlXCI+XG4gICAgICA8UGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgIDxTZWN0aW9uVGl0bGU+XG4gICAgICAgICAgPEZvcm1hdHRlZE1lc3NhZ2UgaWQ9XCJhaUFzc2lzdGFudE1hbmFnZXIuYWlQcm92aWRlclwiIC8+XG4gICAgICAgIDwvU2VjdGlvblRpdGxlPlxuICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgIDxTdHlsZWRXcmFwcGVyPlxuICAgICAgICA8U3R5bGVkSXRlbVNlbGVjdG9yXG4gICAgICAgICAgc2VsZWN0ZWRJdGVtcz17cHJvdmlkZXJ9XG4gICAgICAgICAgb3B0aW9ucz17T2JqZWN0LmtleXMoUFJPVklERVJfTU9ERUxTKX1cbiAgICAgICAgICBtdWx0aVNlbGVjdD17ZmFsc2V9XG4gICAgICAgICAgZGlzYWJsZWQ9e2ZhbHNlfVxuICAgICAgICAgIG9uQ2hhbmdlPXtvbkFpUHJvdmlkZXJTZWxlY3R9XG4gICAgICAgICAgZmlsdGVyT3B0aW9uPVwibmFtZVwiXG4gICAgICAgICAgZ2V0T3B0aW9uVmFsdWU9e29wID0+IG9wfVxuICAgICAgICAgIGRpc3BsYXlPcHRpb249e29wID0+IG9wfVxuICAgICAgICAgIHNlYXJjaGFibGU9e2ZhbHNlfVxuICAgICAgICAgIHNob3dBcnJvdz17dHJ1ZX1cbiAgICAgICAgLz5cbiAgICAgIDwvU3R5bGVkV3JhcHBlcj5cbiAgICAgIDxQYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgPFNlY3Rpb25UaXRsZT5cbiAgICAgICAgICA8Rm9ybWF0dGVkTWVzc2FnZSBpZD1cImFpQXNzaXN0YW50TWFuYWdlci5sbG1Nb2RlbC50aXRsZVwiIC8+XG4gICAgICAgIDwvU2VjdGlvblRpdGxlPlxuICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgIHsoKHByb3ZpZGVyID09PSAnb2xsYW1hJyAmJiAhb2xsYW1hTW9kZWxJbnB1dENoZWNrZWQpIHx8IHByb3ZpZGVyICE9PSAnb2xsYW1hJykgJiYgKFxuICAgICAgICA8U3R5bGVkV3JhcHBlcj5cbiAgICAgICAgICA8U3R5bGVkSXRlbVNlbGVjdG9yXG4gICAgICAgICAgICBzZWxlY3RlZEl0ZW1zPXttb2RlbH1cbiAgICAgICAgICAgIG9wdGlvbnM9e1BST1ZJREVSX01PREVMU1twcm92aWRlcl19XG4gICAgICAgICAgICBtdWx0aVNlbGVjdD17ZmFsc2V9XG4gICAgICAgICAgICBkaXNhYmxlZD17cHJvdmlkZXIgPT09ICdvbGxhbWEnID8gb2xsYW1hTW9kZWxJbnB1dENoZWNrZWQgOiBmYWxzZX1cbiAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiU2VsZWN0IExMTSBNb2RlbFwiXG4gICAgICAgICAgICBvbkNoYW5nZT17b25MTE1Nb2RlbFNlbGVjdH1cbiAgICAgICAgICAgIGZpbHRlck9wdGlvbj1cIm5hbWVcIlxuICAgICAgICAgICAgZ2V0T3B0aW9uVmFsdWU9e29wID0+IG9wfVxuICAgICAgICAgICAgZGlzcGxheU9wdGlvbj17b3AgPT4gb3B9XG4gICAgICAgICAgICBzZWFyY2hhYmxlPXtmYWxzZX1cbiAgICAgICAgICAgIHNob3dBcnJvdz17dHJ1ZX1cbiAgICAgICAgICAvPlxuICAgICAgICA8L1N0eWxlZFdyYXBwZXI+XG4gICAgICApfVxuICAgICAge3Byb3ZpZGVyID09PSAnb2xsYW1hJyAmJiAoXG4gICAgICAgIDxPbGxhbWFNb2RlbElucHV0V3JhcHBlcj5cbiAgICAgICAgICA8ZGl2IHN0eWxlPXt7d2lkdGg6ICcyNTBweCd9fT5cbiAgICAgICAgICAgIDxDaGVja2JveFxuICAgICAgICAgICAgICBpZD1cIm9sbGFtYS1tb2RlbC1pbnB1dFwiXG4gICAgICAgICAgICAgIGxhYmVsPVwiSW5wdXQgTW9kZWwgTmFtZVwiXG4gICAgICAgICAgICAgIG9uQ2hhbmdlPXtvbk9sbGFtYU1vZGVsSW5wdXRDaGVja2VkfVxuICAgICAgICAgICAgICBjaGVja2VkPXtvbGxhbWFNb2RlbElucHV0Q2hlY2tlZH1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPElucHV0XG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICBvbkNoYW5nZT17b25PbGxhbWFNb2RlbElucHV0VmFsdWVDaGFuZ2V9XG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkVudGVyIE1vZGVsIE5hbWVcIlxuICAgICAgICAgICAgdmFsdWU9e29sbGFtYU1vZGVsSW5wdXRWYWx1ZX1cbiAgICAgICAgICAgIGRpc2FibGVkPXshb2xsYW1hTW9kZWxJbnB1dENoZWNrZWR9XG4gICAgICAgICAgLz5cbiAgICAgICAgPC9PbGxhbWFNb2RlbElucHV0V3JhcHBlcj5cbiAgICAgICl9XG4gICAgICB7cHJvdmlkZXIgIT09ICdvbGxhbWEnID8gKFxuICAgICAgICA8PlxuICAgICAgICAgIDxQYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgICAgIDxTZWN0aW9uVGl0bGU+XG4gICAgICAgICAgICAgIDxGb3JtYXR0ZWRNZXNzYWdlIGlkPVwiYWlBc3Npc3RhbnRNYW5hZ2VyLmFwaUtleS5wbGFjZWhvbGRlclwiIC8+XG4gICAgICAgICAgICA8L1NlY3Rpb25UaXRsZT5cbiAgICAgICAgICA8L1BhbmVsTGFiZWxXcmFwcGVyPlxuICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYXBpLWtleS1pbnB1dFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJhcGkta2V5LWlucHV0X19pY29uXCI+XG4gICAgICAgICAgICAgIDxBcGlLZXkgaGVpZ2h0PVwiMjBweFwiIC8+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxJbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgIG9uQ2hhbmdlPXtvbkFwaUtleUNoYW5nZX1cbiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9e2ludGwuZm9ybWF0TWVzc2FnZSh7aWQ6ICdhaUFzc2lzdGFudE1hbmFnZXIuYXBpS2V5LnBsYWNlaG9sZGVyJ30pfVxuICAgICAgICAgICAgICB2YWx1ZT17YXBpS2V5fVxuICAgICAgICAgICAgLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC8+XG4gICAgICApIDogKFxuICAgICAgICA8PlxuICAgICAgICAgIDxQYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgICAgIDxTZWN0aW9uVGl0bGU+XG4gICAgICAgICAgICAgIDxGb3JtYXR0ZWRNZXNzYWdlIGlkPVwiYWlBc3Npc3RhbnRNYW5hZ2VyLmJhc2VVcmwucGxhY2Vob2xkZXJcIiAvPlxuICAgICAgICAgICAgPC9TZWN0aW9uVGl0bGU+XG4gICAgICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImFwaS1rZXktaW5wdXRcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYXBpLWtleS1pbnB1dF9faWNvblwiPlxuICAgICAgICAgICAgICA8QXBpS2V5IGhlaWdodD1cIjIwcHhcIiAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8SW5wdXRcbiAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgICBvbkNoYW5nZT17b25CYXNlVXJsQ2hhbmdlfVxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj17aW50bC5mb3JtYXRNZXNzYWdlKHtpZDogJ2FpQXNzaXN0YW50TWFuYWdlci5iYXNlVXJsLnBsYWNlaG9sZGVyJ30pfVxuICAgICAgICAgICAgICB2YWx1ZT17YmFzZVVybH1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvPlxuICAgICAgKX1cbiAgICAgIHtjb25uZWN0aW9uRXJyb3IgJiYgKFxuICAgICAgICA8U3R5bGVFcnJvck1lc3NhZ2UgY2xhc3NOYW1lPVwiZXJyb3ItbWVzc2FnZVwiPntlcnJvck1lc3NhZ2V9PC9TdHlsZUVycm9yTWVzc2FnZT5cbiAgICAgICl9XG4gICAgICA8UGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgIDxTZWN0aW9uVGl0bGU+XG4gICAgICAgICAgPEZvcm1hdHRlZE1lc3NhZ2UgaWQ9XCJhaUFzc2lzdGFudE1hbmFnZXIudGVtcGVyYXR1cmUudGl0bGVcIiAvPlxuICAgICAgICA8L1NlY3Rpb25UaXRsZT5cbiAgICAgIDwvUGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICA8U3R5bGVTbGlkZXJXcmFwcGVyPlxuICAgICAgICA8UmFuZ2VTbGlkZXJcbiAgICAgICAgICBzaG93SW5wdXQ9e3RydWV9XG4gICAgICAgICAgaXNSYW5nZWQ9e2ZhbHNlfVxuICAgICAgICAgIHZhbHVlMD17MH1cbiAgICAgICAgICB2YWx1ZTE9e3RlbXBlcmF0dXJlfVxuICAgICAgICAgIG9uQ2hhbmdlPXtvblRlbXBlcmF0dXJlQ2hhbmdlfVxuICAgICAgICAgIHJhbmdlPXtbMCwgMl19XG4gICAgICAgICAgc3RlcD17MC4xfVxuICAgICAgICAvPlxuICAgICAgPC9TdHlsZVNsaWRlcldyYXBwZXI+XG4gICAgICA8UGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgIDxTZWN0aW9uVGl0bGU+XG4gICAgICAgICAgPEZvcm1hdHRlZE1lc3NhZ2UgaWQ9XCJhaUFzc2lzdGFudE1hbmFnZXIudG9wUC50aXRsZVwiIC8+XG4gICAgICAgIDwvU2VjdGlvblRpdGxlPlxuICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgIDxTdHlsZVNsaWRlcldyYXBwZXI+XG4gICAgICAgIDxSYW5nZVNsaWRlclxuICAgICAgICAgIHNob3dJbnB1dD17dHJ1ZX1cbiAgICAgICAgICBpc1JhbmdlZD17ZmFsc2V9XG4gICAgICAgICAgdmFsdWUwPXswfVxuICAgICAgICAgIHZhbHVlMT17dG9wUH1cbiAgICAgICAgICBvbkNoYW5nZT17b25Ub3BQQ2hhbmdlfVxuICAgICAgICAgIHJhbmdlPXtbMCwgMV19XG4gICAgICAgICAgc3RlcD17MC4xfVxuICAgICAgICAvPlxuICAgICAgPC9TdHlsZVNsaWRlcldyYXBwZXI+XG4gICAgICA8PlxuICAgICAgICA8UGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgICAgPFNlY3Rpb25UaXRsZT5NYXBib3ggVG9rZW4gKG9wdGlvbmFsIGZvciByb3V0ZS9pc29jaHJvbmUpPC9TZWN0aW9uVGl0bGU+XG4gICAgICAgIDwvUGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYXBpLWtleS1pbnB1dFwiPlxuICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYXBpLWtleS1pbnB1dF9faWNvblwiPlxuICAgICAgICAgICAgPEFwaUtleSBoZWlnaHQ9XCIyMHB4XCIgLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8SW5wdXRcbiAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgIG9uQ2hhbmdlPXtvbk1hcGJveFRva2VuQ2hhbmdlfVxuICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJFbnRlciB5b3VyIE1hcGJveCBUb2tlblwiXG4gICAgICAgICAgICB2YWx1ZT17bWFwYm94VG9rZW59XG4gICAgICAgICAgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8Lz5cbiAgICAgIDxTdHlsZWRCdXR0b24+XG4gICAgICAgIDxCdXR0b24gb25DbGljaz17b25TdGFydENoYXR9IHdpZHRoPXsnMTAwJSd9PlxuICAgICAgICAgIHtpc1J1bm5pbmcgJiYgPExvYWRpbmdTcGlubmVyIHNpemU9ezEyfSAvPn1cbiAgICAgICAgICA8Rm9ybWF0dGVkTWVzc2FnZSBpZD1cImFpQXNzaXN0YW50TWFuYWdlci5zdGFydENoYXRcIiAvPlxuICAgICAgICA8L0J1dHRvbj5cbiAgICAgIDwvU3R5bGVkQnV0dG9uPlxuICAgIDwvU3R5bGVkQWlBc3Npc3RhbnRDb25maWc+XG4gICk7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUdBLElBQUFBLE1BQUEsR0FBQUMsdUJBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLGlCQUFBLEdBQUFDLHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBRyxXQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxXQUFBLEdBQUFKLE9BQUE7QUFXQSxJQUFBSyxPQUFBLEdBQUFILHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBTSxPQUFBLEdBQUFKLHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBTyxXQUFBLEdBQUFQLE9BQUE7QUFDQSxJQUFBUSxLQUFBLEdBQUFSLE9BQUE7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