UNPKG

kepler.gl

Version:

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

364 lines (349 loc) 56.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.toggleSplitMapUpdater = exports.replaceDataInMapUpdater = exports.loadFilesSuccessUpdater = exports.isValidConfig = exports.defaultAddDataToMapOptions = exports.combinedMapStyleChangeUpdater = exports.combinedLayerTypeChangeUpdater = exports.addDataToMapUpdater = exports.addDataToMapComposed = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _uiStateUpdaters = require("./ui-state-updaters"); var _visStateUpdaters = require("./vis-state-updaters"); var _mapStateUpdaters = require("./map-state-updaters"); var _mapStyleUpdaters = require("./map-style-updaters"); var _processors = require("@kepler.gl/processors"); var _composerHelpers = require("./composer-helpers"); var _utils = require("@kepler.gl/utils"); var _dataUtils = require("./data-utils"); var _constants = require("@kepler.gl/constants"); function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project // compose action to apply result multiple reducers, with the output of one /** * Some actions will affect the entire kepler.lg instance state. * The updaters for these actions is exported as `combinedUpdaters`. These updater take the entire instance state * as the first argument. Read more about [Using updaters](../advanced-usage/using-updaters.md) * @public * @example * * import keplerGlReducer, {combinedUpdaters} from 'kepler.gl/reducers'; * // Root Reducer * const reducers = combineReducers({ * keplerGl: keplerGlReducer, * app: appReducer * }); * * const composedReducer = (state, action) => { * switch (action.type) { * // add data to map after receiving data from remote sources * case 'LOAD_REMOTE_RESOURCE_SUCCESS': * return { * ...state, * keplerGl: { * ...state.keplerGl, * // pass in kepler.gl instance state to combinedUpdaters * map: combinedUpdaters.addDataToMapUpdater( * state.keplerGl.map, * { * payload: { * datasets: action.datasets, * options: {readOnly: true}, * config: action.config * } * } * ) * } * }; * } * return reducers(state, action); * }; * * export default composedReducer; */ /* eslint-disable @typescript-eslint/no-unused-vars */ // @ts-ignore var combinedUpdaters = null; /* eslint-enable @typescript-eslint/no-unused-vars */ var isValidConfig = exports.isValidConfig = function isValidConfig(config) { return (0, _utils.isPlainObject)(config) && (0, _utils.isPlainObject)(config.config) && config.version; }; var defaultAddDataToMapOptions = exports.defaultAddDataToMapOptions = { centerMap: true, keepExistingConfig: false, autoCreateLayers: true, autoCreateTooltips: true }; /** * Combine data and full configuration update in a single action * * @memberof combinedUpdaters * @param {Object} state kepler.gl instance state, containing all subreducer state * @param {Object} action * @param {Object} action.payload `{datasets, options, config}` * @param action.payload.datasets - ***required** datasets can be a dataset or an array of datasets * Each dataset object needs to have `info` and `data` property. * @param [action.payload.options] option object `{centerMap: true}` * @param [action.payload.config] map config * @param [action.payload.info] map info contains title and description * @returns nextState * * @typedef {Object} Dataset * @property info -info of a dataset * @property info.id - id of this dataset. If config is defined, `id` should matches the `dataId` in config. * @property info.label - A display name of this dataset * @property data - ***required** The data object, in a tabular format with 2 properties `fields` and `rows` * @property data.fields - ***required** Array of fields, * @property data.fields.name - ***required** Name of the field, * @property data.rows - ***required** Array of rows, in a tabular format with `fields` and `rows` * * @public */ var addDataToMapUpdater = exports.addDataToMapUpdater = function addDataToMapUpdater(state, _ref) { var _datasets$, _datasets$2, _datasets$3, _parsedConfig, _parsedConfig2, _parsedConfig$uiState, _parsedConfig3; var payload = _ref.payload; var datasets = payload.datasets, config = payload.config, info = payload.info; var options = _objectSpread(_objectSpread({}, defaultAddDataToMapOptions), payload.options); // check if progressive loading dataset by batches, and update visState directly var isProgressiveLoading = Array.isArray(datasets) && ((_datasets$ = datasets[0]) === null || _datasets$ === void 0 ? void 0 : _datasets$.info.format) === 'arrow' && ((_datasets$2 = datasets[0]) === null || _datasets$2 === void 0 ? void 0 : _datasets$2.info.id) && ((_datasets$3 = datasets[0]) === null || _datasets$3 === void 0 ? void 0 : _datasets$3.info.id) in state.visState.datasets; if (isProgressiveLoading) { return (0, _composerHelpers.compose_)([(0, _composerHelpers.pick_)('visState')((0, _composerHelpers.apply_)(_visStateUpdaters.updateVisDataUpdater, { datasets: datasets, options: options, config: config }))])(state); } // @ts-expect-error var parsedConfig = config; if (isValidConfig(config)) { // if passed in saved config // @ts-expect-error parsedConfig = state.visState.schema.parseSavedConfig(config); } var oldLayers = state.visState.layers; var filterNewlyAddedLayers = function filterNewlyAddedLayers(layers) { return layers.filter(function (nl) { return !oldLayers.find(function (ol) { return ol === nl; }); }); }; // Returns undefined if not found, to make typescript happy var findMapBoundsIfCentered = function findMapBoundsIfCentered(layers) { var bounds = options.centerMap && (0, _dataUtils.findMapBounds)(layers); return bounds ? bounds : undefined; }; return (0, _composerHelpers.compose_)([(0, _composerHelpers.pick_)('visState')((0, _composerHelpers.apply_)(_visStateUpdaters.updateVisDataUpdater, { datasets: datasets, options: options, config: parsedConfig })), (0, _composerHelpers.if_)(Boolean(info), (0, _composerHelpers.pick_)('visState')((0, _composerHelpers.apply_)(_visStateUpdaters.setMapInfoUpdater, { info: info }))), // Note that fit bounds here won't be called in case datasets are created in Tasks. // A separate Task to update bounds is created once the datasets are ready. (0, _composerHelpers.with_)(function (_ref2) { var visState = _ref2.visState; return (0, _composerHelpers.pick_)('mapState')((0, _composerHelpers.apply_)(_mapStateUpdaters.receiveMapConfigUpdater, (0, _composerHelpers.payload_)({ config: parsedConfig, options: options, bounds: findMapBoundsIfCentered(filterNewlyAddedLayers(visState.layers)) }))); }), (0, _composerHelpers.pick_)('mapStyle')((0, _composerHelpers.apply_)(_mapStyleUpdaters.receiveMapConfigUpdater, (0, _composerHelpers.payload_)({ config: parsedConfig, options: options }))), (0, _composerHelpers.pick_)('uiState')((0, _composerHelpers.apply_)(_uiStateUpdaters.loadFilesSuccessUpdater, (0, _composerHelpers.payload_)(null))), (0, _composerHelpers.if_)(Boolean((_parsedConfig = parsedConfig) === null || _parsedConfig === void 0 || (_parsedConfig = _parsedConfig.uiState) === null || _parsedConfig === void 0 || (_parsedConfig = _parsedConfig.mapControls) === null || _parsedConfig === void 0 || (_parsedConfig = _parsedConfig.mapLegend) === null || _parsedConfig === void 0 ? void 0 : _parsedConfig.active), (0, _composerHelpers.pick_)('uiState')((0, _composerHelpers.apply_)(_uiStateUpdaters.toggleMapControlUpdater, (0, _composerHelpers.payload_)({ panelId: 'mapLegend', index: 0 })))), (0, _composerHelpers.if_)(Boolean((_parsedConfig2 = parsedConfig) === null || _parsedConfig2 === void 0 || (_parsedConfig2 = _parsedConfig2.uiState) === null || _parsedConfig2 === void 0 || (_parsedConfig2 = _parsedConfig2.mapControls) === null || _parsedConfig2 === void 0 || (_parsedConfig2 = _parsedConfig2.mapLegend) === null || _parsedConfig2 === void 0 ? void 0 : _parsedConfig2.settings), (0, _composerHelpers.pick_)('uiState')((0, _composerHelpers.apply_)(_uiStateUpdaters.setMapControlSettingsUpdater, (0, _composerHelpers.payload_)({ panelId: 'mapLegend', settings: (_parsedConfig$uiState = (_parsedConfig3 = parsedConfig) === null || _parsedConfig3 === void 0 || (_parsedConfig3 = _parsedConfig3.uiState) === null || _parsedConfig3 === void 0 || (_parsedConfig3 = _parsedConfig3.mapControls) === null || _parsedConfig3 === void 0 || (_parsedConfig3 = _parsedConfig3.mapLegend) === null || _parsedConfig3 === void 0 ? void 0 : _parsedConfig3.settings) !== null && _parsedConfig$uiState !== void 0 ? _parsedConfig$uiState : {} })))), (0, _composerHelpers.pick_)('uiState')((0, _composerHelpers.apply_)(_uiStateUpdaters.toggleModalUpdater, (0, _composerHelpers.payload_)(null))), (0, _composerHelpers.pick_)('uiState')((0, _composerHelpers.merge_)(Object.prototype.hasOwnProperty.call(options, 'readOnly') ? { readOnly: options.readOnly } : {}))])(state); }; var loadFilesSuccessUpdater = exports.loadFilesSuccessUpdater = function loadFilesSuccessUpdater(state, action) { // still more to load var payloads = (0, _processors.filesToDataPayload)(action.result); var nextState = (0, _composerHelpers.compose_)([(0, _composerHelpers.pick_)('visState')((0, _composerHelpers.merge_)({ fileLoading: false, fileLoadingProgress: {} }))])(state); // make multiple add data to map calls var stateWithData = (0, _composerHelpers.compose_)(payloads.map(function (p) { return (0, _composerHelpers.apply_)(addDataToMapUpdater, (0, _composerHelpers.payload_)(p)); }))(nextState); return stateWithData; }; var addDataToMapComposed = exports.addDataToMapComposed = addDataToMapUpdater; /** * Helper which updates map overlay blending mode in visState, * but only if it's not currently in the `normal` mode. */ var updateOverlayBlending = function updateOverlayBlending(overlayBlending) { return function (visState) { if (visState.overlayBlending !== _constants.OVERLAY_BLENDINGS.normal.value) { return _objectSpread(_objectSpread({}, visState), {}, { overlayBlending: overlayBlending }); } return visState; }; }; /** * Helper which updates `darkBaseMapEnabled` in all the layers in visState which * have this config setting (or in one specific layer if the `layerId` param is provided). */ var updateDarkBaseMapLayers = function updateDarkBaseMapLayers(darkBaseMapEnabled) { var layerId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; return function (visState) { return _objectSpread(_objectSpread({}, visState), {}, { layers: visState.layers.map(function (layer) { if (!layerId || layer.id === layerId) { if (Object.prototype.hasOwnProperty.call(layer.visConfigSettings, 'darkBaseMapEnabled')) { var visConfig = layer.config.visConfig; return layer.updateLayerConfig({ visConfig: _objectSpread(_objectSpread({}, visConfig), {}, { darkBaseMapEnabled: darkBaseMapEnabled }) }); } } return layer; }) }); }; }; /** * Updater that changes the map style by calling mapStyleChangeUpdater on visState. * In addition to that, it does the following: * * 1. Update map overlay blending mode in accordance with the colorMode of the * base map, but only if it's not in the `normal` mode. * * 2. Update all the layers which have the `darkBaseMapEnabled` config setting * adjusting it in accordance with the colorMode of the base map. * */ var combinedMapStyleChangeUpdater = exports.combinedMapStyleChangeUpdater = function combinedMapStyleChangeUpdater(state, action) { var payload = action.payload; var mapStyle = state.mapStyle; var getColorMode = function getColorMode(key) { var _mapStyle$mapStyles$k; return (_mapStyle$mapStyles$k = mapStyle.mapStyles[key]) === null || _mapStyle$mapStyles$k === void 0 ? void 0 : _mapStyle$mapStyles$k.colorMode; }; var prevColorMode = getColorMode(mapStyle.styleType); var nextColorMode = getColorMode(payload.styleType); var visState = state.visState; if (nextColorMode !== prevColorMode) { switch (nextColorMode) { case _constants.BASE_MAP_COLOR_MODES.DARK: visState = (0, _composerHelpers.compose_)([updateOverlayBlending(_constants.OVERLAY_BLENDINGS.screen.value), updateDarkBaseMapLayers(true)])(visState); break; case _constants.BASE_MAP_COLOR_MODES.LIGHT: visState = (0, _composerHelpers.compose_)([updateOverlayBlending(_constants.OVERLAY_BLENDINGS.darken.value), updateDarkBaseMapLayers(false)])(visState); break; default: // do nothing } } return _objectSpread(_objectSpread({}, state), {}, { visState: visState, mapStyle: (0, _mapStyleUpdaters.mapStyleChangeUpdater)(mapStyle, { payload: _objectSpread({}, payload) }) }); }; /** * Updater that changes the layer type by calling `layerTypeChangeUpdater` on visState. * In addition to that, if the new layer type has the `darkBaseMapEnabled` config * setting, we adjust it in accordance with the colorMode of the base map.s */ var combinedLayerTypeChangeUpdater = exports.combinedLayerTypeChangeUpdater = function combinedLayerTypeChangeUpdater(state, action) { var visState = state.visState; var oldLayerIndex = visState.layers.findIndex(function (layer) { return layer === action.oldLayer; }); visState = (0, _visStateUpdaters.layerTypeChangeUpdater)(visState, action); var newLayer = visState.layers[oldLayerIndex]; if (Object.prototype.hasOwnProperty.call(newLayer === null || newLayer === void 0 ? void 0 : newLayer.visConfigSettings, 'darkBaseMapEnabled')) { var mapStyle = state.mapStyle; var colorMode = mapStyle.mapStyles[mapStyle.styleType].colorMode; var darkBaseMapEnabled = newLayer.config.visConfig.darkBaseMapEnabled; switch (colorMode) { case _constants.BASE_MAP_COLOR_MODES.DARK: if (!darkBaseMapEnabled) { visState = updateDarkBaseMapLayers(true, newLayer.id)(visState); } break; case _constants.BASE_MAP_COLOR_MODES.LIGHT: if (darkBaseMapEnabled) { visState = updateDarkBaseMapLayers(false, newLayer.id)(visState); } break; default: // do nothing } } return _objectSpread(_objectSpread({}, state), {}, { visState: visState }); }; /** * Make mapLegend active when toggleSplitMap action is called */ var toggleSplitMapUpdater = exports.toggleSplitMapUpdater = function toggleSplitMapUpdater(state, action) { var _newState$uiState$map; var newState = _objectSpread(_objectSpread({}, state), {}, { visState: (0, _visStateUpdaters.toggleSplitMapUpdater)(state.visState, action), uiState: (0, _uiStateUpdaters.toggleSplitMapUpdater)(state.uiState), mapState: (0, _mapStateUpdaters.toggleSplitMapUpdater)(state.mapState) }); var isSplit = newState.visState.splitMaps.length !== 0; var isLegendActive = (_newState$uiState$map = newState.uiState.mapControls) === null || _newState$uiState$map === void 0 || (_newState$uiState$map = _newState$uiState$map.mapLegend) === null || _newState$uiState$map === void 0 ? void 0 : _newState$uiState$map.active; if (isSplit && !isLegendActive) { newState.uiState = (0, _uiStateUpdaters.toggleMapControlUpdater)(newState.uiState, { payload: { panelId: 'mapLegend', index: action.payload } }); } return newState; }; var defaultReplaceDataToMapOptions = { keepExistingConfig: true, centerMap: true, autoCreateLayers: false }; /** * Updater replace a dataset in state */ var replaceDataInMapUpdater = exports.replaceDataInMapUpdater = function replaceDataInMapUpdater(state, _ref3) { var payload = _ref3.payload; var datasetToReplaceId = payload.datasetToReplaceId, datasetToUse = payload.datasetToUse, _payload$options = payload.options, options = _payload$options === void 0 ? {} : _payload$options; var addDataToMapOptions = _objectSpread(_objectSpread({}, defaultReplaceDataToMapOptions), options); // check if dataset is there if (!state.visState.datasets[datasetToReplaceId]) { return state; } // datasetToUse is ProtoDataset var dataIdToUse = datasetToUse.info.id; if (!dataIdToUse) { return state; } // remove dataset and put dependencies in toBeMerged var preparedState = _objectSpread(_objectSpread({}, state), {}, { visState: (0, _visStateUpdaters.prepareStateForDatasetReplace)(state.visState, datasetToReplaceId, dataIdToUse) }); var nextState = addDataToMapUpdater(preparedState, (0, _composerHelpers.payload_)({ datasets: datasetToUse, // should zoom to new dataset options: addDataToMapOptions })); return nextState; }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfdWlTdGF0ZVVwZGF0ZXJzIiwicmVxdWlyZSIsIl92aXNTdGF0ZVVwZGF0ZXJzIiwiX21hcFN0YXRlVXBkYXRlcnMiLCJfbWFwU3R5bGVVcGRhdGVycyIsIl9wcm9jZXNzb3JzIiwiX2NvbXBvc2VySGVscGVycyIsIl91dGlscyIsIl9kYXRhVXRpbHMiLCJfY29uc3RhbnRzIiwib3duS2V5cyIsImUiLCJyIiwidCIsIk9iamVjdCIsImtleXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJvIiwiZmlsdGVyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiZGVmaW5lUHJvcGVydHkiLCJjb21iaW5lZFVwZGF0ZXJzIiwiaXNWYWxpZENvbmZpZyIsImV4cG9ydHMiLCJjb25maWciLCJpc1BsYWluT2JqZWN0IiwidmVyc2lvbiIsImRlZmF1bHRBZGREYXRhVG9NYXBPcHRpb25zIiwiY2VudGVyTWFwIiwia2VlcEV4aXN0aW5nQ29uZmlnIiwiYXV0b0NyZWF0ZUxheWVycyIsImF1dG9DcmVhdGVUb29sdGlwcyIsImFkZERhdGFUb01hcFVwZGF0ZXIiLCJzdGF0ZSIsIl9yZWYiLCJfZGF0YXNldHMkIiwiX2RhdGFzZXRzJDIiLCJfZGF0YXNldHMkMyIsIl9wYXJzZWRDb25maWciLCJfcGFyc2VkQ29uZmlnMiIsIl9wYXJzZWRDb25maWckdWlTdGF0ZSIsIl9wYXJzZWRDb25maWczIiwicGF5bG9hZCIsImRhdGFzZXRzIiwiaW5mbyIsIm9wdGlvbnMiLCJpc1Byb2dyZXNzaXZlTG9hZGluZyIsIkFycmF5IiwiaXNBcnJheSIsImZvcm1hdCIsImlkIiwidmlzU3RhdGUiLCJjb21wb3NlXyIsInBpY2tfIiwiYXBwbHlfIiwidmlzU3RhdGVVcGRhdGVWaXNEYXRhVXBkYXRlciIsInBhcnNlZENvbmZpZyIsInNjaGVtYSIsInBhcnNlU2F2ZWRDb25maWciLCJvbGRMYXllcnMiLCJsYXllcnMiLCJmaWx0ZXJOZXdseUFkZGVkTGF5ZXJzIiwibmwiLCJmaW5kIiwib2wiLCJmaW5kTWFwQm91bmRzSWZDZW50ZXJlZCIsImJvdW5kcyIsImZpbmRNYXBCb3VuZHMiLCJ1bmRlZmluZWQiLCJpZl8iLCJCb29sZWFuIiwic2V0TWFwSW5mb1VwZGF0ZXIiLCJ3aXRoXyIsIl9yZWYyIiwic3RhdGVNYXBDb25maWdVcGRhdGVyIiwicGF5bG9hZF8iLCJzdHlsZU1hcENvbmZpZ1VwZGF0ZXIiLCJ1aVN0YXRlTG9hZEZpbGVzU3VjY2Vzc1VwZGF0ZXIiLCJ1aVN0YXRlIiwibWFwQ29udHJvbHMiLCJtYXBMZWdlbmQiLCJhY3RpdmUiLCJ1aVN0YXRlVG9nZ2xlTWFwQ29udHJvbFVwZGF0ZXIiLCJwYW5lbElkIiwiaW5kZXgiLCJzZXR0aW5ncyIsInVpU3RhdGVTZXRNYXBDb250cm9sU2V0dGluZ3NVcGRhdGVyIiwidG9nZ2xlTW9kYWxVcGRhdGVyIiwibWVyZ2VfIiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwicmVhZE9ubHkiLCJsb2FkRmlsZXNTdWNjZXNzVXBkYXRlciIsImFjdGlvbiIsInBheWxvYWRzIiwiZmlsZXNUb0RhdGFQYXlsb2FkIiwicmVzdWx0IiwibmV4dFN0YXRlIiwiZmlsZUxvYWRpbmciLCJmaWxlTG9hZGluZ1Byb2dyZXNzIiwic3RhdGVXaXRoRGF0YSIsIm1hcCIsInAiLCJhZGREYXRhVG9NYXBDb21wb3NlZCIsInVwZGF0ZU92ZXJsYXlCbGVuZGluZyIsIm92ZXJsYXlCbGVuZGluZyIsIk9WRVJMQVlfQkxFTkRJTkdTIiwibm9ybWFsIiwidmFsdWUiLCJ1cGRhdGVEYXJrQmFzZU1hcExheWVycyIsImRhcmtCYXNlTWFwRW5hYmxlZCIsImxheWVySWQiLCJsYXllciIsInZpc0NvbmZpZ1NldHRpbmdzIiwidmlzQ29uZmlnIiwidXBkYXRlTGF5ZXJDb25maWciLCJjb21iaW5lZE1hcFN0eWxlQ2hhbmdlVXBkYXRlciIsIm1hcFN0eWxlIiwiZ2V0Q29sb3JNb2RlIiwia2V5IiwiX21hcFN0eWxlJG1hcFN0eWxlcyRrIiwibWFwU3R5bGVzIiwiY29sb3JNb2RlIiwicHJldkNvbG9yTW9kZSIsInN0eWxlVHlwZSIsIm5leHRDb2xvck1vZGUiLCJCQVNFX01BUF9DT0xPUl9NT0RFUyIsIkRBUksiLCJzY3JlZW4iLCJMSUdIVCIsImRhcmtlbiIsIm1hcFN0eWxlQ2hhbmdlVXBkYXRlciIsImNvbWJpbmVkTGF5ZXJUeXBlQ2hhbmdlVXBkYXRlciIsIm9sZExheWVySW5kZXgiLCJmaW5kSW5kZXgiLCJvbGRMYXllciIsImxheWVyVHlwZUNoYW5nZVVwZGF0ZXIiLCJuZXdMYXllciIsInRvZ2dsZVNwbGl0TWFwVXBkYXRlciIsIl9uZXdTdGF0ZSR1aVN0YXRlJG1hcCIsIm5ld1N0YXRlIiwidmlzU3RhdGVUb2dnbGVTcGxpdE1hcFVwZGF0ZXIiLCJ1aVN0YXRlVG9nZ2xlU3BsaXRNYXBVcGRhdGVyIiwibWFwU3RhdGUiLCJtYXBTdGF0ZVRvZ2dsZVNwbGl0TWFwVXBkYXRlciIsImlzU3BsaXQiLCJzcGxpdE1hcHMiLCJpc0xlZ2VuZEFjdGl2ZSIsInRvZ2dsZU1hcENvbnRyb2xVcGRhdGVyIiwiZGVmYXVsdFJlcGxhY2VEYXRhVG9NYXBPcHRpb25zIiwicmVwbGFjZURhdGFJbk1hcFVwZGF0ZXIiLCJfcmVmMyIsImRhdGFzZXRUb1JlcGxhY2VJZCIsImRhdGFzZXRUb1VzZSIsIl9wYXlsb2FkJG9wdGlvbnMiLCJhZGREYXRhVG9NYXBPcHRpb25zIiwiZGF0YUlkVG9Vc2UiLCJwcmVwYXJlZFN0YXRlIiwicHJlcGFyZVN0YXRlRm9yRGF0YXNldFJlcGxhY2UiXSwic291cmNlcyI6WyIuLi9zcmMvY29tYmluZWQtdXBkYXRlcnMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0IHtcbiAgdG9nZ2xlTW9kYWxVcGRhdGVyLFxuICBsb2FkRmlsZXNTdWNjZXNzVXBkYXRlciBhcyB1aVN0YXRlTG9hZEZpbGVzU3VjY2Vzc1VwZGF0ZXIsXG4gIHNldE1hcENvbnRyb2xTZXR0aW5nc1VwZGF0ZXIgYXMgdWlTdGF0ZVNldE1hcENvbnRyb2xTZXR0aW5nc1VwZGF0ZXIsXG4gIHRvZ2dsZU1hcENvbnRyb2xVcGRhdGVyIGFzIHVpU3RhdGVUb2dnbGVNYXBDb250cm9sVXBkYXRlcixcbiAgdG9nZ2xlTWFwQ29udHJvbFVwZGF0ZXIsXG4gIHRvZ2dsZVNwbGl0TWFwVXBkYXRlciBhcyB1aVN0YXRlVG9nZ2xlU3BsaXRNYXBVcGRhdGVyXG59IGZyb20gJy4vdWktc3RhdGUtdXBkYXRlcnMnO1xuaW1wb3J0IHtcbiAgdXBkYXRlVmlzRGF0YVVwZGF0ZXIgYXMgdmlzU3RhdGVVcGRhdGVWaXNEYXRhVXBkYXRlcixcbiAgc2V0TWFwSW5mb1VwZGF0ZXIsXG4gIGxheWVyVHlwZUNoYW5nZVVwZGF0ZXIsXG4gIHRvZ2dsZVNwbGl0TWFwVXBkYXRlciBhcyB2aXNTdGF0ZVRvZ2dsZVNwbGl0TWFwVXBkYXRlcixcbiAgcHJlcGFyZVN0YXRlRm9yRGF0YXNldFJlcGxhY2Vcbn0gZnJvbSAnLi92aXMtc3RhdGUtdXBkYXRlcnMnO1xuaW1wb3J0IHtcbiAgcmVjZWl2ZU1hcENvbmZpZ1VwZGF0ZXIgYXMgc3RhdGVNYXBDb25maWdVcGRhdGVyLFxuICB0b2dnbGVTcGxpdE1hcFVwZGF0ZXIgYXMgbWFwU3RhdGVUb2dnbGVTcGxpdE1hcFVwZGF0ZXJcbn0gZnJvbSAnLi9tYXAtc3RhdGUtdXBkYXRlcnMnO1xuaW1wb3J0IHtcbiAgbWFwU3R5bGVDaGFuZ2VVcGRhdGVyLFxuICByZWNlaXZlTWFwQ29uZmlnVXBkYXRlciBhcyBzdHlsZU1hcENvbmZpZ1VwZGF0ZXJcbn0gZnJvbSAnLi9tYXAtc3R5bGUtdXBkYXRlcnMnO1xuaW1wb3J0IHtmaWxlc1RvRGF0YVBheWxvYWR9IGZyb20gJ0BrZXBsZXIuZ2wvcHJvY2Vzc29ycyc7XG5pbXBvcnQge3BheWxvYWRfLCBhcHBseV8sIHdpdGhfLCBpZl8sIGNvbXBvc2VfLCBtZXJnZV8sIHBpY2tffSBmcm9tICcuL2NvbXBvc2VyLWhlbHBlcnMnO1xuaW1wb3J0IHtNYXBTdGF0ZSwgVWlTdGF0ZSwgQWRkRGF0YVRvTWFwUGF5bG9hZCwgUGFyc2VkQ29uZmlnfSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcbmltcG9ydCB7TWFwU3R5bGV9IGZyb20gJy4vbWFwLXN0eWxlLXVwZGF0ZXJzJztcbmltcG9ydCB7UHJvdmlkZXJTdGF0ZX0gZnJvbSAnLi9wcm92aWRlci1zdGF0ZS11cGRhdGVycyc7XG5pbXBvcnQge1xuICBsb2FkRmlsZXNTdWNjZXNzVXBkYXRlckFjdGlvbixcbiAgTWFwU3R5bGVDaGFuZ2VVcGRhdGVyQWN0aW9uLFxuICBMYXllclR5cGVDaGFuZ2VVcGRhdGVyQWN0aW9uLFxuICBUb2dnbGVTcGxpdE1hcFVwZGF0ZXJBY3Rpb24sXG4gIFJlcGxhY2VEYXRhSW5NYXBQYXlsb2FkXG59IGZyb20gJ0BrZXBsZXIuZ2wvYWN0aW9ucyc7XG5pbXBvcnQge1Zpc1N0YXRlfSBmcm9tICdAa2VwbGVyLmdsL3NjaGVtYXMnO1xuaW1wb3J0IHtMYXllcn0gZnJvbSAnQGtlcGxlci5nbC9sYXllcnMnO1xuaW1wb3J0IHtpc1BsYWluT2JqZWN0fSBmcm9tICdAa2VwbGVyLmdsL3V0aWxzJztcbmltcG9ydCB7ZmluZE1hcEJvdW5kc30gZnJvbSAnLi9kYXRhLXV0aWxzJztcbmltcG9ydCB7QkFTRV9NQVBfQ09MT1JfTU9ERVMsIE9WRVJMQVlfQkxFTkRJTkdTfSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5cbmV4cG9ydCB0eXBlIEtlcGxlckdsU3RhdGUgPSB7XG4gIHZpc1N0YXRlOiBWaXNTdGF0ZTtcbiAgbWFwU3RhdGU6IE1hcFN0YXRlO1xuICBtYXBTdHlsZTogTWFwU3R5bGU7XG4gIHVpU3RhdGU6IFVpU3RhdGU7XG4gIHByb3ZpZGVyU3RhdGU6IFByb3ZpZGVyU3RhdGU7XG59O1xuXG4vLyBjb21wb3NlIGFjdGlvbiB0byBhcHBseSByZXN1bHQgbXVsdGlwbGUgcmVkdWNlcnMsIHdpdGggdGhlIG91dHB1dCBvZiBvbmVcblxuLyoqXG4gKiBTb21lIGFjdGlvbnMgd2lsbCBhZmZlY3QgdGhlIGVudGlyZSBrZXBsZXIubGcgaW5zdGFuY2Ugc3RhdGUuXG4gKiBUaGUgdXBkYXRlcnMgZm9yIHRoZXNlIGFjdGlvbnMgaXMgZXhwb3J0ZWQgYXMgYGNvbWJpbmVkVXBkYXRlcnNgLiBUaGVzZSB1cGRhdGVyIHRha2UgdGhlIGVudGlyZSBpbnN0YW5jZSBzdGF0ZVxuICogYXMgdGhlIGZpcnN0IGFyZ3VtZW50LiBSZWFkIG1vcmUgYWJvdXQgW1VzaW5nIHVwZGF0ZXJzXSguLi9hZHZhbmNlZC11c2FnZS91c2luZy11cGRhdGVycy5tZClcbiAqIEBwdWJsaWNcbiAqIEBleGFtcGxlXG4gKlxuICogaW1wb3J0IGtlcGxlckdsUmVkdWNlciwge2NvbWJpbmVkVXBkYXRlcnN9IGZyb20gJ2tlcGxlci5nbC9yZWR1Y2Vycyc7XG4gKiAvLyBSb290IFJlZHVjZXJcbiAqIGNvbnN0IHJlZHVjZXJzID0gY29tYmluZVJlZHVjZXJzKHtcbiAqICBrZXBsZXJHbDoga2VwbGVyR2xSZWR1Y2VyLFxuICogIGFwcDogYXBwUmVkdWNlclxuICogfSk7XG4gKlxuICogY29uc3QgY29tcG9zZWRSZWR1Y2VyID0gKHN0YXRlLCBhY3Rpb24pID0+IHtcbiAqICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gKiAgICAvLyBhZGQgZGF0YSB0byBtYXAgYWZ0ZXIgcmVjZWl2aW5nIGRhdGEgZnJvbSByZW1vdGUgc291cmNlc1xuICogICAgY2FzZSAnTE9BRF9SRU1PVEVfUkVTT1VSQ0VfU1VDQ0VTUyc6XG4gKiAgICAgIHJldHVybiB7XG4gKiAgICAgICAgLi4uc3RhdGUsXG4gKiAgICAgICAga2VwbGVyR2w6IHtcbiAqICAgICAgICAgIC4uLnN0YXRlLmtlcGxlckdsLFxuICogICAgICAgICAgLy8gcGFzcyBpbiBrZXBsZXIuZ2wgaW5zdGFuY2Ugc3RhdGUgdG8gY29tYmluZWRVcGRhdGVyc1xuICogICAgICAgICAgbWFwOiAgY29tYmluZWRVcGRhdGVycy5hZGREYXRhVG9NYXBVcGRhdGVyKFxuICogICAgICAgICAgIHN0YXRlLmtlcGxlckdsLm1hcCxcbiAqICAgICAgICAgICB7XG4gKiAgICAgICAgICAgICBwYXlsb2FkOiB7XG4gKiAgICAgICAgICAgICAgIGRhdGFzZXRzOiBhY3Rpb24uZGF0YXNldHMsXG4gKiAgICAgICAgICAgICAgIG9wdGlvbnM6IHtyZWFkT25seTogdHJ1ZX0sXG4gKiAgICAgICAgICAgICAgIGNvbmZpZzogYWN0aW9uLmNvbmZpZ1xuICogICAgICAgICAgICAgIH1cbiAqICAgICAgICAgICAgfVxuICogICAgICAgICAgKVxuICogICAgICAgIH1cbiAqICAgICAgfTtcbiAqICB9XG4gKiAgcmV0dXJuIHJlZHVjZXJzKHN0YXRlLCBhY3Rpb24pO1xuICogfTtcbiAqXG4gKiBleHBvcnQgZGVmYXVsdCBjb21wb3NlZFJlZHVjZXI7XG4gKi9cblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG4vLyBAdHMtaWdub3JlXG5jb25zdCBjb21iaW5lZFVwZGF0ZXJzID0gbnVsbDtcbi8qIGVzbGludC1lbmFibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG5cbmV4cG9ydCBjb25zdCBpc1ZhbGlkQ29uZmlnID0gY29uZmlnID0+XG4gIGlzUGxhaW5PYmplY3QoY29uZmlnKSAmJiBpc1BsYWluT2JqZWN0KGNvbmZpZy5jb25maWcpICYmIGNvbmZpZy52ZXJzaW9uO1xuXG5leHBvcnQgY29uc3QgZGVmYXVsdEFkZERhdGFUb01hcE9wdGlvbnMgPSB7XG4gIGNlbnRlck1hcDogdHJ1ZSxcbiAga2VlcEV4aXN0aW5nQ29uZmlnOiBmYWxzZSxcbiAgYXV0b0NyZWF0ZUxheWVyczogdHJ1ZSxcbiAgYXV0b0NyZWF0ZVRvb2x0aXBzOiB0cnVlXG59O1xuXG4vKipcbiAqIENvbWJpbmUgZGF0YSBhbmQgZnVsbCBjb25maWd1cmF0aW9uIHVwZGF0ZSBpbiBhIHNpbmdsZSBhY3Rpb25cbiAqXG4gKiBAbWVtYmVyb2YgY29tYmluZWRVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGtlcGxlci5nbCBpbnN0YW5jZSBzdGF0ZSwgY29udGFpbmluZyBhbGwgc3VicmVkdWNlciBzdGF0ZVxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvblxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5wYXlsb2FkIGB7ZGF0YXNldHMsIG9wdGlvbnMsIGNvbmZpZ31gXG4gKiBAcGFyYW0gYWN0aW9uLnBheWxvYWQuZGF0YXNldHMgLSAqKipyZXF1aXJlZCoqIGRhdGFzZXRzIGNhbiBiZSBhIGRhdGFzZXQgb3IgYW4gYXJyYXkgb2YgZGF0YXNldHNcbiAqIEVhY2ggZGF0YXNldCBvYmplY3QgbmVlZHMgdG8gaGF2ZSBgaW5mb2AgYW5kIGBkYXRhYCBwcm9wZXJ0eS5cbiAqIEBwYXJhbSBbYWN0aW9uLnBheWxvYWQub3B0aW9uc10gb3B0aW9uIG9iamVjdCBge2NlbnRlck1hcDogdHJ1ZX1gXG4gKiBAcGFyYW0gW2FjdGlvbi5wYXlsb2FkLmNvbmZpZ10gbWFwIGNvbmZpZ1xuICogQHBhcmFtIFthY3Rpb24ucGF5bG9hZC5pbmZvXSBtYXAgaW5mbyBjb250YWlucyB0aXRsZSBhbmQgZGVzY3JpcHRpb25cbiAqIEByZXR1cm5zIG5leHRTdGF0ZVxuICpcbiAqIEB0eXBlZGVmIHtPYmplY3R9IERhdGFzZXRcbiAqIEBwcm9wZXJ0eSBpbmZvIC1pbmZvIG9mIGEgZGF0YXNldFxuICogQHByb3BlcnR5IGluZm8uaWQgLSBpZCBvZiB0aGlzIGRhdGFzZXQuIElmIGNvbmZpZyBpcyBkZWZpbmVkLCBgaWRgIHNob3VsZCBtYXRjaGVzIHRoZSBgZGF0YUlkYCBpbiBjb25maWcuXG4gKiBAcHJvcGVydHkgaW5mby5sYWJlbCAtIEEgZGlzcGxheSBuYW1lIG9mIHRoaXMgZGF0YXNldFxuICogQHByb3BlcnR5IGRhdGEgLSAqKipyZXF1aXJlZCoqIFRoZSBkYXRhIG9iamVjdCwgaW4gYSB0YWJ1bGFyIGZvcm1hdCB3aXRoIDIgcHJvcGVydGllcyBgZmllbGRzYCBhbmQgYHJvd3NgXG4gKiBAcHJvcGVydHkgZGF0YS5maWVsZHMgLSAqKipyZXF1aXJlZCoqIEFycmF5IG9mIGZpZWxkcyxcbiAqIEBwcm9wZXJ0eSBkYXRhLmZpZWxkcy5uYW1lIC0gKioqcmVxdWlyZWQqKiBOYW1lIG9mIHRoZSBmaWVsZCxcbiAqIEBwcm9wZXJ0eSBkYXRhLnJvd3MgLSAqKipyZXF1aXJlZCoqIEFycmF5IG9mIHJvd3MsIGluIGEgdGFidWxhciBmb3JtYXQgd2l0aCBgZmllbGRzYCBhbmQgYHJvd3NgXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgYWRkRGF0YVRvTWFwVXBkYXRlciA9IChcbiAgc3RhdGU6IEtlcGxlckdsU3RhdGUsXG4gIHtwYXlsb2FkfToge3BheWxvYWQ6IEFkZERhdGFUb01hcFBheWxvYWR9XG4pOiBLZXBsZXJHbFN0YXRlID0+IHtcbiAgY29uc3Qge2RhdGFzZXRzLCBjb25maWcsIGluZm99ID0gcGF5bG9hZDtcblxuICBjb25zdCBvcHRpb25zID0ge1xuICAgIC4uLmRlZmF1bHRBZGREYXRhVG9NYXBPcHRpb25zLFxuICAgIC4uLnBheWxvYWQub3B0aW9uc1xuICB9O1xuXG4gIC8vIGNoZWNrIGlmIHByb2dyZXNzaXZlIGxvYWRpbmcgZGF0YXNldCBieSBiYXRjaGVzLCBhbmQgdXBkYXRlIHZpc1N0YXRlIGRpcmVjdGx5XG4gIGNvbnN0IGlzUHJvZ3Jlc3NpdmVMb2FkaW5nID1cbiAgICBBcnJheS5pc0FycmF5KGRhdGFzZXRzKSAmJlxuICAgIGRhdGFzZXRzWzBdPy5pbmZvLmZvcm1hdCA9PT0gJ2Fycm93JyAmJlxuICAgIGRhdGFzZXRzWzBdPy5pbmZvLmlkICYmXG4gICAgZGF0YXNldHNbMF0/LmluZm8uaWQgaW4gc3RhdGUudmlzU3RhdGUuZGF0YXNldHM7XG4gIGlmIChpc1Byb2dyZXNzaXZlTG9hZGluZykge1xuICAgIHJldHVybiBjb21wb3NlXzxLZXBsZXJHbFN0YXRlPihbXG4gICAgICBwaWNrXygndmlzU3RhdGUnKShcbiAgICAgICAgYXBwbHlfPFZpc1N0YXRlLCBhbnk+KHZpc1N0YXRlVXBkYXRlVmlzRGF0YVVwZGF0ZXIsIHtcbiAgICAgICAgICBkYXRhc2V0cyxcbiAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgIGNvbmZpZ1xuICAgICAgICB9KVxuICAgICAgKVxuICAgIF0pKHN0YXRlKTtcbiAgfVxuXG4gIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgbGV0IHBhcnNlZENvbmZpZzogUGFyc2VkQ29uZmlnID0gY29uZmlnO1xuXG4gIGlmIChpc1ZhbGlkQ29uZmlnKGNvbmZpZykpIHtcbiAgICAvLyBpZiBwYXNzZWQgaW4gc2F2ZWQgY29uZmlnXG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgIHBhcnNlZENvbmZpZyA9IHN0YXRlLnZpc1N0YXRlLnNjaGVtYS5wYXJzZVNhdmVkQ29uZmlnKGNvbmZpZyk7XG4gIH1cbiAgY29uc3Qgb2xkTGF5ZXJzID0gc3RhdGUudmlzU3RhdGUubGF5ZXJzO1xuICBjb25zdCBmaWx0ZXJOZXdseUFkZGVkTGF5ZXJzID0gKGxheWVyczogTGF5ZXJbXSkgPT5cbiAgICBsYXllcnMuZmlsdGVyKG5sID0+ICFvbGRMYXllcnMuZmluZChvbCA9PiBvbCA9PT0gbmwpKTtcblxuICAvLyBSZXR1cm5zIHVuZGVmaW5lZCBpZiBub3QgZm91bmQsIHRvIG1ha2UgdHlwZXNjcmlwdCBoYXBweVxuICBjb25zdCBmaW5kTWFwQm91bmRzSWZDZW50ZXJlZCA9IChsYXllcnM6IExheWVyW10pID0+IHtcbiAgICBjb25zdCBib3VuZHMgPSBvcHRpb25zLmNlbnRlck1hcCAmJiBmaW5kTWFwQm91bmRzKGxheWVycyk7XG4gICAgcmV0dXJuIGJvdW5kcyA/IGJvdW5kcyA6IHVuZGVmaW5lZDtcbiAgfTtcblxuICByZXR1cm4gY29tcG9zZV88S2VwbGVyR2xTdGF0ZT4oW1xuICAgIHBpY2tfKCd2aXNTdGF0ZScpKFxuICAgICAgYXBwbHlfPFZpc1N0YXRlLCBhbnk+KHZpc1N0YXRlVXBkYXRlVmlzRGF0YVVwZGF0ZXIsIHtcbiAgICAgICAgZGF0YXNldHMsXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICAgIGNvbmZpZzogcGFyc2VkQ29uZmlnXG4gICAgICB9KVxuICAgICksXG5cbiAgICBpZl8oQm9vbGVhbihpbmZvKSwgcGlja18oJ3Zpc1N0YXRlJykoYXBwbHlfPFZpc1N0YXRlLCBhbnk+KHNldE1hcEluZm9VcGRhdGVyLCB7aW5mb30pKSksXG4gICAgLy8gTm90ZSB0aGF0IGZpdCBib3VuZHMgaGVyZSB3b24ndCBiZSBjYWxsZWQgaW4gY2FzZSBkYXRhc2V0cyBhcmUgY3JlYXRlZCBpbiBUYXNrcy5cbiAgICAvLyBBIHNlcGFyYXRlIFRhc2sgdG8gdXBkYXRlIGJvdW5kcyBpcyBjcmVhdGVkIG9uY2UgdGhlIGRhdGFzZXRzIGFyZSByZWFkeS5cbiAgICB3aXRoXygoe3Zpc1N0YXRlfSkgPT5cbiAgICAgIHBpY2tfKCdtYXBTdGF0ZScpKFxuICAgICAgICBhcHBseV8oXG4gICAgICAgICAgc3RhdGVNYXBDb25maWdVcGRhdGVyLFxuICAgICAgICAgIHBheWxvYWRfKHtcbiAgICAgICAgICAgIGNvbmZpZzogcGFyc2VkQ29uZmlnLFxuICAgICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgICAgIGJvdW5kczogZmluZE1hcEJvdW5kc0lmQ2VudGVyZWQoZmlsdGVyTmV3bHlBZGRlZExheWVycyh2aXNTdGF0ZS5sYXllcnMpKVxuICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICAgIClcbiAgICApLFxuICAgIHBpY2tfKCdtYXBTdHlsZScpKGFwcGx5XyhzdHlsZU1hcENvbmZpZ1VwZGF0ZXIsIHBheWxvYWRfKHtjb25maWc6IHBhcnNlZENvbmZpZywgb3B0aW9uc30pKSksXG4gICAgcGlja18oJ3VpU3RhdGUnKShhcHBseV8odWlTdGF0ZUxvYWRGaWxlc1N1Y2Nlc3NVcGRhdGVyLCBwYXlsb2FkXyhudWxsKSkpLFxuXG4gICAgaWZfKFxuICAgICAgQm9vbGVhbihwYXJzZWRDb25maWc/LnVpU3RhdGU/Lm1hcENvbnRyb2xzPy5tYXBMZWdlbmQ/LmFjdGl2ZSksXG4gICAgICBwaWNrXygndWlTdGF0ZScpKFxuICAgICAgICBhcHBseV8odWlTdGF0ZVRvZ2dsZU1hcENvbnRyb2xVcGRhdGVyLCBwYXlsb2FkXyh7cGFuZWxJZDogJ21hcExlZ2VuZCcsIGluZGV4OiAwfSkpXG4gICAgICApXG4gICAgKSxcblxuICAgIGlmXyhcbiAgICAgIEJvb2xlYW4ocGFyc2VkQ29uZmlnPy51aVN0YXRlPy5tYXBDb250cm9scz8ubWFwTGVnZW5kPy5zZXR0aW5ncyksXG4gICAgICBwaWNrXygndWlTdGF0ZScpKFxuICAgICAgICBhcHBseV8oXG4gICAgICAgICAgdWlTdGF0ZVNldE1hcENvbnRyb2xTZXR0aW5nc1VwZGF0ZXIsXG4gICAgICAgICAgcGF5bG9hZF8oe1xuICAgICAgICAgICAgcGFuZWxJZDogJ21hcExlZ2VuZCcsXG4gICAgICAgICAgICBzZXR0aW5nczogcGFyc2VkQ29uZmlnPy51aVN0YXRlPy5tYXBDb250cm9scz8ubWFwTGVnZW5kPy5zZXR0aW5ncyA/PyB7fVxuICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICAgIClcbiAgICApLFxuICAgIHBpY2tfKCd1aVN0YXRlJykoYXBwbHlfKHRvZ2dsZU1vZGFsVXBkYXRlciwgcGF5bG9hZF8obnVsbCkpKSxcbiAgICBwaWNrXygndWlTdGF0ZScpKFxuICAgICAgbWVyZ2VfKFxuICAgICAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob3B0aW9ucywgJ3JlYWRPbmx5JylcbiAgICAgICAgICA/IHtyZWFkT25seTogb3B0aW9ucy5yZWFkT25seX1cbiAgICAgICAgICA6IHt9XG4gICAgICApXG4gICAgKVxuICBdKShzdGF0ZSk7XG59O1xuXG5leHBvcnQgY29uc3QgbG9hZEZpbGVzU3VjY2Vzc1VwZGF0ZXIgPSAoXG4gIHN0YXRlOiBLZXBsZXJHbFN0YXRlLFxuICBhY3Rpb246IGxvYWRGaWxlc1N1Y2Nlc3NVcGRhdGVyQWN0aW9uXG4pOiBLZXBsZXJHbFN0YXRlID0+IHtcbiAgLy8gc3RpbGwgbW9yZSB0byBsb2FkXG4gIGNvbnN0IHBheWxvYWRzID0gZmlsZXNUb0RhdGFQYXlsb2FkKGFjdGlvbi5yZXN1bHQpO1xuICBjb25zdCBuZXh0U3RhdGUgPSBjb21wb3NlXyhbXG4gICAgcGlja18oJ3Zpc1N0YXRlJykoXG4gICAgICBtZXJnZV8oe1xuICAgICAgICBmaWxlTG9hZGluZzogZmFsc2UsXG4gICAgICAgIGZpbGVMb2FkaW5nUHJvZ3Jlc3M6IHt9XG4gICAgICB9KVxuICAgIClcbiAgXSkoc3RhdGUpO1xuICAvLyBtYWtlIG11bHRpcGxlIGFkZCBkYXRhIHRvIG1hcCBjYWxsc1xuICBjb25zdCBzdGF0ZVdpdGhEYXRhID0gY29tcG9zZV8ocGF5bG9hZHMubWFwKHAgPT4gYXBwbHlfKGFkZERhdGFUb01hcFVwZGF0ZXIsIHBheWxvYWRfKHApKSkpKFxuICAgIG5leHRTdGF0ZVxuICApO1xuICByZXR1cm4gc3RhdGVXaXRoRGF0YSBhcyBLZXBsZXJHbFN0YXRlO1xufTtcblxuZXhwb3J0IGNvbnN0IGFkZERhdGFUb01hcENvbXBvc2VkID0gYWRkRGF0YVRvTWFwVXBkYXRlcjtcblxuLyoqXG4gKiBIZWxwZXIgd2hpY2ggdXBkYXRlcyBtYXAgb3ZlcmxheSBibGVuZGluZyBtb2RlIGluIHZpc1N0YXRlLFxuICogYnV0IG9ubHkgaWYgaXQncyBub3QgY3VycmVudGx5IGluIHRoZSBgbm9ybWFsYCBtb2RlLlxuICovXG5jb25zdCB1cGRhdGVPdmVybGF5QmxlbmRpbmcgPSBvdmVybGF5QmxlbmRpbmcgPT4gdmlzU3RhdGUgPT4ge1xuICBpZiAodmlzU3RhdGUub3ZlcmxheUJsZW5kaW5nICE9PSBPVkVSTEFZX0JMRU5ESU5HUy5ub3JtYWwudmFsdWUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4udmlzU3RhdGUsXG4gICAgICBvdmVybGF5QmxlbmRpbmdcbiAgICB9O1xuICB9XG4gIHJldHVybiB2aXNTdGF0ZTtcbn07XG5cbi8qKlxuICogSGVscGVyIHdoaWNoIHVwZGF0ZXMgYGRhcmtCYXNlTWFwRW5hYmxlZGAgaW4gYWxsIHRoZSBsYXllcnMgaW4gdmlzU3RhdGUgd2hpY2hcbiAqIGhhdmUgdGhpcyBjb25maWcgc2V0dGluZyAob3IgaW4gb25lIHNwZWNpZmljIGxheWVyIGlmIHRoZSBgbGF5ZXJJZGAgcGFyYW0gaXMgcHJvdmlkZWQpLlxuICovXG5jb25zdCB1cGRhdGVEYXJrQmFzZU1hcExheWVycyA9XG4gIChkYXJrQmFzZU1hcEVuYWJsZWQ6IGJvb2xlYW4sIGxheWVySWQ6IHN0cmluZyB8IG51bGwgPSBudWxsKSA9PlxuICB2aXNTdGF0ZSA9PiAoe1xuICAgIC4uLnZpc1N0YXRlLFxuICAgIGxheWVyczogdmlzU3RhdGUubGF5ZXJzLm1hcChsYXllciA9PiB7XG4gICAgICBpZiAoIWxheWVySWQgfHwgbGF5ZXIuaWQgPT09IGxheWVySWQpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChsYXllci52aXNDb25maWdTZXR0aW5ncywgJ2RhcmtCYXNlTWFwRW5hYmxlZCcpKSB7XG4gICAgICAgICAgY29uc3Qge3Zpc0NvbmZpZ30gPSBsYXllci5jb25maWc7XG4gICAgICAgICAgcmV0dXJuIGxheWVyLnVwZGF0ZUxheWVyQ29uZmlnKHtcbiAgICAgICAgICAgIHZpc0NvbmZpZzogey4uLnZpc0NvbmZpZywgZGFya0Jhc2VNYXBFbmFibGVkfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfSlcbiAgfSk7XG5cbi8qKlxuICogVXBkYXRlciB0aGF0IGNoYW5nZXMgdGhlIG1hcCBzdHlsZSBieSBjYWxsaW5nIG1hcFN0eWxlQ2hhbmdlVXBkYXRlciBvbiB2aXNTdGF0ZS5cbiAqIEluIGFkZGl0aW9uIHRvIHRoYXQsIGl0IGRvZXMgdGhlIGZvbGxvd2luZzpcbiAqXG4gKiAgIDEuIFVwZGF0ZSBtYXAgb3ZlcmxheSBibGVuZGluZyBtb2RlIGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgY29sb3JNb2RlIG9mIHRoZVxuICogICAgICBiYXNlIG1hcCwgYnV0IG9ubHkgaWYgaXQncyBub3QgaW4gdGhlIGBub3JtYWxgIG1vZGUuXG4gKlxuICogICAyLiBVcGRhdGUgYWxsIHRoZSBsYXllcnMgd2hpY2ggaGF2ZSB0aGUgYGRhcmtCYXNlTWFwRW5hYmxlZGAgY29uZmlnIHNldHRpbmdcbiAqICAgICAgYWRqdXN0aW5nIGl0IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgY29sb3JNb2RlIG9mIHRoZSBiYXNlIG1hcC5cbiAqXG4gKi9cbmV4cG9ydCBjb25zdCBjb21iaW5lZE1hcFN0eWxlQ2hhbmdlVXBkYXRlciA9IChcbiAgc3RhdGU6IEtlcGxlckdsU3RhdGUsXG4gIGFjdGlvbjogTWFwU3R5bGVDaGFuZ2VVcGRhdGVyQWN0aW9uXG4pOiBLZXBsZXJHbFN0YXRlID0+IHtcbiAgY29uc3Qge3BheWxvYWR9ID0gYWN0aW9uO1xuICBjb25zdCB7bWFwU3R5bGV9ID0gc3RhdGU7XG4gIGNvbnN0IGdldENvbG9yTW9kZSA9IGtleSA9PiBtYXBTdHlsZS5tYXBTdHlsZXNba2V5XT8uY29sb3JNb2RlO1xuICBjb25zdCBwcmV2Q29sb3JNb2RlID0gZ2V0Q29sb3JNb2RlKG1hcFN0eWxlLnN0eWxlVHlwZSk7XG4gIGNvbnN0IG5leHRDb2xvck1vZGUgPSBnZXRDb2xvck1vZGUocGF5bG9hZC5zdHlsZVR5cGUpO1xuICBsZXQge3Zpc1N0YXRlfSA9IHN0YXRlO1xuICBpZiAobmV4dENvbG9yTW9kZSAhPT0gcHJldkNvbG9yTW9kZSkge1xuICAgIHN3aXRjaCAobmV4dENvbG9yTW9kZSkge1xuICAgICAgY2FzZSBCQVNFX01BUF9DT0xPUl9NT0RFUy5EQVJLOlxuICAgICAgICB2aXNTdGF0ZSA9IGNvbXBvc2VfKFtcbiAgICAgICAgICB1cGRhdGVPdmVybGF5QmxlbmRpbmcoT1ZFUkxBWV9CTEVORElOR1Muc2NyZWVuLnZhbHVlKSxcbiAgICAgICAgICB1cGRhdGVEYXJrQmFzZU1hcExheWVycyh0cnVlKVxuICAgICAgICBdKSh2aXNTdGF0ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBCQVNFX01BUF9DT0xPUl9NT0RFUy5MSUdIVDpcbiAgICAgICAgdmlzU3RhdGUgPSBjb21wb3NlXyhbXG4gICAgICAgICAgdXBkYXRlT3ZlcmxheUJsZW5kaW5nKE9WRVJMQVlfQkxFTkRJTkdTLmRhcmtlbi52YWx1ZSksXG4gICAgICAgICAgdXBkYXRlRGFya0Jhc2VNYXBMYXllcnMoZmFsc2UpXG4gICAgICAgIF0pKHZpc1N0YXRlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgLy8gZG8gbm90aGluZ1xuICAgIH1cbiAgfVxuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIHZpc1N0YXRlLFxuICAgIG1hcFN0eWxlOiBtYXBTdHlsZUNoYW5nZVVwZGF0ZXIobWFwU3R5bGUsIHtwYXlsb2FkOiB7Li4ucGF5bG9hZH19KVxuICB9O1xufTtcblxuLyoqXG4gKiBVcGRhdGVyIHRoYXQgY2hhbmdlcyB0aGUgbGF5ZXIgdHlwZSBieSBjYWxsaW5nIGBsYXllclR5cGVDaGFuZ2VVcGRhdGVyYCBvbiB2aXNTdGF0ZS5cbiAqIEluIGFkZGl0aW9uIHRvIHRoYXQsIGlmIHRoZSBuZXcgbGF5ZXIgdHlwZSBoYXMgdGhlIGBkYXJrQmFzZU1hcEVuYWJsZWRgIGNvbmZpZ1xuICogc2V0dGluZywgd2UgYWRqdXN0IGl0IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgY29sb3JNb2RlIG9mIHRoZSBiYXNlIG1hcC5zXG4gKi9cbmV4cG9ydCBjb25zdCBjb21iaW5lZExheWVyVHlwZUNoYW5nZVVwZGF0ZXIgPSAoXG4gIHN0YXRlOiBLZXBsZXJHbFN0YXRlLFxuICBhY3Rpb246IExheWVyVHlwZUNoYW5nZVVwZGF0ZXJBY3Rpb25cbik6IEtlcGxlckdsU3RhdGUgPT4ge1xuICBsZXQge3Zpc1N0YXRlfSA9IHN0YXRlO1xuICBjb25zdCBvbGRMYXllckluZGV4ID0gdmlzU3RhdGUubGF5ZXJzLmZpbmRJbmRleChsYXllciA9PiBsYXllciA9PT0gYWN0aW9uLm9sZExheWVyKTtcbiAgdmlzU3RhdGUgPSBsYXllclR5cGVDaGFuZ2VVcGRhdGVyKHZpc1N0YXRlLCBhY3Rpb24pO1xuICBjb25zdCBuZXdMYXllciA9IHZpc1N0YXRlLmxheWVyc1tvbGRMYXllckluZGV4XTtcbiAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChuZXdMYXllcj8udmlzQ29uZmlnU2V0dGluZ3MsICdkYXJrQmFzZU1hcEVuYWJsZWQnKSkge1xuICAgIGNvbnN0IHttYXBTdHlsZX0gPSBzdGF0ZTtcbiAgICBjb25zdCB7Y29sb3JNb2RlfSA9IG1hcFN0eWxlLm1hcFN0eWxlc1ttYXBTdHlsZS5zdHlsZVR5cGVdO1xuICAgIGNvbnN0IHtkYXJrQmFzZU1hcEVuYWJsZWR9ID0gbmV3TGF5ZXIuY29uZmlnLnZpc0NvbmZpZztcbiAgICBzd2l0Y2ggKGNvbG9yTW9kZSkge1xuICAgICAgY2FzZSBCQVNFX01BUF9DT0xPUl9NT0RFUy5EQVJLOlxuICAgICAgICBpZiAoIWRhcmtCYXNlTWFwRW5hYmxlZCkge1xuICAgICAgICAgIHZpc1N0YXRlID0gdXBkYXRlRGFya0Jhc2VNYXBMYXllcnModHJ1ZSwgbmV3TGF5ZXIuaWQpKHZpc1N0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQkFTRV9NQVBfQ09MT1JfTU9ERVMuTElHSFQ6XG4gICAgICAgIGlmIChkYXJrQmFzZU1hcEVuYWJsZWQpIHtcbiAgICAgICAgICB2aXNTdGF0ZSA9IHVwZGF0ZURhcmtCYXNlTWFwTGF5ZXJzKGZhbHNlLCBuZXdMYXllci5pZCkodmlzU3RhdGUpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICB2aXNTdGF0ZVxuICB9O1xufTtcblxuLyoqXG4gKiBNYWtlIG1hcExlZ2VuZCBhY3RpdmUgd2hlbiB0b2dnbGVTcGxpdE1hcCBhY3Rpb24gaXMgY2FsbGVkXG4gKi9cbmV4cG9ydCBjb25zdCB0b2dnbGVTcGxpdE1hcFVwZGF0ZXIgPSAoXG4gIHN0YXRlOiBLZXBsZXJHbFN0YXRlLFxuICBhY3Rpb246IFRvZ2dsZVNwbGl0TWFwVXBkYXRlckFjdGlvblxuKTogS2VwbGVyR2xTdGF0ZSA9PiB7XG4gIGNvbnN0IG5ld1N0YXRlID0ge1xuICAgIC4uLnN0YXRlLFxuICAgIHZpc1N0YXRlOiB2aXNTdGF0ZVRvZ2dsZVNwbGl0TWFwVXBkYXRlcihzdGF0ZS52aXNTdGF0ZSwgYWN0aW9uKSxcbiAgICB1aVN0YXRlOiB1aVN0YXRlVG9nZ2xlU3BsaXRNYXBVcGRhdGVyKHN0YXRlLnVpU3RhdGUpLFxuICAgIG1hcFN0YXRlOiBtYXBTdGF0ZVRvZ2dsZVNwbGl0TWFwVXBkYXRlcihzdGF0ZS5tYXBTdGF0ZSlcbiAgfTtcblxuICBjb25zdCBpc1NwbGl0ID0gbmV3U3RhdGUudmlzU3RhdGUuc3BsaXRNYXBzLmxlbmd0aCAhPT0gMDtcbiAgY29uc3QgaXNMZWdlbmRBY3RpdmUgPSBuZXdTdGF0ZS51aVN0YXRlLm1hcENvbnRyb2xzPy5tYXBMZWdlbmQ/LmFjdGl2ZTtcbiAgaWYgKGlzU3BsaXQgJiYgIWlzTGVnZW5kQWN0aXZlKSB7XG4gICAgbmV3U3RhdGUudWlTdGF0ZSA9IHRvZ2dsZU1hcENvbnRyb2xVcGRhdGVyKG5ld1N0YXRlLnVpU3RhdGUsIHtcbiAgICAgIHBheWxvYWQ6IHtwYW5lbElkOiAnbWFwTGVnZW5kJywgaW5kZXg6IGFjdGlvbi5wYXlsb2FkfVxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIG5ld1N0YXRlO1xufTtcblxuY29uc3QgZGVmYXVsdFJlcGxhY2VEYXRhVG9NYXBPcHRpb25zID0ge1xuICBrZWVwRXhpc3RpbmdDb25maWc6IHRydWUsXG4gIGNlbnRlck1hcDogdHJ1ZSxcbiAgYXV0b0NyZWF0ZUxheWVyczogZmFsc2Vcbn07XG5cbi8qKlxuICogVXBkYXRlciByZXBsYWNlIGEgZGF0YXNldCBpbiBzdGF0ZVxuICovXG5leHBvcnQgY29uc3QgcmVwbGFjZURhdGFJbk1hcFVwZGF0ZXIgPSAoXG4gIHN0YXRlOiBLZXBsZXJHbFN0YXRlLFxuICB7cGF5bG9hZH06IHtwYXlsb2FkOiBSZXBsYWNlRGF0YUluTWFwUGF5bG9hZH1cbik6IEtlcGxlckdsU3RhdGUgPT4ge1xuICBjb25zdCB7ZGF0YXNldFRvUmVwbGFjZUlkLCBkYXRhc2V0VG9Vc2UsIG9wdGlvbnMgPSB7fX0gPSBwYXlsb2FkO1xuICBjb25zdCBhZGREYXRhVG9NYXBPcHRpb25zID0gey4uLmRlZmF1bHRSZXBsYWNlRGF0YVRvTWFwT3B0aW9ucywgLi4ub3B0aW9uc307XG5cbiAgLy8gY2hlY2sgaWYgZGF0YXNldCBpcyB0aGVyZVxuICBpZiAoIXN0YXRlLnZpc1N0YXRlLmRhdGFzZXRzW2RhdGFzZXRUb1JlcGxhY2VJZF0pIHtcbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cbiAgLy8gZGF0YXNldFRvVXNlIGlzIFByb3RvRGF0YXNldFxuICBjb25zdCBkYXRhSWRUb1VzZSA9IGRhdGFzZXRUb1VzZS5pbmZvLmlkO1xuICBpZiAoIWRhdGFJZFRvVXNlKSB7XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG4gIC8vIHJlbW92ZSBkYXRhc2V0IGFuZCBwdXQgZGVwZW5kZW5jaWVzIGluIHRvQmVNZXJnZWRcbiAgY29uc3QgcHJlcGFyZWRTdGF0ZSA9IHtcbiAgICAuLi5zdGF0ZSxcbiAgICB2aXNTdGF0ZTogcHJlcGFyZVN0YXRlRm9yRGF0YXNldFJlcGxhY2Uoc3RhdGUudmlzU3RhdGUsIGRhdGFzZXRUb1JlcGxhY2VJZCwgZGF0YUlkVG9Vc2UpXG4gIH07XG5cbiAgY29uc3QgbmV4dFN0YXRlID0gYWRkRGF0YVRvTWFwVXBkYXRlcihcbiAgICBwcmVwYXJlZFN0YXRlLFxuICAgIHBheWxvYWRfKHtcbiAgICAgIGRhdGFzZXRzOiBkYXRhc2V0VG9Vc2UsXG4gICAgICAvLyBzaG91bGQgem9vbSB0byBuZXcgZGF0YXNldFxuICAgICAgb3B0aW9uczogYWRkRGF0YVRvTWFwT3B0aW9uc1xuICAgIH0pXG4gICk7XG5cbiAgcmV0dXJuIG5leHRTdGF0ZTtcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBR0EsSUFBQUEsZ0JBQUEsR0FBQUMsT0FBQTtBQVFBLElBQUFDLGlCQUFBLEdBQUFELE9BQUE7QUFPQSxJQUFBRSxpQkFBQSxHQUFBRixPQUFBO0FBSUEsSUFBQUcsaUJBQUEsR0FBQUgsT0FBQTtBQUlBLElBQUFJLFdBQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLGdCQUFBLEdBQUFMLE9BQUE7QUFhQSxJQUFBTSxNQUFBLEdBQUFOLE9BQUE7QUFDQSxJQUFBTyxVQUFBLEdBQUFQLE9BQUE7QUFDQSxJQUFBUSxVQUFBLEdBQUFSLE9BQUE7QUFBNkUsU0FBQVMsUUFBQUMsQ0FBQSxFQUFBQyxDQUFBLFFBQUFDLENBQUEsR0FBQUMsTUFBQSxDQUFBQyxJQUFBLENBQUFKLENBQUEsT0FBQUcsTUFBQSxDQUFBRSxxQkFBQSxRQUFBQyxDQUFBLEdBQUFILE1BQUEsQ0FBQUUscUJBQUEsQ0FBQUwsQ0FBQSxHQUFBQyxDQUFBLEtBQUFLLENBQUEsR0FBQUEsQ0FBQSxDQUFBQyxNQUFBLFdBQUFOLENBQUEsV0FBQUUsTUFBQSxDQUFBSyx3QkFBQSxDQUFBUixDQUFBLEVBQUFDLENBQUEsRUFBQVEsVUFBQSxPQUFBUCxDQUFBLENBQUFRLElBQUEsQ0FBQUMsS0FBQSxDQUFBVCxD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