UNPKG

kepler.gl

Version:

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

720 lines (623 loc) 60.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.setLocaleUpdater = exports.toggleSplitMapUpdater = exports.loadFilesErrUpdater = exports.loadFilesSuccessUpdater = exports.loadFilesUpdater = exports.removeNotificationUpdater = exports.addNotificationUpdater = exports.setExportMapHTMLMode = exports.setExportMapFormatUpdater = exports.setUserMapboxAccessTokenUpdater = exports.setExportDataUpdater = exports.setExportFilteredUpdater = exports.setExportDataTypeUpdater = exports.setExportSelectedDatasetUpdater = exports.cleanupExportImage = exports.setExportImageError = exports.setExportImageDataUri = exports.startExportingImage = exports.setExportImageSetting = exports.openDeleteModalUpdater = exports.toggleMapControlUpdater = exports.hideExportDropdownUpdater = exports.showExportDropdownUpdater = exports.toggleModalUpdater = exports.toggleSidePanelUpdater = exports.INITIAL_UI_STATE = exports.DEFAULT_EXPORT_MAP = exports.DEFAULT_EXPORT_JSON = exports.DEFAULT_EXPORT_HTML = exports.DEFAULT_NOTIFICATIONS = exports.DEFAULT_EXPORT_DATA = exports.DEFAULT_LOAD_FILES = exports.DEFAULT_EXPORT_IMAGE = exports.DEFAULT_MAP_CONTROLS = exports.DEFAULT_MODAL = exports.DEFAULT_ACTIVE_SIDE_PANEL = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _defaultSettings = require("../constants/default-settings"); var _notificationsUtils = require("../utils/notifications-utils"); var _exportUtils = require("../utils/export-utils"); var _DEFAULT_EXPORT_MAP; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var DEFAULT_ACTIVE_SIDE_PANEL = 'layer'; exports.DEFAULT_ACTIVE_SIDE_PANEL = DEFAULT_ACTIVE_SIDE_PANEL; var DEFAULT_MODAL = _defaultSettings.ADD_DATA_ID; /** * Updaters for `uiState` reducer. Can be used in your root reducer to directly modify kepler.gl's state. * Read more about [Using updaters](../advanced-usage/using-updaters.md) * * @public * @example * * import keplerGlReducer, {uiStateUpdaters} from 'kepler.gl/reducers'; * // Root Reducer * const reducers = combineReducers({ * keplerGl: keplerGlReducer, * app: appReducer * }); * * const composedReducer = (state, action) => { * switch (action.type) { * // click button to close side panel * case 'CLICK_BUTTON': * return { * ...state, * keplerGl: { * ...state.keplerGl, * foo: { * ...state.keplerGl.foo, * uiState: uiStateUpdaters.toggleSidePanelUpdater( * uiState, {payload: null} * ) * } * } * }; * } * return reducers(state, action); * }; * * export default composedReducer; */ /* eslint-disable no-unused-vars */ exports.DEFAULT_MODAL = DEFAULT_MODAL; var uiStateUpdaters = null; /* eslint-enable no-unused-vars */ /** * A list of map control visibility and whether is it active. * @memberof uiStateUpdaters * @constant * @type {Object} * @property {Object} visibleLayers Default: `{show: true, active: false}` * @property {Object} mapLegend Default: `{show: true, active: false}` * @property {Object} toggle3d Default: `{show: true}` * @property {Object} splitMap Default: `{show: true}` * @property {Object} mapDraw Default: `{show: true, active: false}` * @property {Object} mapLocale Default: `{show: false, active: false}` * @public */ var DEFAULT_MAP_CONTROLS_FEATURES = { show: true, active: false, // defines which map index users are interacting with (through map controls) activeMapIndex: 0 }; var DEFAULT_MAP_CONTROLS = ['visibleLayers', 'mapLegend', 'toggle3d', 'splitMap', 'mapDraw', 'mapLocale'].reduce(function (_final, current) { return _objectSpread({}, _final, (0, _defineProperty2["default"])({}, current, DEFAULT_MAP_CONTROLS_FEATURES)); }, {}); /** * Default image export config * @memberof uiStateUpdaters * @constant * @type {Object} * @property {string} ratio Default: `'SCREEN'`, * @property {string} resolution Default: `'ONE_X'`, * @property {boolean} legend Default: `false`, * @property {string} imageDataUri Default: `''`, * @property {boolean} exporting Default: `false` * @property {boolean} error Default: `false` * @public */ exports.DEFAULT_MAP_CONTROLS = DEFAULT_MAP_CONTROLS; var DEFAULT_EXPORT_IMAGE = { // user options ratio: _defaultSettings.EXPORT_IMG_RATIOS.SCREEN, resolution: _defaultSettings.RESOLUTIONS.ONE_X, legend: false, mapH: 0, mapW: 0, imageSize: { zoomOffset: 0, scale: 1, imageW: 0, imageH: 0 }, // exporting state imageDataUri: '', exporting: false, error: false }; exports.DEFAULT_EXPORT_IMAGE = DEFAULT_EXPORT_IMAGE; var DEFAULT_LOAD_FILES = { fileLoading: false }; /** * Default initial `exportData` settings * @memberof uiStateUpdaters * @constant * @type {Object} * @property {string} selectedDataset Default: `''`, * @property {string} dataType Default: `'csv'`, * @property {boolean} filtered Default: `true`, * @property {boolean} config deprecated * @property {boolean} data used in modal config export. Default: `false` * @public */ exports.DEFAULT_LOAD_FILES = DEFAULT_LOAD_FILES; var DEFAULT_EXPORT_DATA = { selectedDataset: '', dataType: _defaultSettings.EXPORT_DATA_TYPE.CSV, filtered: true }; /** * @constant * @type {Array} */ exports.DEFAULT_EXPORT_DATA = DEFAULT_EXPORT_DATA; var DEFAULT_NOTIFICATIONS = []; /** * @constant * @type {Object} * @property {string} exportMapboxAccessToken - Default: null, this is used when we provide a default mapbox token for users to take advantage of * @property {string} userMapboxToken - Default: '', mapbox token provided by user through input field * @public */ exports.DEFAULT_NOTIFICATIONS = DEFAULT_NOTIFICATIONS; var DEFAULT_EXPORT_HTML = { exportMapboxAccessToken: null, userMapboxToken: '', mode: _defaultSettings.EXPORT_HTML_MAP_MODES.READ }; exports.DEFAULT_EXPORT_HTML = DEFAULT_EXPORT_HTML; var DEFAULT_EXPORT_JSON = { hasData: true }; exports.DEFAULT_EXPORT_JSON = DEFAULT_EXPORT_JSON; var DEFAULT_EXPORT_MAP = (_DEFAULT_EXPORT_MAP = {}, (0, _defineProperty2["default"])(_DEFAULT_EXPORT_MAP, _defaultSettings.EXPORT_MAP_FORMATS.HTML, DEFAULT_EXPORT_HTML), (0, _defineProperty2["default"])(_DEFAULT_EXPORT_MAP, _defaultSettings.EXPORT_MAP_FORMATS.JSON, DEFAULT_EXPORT_JSON), (0, _defineProperty2["default"])(_DEFAULT_EXPORT_MAP, "format", _defaultSettings.EXPORT_MAP_FORMATS.HTML), _DEFAULT_EXPORT_MAP); /** * Default initial `uiState` * @memberof uiStateUpdaters * @constant * @type {Object} * @property {boolean} readOnly Default: `false` * @property {string} activeSidePanel Default: `'layer'` * @property {string|null} currentModal Default: `'addData'` * @property {string|null} datasetKeyToRemove Default: `null` * @property {string|null} visibleDropdown Default: `null` * @property {Object} exportImage Default: [`DEFAULT_EXPORT_IMAGE`](#default_export_image) * @property {Object} exportData Default: [`DEFAULT_EXPORT_DATA`](#default_export_data) * @property {Object} mapControls Default: [`DEFAULT_MAP_CONTROLS`](#default_map_controls) * @property {number} activeMapIndex defines which map the user clicked on. Default: 0 * @public */ exports.DEFAULT_EXPORT_MAP = DEFAULT_EXPORT_MAP; var INITIAL_UI_STATE = { readOnly: false, activeSidePanel: DEFAULT_ACTIVE_SIDE_PANEL, currentModal: DEFAULT_MODAL, datasetKeyToRemove: null, visibleDropdown: null, // export image modal ui exportImage: DEFAULT_EXPORT_IMAGE, // export data modal ui exportData: DEFAULT_EXPORT_DATA, // html export exportMap: DEFAULT_EXPORT_MAP, // map control panels mapControls: DEFAULT_MAP_CONTROLS, // ui notifications notifications: DEFAULT_NOTIFICATIONS, // load files loadFiles: DEFAULT_LOAD_FILES, // Locale of the UI locale: _defaultSettings.LOCALES.en }; /* Updaters */ /** * Toggle active side panel * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {string|null} action.payload id of side panel to be shown, one of `layer`, `filter`, `interaction`, `map`. close side panel if `null` * @returns {Object} nextState * @public */ exports.INITIAL_UI_STATE = INITIAL_UI_STATE; var toggleSidePanelUpdater = function toggleSidePanelUpdater(state, _ref) { var id = _ref.payload; return id === state.activeSidePanel ? state : _objectSpread({}, state, { activeSidePanel: id }); }; /** * Show and hide modal dialog * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {string|null} action.payload id of modal to be shown, null to hide modals. One of: * * - [`DATA_TABLE_ID`](../constants/default-settings.md#data_table_id) * - [`DELETE_DATA_ID`](../constants/default-settings.md#delete_data_id) * - [`ADD_DATA_ID`](../constants/default-settings.md#add_data_id) * - [`EXPORT_IMAGE_ID`](../constants/default-settings.md#export_image_id) * - [`EXPORT_DATA_ID`](../constants/default-settings.md#export_data_id) * - [`ADD_MAP_STYLE_ID`](../constants/default-settings.md#add_map_style_id) * @returns {Object} nextState * @public */ exports.toggleSidePanelUpdater = toggleSidePanelUpdater; var toggleModalUpdater = function toggleModalUpdater(state, _ref2) { var id = _ref2.payload; return _objectSpread({}, state, { currentModal: id }); }; /** * Hide and show side panel header dropdown, activated by clicking the share link on top of the side panel * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {string} action.payload id of the dropdown * @returns {Object} nextState * @public */ exports.toggleModalUpdater = toggleModalUpdater; var showExportDropdownUpdater = function showExportDropdownUpdater(state, _ref3) { var id = _ref3.payload; return _objectSpread({}, state, { visibleDropdown: id }); }; /** * Hide side panel header dropdown, activated by clicking the share link on top of the side panel * @memberof uiStateUpdaters * @param {Object} state `uiState` * @returns {Object} nextState * @public */ exports.showExportDropdownUpdater = showExportDropdownUpdater; var hideExportDropdownUpdater = function hideExportDropdownUpdater(state) { return _objectSpread({}, state, { visibleDropdown: null }); }; /** * Toggle active map control panel * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action action * @param {string} action.payload map control panel id, one of the keys of: [`DEFAULT_MAP_CONTROLS`](#default_map_controls) * @returns {Object} nextState * @public */ exports.hideExportDropdownUpdater = hideExportDropdownUpdater; var toggleMapControlUpdater = function toggleMapControlUpdater(state, _ref4) { var _ref4$payload = _ref4.payload, panelId = _ref4$payload.panelId, _ref4$payload$index = _ref4$payload.index, index = _ref4$payload$index === void 0 ? 0 : _ref4$payload$index; return _objectSpread({}, state, { mapControls: _objectSpread({}, state.mapControls, (0, _defineProperty2["default"])({}, panelId, _objectSpread({}, state.mapControls[panelId], { // this handles split map interaction // Toggling from within the same map will simply toggle the active property // Toggling from within different maps we set the active property to true active: index === state.mapControls[panelId].activeMapIndex ? !state.mapControls[panelId].active : true, activeMapIndex: index }))) }); }; /** * Toggle active map control panel * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {string} action.payload dataset id * @returns {Object} nextState * @public */ exports.toggleMapControlUpdater = toggleMapControlUpdater; var openDeleteModalUpdater = function openDeleteModalUpdater(state, _ref5) { var datasetKeyToRemove = _ref5.payload; return _objectSpread({}, state, { currentModal: _defaultSettings.DELETE_DATA_ID, datasetKeyToRemove: datasetKeyToRemove }); }; /** * Set `exportImage.legend` to `true` or `false` * @memberof uiStateUpdaters * @param {Object} state `uiState` * @returns {Object} nextState * @public */ exports.openDeleteModalUpdater = openDeleteModalUpdater; var setExportImageSetting = function setExportImageSetting(state, _ref6) { var newSetting = _ref6.payload; var updated = _objectSpread({}, state.exportImage, {}, newSetting); var imageSize = (0, _exportUtils.calculateExportImageSize)(updated) || state.exportImage.imageSize; return _objectSpread({}, state, { exportImage: _objectSpread({}, updated, { imageSize: imageSize }) }); }; /** * Set `exportImage.exporting` to `true` * @memberof uiStateUpdaters * @param {Object} state `uiState` * @returns {Object} nextState * @public */ exports.setExportImageSetting = setExportImageSetting; var startExportingImage = function startExportingImage(state) { return _objectSpread({}, state, { exportImage: _objectSpread({}, state.exportImage, { exporting: true, imageDataUri: '' }) }); }; /** * Set `exportImage.setExportImageDataUri` to a image dataUri * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {string} action.payload export image data uri * @returns {Object} nextState * @public */ exports.startExportingImage = startExportingImage; var setExportImageDataUri = function setExportImageDataUri(state, _ref7) { var dataUri = _ref7.payload; return _objectSpread({}, state, { exportImage: _objectSpread({}, state.exportImage, { exporting: false, imageDataUri: dataUri }) }); }; exports.setExportImageDataUri = setExportImageDataUri; var setExportImageError = function setExportImageError(state, _ref8) { var error = _ref8.payload; return _objectSpread({}, state, { exportImage: _objectSpread({}, state.exportImage, { exporting: false, error: error }) }); }; /** * Delete cached export image * @memberof uiStateUpdaters * @param {Object} state `uiState` * @returns {Object} nextState * @public */ exports.setExportImageError = setExportImageError; var cleanupExportImage = function cleanupExportImage(state) { return _objectSpread({}, state, { exportImage: _objectSpread({}, state.exportImage, { exporting: false, imageDataUri: '', error: false }) }); }; /** * Set selected dataset for export * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {string} action.payload dataset id * @returns {Object} nextState * @public */ exports.cleanupExportImage = cleanupExportImage; var setExportSelectedDatasetUpdater = function setExportSelectedDatasetUpdater(state, _ref9) { var dataset = _ref9.payload; return _objectSpread({}, state, { exportData: _objectSpread({}, state.exportData, { selectedDataset: dataset }) }); }; /** * Set data format for exporting data * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {string} action.payload one of `'text/csv'` * @returns {Object} nextState * @public */ exports.setExportSelectedDatasetUpdater = setExportSelectedDatasetUpdater; var setExportDataTypeUpdater = function setExportDataTypeUpdater(state, _ref10) { var dataType = _ref10.payload; return _objectSpread({}, state, { exportData: _objectSpread({}, state.exportData, { dataType: dataType }) }); }; /** * Whether to export filtered data, `true` or `false` * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {boolean} action.payload * @returns {Object} nextState * @public */ exports.setExportDataTypeUpdater = setExportDataTypeUpdater; var setExportFilteredUpdater = function setExportFilteredUpdater(state, _ref11) { var filtered = _ref11.payload; return _objectSpread({}, state, { exportData: _objectSpread({}, state.exportData, { filtered: filtered }) }); }; /** * Whether to including data in map config, toggle between `true` or `false` * @memberof uiStateUpdaters * @param {Object} state `uiState` * @returns {Object} nextState * @public */ exports.setExportFilteredUpdater = setExportFilteredUpdater; var setExportDataUpdater = function setExportDataUpdater(state) { return _objectSpread({}, state, { exportMap: _objectSpread({}, state.exportMap, (0, _defineProperty2["default"])({}, _defaultSettings.EXPORT_MAP_FORMATS.JSON, _objectSpread({}, state.exportMap[_defaultSettings.EXPORT_MAP_FORMATS.JSON], { hasData: !state.exportMap[_defaultSettings.EXPORT_MAP_FORMATS.JSON].hasData }))) }); }; /** * whether to export a mapbox access to HTML single page * @param {Object} state - `uiState` * @param {Object} action * @param {string} action.payload * @returns {Object} nextState * @public */ exports.setExportDataUpdater = setExportDataUpdater; var setUserMapboxAccessTokenUpdater = function setUserMapboxAccessTokenUpdater(state, _ref12) { var userMapboxToken = _ref12.payload; return _objectSpread({}, state, { exportMap: _objectSpread({}, state.exportMap, (0, _defineProperty2["default"])({}, _defaultSettings.EXPORT_MAP_FORMATS.HTML, _objectSpread({}, state.exportMap[_defaultSettings.EXPORT_MAP_FORMATS.HTML], { userMapboxToken: userMapboxToken }))) }); }; /** * Sets the export map format * @param {Object} state - `uiState` * @param {string} format to use to export the map onto * @return {Object} nextState */ exports.setUserMapboxAccessTokenUpdater = setUserMapboxAccessTokenUpdater; var setExportMapFormatUpdater = function setExportMapFormatUpdater(state, _ref13) { var format = _ref13.payload; return _objectSpread({}, state, { exportMap: _objectSpread({}, state.exportMap, { format: format }) }); }; /** * Set the export html map mode * @param {Object} state - `uiState` * @param {string} mode to be set (available modes: EXPORT_HTML_MAP_MODES) * @return {{[p: string]: *}} */ exports.setExportMapFormatUpdater = setExportMapFormatUpdater; var setExportMapHTMLMode = function setExportMapHTMLMode(state, _ref14) { var mode = _ref14.payload; return _objectSpread({}, state, { exportMap: _objectSpread({}, state.exportMap, (0, _defineProperty2["default"])({}, _defaultSettings.EXPORT_MAP_FORMATS.HTML, _objectSpread({}, state.exportMap[_defaultSettings.EXPORT_MAP_FORMATS.HTML], { mode: mode }))) }); }; /** * Add a notification to be displayed * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {Object} action.payload * @returns {Object} nextState * @public */ exports.setExportMapHTMLMode = setExportMapHTMLMode; var addNotificationUpdater = function addNotificationUpdater(state, _ref15) { var payload = _ref15.payload; return _objectSpread({}, state, { notifications: [].concat((0, _toConsumableArray2["default"])(state.notifications || []), [(0, _notificationsUtils.createNotification)(payload)]) }); }; /** * Remove a notification * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {String} action.payload id of the notification to be removed * @returns {Object} nextState * @public */ exports.addNotificationUpdater = addNotificationUpdater; var removeNotificationUpdater = function removeNotificationUpdater(state, _ref16) { var id = _ref16.payload; return _objectSpread({}, state, { notifications: state.notifications.filter(function (n) { return n.id !== id; }) }); }; /** * Fired when file loading begin * @memberof uiStateUpdaters * @param {Object} state `uiState` * @returns {Object} nextState * @public */ exports.removeNotificationUpdater = removeNotificationUpdater; var loadFilesUpdater = function loadFilesUpdater(state) { return _objectSpread({}, state, { loadFiles: _objectSpread({}, state.loadFiles, { fileLoading: true }) }); }; /** * Handles loading file success and set fileLoading property to false * @memberof uiStateUpdaters * @param {Object} state `uiState` * @returns {Object} nextState */ exports.loadFilesUpdater = loadFilesUpdater; var loadFilesSuccessUpdater = function loadFilesSuccessUpdater(state) { return _objectSpread({}, state, { loadFiles: _objectSpread({}, state.loadFiles, { fileLoading: false }) }); }; /** * Handles load file error and set fileLoading property to false * @memberof uiStateUpdaters * @param state * @param error * @returns {Object} nextState * @public */ exports.loadFilesSuccessUpdater = loadFilesSuccessUpdater; var loadFilesErrUpdater = function loadFilesErrUpdater(state, _ref17) { var error = _ref17.error; return addNotificationUpdater(_objectSpread({}, state, { loadFiles: _objectSpread({}, state.loadFiles, { fileLoading: false }) }), { payload: (0, _notificationsUtils.errorNotification)({ message: (error || {}).message || 'Failed to upload files', topic: _defaultSettings.DEFAULT_NOTIFICATION_TOPICS.global }) }); }; /** * Handles toggle map split and reset all map control index to 0 * @memberof uiStateUpdaters * @param state * @returns {Object} nextState * @public */ exports.loadFilesErrUpdater = loadFilesErrUpdater; var toggleSplitMapUpdater = function toggleSplitMapUpdater(state) { return _objectSpread({}, state, { mapControls: Object.entries(state.mapControls).reduce(function (acc, entry) { return _objectSpread({}, acc, (0, _defineProperty2["default"])({}, entry[0], _objectSpread({}, entry[1], { activeMapIndex: 0 }))); }, {}) }); }; /** * Set the locale of the UI * @memberof uiStateUpdaters * @param {Object} state `uiState` * @param {Object} action * @param {String} action.payload locale * @returns {Object} nextState * @public */ exports.toggleSplitMapUpdater = toggleSplitMapUpdater; var setLocaleUpdater = function setLocaleUpdater(state, _ref18) { var locale = _ref18.payload.locale; return _objectSpread({}, state, { locale: locale }); }; exports.setLocaleUpdater = setLocaleUpdater; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZWR1Y2Vycy91aS1zdGF0ZS11cGRhdGVycy5qcyJdLCJuYW1lcyI6WyJERUZBVUxUX0FDVElWRV9TSURFX1BBTkVMIiwiREVGQVVMVF9NT0RBTCIsIkFERF9EQVRBX0lEIiwidWlTdGF0ZVVwZGF0ZXJzIiwiREVGQVVMVF9NQVBfQ09OVFJPTFNfRkVBVFVSRVMiLCJzaG93IiwiYWN0aXZlIiwiYWN0aXZlTWFwSW5kZXgiLCJERUZBVUxUX01BUF9DT05UUk9MUyIsInJlZHVjZSIsImZpbmFsIiwiY3VycmVudCIsIkRFRkFVTFRfRVhQT1JUX0lNQUdFIiwicmF0aW8iLCJFWFBPUlRfSU1HX1JBVElPUyIsIlNDUkVFTiIsInJlc29sdXRpb24iLCJSRVNPTFVUSU9OUyIsIk9ORV9YIiwibGVnZW5kIiwibWFwSCIsIm1hcFciLCJpbWFnZVNpemUiLCJ6b29tT2Zmc2V0Iiwic2NhbGUiLCJpbWFnZVciLCJpbWFnZUgiLCJpbWFnZURhdGFVcmkiLCJleHBvcnRpbmciLCJlcnJvciIsIkRFRkFVTFRfTE9BRF9GSUxFUyIsImZpbGVMb2FkaW5nIiwiREVGQVVMVF9FWFBPUlRfREFUQSIsInNlbGVjdGVkRGF0YXNldCIsImRhdGFUeXBlIiwiRVhQT1JUX0RBVEFfVFlQRSIsIkNTViIsImZpbHRlcmVkIiwiREVGQVVMVF9OT1RJRklDQVRJT05TIiwiREVGQVVMVF9FWFBPUlRfSFRNTCIsImV4cG9ydE1hcGJveEFjY2Vzc1Rva2VuIiwidXNlck1hcGJveFRva2VuIiwibW9kZSIsIkVYUE9SVF9IVE1MX01BUF9NT0RFUyIsIlJFQUQiLCJERUZBVUxUX0VYUE9SVF9KU09OIiwiaGFzRGF0YSIsIkRFRkFVTFRfRVhQT1JUX01BUCIsIkVYUE9SVF9NQVBfRk9STUFUUyIsIkhUTUwiLCJKU09OIiwiSU5JVElBTF9VSV9TVEFURSIsInJlYWRPbmx5IiwiYWN0aXZlU2lkZVBhbmVsIiwiY3VycmVudE1vZGFsIiwiZGF0YXNldEtleVRvUmVtb3ZlIiwidmlzaWJsZURyb3Bkb3duIiwiZXhwb3J0SW1hZ2UiLCJleHBvcnREYXRhIiwiZXhwb3J0TWFwIiwibWFwQ29udHJvbHMiLCJub3RpZmljYXRpb25zIiwibG9hZEZpbGVzIiwibG9jYWxlIiwiTE9DQUxFUyIsImVuIiwidG9nZ2xlU2lkZVBhbmVsVXBkYXRlciIsInN0YXRlIiwiaWQiLCJwYXlsb2FkIiwidG9nZ2xlTW9kYWxVcGRhdGVyIiwic2hvd0V4cG9ydERyb3Bkb3duVXBkYXRlciIsImhpZGVFeHBvcnREcm9wZG93blVwZGF0ZXIiLCJ0b2dnbGVNYXBDb250cm9sVXBkYXRlciIsInBhbmVsSWQiLCJpbmRleCIsIm9wZW5EZWxldGVNb2RhbFVwZGF0ZXIiLCJERUxFVEVfREFUQV9JRCIsInNldEV4cG9ydEltYWdlU2V0dGluZyIsIm5ld1NldHRpbmciLCJ1cGRhdGVkIiwic3RhcnRFeHBvcnRpbmdJbWFnZSIsInNldEV4cG9ydEltYWdlRGF0YVVyaSIsImRhdGFVcmkiLCJzZXRFeHBvcnRJbWFnZUVycm9yIiwiY2xlYW51cEV4cG9ydEltYWdlIiwic2V0RXhwb3J0U2VsZWN0ZWREYXRhc2V0VXBkYXRlciIsImRhdGFzZXQiLCJzZXRFeHBvcnREYXRhVHlwZVVwZGF0ZXIiLCJzZXRFeHBvcnRGaWx0ZXJlZFVwZGF0ZXIiLCJzZXRFeHBvcnREYXRhVXBkYXRlciIsInNldFVzZXJNYXBib3hBY2Nlc3NUb2tlblVwZGF0ZXIiLCJzZXRFeHBvcnRNYXBGb3JtYXRVcGRhdGVyIiwiZm9ybWF0Iiwic2V0RXhwb3J0TWFwSFRNTE1vZGUiLCJhZGROb3RpZmljYXRpb25VcGRhdGVyIiwicmVtb3ZlTm90aWZpY2F0aW9uVXBkYXRlciIsImZpbHRlciIsIm4iLCJsb2FkRmlsZXNVcGRhdGVyIiwibG9hZEZpbGVzU3VjY2Vzc1VwZGF0ZXIiLCJsb2FkRmlsZXNFcnJVcGRhdGVyIiwibWVzc2FnZSIsInRvcGljIiwiREVGQVVMVF9OT1RJRklDQVRJT05fVE9QSUNTIiwiZ2xvYmFsIiwidG9nZ2xlU3BsaXRNYXBVcGRhdGVyIiwiT2JqZWN0IiwiZW50cmllcyIsImFjYyIsImVudHJ5Iiwic2V0TG9jYWxlVXBkYXRlciJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQW9CQTs7QUFXQTs7QUFDQTs7Ozs7Ozs7QUFFTyxJQUFNQSx5QkFBeUIsR0FBRyxPQUFsQzs7QUFDQSxJQUFNQyxhQUFhLEdBQUdDLDRCQUF0QjtBQUVQOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0NBOzs7QUFDQSxJQUFNQyxlQUFlLEdBQUcsSUFBeEI7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7QUFhQSxJQUFNQyw2QkFBNkIsR0FBRztBQUNwQ0MsRUFBQUEsSUFBSSxFQUFFLElBRDhCO0FBRXBDQyxFQUFBQSxNQUFNLEVBQUUsS0FGNEI7QUFHcEM7QUFDQUMsRUFBQUEsY0FBYyxFQUFFO0FBSm9CLENBQXRDO0FBT08sSUFBTUMsb0JBQW9CLEdBQUcsQ0FDbEMsZUFEa0MsRUFFbEMsV0FGa0MsRUFHbEMsVUFIa0MsRUFJbEMsVUFKa0MsRUFLbEMsU0FMa0MsRUFNbEMsV0FOa0MsRUFPbENDLE1BUGtDLENBUWxDLFVBQUNDLE1BQUQsRUFBUUMsT0FBUjtBQUFBLDJCQUNLRCxNQURMLHVDQUVHQyxPQUZILEVBRWFQLDZCQUZiO0FBQUEsQ0FSa0MsRUFZbEMsRUFaa0MsQ0FBN0I7QUFnQlA7Ozs7Ozs7Ozs7Ozs7OztBQWFPLElBQU1RLG9CQUFvQixHQUFHO0FBQ2xDO0FBQ0FDLEVBQUFBLEtBQUssRUFBRUMsbUNBQWtCQyxNQUZTO0FBR2xDQyxFQUFBQSxVQUFVLEVBQUVDLDZCQUFZQyxLQUhVO0FBSWxDQyxFQUFBQSxNQUFNLEVBQUUsS0FKMEI7QUFLbENDLEVBQUFBLElBQUksRUFBRSxDQUw0QjtBQU1sQ0MsRUFBQUEsSUFBSSxFQUFFLENBTjRCO0FBT2xDQyxFQUFBQSxTQUFTLEVBQUU7QUFDVEMsSUFBQUEsVUFBVSxFQUFFLENBREg7QUFFVEMsSUFBQUEsS0FBSyxFQUFFLENBRkU7QUFHVEMsSUFBQUEsTUFBTSxFQUFFLENBSEM7QUFJVEMsSUFBQUEsTUFBTSxFQUFFO0FBSkMsR0FQdUI7QUFhbEM7QUFDQUMsRUFBQUEsWUFBWSxFQUFFLEVBZG9CO0FBZWxDQyxFQUFBQSxTQUFTLEVBQUUsS0FmdUI7QUFnQmxDQyxFQUFBQSxLQUFLLEVBQUU7QUFoQjJCLENBQTdCOztBQW1CQSxJQUFNQyxrQkFBa0IsR0FBRztBQUNoQ0MsRUFBQUEsV0FBVyxFQUFFO0FBRG1CLENBQTNCO0FBSVA7Ozs7Ozs7Ozs7Ozs7O0FBWU8sSUFBTUMsbUJBQW1CLEdBQUc7QUFDakNDLEVBQUFBLGVBQWUsRUFBRSxFQURnQjtBQUVqQ0MsRUFBQUEsUUFBUSxFQUFFQyxrQ0FBaUJDLEdBRk07QUFHakNDLEVBQUFBLFFBQVEsRUFBRTtBQUh1QixDQUE1QjtBQU1QOzs7Ozs7QUFJTyxJQUFNQyxxQkFBcUIsR0FBRyxFQUE5QjtBQUVQOzs7Ozs7Ozs7QUFPTyxJQUFNQyxtQkFBbUIsR0FBRztBQUNqQ0MsRUFBQUEsdUJBQXVCLEVBQUUsSUFEUTtBQUVqQ0MsRUFBQUEsZUFBZSxFQUFFLEVBRmdCO0FBR2pDQyxFQUFBQSxJQUFJLEVBQUVDLHVDQUFzQkM7QUFISyxDQUE1Qjs7QUFNQSxJQUFNQyxtQkFBbUIsR0FBRztBQUNqQ0MsRUFBQUEsT0FBTyxFQUFFO0FBRHdCLENBQTVCOztBQUlBLElBQU1DLGtCQUFrQixvRkFDNUJDLG9DQUFtQkMsSUFEUyxFQUNGVixtQkFERSx5REFFNUJTLG9DQUFtQkUsSUFGUyxFQUVGTCxtQkFGRSxtRUFHckJHLG9DQUFtQkMsSUFIRSx1QkFBeEI7QUFNUDs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JPLElBQU1FLGdCQUFnQixHQUFHO0FBQzlCQyxFQUFBQSxRQUFRLEVBQUUsS0FEb0I7QUFFOUJDLEVBQUFBLGVBQWUsRUFBRXJELHlCQUZhO0FBRzlCc0QsRUFBQUEsWUFBWSxFQUFFckQsYUFIZ0I7QUFJOUJzRCxFQUFBQSxrQkFBa0IsRUFBRSxJQUpVO0FBSzlCQyxFQUFBQSxlQUFlLEVBQUUsSUFMYTtBQU05QjtBQUNBQyxFQUFBQSxXQUFXLEVBQUU3QyxvQkFQaUI7QUFROUI7QUFDQThDLEVBQUFBLFVBQVUsRUFBRTFCLG1CQVRrQjtBQVU5QjtBQUNBMkIsRUFBQUEsU0FBUyxFQUFFWixrQkFYbUI7QUFZOUI7QUFDQWEsRUFBQUEsV0FBVyxFQUFFcEQsb0JBYmlCO0FBYzlCO0FBQ0FxRCxFQUFBQSxhQUFhLEVBQUV2QixxQkFmZTtBQWdCOUI7QUFDQXdCLEVBQUFBLFNBQVMsRUFBRWhDLGtCQWpCbUI7QUFrQjlCO0FBQ0FpQyxFQUFBQSxNQUFNLEVBQUVDLHlCQUFRQztBQW5CYyxDQUF6QjtBQXNCUDs7QUFDQTs7Ozs7Ozs7Ozs7O0FBU08sSUFBTUMsc0JBQXNCLEdBQUcsU0FBekJBLHNCQUF5QixDQUFDQyxLQUFELFFBQTBCO0FBQUEsTUFBUkMsRUFBUSxRQUFqQkMsT0FBaUI7QUFDOUQsU0FBT0QsRUFBRSxLQUFLRCxLQUFLLENBQUNkLGVBQWIsR0FDSGMsS0FERyxxQkFHRUEsS0FIRjtBQUlEZCxJQUFBQSxlQUFlLEVBQUVlO0FBSmhCLElBQVA7QUFNRCxDQVBNO0FBU1A7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JPLElBQU1FLGtCQUFrQixHQUFHLFNBQXJCQSxrQkFBcUIsQ0FBQ0gsS0FBRDtBQUFBLE1BQWtCQyxFQUFsQixTQUFTQyxPQUFUO0FBQUEsMkJBQzdCRixLQUQ2QjtBQUVoQ2IsSUFBQUEsWUFBWSxFQUFFYztBQUZrQjtBQUFBLENBQTNCO0FBS1A7Ozs7Ozs7Ozs7Ozs7QUFTTyxJQUFNRyx5QkFBeUIsR0FBRyxTQUE1QkEseUJBQTRCLENBQUNKLEtBQUQ7QUFBQSxNQUFrQkMsRUFBbEIsU0FBU0MsT0FBVDtBQUFBLDJCQUNwQ0YsS0FEb0M7QUFFdkNYLElBQUFBLGVBQWUsRUFBRVk7QUFGc0I7QUFBQSxDQUFsQztBQUtQOzs7Ozs7Ozs7OztBQU9PLElBQU1JLHlCQUF5QixHQUFHLFNBQTVCQSx5QkFBNEIsQ0FBQUwsS0FBSztBQUFBLDJCQUN6Q0EsS0FEeUM7QUFFNUNYLElBQUFBLGVBQWUsRUFBRTtBQUYyQjtBQUFBLENBQXZDO0FBS1A7Ozs7Ozs7Ozs7Ozs7QUFTTyxJQUFNaUIsdUJBQXVCLEdBQUcsU0FBMUJBLHVCQUEwQixDQUFDTixLQUFEO0FBQUEsNEJBQVNFLE9BQVQ7QUFBQSxNQUFtQkssT0FBbkIsaUJBQW1CQSxPQUFuQjtBQUFBLDBDQUE0QkMsS0FBNUI7QUFBQSxNQUE0QkEsS0FBNUIsb0NBQW9DLENBQXBDO0FBQUEsMkJBQ2xDUixLQURrQztBQUVyQ1AsSUFBQUEsV0FBVyxvQkFDTk8sS0FBSyxDQUFDUCxXQURBLHVDQUVSYyxPQUZRLG9CQUdKUCxLQUFLLENBQUNQLFdBQU4sQ0FBa0JjLE9BQWxCLENBSEk7QUFJUDtBQUNBO0FBQ0E7QUFDQXBFLE1BQUFBLE1BQU0sRUFDSnFFLEtBQUssS0FBS1IsS0FBSyxDQUFDUCxXQUFOLENBQWtCYyxPQUFsQixFQUEyQm5FLGNBQXJDLEdBQ0ksQ0FBQzRELEtBQUssQ0FBQ1AsV0FBTixDQUFrQmMsT0FBbEIsRUFBMkJwRSxNQURoQyxHQUVJLElBVkM7QUFXUEMsTUFBQUEsY0FBYyxFQUFFb0U7QUFYVDtBQUYwQjtBQUFBLENBQWhDO0FBb0JQOzs7Ozs7Ozs7Ozs7O0FBU08sSUFBTUMsc0JBQXNCLEdBQUcsU0FBekJBLHNCQUF5QixDQUFDVCxLQUFEO0FBQUEsTUFBa0JaLGtCQUFsQixTQUFTYyxPQUFUO0FBQUEsMkJBQ2pDRixLQURpQztBQUVwQ2IsSUFBQUEsWUFBWSxFQUFFdUIsK0JBRnNCO0FBR3BDdEIsSUFBQUEsa0JBQWtCLEVBQWxCQTtBQUhvQztBQUFBLENBQS9CO0FBTVA7Ozs7Ozs7Ozs7O0FBT08sSUFBTXVCLHFCQUFxQixHQUFHLFNBQXhCQSxxQkFBd0IsQ0FBQ1gsS0FBRCxTQUFrQztBQUFBLE1BQWhCWSxVQUFnQixTQUF6QlYsT0FBeUI7O0FBQ3JFLE1BQU1XLE9BQU8scUJBQU9iLEtBQUssQ0FBQ1YsV0FBYixNQUE2QnNCLFVBQTdCLENBQWI7O0FBQ0EsTUFBTXpELFNBQVMsR0FBRywyQ0FBeUIwRCxPQUF6QixLQUFxQ2IsS0FBSyxDQUFDVixXQUFOLENBQWtCbkMsU0FBekU7QUFFQSwyQkFDSzZDLEtBREw7QUFFRVYsSUFBQUEsV0FBVyxvQkFDTnVCLE9BRE07QUFFVDFELE1BQUFBLFNBQVMsRUFBVEE7QUFGUztBQUZiO0FBT0QsQ0FYTTtBQWFQOzs7Ozs7Ozs7OztBQU9PLElBQU0yRCxtQkFBbUIsR0FBRyxTQUF0QkEsbUJBQXNCLENBQUFkLEtBQUs7QUFBQSwyQkFDbkNBLEtBRG1DO0FBRXRDVixJQUFBQSxXQUFXLG9CQUNOVSxLQUFLLENBQUNWLFdBREE7QUFFVDdCLE1BQUFBLFNBQVMsRUFBRSxJQUZGO0FBR1RELE1BQUFBLFlBQVksRUFBRTtBQUhMO0FBRjJCO0FBQUEsQ0FBakM7QUFTUDs7Ozs7Ozs7Ozs7OztBQVNPLElBQU11RCxxQkFBcUIsR0FBRyxTQUF4QkEscUJBQXdCLENBQUNmLEtBQUQ7QUFBQSxNQUFrQmdCLE9BQWxCLFNBQVNkLE9BQVQ7QUFBQSwyQkFDaENGLEtBRGdDO0FBRW5DVixJQUFBQSxXQUFXLG9CQUNOVSxLQUFLLENBQUNWLFdBREE7QUFFVDdCLE1BQUFBLFNBQVMsRUFBRSxLQUZGO0FBR1RELE1BQUFBLFlBQVksRUFBRXdEO0FBSEw7QUFGd0I7QUFBQSxDQUE5Qjs7OztBQVNBLElBQU1DLG1CQUFtQixHQUFHLFNBQXRCQSxtQkFBc0IsQ0FBQ2pCLEtBQUQ7QUFBQSxNQUFrQnRDLEtBQWxCLFNBQVN3QyxPQUFUO0FBQUEsMkJBQzlCRixLQUQ4QjtBQUVqQ1YsSUFBQUEsV0FBVyxvQkFDTlUsS0FBSyxDQUFDVixXQURBO0FBRVQ3QixNQUFBQSxTQUFTLEVBQUUsS0FGRjtBQUdUQyxNQUFBQSxLQUFLLEVBQUxBO0FBSFM7QUFGc0I7QUFBQSxDQUE1QjtBQVNQOzs7Ozs7Ozs7OztBQU9PLElBQU13RCxrQkFBa0IsR0FBRyxTQUFyQkEsa0JBQXFCLENBQUFsQixLQUFLO0FBQUEsMkJBQ2xDQSxLQURrQztBQUVyQ1YsSUFBQUEsV0FBVyxvQkFDTlUsS0FBSyxDQUFDVixXQURBO0FBRVQ3QixNQUFBQSxTQUFTLEVBQUUsS0FGRjtBQUdURCxNQUFBQSxZQUFZLEVBQUUsRUFITDtBQUlURSxNQUFBQSxLQUFLLEVBQUU7QUFKRTtBQUYwQjtBQUFBLENBQWhDO0FBVVA7Ozs7Ozs7Ozs7Ozs7QUFTTyxJQUFNeUQsK0JBQStCLEdBQUcsU0FBbENBLCtCQUFrQyxDQUFDbkIsS0FBRDtBQUFBLE1BQWtCb0IsT0FBbEIsU0FBU2xCLE9BQVQ7QUFBQSwyQkFDMUNGLEtBRDBDO0FBRTdDVCxJQUFBQSxVQUFVLG9CQUNMUyxLQUFLLENBQUNULFVBREQ7QUFFUnpCLE1BQUFBLGVBQWUsRUFBRXNEO0FBRlQ7QUFGbUM7QUFBQSxDQUF4QztBQVFQOzs7Ozs7Ozs7Ozs7O0FBU08sSUFBTUMsd0JBQXdCLEdBQUcsU0FBM0JBLHdCQUEyQixDQUFDckIsS0FBRDtBQUFBLE1BQWtCakMsUUFBbEIsVUFBU21DLE9BQVQ7QUFBQSwyQkFDbkNGLEtBRG1DO0FBRXRDVCxJQUFBQSxVQUFVLG9CQUNMUyxLQUFLLENBQUNULFVBREQ7QUFFUnhCLE1BQUFBLFFBQVEsRUFBUkE7QUFGUTtBQUY0QjtBQUFBLENBQWpDO0FBUVA7Ozs7Ozs7Ozs7Ozs7QUFTTyxJQUFNdUQsd0JBQXdCLEdBQUcsU0FBM0JBLHdCQUEyQixDQUFDdEIsS0FBRDtBQUFBLE1BQWtCOUIsUUFBbEIsVUFBU2dDLE9BQVQ7QUFBQSwyQkFDbkNGLEtBRG1DO0FBRXRDVCxJQUFBQSxVQUFVLG9CQUNMUyxLQUFLLENBQUNULFVBREQ7QUFFUnJCLE1BQUFBLFFBQVEsRUFBUkE7QUFGUTtBQUY0QjtBQUFBLENBQWpDO0FBUVA7Ozs7Ozs7Ozs7O0FBT08sSUFBTXFELG9CQUFvQixHQUFHLFNBQXZCQSxvQkFBdUIsQ0FBQXZCLEtBQUs7QUFBQSwyQkFDcENBLEtBRG9DO0FBRXZDUixJQUFBQSxTQUFTLG9CQUNKUSxLQUFLLENBQUNSLFNBREYsdUNBRU5YLG9DQUFtQkUsSUFGYixvQkFHRmlCLEtBQUssQ0FBQ1IsU0FBTixDQUFnQlgsb0NBQW1CRSxJQUFuQyxDQUhFO0FBSUxKLE1BQUFBLE9BQU8sRUFBRSxDQUFDcUIsS0FBSyxDQUFDUixTQUFOLENBQWdCWCxvQ0FBbUJFLElBQW5DLEVBQXlDSjtBQUo5QztBQUY4QjtBQUFBLENBQWxDO0FBV1A7Ozs7Ozs7Ozs7OztBQVFPLElBQU02QywrQkFBK0IsR0FBRyxTQUFsQ0EsK0JBQWtDLENBQUN4QixLQUFEO0FBQUEsTUFBa0IxQixlQUFsQixVQUFTNEIsT0FBVDtBQUFBLDJCQUMxQ0YsS0FEMEM7QUFFN0NSLElBQUFBLFNBQVMsb0JBQ0pRLEtBQUssQ0FBQ1IsU0FERix1Q0FFTlgsb0NBQW1CQyxJQUZiLG9CQUdGa0IsS0FBSyxDQUFDUixTQUFOLENBQWdCWCxvQ0FBbUJDLElBQW5DLENBSEU7QUFJTFIsTUFBQUEsZUFBZSxFQUFmQTtBQUpLO0FBRm9DO0FBQUEsQ0FBeEM7QUFXUDs7Ozs7Ozs7OztBQU1PLElBQU1tRCx5QkFBeUIsR0FBRyxTQUE1QkEseUJBQTRCLENBQUN6QixLQUFEO0FBQUEsTUFBa0IwQixNQUFsQixVQUFTeEIsT0FBVDtBQUFBLDJCQUNwQ0YsS0FEb0M7QUFFdkNSLElBQUFBLFNBQVMsb0JBQ0pRLEtBQUssQ0FBQ1IsU0FERjtBQUVQa0MsTUFBQUEsTUFBTSxFQUFOQTtBQUZPO0FBRjhCO0FBQUEsQ0FBbEM7QUFRUDs7Ozs7Ozs7OztBQU1PLElBQU1DLG9CQUFvQixHQUFHLFNBQXZCQSxvQkFBdUIsQ0FBQzNCLEtBQUQ7QUFBQSxNQUFrQnpCLElBQWxCLFVBQVMyQixPQUFUO0FBQUEsMkJBQy9CRixLQUQrQjtBQUVsQ1IsSUFBQUEsU0FBUyxvQkFDSlEsS0FBSyxDQUFDUixTQURGLHVDQUVOWCxvQ0FBbUJDLElBRmIsb0JBR0ZrQixLQUFLLENBQUNSLFNBQU4sQ0FBZ0JYLG9DQUFtQkMsSUFBbkMsQ0FIRTtBQUlMUCxNQUFBQSxJQUFJLEVBQUpBO0FBSks7QUFGeUI7QUFBQSxDQUE3QjtBQVdQOzs7Ozs7Ozs7Ozs7O0FBU08sSUFBTXFELHNCQUFzQixHQUFHLFNBQXpCQSxzQkFBeUIsQ0FBQzVCLEtBQUQ7QUFBQSxNQUFTRSxPQUFULFVBQVNBLE9BQVQ7QUFBQSwyQkFDakNGLEtBRGlDO0FBRXBDTixJQUFBQSxhQUFhLGdEQUFPTSxLQUFLLENBQUNOLGFBQU4sSUFBdUIsRUFBOUIsSUFBbUMsNENBQW1CUSxPQUFuQixDQUFuQztBQUZ1QjtBQUFBLENBQS9CO0FBS1A7Ozs7Ozs7Ozs7Ozs7QUFTTyxJQUFNMkIseUJBQXlCLEdBQUcsU0FBNUJBLHlCQUE0QixDQUFDN0IsS0FBRDtBQUFBLE1BQWtCQyxFQUFsQixVQUFTQyxPQUFUO0FBQUEsMkJBQ3BDRixLQURvQztBQUV2Q04sSUFBQUEsYUFBYSxFQUFFTSxLQUFLLENBQUNOLGFBQU4sQ0FBb0JvQyxNQUFwQixDQUEyQixVQUFBQyxDQUFDO0FBQUEsYUFBSUEsQ0FBQyxDQUFDOUIsRUFBRixLQUFTQSxFQUFiO0FBQUEsS0FBNUI7QUFGd0I7QUFBQSxDQUFsQztBQUtQOzs7Ozs7Ozs7OztBQU9PLElBQU0rQixnQkFBZ0IsR0FBRyxTQUFuQkEsZ0JBQW1CLENBQUFoQyxLQUFLO0FBQUEsMkJBQ2hDQSxLQURnQztBQUVuQ0wsSUFBQUEsU0FBUyxvQkFDSkssS0FBSyxDQUFDTCxTQURGO0FBRVAvQixNQUFBQSxXQUFXLEVBQUU7QUFGTjtBQUYwQjtBQUFBLENBQTlCO0FBUVA7Ozs7Ozs7Ozs7QUFNTyxJQUFNcUUsdUJBQXVCLEdBQUcsU0FBMUJBLHVCQUEwQixDQUFBakMsS0FBSztBQUFBLDJCQUN2Q0EsS0FEdUM7QUFFMUNMLElBQUFBLFNBQVMsb0JBQ0pLLEtBQUssQ0FBQ0wsU0FERjtBQUVQL0IsTUFBQUEsV0FBVyxFQUFFO0FBRk47QUFGaUM7QUFBQSxDQUFyQztBQVFQOzs7Ozs7Ozs7Ozs7QUFRTyxJQUFNc0UsbUJBQW1CLEdBQUcsU0FBdEJBLG1CQUFzQixDQUFDbEMsS0FBRDtBQUFBLE1BQVN0QyxLQUFULFVBQVNBLEtBQVQ7QUFBQSxTQUNqQ2tFLHNCQUFzQixtQkFFZjVCLEtBRmU7QUFHbEJMLElBQUFBLFNBQVMsb0JBQ0pLLEtBQUssQ0FBQ0wsU0FERjtBQUVQL0IsTUFBQUEsV0FBVyxFQUFFO0FBRk47QUFIUyxNQVFwQjtBQUNFc0MsSUFBQUEsT0FBTyxFQUFFLDJDQUFrQjtBQUN6QmlDLE1BQUFBLE9BQU8sRUFBRSxDQUFDekUsS0FBSyxJQUFJLEVBQVYsRUFBY3lFLE9BQWQsSUFBeUIsd0JBRFQ7QUFFekJDLE1BQUFBLEtBQUssRUFBRUMsNkNBQTRCQztBQUZWLEtBQWxCO0FBRFgsR0FSb0IsQ0FEVztBQUFBLENBQTVCO0FBaUJQOzs7Ozs7Ozs7OztBQU9PLElBQU1DLHFCQUFxQixHQUFHLFNBQXhCQSxxQkFBd0IsQ0FBQXZDLEtBQUs7QUFBQSwyQkFDckNBLEtBRHFDO0FBRXhDUCxJQUFBQSxXQUFXLEVBQUUrQyxNQUFNLENBQUNDLE9BQVAsQ0FBZXpDLEtBQUssQ0FBQ1AsV0FBckIsRUFBa0NuRCxNQUFsQyxDQUNYLFVBQUNvRyxHQUFELEVBQU1DLEtBQU47QUFBQSwrQkFDS0QsR0FETCx1Q0FFR0MsS0FBSyxDQUFDLENBQUQsQ0FGUixvQkFHT0EsS0FBSyxDQUFDLENBQUQsQ0FIWjtBQUlJdkcsUUFBQUEsY0FBYyxFQUFFO0FBSnBCO0FBQUEsS0FEVyxFQVFYLEVBUlc7QUFGMkI7QUFBQSxDQUFuQztBQWNQOzs7Ozs7Ozs7Ozs7O0FBU08sSUFBTXdHLGdCQUFnQixHQUFHLFNBQW5CQSxnQkFBbUIsQ0FBQzVDLEtBQUQ7QUFBQSxNQUFtQkosTUFBbkIsVUFBU00sT0FBVCxDQUFtQk4sTUFBbkI7QUFBQSwyQkFDM0JJLEtBRDJCO0FBRTlCSixJQUFBQSxNQUFNLEVBQU5BO0FBRjhCO0FBQUEsQ0FBekIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMjAgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQge1xuICBBRERfREFUQV9JRCxcbiAgREVGQVVMVF9OT1RJRklDQVRJT05fVE9QSUNTLFxuICBERUxFVEVfREFUQV9JRCxcbiAgRVhQT1JUX0RBVEFfVFlQRSxcbiAgRVhQT1JUX0hUTUxfTUFQX01PREVTLFxuICBFWFBPUlRfSU1HX1JBVElPUyxcbiAgRVhQT1JUX01BUF9GT1JNQVRTLFxuICBSRVNPTFVUSU9OUyxcbiAgTE9DQUxFU1xufSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5pbXBvcnQge2NyZWF0ZU5vdGlmaWNhdGlvbiwgZXJyb3JOb3RpZmljYXRpb259IGZyb20gJ3V0aWxzL25vdGlmaWNhdGlvbnMtdXRpbHMnO1xuaW1wb3J0IHtjYWxjdWxhdGVFeHBvcnRJbWFnZVNpemV9IGZyb20gJ3V0aWxzL2V4cG9ydC11dGlscyc7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0FDVElWRV9TSURFX1BBTkVMID0gJ2xheWVyJztcbmV4cG9ydCBjb25zdCBERUZBVUxUX01PREFMID0gQUREX0RBVEFfSUQ7XG5cbi8qKlxuICogVXBkYXRlcnMgZm9yIGB1aVN0YXRlYCByZWR1Y2VyLiBDYW4gYmUgdXNlZCBpbiB5b3VyIHJvb3QgcmVkdWNlciB0byBkaXJlY3RseSBtb2RpZnkga2VwbGVyLmdsJ3Mgc3RhdGUuXG4gKiBSZWFkIG1vcmUgYWJvdXQgW1VzaW5nIHVwZGF0ZXJzXSguLi9hZHZhbmNlZC11c2FnZS91c2luZy11cGRhdGVycy5tZClcbiAqXG4gKiBAcHVibGljXG4gKiBAZXhhbXBsZVxuICpcbiAqIGltcG9ydCBrZXBsZXJHbFJlZHVjZXIsIHt1aVN0YXRlVXBkYXRlcnN9IGZyb20gJ2tlcGxlci5nbC9yZWR1Y2Vycyc7XG4gKiAvLyBSb290IFJlZHVjZXJcbiAqIGNvbnN0IHJlZHVjZXJzID0gY29tYmluZVJlZHVjZXJzKHtcbiAqICBrZXBsZXJHbDoga2VwbGVyR2xSZWR1Y2VyLFxuICogIGFwcDogYXBwUmVkdWNlclxuICogfSk7XG4gKlxuICogY29uc3QgY29tcG9zZWRSZWR1Y2VyID0gKHN0YXRlLCBhY3Rpb24pID0+IHtcbiAqICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gKiAgICAvLyBjbGljayBidXR0b24gdG8gY2xvc2Ugc2lkZSBwYW5lbFxuICogICAgY2FzZSAnQ0xJQ0tfQlVUVE9OJzpcbiAqICAgICAgcmV0dXJuIHtcbiAqICAgICAgICAuLi5zdGF0ZSxcbiAqICAgICAgICBrZXBsZXJHbDoge1xuICogICAgICAgICAgLi4uc3RhdGUua2VwbGVyR2wsXG4gKiAgICAgICAgICBmb286IHtcbiAqICAgICAgICAgICAgIC4uLnN0YXRlLmtlcGxlckdsLmZvbyxcbiAqICAgICAgICAgICAgIHVpU3RhdGU6IHVpU3RhdGVVcGRhdGVycy50b2dnbGVTaWRlUGFuZWxVcGRhdGVyKFxuICogICAgICAgICAgICAgICB1aVN0YXRlLCB7cGF5bG9hZDogbnVsbH1cbiAqICAgICAgICAgICAgIClcbiAqICAgICAgICAgIH1cbiAqICAgICAgICB9XG4gKiAgICAgIH07XG4gKiAgfVxuICogIHJldHVybiByZWR1Y2VycyhzdGF0ZSwgYWN0aW9uKTtcbiAqIH07XG4gKlxuICogZXhwb3J0IGRlZmF1bHQgY29tcG9zZWRSZWR1Y2VyO1xuICovXG4vKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqL1xuY29uc3QgdWlTdGF0ZVVwZGF0ZXJzID0gbnVsbDtcbi8qIGVzbGludC1lbmFibGUgbm8tdW51c2VkLXZhcnMgKi9cblxuLyoqXG4gKiBBIGxpc3Qgb2YgbWFwIGNvbnRyb2wgdmlzaWJpbGl0eSBhbmQgd2hldGhlciBpcyBpdCBhY3RpdmUuXG4gKiBAbWVtYmVyb2YgdWlTdGF0ZVVwZGF0ZXJzXG4gKiBAY29uc3RhbnRcbiAqIEB0eXBlIHtPYmplY3R9XG4gKiBAcHJvcGVydHkge09iamVjdH0gdmlzaWJsZUxheWVycyBEZWZhdWx0OiBge3Nob3c6IHRydWUsIGFjdGl2ZTogZmFsc2V9YFxuICogQHByb3BlcnR5IHtPYmplY3R9IG1hcExlZ2VuZCBEZWZhdWx0OiBge3Nob3c6IHRydWUsIGFjdGl2ZTogZmFsc2V9YFxuICogQHByb3BlcnR5IHtPYmplY3R9IHRvZ2dsZTNkIERlZmF1bHQ6IGB7c2hvdzogdHJ1ZX1gXG4gKiBAcHJvcGVydHkge09iamVjdH0gc3BsaXRNYXAgRGVmYXVsdDogYHtzaG93OiB0cnVlfWBcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtYXBEcmF3IERlZmF1bHQ6IGB7c2hvdzogdHJ1ZSwgYWN0aXZlOiBmYWxzZX1gXG4gKiBAcHJvcGVydHkge09iamVjdH0gbWFwTG9jYWxlIERlZmF1bHQ6IGB7c2hvdzogZmFsc2UsIGFjdGl2ZTogZmFsc2V9YFxuICogQHB1YmxpY1xuICovXG5jb25zdCBERUZBVUxUX01BUF9DT05UUk9MU19GRUFUVVJFUyA9IHtcbiAgc2hvdzogdHJ1ZSxcbiAgYWN0aXZlOiBmYWxzZSxcbiAgLy8gZGVmaW5lcyB3aGljaCBtYXAgaW5kZXggdXNlcnMgYXJlIGludGVyYWN0aW5nIHdpdGggKHRocm91Z2ggbWFwIGNvbnRyb2xzKVxuICBhY3RpdmVNYXBJbmRleDogMFxufTtcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfTUFQX0NPTlRST0xTID0gW1xuICAndmlzaWJsZUxheWVycycsXG4gICdtYXBMZWdlbmQnLFxuICAndG9nZ2xlM2QnLFxuICAnc3BsaXRNYXAnLFxuICAnbWFwRHJhdycsXG4gICdtYXBMb2NhbGUnXG5dLnJlZHVjZShcbiAgKGZpbmFsLCBjdXJyZW50KSA9PiAoe1xuICAgIC4uLmZpbmFsLFxuICAgIFtjdXJyZW50XTogREVGQVVMVF9NQVBfQ09OVFJPTFNfRkVBVFVSRVNcbiAgfSksXG4gIHt9XG4pO1xuXG5cbi8qKlxuICogRGVmYXVsdCBpbWFnZSBleHBvcnQgY29uZmlnXG4gKiBAbWVtYmVyb2YgdWlTdGF0ZVVwZGF0ZXJzXG4gKiBAY29uc3RhbnRcbiAqIEB0eXBlIHtPYmplY3R9XG4gKiBAcHJvcGVydHkge3N0cmluZ30gcmF0aW8gRGVmYXVsdDogYCdTQ1JFRU4nYCxcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSByZXNvbHV0aW9uIERlZmF1bHQ6IGAnT05FX1gnYCxcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gbGVnZW5kIERlZmF1bHQ6IGBmYWxzZWAsXG4gKiBAcHJvcGVydHkge3N0cmluZ30gaW1hZ2VEYXRhVXJpIERlZmF1bHQ6IGAnJ2AsXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGV4cG9ydGluZyBEZWZhdWx0OiBgZmFsc2VgXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGVycm9yIERlZmF1bHQ6IGBmYWxzZWBcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRVhQT1JUX0lNQUdFID0ge1xuICAvLyB1c2VyIG9wdGlvbnNcbiAgcmF0aW86IEVYUE9SVF9JTUdfUkFUSU9TLlNDUkVFTixcbiAgcmVzb2x1dGlvbjogUkVTT0xVVElPTlMuT05FX1gsXG4gIGxlZ2VuZDogZmFsc2UsXG4gIG1hcEg6IDAsXG4gIG1hcFc6IDAsXG4gIGltYWdlU2l6ZToge1xuICAgIHpvb21PZmZzZXQ6IDAsXG4gICAgc2NhbGU6IDEsXG4gICAgaW1hZ2VXOiAwLFxuICAgIGltYWdlSDogMFxuICB9LFxuICAvLyBleHBvcnRpbmcgc3RhdGVcbiAgaW1hZ2VEYXRhVXJpOiAnJyxcbiAgZXhwb3J0aW5nOiBmYWxzZSxcbiAgZXJyb3I6IGZhbHNlXG59O1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9MT0FEX0ZJTEVTID0ge1xuICBmaWxlTG9hZGluZzogZmFsc2Vcbn07XG5cbi8qKlxuICogRGVmYXVsdCBpbml0aWFsIGBleHBvcnREYXRhYCBzZXR0aW5nc1xuICogQG1lbWJlcm9mIHVpU3RhdGVVcGRhdGVyc1xuICogQGNvbnN0YW50XG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtzdHJpbmd9IHNlbGVjdGVkRGF0YXNldCBEZWZhdWx0OiBgJydgLFxuICogQHByb3BlcnR5IHtzdHJpbmd9IGRhdGFUeXBlIERlZmF1bHQ6IGAnY3N2J2AsXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGZpbHRlcmVkIERlZmF1bHQ6IGB0cnVlYCxcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gY29uZmlnIGRlcHJlY2F0ZWRcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gZGF0YSB1c2VkIGluIG1vZGFsIGNvbmZpZyBleHBvcnQuIERlZmF1bHQ6IGBmYWxzZWBcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRVhQT1JUX0RBVEEgPSB7XG4gIHNlbGVjdGVkRGF0YXNldDogJycsXG4gIGRhdGFUeXBlOiBFWFBPUlRfREFUQV9UWVBFLkNTVixcbiAgZmlsdGVyZWQ6IHRydWVcbn07XG5cbi8qKlxuICogQGNvbnN0YW50XG4gKiBAdHlwZSB7QXJyYXl9XG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX05PVElGSUNBVElPTlMgPSBbXTtcblxuLyoqXG4gKiBAY29uc3RhbnRcbiAqIEB0eXBlIHtPYmplY3R9XG4gKiBAcHJvcGVydHkge3N0cmluZ30gZXhwb3J0TWFwYm94QWNjZXNzVG9rZW4gLSBEZWZhdWx0OiBudWxsLCB0aGlzIGlzIHVzZWQgd2hlbiB3ZSBwcm92aWRlIGEgZGVmYXVsdCBtYXBib3ggdG9rZW4gZm9yIHVzZXJzIHRvIHRha2UgYWR2YW50YWdlIG9mXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdXNlck1hcGJveFRva2VuIC0gRGVmYXVsdDogJycsIG1hcGJveCB0b2tlbiBwcm92aWRlZCBieSB1c2VyIHRocm91Z2ggaW5wdXQgZmllbGRcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRVhQT1JUX0hUTUwgPSB7XG4gIGV4cG9ydE1hcGJveEFjY2Vzc1Rva2VuOiBudWxsLFxuICB1c2VyTWFwYm94VG9rZW46ICcnLFxuICBtb2RlOiBFWFBPUlRfSFRNTF9NQVBfTU9ERVMuUkVBRFxufTtcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfRVhQT1JUX0pTT04gPSB7XG4gIGhhc0RhdGE6IHRydWVcbn07XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0VYUE9SVF9NQVAgPSB7XG4gIFtFWFBPUlRfTUFQX0ZPUk1BVFMuSFRNTF06IERFRkFVTFRfRVhQT1JUX0hUTUwsXG4gIFtFWFBPUlRfTUFQX0ZPUk1BVFMuSlNPTl06IERFRkFVTFRfRVhQT1JUX0pTT04sXG4gIGZvcm1hdDogRVhQT1JUX01BUF9GT1JNQVRTLkhUTUxcbn07XG5cbi8qKlxuICogRGVmYXVsdCBpbml0aWFsIGB1aVN0YXRlYFxuICogQG1lbWJlcm9mIHVpU3RhdGVVcGRhdGVyc1xuICogQGNvbnN0YW50XG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtib29sZWFufSByZWFkT25seSBEZWZhdWx0OiBgZmFsc2VgXG4gKiBAcHJvcGVydHkge3N0cmluZ30gYWN0aXZlU2lkZVBhbmVsIERlZmF1bHQ6IGAnbGF5ZXInYFxuICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gY3VycmVudE1vZGFsIERlZmF1bHQ6IGAnYWRkRGF0YSdgXG4gKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBkYXRhc2V0S2V5VG9SZW1vdmUgRGVmYXVsdDogYG51bGxgXG4gKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSB2aXNpYmxlRHJvcGRvd24gRGVmYXVsdDogYG51bGxgXG4gKiBAcHJvcGVydHkge09iamVjdH0gZXhwb3J0SW1hZ2UgRGVmYXVsdDogW2BERUZBVUxUX0VYUE9SVF9JTUFHRWBdKCNkZWZhdWx0X2V4cG9ydF9pbWFnZSlcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBleHBvcnREYXRhIERlZmF1bHQ6IFtgREVGQVVMVF9FWFBPUlRfREFUQWBdKCNkZWZhdWx0X2V4cG9ydF9kYXRhKVxuICogQHByb3BlcnR5IHtPYmplY3R9IG1hcENvbnRyb2xzIERlZmF1bHQ6IFtgREVGQVVMVF9NQVBfQ09OVFJPTFNgXSgjZGVmYXVsdF9tYXBfY29udHJvbHMpXG4gKiBAcHJvcGVydHkge251bWJlcn0gYWN0aXZlTWFwSW5kZXggZGVmaW5lcyB3aGljaCBtYXAgdGhlIHVzZXIgY2xpY2tlZCBvbi4gRGVmYXVsdDogMFxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgSU5JVElBTF9VSV9TVEFURSA9IHtcbiAgcmVhZE9ubHk6IGZhbHNlLFxuICBhY3RpdmVTaWRlUGFuZWw6IERFRkFVTFRfQUNUSVZFX1NJREVfUEFORUwsXG4gIGN1cnJlbnRNb2RhbDogREVGQVVMVF9NT0RBTCxcbiAgZGF0YXNldEtleVRvUmVtb3ZlOiBudWxsLFxuICB2aXNpYmxlRHJvcGRvd246IG51bGwsXG4gIC8vIGV4cG9ydCBpbWFnZSBtb2RhbCB1aVxuICBleHBvcnRJbWFnZTogREVGQVVMVF9FWFBPUlRfSU1BR0UsXG4gIC8vIGV4cG9ydCBkYXRhIG1vZGFsIHVpXG4gIGV4cG9ydERhdGE6IERFRkFVTFRfRVhQT1JUX0RBVEEsXG4gIC8vIGh0bWwgZXhwb3J0XG4gIGV4cG9ydE1hcDogREVGQVVMVF9FWFBPUlRfTUFQLFxuICAvLyBtYXAgY29udHJvbCBwYW5lbHNcbiAgbWFwQ29udHJvbHM6IERFRkFVTFRfTUFQX0NPTlRST0xTLFxuICAvLyB1aSBub3RpZmljYXRpb25zXG4gIG5vdGlmaWNhdGlvbnM6IERFRkFVTFRfTk9USUZJQ0FUSU9OUyxcbiAgLy8gbG9hZCBmaWxlc1xuICBsb2FkRmlsZXM6IERFRkFVTFRfTE9BRF9GSUxFUyxcbiAgLy8gTG9jYWxlIG9mIHRoZSBVSVxuICBsb2NhbGU6IExPQ0FMRVMuZW5cbn07XG5cbi8qIFVwZGF0ZXJzICovXG4vKipcbiAqIFRvZ2dsZSBhY3RpdmUgc2lkZSBwYW5lbFxuICogQG1lbWJlcm9mIHVpU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB1aVN0YXRlYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvblxuICogQHBhcmFtIHtzdHJpbmd8bnVsbH0gYWN0aW9uLnBheWxvYWQgaWQgb2Ygc2lkZSBwYW5lbCB0byBiZSBzaG93biwgb25lIG9mIGBsYXllcmAsIGBmaWx0ZXJgLCBgaW50ZXJhY3Rpb25gLCBgbWFwYC4gY2xvc2Ugc2lkZSBwYW5lbCBpZiBgbnVsbGBcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgdG9nZ2xlU2lkZVBhbmVsVXBkYXRlciA9IChzdGF0ZSwge3BheWxvYWQ6IGlkfSkgPT4ge1xuICByZXR1cm4gaWQgPT09IHN0YXRlLmFjdGl2ZVNpZGVQYW5lbFxuICAgID8gc3RhdGVcbiAgICA6IHtcbiAgICAgICAgLi4uc3RhdGUsXG4gICAgICAgIGFjdGl2ZVNpZGVQYW5lbDogaWRcbiAgICAgIH07XG59O1xuXG4vKipcbiAqIFNob3cgYW5kIGhpZGUgbW9kYWwgZGlhbG9nXG4gKiBAbWVtYmVyb2YgdWlTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHVpU3RhdGVgXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ3xudWxsfSBhY3Rpb24ucGF5bG9hZCBpZCBvZiBtb2RhbCB0byBiZSBzaG93biwgbnVsbCB0byBoaWRlIG1vZGFscy4gT25lIG9mOlxuICpcbiAqICAtIFtgREFUQV9UQUJMRV9JRGBdKC4uL2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzLm1kI2RhdGFfdGFibGVfaWQpXG4gKiAgLSBbYERFTEVURV9EQVRBX0lEYF0oLi4vY29uc3RhbnRzL2RlZmF1bHQtc2V0dGluZ3MubWQjZGVsZXRlX2RhdGFfaWQpXG4gKiAgLSBbYEFERF9EQVRBX0lEYF0oLi4vY29uc3RhbnRzL2RlZmF1bHQtc2V0dGluZ3MubWQjYWRkX2RhdGFfaWQpXG4gKiAgLSBbYEVYUE9SVF9JTUFHRV9JRGBdKC4uL2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzLm1kI2V4cG9ydF9pbWFnZV9pZClcbiAqICAtIFtgRVhQT1JUX0RBVEFfSURgXSguLi9jb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncy5tZCNleHBvcnRfZGF0YV9pZClcbiAqICAtIFtgQUREX01BUF9TVFlMRV9JRGBdKC4uL2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzLm1kI2FkZF9tYXBfc3R5bGVfaWQpXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHRvZ2dsZU1vZGFsVXBkYXRlciA9IChzdGF0ZSwge3BheWxvYWQ6IGlkfSkgPT4gKHtcbiAgLi4uc3RhdGUsXG4gIGN1cnJlbnRNb2RhbDogaWRcbn0pO1xuXG4vKipcbiAqIEhpZGUgYW5kIHNob3cgc2lkZSBwYW5lbCBoZWFkZXIgZHJvcGRvd24sIGFjdGl2YXRlZCBieSBjbGlja2luZyB0aGUgc2hhcmUgbGluayBvbiB0b3Agb2YgdGhlIHNpZGUgcGFuZWxcbiAqIEBtZW1iZXJvZiB1aVN0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdWlTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24ucGF5bG9hZCBpZCBvZiB0aGUgZHJvcGRvd25cbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3Qgc2hvd0V4cG9ydERyb3Bkb3duVXBkYXRlciA9IChzdGF0ZSwge3BheWxvYWQ6IGlkfSkgPT4gKHtcbiAgLi4uc3RhdGUsXG4gIHZpc2libGVEcm9wZG93bjogaWRcbn0pO1xuXG4vKipcbiAqIEhpZGUgc2lkZSBwYW5lbCBoZWFkZXIgZHJvcGRvd24sIGFjdGl2YXRlZCBieSBjbGlja2luZyB0aGUgc2hhcmUgbGluayBvbiB0b3Agb2YgdGhlIHNpZGUgcGFuZWxcbiAqIEBtZW1iZXJvZiB1aVN0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdWlTdGF0ZWBcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgaGlkZUV4cG9ydERyb3Bkb3duVXBkYXRlciA9IHN0YXRlID0+ICh7XG4gIC4uLnN0YXRlLFxuICB2aXNpYmxlRHJvcGRvd246IG51bGxcbn0pO1xuXG4vKipcbiAqIFRvZ2dsZSBhY3RpdmUgbWFwIGNvbnRyb2wgcGFuZWxcbiAqIEBtZW1iZXJvZiB1aVN0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdWlTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ30gYWN0aW9uLnBheWxvYWQgbWFwIGNvbnRyb2wgcGFuZWwgaWQsIG9uZSBvZiB0aGUga2V5cyBvZjogW2BERUZBVUxUX01BUF9DT05UUk9MU2BdKCNkZWZhdWx0X21hcF9jb250cm9scylcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgdG9nZ2xlTWFwQ29udHJvbFVwZGF0ZXIgPSAoc3RhdGUsIHtwYXlsb2FkOiB7cGFuZWxJZCwgaW5kZXggPSAwfX0pID0+ICh7XG4gIC4uLnN0YXRlLFxuICBtYXBDb250cm9sczoge1xuICAgIC4uLnN0YXRlLm1hcENvbnRyb2xzLFxuICAgIFtwYW5lbElkXToge1xuICAgICAgLi4uc3RhdGUubWFwQ29udHJvbHNbcGFuZWxJZF0sXG4gICAgICAvLyB0aGlzIGhhbmRsZXMgc3BsaXQgbWFwIGludGVyYWN0aW9uXG4gICAgICAvLyBUb2dnbGluZyBmcm9tIHdpdGhpbiB0aGUgc2FtZSBtYXAgd2lsbCBzaW1wbHkgdG9nZ2xlIHRoZSBhY3RpdmUgcHJvcGVydHlcbiAgICAgIC8vIFRvZ2dsaW5nIGZyb20gd2l0aGluIGRpZmZlcmVudCBtYXBzIHdlIHNldCB0aGUgYWN0aXZlIHByb3BlcnR5IHRvIHRydWVcbiAgICAgIGFjdGl2ZTpcbiAgICAgICAgaW5kZXggPT09IHN0YXRlLm1hcENvbnRyb2xzW3BhbmVsSWRdLmFjdGl2ZU1hcEluZGV4XG4gICAgICAgICAgPyAhc3RhdGUubWFwQ29udHJvbHNbcGFuZWxJZF0uYWN0aXZlXG4gICAgICAgICAgOiB0cnVlLFxuICAgICAgYWN0aXZlTWFwSW5kZXg6IGluZGV4XG4gICAgfVxuICB9XG59KTtcblxuXG5cbi8qKlxuICogVG9nZ2xlIGFjdGl2ZSBtYXAgY29udHJvbCBwYW5lbFxuICogQG1lbWJlcm9mIHVpU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3