UNPKG

kepler.gl

Version:

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

191 lines (181 loc) 23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RasterLayerResources = void 0; exports.bandIndexesToURLParams = bandIndexesToURLParams; exports.getMeshMaxError = getMeshMaxError; exports.getSingleCOGUrlParams = getSingleCOGUrlParams; exports.getStacApiUrlParams = getStacApiUrlParams; exports.getTerrainUrl = getTerrainUrl; exports.getTitilerPathMapping = getTitilerPathMapping; exports.getTitilerUrl = getTitilerUrl; var _utils = require("@kepler.gl/utils"); var _config = require("./config"); // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project /* Utilities for creating request urls */ /* global URLSearchParams */ var TILE_SIZE = 256; var STAC_SEARCH_DATA = { // Commenting out Microsoft for now // microsoft: { // sentinelCollectionName: ['sentinel-2-l2a'], // stacSearchUrl: 'https://planetarycomputer.microsoft.com/api/stac/v1/search' // }, 'earth-search': { sentinelCollectionName: ['sentinel-s2-l2a-cogs'], stacSearchUrl: 'https://earth-search.aws.element84.com/v0/search' } }; /** * Construct query parameters to be sent to STAC API instance */ function constructStacApiQuery(options) { var _STAC_SEARCH_DATA$sta; var stac = options.stac, startDate = options.startDate, endDate = options.endDate, stacSearchProvider = options.stacSearchProvider; // This is a quick hack to support the same Sentinel 2 STAC object for searching both microsoft // and AWS var collections = ((_STAC_SEARCH_DATA$sta = STAC_SEARCH_DATA[stacSearchProvider]) === null || _STAC_SEARCH_DATA$sta === void 0 ? void 0 : _STAC_SEARCH_DATA$sta.sentinelCollectionName) || [stac.id]; return { collections: collections, datetime: "".concat(startDate, "T00:00:00Z/").concat(endDate, "T23:59:59Z") }; } /** * Perform lookup to find url of desired STAC search provider */ function getStacApiUrl(stacSearchProvider) { return STAC_SEARCH_DATA[stacSearchProvider].stacSearchUrl; } function getStacApiUrlParams(options) { var stac = options.stac, loadAssetIds = options.loadAssetIds, stacSearchProvider = options.stacSearchProvider, _options$mask = options.mask, mask = _options$mask === void 0 ? false : _options$mask; var query = options._stacQuery || JSON.stringify(constructStacApiQuery(options)); var searchUrl = getStacApiUrl(stacSearchProvider); if (!searchUrl) { return null; } var bandIndexAssets = loadAssetIds.map(function (assetId) { var mapping = _config.DEFAULT_BAND_MAPPINGS[stac.id]; if (!mapping) { // TODO provide a UI to setup custom band mapping return assetId; } var bandIndex = mapping[assetId]; if (bandIndex) { return bandIndex; } // This is most likely incorrect as BXX is expected, not common name return assetId; }); return new URLSearchParams({ assets: bandIndexAssets.join(','), return_mask: String(mask), url: searchUrl, query: query }); } function bandIndexesToURLParams(urlParams, bandIndexes) { if ((0, _utils.getApplicationConfig)().rasterServerUseLatestTitiler) { // for newer titiler versions bandIndexes.forEach(function (bandIndex) { urlParams.append('bidx', String(bandIndex + 1)); }); } else { // The parameter in titiler is `bands` for landsat/sentinel and `bidx` for COG // GDAL/Rasterio/rio-tiler start band indexing at one // older titiler versions urlParams.append('bidx', bandIndexes.map(function (val) { return val + 1; }).join(',')); } return urlParams; } function getSingleCOGUrlParams(options) { var stac = options.stac, loadAssetId = options.loadAssetId, loadBandIndexes = options.loadBandIndexes, _options$mask2 = options.mask, mask = _options$mask2 === void 0 ? false : _options$mask2; var url = stac.assets[loadAssetId].href; if (!url) { return null; } var urlParams = new URLSearchParams({ return_mask: String(mask), url: url }); return bandIndexesToURLParams(urlParams, loadBandIndexes); } /** * Construct full URL to load tile from a Titiler-based backend */ function getTitilerUrl(options) { var _stac$rasterTileServe; // mask Set to false for mosaics because entire image is assumed to be valid var stac = options.stac, useSTACSearching = options.useSTACSearching, x = options.x, y = options.y, z = options.z; if (!((_stac$rasterTileServe = stac.rasterTileServerUrls) !== null && _stac$rasterTileServe !== void 0 && _stac$rasterTileServe.length)) { throw new Error('No raster tile servers'); } var pathStem = getTitilerPathMapping(stac, useSTACSearching); var scale = TILE_SIZE === 512 ? '@2x' : ''; var domain = chooseDomain(stac.rasterTileServerUrls, x, y); return "".concat(domain, "/").concat(pathStem, "/tiles/WebMercatorQuad/").concat(z, "/").concat(x, "/").concat(y).concat(scale, ".npy"); } function getTitilerPathMapping(stac) { var useSTACSearching = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; if (useSTACSearching) { return 'stac/mosaic'; } return 'cog'; } /** * Choose from available domains to load images from * * @param x x tile index * @param y y tile index * * @return domain */ function chooseDomain(domains, x, y) { var index = Math.abs(x + y) % domains.length; return domains[index]; } function getTerrainUrl(rasterTileServerUrls, x, y, z, meshMaxError) { var scale = TILE_SIZE === 512 ? '@2x' : ''; var params = new URLSearchParams({ url: 'terrarium', mesh_max_error: meshMaxError.toFixed(2) }); var domain = chooseDomain(rasterTileServerUrls, x, y); var baseUrl = "".concat(domain, "/mesh/tiles/").concat(z, "/").concat(x, "/").concat(y).concat(scale, ".terrain?"); return baseUrl + params.toString(); } /** * get mesh max error for z value * @param z mercator tile z coord * @param multiplier multipler applied to default error * * Uses suggestion from here * https://www.linkedin.com/pulse/fast-cesium-terrain-rendering-new-quantized-mesh-output-alvaro-huarte/ */ function getMeshMaxError(z, multiplier) { return 77067.34 / (1 << z) * multiplier; } var RasterLayerResources = exports.RasterLayerResources = { rasterColorMap: function rasterColorMap(colormapId) { return "".concat((0, _utils.getApplicationConfig)().cdnUrl, "/raster/colormaps/").concat(colormapId, ".png"); } }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfdXRpbHMiLCJyZXF1aXJlIiwiX2NvbmZpZyIsIlRJTEVfU0laRSIsIlNUQUNfU0VBUkNIX0RBVEEiLCJzZW50aW5lbENvbGxlY3Rpb25OYW1lIiwic3RhY1NlYXJjaFVybCIsImNvbnN0cnVjdFN0YWNBcGlRdWVyeSIsIm9wdGlvbnMiLCJfU1RBQ19TRUFSQ0hfREFUQSRzdGEiLCJzdGFjIiwic3RhcnREYXRlIiwiZW5kRGF0ZSIsInN0YWNTZWFyY2hQcm92aWRlciIsImNvbGxlY3Rpb25zIiwiaWQiLCJkYXRldGltZSIsImNvbmNhdCIsImdldFN0YWNBcGlVcmwiLCJnZXRTdGFjQXBpVXJsUGFyYW1zIiwibG9hZEFzc2V0SWRzIiwiX29wdGlvbnMkbWFzayIsIm1hc2siLCJxdWVyeSIsIl9zdGFjUXVlcnkiLCJKU09OIiwic3RyaW5naWZ5Iiwic2VhcmNoVXJsIiwiYmFuZEluZGV4QXNzZXRzIiwibWFwIiwiYXNzZXRJZCIsIm1hcHBpbmciLCJERUZBVUxUX0JBTkRfTUFQUElOR1MiLCJiYW5kSW5kZXgiLCJVUkxTZWFyY2hQYXJhbXMiLCJhc3NldHMiLCJqb2luIiwicmV0dXJuX21hc2siLCJTdHJpbmciLCJ1cmwiLCJiYW5kSW5kZXhlc1RvVVJMUGFyYW1zIiwidXJsUGFyYW1zIiwiYmFuZEluZGV4ZXMiLCJnZXRBcHBsaWNhdGlvbkNvbmZpZyIsInJhc3RlclNlcnZlclVzZUxhdGVzdFRpdGlsZXIiLCJmb3JFYWNoIiwiYXBwZW5kIiwidmFsIiwiZ2V0U2luZ2xlQ09HVXJsUGFyYW1zIiwibG9hZEFzc2V0SWQiLCJsb2FkQmFuZEluZGV4ZXMiLCJfb3B0aW9ucyRtYXNrMiIsImhyZWYiLCJnZXRUaXRpbGVyVXJsIiwiX3N0YWMkcmFzdGVyVGlsZVNlcnZlIiwidXNlU1RBQ1NlYXJjaGluZyIsIngiLCJ5IiwieiIsInJhc3RlclRpbGVTZXJ2ZXJVcmxzIiwibGVuZ3RoIiwiRXJyb3IiLCJwYXRoU3RlbSIsImdldFRpdGlsZXJQYXRoTWFwcGluZyIsInNjYWxlIiwiZG9tYWluIiwiY2hvb3NlRG9tYWluIiwiYXJndW1lbnRzIiwidW5kZWZpbmVkIiwiZG9tYWlucyIsImluZGV4IiwiTWF0aCIsImFicyIsImdldFRlcnJhaW5VcmwiLCJtZXNoTWF4RXJyb3IiLCJwYXJhbXMiLCJtZXNoX21heF9lcnJvciIsInRvRml4ZWQiLCJiYXNlVXJsIiwidG9TdHJpbmciLCJnZXRNZXNoTWF4RXJyb3IiLCJtdWx0aXBsaWVyIiwiUmFzdGVyTGF5ZXJSZXNvdXJjZXMiLCJleHBvcnRzIiwicmFzdGVyQ29sb3JNYXAiLCJjb2xvcm1hcElkIiwiY2RuVXJsIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Jhc3Rlci10aWxlL3VybC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG4vKiBVdGlsaXRpZXMgZm9yIGNyZWF0aW5nIHJlcXVlc3QgdXJscyAqL1xuLyogZ2xvYmFsIFVSTFNlYXJjaFBhcmFtcyAqL1xuXG5pbXBvcnQge1N0YWNUeXBlc30gZnJvbSAnQGtlcGxlci5nbC90eXBlcyc7XG5pbXBvcnQge2dldEFwcGxpY2F0aW9uQ29uZmlnfSBmcm9tICdAa2VwbGVyLmdsL3V0aWxzJztcblxuaW1wb3J0IHtERUZBVUxUX0JBTkRfTUFQUElOR1N9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7XG4gIEFzc2V0SWRzLFxuICBCYW5kSW5kZXhlcyxcbiAgQ29tcGxldGVTVEFDSXRlbSxcbiAgQ29tcGxldGVTVEFDQ29sbGVjdGlvbixcbiAgR2V0VGlsZURhdGFQcm9wc1xufSBmcm9tICcuL3R5cGVzJztcblxudHlwZSBJdGVtID0gU3RhY1R5cGVzLlNUQUNJdGVtO1xudHlwZSBDb2xsZWN0aW9uID0gU3RhY1R5cGVzLlNUQUNDb2xsZWN0aW9uO1xuXG5jb25zdCBUSUxFX1NJWkU6IDI1NiB8IDUxMiA9IDI1NjtcblxuaW50ZXJmYWNlIFN0YWNTZWFyY2hJbmZvIHtcbiAgc2VudGluZWxDb2xsZWN0aW9uTmFtZTogc3RyaW5nW107XG4gIHN0YWNTZWFyY2hVcmw6IHN0cmluZztcbn1cblxuY29uc3QgU1RBQ19TRUFSQ0hfREFUQTogUmVjb3JkPHN0cmluZywgU3RhY1NlYXJjaEluZm8+ID0ge1xuICAvLyBDb21tZW50aW5nIG91dCBNaWNyb3NvZnQgZm9yIG5vd1xuICAvLyBtaWNyb3NvZnQ6IHtcbiAgLy8gICBzZW50aW5lbENvbGxlY3Rpb25OYW1lOiBbJ3NlbnRpbmVsLTItbDJhJ10sXG4gIC8vICAgc3RhY1NlYXJjaFVybDogJ2h0dHBzOi8vcGxhbmV0YXJ5Y29tcHV0ZXIubWljcm9zb2Z0LmNvbS9hcGkvc3RhYy92MS9zZWFyY2gnXG4gIC8vIH0sXG4gICdlYXJ0aC1zZWFyY2gnOiB7XG4gICAgc2VudGluZWxDb2xsZWN0aW9uTmFtZTogWydzZW50aW5lbC1zMi1sMmEtY29ncyddLFxuICAgIHN0YWNTZWFyY2hVcmw6ICdodHRwczovL2VhcnRoLXNlYXJjaC5hd3MuZWxlbWVudDg0LmNvbS92MC9zZWFyY2gnXG4gIH1cbn07XG5cbi8qKlxuICogQ29uc3RydWN0IHF1ZXJ5IHBhcmFtZXRlcnMgdG8gYmUgc2VudCB0byBTVEFDIEFQSSBpbnN0YW5jZVxuICovXG5mdW5jdGlvbiBjb25zdHJ1Y3RTdGFjQXBpUXVlcnkob3B0aW9uczoge1xuICBzdGFjOiBJdGVtIHwgQ29sbGVjdGlvbjtcbiAgc3RhcnREYXRlOiBzdHJpbmc7XG4gIGVuZERhdGU6IHN0cmluZztcbiAgc3RhY1NlYXJjaFByb3ZpZGVyOiBzdHJpbmc7XG59KToge2NvbGxlY3Rpb25zOiBzdHJpbmdbXTsgZGF0ZXRpbWU6IHN0cmluZ30ge1xuICBjb25zdCB7c3RhYywgc3RhcnREYXRlLCBlbmREYXRlLCBzdGFjU2VhcmNoUHJvdmlkZXJ9ID0gb3B0aW9ucztcblxuICAvLyBUaGlzIGlzIGEgcXVpY2sgaGFjayB0byBzdXBwb3J0IHRoZSBzYW1lIFNlbnRpbmVsIDIgU1RBQyBvYmplY3QgZm9yIHNlYXJjaGluZyBib3RoIG1pY3Jvc29mdFxuICAvLyBhbmQgQVdTXG4gIGNvbnN0IGNvbGxlY3Rpb25zID0gU1RBQ19TRUFSQ0hfREFUQVtzdGFjU2VhcmNoUHJvdmlkZXJdPy5zZW50aW5lbENvbGxlY3Rpb25OYW1lIHx8IFtzdGFjLmlkXTtcblxuICByZXR1cm4ge1xuICAgIGNvbGxlY3Rpb25zLFxuICAgIGRhdGV0aW1lOiBgJHtzdGFydERhdGV9VDAwOjAwOjAwWi8ke2VuZERhdGV9VDIzOjU5OjU5WmBcbiAgfTtcbn1cblxuLyoqXG4gKiBQZXJmb3JtIGxvb2t1cCB0byBmaW5kIHVybCBvZiBkZXNpcmVkIFNUQUMgc2VhcmNoIHByb3ZpZGVyXG4gKi9cbmZ1bmN0aW9uIGdldFN0YWNBcGlVcmwoc3RhY1NlYXJjaFByb3ZpZGVyOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gU1RBQ19TRUFSQ0hfREFUQVtzdGFjU2VhcmNoUHJvdmlkZXJdLnN0YWNTZWFyY2hVcmw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFjQXBpVXJsUGFyYW1zKG9wdGlvbnM6IHtcbiAgc3RhYzogQ29tcGxldGVTVEFDQ29sbGVjdGlvbjtcbiAgc3RhY1NlYXJjaFByb3ZpZGVyOiBzdHJpbmc7XG4gIHN0YXJ0RGF0ZTogc3RyaW5nO1xuICBlbmREYXRlOiBzdHJpbmc7XG4gIG1hc2s/OiBib29sZWFuO1xuICBsb2FkQXNzZXRJZHM6IEFzc2V0SWRzO1xuICBfc3RhY1F1ZXJ5Pzogc3RyaW5nO1xufSk6IFVSTFNlYXJjaFBhcmFtcyB8IG51bGwge1xuICBjb25zdCB7c3RhYywgbG9hZEFzc2V0SWRzLCBzdGFjU2VhcmNoUHJvdmlkZXIsIG1hc2sgPSBmYWxzZX0gPSBvcHRpb25zO1xuICBjb25zdCBxdWVyeSA9IG9wdGlvbnMuX3N0YWNRdWVyeSB8fCBKU09OLnN0cmluZ2lmeShjb25zdHJ1Y3RTdGFjQXBpUXVlcnkob3B0aW9ucykpO1xuICBjb25zdCBzZWFyY2hVcmwgPSBnZXRTdGFjQXBpVXJsKHN0YWNTZWFyY2hQcm92aWRlcik7XG5cbiAgaWYgKCFzZWFyY2hVcmwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGJhbmRJbmRleEFzc2V0cyA9IGxvYWRBc3NldElkcy5tYXAoYXNzZXRJZCA9PiB7XG4gICAgY29uc3QgbWFwcGluZyA9IERFRkFVTFRfQkFORF9NQVBQSU5HU1tzdGFjLmlkXTtcbiAgICBpZiAoIW1hcHBpbmcpIHtcbiAgICAgIC8vIFRPRE8gcHJvdmlkZSBhIFVJIHRvIHNldHVwIGN1c3RvbSBiYW5kIG1hcHBpbmdcbiAgICAgIHJldHVybiBhc3NldElkO1xuICAgIH1cblxuICAgIGNvbnN0IGJhbmRJbmRleCA9IG1hcHBpbmdbYXNzZXRJZF07XG4gICAgaWYgKGJhbmRJbmRleCkge1xuICAgICAgcmV0dXJuIGJhbmRJbmRleDtcbiAgICB9XG5cbiAgICAvLyBUaGlzIGlzIG1vc3QgbGlrZWx5IGluY29ycmVjdCBhcyBCWFggaXMgZXhwZWN0ZWQsIG5vdCBjb21tb24gbmFtZVxuICAgIHJldHVybiBhc3NldElkO1xuICB9KTtcblxuICByZXR1cm4gbmV3IFVSTFNlYXJjaFBhcmFtcyh7XG4gICAgYXNzZXRzOiBiYW5kSW5kZXhBc3NldHMuam9pbignLCcpLFxuICAgIHJldHVybl9tYXNrOiBTdHJpbmcobWFzayksXG4gICAgdXJsOiBzZWFyY2hVcmwsXG4gICAgcXVlcnlcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBiYW5kSW5kZXhlc1RvVVJMUGFyYW1zKFxuICB1cmxQYXJhbXM6IFVSTFNlYXJjaFBhcmFtcyxcbiAgYmFuZEluZGV4ZXM6IEJhbmRJbmRleGVzXG4pOiBVUkxTZWFyY2hQYXJhbXMge1xuICBpZiAoZ2V0QXBwbGljYXRpb25Db25maWcoKS5yYXN0ZXJTZXJ2ZXJVc2VMYXRlc3RUaXRpbGVyKSB7XG4gICAgLy8gZm9yIG5ld2VyIHRpdGlsZXIgdmVyc2lvbnNcbiAgICBiYW5kSW5kZXhlcy5mb3JFYWNoKGJhbmRJbmRleCA9PiB7XG4gICAgICB1cmxQYXJhbXMuYXBwZW5kKCdiaWR4JywgU3RyaW5nKGJhbmRJbmRleCArIDEpKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICAvLyBUaGUgcGFyYW1ldGVyIGluIHRpdGlsZXIgaXMgYGJhbmRzYCBmb3IgbGFuZHNhdC9zZW50aW5lbCBhbmQgYGJpZHhgIGZvciBDT0dcbiAgICAvLyBHREFML1Jhc3RlcmlvL3Jpby10aWxlciBzdGFydCBiYW5kIGluZGV4aW5nIGF0IG9uZVxuICAgIC8vIG9sZGVyIHRpdGlsZXIgdmVyc2lvbnNcbiAgICB1cmxQYXJhbXMuYXBwZW5kKCdiaWR4JywgYmFuZEluZGV4ZXMubWFwKHZhbCA9PiB2YWwgKyAxKS5qb2luKCcsJykpO1xuICB9XG5cbiAgcmV0dXJuIHVybFBhcmFtcztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNpbmdsZUNPR1VybFBhcmFtcyhvcHRpb25zOiB7XG4gIHN0YWM6IENvbXBsZXRlU1RBQ0l0ZW07XG4gIGxvYWRBc3NldElkOiBzdHJpbmc7XG4gIGxvYWRCYW5kSW5kZXhlczogQmFuZEluZGV4ZXM7XG4gIG1hc2s/OiBib29sZWFuO1xufSk6IFVSTFNlYXJjaFBhcmFtcyB8IG51bGwge1xuICBjb25zdCB7c3RhYywgbG9hZEFzc2V0SWQsIGxvYWRCYW5kSW5kZXhlcywgbWFzayA9IGZhbHNlfSA9IG9wdGlvbnM7XG4gIGNvbnN0IHVybCA9IHN0YWMuYXNzZXRzW2xvYWRBc3NldElkXS5ocmVmO1xuXG4gIGlmICghdXJsKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCB1cmxQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICByZXR1cm5fbWFzazogU3RyaW5nKG1hc2spLFxuICAgIHVybFxuICB9KTtcbiAgcmV0dXJuIGJhbmRJbmRleGVzVG9VUkxQYXJhbXModXJsUGFyYW1zLCBsb2FkQmFuZEluZGV4ZXMpO1xufVxuXG4vKipcbiAqIENvbnN0cnVjdCBmdWxsIFVSTCB0byBsb2FkIHRpbGUgZnJvbSBhIFRpdGlsZXItYmFzZWQgYmFja2VuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGl0aWxlclVybChvcHRpb25zOiB7XG4gIHN0YWM6IEdldFRpbGVEYXRhUHJvcHNbJ3N0YWMnXTtcbiAgdXNlU1RBQ1NlYXJjaGluZzogYm9vbGVhbjtcbiAgeDogbnVtYmVyO1xuICB5OiBudW1iZXI7XG4gIHo6IG51bWJlcjtcbn0pOiBzdHJpbmcge1xuICAvLyBtYXNrIFNldCB0byBmYWxzZSBmb3IgbW9zYWljcyBiZWNhdXNlIGVudGlyZSBpbWFnZSBpcyBhc3N1bWVkIHRvIGJlIHZhbGlkXG4gIGNvbnN0IHtzdGFjLCB1c2VTVEFDU2VhcmNoaW5nLCB4LCB5LCB6fSA9IG9wdGlvbnM7XG5cbiAgaWYgKCFzdGFjLnJhc3RlclRpbGVTZXJ2ZXJVcmxzPy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHJhc3RlciB0aWxlIHNlcnZlcnMnKTtcbiAgfVxuXG4gIGNvbnN0IHBhdGhTdGVtID0gZ2V0VGl0aWxlclBhdGhNYXBwaW5nKHN0YWMsIHVzZVNUQUNTZWFyY2hpbmcpO1xuICBjb25zdCBzY2FsZSA9IFRJTEVfU0laRSA9PT0gNTEyID8gJ0AyeCcgOiAnJztcbiAgY29uc3QgZG9tYWluID0gY2hvb3NlRG9tYWluKHN0YWMucmFzdGVyVGlsZVNlcnZlclVybHMsIHgsIHkpO1xuICByZXR1cm4gYCR7ZG9tYWlufS8ke3BhdGhTdGVtfS90aWxlcy9XZWJNZXJjYXRvclF1YWQvJHt6fS8ke3h9LyR7eX0ke3NjYWxlfS5ucHlgO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGl0aWxlclBhdGhNYXBwaW5nKFxuICBzdGFjOiBHZXRUaWxlRGF0YVByb3BzWydzdGFjJ10sXG4gIHVzZVNUQUNTZWFyY2hpbmcgPSBmYWxzZVxuKTogc3RyaW5nIHtcbiAgaWYgKHVzZVNUQUNTZWFyY2hpbmcpIHtcbiAgICByZXR1cm4gJ3N0YWMvbW9zYWljJztcbiAgfVxuXG4gIHJldHVybiAnY29nJztcbn1cblxuLyoqXG4gKiBDaG9vc2UgZnJvbSBhdmFpbGFibGUgZG9tYWlucyB0byBsb2FkIGltYWdlcyBmcm9tXG4gKlxuICogQHBhcmFtIHggIHggdGlsZSBpbmRleFxuICogQHBhcmFtIHkgIHkgdGlsZSBpbmRleFxuICpcbiAqIEByZXR1cm4gZG9tYWluXG4gKi9cbmZ1bmN0aW9uIGNob29zZURvbWFpbihkb21haW5zOiBzdHJpbmdbXSwgeDogbnVtYmVyLCB5OiBudW1iZXIpOiBzdHJpbmcge1xuICBjb25zdCBpbmRleCA9IE1hdGguYWJzKHggKyB5KSAlIGRvbWFpbnMubGVuZ3RoO1xuICByZXR1cm4gZG9tYWluc1tpbmRleF07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUZXJyYWluVXJsKFxuICByYXN0ZXJUaWxlU2VydmVyVXJsczogc3RyaW5nW10sXG4gIHg6IG51bWJlcixcbiAgeTogbnVtYmVyLFxuICB6OiBudW1iZXIsXG4gIG1lc2hNYXhFcnJvcjogbnVtYmVyXG4pOiBzdHJpbmcge1xuICBjb25zdCBzY2FsZSA9IFRJTEVfU0laRSA9PT0gNTEyID8gJ0AyeCcgOiAnJztcblxuICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICB1cmw6ICd0ZXJyYXJpdW0nLFxuICAgIG1lc2hfbWF4X2Vycm9yOiBtZXNoTWF4RXJyb3IudG9GaXhlZCgyKVxuICB9KTtcbiAgY29uc3QgZG9tYWluID0gY2hvb3NlRG9tYWluKHJhc3RlclRpbGVTZXJ2ZXJVcmxzLCB4LCB5KTtcbiAgY29uc3QgYmFzZVVybCA9IGAke2RvbWFpbn0vbWVzaC90aWxlcy8ke3p9LyR7eH0vJHt5fSR7c2NhbGV9LnRlcnJhaW4/YDtcbiAgcmV0dXJuIGJhc2VVcmwgKyBwYXJhbXMudG9TdHJpbmcoKTtcbn1cblxuLyoqXG4gKiBnZXQgbWVzaCBtYXggZXJyb3IgZm9yIHogdmFsdWVcbiAqIEBwYXJhbSB6IG1lcmNhdG9yIHRpbGUgeiBjb29yZFxuICogQHBhcmFtIG11bHRpcGxpZXIgbXVsdGlwbGVyIGFwcGxpZWQgdG8gZGVmYXVsdCBlcnJvclxuICpcbiAqIFVzZXMgc3VnZ2VzdGlvbiBmcm9tIGhlcmVcbiAqIGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9wdWxzZS9mYXN0LWNlc2l1bS10ZXJyYWluLXJlbmRlcmluZy1uZXctcXVhbnRpemVkLW1lc2gtb3V0cHV0LWFsdmFyby1odWFydGUvXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNZXNoTWF4RXJyb3IoejogbnVtYmVyLCBtdWx0aXBsaWVyOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gKDc3MDY3LjM0IC8gKDEgPDwgeikpICogbXVsdGlwbGllcjtcbn1cblxuZXhwb3J0IGNvbnN0IFJhc3RlckxheWVyUmVzb3VyY2VzID0ge1xuICByYXN0ZXJDb2xvck1hcDogKGNvbG9ybWFwSWQ6IHN0cmluZykgPT4ge1xuICAgIHJldHVybiBgJHtnZXRBcHBsaWNhdGlvbkNvbmZpZygpLmNkblVybH0vcmFzdGVyL2NvbG9ybWFwcy8ke2NvbG9ybWFwSWR9LnBuZ2A7XG4gIH1cbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFPQSxJQUFBQSxNQUFBLEdBQUFDLE9BQUE7QUFFQSxJQUFBQyxPQUFBLEdBQUFELE9BQUE7QUFUQTtBQUNBOztBQUVBO0FBQ0E7O0FBaUJBLElBQU1FLFNBQW9CLEdBQUcsR0FBRztBQU9oQyxJQUFNQyxnQkFBZ0QsR0FBRztFQUN2RDtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0EsY0FBYyxFQUFFO0lBQ2RDLHNCQUFzQixFQUFFLENBQUMsc0JBQXNCLENBQUM7SUFDaERDLGFBQWEsRUFBRTtFQUNqQjtBQUNGLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsU0FBU0MscUJBQXFCQSxDQUFDQyxPQUs5QixFQUE2QztFQUFBLElBQUFDLHFCQUFBO0VBQzVDLElBQU9DLElBQUksR0FBNENGLE9BQU8sQ0FBdkRFLElBQUk7SUFBRUMsU0FBUyxHQUFpQ0gsT0FBTyxDQUFqREcsU0FBUztJQUFF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