kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
385 lines (373 loc) • 35.3 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.KEPLER_FORMAT = exports.FILE_CONFLICT_MSG = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _upload = _interopRequireDefault(require("./upload"));
// SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
var NAME = 'cloud-provider';
var DISPLAY_NAME = 'Cloud Provider';
var THUMBNAIL = {
width: 300,
height: 200
};
var ICON = _upload["default"];
var KEPLER_FORMAT = exports.KEPLER_FORMAT = 'keplergl';
var FILE_CONFLICT_MSG = exports.FILE_CONFLICT_MSG = 'file_conflict';
/**
* The default provider class
* @param {object} props
* @param {string} props.name
* @param {string} props.displayName
* @param {React.Component} props.icon - React element
* @param {object} props.thumbnail - thumbnail size object
* @param {number} props.thumbnail.width - thumbnail width in pixels
* @param {number} props.thumbnail.height - thumbnail height in pixels
* @public
* @example
*
* const myProvider = new Provider({
* name: 'foo',
* displayName: 'Foo Storage'
* icon: Icon,
* thumbnail: {width: 300, height: 200}
* })
*/
var Provider = exports["default"] = /*#__PURE__*/function () {
function Provider(props) {
(0, _classCallCheck2["default"])(this, Provider);
(0, _defineProperty2["default"])(this, "name", void 0);
(0, _defineProperty2["default"])(this, "displayName", void 0);
(0, _defineProperty2["default"])(this, "storageMessage", void 0);
(0, _defineProperty2["default"])(this, "icon", void 0);
(0, _defineProperty2["default"])(this, "thumbnail", void 0);
(0, _defineProperty2["default"])(this, "isNew", false);
this.name = props.name || NAME;
this.displayName = props.displayName || DISPLAY_NAME;
this.storageMessage = props.storageMessage;
this.icon = props.icon || ICON;
this.thumbnail = props.thumbnail || THUMBNAIL;
}
/**
* Whether this provider support upload map to a private storage. If truthy, user will be displayed with the storage save icon on the top right of the side bar.
* @returns
* @public
*/
return (0, _createClass2["default"])(Provider, [{
key: "hasPrivateStorage",
value: function hasPrivateStorage() {
return true;
}
/**
* Whether this provider support share map via a public url, if truthy, user will be displayed with a share map via url under the export map option on the top right of the side bar
* @returns
* @public
*/
}, {
key: "hasSharingUrl",
value: function hasSharingUrl() {
return false;
}
/**
* This method is called after user share a map, to display the share url.
* @param fullUrl - Whether to return the full url with domain, or just the location
* @returns shareUrl
* @public
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}, {
key: "getShareUrl",
value: function getShareUrl() {
var fullUrl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
return '';
}
/**
* This method is called by kepler.gl demo app to pushes a new location to history, becoming the current location.
* @returns mapUrl
* @public
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}, {
key: "getMapUrl",
value: function getMapUrl(loadParams) {
return '';
}
/**
* This method is called to determine whether user already logged in to this provider
* @public
* @returns {Promise<string>} return the access token if a user already logged in
*/
}, {
key: "getAccessToken",
value: (function () {
var _getAccessToken = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
return _context.abrupt("return", Promise.reject('You must implement getAccessToken'));
case 1:
case "end":
return _context.stop();
}
}, _callee);
}));
function getAccessToken() {
return _getAccessToken.apply(this, arguments);
}
return getAccessToken;
}()
/**
* This method is called to get the user name of the current user. It will be displayed in the cloud provider tile.
* @public
* @deprecated please use getUser
* @returns true if a user already logged in
*/
)
}, {
key: "getUserName",
value: function getUserName() {
return '';
}
/**
* return a Promise with the user object
*/
}, {
key: "getUser",
value: (function () {
var _getUser = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() {
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
return _context2.abrupt("return", Promise.reject('You must implement getUser'));
case 1:
case "end":
return _context2.stop();
}
}, _callee2);
}));
function getUser() {
return _getUser.apply(this, arguments);
}
return getUser;
}()
/**
* This return a standard error that will trigger the overwrite map modal
*/
)
}, {
key: "getFileConflictError",
value: function getFileConflictError() {
return new Error(FILE_CONFLICT_MSG);
}
/**
* This method will be called when user click the login button in the cloud provider tile.
* Upon login success and return the user Object {name, email, abbreviated}
* @public
*/
}, {
key: "login",
value: (function () {
var _login = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3() {
return _regenerator["default"].wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
return _context3.abrupt("return", Promise.reject(new Error('you must implement the `login` method')));
case 1:
case "end":
return _context3.stop();
}
}, _callee3);
}));
function login() {
return _login.apply(this, arguments);
}
return login;
}()
/**
* This method will be called when user click the logout button under the cloud provider tile.
* Upon login success
* @public
*/
)
}, {
key: "logout",
value: (function () {
var _logout = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4() {
return _regenerator["default"].wrap(function _callee4$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
return _context4.abrupt("return", Promise.reject(new Error('you must implement the `logout` method')));
case 1:
case "end":
return _context4.stop();
}
}, _callee4);
}));
function logout() {
return _logout.apply(this, arguments);
}
return logout;
}()
/**
* This method will be called to upload map for saving and sharing. Kepler.gl will package map data, config, title, description and thumbnail for upload to storage.
* With the option to overwrite already saved map, and upload as private or public map.
*
* @param {Object} param
* @param {Object} param.mapData - the map object
* @param {Object} param.mapData.map - {datasets. config, info: {title, description}}
* @param {Blob} param.mapData.thumbnail - A thumbnail of current map. thumbnail size can be defined by provider by this.thumbnail
* @param {object} [param.options]
* @param {boolean} [param.options.overwrite] - whether user choose to overwrite already saved map under the same name
* @param {boolean} [param.options.isPublic] - whether user wish to share the map with others. if isPublic is truthy, kepler will call this.getShareUrl() to display an URL they can share with others
* @public
*/
)
}, {
key: "uploadMap",
value: (function () {
var _uploadMap = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(_ref) {
var mapData, _ref$options, options;
return _regenerator["default"].wrap(function _callee5$(_context5) {
while (1) switch (_context5.prev = _context5.next) {
case 0:
mapData = _ref.mapData, _ref$options = _ref.options, options = _ref$options === void 0 ? {} : _ref$options;
return _context5.abrupt("return", Promise.reject('You must implement uploadMap'));
case 2:
case "end":
return _context5.stop();
}
}, _callee5);
}));
function uploadMap(_x) {
return _uploadMap.apply(this, arguments);
}
return uploadMap;
}()
/**
* This method is called to get a list of maps saved by the current logged in user.
* @returns visualizations an array of Viz objects
* @public
* @example
* async listMaps() {
* return [
* {
* id: 'a',
* title: 'My map',
* description: 'My first kepler map',
* imageUrl: 'http://',
* updatedAt: 1582677787000,
* privateMap: false,
* loadParams: {}
* }
* ];
* }
*/
)
}, {
key: "listMaps",
value: (function () {
var _listMaps = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6() {
return _regenerator["default"].wrap(function _callee6$(_context6) {
while (1) switch (_context6.prev = _context6.next) {
case 0:
return _context6.abrupt("return", []);
case 1:
case "end":
return _context6.stop();
}
}, _callee6);
}));
function listMaps() {
return _listMaps.apply(this, arguments);
}
return listMaps;
}()
/**
* This method will be called when user select a map to load from the storage map viewer
* @param {*} loadParams - the loadParams property of each visualization object
* @returns mapResponse - the map object containing dataset config info and format option
* @public
* @example
* async downloadMap(loadParams) {
* const mockResponse = {
* map: {
* datasets: [],
* config: {},
* info: {
* app: 'kepler.gl',
* created_at: ''
* title: 'test map',
* description: 'Hello this is my test dropbox map'
* }
* },
* // pass csv here if your provider currently only support save / load file as csv
* format: 'keplergl'
* };
*
* return downloadMap;
* }
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
)
}, {
key: "downloadMap",
value: (function () {
var _downloadMap = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee7(loadParams) {
return _regenerator["default"].wrap(function _callee7$(_context7) {
while (1) switch (_context7.prev = _context7.next) {
case 0:
return _context7.abrupt("return", Promise.reject('You must implement downloadMap'));
case 1:
case "end":
return _context7.stop();
}
}, _callee7);
}));
function downloadMap(_x2) {
return _downloadMap.apply(this, arguments);
}
return downloadMap;
}()
/**
* @return {string} return the storage location url for the current provider
* @public
*/
)
}, {
key: "getManagementUrl",
value: function getManagementUrl() {
throw new Error('You must implement getManagementUrl');
}
/**
* @typedef {Object} Viz
* @property {string} id - An unique id
* @property {string} title - The title of the map
* @property {string} description - The description of the map
* @property {string} imageUrl - The imageUrl of the map
* @property {number} updatedAt - An epoch timestamp in milliseconds
* @property {boolean} privateMap - Optional, whether if this map is private to the user, or can be accessed by others via URL
* @property {*} loadParams - A property to be passed to `downloadMap`
* @public
*/
/**
* The returned object of `downloadMap`. The response object should contain: datasets: [], config: {}, and info: {}
* each dataset object should be {info: {id, label}, data: {...}}
* to inform how kepler should process your data object, pass in `format`
* @typedef {Object} MapResponse
* @property {Object} map
* @property {Array<Object>} map.datasets
* @property {Object} map.config
* @property {Object} map.info
* @property {string} format - one of 'csv': csv file string, 'geojson': geojson object, 'row': row object, 'keplergl': datasets array saved using KeplerGlSchema.save
* @public
*/
}]);
}();
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfdXBsb2FkIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJOQU1FIiwiRElTUExBWV9OQU1FIiwiVEhVTUJOQUlMIiwid2lkdGgiLCJoZWlnaHQiLCJJQ09OIiwiVXBsb2FkIiwiS0VQTEVSX0ZPUk1BVCIsImV4cG9ydHMiLCJGSUxFX0NPTkZMSUNUX01TRyIsIlByb3ZpZGVyIiwicHJvcHMiLCJfY2xhc3NDYWxsQ2hlY2syIiwiX2RlZmluZVByb3BlcnR5MiIsIm5hbWUiLCJkaXNwbGF5TmFtZSIsInN0b3JhZ2VNZXNzYWdlIiwiaWNvbiIsInRodW1ibmFpbCIsIl9jcmVhdGVDbGFzczIiLCJrZXkiLCJ2YWx1ZSIsImhhc1ByaXZhdGVTdG9yYWdlIiwiaGFzU2hhcmluZ1VybCIsImdldFNoYXJlVXJsIiwiZnVsbFVybCIsImFyZ3VtZW50cyIsImxlbmd0aCIsInVuZGVmaW5lZCIsImdldE1hcFVybCIsImxvYWRQYXJhbXMiLCJfZ2V0QWNjZXNzVG9rZW4iLCJfYXN5bmNUb0dlbmVyYXRvcjIiLCJfcmVnZW5lcmF0b3IiLCJtYXJrIiwiX2NhbGxlZSIsIndyYXAiLCJfY2FsbGVlJCIsIl9jb250ZXh0IiwicHJldiIsIm5leHQiLCJhYnJ1cHQiLCJQcm9taXNlIiwicmVqZWN0Iiwic3RvcCIsImdldEFjY2Vzc1Rva2VuIiwiYXBwbHkiLCJnZXRVc2VyTmFtZSIsIl9nZXRVc2VyIiwiX2NhbGxlZTIiLCJfY2FsbGVlMiQiLCJfY29udGV4dDIiLCJnZXRVc2VyIiwiZ2V0RmlsZUNvbmZsaWN0RXJyb3IiLCJFcnJvciIsIl9sb2dpbiIsIl9jYWxsZWUzIiwiX2NhbGxlZTMkIiwiX2NvbnRleHQzIiwibG9naW4iLCJfbG9nb3V0IiwiX2NhbGxlZTQiLCJfY2FsbGVlNCQiLCJfY29udGV4dDQiLCJsb2dvdXQiLCJfdXBsb2FkTWFwIiwiX2NhbGxlZTUiLCJfcmVmIiwibWFwRGF0YSIsIl9yZWYkb3B0aW9ucyIsIm9wdGlvbnMiLCJfY2FsbGVlNSQiLCJfY29udGV4dDUiLCJ1cGxvYWRNYXAiLCJfeCIsIl9saXN0TWFwcyIsIl9jYWxsZWU2IiwiX2NhbGxlZTYkIiwiX2NvbnRleHQ2IiwibGlzdE1hcHMiLCJfZG93bmxvYWRNYXAiLCJfY2FsbGVlNyIsIl9jYWxsZWU3JCIsIl9jb250ZXh0NyIsImRvd25sb2FkTWFwIiwiX3gyIiwiZ2V0TWFuYWdlbWVudFVybCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbG91ZC1wcm92aWRlcnMvc3JjL3Byb3ZpZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCBVcGxvYWQgZnJvbSAnLi91cGxvYWQnO1xuaW1wb3J0IHtNYXBEYXRhLCBFeHBvcnRGaWxlT3B0aW9ucywgTWlsbGlzZWNvbmQsIFNhdmVkTWFwfSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcbmltcG9ydCB7Q29tcG9uZW50VHlwZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgdHlwZSBNYXBJdGVtTG9hZFBhcmFtcyA9IHtcbiAgaWQ6IHN0cmluZztcbiAgcGF0aDogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgTWFwTGlzdEl0ZW0gPSB7XG4gIGlkOiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGxvYWRQYXJhbXM6IGFueTtcbiAgaW1hZ2VVcmw/OiBzdHJpbmc7XG4gIHVwZGF0ZWRBdD86IE1pbGxpc2Vjb25kO1xuICBwcml2YXRlTWFwPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIENsb3VkVXNlciA9IHtcbiAgbmFtZTogc3RyaW5nO1xuICBlbWFpbDogc3RyaW5nO1xuICB0aHVtYm5haWw/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBUaHVtYm5haWwgPSB7XG4gIHdpZHRoOiBudW1iZXI7XG4gIGhlaWdodDogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgUHJvdmlkZXJQcm9wcyA9IHtcbiAgbmFtZT86IHN0cmluZztcbiAgZGlzcGxheU5hbWU/OiBzdHJpbmc7XG4gIHN0b3JhZ2VNZXNzYWdlPzogc3RyaW5nO1xuICBpY29uPzogQ29tcG9uZW50VHlwZTxJY29uUHJvcHM+O1xuICB0aHVtYm5haWw/OiBUaHVtYm5haWw7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIEljb25Qcm9wcyB7XG4gIGhlaWdodD86IHN0cmluZztcbiAgd2lkdGg/OiBzdHJpbmc7XG59XG5cbmNvbnN0IE5BTUUgPSAnY2xvdWQtcHJvdmlkZXInO1xuY29uc3QgRElTUExBWV9OQU1FID0gJ0Nsb3VkIFByb3ZpZGVyJztcbmNvbnN0IFRIVU1CTkFJTCA9IHt3aWR0aDogMzAwLCBoZWlnaHQ6IDIwMH07XG5jb25zdCBJQ09OID0gVXBsb2FkO1xuZXhwb3J0IGNvbnN0IEtFUExFUl9GT1JNQVQgPSAna2VwbGVyZ2wnO1xuZXhwb3J0IGNvbnN0IEZJTEVfQ09ORkxJQ1RfTVNHID0gJ2ZpbGVfY29uZmxpY3QnO1xuXG4vKipcbiAqIFRoZSBkZWZhdWx0IHByb3ZpZGVyIGNsYXNzXG4gKiBAcGFyYW0ge29iamVjdH0gcHJvcHNcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wcy5uYW1lXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcHMuZGlzcGxheU5hbWVcbiAqIEBwYXJhbSB7UmVhY3QuQ29tcG9uZW50fSBwcm9wcy5pY29uIC0gUmVhY3QgZWxlbWVudFxuICogQHBhcmFtIHtvYmplY3R9IHByb3BzLnRodW1ibmFpbCAtIHRodW1ibmFpbCBzaXplIG9iamVjdFxuICogQHBhcmFtIHtudW1iZXJ9IHByb3BzLnRodW1ibmFpbC53aWR0aCAtIHRodW1ibmFpbCB3aWR0aCBpbiBwaXhlbHNcbiAqIEBwYXJhbSB7bnVtYmVyfSBwcm9wcy50aHVtYm5haWwuaGVpZ2h0IC0gdGh1bWJuYWlsIGhlaWdodCBpbiBwaXhlbHNcbiAqIEBwdWJsaWNcbiAqIEBleGFtcGxlXG4gKlxuICogY29uc3QgbXlQcm92aWRlciA9IG5ldyBQcm92aWRlcih7XG4gKiAgbmFtZTogJ2ZvbycsXG4gKiAgZGlzcGxheU5hbWU6ICdGb28gU3RvcmFnZSdcbiAqICBpY29uOiBJY29uLFxuICogIHRodW1ibmFpbDoge3dpZHRoOiAzMDAsIGhlaWdodDogMjAwfVxuICogfSlcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHJvdmlkZXIge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gIHN0b3JhZ2VNZXNzYWdlPzogc3RyaW5nO1xuICBpY29uOiBDb21wb25lbnRUeXBlPEljb25Qcm9wcz47XG4gIHRodW1ibmFpbDogVGh1bWJuYWlsO1xuICBpc05ldyA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzOiBQcm92aWRlclByb3BzKSB7XG4gICAgdGhpcy5uYW1lID0gcHJvcHMubmFtZSB8fCBOQU1FO1xuICAgIHRoaXMuZGlzcGxheU5hbWUgPSBwcm9wcy5kaXNwbGF5TmFtZSB8fCBESVNQTEFZX05BTUU7XG4gICAgdGhpcy5zdG9yYWdlTWVzc2FnZSA9IHByb3BzLnN0b3JhZ2VNZXNzYWdlO1xuICAgIHRoaXMuaWNvbiA9IHByb3BzLmljb24gfHwgSUNPTjtcbiAgICB0aGlzLnRodW1ibmFpbCA9IHByb3BzLnRodW1ibmFpbCB8fCBUSFVNQk5BSUw7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHByb3ZpZGVyIHN1cHBvcnQgdXBsb2FkIG1hcCB0byBhIHByaXZhdGUgc3RvcmFnZS4gSWYgdHJ1dGh5LCB1c2VyIHdpbGwgYmUgZGlzcGxheWVkIHdpdGggdGhlIHN0b3JhZ2Ugc2F2ZSBpY29uIG9uIHRoZSB0b3AgcmlnaHQgb2YgdGhlIHNpZGUgYmFyLlxuICAgKiBAcmV0dXJuc1xuICAgKiBAcHVibGljXG4gICAqL1xuICBoYXNQcml2YXRlU3RvcmFnZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgcHJvdmlkZXIgc3VwcG9ydCBzaGFyZSBtYXAgdmlhIGEgcHVibGljIHVybCwgaWYgdHJ1dGh5LCB1c2VyIHdpbGwgYmUgZGlzcGxheWVkIHdpdGggYSBzaGFyZSBtYXAgdmlhIHVybCB1bmRlciB0aGUgZXhwb3J0IG1hcCBvcHRpb24gb24gdGhlIHRvcCByaWdodCBvZiB0aGUgc2lkZSBiYXJcbiAgICogQHJldHVybnNcbiAgICogQHB1YmxpY1xuICAgKi9cbiAgaGFzU2hhcmluZ1VybCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIGFmdGVyIHVzZXIgc2hhcmUgYSBtYXAsIHRvIGRpc3BsYXkgdGhlIHNoYXJlIHVybC5cbiAgICogQHBhcmFtIGZ1bGxVcmwgLSBXaGV0aGVyIHRvIHJldHVybiB0aGUgZnVsbCB1cmwgd2l0aCBkb21haW4sIG9yIGp1c3QgdGhlIGxvY2F0aW9uXG4gICAqIEByZXR1cm5zIHNoYXJlVXJsXG4gICAqIEBwdWJsaWNcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgZ2V0U2hhcmVVcmwoZnVsbFVybCA9IGZhbHNlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIGJ5IGtlcGxlci5nbCBkZW1vIGFwcCB0byBwdXNoZXMgYSBuZXcgbG9jYXRpb24gdG8gaGlzdG9yeSwgYmVjb21pbmcgdGhlIGN1cnJlbnQgbG9jYXRpb24uXG4gICAqIEByZXR1cm5zIG1hcFVybFxuICAgKiBAcHVibGljXG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGdldE1hcFVybChsb2FkUGFyYW1zOiBNYXBJdGVtTG9hZFBhcmFtcyk6IHN0cmluZyB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB0byBkZXRlcm1pbmUgd2hldGhlciB1c2VyIGFscmVhZHkgbG9nZ2VkIGluIHRvIHRoaXMgcHJvdmlkZXJcbiAgICogQHB1YmxpY1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSByZXR1cm4gdGhlIGFjY2VzcyB0b2tlbiBpZiBhIHVzZXIgYWxyZWFkeSBsb2dnZWQgaW5cbiAgICovXG4gIGFzeW5jIGdldEFjY2Vzc1Rva2VuKCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnWW91IG11c3QgaW1wbGVtZW50IGdldEFjY2Vzc1Rva2VuJyk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIHRvIGdldCB0aGUgdXNlciBuYW1lIG9mIHRoZSBjdXJyZW50IHVzZXIuIEl0IHdpbGwgYmUgZGlzcGxheWVkIGluIHRoZSBjbG91ZCBwcm92aWRlciB0aWxlLlxuICAgKiBAcHVibGljXG4gICAqIEBkZXByZWNhdGVkIHBsZWFzZSB1c2UgZ2V0VXNlclxuICAgKiBAcmV0dXJucyB0cnVlIGlmIGEgdXNlciBhbHJlYWR5IGxvZ2dlZCBpblxuICAgKi9cbiAgZ2V0VXNlck5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICAvKipcbiAgICogcmV0dXJuIGEgUHJvbWlzZSB3aXRoIHRoZSB1c2VyIG9iamVjdFxuICAgKi9cbiAgYXN5bmMgZ2V0VXNlcigpOiBQcm9taXNlPENsb3VkVXNlciB8IG51bGw+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ1lvdSBtdXN0IGltcGxlbWVudCBnZXRVc2VyJyk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyByZXR1cm4gYSBzdGFuZGFyZCBlcnJvciB0aGF0IHdpbGwgdHJpZ2dlciB0aGUgb3ZlcndyaXRlIG1hcCBtb2RhbFxuICAgKi9cbiAgZ2V0RmlsZUNvbmZsaWN0RXJyb3IoKSB7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihGSUxFX0NPTkZMSUNUX01TRyk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgd2hlbiB1c2VyIGNsaWNrIHRoZSBsb2dpbiBidXR0b24gaW4gdGhlIGNsb3VkIHByb3ZpZGVyIHRpbGUuXG4gICAqIFVwb24gbG9naW4gc3VjY2VzcyBhbmQgcmV0dXJuIHRoZSB1c2VyIE9iamVjdCB7bmFtZSwgZW1haWwsIGFiYnJldmlhdGVkfVxuICAgKiBAcHVibGljXG4gICAqL1xuICBhc3luYyBsb2dpbigpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCd5b3UgbXVzdCBpbXBsZW1lbnQgdGhlIGBsb2dpbmAgbWV0aG9kJykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHdoZW4gdXNlciBjbGljayB0aGUgbG9nb3V0IGJ1dHRvbiB1bmRlciB0aGUgY2xvdWQgcHJvdmlkZXIgdGlsZS5cbiAgICogVXBvbiBsb2dpbiBzdWNjZXNzXG4gICAqIEBwdWJsaWNcbiAgICovXG4gIGFzeW5jIGxvZ291dCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCd5b3UgbXVzdCBpbXBsZW1lbnQgdGhlIGBsb2dvdXRgIG1ldGhvZCcpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCB0byB1cGxvYWQgbWFwIGZvciBzYXZpbmcgYW5kIHNoYXJpbmcuIEtlcGxlci5nbCB3aWxsIHBhY2thZ2UgbWFwIGRhdGEsIGNvbmZpZywgdGl0bGUsIGRlc2NyaXB0aW9uIGFuZCB0aHVtYm5haWwgZm9yIHVwbG9hZCB0byBzdG9yYWdlLlxuICAgKiBXaXRoIHRoZSBvcHRpb24gdG8gb3ZlcndyaXRlIGFscmVhZHkgc2F2ZWQgbWFwLCBhbmQgdXBsb2FkIGFzIHByaXZhdGUgb3IgcHVibGljIG1hcC5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbS5tYXBEYXRhIC0gdGhlIG1hcCBvYmplY3RcbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtLm1hcERhdGEubWFwIC0ge2RhdGFzZXRzLiBjb25maWcsIGluZm86IHt0aXRsZSwgZGVzY3JpcHRpb259fVxuICAgKiBAcGFyYW0ge0Jsb2J9IHBhcmFtLm1hcERhdGEudGh1bWJuYWlsIC0gQSB0aHVtYm5haWwgb2YgY3VycmVudCBtYXAuIHRodW1ibmFpbCBzaXplIGNhbiBiZSBkZWZpbmVkIGJ5IHByb3ZpZGVyIGJ5IHRoaXMudGh1bWJuYWlsXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBbcGFyYW0ub3B0aW9uc11cbiAgICogQHBhcmFtIHtib29sZWFufSBbcGFyYW0ub3B0aW9ucy5vdmVyd3JpdGVdIC0gd2hldGhlciB1c2VyIGNob29zZSB0byBvdmVyd3JpdGUgYWxyZWFkeSBzYXZlZCBtYXAgdW5kZXIgdGhlIHNhbWUgbmFtZVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtwYXJhbS5vcHRpb25zLmlzUHVibGljXSAtIHdoZXRoZXIgdXNlciB3aXNoIHRvIHNoYXJlIHRoZSBtYXAgd2l0aCBvdGhlcnMuIGlmIGlzUHVibGljIGlzIHRydXRoeSwga2VwbGVyIHdpbGwgY2FsbCB0aGlzLmdldFNoYXJlVXJsKCkgdG8gZGlzcGxheSBhbiBVUkwgdGhleSBjYW4gc2hhcmUgd2l0aCBvdGhlcnNcbiAgICogQHB1YmxpY1xuICAgKi9cbiAgYXN5bmMgdXBsb2FkTWFwKHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgbWFwRGF0YSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgb3B0aW9ucyA9IHt9XG4gIH06IHtcbiAgICBtYXBEYXRhOiBNYXBEYXRhO1xuICAgIG9wdGlvbnM6IEV4cG9ydEZpbGVPcHRpb25zO1xuICB9KTogUHJvbWlzZTxNYXBMaXN0SXRlbT4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnWW91IG11c3QgaW1wbGVtZW50IHVwbG9hZE1hcCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB0byBnZXQgYSBsaXN0IG9mIG1hcHMgc2F2ZWQgYnkgdGhlIGN1cnJlbnQgbG9nZ2VkIGluIHVzZXIuXG4gICAqIEByZXR1cm5zIHZpc3VhbGl6YXRpb25zIGFuIGFycmF5IG9mIFZpeiBvYmplY3RzXG4gICAqIEBwdWJsaWNcbiAgICogQGV4YW1wbGVcbiAgICogIGFzeW5jIGxpc3RNYXBzKCkge1xuICAgKiAgICByZXR1cm4gW1xuICAgKiAgICAgIHtcbiAgICogICAgICAgIGlkOiAnYScsXG4gICAqICAgICAgICB0aXRsZTogJ015IG1hcCcsXG4gICAqICAgICAgICBkZXNjcmlwdGlvbjogJ015IGZpcnN0IGtlcGxlciBtYXAnLFxuICAgKiAgICAgICAgaW1hZ2VVcmw6ICdodHRwOi8vJyxcbiAgICogICAgICAgIHVwZGF0ZWRBdDogMTU4MjY3Nzc4NzAwMCxcbiAgICogICAgICAgIHByaXZhdGVNYXA6IGZhbHNlLFxuICAgKiAgICAgICAgbG9hZFBhcmFtczoge31cbiAgICogICAgICB9XG4gICAqICAgIF07XG4gICAqICB9XG4gICAqL1xuICBhc3luYyBsaXN0TWFwcygpOiBQcm9taXNlPE1hcExpc3RJdGVtW10+IHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgd2hlbiB1c2VyIHNlbGVjdCBhIG1hcCB0byBsb2FkIGZyb20gdGhlIHN0b3JhZ2UgbWFwIHZpZXdlclxuICAgKiBAcGFyYW0geyp9IGxvYWRQYXJhbXMgLSB0aGUgbG9hZFBhcmFtcyBwcm9wZXJ0eSBvZiBlYWNoIHZpc3VhbGl6YXRpb24gb2JqZWN0XG4gICAqIEByZXR1cm5zIG1hcFJlc3BvbnNlIC0gdGhlIG1hcCBvYmplY3QgY29udGFpbmluZyBkYXRhc2V0IGNvbmZpZyBpbmZvIGFuZCBmb3JtYXQgb3B0aW9uXG4gICAqIEBwdWJsaWNcbiAgICogQGV4YW1wbGVcbiAgICogYXN5bmMgZG93bmxvYWRNYXAobG9hZFBhcmFtcykge1xuICAgKiAgY29uc3QgbW9ja1Jlc3BvbnNlID0ge1xuICAgKiAgICBtYXA6IHtcbiAgICogICAgICBkYXRhc2V0czogW10sXG4gICAqICAgICAgY29uZmlnOiB7fSxcbiAgICogICAgICBpbmZvOiB7XG4gICAqICAgICAgICBhcHA6ICdrZXBsZXIuZ2wnLFxuICAgKiAgICAgICAgY3JlYXRlZF9hdDogJydcbiAgICogICAgICAgIHRpdGxlOiAndGVzdCBtYXAnLFxuICAgKiAgICAgICAgZGVzY3JpcHRpb246ICdIZWxsbyB0aGlzIGlzIG15IHRlc3QgZHJvcGJveCBtYXAnXG4gICAqICAgICAgfVxuICAgKiAgICB9LFxuICAgKiAgICAvLyBwYXNzIGNzdiBoZXJlIGlmIHlvdXIgcHJvdmlkZXIgY3VycmVudGx5IG9ubHkgc3VwcG9ydCBzYXZlIC8gbG9hZCBmaWxlIGFzIGNzdlxuICAgKiAgICBmb3JtYXQ6ICdrZXBsZXJnbCdcbiAgICogIH07XG4gICAqXG4gICAqICByZXR1cm4gZG93bmxvYWRNYXA7XG4gICAqIH1cbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgYXN5bmMgZG93bmxvYWRNYXAobG9hZFBhcmFtcyk6IFByb21pc2U8e21hcDogU2F2ZWRNYXA7IGZvcm1hdDogc3RyaW5nfT4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnWW91IG11c3QgaW1wbGVtZW50IGRvd25sb2FkTWFwJyk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7c3RyaW5nfSByZXR1cm4gdGhlIHN0b3JhZ2UgbG9jYXRpb24gdXJsIGZvciB0aGUgY3VycmVudCBwcm92aWRlclxuICAgKiBAcHVibGljXG4gICAqL1xuICBnZXRNYW5hZ2VtZW50VXJsKCk6IHN0cmluZyB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgbXVzdCBpbXBsZW1lbnQgZ2V0TWFuYWdlbWVudFVybCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IFZpelxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gaWQgLSBBbiB1bmlxdWUgaWRcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IHRpdGxlIC0gVGhlIHRpdGxlIG9mIHRoZSBtYXBcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IGRlc2NyaXB0aW9uIC0gVGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBtYXBcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IGltYWdlVXJsIC0gVGhlIGltYWdlVXJsIG9mIHRoZSBtYXBcbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IHVwZGF0ZWRBdCAtIEFuIGVwb2NoIHRpbWVzdGFtcCBpbiBtaWxsaXNlY29uZHNcbiAgICogQHByb3BlcnR5IHtib29sZWFufSBwcml2YXRlTWFwIC0gT3B0aW9uYWwsIHdoZXRoZXIgaWYgdGhpcyBtYXAgaXMgcHJpdmF0ZSB0byB0aGUgdXNlciwgb3IgY2FuIGJlIGFjY2Vzc2VkIGJ5IG90aGVycyB2aWEgVVJMXG4gICAqIEBwcm9wZXJ0eSB7Kn0gbG9hZFBhcmFtcyAtIEEgcHJvcGVydHkgdG8gYmUgcGFzc2VkIHRvIGBkb3dubG9hZE1hcGBcbiAgICogQHB1YmxpY1xuICAgKi9cblxuICAvKipcbiAgICogVGhlIHJldHVybmVkIG9iamVjdCBvZiBgZG93bmxvYWRNYXBgLiBUaGUgcmVzcG9uc2Ugb2JqZWN0IHNob3VsZCBjb250YWluOiBkYXRhc2V0czogW10sIGNvbmZpZzoge30sIGFuZCBpbmZvOiB7fVxuICAgKiBlYWNoIGRhdGFzZXQgb2JqZWN0IHNob3VsZCBiZSB7aW5mbzoge2lkLCBsYWJlbH0sIGRhdGE6IHsuLi59fVxuICAgKiB0byBpbmZvcm0gaG93IGtlcGxlciBzaG91bGQgcHJvY2VzcyB5b3VyIGRhdGEgb2JqZWN0LCBwYXNzIGluIGBmb3JtYXRgXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IE1hcFJlc3BvbnNlXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtYXBcbiAgICogQHByb3BlcnR5IHtBcnJheTxPYmplY3Q+fSBtYXAuZGF0YXNldHNcbiAgICogQHByb3BlcnR5IHtPYmplY3R9IG1hcC5jb25maWdcbiAgICogQHByb3BlcnR5IHtPYmplY3R9IG1hcC5pbmZvXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBmb3JtYXQgLSBvbmUgb2YgJ2Nzdic6IGNzdiBmaWxlIHN0cmluZywgJ2dlb2pzb24nOiBnZW9qc29uIG9iamVjdCwgJ3Jvdyc6IHJvdyBvYmplY3QsICdrZXBsZXJnbCc6IGRhdGFzZXRzIGFycmF5IHNhdmVkIHVzaW5nIEtlcGxlckdsU2NoZW1hLnNhdmVcbiAgICogQHB1YmxpY1xuICAgKi9cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEsT0FBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBSEE7QUFDQTs7QUE2Q0EsSUFBTUMsSUFBSSxHQUFHLGdCQUFnQjtBQUM3QixJQUFNQyxZQUFZLEdBQUcsZ0JBQWdCO0FBQ3JDLElBQU1DLFNBQVMsR0FBRztFQUFDQyxLQUFLLEVBQUUsR0FBRztFQUFFQyxNQUFNLEVBQUU7QUFBRyxDQUFDO0FBQzNDLElBQU1DLElBQUksR0FBR0Msa0JBQU07QUFDWixJQUFNQyxhQUFhLEdBQUFDLE9BQUEsQ0FBQUQsYUFBQSxHQUFHLFVBQVU7QUFDaEMsSUFBTUUsaUJBQWlCLEdBQUFELE9BQUEsQ0FBQUMsaUJBQUEsR0FBRyxlQUFlOztBQUVoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWxCQSxJQW1CcUJDLFFBQVEsR0FBQUYsT0FBQTtFQVEzQixTQUFBRSxTQUFZQyxLQUFvQixFQUFFO0lBQUEsSUFBQUMsZ0JBQUEsbUJBQUFGLFFBQUE7SUFBQSxJQUFBRyxnQkFBQTtJQUFBLElBQUFBLGdCQUFBO0lBQUEsSUFBQUEsZ0JBQUE7SUFBQSxJQUFBQSxnQkFBQTtJQUFBLElBQUFBLGdCQUFBO0lBQUEsSUFBQUEsZ0JBQUEsNEJBRjFCLEtBQUs7SUFHWCxJQUFJLENBQUNDLElBQUksR0FBR0gsS0FBSyxDQUFDRyxJQUFJLElBQUlkLElBQUk7SUFDOUIsSUFBSSxDQUFDZSxXQUFXLEdBQUdKLEtBQUssQ0FBQ0ksV0FBVyxJQUFJZCxZQUFZO0lBQ3BELElBQUksQ0FBQ2UsY0FBYyxHQUFHTCxLQUFLLENBQUNLLGNBQWM7SUFDMUMsSUFBSSxDQUFDQyxJQUFJLEdBQUdOLEtBQUssQ0FBQ00sSUFBSSxJQUFJWixJQUFJO0lBQzlCLElBQUksQ0FBQ2EsU0FBUyxHQUFHUCxLQUFLLENBQUNPLFNBQVMsSUFBSWhCLFNBQVM7RUFDL0M7O0VBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTtFQUpFLFdBQUFpQixhQUFBLGFBQUFULFFBQUE7SUFBQVUsR0FBQTtJQUFBQyxLQUFBLEVBS0EsU0FBQUMsaUJBQWlCQSxDQUFBLEVBQVk7TUFDM0IsT0FBTyxJQUFJO0lBQ2I7O0lBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTtFQUpFO0lBQUFGLEdBQUE7SUFBQUMsS0FBQSxFQUtBLFNBQUFFLGFBQWFBLENBQUEsRUFBWTtNQUN2QixPQUFPLEtBQUs7SUFDZDs7SUFFQTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDRTtFQUFBO0lBQUFILEdBQUE7SUFBQUMsS0FBQSxFQUNBLFNBQUFHLFdBQVdBLENBQUEsRUFBMEI7TUFBQSxJQUF6QkMsT0FBTyxHQUFBQyxTQUFBLENBQUFDLE1BQUEsUUFBQUQsU0FBQSxRQUFBRSxTQUFBLEdBQUFGLFNBQUEsTUFBRyxLQUFLO01BQ3pCLE9BQU8sRUFBRTtJQUNYOztJQUVBO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7SUFDRTtFQUFBO0lBQUFOLEdBQUE7SUFBQUMsS0FBQSxFQUNBLFNBQUFRLFNBQVNBLENBQUNDLFVBQTZCLEVBQVU7TUFDL0MsT0FBTyxFQUFFO0lBQ1g7O0lBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTtFQUpFO0lBQUFWLEdBQUE7SUFBQUMsS0FBQTtNQUFBLElBQUFVLGVBQUEsT0FBQUMsa0JBQUEsMkJBQUFDLFlBQUEsWUFBQUMsSUFBQSxDQUtBLFNBQUFDLFFBQUE7UUFBQSxPQUFBRixZQUFBLFlBQUFHLElBQUEsVUFBQUMsU0FBQUMsUUFBQTtVQUFBLGtCQUFBQSxRQUFBLENBQUFDLElBQUEsR0FBQUQsUUFBQSxDQUFBRSxJQUFBO1lBQUE7Y0FBQSxPQUFBRixRQUFBLENBQUFHLE1BQUEsV0FDU0MsT0FBTyxDQUFDQyxNQUFNLENBQUMsbUNBQW1DLENBQUM7WUFBQTtZQUFBO2NBQUEsT0FBQUwsUUFBQSxDQUFBTSxJQUFBO1VBQUE7UUFBQSxHQUFBVCxPQUFBO01BQUEsQ0FDM0Q7TUFBQSxTQUZLVSxjQUFjQSxDQUFBO1FBQUEsT0FBQWQsZUFBQSxDQUFBZSxLQUFBLE9BQUFwQixTQUFBO01BQUE7TUFBQSxPQUFkbUIsY0FBYztJQUFBO0lBSXBCO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtJQUxFO0VBQUE7SUFBQXpCLEdBQUE7SUFBQUMsS0FBQSxFQU1BLFNBQUEwQixXQUFXQSxDQUFBLEVBQVc7TUFDcEIsT0FBTyxFQUFFO0lBQ1g7O0lBRUE7QUFDRjtBQUNBO0VBRkU7SUFBQTNCLEdBQUE7SUFBQUMsS0FBQTtNQUFBLElBQUEyQixRQUFBLE9BQUFoQixrQkFBQSwyQkFBQUMsWUFBQSxZQUFBQyxJQUFBLENBR0EsU0FBQWUsU0FBQTtRQUFBLE9BQUFoQixZQUFBLFlBQUFHLElBQUEsVUFBQWMsVUFBQUMsU0FBQTtVQUFBLGtCQUFBQSxTQUFBLENBQUFaLElBQUEsR0FBQVksU0FBQSxDQUFBWCxJQUFBO1lBQUE7Y0FBQSxPQUFBVyxTQUFBLENBQUFWLE1BQUEsV0FDU0MsT0FBTyxDQUFDQyxNQUFNLENBQUMsNEJBQTRCLENBQUM7WUFBQTtZQUFBO2NBQUEsT0FBQVEsU0FBQSxDQUFBUCxJQUFBO1VBQUE7UUFBQSxHQUFBSyxRQUFBO01BQUEsQ0FDcEQ7TUFBQSxTQUZLRyxPQUFPQSxDQUFBO1FBQUEsT0FBQUosUUFBQSxDQUFBRixLQUFBLE9BQUFwQixTQUFBO01BQUE7TUFBQSxPQUFQMEIsT0FBTztJQUFBO0lBSWI7QUFDRjtBQUNBO0lBRkU7RUFBQTtJQUFBaEMsR0FBQTtJQUFBQyxLQUFBLEVBR0EsU0FBQWdDLG9CQUFvQkEsQ0FBQSxFQUFHO01BQ3JCLE9BQU8sSUFBSUMsS0FBSyxDQUFDN0MsaUJBQWlCLENBQUM7SUFDckM7O0lBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTtFQUpFO0lBQUFXLEdBQUE7SUFBQUMsS0FBQTtNQUFBLElBQUFrQyxNQUFBLE9BQUF2QixrQkFBQSwyQkFBQUMsWUFBQSxZQUFBQyxJQUFBLENBS0EsU0FBQXNCLFNBQUE7UUFBQSxPQUFBdkIsWUFBQSxZQUFBRyxJQUFBLFVBQUFxQixVQUFBQyxTQUFBO1VBQUEsa0JBQUFBLFNBQUEsQ0FBQW5CLElBQUEsR0FBQW1CLFNBQUEsQ0FBQWxCLElBQUE7WUFBQTtjQUFBLE9BQUFrQixTQUFBLENBQUFqQixNQUFBLFdBQ1NDLE9BQU8sQ0FBQ0MsTUFBTSxDQUFDLElBQUlXLEtBQUssQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO1lBQUE7WUFBQTtjQUFBLE9BQUFJLFNBQUEsQ0FBQWQsSUFBQTtVQUFBO1FBQUEsR0FBQVksUUFBQTtNQUFBLENBQzFFO01BQUEsU0FGS0csS0FBS0EsQ0FBQTtRQUFBLE9BQUFKLE1BQUEsQ0FBQVQsS0FBQSxPQUFBcEIsU0FBQTtNQUFBO01BQUEsT0FBTGlDLEtBQUs7SUFBQTtJQUlYO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7SUFKRTtFQUFBO0lBQUF2QyxHQUFBO0lBQUFDLEtBQUE7TUFBQSxJQUFBdUMsT0FBQSxPQUFBNUIsa0JBQUEsMkJBQUFDLFlBQUEsWUFBQUMsSUFBQSxDQUtBLFNBQUEyQixTQUFBO1FBQUEsT0FBQTVCLFlBQUEsWUFBQUcsSUFBQSxVQUFBMEIsVUFBQUMsU0FBQTtVQUFBLGtCQUFBQSxTQUFBLENBQUF4QixJQUFBLEdBQUF3QixTQUFBLENBQUF2QixJQUFBO1lBQUE7Y0FBQSxPQUFBdUIsU0FBQSxDQUFBdEIsTUFBQSxXQUNTQyxPQUFPLENBQUNDLE1BQU0sQ0FBQyxJQUFJVyxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQztZQUFBO1lBQUE7Y0FBQSxPQUFBUyxTQUFBLENBQUFuQixJQUFBO1VBQUE7UUFBQSxHQUFBaUIsUUFBQTtNQUFBLENBQzNFO01BQUEsU0FGS0csTUFBTUEsQ0FBQTtRQUFBLE9BQUFKLE9BQUEsQ0FBQWQsS0FBQSxPQUFBcEIsU0FBQTtNQUFBO01BQUEsT0FBTnNDLE1BQU07SUFBQTtJQUlaO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0lBWkU7RUFBQTtJQUFBNUMsR0FBQTtJQUFBQyxLQUFBO01BQUEsSUFBQTRDLFVBQUEsT0FBQWpDLGtCQUFBLDJCQUFBQyxZQUFBLFlBQUFDLElBQUEsQ0FhQSxTQUFBZ0MsU0FBQUMsSUFBQTtRQUFBLElBQUFDLE9BQUEsRUFBQUMsWUFBQSxFQUFBQyxPQUFBO1FBQUEsT0FBQXJDLFlBQUEsWUFBQUcsSUFBQSxVQUFBbUMsVUFBQUMsU0FBQTtVQUFBLGtCQUFBQSxTQUFBLENBQUFqQyxJQUFBLEdBQUFpQyxTQUFBLENBQUFoQyxJQUFBO1lBQUE7Y0FFRTRCLE9BQU8sR0FBQUQsSUFBQSxDQUFQQyxPQUFPLEVBQUFDLFlBQUEsR0FBQUYsSUFBQSxDQUVQRyxPQUFPLEVBQVBBLE9BQU8sR0FBQUQsWUFBQSxjQUFHLENBQUMsQ0FBQyxHQUFBQSxZQUFBO2NBQUEsT0FBQUcsU0FBQSxDQUFBL0IsTUFBQSxXQUtMQyxPQUFPLENBQUNDLE1BQU0sQ0FBQyw4QkFBOEIsQ0FBQztZQUFBO1lBQUE7Y0FBQSxPQUFBNkIsU0FBQSxDQUFBNUIsSUFBQTtVQUFBO1FBQUEsR0FBQXNCLFFBQUE7TUFBQSxDQUN0RDtNQUFBLFNBVktPLFNBQVNBLENBQUFDLEVBQUE7UUFBQSxPQUFBVCxVQUFBLENBQUFuQixLQUFBLE9BQUFwQixTQUFBO01BQUE7TUFBQSxPQUFUK0MsU0FBUztJQUFBO0lBWWY7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFsQkU7RUFBQTtJQUFBckQsR0FBQTtJQUFBQyxLQUFBO01BQUEsSUFBQXNELFNBQUEsT0FBQTNDLGtCQUFBLDJCQUFBQyxZQUFBLFlBQUFDLElBQUEsQ0FtQkEsU0FBQTBDLFNBQUE7UUFBQSxPQUFBM0MsWUFBQSxZQUFBRyxJQUFBLFVBQUF5QyxVQUFBQyxTQUFBO1VBQUEsa0JBQUFBLFNBQUEsQ0FBQXZDLElBQUEsR0FBQXVDLFNBQUEsQ0FBQXRDLElBQUE7WUFBQTtjQUFBLE9BQUFzQyxTQUFBLENBQUFyQyxNQUFBLFdBQ1MsRUFBRTtZQUFBO1lBQUE7Y0FBQSxPQUFBcUMsU0FBQSxDQUFBbEMsSUFBQTtVQUFBO1FBQUEsR0FBQWdDLFFBQUE7TUFBQSxDQUNWO01BQUEsU0FGS0csUUFBUUEsQ0FBQTtRQUFBLE9BQUFKLFNBQUEsQ0FBQTdCLEtBQUEsT0FBQXBCLFNBQUE7TUFBQTtNQUFBLE9BQVJxRCxRQUFRO0lBQUE7SUFJZDtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtJQUNFO0lBQUE7RUFBQTtJQUFBM0QsR0FBQTtJQUFBQyxLQUFBO01BQUEsSUFBQTJELFlBQUEsT0FBQWhELGtCQUFBLDJCQUFBQyxZQUFBLFlBQUFDLElBQUEsQ0FDQSxTQUFBK0MsU0FBa0JuRCxVQUFVO1FBQUEsT0FBQUcsWUFBQSxZQUFBRyxJQUFBLFVBQUE4QyxVQUFBQyxTQUFBO1VBQUEsa0JBQUFBLFNBQUEsQ0FBQTVDLElBQUEsR0FBQTRDLFNBQUEsQ0FBQTNDLElBQUE7WUFBQTtjQUFBLE9BQUEyQyxTQUFBLENBQUExQyxNQUFBLFdBQ25CQyxPQUFPLENBQUNDLE1BQU0sQ0FBQyxnQ0FBZ0MsQ0FBQztZQUFBO1lBQUE7Y0FBQSxPQUFBd0MsU0FBQSxDQUFBdkMsSUFBQTtVQUFBO1FBQUEsR0FBQXFDLFFBQUE7TUFBQSxDQUN4RDtNQUFBLFNBRktHLFdBQVdBLENBQUFDLEdBQUE7UUFBQSxPQUFBTCxZQUFBLENBQUFsQyxLQUFBLE9BQUFwQixTQUFBO01BQUE7TUFBQSxPQUFYMEQsV0FBVztJQUFBO0lBSWpCO0FBQ0Y7QUFDQTtBQUNBO0lBSEU7RUFBQTtJQUFBaEUsR0FBQTtJQUFBQyxLQUFBLEVBSUEsU0FBQWlFLGdCQUFnQkEsQ0FBQSxFQUFXO01BQ3pCLE1BQU0sSUFBSWhDLEtBQUssQ0FBQyxxQ0FBcUMsQ0FBQztJQUN4RDs7SUFFQTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztJQUVFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQVhFO0FBQUEiLCJpZ25vcmVMaXN0IjpbXX0=
;