kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
187 lines (183 loc) • 23.4 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.resetMapConfig = exports.replaceDataInMap = exports.receiveMapConfig = exports.keplerGlInit = exports.addDataToMap = void 0;
var _actionTypes = _interopRequireDefault(require("./action-types"));
var _toolkit = require("@reduxjs/toolkit");
// SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
/**
* Add data to kepler.gl reducer, prepare map with preset configuration if config is passed.
* Kepler.gl provides a handy set of utils to parse data from different formats to the `data` object required in dataset. You rarely need to manually format the data obejct.
*
* Use `KeplerGlSchema.getConfigToSave` to generate a json blob of the currents instance config.
* The config object value will always have higher precedence than the options properties.
*
* Kepler.gl uses `dataId` in the config to match with loaded dataset. If you pass a config object, you need
* to match the `info.id` of your dataset to the `dataId` in each `layer`, `filter` and `interactionConfig.tooltips.fieldsToShow`
*
* @memberof main
* @param {Object} data
* @param {Array<Object>|Object} data.datasets - ***required** datasets can be a dataset or an array of datasets
* Each dataset object needs to have `info` and `data` property.
* @param {Object} data.datasets.info -info of a dataset
* @param {string} data.datasets.info.id - id of this dataset. If config is defined, `id` should matches the `dataId` in config.
* @param {string} data.datasets.info.label - A display name of this dataset
* @param {Object} data.datasets.data - ***required** The data object, in a tabular format with 2 properties `fields` and `rows`
* @param {Array<Object>} data.datasets.data.fields - ***required** Array of fields,
* @param {string} data.datasets.data.fields.name - ***required** Name of the field,
* @param {Array<Array>} data.datasets.data.rows - ***required** Array of rows, in a tabular format with `fields` and `rows`
*
* @param {Object} data.options
* @param {boolean} data.options.centerMap `default: true` if `centerMap` is set to `true` kepler.gl will
* place the map view within the data points boundaries. `options.centerMap` will override `config.mapState` if passed in.
* @param {boolean} data.options.readOnly `default: false` if `readOnly` is set to `true`
* the left setting panel will be hidden
* @param {boolean} data.options.keepExistingConfig whether to keep exiting map data and associated layer filter interaction config `default: false`.
* @param {Object} data.config this object will contain the full kepler.gl instance configuration {mapState, mapStyle, visState}
* @public
* @example
*
* // app.js
* import {addDataToMap} from 'kepler.gl/actions';
*
* const sampleTripData = {
* fields: [
* {name: 'tpep_pickup_datetime', format: 'YYYY-M-D H:m:s', type: 'timestamp'},
* {name: 'pickup_longitude', format: '', type: 'real'},
* {name: 'pickup_latitude', format: '', type: 'real'}
* ],
* rows: [
* ['2015-01-15 19:05:39 +00:00', -73.99389648, 40.75011063],
* ['2015-01-15 19:05:39 +00:00', -73.97642517, 40.73981094],
* ['2015-01-15 19:05:40 +00:00', -73.96870422, 40.75424576],
* ]
* };
*
* const sampleConfig = {
* visState: {
* filters: [
* {
* id: 'me',
* dataId: 'test_trip_data',
* name: 'tpep_pickup_datetime',
* type: 'timeRange',
* view: 'enlarged'
* }
* ]
* }
* }
*
* this.props.dispatch(
* addDataToMap({
* datasets: {
* info: {
* label: 'Sample Taxi Trips in New York City',
* id: 'test_trip_data'
* },
* data: sampleTripData
* },
* options: {
* centerMap: true,
* readOnly: false,
* keepExistingConfig: false
* },
* info: {
* title: 'Taro and Blue',
* description: 'This is my map'
* },
* config: sampleConfig
* })
* );
*/
var addDataToMap = exports.addDataToMap = (0, _toolkit.createAction)(_actionTypes["default"].ADD_DATA_TO_MAP, function (data) {
return {
payload: data
};
});
/**
* Reset all sub-reducers to its initial state. This can be used to clear out all configuration in the reducer.
* @memberof main
* @public
*/
var resetMapConfig = exports.resetMapConfig = (0, _toolkit.createAction)(_actionTypes["default"].RESET_MAP_CONFIG);
/**
* Pass config to kepler.gl instance, prepare the state with preset configs.
* Calling `KeplerGlSchema.parseSavedConfig` to convert saved config before passing it in is required.
*
* You can call `receiveMapConfig` before passing in any data. The reducer will store layer and filter config, waiting for
* data to come in. When data arrives, you can call `addDataToMap` without passing any config, and the reducer will try to match
* preloaded configs. This behavior is designed to allow asynchronous data loading.
*
* It is also useful when you want to prepare the kepler.gl instance with some preset layer and filter settings.
* **Note** Sequence is important, `receiveMapConfig` needs to be called __before__ data is loaded. Currently kepler.gl doesn't allow calling `receiveMapConfig` after data is loaded.
* It will reset current configuration first then apply config to it.
* @memberof main
* @param {Object} config - ***required** The Config Object
* @param {Object} options - ***optional** The Option object
* @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 {boolean} options.keepExistingConfig whether to keep exiting layer filter and interaction config `default: false`.
* @param {boolean} options.autoCreateLayers whether to automatically create layers based on dataset columns `default: true`.
* @public
* @example
* import {receiveMapConfig} from 'kepler.gl/actions';
* import KeplerGlSchema from 'kepler.gl/schemas';
*
* const parsedConfig = KeplerGlSchema.parseSavedConfig(config);
* this.props.dispatch(receiveMapConfig(parsedConfig));
*/
var receiveMapConfig = exports.receiveMapConfig = (0, _toolkit.createAction)(_actionTypes["default"].RECEIVE_MAP_CONFIG, function (config, options) {
return {
payload: {
config: config,
options: options
}
};
});
/**
* Initialize kepler.gl reducer. It is used to pass in `mapboxApiAccessToken` to `mapStyle` reducer.
* @memberof main
* @param {object} payload
* @param payload.mapboxApiAccessToken - mapboxApiAccessToken to be saved to mapStyle reducer
* @param payload.mapboxApiUrl - mapboxApiUrl to be saved to mapStyle reducer.
* @param payload.mapStylesReplaceDefault - mapStylesReplaceDefault to be saved to mapStyle reducer
* @param payload.initialUiState - initial ui state
* @public
*/
// @ts-expect-error
var keplerGlInit = exports.keplerGlInit = (0, _toolkit.createAction)(_actionTypes["default"].INIT, function (payload) {
return {
payload: payload
};
});
/**
* Initialize kepler.gl reducer. It is used to pass in `mapboxApiAccessToken` to `mapStyle` reducer.
* @memberof main
* @param payload
* @param payload.datasetToReplaceId - mapboxApiAccessToken to be saved to mapStyle reducer
* @param payload.datasetToUse - mapboxApiUrl to be saved to mapStyle reducer.
* @public
*/
var replaceDataInMap = exports.replaceDataInMap = (0, _toolkit.createAction)(_actionTypes["default"].REPLACE_DATA_IN_MAP, function (payload) {
return {
payload: payload
};
});
/**
* This declaration is needed to group actions in docs
*/
/**
* Main kepler.gl actions, these actions handles loading data and config into kepler.gl reducer. These actions
* is listened by all subreducers,
* @public
*/
/* eslint-disable @typescript-eslint/no-unused-vars */
// @ts-ignore
var main = null;
/* eslint-enable @typescript-eslint/no-unused-vars */
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfYWN0aW9uVHlwZXMiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl90b29sa2l0IiwiYWRkRGF0YVRvTWFwIiwiZXhwb3J0cyIsImNyZWF0ZUFjdGlvbiIsIkFjdGlvblR5cGVzIiwiQUREX0RBVEFfVE9fTUFQIiwiZGF0YSIsInBheWxvYWQiLCJyZXNldE1hcENvbmZpZyIsIlJFU0VUX01BUF9DT05GSUciLCJyZWNlaXZlTWFwQ29uZmlnIiwiUkVDRUlWRV9NQVBfQ09ORklHIiwiY29uZmlnIiwib3B0aW9ucyIsImtlcGxlckdsSW5pdCIsIklOSVQiLCJyZXBsYWNlRGF0YUluTWFwIiwiUkVQTEFDRV9EQVRBX0lOX01BUCIsIm1haW4iXSwic291cmNlcyI6WyIuLi9zcmMvYWN0aW9ucy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQge2RlZmF1bHQgYXMgQWN0aW9uVHlwZXN9IGZyb20gJy4vYWN0aW9uLXR5cGVzJztcbmltcG9ydCB7Y3JlYXRlQWN0aW9ufSBmcm9tICdAcmVkdXhqcy90b29sa2l0JztcblxuaW1wb3J0IHtcbiAgQWRkRGF0YVRvTWFwT3B0aW9ucyxcbiAgQWRkRGF0YVRvTWFwUGF5bG9hZCxcbiAgQm91bmRzLFxuICBVaVN0YXRlLFxuICBQYXJzZWRDb25maWcsXG4gIFByb3RvRGF0YXNldFxufSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcblxudHlwZSBIYW5kbGVyID0gKC4uLmFyZ3M6IGFueSkgPT4gYW55O1xuXG5leHBvcnQgdHlwZSBBY3Rpb25IYW5kbGVyPEEgZXh0ZW5kcyBIYW5kbGVyPiA9ICguLi5hcmdzOiBQYXJhbWV0ZXJzPEE+KSA9PiB2b2lkO1xuXG5leHBvcnQgdHlwZSBBY3Rpb25IYW5kbGVyczxUIGV4dGVuZHMge1trOiBzdHJpbmddOiBIYW5kbGVyfT4gPSB7XG4gIFtLIGluIGtleW9mIFRdOiBBY3Rpb25IYW5kbGVyPFRbS10+O1xufTtcblxuLyoqXG4gKiBBZGQgZGF0YSB0byBrZXBsZXIuZ2wgcmVkdWNlciwgcHJlcGFyZSBtYXAgd2l0aCBwcmVzZXQgY29uZmlndXJhdGlvbiBpZiBjb25maWcgaXMgcGFzc2VkLlxuICogS2VwbGVyLmdsIHByb3ZpZGVzIGEgaGFuZHkgc2V0IG9mIHV0aWxzIHRvIHBhcnNlIGRhdGEgZnJvbSBkaWZmZXJlbnQgZm9ybWF0cyB0byB0aGUgYGRhdGFgIG9iamVjdCByZXF1aXJlZCBpbiBkYXRhc2V0LiBZb3UgcmFyZWx5IG5lZWQgdG8gbWFudWFsbHkgZm9ybWF0IHRoZSBkYXRhIG9iZWpjdC5cbiAqXG4gKiBVc2UgYEtlcGxlckdsU2NoZW1hLmdldENvbmZpZ1RvU2F2ZWAgdG8gZ2VuZXJhdGUgYSBqc29uIGJsb2Igb2YgdGhlIGN1cnJlbnRzIGluc3RhbmNlIGNvbmZpZy5cbiAqIFRoZSBjb25maWcgb2JqZWN0IHZhbHVlIHdpbGwgYWx3YXlzIGhhdmUgaGlnaGVyIHByZWNlZGVuY2UgdGhhbiB0aGUgb3B0aW9ucyBwcm9wZXJ0aWVzLlxuICpcbiAqIEtlcGxlci5nbCB1c2VzIGBkYXRhSWRgIGluIHRoZSBjb25maWcgdG8gbWF0Y2ggd2l0aCBsb2FkZWQgZGF0YXNldC4gSWYgeW91IHBhc3MgYSBjb25maWcgb2JqZWN0LCB5b3UgbmVlZFxuICogdG8gbWF0Y2ggdGhlIGBpbmZvLmlkYCBvZiB5b3VyIGRhdGFzZXQgdG8gdGhlIGBkYXRhSWRgIGluIGVhY2ggYGxheWVyYCwgYGZpbHRlcmAgYW5kIGBpbnRlcmFjdGlvbkNvbmZpZy50b29sdGlwcy5maWVsZHNUb1Nob3dgXG4gKlxuICogQG1lbWJlcm9mIG1haW5cbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD58T2JqZWN0fSBkYXRhLmRhdGFzZXRzIC0gKioqcmVxdWlyZWQqKiBkYXRhc2V0cyBjYW4gYmUgYSBkYXRhc2V0IG9yIGFuIGFycmF5IG9mIGRhdGFzZXRzXG4gKiBFYWNoIGRhdGFzZXQgb2JqZWN0IG5lZWRzIHRvIGhhdmUgYGluZm9gIGFuZCBgZGF0YWAgcHJvcGVydHkuXG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YS5kYXRhc2V0cy5pbmZvIC1pbmZvIG9mIGEgZGF0YXNldFxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEuZGF0YXNldHMuaW5mby5pZCAtIGlkIG9mIHRoaXMgZGF0YXNldC4gSWYgY29uZmlnIGlzIGRlZmluZWQsIGBpZGAgc2hvdWxkIG1hdGNoZXMgdGhlIGBkYXRhSWRgIGluIGNvbmZpZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhLmRhdGFzZXRzLmluZm8ubGFiZWwgLSBBIGRpc3BsYXkgbmFtZSBvZiB0aGlzIGRhdGFzZXRcbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhLmRhdGFzZXRzLmRhdGEgLSAqKipyZXF1aXJlZCoqIFRoZSBkYXRhIG9iamVjdCwgaW4gYSB0YWJ1bGFyIGZvcm1hdCB3aXRoIDIgcHJvcGVydGllcyBgZmllbGRzYCBhbmQgYHJvd3NgXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGRhdGEuZGF0YXNldHMuZGF0YS5maWVsZHMgLSAqKipyZXF1aXJlZCoqIEFycmF5IG9mIGZpZWxkcyxcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhLmRhdGFzZXRzLmRhdGEuZmllbGRzLm5hbWUgLSAqKipyZXF1aXJlZCoqIE5hbWUgb2YgdGhlIGZpZWxkLFxuICogQHBhcmFtIHtBcnJheTxBcnJheT59IGRhdGEuZGF0YXNldHMuZGF0YS5yb3dzIC0gKioqcmVxdWlyZWQqKiBBcnJheSBvZiByb3dzLCBpbiBhIHRhYnVsYXIgZm9ybWF0IHdpdGggYGZpZWxkc2AgYW5kIGByb3dzYFxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhLm9wdGlvbnNcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZGF0YS5vcHRpb25zLmNlbnRlck1hcCBgZGVmYXVsdDogdHJ1ZWAgaWYgYGNlbnRlck1hcGAgaXMgc2V0IHRvIGB0cnVlYCBrZXBsZXIuZ2wgd2lsbFxuICogcGxhY2UgdGhlIG1hcCB2aWV3IHdpdGhpbiB0aGUgZGF0YSBwb2ludHMgYm91bmRhcmllcy4gIGBvcHRpb25zLmNlbnRlck1hcGAgd2lsbCBvdmVycmlkZSBgY29uZmlnLm1hcFN0YXRlYCBpZiBwYXNzZWQgaW4uXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGRhdGEub3B0aW9ucy5yZWFkT25seSBgZGVmYXVsdDogZmFsc2VgIGlmIGByZWFkT25seWAgaXMgc2V0IHRvIGB0cnVlYFxuICogdGhlIGxlZnQgc2V0dGluZyBwYW5lbCB3aWxsIGJlIGhpZGRlblxuICogQHBhcmFtIHtib29sZWFufSBkYXRhLm9wdGlvbnMua2VlcEV4aXN0aW5nQ29uZmlnIHdoZXRoZXIgdG8ga2VlcCBleGl0aW5nIG1hcCBkYXRhIGFuZCBhc3NvY2lhdGVkIGxheWVyIGZpbHRlciAgaW50ZXJhY3Rpb24gY29uZmlnIGBkZWZhdWx0OiBmYWxzZWAuXG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YS5jb25maWcgdGhpcyBvYmplY3Qgd2lsbCBjb250YWluIHRoZSBmdWxsIGtlcGxlci5nbCBpbnN0YW5jZSBjb25maWd1cmF0aW9uIHttYXBTdGF0ZSwgbWFwU3R5bGUsIHZpc1N0YXRlfVxuICogQHB1YmxpY1xuICogQGV4YW1wbGVcbiAqXG4gKiAvLyBhcHAuanNcbiAqIGltcG9ydCB7YWRkRGF0YVRvTWFwfSBmcm9tICdrZXBsZXIuZ2wvYWN0aW9ucyc7XG4gKlxuICogY29uc3Qgc2FtcGxlVHJpcERhdGEgPSB7XG4gKiAgZmllbGRzOiBbXG4gKiAgICB7bmFtZTogJ3RwZXBfcGlja3VwX2RhdGV0aW1lJywgZm9ybWF0OiAnWVlZWS1NLUQgSDptOnMnLCB0eXBlOiAndGltZXN0YW1wJ30sXG4gKiAgICB7bmFtZTogJ3BpY2t1cF9sb25naXR1ZGUnLCBmb3JtYXQ6ICcnLCB0eXBlOiAncmVhbCd9LFxuICogICAge25hbWU6ICdwaWNrdXBfbGF0aXR1ZGUnLCBmb3JtYXQ6ICcnLCB0eXBlOiAncmVhbCd9XG4gKiAgXSxcbiAqICByb3dzOiBbXG4gKiAgICBbJzIwMTUtMDEtMTUgMTk6MDU6MzkgKzAwOjAwJywgLTczLjk5Mzg5NjQ4LCA0MC43NTAxMTA2M10sXG4gKiAgICBbJzIwMTUtMDEtMTUgMTk6MDU6MzkgKzAwOjAwJywgLTczLjk3NjQyNTE3LCA0MC43Mzk4MTA5NF0sXG4gKiAgICBbJzIwMTUtMDEtMTUgMTk6MDU6NDAgKzAwOjAwJywgLTczLjk2ODcwNDIyLCA0MC43NTQyNDU3Nl0sXG4gKiAgXVxuICogfTtcbiAqXG4gKiBjb25zdCBzYW1wbGVDb25maWcgPSB7XG4gKiAgIHZpc1N0YXRlOiB7XG4gKiAgICAgZmlsdGVyczogW1xuICogICAgICAge1xuICogICAgICAgICBpZDogJ21lJyxcbiAqICAgICAgICAgZGF0YUlkOiAndGVzdF90cmlwX2RhdGEnLFxuICogICAgICAgICBuYW1lOiAndHBlcF9waWNrdXBfZGF0ZXRpbWUnLFxuICogICAgICAgICB0eXBlOiAndGltZVJhbmdlJyxcbiAqICAgICAgICAgdmlldzogJ2VubGFyZ2VkJ1xuICogICAgICAgfVxuICogICAgIF1cbiAqICAgfVxuICogfVxuICpcbiAqIHRoaXMucHJvcHMuZGlzcGF0Y2goXG4gKiAgIGFkZERhdGFUb01hcCh7XG4gKiAgICAgZGF0YXNldHM6IHtcbiAqICAgICAgIGluZm86IHtcbiAqICAgICAgICAgbGFiZWw6ICdTYW1wbGUgVGF4aSBUcmlwcyBpbiBOZXcgWW9yayBDaXR5JyxcbiAqICAgICAgICAgaWQ6ICd0ZXN0X3RyaXBfZGF0YSdcbiAqICAgICAgIH0sXG4gKiAgICAgICBkYXRhOiBzYW1wbGVUcmlwRGF0YVxuICogICAgIH0sXG4gKiAgICAgb3B0aW9uczoge1xuICogICAgICAgY2VudGVyTWFwOiB0cnVlLFxuICogICAgICAgcmVhZE9ubHk6IGZhbHNlLFxuICogICAgICAga2VlcEV4aXN0aW5nQ29uZmlnOiBmYWxzZVxuICogICAgIH0sXG4gKiAgICAgaW5mbzoge1xuICogICAgICAgdGl0bGU6ICdUYXJvIGFuZCBCbHVlJyxcbiAqICAgICAgIGRlc2NyaXB0aW9uOiAnVGhpcyBpcyBteSBtYXAnXG4gKiAgICAgfSxcbiAqICAgICBjb25maWc6IHNhbXBsZUNvbmZpZ1xuICogICB9KVxuICogKTtcbiAqL1xuZXhwb3J0IGNvbnN0IGFkZERhdGFUb01hcDogKGRhdGE6IEFkZERhdGFUb01hcFBheWxvYWQpID0+IHtcbiAgdHlwZTogdHlwZW9mIEFjdGlvblR5cGVzLkFERF9EQVRBX1RPX01BUDtcbiAgcGF5bG9hZDogQWRkRGF0YVRvTWFwUGF5bG9hZDtcbn0gPSBjcmVhdGVBY3Rpb24oQWN0aW9uVHlwZXMuQUREX0RBVEFfVE9fTUFQLCAoZGF0YTogQWRkRGF0YVRvTWFwUGF5bG9hZCkgPT4gKHtwYXlsb2FkOiBkYXRhfSkpO1xuXG4vKipcbiAqIFJlc2V0IGFsbCBzdWItcmVkdWNlcnMgdG8gaXRzIGluaXRpYWwgc3RhdGUuIFRoaXMgY2FuIGJlIHVzZWQgdG8gY2xlYXIgb3V0IGFsbCBjb25maWd1cmF0aW9uIGluIHRoZSByZWR1Y2VyLlxuICogQG1lbWJlcm9mIG1haW5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHJlc2V0TWFwQ29uZmlnOiAoKSA9PiB7dHlwZTogdHlwZW9mIEFjdGlvblR5cGVzLlJFU0VUX01BUF9DT05GSUd9ID0gY3JlYXRlQWN0aW9uKFxuICBBY3Rpb25UeXBlcy5SRVNFVF9NQVBfQ09ORklHXG4pO1xuXG5leHBvcnQgdHlwZSBSZWNlaXZlTWFwQ29uZmlnUGF5bG9hZCA9IHtcbiAgY29uZmlnOiBQYXJzZWRDb25maWc7XG4gIG9wdGlvbnM/OiBBZGREYXRhVG9NYXBPcHRpb25zO1xuICBib3VuZHM/OiBCb3VuZHM7XG59O1xuLyoqXG4gKiBQYXNzIGNvbmZpZyB0byBrZXBsZXIuZ2wgaW5zdGFuY2UsIHByZXBhcmUgdGhlIHN0YXRlIHdpdGggcHJlc2V0IGNvbmZpZ3MuXG4gKiBDYWxsaW5nIGBLZXBsZXJHbFNjaGVtYS5wYXJzZVNhdmVkQ29uZmlnYCB0byBjb252ZXJ0IHNhdmVkIGNvbmZpZyBiZWZvcmUgcGFzc2luZyBpdCBpbiBpcyByZXF1aXJlZC5cbiAqXG4gKiBZb3UgY2FuIGNhbGwgYHJlY2VpdmVNYXBDb25maWdgIGJlZm9yZSBwYXNzaW5nIGluIGFueSBkYXRhLiBUaGUgcmVkdWNlciB3aWxsIHN0b3JlIGxheWVyIGFuZCBmaWx0ZXIgY29uZmlnLCB3YWl0aW5nIGZvclxuICogZGF0YSB0byBjb21lIGluLiBXaGVuIGRhdGEgYXJyaXZlcywgeW91IGNhbiBjYWxsIGBhZGREYXRhVG9NYXBgIHdpdGhvdXQgcGFzc2luZyBhbnkgY29uZmlnLCBhbmQgdGhlIHJlZHVjZXIgd2lsbCB0cnkgdG8gbWF0Y2hcbiAqIHByZWxvYWRlZCBjb25maWdzLiBUaGlzIGJlaGF2aW9yIGlzIGRlc2lnbmVkIHRvIGFsbG93IGFzeW5jaHJvbm91cyBkYXRhIGxvYWRpbmcuXG4gKlxuICogSXQgaXMgYWxzbyB1c2VmdWwgd2hlbiB5b3Ugd2FudCB0byBwcmVwYXJlIHRoZSBrZXBsZXIuZ2wgaW5zdGFuY2Ugd2l0aCBzb21lIHByZXNldCBsYXllciBhbmQgZmlsdGVyIHNldHRpbmdzLlxuICogKipOb3RlKiogU2VxdWVuY2UgaXMgaW1wb3J0YW50LCBgcmVjZWl2ZU1hcENvbmZpZ2AgbmVlZHMgdG8gYmUgY2FsbGVkIF9fYmVmb3JlX18gZGF0YSBpcyBsb2FkZWQuIEN1cnJlbnRseSBrZXBsZXIuZ2wgZG9lc24ndCBhbGxvdyBjYWxsaW5nIGByZWNlaXZlTWFwQ29uZmlnYCBhZnRlciBkYXRhIGlzIGxvYWRlZC5cbiAqIEl0IHdpbGwgcmVzZXQgY3VycmVudCBjb25maWd1cmF0aW9uIGZpcnN0IHRoZW4gYXBwbHkgY29uZmlnIHRvIGl0LlxuICogQG1lbWJlcm9mIG1haW5cbiAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgLSAqKipyZXF1aXJlZCoqIFRoZSBDb25maWcgT2JqZWN0XG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtICoqKm9wdGlvbmFsKiogVGhlIE9wdGlvbiBvYmplY3RcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0aW9ucy5jZW50ZXJNYXAgYGRlZmF1bHQ6IHRydWVgIGlmIGBjZW50ZXJNYXBgIGlzIHNldCB0byBgdHJ1ZWAga2VwbGVyLmdsIHdpbGxcbiAqIHBsYWNlIHRoZSBtYXAgdmlldyB3aXRoaW4gdGhlIGRhdGEgcG9pbnRzIGJvdW5kYXJpZXNcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0aW9ucy5yZWFkT25seSBgZGVmYXVsdDogZmFsc2VgIGlmIGByZWFkT25seWAgaXMgc2V0IHRvIGB0cnVlYFxuICogdGhlIGxlZnQgc2V0dGluZyBwYW5lbCB3aWxsIGJlIGhpZGRlblxuICogQHBhcmFtIHtib29sZWFufSBvcHRpb25zLmtlZXBFeGlzdGluZ0NvbmZpZyB3aGV0aGVyIHRvIGtlZXAgZXhpdGluZyBsYXllciBmaWx0ZXIgYW5kIGludGVyYWN0aW9uIGNvbmZpZyBgZGVmYXVsdDogZmFsc2VgLlxuICogQHBhcmFtIHtib29sZWFufSBvcHRpb25zLmF1dG9DcmVhdGVMYXllcnMgd2hldGhlciB0byBhdXRvbWF0aWNhbGx5IGNyZWF0ZSBsYXllcnMgYmFzZWQgb24gZGF0YXNldCBjb2x1bW5zIGBkZWZhdWx0OiB0cnVlYC5cbiAqIEBwdWJsaWNcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQge3JlY2VpdmVNYXBDb25maWd9IGZyb20gJ2tlcGxlci5nbC9hY3Rpb25zJztcbiAqIGltcG9ydCBLZXBsZXJHbFNjaGVtYSBmcm9tICdrZXBsZXIuZ2wvc2NoZW1hcyc7XG4gKlxuICogY29uc3QgcGFyc2VkQ29uZmlnID0gS2VwbGVyR2xTY2hlbWEucGFyc2VTYXZlZENvbmZpZyhjb25maWcpO1xuICogdGhpcy5wcm9wcy5kaXNwYXRjaChyZWNlaXZlTWFwQ29uZmlnKHBhcnNlZENvbmZpZykpO1xuICovXG5leHBvcnQgY29uc3QgcmVjZWl2ZU1hcENvbmZpZzogKFxuICBjb25maWc6IFJlY2VpdmVNYXBDb25maWdQYXlsb2FkWydjb25maWcnXSxcbiAgb3B0aW9uczogUmVjZWl2ZU1hcENvbmZpZ1BheWxvYWRbJ29wdGlvbnMnXVxuKSA9PiB7XG4gIHR5cGU6IHR5cGVvZiBBY3Rpb25UeXBlcy5SRUNFSVZFX01BUF9DT05GSUc7XG4gIHBheWxvYWQ6IFJlY2VpdmVNYXBDb25maWdQYXlsb2FkO1xufSA9IGNyZWF0ZUFjdGlvbihcbiAgQWN0aW9uVHlwZXMuUkVDRUlWRV9NQVBfQ09ORklHLFxuICAoY29uZmlnOiBSZWNlaXZlTWFwQ29uZmlnUGF5bG9hZFsnY29uZmlnJ10sIG9wdGlvbnM6IFJlY2VpdmVNYXBDb25maWdQYXlsb2FkWydvcHRpb25zJ10pID0+ICh7XG4gICAgcGF5bG9hZDoge1xuICAgICAgY29uZmlnLFxuICAgICAgb3B0aW9uc1xuICAgIH1cbiAgfSlcbik7XG5cbmV4cG9ydCB0eXBlIEtlcGxlckdsSW5pdFBheWxvYWQgPSB7XG4gIG1hcGJveEFwaUFjY2Vzc1Rva2VuPzogc3RyaW5nO1xuICBtYXBib3hBcGlVcmw/OiBzdHJpbmc7XG4gIG1hcFN0eWxlc1JlcGxhY2VEZWZhdWx0PzogYm9vbGVhbjtcbiAgaW5pdGlhbFVpU3RhdGU/OiBQYXJ0aWFsPFVpU3RhdGU+O1xufTtcbi8qKlxuICogSW5pdGlhbGl6ZSBrZXBsZXIuZ2wgcmVkdWNlci4gSXQgaXMgdXNlZCB0byBwYXNzIGluIGBtYXBib3hBcGlBY2Nlc3NUb2tlbmAgdG8gYG1hcFN0eWxlYCByZWR1Y2VyLlxuICogQG1lbWJlcm9mIG1haW5cbiAqIEBwYXJhbSB7b2JqZWN0fSBwYXlsb2FkXG4gKiBAcGFyYW0gcGF5bG9hZC5tYXBib3hBcGlBY2Nlc3NUb2tlbiAtIG1hcGJveEFwaUFjY2Vzc1Rva2VuIHRvIGJlIHNhdmVkIHRvIG1hcFN0eWxlIHJlZHVjZXJcbiAqIEBwYXJhbSBwYXlsb2FkLm1hcGJveEFwaVVybCAtIG1hcGJveEFwaVVybCB0byBiZSBzYXZlZCB0byBtYXBTdHlsZSByZWR1Y2VyLlxuICogQHBhcmFtIHBheWxvYWQubWFwU3R5bGVzUmVwbGFjZURlZmF1bHQgLSBtYXBTdHlsZXNSZXBsYWNlRGVmYXVsdCB0byBiZSBzYXZlZCB0byBtYXBTdHlsZSByZWR1Y2VyXG4gKiBAcGFyYW0gcGF5bG9hZC5pbml0aWFsVWlTdGF0ZSAtIGluaXRpYWwgdWkgc3RhdGVcbiAqIEBwdWJsaWNcbiAqL1xuLy8gQHRzLWV4cGVjdC1lcnJvclxuZXhwb3J0IGNvbnN0IGtlcGxlckdsSW5pdDogKG9wdGlvbnM/OiBLZXBsZXJHbEluaXRQYXlsb2FkKSA9PiB7XG4gIHR5cGU6IHR5cGVvZiBBY3Rpb25UeXBlcy5JTklUO1xuICBwYXlsb2FkOiBLZXBsZXJHbEluaXRQYXlsb2FkO1xufSA9IGNyZWF0ZUFjdGlvbihBY3Rpb25UeXBlcy5JTklULCAocGF5bG9hZDogS2VwbGVyR2xJbml0UGF5bG9hZCkgPT4gKHtwYXlsb2FkfSkpO1xuXG5leHBvcnQgdHlwZSBSZXBsYWNlRGF0YVRvTWFwT3B0aW9ucyA9IHtcbiAgY2VudGVyTWFwPzogYm9vbGVhbjtcbiAga2VlcEV4aXN0aW5nQ29uZmlnPzogYm9vbGVhbjtcbiAgYXV0b0NyZWF0ZUxheWVycz86IGJvb2xlYW47XG59O1xuZXhwb3J0IHR5cGUgUmVwbGFjZURhdGFJbk1hcFBheWxvYWQgPSB7XG4gIGRhdGFzZXRUb1JlcGxhY2VJZDogc3RyaW5nO1xuICBkYXRhc2V0VG9Vc2U6IFByb3RvRGF0YXNldDtcbiAgb3B0aW9ucz86IFJlcGxhY2VEYXRhVG9NYXBPcHRpb25zO1xufTtcblxuLyoqXG4gKiBJbml0aWFsaXplIGtlcGxlci5nbCByZWR1Y2VyLiBJdCBpcyB1c2VkIHRvIHBhc3MgaW4gYG1hcGJveEFwaUFjY2Vzc1Rva2VuYCB0byBgbWFwU3R5bGVgIHJlZHVjZXIuXG4gKiBAbWVtYmVyb2YgbWFpblxuICogQHBhcmFtIHBheWxvYWRcbiAqIEBwYXJhbSBwYXlsb2FkLmRhdGFzZXRUb1JlcGxhY2VJZCAtIG1hcGJveEFwaUFjY2Vzc1Rva2VuIHRvIGJlIHNhdmVkIHRvIG1hcFN0eWxlIHJlZHVjZXJcbiAqIEBwYXJhbSBwYXlsb2FkLmRhdGFzZXRUb1VzZSAtIG1hcGJveEFwaVVybCB0byBiZSBzYXZlZCB0byBtYXBTdHlsZSByZWR1Y2VyLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgcmVwbGFjZURhdGFJbk1hcDogKHBheWxvYWQ6IFJlcGxhY2VEYXRhSW5NYXBQYXlsb2FkKSA9PiB7XG4gIHR5cGU6IHR5cGVvZiBBY3Rpb25UeXBlcy5SRVBMQUNFX0RBVEFfSU5fTUFQO1xuICBwYXlsb2FkOiBSZXBsYWNlRGF0YUluTWFwUGF5bG9hZDtcbn0gPSBjcmVhdGVBY3Rpb24oQWN0aW9uVHlwZXMuUkVQTEFDRV9EQVRBX0lOX01BUCwgKHBheWxvYWQ6IFJlcGxhY2VEYXRhSW5NYXBQYXlsb2FkKSA9PiAoe1xuICBwYXlsb2FkXG59KSk7XG5cbi8qKlxuICogVGhpcyBkZWNsYXJhdGlvbiBpcyBuZWVkZWQgdG8gZ3JvdXAgYWN0aW9ucyBpbiBkb2NzXG4gKi9cbi8qKlxuICogTWFpbiBrZXBsZXIuZ2wgYWN0aW9ucywgdGhlc2UgYWN0aW9ucyBoYW5kbGVzIGxvYWRpbmcgZGF0YSBhbmQgY29uZmlnIGludG8ga2VwbGVyLmdsIHJlZHVjZXIuIFRoZXNlIGFjdGlvbnNcbiAqIGlzIGxpc3RlbmVkIGJ5IGFsbCBzdWJyZWR1Y2VycyxcbiAqIEBwdWJsaWNcbiAqL1xuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG4vLyBAdHMtaWdub3JlXG5jb25zdCBtYWluID0gbnVsbDtcbi8qIGVzbGludC1lbmFibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFHQSxJQUFBQSxZQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxRQUFBLEdBQUFELE9BQUE7QUFKQTtBQUNBOztBQXNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxJQUFNRSxZQUdaLEdBQUFDLE9BQUEsQ0FBQUQsWUFBQSxHQUFHLElBQUFFLHFCQUFZLEVBQUNDLHVCQUFXLENBQUNDLGVBQWUsRUFBRSxVQUFDQyxJQUF5QjtFQUFBLE9BQU07SUFBQ0MsT0FBTyxFQUFFRDtFQUFJLENBQUM7QUFBQSxDQUFDLENBQUM7O0FBRS9GO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxJQUFNRSxjQUFpRSxHQUFBTixPQUFBLENBQUFNLGNBQUEsR0FBRyxJQUFBTCxxQkFBWSxFQUMzRkMsdUJBQVcsQ0FBQ0ssZ0JBQ2QsQ0FBQztBQU9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sSUFBTUMsZ0JBTVosR0FBQVIsT0FBQSxDQUFBUSxnQkFBQSxHQUFHLElBQUFQLHFCQUFZLEVBQ2RDLHVCQUFXLENBQUNPLGtCQUFrQixFQUM5QixVQUFDQyxNQUF5QyxFQUFFQyxPQUEyQztFQUFBLE9BQU07SUFDM0ZOLE9BQU8sRUFBRTtNQUNQSyxNQUFNLEVBQU5BLE1BQU07TUFDTkMsT0FBTyxFQUFQQTtJQUNGO0VBQ0YsQ0FBQztBQUFBLENBQ0gsQ0FBQztBQVFEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxJQUFNQyxZQUdaLEdBQUFaLE9BQUEsQ0FBQVksWUFBQSxHQUFHLElBQUFYLHFCQUFZLEVBQUNDLHVCQUFXLENBQUNXLElBQUksRUFBRSxVQUFDUixPQUE0QjtFQUFBLE9BQU07SUFBQ0EsT0FBTyxFQUFQQTtFQUFPLENBQUM7QUFBQSxDQUFDLENBQUM7QUFhakY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNPLElBQU1TLGdCQUdaLEdBQUFkLE9BQUEsQ0FBQWMsZ0JBQUEsR0FBRyxJQUFBYixxQkFBWSxFQUFDQyx1QkFBVyxDQUFDYSxtQkFBbUIsRUFBRSxVQUFDVixPQUFnQztFQUFBLE9BQU07SUFDdkZBLE9BQU8sRUFBUEE7RUFDRixDQUFDO0FBQUEsQ0FBQyxDQUFDOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBTVcsSUFBSSxHQUFHLElBQUk7QUFDakIiLCJpZ25vcmVMaXN0IjpbXX0=
;