UNPKG

kepler.gl

Version:

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

25 lines (22 loc) 37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.exportMapToHTML = void 0; var _constants = require("@kepler.gl/constants"); // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project // @ts-nocheck /** * This method is used to create an html file which will inlcude kepler and map data * @param {Object} options Object that collects all necessary data to create the html file * @param {string} options.mapboxApiAccessToken Mapbox token used to fetch mapbox tiles * @param {Array<Object>} options.datasets Data to include in the map * @param {Object} options.config this object will contain the full kepler.gl instance configuration {mapState, mapStyle, visState} * @param {string} version which version of Kepler.gl to load. */ var exportMapToHTML = exports.exportMapToHTML = function exportMapToHTML(options) { var version = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.KEPLER_GL_VERSION; return "\n <!DOCTYPE html>\n <html>\n <head>\n <meta charset=\"UTF-8\"/>\n <title>Kepler.gl embedded map</title>\n\n <!--Uber Font-->\n <link rel=\"stylesheet\" href=\"https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/uber-fonts/4.0.0/superfine.css\">\n\n <!--Kepler css-->\n <link href=\"https://unpkg.com/kepler.gl@".concat(version, "/umd/keplergl.min.css\" rel=\"stylesheet\">\n\n <!--MapBox css-->\n <link href=\"https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.css\" rel=\"stylesheet\">\n <link href=\"https://unpkg.com/maplibre-gl@^3/dist/maplibre-gl.css\" rel=\"stylesheet\">\n\n <!-\u2014 facebook open graph tags -->\n <meta property=\"og:url\" content=\"http://kepler.gl/\" />\n <meta property=\"og:title\" content=\"Large-scale WebGL-powered Geospatial Data Visualization Tool\" />\n <meta property=\"og:description\" content=\"Kepler.gl is a powerful web-based geospatial data analysis tool. Built on a high performance rendering engine and designed for large-scale data sets.\" />\n <meta property=\"og:site_name\" content=\"kepler.gl\" />\n <meta property=\"og:image\" content=\"https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/kepler.gl-meta-tag.png\" />\n <meta property=\"og:image:type\" content=\"image/png\" />\n <meta property=\"og:image:width\" content=\"800\" />\n <meta property=\"og:image:height\" content=\"800\" />\n\n <!-\u2014 twitter card tags -->\n <meta name=\"twitter:card\" content=\"summary_large_image\">\n <meta name=\"twitter:site\" content=\"@openjsf\">\n <meta name=\"twitter:creator\" content=\"@openjsf\">\n <meta name=\"twitter:title\" content=\"Large-scale WebGL-powered Geospatial Data Visualization Tool\">\n <meta name=\"twitter:description\" content=\"Kepler.gl is a powerful web-based geospatial data analysis tool. Built on a high performance rendering engine and designed for large-scale data sets.\">\n <meta name=\"twitter:image\" content=\"https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/kepler.gl-meta-tag.png\" />\n\n <!-- Load React/Redux -->\n <script src=\"https://unpkg.com/react@18.3.1/umd/react.production.min.js\" crossorigin></script>\n <script src=\"https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js\" crossorigin></script>\n <script src=\"https://unpkg.com/redux@4.2.1/dist/redux.js\" crossorigin></script>\n <script src=\"https://unpkg.com/react-redux@8.1.2/dist/react-redux.min.js\" crossorigin></script>\n <script src=\"https://unpkg.com/styled-components@6.1.8/dist/styled-components.min.js\" crossorigin></script>\n\n <!-- Load Kepler.gl -->\n <script src=\"https://unpkg.com/kepler.gl@").concat(version, "/umd/keplergl.min.js\" crossorigin></script>\n\n <style type=\"text/css\">\n body {margin: 0; padding: 0; overflow: hidden;}\n </style>\n\n <!--MapBox token-->\n <script>\n /**\n * Provide your MapBox Token\n **/\n const MAPBOX_TOKEN = '").concat(options.mapboxApiAccessToken || 'PROVIDE_MAPBOX_TOKEN', "';\n const WARNING_MESSAGE = 'Please Provide a Mapbox Token in order to use Kepler.gl. Edit this file and fill out MAPBOX_TOKEN with your access key';\n </script>\n\n <!-- GA: Delete this as you wish, However to pat ourselves on the back, we only track anonymous pageview to understand how many people are using kepler.gl. -->\n <script>\n (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\n ga('create', 'UA-64694404-19', {\n 'storage': 'none',\n 'clientId': localStorage.getItem('ga:clientId')\n });\n ga(function(tracker) {\n localStorage.setItem('ga:clientId', tracker.get('clientId'));\n });\n ga('set', 'checkProtocolTask', null); // Disable file protocol checking.\n ga('set', 'checkStorageTask', null); // Disable cookie storage checking.\n ga('set', 'historyImportTask', null); // Disable history checking (requires reading from cookies).\n ga('set', 'page', 'keplergl-html');\n ga('send', 'pageview');\n </script>\n </head>\n <body>\n <!-- We will put our React component inside this div. -->\n <div id=\"app\">\n <!-- Kepler.gl map will be placed here-->\n </div>\n\n <!-- Load our React component. -->\n <script>\n /* Validate Mapbox Token */\n if ((MAPBOX_TOKEN || '') === '' || MAPBOX_TOKEN === 'PROVIDE_MAPBOX_TOKEN') {\n alert(WARNING_MESSAGE);\n }\n\n /** STORE **/\n const reducers = (function createReducers(redux, keplerGl) {\n return redux.combineReducers({\n // mount keplerGl reducer\n keplerGl: keplerGl.keplerGlReducer.initialState({\n uiState: {\n readOnly: ").concat(options.mode === _constants.EXPORT_HTML_MAP_MODES.READ, ",\n currentModal: null\n }\n })\n });\n }(Redux, KeplerGl));\n\n const middleWares = (function createMiddlewares(keplerGl) {\n return keplerGl.enhanceReduxMiddleware([\n // Add other middlewares here\n ]);\n }(KeplerGl));\n\n const enhancers = (function craeteEnhancers(redux, middles) {\n return redux.applyMiddleware(...middles);\n }(Redux, middleWares));\n\n const store = (function createStore(redux, enhancers) {\n const initialState = {};\n\n return redux.createStore(\n reducers,\n initialState,\n redux.compose(enhancers)\n );\n }(Redux, enhancers));\n /** END STORE **/\n\n /** COMPONENTS **/\n var KeplerElement = (function makeKeplerElement(react, keplerGl, mapboxToken) {\n var LogoSvg = function LogoSvg() {\n return react.createElement(\n \"div\",\n { className: \"logo-container\", style: {position: 'fixed', zIndex: 10000, padding: '4px'} },\n react.createElement(\n \"svg\",\n {\n className: \"kepler_gl__logo\",\n width: \"107px\",\n height: \"21px\",\n viewBox: \"0 0 124 24\"\n },\n react.createElement(\n \"g\",\n { transform: \"translate(13.500000, 13.500000) rotate(45.000000) translate(-13.500000, -13.500000) translate(4.000000, 4.000000)\" },\n react.createElement(\"rect\", { x: \"0\", y: \"6\", transform: \"matrix(2.535181e-06 1 -1 2.535181e-06 18.1107 6.0369)\", fill: \"#535C6C\", width: \"12.1\", height: \"12.1\" }),\n react.createElement(\"rect\", { x: \"6\", y: \"0\", transform: \"matrix(2.535182e-06 1 -1 2.535182e-06 18.1107 -6.0369)\", fill:\"#1FBAD6\", width: \"12.1\", height: \"12.1\" })\n ),\n react.createElement(\n \"g\",\n {},\n react.createElement(\"path\", { fill:\"#1FBAD6\", d: \"M39,8.7h2.2l-2.8,4.2l2.9,5.1H39l-2.4-4.2h-1.3V18h-2V5l2-0.1v7.3h1.3L39,8.7z\" }),\n react.createElement(\"path\", { fill:\"#1FBAD6\", d: \"M42.4,13.3c0-1.5,0.4-2.7,1.1-3.5s1.8-1.2,3.1-1.2c1.3,0,2.2,0.4,2.8,1.1c0.6,0.7,0.9,1.8,0.9,3.3 c0,0.4,0,0.8,0,1.1h-5.8c0,1.6,0.8,2.4,2.4,2.4c1,0,2-0.2,2.9-0.6l0.2,1.7c-0.4,0.2-0.9,0.4-1.4,0.5s-1.1,0.2-1.7,0.2 c-1.5,0-2.6-0.4-3.3-1.2C42.8,16.1,42.4,14.9,42.4,13.3z M46.6,10.1c-0.7,0-1.2,0.2-1.5,0.5c-0.4,0.4-0.6,0.9-0.6,1.7h4 c0-0.8-0.2-1.4-0.5-1.7S47.2,10.1,46.6,10.1z\" }),\n react.createElement(\"path\", { fill:\"#1FBAD6\", d: \"M57.1,18.2c-1,0-1.8-0.3-2.3-0.9l0,0l0,1.3v2.5h-2V8.7h1.5l0.3,0.9h0c0.3-0.3,0.7-0.6,1.2-0.7 c0.4-0.2,0.9-0.3,1.4-0.3c1.2,0,2.1,0.4,2.7,1.1c0.6,0.7,0.9,2,0.9,3.7c0,1.6-0.3,2.8-1,3.7C59.2,17.8,58.3,18.2,57.1,18.2z M56.7,10.3c-0.4,0-0.8,0.1-1.1,0.2c-0.3,0.2-0.6,0.4-0.8,0.7v4.3c0.2,0.3,0.4,0.5,0.7,0.7c0.3,0.2,0.7,0.3,1.1,0.3 c0.7,0,1.2-0.2,1.6-0.7c0.4-0.5,0.5-1.3,0.5-2.5c0-0.8-0.1-1.4-0.2-1.8s-0.4-0.7-0.7-0.9C57.6,10.4,57.2,10.3,56.7,10.3z\" }),\n react.createElement(\"path\", { fill:\"#1FBAD6\", d: \"M63.2,16V5l2-0.1v10.8c0,0.3,0.1,0.5,0.2,0.6c0.1,0.1,0.3,0.2,0.6,0.2c0.3,0,0.6,0,0.9-0.1V18 c-0.4,0.1-1,0.2-1.6,0.2c-0.8,0-1.3-0.2-1.7-0.5S63.2,16.8,63.2,16z\" }),\n react.createElement(\"path\", { fill:\"#1FBAD6\", d: \"M68.2,13.3c0-1.5,0.4-2.7,1.1-3.5c0.7-0.8,1.8-1.2,3.1-1.2c1.3,0,2.2,0.4,2.8,1.1c0.6,0.7,0.9,1.8,0.9,3.3 c0,0.4,0,0.8,0,1.1h-5.8c0,1.6,0.8,2.4,2.4,2.4c1,0,2-0.2,2.9-0.6l0.2,1.7c-0.4,0.2-0.9,0.4-1.4,0.5s-1.1,0.2-1.7,0.2 c-1.5,0-2.6-0.4-3.3-1.2C68.6,16.1,68.2,14.9,68.2,13.3z M72.4,10.1c-0.7,0-1.2,0.2-1.5,0.5c-0.4,0.4-0.6,0.9-0.6,1.7h4 c0-0.8-0.2-1.4-0.5-1.7S73,10.1,72.4,10.1z\" }),\n react.createElement(\"path\", { fill:\"#1FBAD6\", d: \"M80.2,8.7l0.1,1.7h0c0.3-0.6,0.7-1.1,1.1-1.4c0.4-0.3,1-0.5,1.6-0.5c0.4,0,0.7,0,1,0.1l-0.1,2 c-0.3-0.1-0.7-0.2-1-0.2c-0.7,0-1.3,0.3-1.7,0.8c-0.4,0.5-0.7,1.2-0.7,2.1V18h-2V8.7H80.2z\" }),\n react.createElement(\"path\", { fill:\"#1FBAD6\", d: \"M83.8,17c0-0.8,0.4-1.2,1.2-1.2c0.8,0,1.2,0.4,1.2,1.2c0,0.8-0.4,1.1-1.2,1.1C84.2,18.2,83.8,17.8,83.8,17z\" }),\n react.createElement(\"path\", { fill:\"#1FBAD6\", d: \"M88.5,18.7c0-0.8,0.4-1.4,1.2-1.8c-0.6-0.3-0.9-0.8-0.9-1.5c0-0.7,0.4-1.2,1.1-1.6c-0.3-0.3-0.6-0.6-0.7-0.9 c-0.2-0.4-0.2-0.8-0.2-1.3c0-1,0.3-1.8,0.9-2.3c0.6-0.5,1.6-0.8,2.8-0.8c0.5,0,1,0,1.4,0.1c0.4,0.1,0.8,0.2,1.1,0.4l2.4-0.2v1.5 h-1.5c0.2,0.4,0.2,0.8,0.2,1.3c0,1-0.3,1.7-0.9,2.2s-1.5,0.8-2.7,0.8c-0.7,0-1.2-0.1-1.6-0.2c-0.1,0.1-0.2,0.2-0.3,0.3 c-0.1,0.1-0.1,0.2-0.1,0.4c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.6,0.2l2.7,0.2c1,0.1,1.7,0.3,2.2,0.6c0.5,0.3,0.8,0.9,0.8,1.7 c0,0.6-0.2,1.1-0.5,1.5c-0.4,0.4-0.9,0.8-1.5,1c-0.7,0.2-1.5,0.4-2.4,0.4c-1.3,0-2.3-0.2-3-0.6C88.8,20.1,88.5,19.5,88.5,18.7z M95.1,18.4c0-0.3-0.1-0.5-0.3-0.7s-0.6-0.2-1.1-0.3l-2.7-0.3c-0.2,0.1-0.4,0.3-0.5,0.5c-0.1,0.2-0.2,0.4-0.2,0.6 c0,0.4,0.2,0.8,0.5,1c0.4,0.2,1,0.3,1.8,0.3C94.2,19.5,95.1,19.2,95.1,18.4z M94.3,11.5c0-0.6-0.1-1-0.4-1.2 c-0.3-0.2-0.7-0.3-1.3-0.3c-0.7,0-1.1,0.1-1.4,0.3c-0.3,0.2-0.4,0.6-0.4,1.2s0.1,1,0.4,1.2c0.3,0.2,0.7,0.3,1.4,0.3 c0.6,0,1.1-0.1,1.3-0.4S94.3,12,94.3,11.5z\" }),\n react.createElement(\"path\", { fill:\"#1FBAD6\", d: \"M99.4,16V5l2-0.1v10.8c0,0.3,0.1,0.5,0.2,0.6c0.1,0.1,0.3,0.2,0.6,0.2c0.3,0,0.6,0,0.9-0.1V18 c-0.4,0.1-1,0.2-1.6,0.2c-0.8,0-1.3-0.2-1.7-0.5S99.4,16.8,99.4,16z\" })\n )\n )\n );\n };\n\n return function App() {\n var rootElm = react.useRef(null);\n var _useState = react.useState({\n width: window.innerWidth,\n height: window.innerHeight\n });\n var windowDimension = _useState[0];\n var setDimension = _useState[1];\n react.useEffect(function sideEffect(){\n function handleResize() {\n setDimension({width: window.innerWidth, height: window.innerHeight});\n };\n window.addEventListener('resize', handleResize);\n return function() {window.removeEventListener('resize', handleResize);};\n }, []);\n return react.createElement(\n 'div',\n {style: {position: 'absolute', left: 0, width: '100vw', height: '100vh'}},\n ").concat(options.mode === _constants.EXPORT_HTML_MAP_MODES.READ ? 'LogoSvg(),' : '', "\n react.createElement(keplerGl.KeplerGl, {\n mapboxApiAccessToken: mapboxToken,\n id: \"map\",\n width: windowDimension.width,\n height: windowDimension.height\n })\n )\n }\n }(React, KeplerGl, MAPBOX_TOKEN));\n\n const app = (function createReactReduxProvider(react, reactRedux, KeplerElement) {\n return react.createElement(\n reactRedux.Provider,\n {store},\n react.createElement(KeplerElement, null)\n )\n }(React, ReactRedux, KeplerElement));\n /** END COMPONENTS **/\n\n /** Render **/\n (function render(react, reactDOM, app) {\n const container = document.getElementById('app');\n const root = reactDOM.createRoot(container);\n root.render(app);\n }(React, ReactDOM, app));\n </script>\n <!-- The next script will show how to interact directly with Kepler map store -->\n <script>\n /**\n * Customize map.\n * In the following section you can use the store object to dispatch Kepler.gl actions\n * to add new data and customize behavior\n */\n (function customize(keplerGl, store) {\n const datasets = ").concat(JSON.stringify(options.datasets), ";\n const config = ").concat(JSON.stringify(options.config), ";\n\n const loadedData = keplerGl.KeplerGlSchema.load(\n datasets,\n config\n );\n\n // For some reason Kepler overwrites the config without extra wait time\n window.setTimeout(() => {\n store.dispatch(\n keplerGl.addDataToMap({\n datasets: loadedData.datasets,\n config: loadedData.config,\n options: {\n centerMap: false,\n },\n })\n );\n }, 500);\n }(KeplerGl, store))\n </script>\n </body>\n </html>\n "); }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29uc3RhbnRzIiwicmVxdWlyZSIsImV4cG9ydE1hcFRvSFRNTCIsImV4cG9ydHMiLCJvcHRpb25zIiwidmVyc2lvbiIsImFyZ3VtZW50cyIsImxlbmd0aCIsInVuZGVmaW5lZCIsIktFUExFUl9HTF9WRVJTSU9OIiwiY29uY2F0IiwibWFwYm94QXBpQWNjZXNzVG9rZW4iLCJtb2RlIiwiRVhQT1JUX0hUTUxfTUFQX01PREVTIiwiUkVBRCIsIkpTT04iLCJzdHJpbmdpZnkiLCJkYXRhc2V0cyIsImNvbmZpZyJdLCJzb3VyY2VzIjpbIi4uL3NyYy9leHBvcnQtbWFwLWh0bWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuLy8gQHRzLW5vY2hlY2tcbmltcG9ydCB7RVhQT1JUX0hUTUxfTUFQX01PREVTLCBLRVBMRVJfR0xfVkVSU0lPTn0gZnJvbSAnQGtlcGxlci5nbC9jb25zdGFudHMnO1xuXG4vKipcbiAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gY3JlYXRlIGFuIGh0bWwgZmlsZSB3aGljaCB3aWxsIGlubGN1ZGUga2VwbGVyIGFuZCBtYXAgZGF0YVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgT2JqZWN0IHRoYXQgY29sbGVjdHMgYWxsIG5lY2Vzc2FyeSBkYXRhIHRvICBjcmVhdGUgdGhlIGh0bWwgZmlsZVxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMubWFwYm94QXBpQWNjZXNzVG9rZW4gTWFwYm94IHRva2VuIHVzZWQgdG8gZmV0Y2ggbWFwYm94IHRpbGVzXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IG9wdGlvbnMuZGF0YXNldHMgRGF0YSB0byBpbmNsdWRlIGluIHRoZSBtYXBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLmNvbmZpZyB0aGlzIG9iamVjdCB3aWxsIGNvbnRhaW4gdGhlIGZ1bGwga2VwbGVyLmdsIGluc3RhbmNlIGNvbmZpZ3VyYXRpb24ge21hcFN0YXRlLCBtYXBTdHlsZSwgdmlzU3RhdGV9XG4gKiBAcGFyYW0ge3N0cmluZ30gdmVyc2lvbiB3aGljaCB2ZXJzaW9uIG9mIEtlcGxlci5nbCB0byBsb2FkLlxuICovXG5leHBvcnQgY29uc3QgZXhwb3J0TWFwVG9IVE1MID0gKG9wdGlvbnMsIHZlcnNpb24gPSBLRVBMRVJfR0xfVkVSU0lPTikgPT4ge1xuICByZXR1cm4gYFxuICAgIDwhRE9DVFlQRSBodG1sPlxuICAgIDxodG1sPlxuICAgICAgPGhlYWQ+XG4gICAgICAgIDxtZXRhIGNoYXJzZXQ9XCJVVEYtOFwiLz5cbiAgICAgICAgPHRpdGxlPktlcGxlci5nbCBlbWJlZGRlZCBtYXA8L3RpdGxlPlxuXG4gICAgICAgIDwhLS1VYmVyIEZvbnQtLT5cbiAgICAgICAgPGxpbmsgcmVsPVwic3R5bGVzaGVldFwiIGhyZWY9XCJodHRwczovL2QxYTNmNHNwYXp6cnA0LmNsb3VkZnJvbnQubmV0L2tlcGxlci5nbC91YmVyLWZvbnRzLzQuMC4wL3N1cGVyZmluZS5jc3NcIj5cblxuICAgICAgICA8IS0tS2VwbGVyIGNzcy0tPlxuICAgICAgICA8bGluayBocmVmPVwiaHR0cHM6Ly91bnBrZy5jb20va2VwbGVyLmdsQCR7dmVyc2lvbn0vdW1kL2tlcGxlcmdsLm1pbi5jc3NcIiByZWw9XCJzdHlsZXNoZWV0XCI+XG5cbiAgICAgICAgPCEtLU1hcEJveCBjc3MtLT5cbiAgICAgICAgPGxpbmsgaHJlZj1cImh0dHBzOi8vYXBpLnRpbGVzLm1hcGJveC5jb20vbWFwYm94LWdsLWpzL3YxLjEuMS9tYXBib3gtZ2wuY3NzXCIgcmVsPVwic3R5bGVzaGVldFwiPlxuICAgICAgICA8bGluayBocmVmPVwiaHR0cHM6Ly91bnBrZy5jb20vbWFwbGlicmUtZ2xAXjMvZGlzdC9tYXBsaWJyZS1nbC5jc3NcIiByZWw9XCJzdHlsZXNoZWV0XCI+XG5cbiAgICAgICAgPCEt4oCUIGZhY2Vib29rIG9wZW4gZ3JhcGggdGFncyAtLT5cbiAgICAgICAgPG1ldGEgcHJvcGVydHk9XCJvZzp1cmxcIiBjb250ZW50PVwiaHR0cDovL2tlcGxlci5nbC9cIiAvPlxuICAgICAgICA8bWV0YSBwcm9wZXJ0eT1cIm9nOnRpdGxlXCIgY29udGVudD1cIkxhcmdlLXNjYWxlIFdlYkdMLXBvd2VyZWQgR2Vvc3BhdGlhbCBEYXRhIFZpc3VhbGl6YXRpb24gVG9vbFwiIC8+XG4gICAgICAgIDxtZXRhIHByb3BlcnR5PVwib2c6ZGVzY3JpcHRpb25cIiBjb250ZW50PVwiS2VwbGVyLmdsIGlzIGEgcG93ZXJmdWwgd2ViLWJhc2VkIGdlb3NwYXRpYWwgZGF0YSBhbmFseXNpcyB0b29sLiBCdWlsdCBvbiBhIGhpZ2ggcGVyZm9ybWFuY2UgcmVuZGVyaW5nIGVuZ2luZSBhbmQgZGVzaWduZWQgZm9yIGxhcmdlLXNjYWxlIGRhdGEgc2V0cy5cIiAvPlxuICAgICAgICA8bWV0YSBwcm9wZXJ0eT1cIm9nOnNpdGVfbmFtZVwiIGNvbnRlbnQ9XCJrZXBsZXIuZ2xcIiAvPlxuICAgICAgICA8bWV0YSBwcm9wZXJ0eT1cIm9nOmltYWdlXCIgY29udGVudD1cImh0dHBzOi8vZDFhM2Y0c3BhenpycDQuY2xvdWRmcm9udC5uZXQva2VwbGVyLmdsL2tlcGxlci5nbC1tZXRhLXRhZy5wbmdcIiAvPlxuICAgICAgICA8bWV0YSBwcm9wZXJ0eT1cIm9nOmltYWdlOnR5cGVcIiBjb250ZW50PVwiaW1hZ2UvcG5nXCIgLz5cbiAgICAgICAgPG1ldGEgcHJvcGVydHk9XCJvZzppbWFnZTp3aWR0aFwiIGNvbnRlbnQ9XCI4MDBcIiAvPlxuICAgICAgICA8bWV0YSBwcm9wZXJ0eT1cIm9nOmltYWdlOmhlaWdodFwiIGNvbnRlbnQ9XCI4MDBcIiAvPlxuXG4gICAgICAgIDwhLeKAlCB0d2l0dGVyIGNhcmQgdGFncyAtLT5cbiAgICAgICAgPG1ldGEgbmFtZT1cInR3aXR0ZXI6Y2FyZFwiIGNvbnRlbnQ9XCJzdW1tYXJ5X2xhcmdlX2ltYWdlXCI+XG4gICAgICAgIDxtZXRhIG5hbWU9XCJ0d2l0dGVyOnNpdGVcIiBjb250ZW50PVwiQG9wZW5qc2ZcIj5cbiAgICAgICAgPG1ldGEgbmFtZT1cInR3aXR0ZXI6Y3JlYXRvclwiIGNvbnRlbnQ9XCJAb3BlbmpzZlwiPlxuICAgICAgICA8bWV0YSBuYW1lPVwidHdpdHRlcjp0aXRsZVwiIGNvbnRlbnQ9XCJMYXJnZS1zY2FsZSBXZWJHTC1wb3dlcmVkIEdlb3NwYXRpYWwgRGF0YSBWaXN1YWxpemF0aW9uIFRvb2xcIj5cbiAgICAgICAgPG1ldGEgbmFtZT1cInR3aXR0ZXI6ZGVzY3JpcHRpb25cIiBjb250ZW50PVwiS2VwbGVyLmdsIGlzIGEgcG93ZXJmdWwgd2ViLWJhc2VkIGdlb3NwYXRpYWwgZGF0YSBhbmFseXNpcyB0b29sLiBCdWlsdCBvbiBhIGhpZ2ggcGVyZm9ybWFuY2UgcmVuZGVyaW5nIGVuZ2luZSBhbmQgZGVzaWduZWQgZm9yIGxhcmdlLXNjYWxlIGRhdGEgc2V0cy5cIj5cbiAgICAgICAgPG1ldGEgbmFtZT1cInR3aXR0ZXI6aW1hZ2VcIiBjb250ZW50PVwiaHR0cHM6Ly9kMWEzZjRzcGF6enJwNC5jbG91ZGZyb250Lm5ldC9rZXBsZXIuZ2wva2VwbGVyLmdsLW1ldGEtdGFnLnBuZ1wiIC8+XG5cbiAgICAgICAgPCEtLSBMb2FkIFJlYWN0L1JlZHV4IC0tPlxuICAgICAgICA8c2NyaXB0IHNyYz1cImh0dHBzOi8vdW5wa2cuY29tL3JlYWN0QDE4LjMuMS91bWQvcmVhY3QucHJvZHVjdGlvbi5taW4uanNcIiBjcm9zc29yaWdpbj48L3NjcmlwdD5cbiAgICAgICAgPHNjcmlwdCBzcmM9XCJodHRwczovL3VucGtnLmNvbS9yZWFjdC1kb21AMTguMy4xL3VtZC9yZWFjdC1kb20ucHJvZHVjdGlvbi5taW4uanNcIiBjcm9zc29yaWdpbj48L3NjcmlwdD5cbiAgICAgICAgPHNjcmlwdCBzcmM9XCJodHRwczovL3VucGtnLmNvbS9yZWR1eEA0LjIuMS9kaXN0L3JlZHV4LmpzXCIgY3Jvc3NvcmlnaW4+PC9zY3JpcHQ+XG4gICAgICAgIDxzY3JpcHQgc3JjPVwiaHR0cHM6Ly91bnBrZy5jb20vcmVhY3QtcmVkdXhAOC4xLjIvZGlzdC9yZWFjdC1yZWR1eC5taW4uanNcIiBjcm9zc29yaWdpbj48L3NjcmlwdD5cbiAgICAgICAgPHNjcmlwdCBzcmM9XCJodHRwczovL3VucGtnLmNvbS9zdHlsZWQtY29tcG9uZW50c0A2LjEuOC9kaXN0L3N0eWxlZC1jb21wb25lbnRzLm1pbi5qc1wiIGNyb3Nzb3JpZ2luPjwvc2NyaXB0PlxuXG4gICAgICAgIDwhLS0gTG9hZCBLZXBsZXIuZ2wgLS0+XG4gICAgICAgIDxzY3JpcHQgc3JjPVwiaHR0cHM6Ly91bnBrZy5jb20va2VwbGVyLmdsQCR7dmVyc2lvbn0vdW1kL2tlcGxlcmdsLm1pbi5qc1wiIGNyb3Nzb3JpZ2luPjwvc2NyaXB0PlxuXG4gICAgICAgIDxzdHlsZSB0eXBlPVwidGV4dC9jc3NcIj5cbiAgICAgICAgICBib2R5IHttYXJnaW46IDA7IHBhZGRpbmc6IDA7IG92ZXJmbG93OiBoaWRkZW47fVxuICAgICAgICA8L3N0eWxlPlxuXG4gICAgICAgIDwhLS1NYXBCb3ggdG9rZW4tLT5cbiAgICAgICAgPHNjcmlwdD5cbiAgICAgICAgICAvKipcbiAgICAgICAgICAgKiBQcm92aWRlIHlvdXIgTWFwQm94IFRva2VuXG4gICAgICAgICAgICoqL1xuICAgICAgICAgIGNvbnN0IE1BUEJPWF9UT0tFTiA9ICcke29wdGlvbnMubWFwYm94QXBpQWNjZXNzVG9rZW4gfHwgJ1BST1ZJREVfTUFQQk9YX1RPS0VOJ30nO1xuICAgICAgICAgIGNvbnN0IFdBUk5JTkdfTUVTU0FHRSA9ICdQbGVhc2UgUHJvdmlkZSBhIE1hcGJveCBUb2tlbiBpbiBvcmRlciB0byB1c2UgS2VwbGVyLmdsLiBFZGl0IHRoaXMgZmlsZSBhbmQgZmlsbCBvdXQgTUFQQk9YX1RPS0VOIHdpdGggeW91ciBhY2Nlc3Mga2V5JztcbiAgICAgICAgPC9zY3JpcHQ+XG5cbiAgICAgICAgPCEtLSBHQTogRGVsZXRlIHRoaXMgYXMgeW91IHdpc2gsIEhvd2V2ZXIgdG8gcGF0IG91cnNlbHZlcyBvbiB0aGUgYmFjaywgd2Ugb25seSB0cmFjayBhbm9ueW1vdXMgcGFnZXZpZXcgdG8gdW5kZXJzdGFuZCBob3cgbWFueSBwZW9wbGUgYXJlIHVzaW5nIGtlcGxlci5nbC4gLS0+XG4gICAgICAgIDxzY3JpcHQ+XG4gICAgICAgICAgKGZ1bmN0aW9uKGkscyxvLGcscixhLG0pe2lbJ0dvb2dsZUFuYWx5dGljc09iamVjdCddPXI7aVtyXT1pW3JdfHxmdW5jdGlvbigpe1xuICAgICAgICAgIChpW3JdLnE9aVtyXS5xfHxbXSkucHVzaChhcmd1bWVudHMpfSxpW3JdLmw9MSpuZXcgRGF0ZSgpO2E9cy5jcmVhdGVFbGVtZW50KG8pLFxuICAgICAgICAgIG09cy5nZXRFbGVtZW50c0J5VGFnTmFtZShvKVswXTthLmFzeW5jPTE7YS5zcmM9ZzttLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGEsbSlcbiAgICAgICAgICB9KSh3aW5kb3csZG9jdW1lbnQsJ3NjcmlwdCcsJ2h0dHBzOi8vd3d3Lmdvb2dsZS1hbmFseXRpY3MuY29tL2FuYWx5dGljcy5qcycsJ2dhJyk7XG4gICAgICAgICAgZ2EoJ2NyZWF0ZScsICdVQS02NDY5NDQwNC0xOScsIHtcbiAgICAgICAgICAgICdzdG9yYWdlJzogJ25vbmUnLFxuICAgICAgICAgICAgJ2NsaWVudElkJzogbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2dhOmNsaWVudElkJylcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBnYShmdW5jdGlvbih0cmFja2VyKSB7XG4gICAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdnYTpjbGllbnRJZCcsIHRyYWNrZXIuZ2V0KCdjbGllbnRJZCcpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBnYSgnc2V0JywgJ2NoZWNrUHJvdG9jb2xUYXNrJywgbnVsbCk7IC8vIERpc2FibGUgZmlsZSBwcm90b2NvbCBjaGVja2luZy5cbiAgICAgICAgICBnYSgnc2V0JywgJ2NoZWNrU3RvcmFnZVRhc2snLCBudWxsKTsgLy8gRGlzYWJsZSBjb29raWUgc3RvcmFnZSBjaGVja2luZy5cbiAgICAgICAgICBnYSgnc2V0JywgJ2hpc3RvcnlJbXBvcnRUYXNrJywgbnVsbCk7IC8vIERpc2FibGUgaGlzdG9yeSBjaGVja2luZyAocmVxdWlyZXMgcmVhZGluZyBmcm9tIGNvb2tpZXMpLlxuICAgICAgICAgIGdhKCdzZXQnLCAncGFnZScsICdrZXBsZXJnbC1odG1sJyk7XG4gICAgICAgICAgZ2EoJ3NlbmQnLCAncGFnZXZpZXcnKTtcbiAgICAgICAgPC9zY3JpcHQ+XG4gICAgICA8L2hlYWQ+XG4gICAgICA8Ym9keT5cbiAgICAgICAgPCEtLSBXZSB3aWxsIHB1dCBvdXIgUmVhY3QgY29tcG9uZW50IGluc2lkZSB0aGlzIGRpdi4gLS0+XG4gICAgICAgIDxkaXYgaWQ9XCJhcHBcIj5cbiAgICAgICAgICA8IS0tIEtlcGxlci5nbCBtYXAgd2lsbCBiZSBwbGFjZWQgaGVyZS0tPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIExvYWQgb3VyIFJlYWN0IGNvbXBvbmVudC4gLS0+XG4gICAgICAgIDxzY3JpcHQ+XG4gICAgICAgICAgLyogVmFsaWRhdGUgTWFwYm94IFRva2VuICovXG4gICAgICAgICAgaWYgKChNQVBCT1hfVE9LRU4gfHwgJycpID09PSAnJyB8fCBNQVBCT1hfVE9LRU4gPT09ICdQUk9WSURFX01BUEJPWF9UT0tFTicpIHtcbiAgICAgICAgICAgIGFsZXJ0KFdBUk5JTkdfTUVTU0FHRSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLyoqIFNUT1JFICoqL1xuICAgICAgICAgIGNvbnN0IHJlZHVjZXJzID0gKGZ1bmN0aW9uIGNyZWF0ZVJlZHVjZXJzKHJlZHV4LCBrZXBsZXJHbCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlZHV4LmNvbWJpbmVSZWR1Y2Vycyh7XG4gICAgICAgICAgICAgIC8vIG1vdW50IGtlcGxlckdsIHJlZHVjZXJcbiAgICAgICAgICAgICAga2VwbGVyR2w6IGtlcGxlckdsLmtlcGxlckdsUmVkdWNlci5pbml0aWFsU3RhdGUoe1xuICAgICAgICAgICAgICAgIHVpU3RhdGU6IHtcbiAgICAgICAgICAgICAgICAgIHJlYWRPbmx5OiAke29wdGlvbnMubW9kZSA9PT0gRVhQT1JUX0hUTUxfTUFQX01PREVTLlJFQUR9LFxuICAgICAgICAgICAgICAgICAgY3VycmVudE1vZGFsOiBudWxsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfShSZWR1eCwgS2VwbGVyR2wpKTtcblxuICAgICAgICAgIGNvbnN0IG1pZGRsZVdhcmVzID0gKGZ1bmN0aW9uIGNyZWF0ZU1pZGRsZXdhcmVzKGtlcGxlckdsKSB7XG4gICAgICAgICAgICByZXR1cm4ga2VwbGVyR2wuZW5oYW5jZVJlZHV4TWlkZGxld2FyZShbXG4gICAgICAgICAgICAgIC8vIEFkZCBvdGhlciBtaWRkbGV3YXJlcyBoZXJlXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICB9KEtlcGxlckdsKSk7XG5cbiAgICAgICAgICBjb25zdCBlbmhhbmNlcnMgPSAoZnVuY3Rpb24gY3JhZXRlRW5oYW5jZXJzKHJlZHV4LCBtaWRkbGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVkdXguYXBwbHlNaWRkbGV3YXJlKC4uLm1pZGRsZXMpO1xuICAgICAgICAgIH0oUmVkdXgsIG1pZGRsZVdhcmVzKSk7XG5cbiAgICAgICAgICBjb25zdCBzdG9yZSA9IChmdW5jdGlvbiBjcmVhdGVTdG9yZShyZWR1eCwgZW5oYW5jZXJzKSB7XG4gICAgICAgICAgICBjb25zdCBpbml0aWFsU3RhdGUgPSB7fTtcblxuICAgICAgICAgICAgcmV0dXJuIHJlZHV4LmNyZWF0ZVN0b3JlKFxuICAgICAgICAgICAgICByZWR1Y2VycyxcbiAgICAgICAgICAgICAgaW5pdGlhbFN0YXRlLFxuICAgICAgICAgICAgICByZWR1eC5jb21wb3NlKGVuaGFuY2VycylcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfShSZWR1eCwgZW5oYW5jZXJzKSk7XG4gICAgICAgICAgLyoqIEVORCBTVE9SRSAqKi9cblxuICAgICAgICAgIC8qKiBDT01QT05FTlRTICoqL1xuICAgICAgICAgIHZhciBLZXBsZXJFbGVtZW50ID0gKGZ1bmN0aW9uIG1ha2VLZXBsZXJFbGVtZW50KHJlYWN0LCBrZXBsZXJHbCwgbWFwYm94VG9rZW4pIHtcbiAgICAgICAgICAgIHZhciBMb2dvU3ZnID0gZnVuY3Rpb24gTG9nb1N2ZygpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlYWN0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAgICAgICAgICAgXCJkaXZcIixcbiAgICAgICAgICAgICAgICB7IGNsYXNzTmFtZTogXCJsb2dvLWNvbnRhaW5lclwiLCBzdHlsZToge3Bvc2l0aW9uOiAnZml4ZWQnLCB6SW5kZXg6IDEwMDAwLCBwYWRkaW5nOiAnNHB4J30gfSxcbiAgICAgICAgICAgICAgICAgIHJlYWN0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAgICAgICAgICAgICAgIFwic3ZnXCIsXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IFwia2VwbGVyX2dsX19sb2dvXCIsXG4gICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IFwiMTA3cHhcIixcbiAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IFwiMjFweFwiLFxuICAgICAgICAgICAgICAgICAgICAgIHZpZXdCb3g6IFwiMCAwIDEyNCAyNFwiXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHJlYWN0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAgICAgICAgICAgICAgICAgXCJnXCIsXG4gICAgICAgICAgICAgICAgICAgICAgeyB0cmFuc2Zvcm06IFwidHJhbnNsYXRlKDEzLjUwMDAwMCwgMTMuNTAwMDAwKSByb3RhdGUoNDUuMDAwMDAwKSB0cmFuc2xhdGUoLTEzLjUwMDAwMCwgLTEzLjUwMDAwMCkgdHJhbnNsYXRlKDQuMDAwMDAwLCA0LjAwMDAwMClcIiB9LFxuICAgICAgICAgICAgICAgICAgICAgIHJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJyZWN0XCIsIHsgeDogXCIwXCIsIHk6IFwiNlwiLCB0cmFuc2Zvcm06IFwibWF0cml4KDIuNTM1MTgxZS0wNiAxIC0xIDIuNTM1MTgxZS0wNiAxOC4xMTA3IDYuMDM2OSlcIiwgZmlsbDogXCIjNTM1QzZDXCIsIHdpZHRoOiBcIjEyLjFcIiwgaGVpZ2h0OiBcIjEyLjFcIiB9KSxcbiAgICAgICAgICAgICAgICAgICAgICByZWFjdC5jcmVhdGVFbGVtZW50KFwicmVjdFwiLCB7IHg6IFwiNlwiLCB5OiBcIjBcIiwgdHJhbnNmb3JtOiBcIm1hdHJpeCgyLjUzNTE4MmUtMDYgMSAtMSAyLjUzNTE4MmUtMDYgMTguMTEwNyAtNi4wMzY5KVwiLCBmaWxsOlwiIzFGQkFENlwiLCB3aWR0aDogXCIxMi4xXCIsIGhlaWdodDogXCIxMi4xXCIgfSlcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhY3QuY3JlYXRlRWxlbWVudChcbiAgICAgICAgICAgICAgICAgICAgICBcImdcIixcbiAgICAgICAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICAgICAgICByZWFjdC5jcmVhdGVFbGVtZW50KFwicGF0aFwiLCB7IGZpbGw6XCIjMUZCQUQ2XCIsIGQ6IFwiTTM5LDguN2gyLjJsLTIuOCw0LjJsMi45LDUuMUgzOWwtMi40LTQuMmgtMS4zVjE4aC0yVjVsMi0wLjF2Ny4zaDEuM0wzOSw4Ljd6XCIgfSksXG4gICAgICAgICAgICAgICAgICAgICAgcmVhY3QuY3JlYXRlRWxlbWVudChcInBhdGhcIiwgeyBmaWxsOlwiIzFGQkFENlwiLCBkOiBcIk00Mi40LDEzLjNjMC0xLjUsMC40LTIuNywxLjEtMy41czEuOC0xLjIsMy4xLTEuMmMxLjMsMCwyLjIsMC40LDIuOCwxLjFjMC42LDAuNywwLjksMS44LDAuOSwzLjMgYzAsMC40LDAsMC44LDAsMS4xaC01LjhjMCwxLjYsMC44LDIuNCwyLjQsMi40YzEsMCwyLTAuMiwyLjktMC42bDAuMiwxLjdjLTAuNCwwLjItMC45LDAuNC0xLjQsMC41cy0xLjEsMC4yLTEuNywwLjIgYy0xLjUsMC0yLjYtMC40LTMuMy0xLjJDNDIuOCwxNi4xLDQyLjQsMTQuOSw0Mi40LDEzLjN6IE00Ni42LDEwLjFjLTAuNywwLTEuMiwwLjItMS41LDAuNWMtMC40LDAuNC0wLjYsMC45LTAuNiwxLjdoNCBjMC0wLjgtMC4yLTEuNC0wLjUtMS43UzQ3LjIsMTAuMSw0Ni42LDEwLjF6XCIgfSksXG4gICAgICAgICAgICAgICAgICAgICAgcmVhY3QuY3JlYXRlRWxlbWVudChcInBhdGhcIiwgeyBmaWxsOlwiIzFGQkFENlwiLCBkOiBcIk01Ny4xLDE4LjJjLTEsMC0xLjgtMC4zLTIuMy0wLjlsMCwwbDAsMS4zdjIuNWgtMlY4LjdoMS41bDAuMywwLjloMGMwLjMtMC4zLDAuNy0wLjYsMS4yLTAuNyBjMC40LTAuMiwwLjktMC4zLDEuNC0wLjNjMS4yLDAsMi4xLDAuNCwyLjcsMS4xYzAuNiwwLjcsMC45LDIsMC45LDMuN2MwLDEuNi0wLjMsMi44LTEsMy43QzU5LjIsMTcuOCw1OC4zLDE4LjIsNTcuMSwxOC4yeiBNNTYuNywxMC4zYy0wLjQsMC0wLjgsMC4xLTEuMSwwLjJjLTAuMywwLjItMC42LDAuNC0wLjgsMC43djQuM2MwLjIsMC4zLDAuNCwwLjUsMC43LDAuN2MwLjMsMC4yLDAuNywwLjMsMS4xLDAuMyBjMC43LDAsMS4yLTAuMiwxLjYtMC43YzAuNC0wLjUsMC41LTEuMywwLjUtMi41YzAtMC44LTAuMS0xLjQtMC4yLTEuOHMtMC40LTAuNy0wLjctMC45QzU3LjYsMTAuNCw1Ny4yLDEwLjMsNTYuNywxMC4zelwiIH0pLFxuICAgICAgICAgICAgICAgICAgICAgIHJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJwYXRoXCIsIHsgZmlsbDpcIiMxRkJBRDZcIiwgZDogXCJNNjMuMiwxNlY1bDItMC4xdjEwLjhjMCwwLjMsMC4xLDAuNSwwLjIsMC42YzAuMSwwLjEsMC4zLDAuMiwwLjYsMC4yYzAuMywwLDAuNiwwLDAuOS0wLjFWMTggYy0wLjQsMC4xLTEsMC4yLTEuNiwwLjJjLTAuOCwwLTEuMy0wLjItMS43LTAuNVM2My4yLDE2LjgsNjMuMiwxNnpcIiB9KSxcbiAgICAgICAgICAgICAgICAgICAgICByZWFjdC5jcmVhdGVFbGVtZW50KFwicGF0aFwiLCB7IGZpbGw6XCIjMUZCQUQ2XCIsIGQ6IFwiTTY4LjIsMTMuM2MwLTEuNSwwLjQtMi43LDEuMS0zLjVjMC43LTAuOCwxLjgtMS4yLDMuMS0xLjJjMS4zLDAsMi4yLDAuNCwyLjgsMS4xYzAuNiwwLjcsMC45LDEuOCwwLjksMy4zIGMwLDAuNCwwLDAuOCwwLDEuMWgtNS44YzAsMS42LDAuOCwyLjQsMi40LDIuNGMxLDAsMi0wLjIsMi45LTAuNmwwLjIsMS43Yy0wLjQsMC4yLTAuOSwwLjQtMS40LDAuNXMtMS4xLDAuMi0xLjcsMC4yIGMtMS41LDAtMi42LTAuNC0zLjMtMS4yQzY4LjYsMTYuMSw2OC4yLDE0LjksNjguMiwxMy4zeiBNNzIuNCwxMC4xYy0wLjcsMC0xLjIsMC4yLTEuNSwwLjVjLTAuNCwwLjQtMC42LDAuOS0wLjYsMS43aDQgYzAtMC44LTAuMi0xLjQtMC41LTEuN1M3MywxMC4xLDcyLjQsMTAuMXpcIiB9KSxcbiAgICAgICAgICAgICAgICAgICAgICByZWFjdC5jcmVhdGVFbGVtZW50KFwicGF0aFwiLCB7IGZpbGw6XCIjMUZCQUQ2XCIsIGQ6IFwiTTgwLjIsOC43bDAuMSwxLjdoMGMwLjMtMC42LDAuNy0xLjEsMS4xLTEuNGMwLjQtMC4zLDEtMC41LDEuNi0wLjVjMC40LDAsMC43LDAsMSwwLjFsLTAuMSwyIGMtMC4zLTAuMS0wLjctMC4yLTEtMC4yYy0wLjcsMC0xLjMsMC4zLTEuNywwLjhjLTAuNCwwLjUtMC43LDEuMi0wLjcsMi4xVjE4aC0yVjguN0g4MC4yelwiIH0pLFxuICAgICAgICAgICAgICAgICAgICAgIHJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJwYXRoXCIsIHsgZmlsbDpcIiMxRkJBRDZcIiwgZDogXCJNODMuOCwxN2MwLTAuOCwwLjQtMS4yLDEuMi0xLjJjMC44LDAsMS4yLDAuNCwxLjIsMS4yYzAsMC44LTAuNCwxLjEtMS4yLDEuMUM4NC4yLDE4LjIsODMuOCwxNy44LDgzLjgsMTd6XCIgfSksXG4gICAgICAgICAgICAgICAgICAgICAgcmVhY3QuY3JlYXRlRWxlbWVudChcInBhdGhcIiwgeyBmaWxsOlwiIzFGQkFENlwiLCBkOiBcIk04OC41LDE4LjdjMC0wLjgsMC40LTEuNCwxLjItMS44Yy0wLjYtMC4zLTAuOS0wLjgtMC45LTEuNWMwLTAuNywwLjQtMS4yLDEuMS0xLjZjLTAuMy0wLjMtMC42LTAuNi0wLjctMC45IGMtMC4yLTAuNC0wLjItMC44LTAuMi0xLjNjMC0xLDAuMy0xLjgsMC45LTIuM2MwLjYtMC41LDEuNi0wLjgsMi44LTAuOGMwLjUsMCwxLDAsMS40LDAuMWMwLjQsMC4xLDAuOCwwLjIsMS4xLDAuNGwyLjQtMC4ydjEuNSBoLTEuNWMwLjIsMC40LDAuMiwwLjgsMC4yLDEuM2MwLDEtMC4zLDEuNy0wLjksMi4ycy0xLjUsMC44LTIuNywwLjhjLTAuNywwLTEuMi0wLjEtMS42LTAuMmMtMC4xLDAuMS0wLjIsMC4yLTAuMywwLjMgYy0wLjEsMC4xLTAuMSwwLjItMC4xLDAuNGMwLDAuMiwwLjEsMC4zLDAuMiwwLjRjMC4xLDAuMSwwLjMsMC4yLDAuNiwwLjJsMi43LDAuMmMxLDAuMSwxLjcsMC4zLDIuMiwwLjZjMC41LDAuMywwLjgsMC45LDAuOCwxLjcgYzAsMC42LTAuMiwxLjEtMC41LDEuNWMtMC40LDAuNC0wLjksMC44LTEuNSwxYy0wLjcsMC4yLTEuNSwwLjQtMi40LDAuNGMtMS4zLDAtMi4zLTAuMi0zLTAuNkM4OC44LDIwLjEsODguNSwxOS41LDg4LjUsMTguN3ogTTk1LjEsMTguNGMwLTAuMy0wLjEtMC41LTAuMy0wLjdzLTAuNi0wLjItMS4xLTAuM2wtMi43LTAuM2MtMC4yLDAuMS0wLjQsMC4zLTAuNSwwLjVjLTAuMSwwLjItMC4yLDAuNC0wLjIsMC42IGMwLDAuNCwwLjIsMC44LDAuNSwxYzAuNCwwLjIsMSwwLjMsMS44LDAuM0M5NC4yLDE5LjUsOTUuMSwxOS4yLDk1LjEsMTguNHogTTk0LjMsMTEuNWMwLTAuNi0wLjEtMS0wLjQtMS4yIGMtMC4zLTAuMi0wLjctMC4zLTEuMy0wLjNjLTAuNywwLTEuMSwwLjEtMS40LDAuM2MtMC4zLDAuMi0wLjQsMC42LTAuNCwxLjJzMC4xLDEsMC40LDEuMmMwLjMsMC4yLDAuNywwLjMsMS40LDAuMyBjMC42LDAsMS4xLTAuMSwxLjMtMC40Uzk0LjMsMTIsOTQuMywxMS41elwiIH0pLFxuICAgICAgICAgICAgICAgICAgICAgIHJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJwYXRoXCIsIHsgZmlsbDpcIiMxRkJBRDZcIiwgZDogXCJNOTkuNCwxNlY1bDItMC4xdjEwLjhjMCwwLjMsMC4xLDAuNSwwLjIsMC42YzAuMSwwLjEsMC4zLDAuMiwwLjYsMC4yYzAuMywwLDAuNiwwLDAuOS0wLjFWMTggYy0wLjQsMC4xLTEsMC4yLTEuNiwwLjJjLTAuOCwwLTEuMy0wLjItMS43LTAuNVM5OS40LDE2LjgsOTkuNCwxNnpcIiB9KVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIEFwcCgpIHtcbiAgICAgICAgICAgICAgdmFyIHJvb3RFbG0gPSByZWFjdC51c2VSZWYobnVsbCk7XG4gICAgICAgICAgICAgIHZhciBfdXNlU3RhdGUgPSByZWFjdC51c2VTdGF0ZSh7XG4gICAgICAgICAgICAgICAgd2lkdGg6IHdpbmRvdy5pbm5lcldpZHRoLFxuICAgICAgICAgICAgICAgIGhlaWdodDogd2luZG93LmlubmVySGVpZ2h0XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB2YXIgd2luZG93RGltZW5zaW9uID0gX3VzZVN0YXRlWzBdO1xuICAgICAgICAgICAgICB2YXIgc2V0RGltZW5zaW9uID0gX3VzZVN0YXRlWzFdO1xuICAgICAgICAgICAgICByZWFjdC51c2VFZmZlY3QoZnVuY3Rpb24gc2lkZUVmZmVjdCgpe1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVJlc2l6ZSgpIHtcbiAgICAgICAgICAgICAgICAgIHNldERpbWVuc2lvbih7d2lkdGg6IHdpbmRvdy5pbm5lcldpZHRoLCBoZWlnaHQ6IHdpbmRvdy5pbm5lckhlaWdodH0pO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIGhhbmRsZVJlc2l6ZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge3dpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCBoYW5kbGVSZXNpemUpO307XG4gICAgICAgICAgICAgIH0sIFtdKTtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlYWN0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAgICAgICAgICAgJ2RpdicsXG4gICAgICAgICAgICAgICAge3N0eWxlOiB7cG9zaXRpb246ICdhYnNvbHV0ZScsIGxlZnQ6IDAsIHdpZHRoOiAnMTAwdncnLCBoZWlnaHQ6ICcxMDB2aCd9fSxcbiAgICAgICAgICAgICAgICAke29wdGlvbnMubW9kZSA9PT0gRVhQT1JUX0hUTUxfTUFQX01PREVTLlJFQUQgPyAnTG9nb1N2ZygpLCcgOiAnJ31cbiAgICAgICAgICAgICAgICByZWFjdC5jcmVhdGVFbGVtZW50KGtlcGxlckdsLktlcGxlckdsLCB7XG4gICAgICAgICAgICAgICAgICBtYXBib3hBcGlBY2Nlc3NUb2tlbjogbWFwYm94VG9rZW4sXG4gICAgICAgICAgICAgICAgICBpZDogXCJtYXBcIixcbiAgICAgICAgICAgICAgICAgIHdpZHRoOiB3aW5kb3dEaW1lbnNpb24ud2lkdGgsXG4gICAgICAgICAgICAgICAgICBoZWlnaHQ6IHdpbmRvd0RpbWVuc2lvbi5oZWlnaHRcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfShSZWFjdCwgS2VwbGVyR2wsIE1BUEJPWF9UT0tFTikpO1xuXG4gICAgICAgICAgY29uc3QgYXBwID0gKGZ1bmN0aW9uIGNyZWF0ZVJlYWN0UmVkdXhQcm92aWRlcihyZWFjdCwgcmVhY3RSZWR1eCwgS2VwbGVyRWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlYWN0LmNyZWF0ZUVsZW1lbnQoXG4gICAgICAgICAgICAgIHJlYWN0UmVkdXguUHJvdmlkZXIsXG4gICAgICAgICAgICAgIHtzdG9yZX0sXG4gICAgICAgICAgICAgIHJlYWN0LmNyZWF0ZUVsZW1lbnQoS2VwbGVyRWxlbWVudCwgbnVsbClcbiAgICAgICAgICAgIClcbiAgICAgICAgICB9KFJlYWN0LCBSZWFjdFJlZHV4LCBLZXBsZXJFbGVtZW50KSk7XG4gICAgICAgICAgLyoqIEVORCBDT01QT05FTlRTICoqL1xuXG4gICAgICAgICAgLyoqIFJlbmRlciAqKi9cbiAgICAgICAgICAoZnVuY3Rpb24gcmVuZGVyKHJlYWN0LCByZWFjdERPTSwgYXBwKSB7XG4gICAgICAgICAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYXBwJyk7XG4gICAgICAgICAgICBjb25zdCByb290ID0gcmVhY3RET00uY3JlYXRlUm9vdChjb250YWluZXIpO1xuICAgICAgICAgICAgcm9vdC5yZW5kZXIoYXBwKTtcbiAgICAgICAgICB9KFJlYWN0LCBSZWFjdERPTSwgYXBwKSk7XG4gICAgICAgIDwvc2NyaXB0PlxuICAgICAgICA8IS0tIFRoZSBuZXh0IHNjcmlwdCB3aWxsIHNob3cgaG93IHRvIGludGVyYWN0IGRpcmVjdGx5IHdpdGggS2VwbGVyIG1hcCBzdG9yZSAtLT5cbiAgICAgICAgPHNjcmlwdD5cbiAgICAgICAgICAvKipcbiAgICAgICAgICAgKiBDdXN0b21pemUgbWFwLlxuICAgICAgICAgICAqIEluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbiB5b3UgY2FuIHVzZSB0aGUgc3RvcmUgb2JqZWN0IHRvIGRpc3BhdGNoIEtlcGxlci5nbCBhY3Rpb25zXG4gICAgICAgICAgICogdG8gYWRkIG5ldyBkYXRhIGFuZCBjdXN0b21pemUgYmVoYXZpb3JcbiAgICAgICAgICAgKi9cbiAgICAgICAgICAoZnVuY3Rpb24gY3VzdG9taXplKGtlcGxlckdsLCBzdG9yZSkge1xuICAgICAgICAgICAgY29uc3QgZGF0YXNldHMgPSAke0pTT04uc3RyaW5naWZ5KG9wdGlvbnMuZGF0YXNldHMpfTtcbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZyA9ICR7SlNPTi5zdHJpbmdpZnkob3B0aW9ucy5jb25maWcpfTtcblxuICAgICAgICAgICAgY29uc3QgbG9hZGVkRGF0YSA9IGtlcGxlckdsLktlcGxlckdsU2NoZW1hLmxvYWQoXG4gICAgICAgICAgICAgIGRhdGFzZXRzLFxuICAgICAgICAgICAgICBjb25maWdcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIEZvciBzb21lIHJlYXNvbiBLZXBsZXIgb3ZlcndyaXRlcyB0aGUgY29uZmlnIHdpdGhvdXQgZXh0cmEgd2FpdCB0aW1lXG4gICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgIHN0b3JlLmRpc3BhdGNoKFxuICAgICAgICAgICAgICAgIGtlcGxlckdsLmFkZERhdGFUb01hcCh7XG4gICAgICAgICAgICAgICAgICBkYXRhc2V0czogbG9hZGVkRGF0YS5kYXRhc2V0cyxcbiAgICAgICAgICAgICAgICAgIGNvbmZpZzogbG9hZGVkRGF0YS5jb25maWcsXG4gICAgICAgICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgICAgICAgIGNlbnRlck1hcDogZmFsc2UsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LCA1MDApO1xuICAgICAgICAgIH0oS2VwbGVyR2wsIHN0b3JlKSlcbiAgICAgICAgPC9zY3JpcHQ+XG4gICAgICA8L2JvZHk+XG4gICAgPC9odG1sPlxuICBgO1xufTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBSUEsSUFBQUEsVUFBQSxHQUFBQyxPQUFBO0FBSkE7QUFDQTs7QUFFQTs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sSUFBTUMsZUFBZSxHQUFBQyxPQUFBLENBQUFELGVBQUEsR0FBRyxTQUFsQkEsZUFBZUEsQ0FBSUUsT0FBTyxFQUFrQztFQUFBLElBQWhDQyxPQUFPLEdBQUFDLFNBQUEsQ0FBQUMsTUFBQSxRQUFBRCxTQUFBLFFBQUFFLFNBQUEsR0FBQUYsU0FBQSxNQUFHRyw0QkFBaUI7RUFDbEUsa1hBQUFDLE1BQUEsQ0FXZ0RMLE9BQU8seTRFQUFBSyxNQUFBLENBZ0NOTCxPQUFPLDhUQUFBSyxNQUFBLENBV3hCTixPQUFPLENBQUNPLG9CQUFvQixJQUFJLHNCQUFzQixxbEVBQUFELE1BQUEsQ0EyQzFETixPQUFPLENBQUNRLElBQUksS0FBS0MsZ0NBQXFCLENBQUNDLElBQUksMG9OQUFBSixNQUFBLENBbUZ2RE4sT0FBTyxDQUFDUSxJQUFJLEtBQUtDLGdDQUFxQixDQUFDQyxJQUFJLEdBQUcsWUFBWSxHQUFHLEVBQUUsMDJDQUFBSixNQUFBLENBbUNsREssSUFBSSxDQUFDQyxTQUFTLENBQUNaLE9BQU8sQ0FBQ2EsUUFBUSxDQUFDLG9DQUFBUCxNQUFBLENBQ2xDSyxJQUFJLENBQUNDLFNBQVMsQ0FBQ1osT0FBTyxDQUFDYyxNQUFNLENBQUM7QUF3QjNELENBQUMiLCJpZ25vcmVMaXN0IjpbXX0=