UNPKG

kepler.gl

Version:

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

810 lines (713 loc) 60.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.layerConfigChange = layerConfigChange; exports.layerTextLabelChange = layerTextLabelChange; exports.layerTypeChange = layerTypeChange; exports.layerVisualChannelConfigChange = layerVisualChannelConfigChange; exports.layerVisConfigChange = layerVisConfigChange; exports.layerColorUIChange = layerColorUIChange; exports.updateLayerBlending = updateLayerBlending; exports.interactionConfigChange = interactionConfigChange; exports.setFilter = setFilter; exports.addFilter = addFilter; exports.addLayer = addLayer; exports.reorderLayer = reorderLayer; exports.removeFilter = removeFilter; exports.removeLayer = removeLayer; exports.removeDataset = removeDataset; exports.showDatasetTable = showDatasetTable; exports.sortTableColumn = sortTableColumn; exports.pinTableColumn = pinTableColumn; exports.copyTableColumn = copyTableColumn; exports.updateVisData = updateVisData; exports.toggleFilterAnimation = toggleFilterAnimation; exports.updateFilterAnimationSpeed = updateFilterAnimationSpeed; exports.updateAnimationTime = updateAnimationTime; exports.updateLayerAnimationSpeed = updateLayerAnimationSpeed; exports.enlargeFilter = enlargeFilter; exports.toggleFilterFeature = toggleFilterFeature; exports.onLayerHover = onLayerHover; exports.onLayerClick = onLayerClick; exports.onMapClick = onMapClick; exports.onMouseMove = onMouseMove; exports.toggleLayerForMap = toggleLayerForMap; exports.setFilterPlot = setFilterPlot; exports.setMapInfo = setMapInfo; exports.loadFiles = loadFiles; exports.loadNextFile = loadNextFile; exports.loadFileSuccess = loadFileSuccess; exports.loadFilesErr = loadFilesErr; exports.setFeatures = setFeatures; exports.setPolygonFilterLayer = setPolygonFilterLayer; exports.setSelectedFeature = setSelectedFeature; exports.deleteFeature = deleteFeature; exports.setEditorMode = setEditorMode; exports.applyCPUFilter = applyCPUFilter; exports.toggleEditorVisibility = toggleEditorVisibility; var _actionTypes = _interopRequireDefault(require("../constants/action-types")); // Copyright (c) 2020 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // vis-state-reducer /** * Update layer base config: dataId, label, column, isVisible * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {Object} newConfig - new config * @returns {{type: ActionTypes.LAYER_CONFIG_CHANGE, oldLayer: oldLayer, newConfig: newConfig}} * @public */ function layerConfigChange(oldLayer, newConfig) { return { type: _actionTypes["default"].LAYER_CONFIG_CHANGE, oldLayer: oldLayer, newConfig: newConfig }; } /** * Update layer text label * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {Number} idx -`idx` of text label to be updated * @param {string} prop - `prop` of text label, e,g, `anchor`, `alignment`, `color`, `size`, `field` * @param {*} value - new value * @returns {{type: ActionTypes.LAYER_TEXT_LABEL_CHANGE, oldLayer: oldLayer, idx: idx, prop: prop, value:}} * @public */ function layerTextLabelChange(oldLayer, idx, prop, value) { return { type: _actionTypes["default"].LAYER_TEXT_LABEL_CHANGE, oldLayer: oldLayer, idx: idx, prop: prop, value: value }; } /** * Update layer type. Previews layer config will be copied if applicable. * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {string} newType - new type * @returns {{type: ActionTypes.LAYER_TYPE_CHANGE, oldLayer: oldLayer, newType: newType}} * @public */ function layerTypeChange(oldLayer, newType) { return { type: _actionTypes["default"].LAYER_TYPE_CHANGE, oldLayer: oldLayer, newType: newType }; } /** * Update layer visual channel * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {Object} newConfig - new visual channel config * @param {string} channel - channel to be updated * @returns {{type: ActionTypes.LAYER_VISUAL_CHANNEL_CHANGE, oldLayer: oldLayer, newConfig: newConfig, channel: channel}} * @public */ function layerVisualChannelConfigChange(oldLayer, newConfig, channel) { return { type: _actionTypes["default"].LAYER_VISUAL_CHANNEL_CHANGE, oldLayer: oldLayer, newConfig: newConfig, channel: channel }; } /** * Update layer `visConfig` * @memberof visStateActions * @param {Object} oldLayer - layer to be updated * @param {Object} newVisConfig - new visConfig as a key value map: e.g. `{opacity: 0.8}` * @returns {{type: ActionTypes.LAYER_VIS_CONFIG_CHANGE, oldLayer: oldLayer, newVisConfig: newVisConfig}} * @public */ function layerVisConfigChange(oldLayer, newVisConfig) { return { type: _actionTypes["default"].LAYER_VIS_CONFIG_CHANGE, oldLayer: oldLayer, newVisConfig: newVisConfig }; } /** * Set the color palette ui for layer color * @memberOf visStateActions * @param {Object} oldLayer - layer to be updated * @param {String} prop - which color prop * @param {object} newConfig - to be merged * @public */ function layerColorUIChange(oldLayer, prop, newConfig) { return { type: _actionTypes["default"].LAYER_COLOR_UI_CHANGE, oldLayer: oldLayer, prop: prop, newConfig: newConfig }; } /** * Update layer blending mode * @memberof visStateActions * @param {string} mode one of `additive`, `normal` and `subtractive` * @returns {{type: ActionTypes.UPDATE_LAYER_BLENDING, mode: mode}} * @public */ function updateLayerBlending(mode) { return { type: _actionTypes["default"].UPDATE_LAYER_BLENDING, mode: mode }; } /** * Update `interactionConfig` * @memberof visStateActions * @param {Object} config - new config as key value map: `{tooltip: {enabled: true}}` * @returns {{type: ActionTypes.INTERACTION_CONFIG_CHANGE, config: config}} * @public */ function interactionConfigChange(config) { return { type: _actionTypes["default"].INTERACTION_CONFIG_CHANGE, config: config }; } /** * Update filter property * @memberof visStateActions * @param {Number} idx -`idx` of filter to be updated * @param {string} prop - `prop` of filter, e,g, `dataId`, `name`, `value` * @param {*} value - new value * @param {Number} valueIndex - array properties like dataset require index in order to improve performance * @returns {{type: ActionTypes.SET_FILTER, idx: idx, prop: prop, value: value}} * @public */ function setFilter(idx, prop, value, valueIndex) { return { type: _actionTypes["default"].SET_FILTER, idx: idx, prop: prop, value: value, valueIndex: valueIndex }; } /** * Add a new filter * @memberof visStateActions * @param {string} dataId - dataset `id` this new filter is associated with * @returns {{type: ActionTypes.ADD_FILTER, dataId: dataId}} * @public */ function addFilter(dataId) { return { type: _actionTypes["default"].ADD_FILTER, dataId: dataId }; } /** * Add a new layer * @memberof visStateActions * @param {Object} props - new layer props * @returns {{type: ActionTypes.ADD_LAYER, props: props}} * @public */ function addLayer(props) { return { type: _actionTypes["default"].ADD_LAYER, props: props }; } /** * Reorder layer, order is an array of layer indexes, index 0 will be the one at the bottom * @memberof visStateActions * @param {Array<Number>} order an array of layer indexes * @returns {{type: ActionTypes.REORDER_LAYER, order: order}} * @public * @example * * // bring `layers[1]` below `layers[0]`, the sequence layers will be rendered is `1`, `0`, `2`, `3`. * // `1` will be at the bottom, `3` will be at the top. * this.props.dispatch(reorderLayer([1, 0, 2, 3])); */ function reorderLayer(order) { return { type: _actionTypes["default"].REORDER_LAYER, order: order }; } /** * Remove a filter from `visState.filters`, once a filter is removed, data will be re-filtered and layer will be updated * @memberof visStateActions * @param {Number} idx idx of filter to be removed * @returns {{type: ActionTypes.REMOVE_FILTER, idx: idx}} * @public */ function removeFilter(idx) { return { type: _actionTypes["default"].REMOVE_FILTER, idx: idx }; } /** * Remove a layer * @memberof visStateActions * @param {Number} idx idx of layer to be removed * @returns {{type: ActionTypes.REMOVE_LAYER, idx: idx}} * @public */ function removeLayer(idx) { return { type: _actionTypes["default"].REMOVE_LAYER, idx: idx }; } /** * Remove a dataset and all layers, filters, tooltip configs that based on it * @memberof visStateActions * @param {string} key dataset id * @returns {{type: ActionTypes.REMOVE_DATASET, key: key}} * @public */ function removeDataset(key) { return { type: _actionTypes["default"].REMOVE_DATASET, key: key }; } /** * Display dataset table in a modal * @memberof visStateActions * @param {string} dataId dataset id to show in table * @returns {{type: ActionTypes.SHOW_DATASET_TABLE, dataId: dataId}} * @public */ function showDatasetTable(dataId) { return { type: _actionTypes["default"].SHOW_DATASET_TABLE, dataId: dataId }; } /** * Sort dataset column, for table display * @param {string} dataId * @param {string} column * @param {string} mode */ function sortTableColumn(dataId, column, mode) { return { type: _actionTypes["default"].SORT_TABLE_COLUMN, dataId: dataId, column: column, mode: mode }; } /** * Pin dataset column, for table display * @param {string} dataId * @param {string} column */ function pinTableColumn(dataId, column) { return { type: _actionTypes["default"].PIN_TABLE_COLUMN, dataId: dataId, column: column }; } /** * Copy column, for table display * @param {string} dataId * @param {string} column */ function copyTableColumn(dataId, column) { return { type: _actionTypes["default"].COPY_TABLE_COLUMN, dataId: dataId, column: column }; } /** * Add new dataset to `visState`, with option to load a map config along with the datasets * @memberof visStateActions * @param {Array<Object>|Object} datasets - ***required** datasets can be a dataset or an array of datasets * Each dataset object needs to have `info` and `data` property. * @param {Object} datasets.info -info of a dataset * @param {string} datasets.info.id - id of this dataset. If config is defined, `id` should matches the `dataId` in config. * @param {string} datasets.info.label - A display name of this dataset * @param {Object} datasets.data - ***required** The data object, in a tabular format with 2 properties `fields` and `rows` * @param {Array<Object>} datasets.data.fields - ***required** Array of fields, * @param {string} datasets.data.fields.name - ***required** Name of the field, * @param {Array<Array>} datasets.data.rows - ***required** Array of rows, in a tabular format with `fields` and `rows` * @param {Object} options * @param {boolean} options.centerMap `default: true` if `centerMap` is set to `true` kepler.gl will * place the map view within the data points boundaries * @param {boolean} options.readOnly `default: false` if `readOnly` is set to `true` * the left setting panel will be hidden * @param {Object} config this object will contain the full kepler.gl instance configuration {mapState, mapStyle, visState} * @returns {{type: ActionTypes.UPDATE_VIS_DATA, datasets: datasets, options: options, config: config}} * @public */ function updateVisData(datasets, options, config) { return { type: _actionTypes["default"].UPDATE_VIS_DATA, datasets: datasets, options: options, config: config }; } /** * Start and end filter animation * @memberof visStateActions * @param {Number} idx - idx of filter * @returns {{type: ActionTypes.TOGGLE_FILTER_ANIMATION, idx: idx}} * @public */ function toggleFilterAnimation(idx) { return { type: _actionTypes["default"].TOGGLE_FILTER_ANIMATION, idx: idx }; } /** * Change filter animation speed * @memberof visStateActions * @param {Number} idx - `idx` of filter * @param {Number} speed - `speed` to change it to. `speed` is a multiplier * @returns {{type: ActionTypes.UPDATE_FILTER_ANIMATION_SPEED, idx: idx, speed: speed}} * @public */ function updateFilterAnimationSpeed(idx, speed) { return { type: _actionTypes["default"].UPDATE_FILTER_ANIMATION_SPEED, idx: idx, speed: speed }; } /** * Reset animation * @memberof visStateActions * @param {Number} value - Current value of the slider * @returns {{type: ActionTypes.UPDATE_ANIMATION_TIME, value: value}} * @public */ function updateAnimationTime(value) { return { type: _actionTypes["default"].UPDATE_ANIMATION_TIME, value: value }; } /** * update trip layer animation speed * @memberof visStateActions * @param {Number} speed - `speed` to change it to. `speed` is a multiplier * @returns {{type: ActionTypes.UPDATE_LAYER_ANIMATION_SPEED, speed: speed}} * @public */ function updateLayerAnimationSpeed(speed) { return { type: _actionTypes["default"].UPDATE_LAYER_ANIMATION_SPEED, speed: speed }; } /** * Show larger time filter at bottom for time playback (apply to time filter only) * @memberof visStateActions * @param {Number} idx - index of filter to enlarge * @returns {{type: ActionTypes.ENLARGE_FILTER, idx: idx}} * @public */ function enlargeFilter(idx) { return { type: _actionTypes["default"].ENLARGE_FILTER, idx: idx }; } /** * Show/hide filter feature on map * @memberof visStateActions * @param {Number} idx - index of filter feature to show/hide * @return {{type: ActionTypes.TOGGLE_FILTER_FEATURE, idx: idx}} */ function toggleFilterFeature(idx) { return { type: _actionTypes["default"].TOGGLE_FILTER_FEATURE, idx: idx }; } /** * Trigger layer hover event with hovered object * @memberof visStateActions * @param {Object} info - Object hovered, returned by deck.gl * @returns {{type: ActionTypes.LAYER_HOVER, info: info}} * @public */ function onLayerHover(info) { return { type: _actionTypes["default"].LAYER_HOVER, info: info }; } /** * Trigger layer click event with clicked object * @memberof visStateActions * @param {Object} info - Object clicked, returned by deck.gl * @returns {{type: ActionTypes.LAYER_CLICK, info: info}} * @public */ function onLayerClick(info) { return { type: _actionTypes["default"].LAYER_CLICK, info: info }; } /** * Trigger map click event, unselect clicked object * @memberof visStateActions * @returns {{type: ActionTypes.MAP_CLICK}} * @public */ function onMapClick() { return { type: _actionTypes["default"].MAP_CLICK }; } /** * Trigger map mouse moveevent, payload would be * React-map-gl PointerEvent * https://uber.github.io/react-map-gl/#/documentation/api-reference/pointer-event * * @memberof visStateActions * @param {Object} evt - PointerEvent * @returns {{type: ActionTypes.MAP_CLICK}} * @public */ function onMouseMove(evt) { return { type: _actionTypes["default"].MOUSE_MOVE, evt: evt }; } /** * Toggle visibility of a layer in a split map * @memberof visStateActions * @param {Number} mapIndex - index of the split map * @param {string} layerId - id of the layer * @returns {{type: ActionTypes.TOGGLE_LAYER_FOR_MAP, mapIndex: *, layerId: *}} * @public */ function toggleLayerForMap(mapIndex, layerId) { return { type: _actionTypes["default"].TOGGLE_LAYER_FOR_MAP, mapIndex: mapIndex, layerId: layerId }; } /** * Set the property of a filter plot * @memberof visStateActions * @param {Number} idx * @param {Object} newProp key value mapping of new prop `{yAxis: 'histogram'}` * @returns {{type: ActionTypes.SET_FILTER_PLOT, idx: *, newProp: *}} * @public */ function setFilterPlot(idx, newProp) { return { type: _actionTypes["default"].SET_FILTER_PLOT, idx: idx, newProp: newProp }; } /** * Set the property of a filter plot * @memberof visStateActions * @param {Number} idx * @param {Object} newProp key value mapping of new prop `{yAxis: 'histogram'}` * @returns {{type: ActionTypes.SET_FILTER_PLOT, idx: *, newProp: *}} * @public */ function setMapInfo(info) { return { type: _actionTypes["default"].SET_MAP_INFO, info: info }; } /** * Trigger file loading dispatch `addDataToMap` if succeed, or `loadFilesErr` if failed * @memberof visStateActions * @param {Array<Object>} files array of fileblob * @returns {{type: ActionTypes.LOAD_FILES, files: *}} * @public */ function loadFiles(files) { return { type: _actionTypes["default"].LOAD_FILES, files: files }; } /** * called with next file to load * @param {object} payload * @param {Array<object>} payload.fileCache * @param {Array<object>} payload.filesToLoad * @param {number} payload.totalCount * @param {Function} payload.onFinish - action creator to execute when all files are loaded */ function loadNextFile(_ref) { var fileCache = _ref.fileCache, filesToLoad = _ref.filesToLoad, totalCount = _ref.totalCount, onFinish = _ref.onFinish; return { type: _actionTypes["default"].LOAD_NEXT_FILE, fileCache: fileCache, filesToLoad: filesToLoad, totalCount: totalCount, onFinish: onFinish }; } /** * called when all files are processed and loaded * @param {Array<object>} result */ function loadFileSuccess(result) { return { type: _actionTypes["default"].LOAD_FILES_SUCCESS, result: result }; } /** * Trigger loading file error * @memberof visStateActions * @param {*} error * @returns {{type: ActionTypes.LOAD_FILES_ERR, error: Object}} * @public */ function loadFilesErr(error) { return { type: _actionTypes["default"].LOAD_FILES_ERR, error: error }; } /** * Store features to state * @memberof visStateActions * @param {Array<Object>} features * @returns {{type: ActionTypes.SET_FEATURES, features: Object}} */ function setFeatures(features) { return { type: _actionTypes["default"].SET_FEATURES, features: features }; } /** * It will apply the provide feature as filter to the given layer. * If the given feature is already applied as filter to the layer, it will remove the layer from the filter * @memberof visStateActions * @param {Object} layer * @param {Object} feature * @return {{feature: *, type: ActionTypes.SET_POLYGON_FILTER_LAYER, layer: *}} */ function setPolygonFilterLayer(layer, feature) { return { type: _actionTypes["default"].SET_POLYGON_FILTER_LAYER, layer: layer, feature: feature }; } /** * Set the current feature to be edited/deleted * @memberof visStateActions * @param {Object} feature * @return {{feature: feature, type: ActionTypes.SET_SELECTED_FEATURE}} */ function setSelectedFeature(feature) { return { type: _actionTypes["default"].SET_SELECTED_FEATURE, feature: feature }; } /** * Delete the given feature * @memberof visStateActions * @param {Object} feature * @return {{type: ActionTypes.DELETE_FEATURE, feature: feature}} */ function deleteFeature(feature) { return { type: _actionTypes["default"].DELETE_FEATURE, feature: feature }; } /** Set the map mode * @memberof visStateActions * @param {string} mode one of EDITOR_MODES * @return {{type: ActionTypes. SET_EDITOR_MODE, mode: *}} * @public * @example * import {setMapMode} from 'kepler.gl/actions'; * import {EDITOR_MODES} from 'kepler.gl/constants'; * * this.props.dispatch(setMapMode(EDITOR_MODES.DRAW_POLYGON)); */ function setEditorMode(mode) { return { type: _actionTypes["default"].SET_EDITOR_MODE, mode: mode }; } /** * Trigger CPU filter of selected dataset * @memberof visStateActions * @param {string | Arrary<string>} dataId - single dataId or an array of dataIds * @returns {{type: ActionTypes.APPLY_CPU_FILTER, dataId: string}} * @public */ function applyCPUFilter(dataId) { return { type: _actionTypes["default"].APPLY_CPU_FILTER, dataId: dataId }; } /** * Toggle editor layer visibility * @memberof visStateActions * @return {{type: ActionTypes.TOGGLE_EDITOR_VISIBILITY}} */ function toggleEditorVisibility() { return { type: _actionTypes["default"].TOGGLE_EDITOR_VISIBILITY }; } /** * This declaration is needed to group actions in docs */ /** * Actions handled mostly by `visState` reducer. * They manage how data is processed, filtered and displayed on the map by operates on layers, * filters and interaction settings. * * @public */ /* eslint-disable no-unused-vars */ var visStateActions = null; /* eslint-enable no-unused-vars */ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hY3Rpb25zL3Zpcy1zdGF0ZS1hY3Rpb25zLmpzIl0sIm5hbWVzIjpbImxheWVyQ29uZmlnQ2hhbmdlIiwib2xkTGF5ZXIiLCJuZXdDb25maWciLCJ0eXBlIiwiQWN0aW9uVHlwZXMiLCJMQVlFUl9DT05GSUdfQ0hBTkdFIiwibGF5ZXJUZXh0TGFiZWxDaGFuZ2UiLCJpZHgiLCJwcm9wIiwidmFsdWUiLCJMQVlFUl9URVhUX0xBQkVMX0NIQU5HRSIsImxheWVyVHlwZUNoYW5nZSIsIm5ld1R5cGUiLCJMQVlFUl9UWVBFX0NIQU5HRSIsImxheWVyVmlzdWFsQ2hhbm5lbENvbmZpZ0NoYW5nZSIsImNoYW5uZWwiLCJMQVlFUl9WSVNVQUxfQ0hBTk5FTF9DSEFOR0UiLCJsYXllclZpc0NvbmZpZ0NoYW5nZSIsIm5ld1Zpc0NvbmZpZyIsIkxBWUVSX1ZJU19DT05GSUdfQ0hBTkdFIiwibGF5ZXJDb2xvclVJQ2hhbmdlIiwiTEFZRVJfQ09MT1JfVUlfQ0hBTkdFIiwidXBkYXRlTGF5ZXJCbGVuZGluZyIsIm1vZGUiLCJVUERBVEVfTEFZRVJfQkxFTkRJTkciLCJpbnRlcmFjdGlvbkNvbmZpZ0NoYW5nZSIsImNvbmZpZyIsIklOVEVSQUNUSU9OX0NPTkZJR19DSEFOR0UiLCJzZXRGaWx0ZXIiLCJ2YWx1ZUluZGV4IiwiU0VUX0ZJTFRFUiIsImFkZEZpbHRlciIsImRhdGFJZCIsIkFERF9GSUxURVIiLCJhZGRMYXllciIsInByb3BzIiwiQUREX0xBWUVSIiwicmVvcmRlckxheWVyIiwib3JkZXIiLCJSRU9SREVSX0xBWUVSIiwicmVtb3ZlRmlsdGVyIiwiUkVNT1ZFX0ZJTFRFUiIsInJlbW92ZUxheWVyIiwiUkVNT1ZFX0xBWUVSIiwicmVtb3ZlRGF0YXNldCIsImtleSIsIlJFTU9WRV9EQVRBU0VUIiwic2hvd0RhdGFzZXRUYWJsZSIsIlNIT1dfREFUQVNFVF9UQUJMRSIsInNvcnRUYWJsZUNvbHVtbiIsImNvbHVtbiIsIlNPUlRfVEFCTEVfQ09MVU1OIiwicGluVGFibGVDb2x1bW4iLCJQSU5fVEFCTEVfQ09MVU1OIiwiY29weVRhYmxlQ29sdW1uIiwiQ09QWV9UQUJMRV9DT0xVTU4iLCJ1cGRhdGVWaXNEYXRhIiwiZGF0YXNldHMiLCJvcHRpb25zIiwiVVBEQVRFX1ZJU19EQVRBIiwidG9nZ2xlRmlsdGVyQW5pbWF0aW9uIiwiVE9HR0xFX0ZJTFRFUl9BTklNQVRJT04iLCJ1cGRhdGVGaWx0ZXJBbmltYXRpb25TcGVlZCIsInNwZWVkIiwiVVBEQVRFX0ZJTFRFUl9BTklNQVRJT05fU1BFRUQiLCJ1cGRhdGVBbmltYXRpb25UaW1lIiwiVVBEQVRFX0FOSU1BVElPTl9USU1FIiwidXBkYXRlTGF5ZXJBbmltYXRpb25TcGVlZCIsIlVQREFURV9MQVlFUl9BTklNQVRJT05fU1BFRUQiLCJlbmxhcmdlRmlsdGVyIiwiRU5MQVJHRV9GSUxURVIiLCJ0b2dnbGVGaWx0ZXJGZWF0dXJlIiwiVE9HR0xFX0ZJTFRFUl9GRUFUVVJFIiwib25MYXllckhvdmVyIiwiaW5mbyIsIkxBWUVSX0hPVkVSIiwib25MYXllckNsaWNrIiwiTEFZRVJfQ0xJQ0siLCJvbk1hcENsaWNrIiwiTUFQX0NMSUNLIiwib25Nb3VzZU1vdmUiLCJldnQiLCJNT1VTRV9NT1ZFIiwidG9nZ2xlTGF5ZXJGb3JNYXAiLCJtYXBJbmRleCIsImxheWVySWQiLCJUT0dHTEVfTEFZRVJfRk9SX01BUCIsInNldEZpbHRlclBsb3QiLCJuZXdQcm9wIiwiU0VUX0ZJTFRFUl9QTE9UIiwic2V0TWFwSW5mbyIsIlNFVF9NQVBfSU5GTyIsImxvYWRGaWxlcyIsImZpbGVzIiwiTE9BRF9GSUxFUyIsImxvYWROZXh0RmlsZSIsImZpbGVDYWNoZSIsImZpbGVzVG9Mb2FkIiwidG90YWxDb3VudCIsIm9uRmluaXNoIiwiTE9BRF9ORVhUX0ZJTEUiLCJsb2FkRmlsZVN1Y2Nlc3MiLCJyZXN1bHQiLCJMT0FEX0ZJTEVTX1NVQ0NFU1MiLCJsb2FkRmlsZXNFcnIiLCJlcnJvciIsIkxPQURfRklMRVNfRVJSIiwic2V0RmVhdHVyZXMiLCJmZWF0dXJlcyIsIlNFVF9GRUFUVVJFUyIsInNldFBvbHlnb25GaWx0ZXJMYXllciIsImxheWVyIiwiZmVhdHVyZSIsIlNFVF9QT0xZR09OX0ZJTFRFUl9MQVlFUiIsInNldFNlbGVjdGVkRmVhdHVyZSIsIlNFVF9TRUxFQ1RFRF9GRUFUVVJFIiwiZGVsZXRlRmVhdHVyZSIsIkRFTEVURV9GRUFUVVJFIiwic2V0RWRpdG9yTW9kZSIsIlNFVF9FRElUT1JfTU9ERSIsImFwcGx5Q1BVRmlsdGVyIiwiQVBQTFlfQ1BVX0ZJTFRFUiIsInRvZ2dsZUVkaXRvclZpc2liaWxpdHkiLCJUT0dHTEVfRURJVE9SX1ZJU0lCSUxJVFkiLCJ2aXNTdGF0ZUFjdGlvbnMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFxQkE7O0FBckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBR0E7Ozs7Ozs7O0FBUU8sU0FBU0EsaUJBQVQsQ0FBMkJDLFFBQTNCLEVBQXFDQyxTQUFyQyxFQUFnRDtBQUNyRCxTQUFPO0FBQ0xDLElBQUFBLElBQUksRUFBRUMsd0JBQVlDLG1CQURiO0FBRUxKLElBQUFBLFFBQVEsRUFBUkEsUUFGSztBQUdMQyxJQUFBQSxTQUFTLEVBQVRBO0FBSEssR0FBUDtBQUtEO0FBRUQ7Ozs7Ozs7Ozs7OztBQVVPLFNBQVNJLG9CQUFULENBQThCTCxRQUE5QixFQUF3Q00sR0FBeEMsRUFBNkNDLElBQTdDLEVBQW1EQyxLQUFuRCxFQUEwRDtBQUMvRCxTQUFPO0FBQ0xOLElBQUFBLElBQUksRUFBRUMsd0JBQVlNLHVCQURiO0FBRUxULElBQUFBLFFBQVEsRUFBUkEsUUFGSztBQUdMTSxJQUFBQSxHQUFHLEVBQUhBLEdBSEs7QUFJTEMsSUFBQUEsSUFBSSxFQUFKQSxJQUpLO0FBS0xD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Ozs7Ozs7Ozs7O0FBV08sU0FBU00sYUFBVCxDQUF1Qi9GLElBQXZCLEVBQTZCO0FBQ2xDLFNBQU87QUFDTHBCLElBQUFBLElBQUksRUFBRUMsd0JBQVltSCxlQURiO0FBRUxoRyxJQUFBQSxJQUFJLEVBQUpBO0FBRkssR0FBUDtBQUlEO0FBRUQ7Ozs7Ozs7OztBQU9PLFNBQVNpRyxjQUFULENBQXdCeEYsTUFBeEIsRUFBZ0M7QUFDckMsU0FBTztBQUNMN0IsSUFBQUEsSUFBSSxFQUFFQyx3QkFBWXFILGdCQURiO0FBRUx6RixJQUFBQSxNQUFNLEVBQU5BO0FBRkssR0FBUDtBQUlEO0FBRUQ7Ozs7Ozs7O0FBTU8sU0FBUzBGLHNCQUFULEdBQWtDO0FBQ3ZDLFNBQU87QUFDTHZILElBQUFBLElBQUksRUFBRUMsd0JBQVl1SDtBQURiLEdBQVA7QUFHRDtBQUVEOzs7O0FBR0E7Ozs7Ozs7O0FBT0E7OztBQUNBLElBQU1DLGVBQWUsR0FBRyxJQUF4QjtBQUNBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDIwIFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuLy8gdmlzLXN0YXRlLXJlZHVjZXJcbmltcG9ydCBBY3Rpb25UeXBlcyBmcm9tICdjb25zdGFudHMvYWN0aW9uLXR5cGVzJztcblxuLyoqXG4gKiBVcGRhdGUgbGF5ZXIgYmFzZSBjb25maWc6IGRhdGFJZCwgbGFiZWwsIGNvbHVtbiwgaXNWaXNpYmxlXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVBY3Rpb25zXG4gKiBAcGFyYW0ge09iamVjdH0gb2xkTGF5ZXIgLSBsYXllciB0byBiZSB1cGRhdGVkXG4gKiBAcGFyYW0ge09iamVjdH0gbmV3Q29uZmlnIC0gbmV3IGNvbmZpZ1xuICogQHJldHVybnMge3t0eXBlOiBBY3Rpb25UeXBlcy5MQVlFUl9DT05GSUdfQ0hBTkdFLCBvbGRMYXllcjogb2xkTGF5ZXIsIG5ld0NvbmZpZzogbmV3Q29uZmlnfX1cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxheWVyQ29uZmlnQ2hhbmdlKG9sZExheWVyLCBuZXdDb25maWcpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBBY3Rpb25UeXBlcy5MQVlFUl9DT05GSUdfQ0hBTkdFLFxuICAgIG9sZExheWVyLFxuICAgIG5ld0NvbmZpZ1xuICB9O1xufVxuXG4vKipcbiAqIFVwZGF0ZSBsYXllciB0ZXh0IGxhYmVsXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVBY3Rpb25zXG4gKiBAcGFyYW0ge09iamVjdH0gb2xkTGF5ZXIgLSBsYXllciB0byBiZSB1cGRhdGVkXG4gKiBAcGFyYW0ge051bWJlcn0gaWR4IC1gaWR4YCBvZiB0ZXh0IGxhYmVsIHRvIGJlIHVwZGF0ZWRcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wIC0gYHByb3BgIG9mIHRleHQgbGFiZWwsIGUsZywgYGFuY2hvcmAsIGBhbGlnbm1lbnRgLCBgY29sb3JgLCBgc2l6ZWAsIGBmaWVsZGBcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgLSBuZXcgdmFsdWVcbiAqIEByZXR1cm5zIHt7dHlwZTogQWN0aW9uVHlwZXMuTEFZRVJfVEVYVF9MQUJFTF9DSEFOR0UsIG9sZExheWVyOiBvbGRMYXllciwgaWR4OiBpZHgsIHByb3A6IHByb3AsIHZhbHVlOn19XG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYXllclRleHRMYWJlbENoYW5nZShvbGRMYXllciwgaWR4LCBwcm9wLCB2YWx1ZSkge1xuICByZXR1cm4ge1xuICAgIHR5cGU6IEFjdGlvblR5cGVzLkxBWUVSX1RFWFRfTEFCRUxfQ0hBTkdFLFxuICAgIG9sZExheWVyLFxuICAgIGlkeCxcbiAgICBwcm9wLFxuICAgIHZhbHVlXG4gIH07XG59XG5cbi8qKlxuICogVXBkYXRlIGxheWVyIHR5cGUuIFByZXZpZXdzIGxheWVyIGNvbmZpZyB3aWxsIGJlIGNvcGllZCBpZiBhcHBsaWNhYmxlLlxuICogQG1lbWJlcm9mIHZpc1N0YXRlQWN0aW9uc1xuICogQHBhcmFtIHtPYmplY3R9IG9sZExheWVyIC0gbGF5ZXIgdG8gYmUgdXBkYXRlZFxuICogQHBhcmFtIHtzdHJpbmd9IG5ld1R5cGUgLSBuZXcgdHlwZVxuICogQHJldHVybnMge3t0eXBlOiBBY3Rpb25UeXBlcy5MQVlFUl9UWVBFX0NIQU5HRSwgb2xkTGF5ZXI6IG9sZExheWVyLCBuZXdUeXBlOiBuZXdUeXBlfX1cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxheWVyVHlwZUNoYW5nZShvbGRMYXllciwgbmV3VHlwZSkge1xuICByZXR1cm4ge1xuICAgIHR5cGU6IEFjdGlvblR5cGVzLkxBWUVSX1RZUEVfQ0hBTkdFLFxuICAgIG9sZExheWVyLFxuICAgIG5ld1R5cGVcbiAgfTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgbGF5ZXIgdmlzdWFsIGNoYW5uZWxcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZUFjdGlvbnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBvbGRMYXllciAtIGxheWVyIHRvIGJlIHVwZGF0ZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBuZXdDb25maWcgLSBuZXcgdmlzdWFsIGNoYW5uZWwgY29uZmlnXG4gKiBAcGFyYW0ge3N0cmluZ30gY2hhbm5lbCAtIGNoYW5uZWwgdG8gYmUgdXBkYXRlZFxuICogQHJldHVybnMge3t0eXBlOiBBY3Rpb25UeXBlcy5MQVlFUl9WSVNVQUxfQ0hBTk5FTF9DSEFOR0UsIG9sZExheWVyOiBvbGRMYXllciwgbmV3Q29uZmlnOiBuZXdDb25maWcsIGNoYW5uZWw6IGNoYW5uZWx9fVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gbGF5ZXJWaXN1YWxDaGFubmVsQ29uZmlnQ2hhbmdlKG9sZExheWVyLCBuZXdDb25maWcsIGNoYW5uZWwpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBBY3Rpb25UeXBlcy5MQVlFUl9WSVNVQUxfQ0hBTk5FTF9DSEFOR0UsXG4gICAgb2xkTGF5ZXIsXG4gICAgbmV3Q29uZmlnLFxuICAgIGNoYW5uZWxcbiAgfTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgbGF5ZXIgYHZpc0NvbmZpZ2BcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZUFjdGlvbnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBvbGRMYXllciAtIGxheWVyIHRvIGJlIHVwZGF0ZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBuZXdWaXNDb25maWcgLSBuZXcgdmlzQ29uZmlnIGFzIGEga2V5IHZhbHVlIG1hcDogZS5nLiBge29wYWNpdHk6IDAuOH1gXG4gKiBAcmV0dXJucyB7e3R5cGU6IEFjdGlvblR5cGVzLkxBWUVSX1ZJU19DT05GSUdfQ0hBTkdFLCBvbGRMYXllcjogb2xkTGF5ZXIsIG5ld1Zpc0NvbmZpZzogbmV3VmlzQ29uZmlnfX1cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxheWVyVmlzQ29uZmlnQ2hhbmdlKG9sZExheWVyLCBuZXdWaXNDb25maWcpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBBY3Rpb25UeXBlcy5MQVlFUl9WSVNfQ09ORklHX0NIQU5HRSxcbiAgICBvbGRMYXllcixcbiAgICBuZXdWaXNDb25maWdcbiAgfTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIGNvbG9yIHBhbGV0dGUgdWkgZm9yIGxheWVyIGNvbG9yXG4gKiBAbWVtYmVyT2YgdmlzU3RhdGVBY3Rpb25zXG4gKiBAcGFyYW0ge09iamVjdH0gb2xkTGF5ZXIgLSBsYXllciB0byBiZSB1cGRhdGVkXG4gKiBAcGFyYW0ge1N0cmluZ30gcHJvcCAtIHdoaWNoIGNvbG9yIHByb3BcbiAqIEBwYXJhbSB7b2JqZWN0fSBuZXdDb25maWcgLSB0byBiZSBtZXJnZWRcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxheWVyQ29sb3JVSUNoYW5nZShvbGRMYXllciwgcHJvcCwgbmV3Q29uZmlnKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogQWN0aW9uVHlwZXMuTEFZRVJfQ09MT1JfVUlfQ0hBTkdFLFxuICAgIG9sZExheWVyLFxuICAgIHByb3AsXG4gICAgbmV3Q29uZmlnXG4gIH07XG59XG5cbi8qKlxuICogVXBkYXRlIGxheWVyIGJsZW5kaW5nIG1vZGVcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZUFjdGlvbnNcbiAqIEBwYXJhbSB7c3RyaW5nfSBtb2RlIG9uZSBvZiBgYWRkaXRpdmVgLCBgbm9ybWFsYCBhbmQgYHN1YnRyYWN0aXZlYFxuICogQHJldHVybnMge3t0eXBlOiBBY3Rpb25UeXBlcy5VUERBVEVfTEFZRVJfQkxFTkRJTkcsIG1vZGU6IG1vZGV9fVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlTGF5ZXJCbGVuZGluZyhtb2RlKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogQWN0aW9uVHlwZXMuVVBEQVRFX0xBWUVSX0JMRU5ESU5HLFxuICAgIG1vZGVcbiAgfTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgYGludGVyYWN0aW9uQ29uZmlnYFxuICogQG1lbWJlcm9mIHZpc1N0YXRlQWN0aW9uc1xuICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyAtIG5ldyBjb25maWcgYXMga2V5IHZhbHVlIG1hcDogYHt0b29sdGlwOiB7ZW5hYmxlZDogdHJ1ZX19YFxuICogQHJldHVybnMge3t0eXBlOiBBY3Rpb25UeXBlcy5JTlRFUkFDVElPTl9DT05GSUdfQ0hBTkdFLCBjb25maWc6IGNvbmZpZ319XG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcmFjdGlvbkNvbmZpZ0NoYW5nZShjb25maWcpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBBY3Rpb25UeXBlcy5JTlRFUkFDVElPTl9DT05GSUdfQ0hBTkdFLFxuICAgIGNvbmZpZ1xuICB9O1xufVxuXG4vKipcbiAqIFVwZGF0ZSBmaWx0ZXIgcHJvcGVydHlcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZUFjdGlvbnNcbiAqIEBwYXJhbSB7TnVtYmVyfSBpZHggLWBpZHhgIG9mIGZpbHRlciB0byBiZSB1cGRhdGVkXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcCAtIGBwcm9wYCBvZiBmaWx0ZXIsIGUsZywgYGRhdGFJZGAsIGBuYW1lYCwgYHZhbHVlYFxuICogQHBhcmFtIHsqfSB2YWx1ZSAtIG5ldyB2YWx1ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlSW5kZXggLSBhcnJheSBwcm9wZXJ0aWVzIGxpa2UgZGF0YXNldCByZXF1aXJlIGluZGV4IGluIG9yZGVyIHRvIGltcHJvdmUgcGVyZm9ybWFuY2VcbiAqIEByZXR1cm5zIHt7dHlwZTogQWN0aW9uVHlwZXMuU0VUX0ZJTFRFUiwgaWR4OiBpZHgsIHByb3A6IHByb3AsIHZhbHVlOiB2YWx1ZX19XG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRGaWx0ZXIoaWR4LCBwcm9wLCB2YWx1ZSwgdmFsdWVJbmRleCkge1xuICByZXR1cm4ge1xuICAgIHR5cGU6IEFjdGlvblR5cGVzLlNFVF9GSUxURVIsXG4gICAgaWR4LFxuICAgIHByb3AsXG4gICAgdmFsdWUsXG4gICAgdmFsdWVJbmRleFxuICB9O1xufVxuXG4vKipcbiAqIEFkZCBhIG5ldyBmaWx0ZXJcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZUFjdGlvbnNcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhSWQgLSBkYXRhc2V0IGBpZGAgdGhpcyBuZXcgZmlsdGVyIGlzIGFzc29jaWF0ZWQgd2l0aFxuICogQHJldHVybnMge3t0eXBlOiBBY3Rpb25UeXBlcy5BRERfRklMVEVSLCBkYXRhSWQ6IGRhdGFJZH19XG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRGaWx0ZXIoZGF0YUlkKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogQWN0aW9uVHlwZXMuQUREX0ZJTFRFUixcbiAgICBkYXRhSWRcbiAgfTtcbn1cblxuLyoqXG4gKiBBZGQgYSBuZXcgbGF5ZXJcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZUFjdGlvbnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wcyAtIG5ldyBsYXllciBwcm9wc1xuICogQHJldHVybnMge3t0eXBlOiBBY3Rpb25UeXBlcy5BRERfTEFZRVIsIHByb3BzOiBwcm9wc319XG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRMYXllcihwcm9wcykge1xuICByZXR1cm4ge1xuICAgIHR5cGU6IEFjdGlvblR5cGVzLkFERF9MQVlFUixcbiAgICBwcm9wc1xuICB9O1xufVxuXG4vKipcbiAqIFJlb3JkZXIgbGF5ZXIsIG9yZGVyIGlzIGFuIGFycmF5IG9mIGxheWVyIGluZGV4ZXMsIGluZGV4IDAgd2lsbCBiZSB0aGUgb25lIGF0IHRoZSBib3R0b21cbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZUFjdGlvbnNcbiAqIEBwYXJhbSB7QXJyYXk8TnVtYmVyPn0gb3JkZXIgYW4gYXJyYXkgb2YgbGF5ZXIgaW5kZXhlc1xuICogQHJldHVybnMge3t0eXBlOiBBY3Rpb25UeXBlcy5SRU9SREVSX0xBWUVSLCBvcmRlcjogb3JkZXJ9fVxuICogQHB1YmxpY1xuICogQGV4YW1wbGVcbiAqXG4gKiAvLyBicmluZyBgbGF5ZXJzWzFdYCBiZWxvdyBgbGF5ZXJzWzBdYCwgdGhlIHNlcXVlbmNlIGxheWVycyB3aWxsIGJlIHJlbmRlcmVkIGlzIGAxYCwgYDBgLCBgMmAsIGAzYC5cbiAqIC8vIGAxYCB3aWxsIGJlIGF0IHRoZSBib3R0b20sIGAzYCB3aWxsIGJlIGF0IHRoZSB0b3AuXG4gKiB0aGlzLnByb3BzLmRpc3BhdGNoKHJlb3JkZXJMYXllcihbMSwgMCwgMiwgM10pKTtcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlb3JkZXJMYXllcihvcmRlcikge1xuICByZXR1cm4ge1xuICAgIHR5cGU6IEFjdGlvblR5cGVzLlJFT1JERVJfTEFZRVIsXG4gICAgb3JkZXJcbiAgfTtcbn1cblxuLyoqXG4gKiBSZW1vdmUgYSBmaWx0ZXIgZnJvbSBgdmlzU3RhdGUuZmlsdGVyc2AsIG9uY2UgYSBmaWx0ZXIgaXMgcmVtb3ZlZCwgZGF0YSB3aWxsIGJlIHJlLWZpbHRlcmVkIGFuZCBsYXllciB3aWxsIGJlIHVwZGF0ZWRcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZUFjdGlvbnNcbiAqIEBwYXJhbSB7TnVtYmVyfSBpZHggaWR4IG9mIGZpbHRlciB0byBiZSByZW1vdmVkXG4gKiBAcmV0dXJucyB7e3R5cGU6IEFjdGlvblR5cGVzLlJFTU9WRV9GSUxURVIsIGlkeDogaWR4fX1cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUZpbHRlcihpZHgpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBBY3Rpb25UeXBlcy5SRU1PVkVfRklMVEVSLFxuICAgIGlkeFxuICB9O1xufVxuXG4vKipcbiAqIFJlbW92ZSBhIGxheWVyXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVBY3Rpb25zXG4gKiBAcGFyYW0ge051bWJlcn0gaWR4IGlkeCBvZiBsYXllciB0byBiZSByZW1vdmVkXG4gKiBAcmV0dXJucyB7e3R5cGU6IEFjdGlvblR5cGVzLlJFTU9WRV9MQVlFUiwgaWR4OiBpZHh9fVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlTGF5ZXIoaWR4KSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogQWN0aW9uVHlwZXMuUkVNT1ZFX0xBWUVSLFxuICAgIGlkeFxuICB9O1xufVxuXG4vKipcbiAqIFJlbW92ZSBhIGRhdGFzZXQgYW5kIGFsbCBsYXllcnMsIGZpbHRlcnMsIHRvb2x0aXAgY29uZmlncyB0aGF0IGJhc2VkIG9uIGl0XG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVBY3Rpb25zXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IGRhdGFzZXQgaWRcbiAqIEByZXR1cm5zIHt7dHlwZTogQWN0aW9uVHlwZXMuUkVNT1ZFX0RBVEFTRVQsIGtleToga2V5fX1cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZURhdGFzZXQoa2V5KSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogQWN0aW9uVHlwZXMuUkVNT1ZFX0RBVEFTRVQsXG4gICAga2V5XG4gIH07XG59XG5cbi8qKlxuICogRGlzcGxheSBkYXRhc2V0IHRhYmxlIGluIGEgbW9kYWxcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZUFjdGlvbnNcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhSWQgZGF0YXNldCBpZCB0byBzaG93IGluIHRhYmxlXG4gKiBAcmV0dXJucyB7e3R5cGU6IEFjdGlvblR5cGVzLlNIT1dfREFUQVNFVF9UQUJMRSwgZGF0YUlkOiBkYXRhSWR9fVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2hvd0RhdGFzZXRUYWJsZShkYXRhSWQpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBBY3Rpb25UeXBlcy5TSE9XX0RBVEFTRVRfVEFCTEUsXG4gICAgZGF0YUlkXG4gIH07XG59XG5cbi8qKlxuICogU29ydCBkYXRhc2V0IGNvbHVtbiwgZm9yIHRhYmxlIGRpc3BsYXlcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhSWRcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb2x1bW5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtb2RlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzb3J0VGFibGVDb2x1bW4oZGF0YUlkLCBjb2x1bW4sIG1vZGUpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBBY3Rpb25UeXBlcy5TT1JUX1RBQkxFX0NPTFVNTixcbiAgICBkYXRhSWQsXG4gICAgY29sdW1uLFxuICAgIG1vZGVcbiAgfTtcbn1cblxuLyoqXG4gKiBQaW4gZGF0YXNldCBjb2x1bW4sIGZvciB0YWJsZSBkaXNwbGF5XG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YUlkXG4gKiBAcGFyYW0ge3N0cmluZ30gY29sdW1uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwaW5UYWJsZUNvbHVtbihkYXRhSWQsIGNvbHVtbikge1xuICByZXR1cm4ge1xuICAgIHR5cGU6IEFjdGlvblR5cGVzLlBJTl9UQUJMRV9DT0xVTU4sXG4gICAgZGF0YUlkLFxuICAgIGNvbHVtblxuICB9O1xufVxuXG4vKipcbiAqIENvcHkgY29sdW1uLCBmb3IgdGFibGUgZGlzcGxheVxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGFJZFxuICogQHBhcmFtIHtzdHJpbmd9IGNvbHVtblxuICovXG5leHBvcnQgZnVuY3Rpb24gY29weVRhYmxlQ29sdW1uKGRhdGFJZCwgY29sdW1uKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogQWN0aW9uVHlwZXMuQ09QWV9UQUJMRV9DT0xVTU4sXG4gICAgZGF0YUlkLFxuICAgIGNvbHVtblxuICB9O1xufVxuXG4vKipcbiAqIEFkZCBuZXcgZGF0YXNldCB0byBgdmlzU3RhdGVgLCB3aXRoIG9wdGlvbiB0byBsb2FkIGEgbWFwIGNvbmZpZyBhbG9uZyB3aXRoIHRoZSBkYXRhc2V0c1xuICogQG1lbWJlcm9mIHZpc1N0YXRlQWN0aW9uc1xuICogQHBhcmFtIHtBcnJheTxPYmplY3Q+fE9iamVjdH0gZGF0YXNldHMgLSAqKipyZXF1aXJlZCoqIGRhdGFzZXRzIGNhbiBiZSBhIGRhdGFzZXQgb3IgYW4gYXJyYXkgb2YgZGF0YXNldHNcbiAqIEVhY2ggZGF0YXNldCBvYmplY3QgbmVlZHMgdG8gaGF2ZSBgaW5mb2AgYW5kIGBkYXRhYCBwcm9wZXJ0eS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhc2V0cy5pbmZvIC1pbmZvIG9mIGEgZGF0YXNldFxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGFzZXRzLmluZm8uaWQgLSBpZCBvZiB0aGlzIGRhdGFzZXQuIElmIGNvbmZpZyBpcyBkZWZpbmVkLCBgaWRgIHNob3VsZCBtYXRjaGVzIHRoZSBgZGF0YUlkYCBpbiBjb25maWcuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YXNldHMuaW5mby5sYWJlbCAtIEEgZGlzcGxheSBuYW1lIG9mIHRoaXMgZGF0YXNldFxuICogQHBhcmFtIHtPYmplY3R9IGRhdGFzZXRzLmRhdGEgLSAqKipyZXF1aXJlZCoqIFRoZSBkYXRhIG9iamVjdCwgaW4gYSB0YWJ1bGFyIGZvcm1hdCB3aXRoIDIgcHJvcGVydGllcyBgZmllbGRzYCBhbmQgYHJvd3NgXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGRhdGFzZXRzLmRhdGEuZmllbGRzIC0gKioqcmVxdWlyZWQqKiBBcnJheSBvZiBmaWVsZHMsXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YXNldHMuZGF0YS5maWVsZHMubmFtZSAtICoqKnJlcXVpcmVkKiogTmFtZSBvZiB0aGUgZmllbGQsXG4gKiBAcGFyYW0ge0FycmF5PEFycmF5Pn0gZGF0YXNldHMuZGF0YS5yb3dzIC0gKioqcmVxdWlyZWQqKiBBcnJheSBvZiByb3dzLCBpbiBhIHRhYnVsYXIgZm9ybWF0IHdpdGggYGZpZWxkc2AgYW5kIGByb3dzYFxuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogQHBhcmFtIHtib29sZWFufSBvcHRpb25zLmNlbnRlck1hcCBgZGVmYXVsdDogdHJ1ZWAgaWYgYGNlbnRlck1hcGAgaXMgc2V0IHRvIGB0cnVlYCBrZXBsZXIuZ2wgd2lsbFxuICogcGxhY2UgdGhlIG1hcCB2aWV3IHdpdGhpbiB0aGUgZGF0YSBwb2ludHMgYm91bmRhcmllc1xuICogQHBhcmFtIHtib29sZWFufSBvcHRpb25zLnJlYWRPbmx5IGBkZWZhdWx0OiBmYWxzZWAgaWYgYHJlYWRPbmx5YCBpcyBzZXQgdG8gYHRydWVgXG4gKiB0aGUgbGVmdCBzZXR0aW5nIHBhbmVsIHdpbGwgYmUgaGlkZGVuXG4gKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIHRoaXMgb2JqZWN0IHdpbGwgY29udGFpbiB0aGUgZnVsbCBrZXBsZXIuZ2wgaW5zdGFuY2UgY29uZmlndXJhdGlvbiB7bWFwU3RhdGUsIG1hcFN0eWxlLCB2aXNTdGF0ZX1cbiAqIEByZXR1cm5zIHt7dHlwZTogQWN0aW9uVHlwZXMuVVBEQVRFX1ZJU19EQVRBLCBkYXRhc2V0czogZGF0YXNldHMsIG9wdGlvbnM6IG9wdGlvbnMsIGNvbmZpZzogY29uZmlnfX1cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVZpc0RhdGEoZGF0YXNldHMsIG9wdGlvbnMsIGNvbmZpZykge1xuICByZXR1cm4ge1xuICAgIHR5cGU6IEFjdGlvblR5cGVzLlVQREFURV9WSVNfREFUQSxcbiAgICBkYXRhc2V0cyxcbiAgICBvcHRpb25zLFxuICAgIGNvbmZpZ1xuICB9O1xufVxuXG4vKipcbiAqIFN0YXJ0IGFuZCBlbmQgZmlsdGVyIGFuaW1hdGlvblxuICogQG1lbWJlcm9mIHZpc1N0YXRlQWN0aW9uc1xuICogQHBhcmFtIHtOdW1iZXJ9IGlkeCAtIGlkeCBvZiBmaWx0ZXJcbiAqIEByZXR1cm5zIHt7dHlwZTogQWN0aW9uVHlwZXMuVE9HR0xFX0ZJTFRFUl9BTklNQVRJT04sIGlkeDogaWR4fX1cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvZ2dsZUZpbHRlckFuaW1hdGlvbihpZHgpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBBY3Rpb25UeXBlcy5UT0dHTEVfRklMVEVSX0FOSU1BVElPTixcbiAgICBpZHhcbiAgfTtcbn1cblxuLyoqXG4gKiBDaGFuZ2UgZmlsdGVyIGFuaW1hdGlvbiBzcGVlZFxuICogQG1lbWJlcm9mIHZpc1N0YXRlQWN0aW9uc1xuICogQHBhcmFtIHtOdW1iZXJ9IGlkeCAtICBgaWR4YCBvZiBmaWx0ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzcGVlZCAtIGBzcGVlZGAgdG8gY2hhbmdlIGl0IHRvLiBgc3BlZWRgIGlzIGEgbXVsdGlwbGllclxuICogQHJldHVybnMge3t0eXBlOiBBY3Rpb25UeXBlcy5VUERBVEVfRklMVEVSX0FOSU1BVElPTl9TUEVFRCwgaWR4OiBpZHgsIHNwZWVkOiBzcGVlZH19XG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVGaWx0ZXJBbmltYXRpb25TcGVlZChpZHgsIHNwZWVkKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogQWN0aW9uVHlwZXMuVVBEQVRFX0ZJTFRFUl9BTklNQVRJT05fU1BFRUQsXG4gICAgaWR4LFxuICAgIHNwZWVkXG4gIH07XG59XG5cbi8qKlxuICogUmVzZXQgYW5pbWF0aW9uXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVBY3Rpb25zXG4gKiBAcGFyYW0ge051bWJlcn0gdmFsdWUgLSAgQ3VycmVudCB2YWx1ZSBvZiB0aGUgc2xpZGVyXG4gKiBAcmV0dXJucyB7e3R5cGU6IEFjdGlvblR5cGVzLlVQREFURV9BTklNQVRJT05fVElNRSwgdmFsdWU6IHZhbHVlfX1cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUFuaW1hdGlvblRpbWUodmFsdWUpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBBY3Rpb25UeXBlcy5VUERBVEVfQU5JTUFUSU9OX1RJTUUsXG4gICAgdmF