kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
366 lines (351 loc) • 56.7 kB
JavaScript
"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 _src = require("/Users/ihordykhta/Desktop/unfolded/kepler.gl/src/processors/src");
var _composerHelpers = require("./composer-helpers");
var _src2 = require("/Users/ihordykhta/Desktop/unfolded/kepler.gl/src/utils/src");
var _dataUtils = require("./data-utils");
var _src3 = require("/Users/ihordykhta/Desktop/unfolded/kepler.gl/src/constants/src");
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, _src2.isPlainObject)(config) && (0, _src2.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')(
// this part can be async
(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, _src.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 !== _src3.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 _src3.BASE_MAP_COLOR_MODES.DARK:
visState = (0, _composerHelpers.compose_)([updateOverlayBlending(_src3.OVERLAY_BLENDINGS.screen.value), updateDarkBaseMapLayers(true)])(visState);
break;
case _src3.BASE_MAP_COLOR_MODES.LIGHT:
visState = (0, _composerHelpers.compose_)([updateOverlayBlending(_src3.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 _src3.BASE_MAP_COLOR_MODES.DARK:
if (!darkBaseMapEnabled) {
visState = updateDarkBaseMapLayers(true, newLayer.id)(visState);
}
break;
case _src3.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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfdWlTdGF0ZVVwZGF0ZXJzIiwicmVxdWlyZSIsIl92aXNTdGF0ZVVwZGF0ZXJzIiwiX21hcFN0YXRlVXBkYXRlcnMiLCJfbWFwU3R5bGVVcGRhdGVycyIsIl9zcmMiLCJfY29tcG9zZXJIZWxwZXJzIiwiX3NyYzIiLCJfZGF0YVV0aWxzIiwiX3NyYzMiLCJvd25LZXlzIiwiZSIsInIiLCJ0IiwiT2JqZWN0Iiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJkZWZpbmVQcm9wZXJ0eSIsImNvbWJpbmVkVXBkYXRlcnMiLCJpc1ZhbGlkQ29uZmlnIiwiZXhwb3J0cyIsImNvbmZpZyIsImlzUGxhaW5PYmplY3QiLCJ2ZXJzaW9uIiwiZGVmYXVsdEFkZERhdGFUb01hcE9wdGlvbnMiLCJjZW50ZXJNYXAiLCJrZWVwRXhpc3RpbmdDb25maWciLCJhdXRvQ3JlYXRlTGF5ZXJzIiwiYXV0b0NyZWF0ZVRvb2x0aXBzIiwiYWRkRGF0YVRvTWFwVXBkYXRlciIsInN0YXRlIiwiX3JlZiIsIl9kYXRhc2V0cyQiLCJfZGF0YXNldHMkMiIsIl9kYXRhc2V0cyQzIiwiX3BhcnNlZENvbmZpZyIsIl9wYXJzZWRDb25maWcyIiwiX3BhcnNlZENvbmZpZyR1aVN0YXRlIiwiX3BhcnNlZENvbmZpZzMiLCJwYXlsb2FkIiwiZGF0YXNldHMiLCJpbmZvIiwib3B0aW9ucyIsImlzUHJvZ3Jlc3NpdmVMb2FkaW5nIiwiQXJyYXkiLCJpc0FycmF5IiwiZm9ybWF0IiwiaWQiLCJ2aXNTdGF0ZSIsImNvbXBvc2VfIiwicGlja18iLCJhcHBseV8iLCJ2aXNTdGF0ZVVwZGF0ZVZpc0RhdGFVcGRhdGVyIiwicGFyc2VkQ29uZmlnIiwic2NoZW1hIiwicGFyc2VTYXZlZENvbmZpZyIsIm9sZExheWVycyIsImxheWVycyIsImZpbHRlck5ld2x5QWRkZWRMYXllcnMiLCJubCIsImZpbmQiLCJvbCIsImZpbmRNYXBCb3VuZHNJZkNlbnRlcmVkIiwiYm91bmRzIiwiZmluZE1hcEJvdW5kcyIsInVuZGVmaW5lZCIsImlmXyIsIkJvb2xlYW4iLCJzZXRNYXBJbmZvVXBkYXRlciIsIndpdGhfIiwiX3JlZjIiLCJzdGF0ZU1hcENvbmZpZ1VwZGF0ZXIiLCJwYXlsb2FkXyIsInN0eWxlTWFwQ29uZmlnVXBkYXRlciIsInVpU3RhdGVMb2FkRmlsZXNTdWNjZXNzVXBkYXRlciIsInVpU3RhdGUiLCJtYXBDb250cm9scyIsIm1hcExlZ2VuZCIsImFjdGl2ZSIsInVpU3RhdGVUb2dnbGVNYXBDb250cm9sVXBkYXRlciIsInBhbmVsSWQiLCJpbmRleCIsInNldHRpbmdzIiwidWlTdGF0ZVNldE1hcENvbnRyb2xTZXR0aW5nc1VwZGF0ZXIiLCJ0b2dnbGVNb2RhbFVwZGF0ZXIiLCJtZXJnZV8iLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJyZWFkT25seSIsImxvYWRGaWxlc1N1Y2Nlc3NVcGRhdGVyIiwiYWN0aW9uIiwicGF5bG9hZHMiLCJmaWxlc1RvRGF0YVBheWxvYWQiLCJyZXN1bHQiLCJuZXh0U3RhdGUiLCJmaWxlTG9hZGluZyIsImZpbGVMb2FkaW5nUHJvZ3Jlc3MiLCJzdGF0ZVdpdGhEYXRhIiwibWFwIiwicCIsImFkZERhdGFUb01hcENvbXBvc2VkIiwidXBkYXRlT3ZlcmxheUJsZW5kaW5nIiwib3ZlcmxheUJsZW5kaW5nIiwiT1ZFUkxBWV9CTEVORElOR1MiLCJub3JtYWwiLCJ2YWx1ZSIsInVwZGF0ZURhcmtCYXNlTWFwTGF5ZXJzIiwiZGFya0Jhc2VNYXBFbmFibGVkIiwibGF5ZXJJZCIsImxheWVyIiwidmlzQ29uZmlnU2V0dGluZ3MiLCJ2aXNDb25maWciLCJ1cGRhdGVMYXllckNvbmZpZyIsImNvbWJpbmVkTWFwU3R5bGVDaGFuZ2VVcGRhdGVyIiwibWFwU3R5bGUiLCJnZXRDb2xvck1vZGUiLCJrZXkiLCJfbWFwU3R5bGUkbWFwU3R5bGVzJGsiLCJtYXBTdHlsZXMiLCJjb2xvck1vZGUiLCJwcmV2Q29sb3JNb2RlIiwic3R5bGVUeXBlIiwibmV4dENvbG9yTW9kZSIsIkJBU0VfTUFQX0NPTE9SX01PREVTIiwiREFSSyIsInNjcmVlbiIsIkxJR0hUIiwiZGFya2VuIiwibWFwU3R5bGVDaGFuZ2VVcGRhdGVyIiwiY29tYmluZWRMYXllclR5cGVDaGFuZ2VVcGRhdGVyIiwib2xkTGF5ZXJJbmRleCIsImZpbmRJbmRleCIsIm9sZExheWVyIiwibGF5ZXJUeXBlQ2hhbmdlVXBkYXRlciIsIm5ld0xheWVyIiwidG9nZ2xlU3BsaXRNYXBVcGRhdGVyIiwiX25ld1N0YXRlJHVpU3RhdGUkbWFwIiwibmV3U3RhdGUiLCJ2aXNTdGF0ZVRvZ2dsZVNwbGl0TWFwVXBkYXRlciIsInVpU3RhdGVUb2dnbGVTcGxpdE1hcFVwZGF0ZXIiLCJtYXBTdGF0ZSIsIm1hcFN0YXRlVG9nZ2xlU3BsaXRNYXBVcGRhdGVyIiwiaXNTcGxpdCIsInNwbGl0TWFwcyIsImlzTGVnZW5kQWN0aXZlIiwidG9nZ2xlTWFwQ29udHJvbFVwZGF0ZXIiLCJkZWZhdWx0UmVwbGFjZURhdGFUb01hcE9wdGlvbnMiLCJyZXBsYWNlRGF0YUluTWFwVXBkYXRlciIsIl9yZWYzIiwiZGF0YXNldFRvUmVwbGFjZUlkIiwiZGF0YXNldFRvVXNlIiwiX3BheWxvYWQkb3B0aW9ucyIsImFkZERhdGFUb01hcE9wdGlvbnMiLCJkYXRhSWRUb1VzZSIsInByZXBhcmVkU3RhdGUiLCJwcmVwYXJlU3RhdGVGb3JEYXRhc2V0UmVwbGFjZSJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZWR1Y2Vycy9zcmMvY29tYmluZWQtdXBkYXRlcnMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0IHtcbiAgdG9nZ2xlTW9kYWxVcGRhdGVyLFxuICBsb2FkRmlsZXNTdWNjZXNzVXBkYXRlciBhcyB1aVN0YXRlTG9hZEZpbGVzU3VjY2Vzc1VwZGF0ZXIsXG4gIHNldE1hcENvbnRyb2xTZXR0aW5nc1VwZGF0ZXIgYXMgdWlTdGF0ZVNldE1hcENvbnRyb2xTZXR0aW5nc1VwZGF0ZXIsXG4gIHRvZ2dsZU1hcENvbnRyb2xVcGRhdGVyIGFzIHVpU3RhdGVUb2dnbGVNYXBDb250cm9sVXBkYXRlcixcbiAgdG9nZ2xlTWFwQ29udHJvbFVwZGF0ZXIsXG4gIHRvZ2dsZVNwbGl0TWFwVXBkYXRlciBhcyB1aVN0YXRlVG9nZ2xlU3BsaXRNYXBVcGRhdGVyXG59IGZyb20gJy4vdWktc3RhdGUtdXBkYXRlcnMnO1xuaW1wb3J0IHtcbiAgdXBkYXRlVmlzRGF0YVVwZGF0ZXIgYXMgdmlzU3RhdGVVcGRhdGVWaXNEYXRhVXBkYXRlcixcbiAgc2V0TWFwSW5mb1VwZGF0ZXIsXG4gIGxheWVyVHlwZUNoYW5nZVVwZGF0ZXIsXG4gIHRvZ2dsZVNwbGl0TWFwVXBkYXRlciBhcyB2aXNTdGF0ZVRvZ2dsZVNwbGl0TWFwVXBkYXRlcixcbiAgcHJlcGFyZVN0YXRlRm9yRGF0YXNldFJlcGxhY2Vcbn0gZnJvbSAnLi92aXMtc3RhdGUtdXBkYXRlcnMnO1xuaW1wb3J0IHtcbiAgcmVjZWl2ZU1hcENvbmZpZ1VwZGF0ZXIgYXMgc3RhdGVNYXBDb25maWdVcGRhdGVyLFxuICB0b2dnbGVTcGxpdE1hcFVwZGF0ZXIgYXMgbWFwU3RhdGVUb2dnbGVTcGxpdE1hcFVwZGF0ZXJcbn0gZnJvbSAnLi9tYXAtc3RhdGUtdXBkYXRlcnMnO1xuaW1wb3J0IHtcbiAgbWFwU3R5bGVDaGFuZ2VVcGRhdGVyLFxuICByZWNlaXZlTWFwQ29uZmlnVXBkYXRlciBhcyBzdHlsZU1hcENvbmZpZ1VwZGF0ZXJcbn0gZnJvbSAnLi9tYXAtc3R5bGUtdXBkYXRlcnMnO1xuaW1wb3J0IHtmaWxlc1RvRGF0YVBheWxvYWR9IGZyb20gJ0BrZXBsZXIuZ2wvcHJvY2Vzc29ycyc7XG5pbXBvcnQge3BheWxvYWRfLCBhcHBseV8sIHdpdGhfLCBpZl8sIGNvbXBvc2VfLCBtZXJnZV8sIHBpY2tffSBmcm9tICcuL2NvbXBvc2VyLWhlbHBlcnMnO1xuaW1wb3J0IHtNYXBTdGF0ZSwgVWlTdGF0ZSwgQWRkRGF0YVRvTWFwUGF5bG9hZCwgUGFyc2VkQ29uZmlnfSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcbmltcG9ydCB7TWFwU3R5bGV9IGZyb20gJy4vbWFwLXN0eWxlLXVwZGF0ZXJzJztcbmltcG9ydCB7UHJvdmlkZXJTdGF0ZX0gZnJvbSAnLi9wcm92aWRlci1zdGF0ZS11cGRhdGVycyc7XG5pbXBvcnQge1xuICBsb2FkRmlsZXNTdWNjZXNzVXBkYXRlckFjdGlvbixcbiAgTWFwU3R5bGVDaGFuZ2VVcGRhdGVyQWN0aW9uLFxuICBMYXllclR5cGVDaGFuZ2VVcGRhdGVyQWN0aW9uLFxuICBUb2dnbGVTcGxpdE1hcFVwZGF0ZXJBY3Rpb24sXG4gIFJlcGxhY2VEYXRhSW5NYXBQYXlsb2FkXG59IGZyb20gJ0BrZXBsZXIuZ2wvYWN0aW9ucyc7XG5pbXBvcnQge1Zpc1N0YXRlfSBmcm9tICdAa2VwbGVyLmdsL3NjaGVtYXMnO1xuaW1wb3J0IHtMYXllcn0gZnJvbSAnQGtlcGxlci5nbC9sYXllcnMnO1xuaW1wb3J0IHtpc1BsYWluT2JqZWN0fSBmcm9tICdAa2VwbGVyLmdsL3V0aWxzJztcbmltcG9ydCB7ZmluZE1hcEJvdW5kc30gZnJvbSAnLi9kYXRhLXV0aWxzJztcbmltcG9ydCB7QkFTRV9NQVBfQ09MT1JfTU9ERVMsIE9WRVJMQVlfQkxFTkRJTkdTfSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5cbmV4cG9ydCB0eXBlIEtlcGxlckdsU3RhdGUgPSB7XG4gIHZpc1N0YXRlOiBWaXNTdGF0ZTtcbiAgbWFwU3RhdGU6IE1hcFN0YXRlO1xuICBtYXBTdHlsZTogTWFwU3R5bGU7XG4gIHVpU3RhdGU6IFVpU3RhdGU7XG4gIHByb3ZpZGVyU3RhdGU6IFByb3ZpZGVyU3RhdGU7XG59O1xuXG4vLyBjb21wb3NlIGFjdGlvbiB0byBhcHBseSByZXN1bHQgbXVsdGlwbGUgcmVkdWNlcnMsIHdpdGggdGhlIG91dHB1dCBvZiBvbmVcblxuLyoqXG4gKiBTb21lIGFjdGlvbnMgd2lsbCBhZmZlY3QgdGhlIGVudGlyZSBrZXBsZXIubGcgaW5zdGFuY2Ugc3RhdGUuXG4gKiBUaGUgdXBkYXRlcnMgZm9yIHRoZXNlIGFjdGlvbnMgaXMgZXhwb3J0ZWQgYXMgYGNvbWJpbmVkVXBkYXRlcnNgLiBUaGVzZSB1cGRhdGVyIHRha2UgdGhlIGVudGlyZSBpbnN0YW5jZSBzdGF0ZVxuICogYXMgdGhlIGZpcnN0IGFyZ3VtZW50LiBSZWFkIG1vcmUgYWJvdXQgW1VzaW5nIHVwZGF0ZXJzXSguLi9hZHZhbmNlZC11c2FnZS91c2luZy11cGRhdGVycy5tZClcbiAqIEBwdWJsaWNcbiAqIEBleGFtcGxlXG4gKlxuICogaW1wb3J0IGtlcGxlckdsUmVkdWNlciwge2NvbWJpbmVkVXBkYXRlcnN9IGZyb20gJ0BrZXBsZXIuZ2wvcmVkdWNlcnMnO1xuICogLy8gUm9vdCBSZWR1Y2VyXG4gKiBjb25zdCByZWR1Y2VycyA9IGNvbWJpbmVSZWR1Y2Vycyh7XG4gKiAga2VwbGVyR2w6IGtlcGxlckdsUmVkdWNlcixcbiAqICBhcHA6IGFwcFJlZHVjZXJcbiAqIH0pO1xuICpcbiAqIGNvbnN0IGNvbXBvc2VkUmVkdWNlciA9IChzdGF0ZSwgYWN0aW9uKSA9PiB7XG4gKiAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICogICAgLy8gYWRkIGRhdGEgdG8gbWFwIGFmdGVyIHJlY2VpdmluZyBkYXRhIGZyb20gcmVtb3RlIHNvdXJjZXNcbiAqICAgIGNhc2UgJ0xPQURfUkVNT1RFX1JFU09VUkNFX1NVQ0NFU1MnOlxuICogICAgICByZXR1cm4ge1xuICogICAgICAgIC4uLnN0YXRlLFxuICogICAgICAgIGtlcGxlckdsOiB7XG4gKiAgICAgICAgICAuLi5zdGF0ZS5rZXBsZXJHbCxcbiAqICAgICAgICAgIC8vIHBhc3MgaW4ga2VwbGVyLmdsIGluc3RhbmNlIHN0YXRlIHRvIGNvbWJpbmVkVXBkYXRlcnNcbiAqICAgICAgICAgIG1hcDogIGNvbWJpbmVkVXBkYXRlcnMuYWRkRGF0YVRvTWFwVXBkYXRlcihcbiAqICAgICAgICAgICBzdGF0ZS5rZXBsZXJHbC5tYXAsXG4gKiAgICAgICAgICAge1xuICogICAgICAgICAgICAgcGF5bG9hZDoge1xuICogICAgICAgICAgICAgICBkYXRhc2V0czogYWN0aW9uLmRhdGFzZXRzLFxuICogICAgICAgICAgICAgICBvcHRpb25zOiB7cmVhZE9ubHk6IHRydWV9LFxuICogICAgICAgICAgICAgICBjb25maWc6IGFjdGlvbi5jb25maWdcbiAqICAgICAgICAgICAgICB9XG4gKiAgICAgICAgICAgIH1cbiAqICAgICAgICAgIClcbiAqICAgICAgICB9XG4gKiAgICAgIH07XG4gKiAgfVxuICogIHJldHVybiByZWR1Y2VycyhzdGF0ZSwgYWN0aW9uKTtcbiAqIH07XG4gKlxuICogZXhwb3J0IGRlZmF1bHQgY29tcG9zZWRSZWR1Y2VyO1xuICovXG5cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyAqL1xuLy8gQHRzLWlnbm9yZVxuY29uc3QgY29tYmluZWRVcGRhdGVycyA9IG51bGw7XG4vKiBlc2xpbnQtZW5hYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyAqL1xuXG5leHBvcnQgY29uc3QgaXNWYWxpZENvbmZpZyA9IGNvbmZpZyA9PlxuICBpc1BsYWluT2JqZWN0KGNvbmZpZykgJiYgaXNQbGFpbk9iamVjdChjb25maWcuY29uZmlnKSAmJiBjb25maWcudmVyc2lvbjtcblxuZXhwb3J0IGNvbnN0IGRlZmF1bHRBZGREYXRhVG9NYXBPcHRpb25zID0ge1xuICBjZW50ZXJNYXA6IHRydWUsXG4gIGtlZXBFeGlzdGluZ0NvbmZpZzogZmFsc2UsXG4gIGF1dG9DcmVhdGVMYXllcnM6IHRydWUsXG4gIGF1dG9DcmVhdGVUb29sdGlwczogdHJ1ZVxufTtcblxuLyoqXG4gKiBDb21iaW5lIGRhdGEgYW5kIGZ1bGwgY29uZmlndXJhdGlvbiB1cGRhdGUgaW4gYSBzaW5nbGUgYWN0aW9uXG4gKlxuICogQG1lbWJlcm9mIGNvbWJpbmVkVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBrZXBsZXIuZ2wgaW5zdGFuY2Ugc3RhdGUsIGNvbnRhaW5pbmcgYWxsIHN1YnJlZHVjZXIgc3RhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24ucGF5bG9hZCBge2RhdGFzZXRzLCBvcHRpb25zLCBjb25maWd9YFxuICogQHBhcmFtIGFjdGlvbi5wYXlsb2FkLmRhdGFzZXRzIC0gKioqcmVxdWlyZWQqKiBkYXRhc2V0cyBjYW4gYmUgYSBkYXRhc2V0IG9yIGFuIGFycmF5IG9mIGRhdGFzZXRzXG4gKiBFYWNoIGRhdGFzZXQgb2JqZWN0IG5lZWRzIHRvIGhhdmUgYGluZm9gIGFuZCBgZGF0YWAgcHJvcGVydHkuXG4gKiBAcGFyYW0gW2FjdGlvbi5wYXlsb2FkLm9wdGlvbnNdIG9wdGlvbiBvYmplY3QgYHtjZW50ZXJNYXA6IHRydWV9YFxuICogQHBhcmFtIFthY3Rpb24ucGF5bG9hZC5jb25maWddIG1hcCBjb25maWdcbiAqIEBwYXJhbSBbYWN0aW9uLnBheWxvYWQuaW5mb10gbWFwIGluZm8gY29udGFpbnMgdGl0bGUgYW5kIGRlc2NyaXB0aW9uXG4gKiBAcmV0dXJucyBuZXh0U3RhdGVcbiAqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEYXRhc2V0XG4gKiBAcHJvcGVydHkgaW5mbyAtaW5mbyBvZiBhIGRhdGFzZXRcbiAqIEBwcm9wZXJ0eSBpbmZvLmlkIC0gaWQgb2YgdGhpcyBkYXRhc2V0LiBJZiBjb25maWcgaXMgZGVmaW5lZCwgYGlkYCBzaG91bGQgbWF0Y2hlcyB0aGUgYGRhdGFJZGAgaW4gY29uZmlnLlxuICogQHByb3BlcnR5IGluZm8ubGFiZWwgLSBBIGRpc3BsYXkgbmFtZSBvZiB0aGlzIGRhdGFzZXRcbiAqIEBwcm9wZXJ0eSBkYXRhIC0gKioqcmVxdWlyZWQqKiBUaGUgZGF0YSBvYmplY3QsIGluIGEgdGFidWxhciBmb3JtYXQgd2l0aCAyIHByb3BlcnRpZXMgYGZpZWxkc2AgYW5kIGByb3dzYFxuICogQHByb3BlcnR5IGRhdGEuZmllbGRzIC0gKioqcmVxdWlyZWQqKiBBcnJheSBvZiBmaWVsZHMsXG4gKiBAcHJvcGVydHkgZGF0YS5maWVsZHMubmFtZSAtICoqKnJlcXVpcmVkKiogTmFtZSBvZiB0aGUgZmllbGQsXG4gKiBAcHJvcGVydHkgZGF0YS5yb3dzIC0gKioqcmVxdWlyZWQqKiBBcnJheSBvZiByb3dzLCBpbiBhIHRhYnVsYXIgZm9ybWF0IHdpdGggYGZpZWxkc2AgYW5kIGByb3dzYFxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGFkZERhdGFUb01hcFVwZGF0ZXIgPSAoXG4gIHN0YXRlOiBLZXBsZXJHbFN0YXRlLFxuICB7cGF5bG9hZH06IHtwYXlsb2FkOiBBZGREYXRhVG9NYXBQYXlsb2FkfVxuKTogS2VwbGVyR2xTdGF0ZSA9PiB7XG4gIGNvbnN0IHtkYXRhc2V0cywgY29uZmlnLCBpbmZvfSA9IHBheWxvYWQ7XG5cbiAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAuLi5kZWZhdWx0QWRkRGF0YVRvTWFwT3B0aW9ucyxcbiAgICAuLi5wYXlsb2FkLm9wdGlvbnNcbiAgfTtcblxuICAvLyBjaGVjayBpZiBwcm9ncmVzc2l2ZSBsb2FkaW5nIGRhdGFzZXQgYnkgYmF0Y2hlcywgYW5kIHVwZGF0ZSB2aXNTdGF0ZSBkaXJlY3RseVxuICBjb25zdCBpc1Byb2dyZXNzaXZlTG9hZGluZyA9XG4gICAgQXJyYXkuaXNBcnJheShkYXRhc2V0cykgJiZcbiAgICBkYXRhc2V0c1swXT8uaW5mby5mb3JtYXQgPT09ICdhcnJvdycgJiZcbiAgICBkYXRhc2V0c1swXT8uaW5mby5pZCAmJlxuICAgIGRhdGFzZXRzWzBdPy5pbmZvLmlkIGluIHN0YXRlLnZpc1N0YXRlLmRhdGFzZXRzO1xuICBpZiAoaXNQcm9ncmVzc2l2ZUxvYWRpbmcpIHtcbiAgICByZXR1cm4gY29tcG9zZV88S2VwbGVyR2xTdGF0ZT4oW1xuICAgICAgcGlja18oJ3Zpc1N0YXRlJykoXG4gICAgICAgIGFwcGx5XzxWaXNTdGF0ZSwgYW55Pih2aXNTdGF0ZVVwZGF0ZVZpc0RhdGFVcGRhdGVyLCB7XG4gICAgICAgICAgZGF0YXNldHMsXG4gICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgICBjb25maWdcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICBdKShzdGF0ZSk7XG4gIH1cblxuICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gIGxldCBwYXJzZWRDb25maWc6IFBhcnNlZENvbmZpZyA9IGNvbmZpZztcblxuICBpZiAoaXNWYWxpZENvbmZpZyhjb25maWcpKSB7XG4gICAgLy8gaWYgcGFzc2VkIGluIHNhdmVkIGNvbmZpZ1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICBwYXJzZWRDb25maWcgPSBzdGF0ZS52aXNTdGF0ZS5zY2hlbWEucGFyc2VTYXZlZENvbmZpZyhjb25maWcpO1xuICB9XG4gIGNvbnN0IG9sZExheWVycyA9IHN0YXRlLnZpc1N0YXRlLmxheWVycztcbiAgY29uc3QgZmlsdGVyTmV3bHlBZGRlZExheWVycyA9IChsYXllcnM6IExheWVyW10pID0+XG4gICAgbGF5ZXJzLmZpbHRlcihubCA9PiAhb2xkTGF5ZXJzLmZpbmQob2wgPT4gb2wgPT09IG5sKSk7XG5cbiAgLy8gUmV0dXJucyB1bmRlZmluZWQgaWYgbm90IGZvdW5kLCB0byBtYWtlIHR5cGVzY3JpcHQgaGFwcHlcbiAgY29uc3QgZmluZE1hcEJvdW5kc0lmQ2VudGVyZWQgPSAobGF5ZXJzOiBMYXllcltdKSA9PiB7XG4gICAgY29uc3QgYm91bmRzID0gb3B0aW9ucy5jZW50ZXJNYXAgJiYgZmluZE1hcEJvdW5kcyhsYXllcnMpO1xuICAgIHJldHVybiBib3VuZHMgPyBib3VuZHMgOiB1bmRlZmluZWQ7XG4gIH07XG5cbiAgcmV0dXJuIGNvbXBvc2VfPEtlcGxlckdsU3RhdGU+KFtcbiAgICBwaWNrXygndmlzU3RhdGUnKShcbiAgICAgIC8vIHRoaXMgcGFydCBjYW4gYmUgYXN5bmNcbiAgICAgIGFwcGx5XzxWaXNTdGF0ZSwgYW55Pih2aXNTdGF0ZVVwZGF0ZVZpc0RhdGFVcGRhdGVyLCB7XG4gICAgICAgIGRhdGFzZXRzLFxuICAgICAgICBvcHRpb25zLFxuICAgICAgICBjb25maWc6IHBhcnNlZENvbmZpZ1xuICAgICAgfSlcbiAgICApLFxuXG4gICAgaWZfKEJvb2xlYW4oaW5mbyksIHBpY2tfKCd2aXNTdGF0ZScpKGFwcGx5XzxWaXNTdGF0ZSwgYW55PihzZXRNYXBJbmZvVXBkYXRlciwge2luZm99KSkpLFxuICAgIC8vIE5vdGUgdGhhdCBmaXQgYm91bmRzIGhlcmUgd29uJ3QgYmUgY2FsbGVkIGluIGNhc2UgZGF0YXNldHMgYXJlIGNyZWF0ZWQgaW4gVGFza3MuXG4gICAgLy8gQSBzZXBhcmF0ZSBUYXNrIHRvIHVwZGF0ZSBib3VuZHMgaXMgY3JlYXRlZCBvbmNlIHRoZSBkYXRhc2V0cyBhcmUgcmVhZHkuXG4gICAgd2l0aF8oKHt2aXNTdGF0ZX0pID0+XG4gICAgICBwaWNrXygnbWFwU3RhdGUnKShcbiAgICAgICAgYXBwbHlfKFxuICAgICAgICAgIHN0YXRlTWFwQ29uZmlnVXBkYXRlcixcbiAgICAgICAgICBwYXlsb2FkXyh7XG4gICAgICAgICAgICBjb25maWc6IHBhcnNlZENvbmZpZyxcbiAgICAgICAgICAgIG9wdGlvbnMsXG4gICAgICAgICAgICBib3VuZHM6IGZpbmRNYXBCb3VuZHNJZkNlbnRlcmVkKGZpbHRlck5ld2x5QWRkZWRMYXllcnModmlzU3RhdGUubGF5ZXJzKSlcbiAgICAgICAgICB9KVxuICAgICAgICApXG4gICAgICApXG4gICAgKSxcbiAgICBwaWNrXygnbWFwU3R5bGUnKShhcHBseV8oc3R5bGVNYXBDb25maWdVcGRhdGVyLCBwYXlsb2FkXyh7Y29uZmlnOiBwYXJzZWRDb25maWcsIG9wdGlvbnN9KSkpLFxuICAgIHBpY2tfKCd1aVN0YXRlJykoYXBwbHlfKHVpU3RhdGVMb2FkRmlsZXNTdWNjZXNzVXBkYXRlciwgcGF5bG9hZF8obnVsbCkpKSxcblxuICAgIGlmXyhcbiAgICAgIEJvb2xlYW4ocGFyc2VkQ29uZmlnPy51aVN0YXRlPy5tYXBDb250cm9scz8ubWFwTGVnZW5kPy5hY3RpdmUpLFxuICAgICAgcGlja18oJ3VpU3RhdGUnKShcbiAgICAgICAgYXBwbHlfKHVpU3RhdGVUb2dnbGVNYXBDb250cm9sVXBkYXRlciwgcGF5bG9hZF8oe3BhbmVsSWQ6ICdtYXBMZWdlbmQnLCBpbmRleDogMH0pKVxuICAgICAgKVxuICAgICksXG5cbiAgICBpZl8oXG4gICAgICBCb29sZWFuKHBhcnNlZENvbmZpZz8udWlTdGF0ZT8ubWFwQ29udHJvbHM/Lm1hcExlZ2VuZD8uc2V0dGluZ3MpLFxuICAgICAgcGlja18oJ3VpU3RhdGUnKShcbiAgICAgICAgYXBwbHlfKFxuICAgICAgICAgIHVpU3RhdGVTZXRNYXBDb250cm9sU2V0dGluZ3NVcGRhdGVyLFxuICAgICAgICAgIHBheWxvYWRfKHtcbiAgICAgICAgICAgIHBhbmVsSWQ6ICdtYXBMZWdlbmQnLFxuICAgICAgICAgICAgc2V0dGluZ3M6IHBhcnNlZENvbmZpZz8udWlTdGF0ZT8ubWFwQ29udHJvbHM/Lm1hcExlZ2VuZD8uc2V0dGluZ3MgPz8ge31cbiAgICAgICAgICB9KVxuICAgICAgICApXG4gICAgICApXG4gICAgKSxcbiAgICBwaWNrXygndWlTdGF0ZScpKGFwcGx5Xyh0b2dnbGVNb2RhbFVwZGF0ZXIsIHBheWxvYWRfKG51bGwpKSksXG4gICAgcGlja18oJ3VpU3RhdGUnKShcbiAgICAgIG1lcmdlXyhcbiAgICAgICAgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9wdGlvbnMsICdyZWFkT25seScpXG4gICAgICAgICAgPyB7cmVhZE9ubHk6IG9wdGlvbnMucmVhZE9ubHl9XG4gICAgICAgICAgOiB7fVxuICAgICAgKVxuICAgIClcbiAgXSkoc3RhdGUpO1xufTtcblxuZXhwb3J0IGNvbnN0IGxvYWRGaWxlc1N1Y2Nlc3NVcGRhdGVyID0gKFxuICBzdGF0ZTogS2VwbGVyR2xTdGF0ZSxcbiAgYWN0aW9uOiBsb2FkRmlsZXNTdWNjZXNzVXBkYXRlckFjdGlvblxuKTogS2VwbGVyR2xTdGF0ZSA9PiB7XG4gIC8vIHN0aWxsIG1vcmUgdG8gbG9hZFxuICBjb25zdCBwYXlsb2FkcyA9IGZpbGVzVG9EYXRhUGF5bG9hZChhY3Rpb24ucmVzdWx0KTtcbiAgY29uc3QgbmV4dFN0YXRlID0gY29tcG9zZV8oW1xuICAgIHBpY2tfKCd2aXNTdGF0ZScpKFxuICAgICAgbWVyZ2VfKHtcbiAgICAgICAgZmlsZUxvYWRpbmc6IGZhbHNlLFxuICAgICAgICBmaWxlTG9hZGluZ1Byb2dyZXNzOiB7fVxuICAgICAgfSlcbiAgICApXG4gIF0pKHN0YXRlKTtcbiAgLy8gbWFrZSBtdWx0aXBsZSBhZGQgZGF0YSB0byBtYXAgY2FsbHNcbiAgY29uc3Qgc3RhdGVXaXRoRGF0YSA9IGNvbXBvc2VfKHBheWxvYWRzLm1hcChwID0+IGFwcGx5XyhhZGREYXRhVG9NYXBVcGRhdGVyLCBwYXlsb2FkXyhwKSkpKShcbiAgICBuZXh0U3RhdGVcbiAgKTtcbiAgcmV0dXJuIHN0YXRlV2l0aERhdGEgYXMgS2VwbGVyR2xTdGF0ZTtcbn07XG5cbmV4cG9ydCBjb25zdCBhZGREYXRhVG9NYXBDb21wb3NlZCA9IGFkZERhdGFUb01hcFVwZGF0ZXI7XG5cbi8qKlxuICogSGVscGVyIHdoaWNoIHVwZGF0ZXMgbWFwIG92ZXJsYXkgYmxlbmRpbmcgbW9kZSBpbiB2aXNTdGF0ZSxcbiAqIGJ1dCBvbmx5IGlmIGl0J3Mgbm90IGN1cnJlbnRseSBpbiB0aGUgYG5vcm1hbGAgbW9kZS5cbiAqL1xuY29uc3QgdXBkYXRlT3ZlcmxheUJsZW5kaW5nID0gb3ZlcmxheUJsZW5kaW5nID0+IHZpc1N0YXRlID0+IHtcbiAgaWYgKHZpc1N0YXRlLm92ZXJsYXlCbGVuZGluZyAhPT0gT1ZFUkxBWV9CTEVORElOR1Mubm9ybWFsLnZhbHVlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnZpc1N0YXRlLFxuICAgICAgb3ZlcmxheUJsZW5kaW5nXG4gICAgfTtcbiAgfVxuICByZXR1cm4gdmlzU3RhdGU7XG59O1xuXG4vKipcbiAqIEhlbHBlciB3aGljaCB1cGRhdGVzIGBkYXJrQmFzZU1hcEVuYWJsZWRgIGluIGFsbCB0aGUgbGF5ZXJzIGluIHZpc1N0YXRlIHdoaWNoXG4gKiBoYXZlIHRoaXMgY29uZmlnIHNldHRpbmcgKG9yIGluIG9uZSBzcGVjaWZpYyBsYXllciBpZiB0aGUgYGxheWVySWRgIHBhcmFtIGlzIHByb3ZpZGVkKS5cbiAqL1xuY29uc3QgdXBkYXRlRGFya0Jhc2VNYXBMYXllcnMgPVxuICAoZGFya0Jhc2VNYXBFbmFibGVkOiBib29sZWFuLCBsYXllcklkOiBzdHJpbmcgfCBudWxsID0gbnVsbCkgPT5cbiAgdmlzU3RhdGUgPT4gKHtcbiAgICAuLi52aXNTdGF0ZSxcbiAgICBsYXllcnM6IHZpc1N0YXRlLmxheWVycy5tYXAobGF5ZXIgPT4ge1xuICAgICAgaWYgKCFsYXllcklkIHx8IGxheWVyLmlkID09PSBsYXllcklkKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobGF5ZXIudmlzQ29uZmlnU2V0dGluZ3MsICdkYXJrQmFzZU1hcEVuYWJsZWQnKSkge1xuICAgICAgICAgIGNvbnN0IHt2aXNDb25maWd9ID0gbGF5ZXIuY29uZmlnO1xuICAgICAgICAgIHJldHVybiBsYXllci51cGRhdGVMYXllckNvbmZpZyh7XG4gICAgICAgICAgICB2aXNDb25maWc6IHsuLi52aXNDb25maWcsIGRhcmtCYXNlTWFwRW5hYmxlZH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGxheWVyO1xuICAgIH0pXG4gIH0pO1xuXG4vKipcbiAqIFVwZGF0ZXIgdGhhdCBjaGFuZ2VzIHRoZSBtYXAgc3R5bGUgYnkgY2FsbGluZyBtYXBTdHlsZUNoYW5nZVVwZGF0ZXIgb24gdmlzU3RhdGUuXG4gKiBJbiBhZGRpdGlvbiB0byB0aGF0LCBpdCBkb2VzIHRoZSBmb2xsb3dpbmc6XG4gKlxuICogICAxLiBVcGRhdGUgbWFwIG92ZXJsYXkgYmxlbmRpbmcgbW9kZSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIGNvbG9yTW9kZSBvZiB0aGVcbiAqICAgICAgYmFzZSBtYXAsIGJ1dCBvbmx5IGlmIGl0J3Mgbm90IGluIHRoZSBgbm9ybWFsYCBtb2RlLlxuICpcbiAqICAgMi4gVXBkYXRlIGFsbCB0aGUgbGF5ZXJzIHdoaWNoIGhhdmUgdGhlIGBkYXJrQmFzZU1hcEVuYWJsZWRgIGNvbmZpZyBzZXR0aW5nXG4gKiAgICAgIGFkanVzdGluZyBpdCBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIGNvbG9yTW9kZSBvZiB0aGUgYmFzZSBtYXAuXG4gKlxuICovXG5leHBvcnQgY29uc3QgY29tYmluZWRNYXBTdHlsZUNoYW5nZVVwZGF0ZXIgPSAoXG4gIHN0YXRlOiBLZXBsZXJHbFN0YXRlLFxuICBhY3Rpb246IE1hcFN0eWxlQ2hhbmdlVXBkYXRlckFjdGlvblxuKTogS2VwbGVyR2xTdGF0ZSA9PiB7XG4gIGNvbnN0IHtwYXlsb2FkfSA9IGFjdGlvbjtcbiAgY29uc3Qge21hcFN0eWxlfSA9IHN0YXRlO1xuICBjb25zdCBnZXRDb2xvck1vZGUgPSBrZXkgPT4gbWFwU3R5bGUubWFwU3R5bGVzW2tleV0/LmNvbG9yTW9kZTtcbiAgY29uc3QgcHJldkNvbG9yTW9kZSA9IGdldENvbG9yTW9kZShtYXBTdHlsZS5zdHlsZVR5cGUpO1xuICBjb25zdCBuZXh0Q29sb3JNb2RlID0gZ2V0Q29sb3JNb2RlKHBheWxvYWQuc3R5bGVUeXBlKTtcbiAgbGV0IHt2aXNTdGF0ZX0gPSBzdGF0ZTtcbiAgaWYgKG5leHRDb2xvck1vZGUgIT09IHByZXZDb2xvck1vZGUpIHtcbiAgICBzd2l0Y2ggKG5leHRDb2xvck1vZGUpIHtcbiAgICAgIGNhc2UgQkFTRV9NQVBfQ09MT1JfTU9ERVMuREFSSzpcbiAgICAgICAgdmlzU3RhdGUgPSBjb21wb3NlXyhbXG4gICAgICAgICAgdXBkYXRlT3ZlcmxheUJsZW5kaW5nKE9WRVJMQVlfQkxFTkRJTkdTLnNjcmVlbi52YWx1ZSksXG4gICAgICAgICAgdXBkYXRlRGFya0Jhc2VNYXBMYXllcnModHJ1ZSlcbiAgICAgICAgXSkodmlzU3RhdGUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQkFTRV9NQVBfQ09MT1JfTU9ERVMuTElHSFQ6XG4gICAgICAgIHZpc1N0YXRlID0gY29tcG9zZV8oW1xuICAgICAgICAgIHVwZGF0ZU92ZXJsYXlCbGVuZGluZyhPVkVSTEFZX0JMRU5ESU5HUy5kYXJrZW4udmFsdWUpLFxuICAgICAgICAgIHVwZGF0ZURhcmtCYXNlTWFwTGF5ZXJzKGZhbHNlKVxuICAgICAgICBdKSh2aXNTdGF0ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICB2aXNTdGF0ZSxcbiAgICBtYXBTdHlsZTogbWFwU3R5bGVDaGFuZ2VVcGRhdGVyKG1hcFN0eWxlLCB7cGF5bG9hZDogey4uLnBheWxvYWR9fSlcbiAgfTtcbn07XG5cbi8qKlxuICogVXBkYXRlciB0aGF0IGNoYW5nZXMgdGhlIGxheWVyIHR5cGUgYnkgY2FsbGluZyBgbGF5ZXJUeXBlQ2hhbmdlVXBkYXRlcmAgb24gdmlzU3RhdGUuXG4gKiBJbiBhZGRpdGlvbiB0byB0aGF0LCBpZiB0aGUgbmV3IGxheWVyIHR5cGUgaGFzIHRoZSBgZGFya0Jhc2VNYXBFbmFibGVkYCBjb25maWdcbiAqIHNldHRpbmcsIHdlIGFkanVzdCBpdCBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIGNvbG9yTW9kZSBvZiB0aGUgYmFzZSBtYXAuc1xuICovXG5leHBvcnQgY29uc3QgY29tYmluZWRMYXllclR5cGVDaGFuZ2VVcGRhdGVyID0gKFxuICBzdGF0ZTogS2VwbGVyR2xTdGF0ZSxcbiAgYWN0aW9uOiBMYXllclR5cGVDaGFuZ2VVcGRhdGVyQWN0aW9uXG4pOiBLZXBsZXJHbFN0YXRlID0+IHtcbiAgbGV0IHt2aXNTdGF0ZX0gPSBzdGF0ZTtcbiAgY29uc3Qgb2xkTGF5ZXJJbmRleCA9IHZpc1N0YXRlLmxheWVycy5maW5kSW5kZXgobGF5ZXIgPT4gbGF5ZXIgPT09IGFjdGlvbi5vbGRMYXllcik7XG4gIHZpc1N0YXRlID0gbGF5ZXJUeXBlQ2hhbmdlVXBkYXRlcih2aXNTdGF0ZSwgYWN0aW9uKTtcbiAgY29uc3QgbmV3TGF5ZXIgPSB2aXNTdGF0ZS5sYXllcnNbb2xkTGF5ZXJJbmRleF07XG4gIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobmV3TGF5ZXI/LnZpc0NvbmZpZ1NldHRpbmdzLCAnZGFya0Jhc2VNYXBFbmFibGVkJykpIHtcbiAgICBjb25zdCB7bWFwU3R5bGV9ID0gc3RhdGU7XG4gICAgY29uc3Qge2NvbG9yTW9kZX0gPSBtYXBTdHlsZS5tYXBTdHlsZXNbbWFwU3R5bGUuc3R5bGVUeXBlXTtcbiAgICBjb25zdCB7ZGFya0Jhc2VNYXBFbmFibGVkfSA9IG5ld0xheWVyLmNvbmZpZy52aXNDb25maWc7XG4gICAgc3dpdGNoIChjb2xvck1vZGUpIHtcbiAgICAgIGNhc2UgQkFTRV9NQVBfQ09MT1JfTU9ERVMuREFSSzpcbiAgICAgICAgaWYgKCFkYXJrQmFzZU1hcEVuYWJsZWQpIHtcbiAgICAgICAgICB2aXNTdGF0ZSA9IHVwZGF0ZURhcmtCYXNlTWFwTGF5ZXJzKHRydWUsIG5ld0xheWVyLmlkKSh2aXNTdGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEJBU0VfTUFQX0NPTE9SX01PREVTLkxJR0hUOlxuICAgICAgICBpZiAoZGFya0Jhc2VNYXBFbmFibGVkKSB7XG4gICAgICAgICAgdmlzU3RhdGUgPSB1cGRhdGVEYXJrQmFzZU1hcExheWVycyhmYWxzZSwgbmV3TGF5ZXIuaWQpKHZpc1N0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfVxuICB9XG4gIHJldHVybiB7XG4gICAgLi4uc3RhdGUsXG4gICAgdmlzU3RhdGVcbiAgfTtcbn07XG5cbi8qKlxuICogTWFrZSBtYXBMZWdlbmQgYWN0aXZlIHdoZW4gdG9nZ2xlU3BsaXRNYXAgYWN0aW9uIGlzIGNhbGxlZFxuICovXG5leHBvcnQgY29uc3QgdG9nZ2xlU3BsaXRNYXBVcGRhdGVyID0gKFxuICBzdGF0ZTogS2VwbGVyR2xTdGF0ZSxcbiAgYWN0aW9uOiBUb2dnbGVTcGxpdE1hcFVwZGF0ZXJBY3Rpb25cbik6IEtlcGxlckdsU3RhdGUgPT4ge1xuICBjb25zdCBuZXdTdGF0ZSA9IHtcbiAgICAuLi5zdGF0ZSxcbiAgICB2aXNTdGF0ZTogdmlzU3RhdGVUb2dnbGVTcGxpdE1hcFVwZGF0ZXIoc3RhdGUudmlzU3RhdGUsIGFjdGlvbiksXG4gICAgdWlTdGF0ZTogdWlTdGF0ZVRvZ2dsZVNwbGl0TWFwVXBkYXRlcihzdGF0ZS51aVN0YXRlKSxcbiAgICBtYXBTdGF0ZTogbWFwU3RhdGVUb2dnbGVTcGxpdE1hcFVwZGF0ZXIoc3RhdGUubWFwU3RhdGUpXG4gIH07XG5cbiAgY29uc3QgaXNTcGxpdCA9IG5ld1N0YXRlLnZpc1N0YXRlLnNwbGl0TWFwcy5sZW5ndGggIT09IDA7XG4gIGNvbnN0IGlzTGVnZW5kQWN0aXZlID0gbmV3U3RhdGUudWlTdGF0ZS5tYXBDb250cm9scz8ubWFwTGVnZW5kPy5hY3RpdmU7XG4gIGlmIChpc1NwbGl0ICYmICFpc0xlZ2VuZEFjdGl2ZSkge1xuICAgIG5ld1N0YXRlLnVpU3RhdGUgPSB0b2dnbGVNYXBDb250cm9sVXBkYXRlcihuZXdTdGF0ZS51aVN0YXRlLCB7XG4gICAgICBwYXlsb2FkOiB7cGFuZWxJZDogJ21hcExlZ2VuZCcsIGluZGV4OiBhY3Rpb24ucGF5bG9hZH1cbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBuZXdTdGF0ZTtcbn07XG5cbmNvbnN0IGRlZmF1bHRSZXBsYWNlRGF0YVRvTWFwT3B0aW9ucyA9IHtcbiAga2VlcEV4aXN0aW5nQ29uZmlnOiB0cnVlLFxuICBjZW50ZXJNYXA6IHRydWUsXG4gIGF1dG9DcmVhdGVMYXllcnM6IGZhbHNlXG59O1xuXG4vKipcbiAqIFVwZGF0ZXIgcmVwbGFjZSBhIGRhdGFzZXQgaW4gc3RhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IHJlcGxhY2VEYXRhSW5NYXBVcGRhdGVyID0gKFxuICBzdGF0ZTogS2VwbGVyR2xTdGF0ZSxcbiAge3BheWxvYWR9OiB7cGF5bG9hZDogUmVwbGFjZURhdGFJbk1hcFBheWxvYWR9XG4pOiBLZXBsZXJHbFN0YXRlID0+IHtcbiAgY29uc3Qge2RhdGFzZXRUb1JlcGxhY2VJZCwgZGF0YXNldFRvVXNlLCBvcHRpb25zID0ge319ID0gcGF5bG9hZDtcbiAgY29uc3QgYWRkRGF0YVRvTWFwT3B0aW9ucyA9IHsuLi5kZWZhdWx0UmVwbGFjZURhdGFUb01hcE9wdGlvbnMsIC4uLm9wdGlvbnN9O1xuXG4gIC8vIGNoZWNrIGlmIGRhdGFzZXQgaXMgdGhlcmVcbiAgaWYgKCFzdGF0ZS52aXNTdGF0ZS5kYXRhc2V0c1tkYXRhc2V0VG9SZXBsYWNlSWRdKSB7XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG4gIC8vIGRhdGFzZXRUb1VzZSBpcyBQcm90b0RhdGFzZXRcbiAgY29uc3QgZGF0YUlkVG9Vc2UgPSBkYXRhc2V0VG9Vc2UuaW5mby5pZDtcbiAgaWYgKCFkYXRhSWRUb1VzZSkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuICAvLyByZW1vdmUgZGF0YXNldCBhbmQgcHV0IGRlcGVuZGVuY2llcyBpbiB0b0JlTWVyZ2VkXG4gIGNvbnN0IHByZXBhcmVkU3RhdGUgPSB7XG4gICAgLi4uc3RhdGUsXG4gICAgdmlzU3RhdGU6IHByZXBhcmVTdGF0ZUZvckRhdGFzZXRSZXBsYWNlKHN0YXRlLnZpc1N0YXRlLCBkYXRhc2V0VG9SZXBsYWNlSWQsIGRhdGFJZFRvVXNlKVxuICB9O1xuXG4gIGNvbnN0IG5leHRTdGF0ZSA9IGFkZERhdGFUb01hcFVwZGF0ZXIoXG4gICAgcHJlcGFyZWRTdGF0ZSxcbiAgICBwYXlsb2FkXyh7XG4gICAgICBkYXRhc2V0czogZGF0YXNldFRvVXNlLFxuICAgICAgLy8gc2hvdWxkIHpvb20gdG8gbmV3IGRhdGFzZXRcbiAgICAgIG9wdGlvbnM6IGFkZERhdGFUb01hcE9wdGlvbnNcbiAgICB9KVxuICApO1xuXG4gIHJldHVybiBuZXh0U3RhdGU7XG59O1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUdBLElBQUFBLGdCQUFBLEdBQUFDLE9BQUE7QUFRQSxJQUFBQyxpQkFBQSxHQUFBRCxPQUFBO0FBT0EsSUFBQUUsaUJBQUEsR0FBQUYsT0FBQTtBQUlBLElBQUFHLGlCQUFBLEdBQUFILE9BQUE7QUFJQSxJQUFBSSxJQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxnQkFBQSxHQUFBTCxPQUFBO0FBYUEsSUFBQU0sS0FBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8sVUFBQSxHQUFBUCxPQUFBO0FBQ0EsSUFBQVEsS0FBQSxHQUFBUixPQUFBO0FBQTZFLFNBQUFTLFFBQUFDLENBQUEsRUFBQUMsQ0FBQSxRQUFBQyxDQUFBLEdBQUFDLE1BQUEsQ0FBQUMsSUFBQSxDQUFBSixDQUFBLE9BQUFHLE1BQUEsQ0FBQUUscUJBQUEsUUFBQUMsQ0FBQSxHQUFBSCxNQUFBLENBQUFFLHFCQUFBLENBQUFMLENBQUEsR0FBQUMsQ0FBQSxLQUFBSyxDQUFBLEdBQUFBLENBQUEsQ0FBQUMsTUFBQSxXQUFBTixDQUFBLFdBQUFFLE1BQUEsQ0FBQUssd0JBQUEsQ0FBQVIsQ0FBQSxFQUFBQyxDQUFBLEVBQUFRLFVBQUEsT0FBQVAsQ0FBQSxDQUFBUSxJQUFBLENBQUFDLEtBQUEsQ0FBQVQsQ0FBQSxFQUFBSSxDQUFBLFlBQUFKLENBQUE7QUFBQSxTQUFBVSxjQUFBWixDQUFBLGFBQUFDLENBQUEsTUFBQUEsQ0FBQSxHQUFBWSxTQUFBLENBQUFDLE1BQUEsRUFBQWIsQ0FBQSxVQUFBQyxDQUFBLFdBQUFXLFNBQUEsQ0FBQVosQ0FBQSxJQUFBWSxTQUFBLENBQUFaLENBQUEsUUFBQUEsQ0FBQSxPQUFBRixPQUFBLENBQUFJLE1BQUEsQ0FBQUQsQ0FBQSxPQUFBYSxPQUFBLFdBQUFkLENBQUEsUUFBQWUsZ0JBQUEsYUFBQWhCLENBQUEsRUFBQUMsQ0FBQSxFQUFBQyxDQUFBLENBQUFELENBQUEsU0FBQUUsTUFBQSxDQUFBYyx5QkFBQSxHQUFBZCxNQUFBLENBQUFlLGdCQUFBLENBQUFsQixDQUFBLEVBQUFHLE1BQUEsQ0FBQWMseUJBQUEsQ0FBQWYsQ0FBQSxLQUFBSCxPQUFBLENBQUFJLE1BQUEsQ0FBQUQsQ0FBQSxHQUFBYSxPQUFBLFdBQUFkLENBQUEsSUFBQUUsTUFBQSxDQUFBZ0IsY0FBQSxDQUFBbkIsQ0FBQSxFQUFBQyxDQUFBLEVBQUFFLE1BQUEsQ0FBQUssd0JBQUEsQ0FBQU4sQ0FBQSxFQUFBRCxDQUFBLGlCQUFBRCxDQUFBLElBMUM3RTtBQUNBO0FBbURBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQU1vQixnQkFBZ0IsR0FBRyxJQUFJO0FBQzdCOztBQUVPLElBQU1DLGFBQWEsR0FBQUMsT0FBQSxDQUFBRCxhQUFBLEdBQUcsU0FBaEJBLGFBQWFBLENBQUdFLE1BQU07RUFBQSxPQUNqQyxJQUFBQyxtQkFBYSxFQUFDRCxNQUFNLENBQUMsSUFBSSxJQUFBQyxtQkFBYSxFQUFDRCxNQUFNLENBQUNBLE1BQU0sQ0FBQyxJQUFJQSxNQUFNLENBQUNFLE9BQU87QUFBQTtBQUVsRSxJQUFNQywwQkFBMEIsR0FBQUosT0FBQSxDQUFBSSwwQkFBQSxHQUFHO0VBQ3hDQyxTQUFTLEVBQUUsSUFBSTtFQUNmQyxrQkFBa0IsRUFBRSxLQUFLO0VBQ3pCQyxnQkFBZ0IsRUFBRSxJQUFJO0VBQ3RCQyxrQkFBa0IsRUFBRTtBQUN0QixDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sSUFBTUMsbUJBQW1CLEdBQUFULE9BQUEsQ0FBQVMsbUJBQUEsR0FBRyxTQUF0QkEsbUJBQW1CQSxDQUM5QkMsS0FBb0IsRUFBQUMsSUFBQSxFQUVGO0VBQUEsSUFBQUMsVUFBQSxFQUFBQyxXQUFBLEVBQUFDLFdBQUEsRUFBQUMsYUFBQSxFQUFBQyxjQUFBLEVBQUFDLHFCQUFBLEVBQUFDLGNBQUE7RUFBQSxJQURqQkMsT0FBTyxHQUFBUixJQUFBLENBQVBRLE9BQU87RUFFUixJQUFPQyxRQUFRLEdBQWtCRCxPQUFPLENBQWpDQyxRQUFRO0lBQUVuQixNQUFNLEdBQVVrQixPQUFPLENBQXZCbEIsTUFBTTtJQUFFb0IsSUFBSSxHQUFJRixPQUFPLENBQWZFLElBQUk7RUFFN0IsSUFBTUMsT0FBTyxHQUFBaEMsYUFBQSxDQUFBQSxhQUFBLEtBQ1JjLDBCQUEwQixHQUMxQmUsT0FBTyxDQUFDRyxPQUFPLENBQ25COztFQUVEO0VBQ0EsSUFBTUMsb0JBQW9CLEdBQ3hCQyxLQUFLLENBQUNDLE9BQU8sQ0FBQ0wsUUFBUSxDQUFDLElBQ3ZCLEVBQUFSLFVBQUEsR0FBQVEsUUFBUSxDQUFDLENBQUMsQ0FBQyxjQUFBUixVQUFBLHVCQUFYQSxVQUFBLENBQWFTLElBQUksQ0FBQ0ssTUFBTSxNQUFLLE9BQU8sTUFBQWIsV0FBQSxHQUNwQ08sUUFBUSxDQUFDLENBQUMsQ0FBQyxjQUFBUCxXQUFBLHVCQUFYQSxXQUFBLENBQWFRLElBQUksQ0FBQ00sRUFBRSxLQUNwQixFQUFBYixXQUFBLEdBQUFNLFFBQVEsQ0FBQyxDQUFDLENBQUMsY0FBQU4sV0FBQSx1QkFBWEEsV0FBQSxDQUFhTyxJQUFJLENBQUNNLEVBQUUsS0FBSWpCLEtBQUssQ0FBQ2tCLFFBQVEsQ0FBQ1IsUUFBUTtFQUNqRCxJQUFJRyxvQkFBb0IsRUFBRTtJQUN4QixPQUFPLElBQUFNLHlCQUFRLEVBQWdCLENBQzdCLElBQUFDLHNCQUFLLEVBQUMsVUFBVSxDQUFDLENBQ2YsSUFBQUMsdUJBQU0sRUFBZ0JDLHNDQUE0QixFQUFFO01BQ2xEWixRQUFRLEVBQVJBLFFBQVE7TUFDUkUsT0FBTyxFQUFQQSxPQUFPO01BQ1ByQixNQUFNLEVBQU5BO0lBQ0YsQ0FBQyxDQUNILENBQUMsQ0FDRixDQUFDLENBQUNTLEtBQUssQ0FBQztFQUNYOztFQUVBO0VBQ0EsSUFBSXVCLFlBQTBCLEdBQUdoQyxNQUFNO0VBRXZDLElBQUlGLGFBQWEsQ0FBQ0UsTUFBTSxDQUFDLEVBQUU7SUFDekI7SUFDQTtJQUNBZ0MsWUFBWSxHQUFHdkIsS0FBSyxDQUFDa0IsUUFBUSxDQUFDTSxNQUFNLENBQUNDLGdCQUFnQixDQUFDbEMsTUFBTSxDQUFDO0VBQy9EO0VBQ0EsSUFBTW1DLFNBQVMsR0FBRzFCLEtBQUssQ0FBQ2tCLFFBQVEsQ0FBQ1MsTUFBTTtFQUN2QyxJQUFNQyxzQkFBc0IsR0FBRyxTQUF6QkEsc0JBQXNCQSxDQUFJRCxNQUFlO0lBQUEsT0FDN0NBLE1BQU0sQ0FBQ3BELE1BQU0sQ0FBQyxVQUFBc0QsRUFBRTtNQUFBLE9BQUksQ0FBQ0gsU0FBUyxDQUFDSSxJQUFJLENBQUMsVUFBQUMsRUFBRTtRQUFBLE9BQUlBLEVBQUUsS0FBS0YsRUFBRTtNQUFBLEVBQUM7SUFBQSxFQUFDO0VBQUE7O0VBRXZEO0VBQ0EsSUFBTUcsdUJBQXVCLEdBQUcsU0FBMUJBLHVCQUF1QkEsQ0FBSUwsTUFBZSxFQUFLO0lBQ25ELElBQU1NLE1BQU0sR0FBR3JCLE9BQU8sQ0FBQ2pCLFNBQVMsSUFBSSxJQUFBdUMsd0JBQWEsRUFBQ1AsTUFBTSxDQUFDO0lBQ3pELE9BQU9NLE1BQU0sR0FBR0EsTUFBTSxHQUFHRSxTQUFTO0VBQ3BDLENBQUM7RUFFRCxPQUFPLElBQUFoQix5QkFBUSxFQUFnQixDQUM3QixJQUFBQyxzQkFBSyxFQUFDLFVBQVUsQ0FBQztFQUNmO0VBQ0EsSUFBQUMsdUJBQU0sRUFBZ0JDLHNDQUE0QixFQUFFO0lBQ2xEWixRQUFRLEVBQVJBLFFBQVE7SUFDUkUsT0FBTyxFQUFQQSxPQUFPO0lBQ1ByQixNQUFNLEVBQUVnQztFQUNWLENBQUMsQ0FDSCxDQUFDLEVBRUQsSUFBQWEsb0JBQUcsRUFBQ0MsT0FBTyxDQUFDMUIsSUFBSSxDQUFDLEVBQUUsSUFBQVMsc0JBQUssRUFBQyxVQUFVLENBQUMsQ0FBQyxJQUFBQyx1QkFBTSxFQUFnQmlCLG1DQUFpQixFQUFFO0lBQUMzQixJQUFJLEVBQUpBO0VBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztFQUN2RjtFQUNBO0VBQ0EsSUFBQTRCLHNCQUFLLEVBQUMsVUFBQUMsS0FBQTtJQUFBLElBQUV0QixRQUFRLEdBQUFzQixLQUFBLENBQVJ0QixRQUFRO0lBQUEsT0FDZCxJQUFBRSxzQkFBSyxFQUFDLFVBQVUsQ0FBQyxDQUNmLElBQUFDLHVCQUFNLEVBQ0pvQix5Q0FBcUIsRUFDckIsSUFBQUMseUJBQVEsRUFBQztNQUNQbkQsTUFBTSxFQUFFZ0MsWUFBWTtNQUNwQlgsT0FBTyxFQUFQQSxPQUFPO01BQ1BxQixNQUFNLEVBQUVELHVCQUF1QixDQUFDSixzQkFBc0IsQ0FBQ1YsUUFBUSxDQUFDUyxNQUFNLENBQUM7SUFDekUsQ0FBQyxDQUNILENBQ0YsQ0FBQztFQUFBLENBQ0gsQ0FBQyxFQUNELElBQUFQLHNCQUFLLEVBQUMsVUFBVSxDQUFDLENBQUMsSUFBQUMsdUJBQU0sRUFBQ3NCLHlDQUFxQixFQUFFLElBQUFELHlCQUFRLEVBQUM7SUFBQ25ELE1BQU0sRUFBRWdDLFlBQVk7SUFBRVgsT0FBTyxFQUFQQTtFQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFDM0YsSUFBQVEsc0JBQUssRUFBQyxTQUFTLENBQUMsQ0FBQyxJQUFBQyx1QkFBTSxFQUFDdUIsd0NBQThCLEVBQUUsSUFBQUYseUJBQVEsRUFBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBRXhFLElBQUFOLG9CQUFHLEVBQ0RDLE9BQU8sRUFBQWhDLGFBQUEsR0FBQ2tCLFlBQVksY0FBQWxCLGFBQUEsZ0JBQUFBLGFBQUEsR0FBWkEsYUFBQSxDQUFjd0MsT0FBTyxjQUFBeEMsYUFBQSxnQkFBQUEsYUFBQSxHQUFyQkEsYUFBQSxDQUF1QnlDLFdBQVcsY0FBQXpDLGFBQUEsZ0JBQUFBLGFBQUEsR0FBbENBLGFBQUEsQ0FBb0MwQyxTQUFTLGNBQUExQyxhQUFBLHVCQUE3Q0EsYUFBQSxDQUErQzJDLE1BQU0sQ0FBQyxFQUM5RCxJQUFBNUIsc0JBQUssRUFBQyxTQUFTLENBQUMsQ0FDZCxJQUFBQyx1QkFBTSxFQUFDNEIsd0NBQThCLEVBQUUsSUFBQVAseUJBQVEsRUFBQztJQUFDUSxPQUFPLEVBQUUsV0FBVztJQUFFQyxLQUFLLEVBQUU7RUFBQyxDQUFDLENBQUMsQ0FDbkYsQ0FDRixDQUFDLEVBRUQsSUFBQWYsb0JBQUcsRUFDREMsT0FBTyxFQUFBL0IsY0FBQSxHQUFDaUIsWUFBWSxjQUFBakIsY0FBQSxnQkFBQUEsY0FBQSxHQUFaQSxjQUFBLENBQWN1QyxPQUFPLGNBQUF2QyxjQUFBLGdCQUFBQSxjQUFBLEdBQXJCQSxjQUFBLENBQXVCd0MsV0FBVyxjQUFBeEMsY0FBQSxnQkFBQUEsY0FBQSxHQUFsQ0EsY0FBQSxDQUFvQ3lDLFNBQVMsY0FBQXpDLGNBQUEsdUJBQTdDQSxjQUFBLENBQStDOEMsUUFBUSxDQUFDLEVBQ2hFLElBQUFoQyxzQkFBSyxFQUFDLFNBQVMsQ0FBQyxDQUNkLElBQUFDLHVCQUFNLEVBQ0pnQyw2Q0FBbUMsRUFDbkMsSUFBQVgseUJBQVEsRUFBQztJQUNQUSxPQUFPLEVBQUUsV0FBVztJQUNwQkUsUUFBUSxHQUFBN0MscUJBQUEsSUFBQUMsY0FBQSxHQUFFZSxZQUFZLGNBQUFmLGNBQUEsZ0JBQUFBLGNBQUEsR0FBWkEsY0FBQSxDQUFjcUMsT0FBTyxjQUFBckMsY0FBQSxnQkFBQUEsY0FBQSxHQUFyQkEsY0FBQSxDQUF1QnNDLFdBQVcsY0FBQXRDLGNBQUEsZ0JBQUFBLGNBQUEsR0FBbENBLGNBQUEsQ0FBb0N1QyxTQUFTLGNBQUF2QyxjQUFBLHVCQUE3Q0EsY0FBQSxDQUErQzRDLFFBQVEsY0FBQTdDLHFCQUFBLGNBQUFBLHFCQUFBLEdBQUksQ0FBQztFQUN4RSxDQUFDLENBQ0gsQ0FDRixDQUNGLENBQUMsRUFDRCxJQUFBYSxzQkFBSyxFQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUFDLHVCQUFNLEVBQUNpQyxtQ0FBa0IsRUFBRSxJQUFBWix5QkFBUSxFQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFDNUQsSUFBQXRCLHNCQUFLLEVBQUMsU0FBUyxDQUFDLENBQ2QsSUFBQW1DLHVCQUFNLEVBQ0pwRixNQUFNLENBQUNxRixTQUFTLENBQUNDLGNBQWMsQ0FBQ0MsSUFBSSxDQUFDOUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxHQUNyRDtJQUFDK0MsUUFBUSxFQUFFL0MsT0FBTyxDQUFDK0M7RUFBUSxDQUFDLEdBQzVCLENBQUMsQ0FDUCxDQUNGLENBQUMsQ0FDRixDQUFDLENBQUMzRCxLQUFLLENBQUM7QUFDWCxDQUFDO0FBRU0sSUFBTTRELHVCQUF1QixHQUFBdEUsT0FBQSxDQUFBc0UsdUJBQUEsR0FBRyxTQUExQkEsdUJBQXVCQSxDQUNsQzVELEtBQW9CLEVBQ3BCNkQsTUFBcUMsRUFDbkI7RUFDbEI7RUFDQSxJQUFNQyxRQUFRLEdBQUcsSUFBQUMsdUJBQWtCLEVBQUNGLE1BQU0sQ0FBQ0csTUFBTSxDQUFDO0VBQ2xELElBQU1DLFNBQVMsR0FBRyxJQUFBOUMseUJBQVEsRUFBQyxDQUN6QixJQUFBQyxzQkFBSyxFQUFDLFVBQVUsQ0FBQyxDQUNmLElBQUFtQyx1QkFBTSxFQUFDO0lBQ0xXLFdBQVcsRUFBRSxLQUFLO0lBQ2xCQyxtQkFBbUIsRUFBRSxDQUFDO0VBQ3hCLENBQUMsQ0FDSCxDQUFDLENBQ0YsQ0FBQyxDQUFDbkUsS0FBSyxDQUFDO0VBQ1Q7RUFDQSxJQUFNb0UsYUFBYSxHQUFHLElBQUFqRCx5QkFBUSxFQUFDMkMsUUFBUSxDQUFDTyxHQUFHLENBQUMsVUFBQUMsQ0FBQztJQUFBLE9BQUksSUFBQWpELHVCQUFNLEVBQUN0QixtQkFBbUIsRUFBRSxJQUFBMkMseUJBQVEsRUFBQzRCLENBQUMsQ0FBQyxDQUFDO0VBQUEsRUFBQyxDQUFDLENBQ3pGTCxTQUNGLENBQUM7RUFDRCxPQUFPRyxhQUFhO0FBQ3RCLENBQUM7QUFFTSxJQUFNRyxvQkFBb0IsR0FBQWpGLE9BQUEsQ0FBQWlGLG9CQUFBLEdBQUd4RSxtQkFBbUI7O0FBRXZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBTXlFLHFCQUFxQixHQUFHLFNBQXhCQSxxQkFBcUJBLENBQUdDLGVBQWU7RUFBQSxPQUFJL