UNPKG

kepler.gl

Version:

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

415 lines (412 loc) 54 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.filesToDataPayload = filesToDataPayload; exports.isArrowData = isArrowData; exports.isArrowTable = isArrowTable; exports.isFeature = isFeature; exports.isFeatureCollection = isFeatureCollection; exports.isGeoJson = isGeoJson; exports.isKeplerGlMap = isKeplerGlMap; exports.isRowObject = isRowObject; exports.makeProgressIterator = makeProgressIterator; exports.processFileData = processFileData; exports.readBatch = readBatch; exports.readFileInBatches = readFileInBatches; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _awaitAsyncGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/awaitAsyncGenerator")); var _wrapAsyncGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/wrapAsyncGenerator")); var arrow = _interopRequireWildcard(require("apache-arrow")); var _core = require("@loaders.gl/core"); var _json = require("@loaders.gl/json"); var _csv = require("@loaders.gl/csv"); var _arrow = require("@loaders.gl/arrow"); var _parquet = require("@loaders.gl/parquet"); var _utils = require("@kepler.gl/utils"); var _commonUtils = require("@kepler.gl/common-utils"); var _constants = require("@kepler.gl/constants"); var _table = require("@kepler.gl/table"); var _dataProcessor = require("./data-processor"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _asyncIterator(r) { var n, t, o, e = 2; for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) { if (t && null != (n = r[t])) return n.call(r); if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r)); t = "@@asyncIterator", o = "@@iterator"; } throw new TypeError("Object is not async iterable"); } function AsyncFromSyncIterator(r) { function AsyncFromSyncIteratorContinuation(r) { if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object.")); var n = r.done; return Promise.resolve(r.value).then(function (r) { return { value: r, done: n }; }); } return AsyncFromSyncIterator = function AsyncFromSyncIterator(r) { this.s = r, this.n = r.next; }, AsyncFromSyncIterator.prototype = { s: null, n: null, next: function next() { return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); }, "return": function _return(r) { var n = this.s["return"]; return void 0 === n ? Promise.resolve({ value: r, done: !0 }) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); }, "throw": function _throw(r) { var n = this.s["return"]; return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); } }, new AsyncFromSyncIterator(r); } // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project var BATCH_TYPE = { METADATA: 'metadata', PARTIAL_RESULT: 'partial-result', FINAL_RESULT: 'final-result' }; var CSV_LOADER_OPTIONS = { shape: 'object-row-table', dynamicTyping: false // not working for now }; var ARROW_LOADER_OPTIONS = { shape: 'arrow-table', batchDebounceMs: 10 // time to delay between batches, for incremental loading }; var PARQUET_LOADER_OPTIONS = { shape: 'arrow-table' }; var JSON_LOADER_OPTIONS = { shape: 'object-row-table', // instruct loaders.gl on what json paths to stream jsonpaths: ['$', // JSON Row array '$.features', // GeoJSON '$.datasets' // KeplerGL JSON ] }; /** * check if table is an ArrowTable object * @param table - object to check * @returns {boolean} - true if table is an ArrowTable object type guarded */ function isArrowTable(table) { return Boolean(table instanceof arrow.Table); } /** * check if data is an ArrowData object, which is an array of RecordBatch * @param data - object to check * @returns {boolean} - true if data is an ArrowData object type guarded */ function isArrowData(data) { return Array.isArray(data) && Boolean(data.length && data[0].data && data[0].schema); } function isGeoJson(json) { // json can be feature collection // or single feature return (0, _utils.isPlainObject)(json) && (isFeature(json) || isFeatureCollection(json)); } function isFeature(json) { return (0, _utils.isPlainObject)(json) && json.type === 'Feature' && Boolean(json.geometry); } function isFeatureCollection(json) { return (0, _utils.isPlainObject)(json) && json.type === 'FeatureCollection' && Boolean(json.features); } function isRowObject(json) { return Array.isArray(json) && (0, _utils.isPlainObject)(json[0]); } function isKeplerGlMap(json) { return Boolean((0, _utils.isPlainObject)(json) && json.datasets && json.config && json.info && (0, _utils.isPlainObject)(json.info) && json.info.app === 'kepler.gl'); } function makeProgressIterator(_x, _x2) { return _makeProgressIterator.apply(this, arguments); } // eslint-disable-next-line complexity function _makeProgressIterator() { _makeProgressIterator = (0, _wrapAsyncGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(asyncIterator, info) { var rowCount, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, batch, rowCountInBatch, percent, progress; return _regenerator["default"].wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: rowCount = 0; _iteratorAbruptCompletion = false; _didIteratorError = false; _context.prev = 3; _iterator = _asyncIterator(asyncIterator); case 5: _context.next = 7; return (0, _awaitAsyncGenerator2["default"])(_iterator.next()); case 7: if (!(_iteratorAbruptCompletion = !(_step = _context.sent).done)) { _context.next = 18; break; } batch = _step.value; // the length could be stored in `batch.length` for arrow batch rowCountInBatch = batch.data && (batch.data.length || batch.length) || 0; rowCount += rowCountInBatch; percent = Number.isFinite(batch.bytesUsed) ? batch.bytesUsed / info.size : null; // Update progress object progress = _objectSpread({ rowCount: rowCount, rowCountInBatch: rowCountInBatch }, Number.isFinite(percent) ? { percent: percent } : {}); _context.next = 15; return _objectSpread(_objectSpread({}, batch), {}, { progress: progress }); case 15: _iteratorAbruptCompletion = false; _context.next = 5; break; case 18: _context.next = 24; break; case 20: _context.prev = 20; _context.t0 = _context["catch"](3); _didIteratorError = true; _iteratorError = _context.t0; case 24: _context.prev = 24; _context.prev = 25; if (!(_iteratorAbruptCompletion && _iterator["return"] != null)) { _context.next = 29; break; } _context.next = 29; return (0, _awaitAsyncGenerator2["default"])(_iterator["return"]()); case 29: _context.prev = 29; if (!_didIteratorError) { _context.next = 32; break; } throw _iteratorError; case 32: return _context.finish(29); case 33: return _context.finish(24); case 34: case "end": return _context.stop(); } }, _callee, null, [[3, 20, 24, 34], [25,, 29, 33]]); })); return _makeProgressIterator.apply(this, arguments); } function readBatch(_x3, _x4) { return _readBatch.apply(this, arguments); } function _readBatch() { _readBatch = (0, _wrapAsyncGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(asyncIterator, fileName) { var result, batches, _iteratorAbruptCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, batch, streamingPath, batchData, i; return _regenerator["default"].wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: result = null; batches = []; _iteratorAbruptCompletion2 = false; _didIteratorError2 = false; _context2.prev = 4; _iterator2 = _asyncIterator(asyncIterator); case 6: _context2.next = 8; return (0, _awaitAsyncGenerator2["default"])(_iterator2.next()); case 8: if (!(_iteratorAbruptCompletion2 = !(_step2 = _context2.sent).done)) { _context2.next = 16; break; } batch = _step2.value; // Last batch will have this special type and will provide all the root // properties of the parsed document. // Only json parse will have `FINAL_RESULT` if (batch.batchType === BATCH_TYPE.FINAL_RESULT) { if (batch.container) { result = _objectSpread({}, batch.container); } // Set the streamed data correctly is Batch json path is set // and the path streamed is not the top level object (jsonpath = '$') if (batch.jsonpath && batch.jsonpath.length > 1) { streamingPath = new _json._JSONPath(batch.jsonpath); streamingPath.setFieldAtPath(result, batches); } else if (batch.jsonpath && batch.jsonpath.length === 1) { // The streamed object is a ROW JSON-batch (jsonpath = '$') // row objects result = batches; } } else { batchData = isArrowTable(batch.data) ? batch.data.batches : batch.data; for (i = 0; i < (batchData === null || batchData === void 0 ? void 0 : batchData.length); i++) { batches.push(batchData[i]); } } _context2.next = 13; return _objectSpread(_objectSpread(_objectSpread({}, batch), batch.schema ? { headers: Object.keys(batch.schema) } : {}), {}, { fileName: fileName, // if dataset is CSV, data is set to the raw batches data: result ? result : batches }); case 13: _iteratorAbruptCompletion2 = false; _context2.next = 6; break; case 16: _context2.next = 22; break; case 18: _context2.prev = 18; _context2.t0 = _context2["catch"](4); _didIteratorError2 = true; _iteratorError2 = _context2.t0; case 22: _context2.prev = 22; _context2.prev = 23; if (!(_iteratorAbruptCompletion2 && _iterator2["return"] != null)) { _context2.next = 27; break; } _context2.next = 27; return (0, _awaitAsyncGenerator2["default"])(_iterator2["return"]()); case 27: _context2.prev = 27; if (!_didIteratorError2) { _context2.next = 30; break; } throw _iteratorError2; case 30: return _context2.finish(27); case 31: return _context2.finish(22); case 32: case "end": return _context2.stop(); } }, _callee2, null, [[4, 18, 22, 32], [23,, 27, 31]]); })); return _readBatch.apply(this, arguments); } function readFileInBatches(_x5) { return _readFileInBatches.apply(this, arguments); } function _readFileInBatches() { _readFileInBatches = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(_ref) { var file, _ref$loaders, loaders, _ref$loadOptions, loadOptions, batchIterator, progressIterator; return _regenerator["default"].wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: file = _ref.file, _ref$loaders = _ref.loaders, loaders = _ref$loaders === void 0 ? [] : _ref$loaders, _ref$loadOptions = _ref.loadOptions, loadOptions = _ref$loadOptions === void 0 ? {} : _ref$loadOptions; loaders = [_json.JSONLoader, _csv.CSVLoader, _arrow.GeoArrowLoader, _parquet.ParquetWasmLoader].concat((0, _toConsumableArray2["default"])(loaders)); loadOptions = _objectSpread({ csv: CSV_LOADER_OPTIONS, arrow: ARROW_LOADER_OPTIONS, json: JSON_LOADER_OPTIONS, parquet: PARQUET_LOADER_OPTIONS, metadata: true }, loadOptions); _context3.next = 5; return (0, _core.parseInBatches)(file, loaders, loadOptions); case 5: batchIterator = _context3.sent; progressIterator = makeProgressIterator(batchIterator, { size: file.size }); return _context3.abrupt("return", readBatch(progressIterator, file.name)); case 8: case "end": return _context3.stop(); } }, _callee3); })); return _readFileInBatches.apply(this, arguments); } function processFileData(_x6) { return _processFileData.apply(this, arguments); } function _processFileData() { _processFileData = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(_ref2) { var _getApplicationConfig; var content, fileCache, fileName, data, format, processor, id, table, processorResult, result; return _regenerator["default"].wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: content = _ref2.content, fileCache = _ref2.fileCache; fileName = content.fileName, data = content.data; // generate unique id with length of 4 using fileName string id = (0, _utils.generateHashIdFromString)(fileName); // decide on which table class to use based on application config table = (_getApplicationConfig = (0, _utils.getApplicationConfig)().table) !== null && _getApplicationConfig !== void 0 ? _getApplicationConfig : _table.KeplerTable; if (typeof table.getFileProcessor === 'function') { // use custom processors from table class processorResult = table.getFileProcessor(data); format = processorResult.format; processor = processorResult.processor; } else { // use default processors if (isArrowData(data)) { format = _constants.DATASET_FORMATS.arrow; processor = _dataProcessor.processArrowBatches; } else if (isKeplerGlMap(data)) { format = _constants.DATASET_FORMATS.keplergl; processor = _dataProcessor.processKeplerglJSON; } else if (isRowObject(data)) { // csv file goes here format = _constants.DATASET_FORMATS.row; processor = _dataProcessor.processRowObject; } else if (isGeoJson(data)) { format = _constants.DATASET_FORMATS.geojson; processor = _dataProcessor.processGeojson; } } if (!(format && processor)) { _context4.next = 18; break; } _context4.prev = 6; _context4.next = 9; return processor(data); case 9: result = _context4.sent; _context4.next = 15; break; case 12: _context4.prev = 12; _context4.t0 = _context4["catch"](6); throw new Error("Can not process uploaded file, ".concat((0, _utils.getError)(_context4.t0))); case 15: return _context4.abrupt("return", [].concat((0, _toConsumableArray2["default"])(fileCache), [{ data: result, info: { id: id, label: content.fileName, format: format } }])); case 18: throw new Error('Can not process uploaded file, unknown file format'); case 19: case "end": return _context4.stop(); } }, _callee4, null, [[6, 12]]); })); return _processFileData.apply(this, arguments); } function filesToDataPayload(fileCache) { // seperate out files which could be a single datasets. or a keplergl map json var collection = fileCache.reduce(function (accu, file) { var data = file.data, info = file.info; if ((info === null || info === void 0 ? void 0 : info.format) === _constants.DATASET_FORMATS.keplergl) { // if file contains a single kepler map dataset & config accu.keplerMaps.push(_objectSpread(_objectSpread({}, data), {}, { options: { centerMap: !(data.config && data.config.mapState) } })); } else if (_constants.DATASET_FORMATS[info === null || info === void 0 ? void 0 : info.format]) { // if file contains only data var newDataset = { data: data, info: _objectSpread({ id: (info === null || info === void 0 ? void 0 : info.id) || (0, _commonUtils.generateHashId)(4) }, info || {}) }; accu.datasets.push(newDataset); } return accu; }, { datasets: [], keplerMaps: [] }); // add kepler map first with config // add datasets later in one add data call return collection.keplerMaps.concat({ datasets: collection.datasets }); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJhcnJvdyIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwicmVxdWlyZSIsIl9jb3JlIiwiX2pzb24iLCJfY3N2IiwiX2Fycm93IiwiX3BhcnF1ZXQiLCJfdXRpbHMiLCJfY29tbW9uVXRpbHMiLCJfY29uc3RhbnRzIiwiX3RhYmxlIiwiX2RhdGFQcm9jZXNzb3IiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX19lc01vZHVsZSIsIl90eXBlb2YiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJvd25LZXlzIiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJfYXN5bmNJdGVyYXRvciIsIlN5bWJvbCIsImFzeW5jSXRlcmF0b3IiLCJpdGVyYXRvciIsIkFzeW5jRnJvbVN5bmNJdGVyYXRvciIsIlR5cGVFcnJvciIsIkFzeW5jRnJvbVN5bmNJdGVyYXRvckNvbnRpbnVhdGlvbiIsIlByb21pc2UiLCJyZWplY3QiLCJkb25lIiwicmVzb2x2ZSIsInZhbHVlIiwidGhlbiIsInMiLCJuZXh0IiwicHJvdG90eXBlIiwiX3JldHVybiIsIl90aHJvdyIsIkJBVENIX1RZUEUiLCJNRVRBREFUQSIsIlBBUlRJQUxfUkVTVUxUIiwiRklOQUxfUkVTVUxUIiwiQ1NWX0xPQURFUl9PUFRJT05TIiwic2hhcGUiLCJkeW5hbWljVHlwaW5nIiwiQVJST1dfTE9BREVSX09QVElPTlMiLCJiYXRjaERlYm91bmNlTXMiLCJQQVJRVUVUX0xPQURFUl9PUFRJT05TIiwiSlNPTl9MT0FERVJfT1BUSU9OUyIsImpzb25wYXRocyIsImlzQXJyb3dUYWJsZSIsInRhYmxlIiwiQm9vbGVhbiIsIlRhYmxlIiwiaXNBcnJvd0RhdGEiLCJkYXRhIiwiQXJyYXkiLCJpc0FycmF5Iiwic2NoZW1hIiwiaXNHZW9Kc29uIiwianNvbiIsImlzUGxhaW5PYmplY3QiLCJpc0ZlYXR1cmUiLCJpc0ZlYXR1cmVDb2xsZWN0aW9uIiwidHlwZSIsImdlb21ldHJ5IiwiZmVhdHVyZXMiLCJpc1Jvd09iamVjdCIsImlzS2VwbGVyR2xNYXAiLCJkYXRhc2V0cyIsImNvbmZpZyIsImluZm8iLCJhcHAiLCJtYWtlUHJvZ3Jlc3NJdGVyYXRvciIsIl94IiwiX3gyIiwiX21ha2VQcm9ncmVzc0l0ZXJhdG9yIiwiX3dyYXBBc3luY0dlbmVyYXRvcjIiLCJfcmVnZW5lcmF0b3IiLCJtYXJrIiwiX2NhbGxlZSIsInJvd0NvdW50IiwiX2l0ZXJhdG9yQWJydXB0Q29tcGxldGlvbiIsIl9kaWRJdGVyYXRvckVycm9yIiwiX2l0ZXJhdG9yRXJyb3IiLCJfaXRlcmF0b3IiLCJfc3RlcCIsImJhdGNoIiwicm93Q291bnRJbkJhdGNoIiwicGVyY2VudCIsInByb2dyZXNzIiwid3JhcCIsIl9jYWxsZWUkIiwiX2NvbnRleHQiLCJwcmV2IiwiX2F3YWl0QXN5bmNHZW5lcmF0b3IyIiwic2VudCIsIk51bWJlciIsImlzRmluaXRlIiwiYnl0ZXNVc2VkIiwic2l6ZSIsInQwIiwiZmluaXNoIiwic3RvcCIsInJlYWRCYXRjaCIsIl94MyIsIl94NCIsIl9yZWFkQmF0Y2giLCJfY2FsbGVlMiIsImZpbGVOYW1lIiwicmVzdWx0IiwiYmF0Y2hlcyIsIl9pdGVyYXRvckFicnVwdENvbXBsZXRpb24yIiwiX2RpZEl0ZXJhdG9yRXJyb3IyIiwiX2l0ZXJhdG9yRXJyb3IyIiwiX2l0ZXJhdG9yMiIsIl9zdGVwMiIsInN0cmVhbWluZ1BhdGgiLCJiYXRjaERhdGEiLCJfY2FsbGVlMiQiLCJfY29udGV4dDIiLCJiYXRjaFR5cGUiLCJjb250YWluZXIiLCJqc29ucGF0aCIsIl9KU09OUGF0aCIsInNldEZpZWxkQXRQYXRoIiwiaGVhZGVycyIsInJlYWRGaWxlSW5CYXRjaGVzIiwiX3g1IiwiX3JlYWRGaWxlSW5CYXRjaGVzIiwiX2FzeW5jVG9HZW5lcmF0b3IyIiwiX2NhbGxlZTMiLCJfcmVmIiwiZmlsZSIsIl9yZWYkbG9hZGVycyIsImxvYWRlcnMiLCJfcmVmJGxvYWRPcHRpb25zIiwibG9hZE9wdGlvbnMiLCJiYXRjaEl0ZXJhdG9yIiwicHJvZ3Jlc3NJdGVyYXRvciIsIl9jYWxsZWUzJCIsIl9jb250ZXh0MyIsIkpTT05Mb2FkZXIiLCJDU1ZMb2FkZXIiLCJHZW9BcnJvd0xvYWRlciIsIlBhcnF1ZXRXYXNtTG9hZGVyIiwiY29uY2F0IiwiX3RvQ29uc3VtYWJsZUFycmF5MiIsImNzdiIsInBhcnF1ZXQiLCJtZXRhZGF0YSIsInBhcnNlSW5CYXRjaGVzIiwiYWJydXB0IiwibmFtZSIsInByb2Nlc3NGaWxlRGF0YSIsIl94NiIsIl9wcm9jZXNzRmlsZURhdGEiLCJfY2FsbGVlNCIsIl9yZWYyIiwiX2dldEFwcGxpY2F0aW9uQ29uZmlnIiwiY29udGVudCIsImZpbGVDYWNoZSIsImZvcm1hdCIsInByb2Nlc3NvciIsImlkIiwicHJvY2Vzc29yUmVzdWx0IiwiX2NhbGxlZTQkIiwiX2NvbnRleHQ0IiwiZ2VuZXJhdGVIYXNoSWRGcm9tU3RyaW5nIiwiZ2V0QXBwbGljYXRpb25Db25maWciLCJLZXBsZXJUYWJsZSIsImdldEZpbGVQcm9jZXNzb3IiLCJEQVRBU0VUX0ZPUk1BVFMiLCJwcm9jZXNzQXJyb3dCYXRjaGVzIiwia2VwbGVyZ2wiLCJwcm9jZXNzS2VwbGVyZ2xKU09OIiwicm93IiwicHJvY2Vzc1Jvd09iamVjdCIsImdlb2pzb24iLCJwcm9jZXNzR2VvanNvbiIsIkVycm9yIiwiZ2V0RXJyb3IiLCJsYWJlbCIsImZpbGVzVG9EYXRhUGF5bG9hZCIsImNvbGxlY3Rpb24iLCJyZWR1Y2UiLCJhY2N1Iiwia2VwbGVyTWFwcyIsIm9wdGlvbnMiLCJjZW50ZXJNYXAiLCJtYXBTdGF0ZSIsIm5ld0RhdGFzZXQiLCJnZW5lcmF0ZUhhc2hJZCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9maWxlLWhhbmRsZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0ICogYXMgYXJyb3cgZnJvbSAnYXBhY2hlLWFycm93JztcbmltcG9ydCB7cGFyc2VJbkJhdGNoZXN9IGZyb20gJ0Bsb2FkZXJzLmdsL2NvcmUnO1xuaW1wb3J0IHtKU09OTG9hZGVyLCBfSlNPTlBhdGh9IGZyb20gJ0Bsb2FkZXJzLmdsL2pzb24nO1xuaW1wb3J0IHtDU1ZMb2FkZXJ9IGZyb20gJ0Bsb2FkZXJzLmdsL2Nzdic7XG5pbXBvcnQge0dlb0Fycm93TG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9hcnJvdyc7XG5pbXBvcnQge1BhcnF1ZXRXYXNtTG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9wYXJxdWV0JztcbmltcG9ydCB7TG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC9sb2FkZXItdXRpbHMnO1xuaW1wb3J0IHtcbiAgaXNQbGFpbk9iamVjdCxcbiAgZ2VuZXJhdGVIYXNoSWRGcm9tU3RyaW5nLFxuICBnZXRBcHBsaWNhdGlvbkNvbmZpZyxcbiAgZ2V0RXJyb3Jcbn0gZnJvbSAnQGtlcGxlci5nbC91dGlscyc7XG5pbXBvcnQge2dlbmVyYXRlSGFzaElkfSBmcm9tICdAa2VwbGVyLmdsL2NvbW1vbi11dGlscyc7XG5pbXBvcnQge0RBVEFTRVRfRk9STUFUU30gZnJvbSAnQGtlcGxlci5nbC9jb25zdGFudHMnO1xuaW1wb3J0IHtBZGREYXRhVG9NYXBQYXlsb2FkLCBGZWF0dXJlLCBMb2FkZWRNYXAsIFByb2Nlc3NvclJlc3VsdH0gZnJvbSAnQGtlcGxlci5nbC90eXBlcyc7XG5pbXBvcnQge0tlcGxlclRhYmxlfSBmcm9tICdAa2VwbGVyLmdsL3RhYmxlJztcbmltcG9ydCB7RmVhdHVyZUNvbGxlY3Rpb259IGZyb20gJ0B0dXJmL2hlbHBlcnMnO1xuXG5pbXBvcnQge1xuICBwcm9jZXNzQXJyb3dCYXRjaGVzLFxuICBwcm9jZXNzR2VvanNvbixcbiAgcHJvY2Vzc0tlcGxlcmdsSlNPTixcbiAgcHJvY2Vzc1Jvd09iamVjdFxufSBmcm9tICcuL2RhdGEtcHJvY2Vzc29yJztcblxuaW1wb3J0IHtGaWxlQ2FjaGVJdGVtLCBWYWxpZEtlcGxlckdsTWFwfSBmcm9tICcuL3R5cGVzJztcblxuY29uc3QgQkFUQ0hfVFlQRSA9IHtcbiAgTUVUQURBVEE6ICdtZXRhZGF0YScsXG4gIFBBUlRJQUxfUkVTVUxUOiAncGFydGlhbC1yZXN1bHQnLFxuICBGSU5BTF9SRVNVTFQ6ICdmaW5hbC1yZXN1bHQnXG59O1xuXG5jb25zdCBDU1ZfTE9BREVSX09QVElPTlMgPSB7XG4gIHNoYXBlOiAnb2JqZWN0LXJvdy10YWJsZScsXG4gIGR5bmFtaWNUeXBpbmc6IGZhbHNlIC8vIG5vdCB3b3JraW5nIGZvciBub3dcbn07XG5cbmNvbnN0IEFSUk9XX0xPQURFUl9PUFRJT05TID0ge1xuICBzaGFwZTogJ2Fycm93LXRhYmxlJyxcbiAgYmF0Y2hEZWJvdW5jZU1zOiAxMCAvLyB0aW1lIHRvIGRlbGF5IGJldHdlZW4gYmF0Y2hlcywgZm9yIGluY3JlbWVudGFsIGxvYWRpbmdcbn07XG5cbmNvbnN0IFBBUlFVRVRfTE9BREVSX09QVElPTlMgPSB7XG4gIHNoYXBlOiAnYXJyb3ctdGFibGUnXG59O1xuXG5jb25zdCBKU09OX0xPQURFUl9PUFRJT05TID0ge1xuICBzaGFwZTogJ29iamVjdC1yb3ctdGFibGUnLFxuICAvLyBpbnN0cnVjdCBsb2FkZXJzLmdsIG9uIHdoYXQganNvbiBwYXRocyB0byBzdHJlYW1cbiAganNvbnBhdGhzOiBbXG4gICAgJyQnLCAvLyBKU09OIFJvdyBhcnJheVxuICAgICckLmZlYXR1cmVzJywgLy8gR2VvSlNPTlxuICAgICckLmRhdGFzZXRzJyAvLyBLZXBsZXJHTCBKU09OXG4gIF1cbn07XG5cbmV4cG9ydCB0eXBlIFByb2Nlc3NGaWxlRGF0YUNvbnRlbnQgPSB7XG4gIGRhdGE6IHVua25vd247XG4gIGZpbGVOYW1lOiBzdHJpbmc7XG4gIGxlbmd0aD86IG51bWJlcjtcbiAgcHJvZ3Jlc3M/OiB7cm93Q291bnQ/OiBudW1iZXI7IHJvd0NvdW50SW5CYXRjaD86IG51bWJlcjsgcGVyY2VudD86IG51bWJlcn07XG4gIC8qKiAgbWV0YWRhdGEgZS5nLiBmb3IgYXJyb3cgZGF0YSwgbWV0YWRhdGEgY291bGQgYmUgdGhlIHNjaGVtYS5maWVsZHMgKi9cbiAgbWV0YWRhdGE/OiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xufTtcblxuLyoqXG4gKiBjaGVjayBpZiB0YWJsZSBpcyBhbiBBcnJvd1RhYmxlIG9iamVjdFxuICogQHBhcmFtIHRhYmxlIC0gb2JqZWN0IHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0cnVlIGlmIHRhYmxlIGlzIGFuIEFycm93VGFibGUgb2JqZWN0IHR5cGUgZ3VhcmRlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNBcnJvd1RhYmxlKHRhYmxlOiBhbnkpOiB0YWJsZSBpcyBhcnJvdy5UYWJsZSB7XG4gIHJldHVybiBCb29sZWFuKHRhYmxlIGluc3RhbmNlb2YgYXJyb3cuVGFibGUpO1xufVxuXG4vKipcbiAqIGNoZWNrIGlmIGRhdGEgaXMgYW4gQXJyb3dEYXRhIG9iamVjdCwgd2hpY2ggaXMgYW4gYXJyYXkgb2YgUmVjb3JkQmF0Y2hcbiAqIEBwYXJhbSBkYXRhIC0gb2JqZWN0IHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0cnVlIGlmIGRhdGEgaXMgYW4gQXJyb3dEYXRhIG9iamVjdCB0eXBlIGd1YXJkZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQXJyb3dEYXRhKGRhdGE6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShkYXRhKSAmJiBCb29sZWFuKGRhdGEubGVuZ3RoICYmIGRhdGFbMF0uZGF0YSAmJiBkYXRhWzBdLnNjaGVtYSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0dlb0pzb24oanNvbjogdW5rbm93bik6IGpzb24gaXMgRmVhdHVyZSB8IEZlYXR1cmVDb2xsZWN0aW9uIHtcbiAgLy8ganNvbiBjYW4gYmUgZmVhdHVyZSBjb2xsZWN0aW9uXG4gIC8vIG9yIHNpbmdsZSBmZWF0dXJlXG4gIHJldHVybiBpc1BsYWluT2JqZWN0KGpzb24pICYmIChpc0ZlYXR1cmUoanNvbikgfHwgaXNGZWF0dXJlQ29sbGVjdGlvbihqc29uKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0ZlYXR1cmUoanNvbjogdW5rbm93bik6IGpzb24gaXMgRmVhdHVyZSB7XG4gIHJldHVybiBpc1BsYWluT2JqZWN0KGpzb24pICYmIGpzb24udHlwZSA9PT0gJ0ZlYXR1cmUnICYmIEJvb2xlYW4oanNvbi5nZW9tZXRyeSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0ZlYXR1cmVDb2xsZWN0aW9uKGpzb246IHVua25vd24pOiBqc29uIGlzIEZlYXR1cmVDb2xsZWN0aW9uIHtcbiAgcmV0dXJuIGlzUGxhaW5PYmplY3QoanNvbikgJiYganNvbi50eXBlID09PSAnRmVhdHVyZUNvbGxlY3Rpb24nICYmIEJvb2xlYW4oanNvbi5mZWF0dXJlcyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1Jvd09iamVjdChqc29uOiBhbnkpOiBib29sZWFuIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoanNvbikgJiYgaXNQbGFpbk9iamVjdChqc29uWzBdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzS2VwbGVyR2xNYXAoanNvbjogdW5rbm93bik6IGpzb24gaXMgVmFsaWRLZXBsZXJHbE1hcCB7XG4gIHJldHVybiBCb29sZWFuKFxuICAgIGlzUGxhaW5PYmplY3QoanNvbikgJiZcbiAgICAgIGpzb24uZGF0YXNldHMgJiZcbiAgICAgIGpzb24uY29uZmlnICYmXG4gICAgICBqc29uLmluZm8gJiZcbiAgICAgIGlzUGxhaW5PYmplY3QoanNvbi5pbmZvKSAmJlxuICAgICAganNvbi5pbmZvLmFwcCA9PT0gJ2tlcGxlci5nbCdcbiAgKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiBtYWtlUHJvZ3Jlc3NJdGVyYXRvcihcbiAgYXN5bmNJdGVyYXRvcjogQXN5bmNJdGVyYWJsZTxhbnk+LFxuICBpbmZvOiB7c2l6ZTogbnVtYmVyfVxuKTogQXN5bmNHZW5lcmF0b3Ige1xuICBsZXQgcm93Q291bnQgPSAwO1xuXG4gIGZvciBhd2FpdCAoY29uc3QgYmF0Y2ggb2YgYXN5bmNJdGVyYXRvcikge1xuICAgIC8vIHRoZSBsZW5ndGggY291bGQgYmUgc3RvcmVkIGluIGBiYXRjaC5sZW5ndGhgIGZvciBhcnJvdyBiYXRjaFxuICAgIGNvbnN0IHJvd0NvdW50SW5CYXRjaCA9IChiYXRjaC5kYXRhICYmIChiYXRjaC5kYXRhLmxlbmd0aCB8fCBiYXRjaC5sZW5ndGgpKSB8fCAwO1xuICAgIHJvd0NvdW50ICs9IHJvd0NvdW50SW5CYXRjaDtcbiAgICBjb25zdCBwZXJjZW50ID0gTnVtYmVyLmlzRmluaXRlKGJhdGNoLmJ5dGVzVXNlZCkgPyBiYXRjaC5ieXRlc1VzZWQgLyBpbmZvLnNpemUgOiBudWxsO1xuXG4gICAgLy8gVXBkYXRlIHByb2dyZXNzIG9iamVjdFxuICAgIGNvbnN0IHByb2dyZXNzID0ge1xuICAgICAgcm93Q291bnQsXG4gICAgICByb3dDb3VudEluQmF0Y2gsXG4gICAgICAuLi4oTnVtYmVyLmlzRmluaXRlKHBlcmNlbnQpID8ge3BlcmNlbnR9IDoge30pXG4gICAgfTtcblxuICAgIHlpZWxkIHsuLi5iYXRjaCwgcHJvZ3Jlc3N9O1xuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5leHBvcnQgYXN5bmMgZnVuY3Rpb24qIHJlYWRCYXRjaChcbiAgYXN5bmNJdGVyYXRvcjogQXN5bmNJdGVyYWJsZTxhbnk+LFxuICBmaWxlTmFtZTogc3RyaW5nXG4pOiBBc3luY0dlbmVyYXRvciB7XG4gIGxldCByZXN1bHQgPSBudWxsO1xuICBjb25zdCBiYXRjaGVzID0gPGFueT5bXTtcbiAgZm9yIGF3YWl0IChjb25zdCBiYXRjaCBvZiBhc3luY0l0ZXJhdG9yKSB7XG4gICAgLy8gTGFzdCBiYXRjaCB3aWxsIGhhdmUgdGhpcyBzcGVjaWFsIHR5cGUgYW5kIHdpbGwgcHJvdmlkZSBhbGwgdGhlIHJvb3RcbiAgICAvLyBwcm9wZXJ0aWVzIG9mIHRoZSBwYXJzZWQgZG9jdW1lbnQuXG4gICAgLy8gT25seSBqc29uIHBhcnNlIHdpbGwgaGF2ZSBgRklOQUxfUkVTVUxUYFxuICAgIGlmIChiYXRjaC5iYXRjaFR5cGUgPT09IEJBVENIX1RZUEUuRklOQUxfUkVTVUxUKSB7XG4gICAgICBpZiAoYmF0Y2guY29udGFpbmVyKSB7XG4gICAgICAgIHJlc3VsdCA9IHsuLi5iYXRjaC5jb250YWluZXJ9O1xuICAgICAgfVxuICAgICAgLy8gU2V0IHRoZSBzdHJlYW1lZCBkYXRhIGNvcnJlY3RseSBpcyBCYXRjaCBqc29uIHBhdGggaXMgc2V0XG4gICAgICAvLyBhbmQgdGhlIHBhdGggc3RyZWFtZWQgaXMgbm90IHRoZSB0b3AgbGV2ZWwgb2JqZWN0IChqc29ucGF0aCA9ICckJylcbiAgICAgIGlmIChiYXRjaC5qc29ucGF0aCAmJiBiYXRjaC5qc29ucGF0aC5sZW5ndGggPiAxKSB7XG4gICAgICAgIGNvbnN0IHN0cmVhbWluZ1BhdGggPSBuZXcgX0pTT05QYXRoKGJhdGNoLmpzb25wYXRoKTtcbiAgICAgICAgc3RyZWFtaW5nUGF0aC5zZXRGaWVsZEF0UGF0aChyZXN1bHQsIGJhdGNoZXMpO1xuICAgICAgfSBlbHNlIGlmIChiYXRjaC5qc29ucGF0aCAmJiBiYXRjaC5qc29ucGF0aC5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgLy8gVGhlIHN0cmVhbWVkIG9iamVjdCBpcyBhIFJPVyBKU09OLWJhdGNoIChqc29ucGF0aCA9ICckJylcbiAgICAgICAgLy8gcm93IG9iamVjdHNcbiAgICAgICAgcmVzdWx0ID0gYmF0Y2hlcztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgYmF0Y2hEYXRhID0gaXNBcnJvd1RhYmxlKGJhdGNoLmRhdGEpID8gYmF0Y2guZGF0YS5iYXRjaGVzIDogYmF0Y2guZGF0YTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYmF0Y2hEYXRhPy5sZW5ndGg7IGkrKykge1xuICAgICAgICBiYXRjaGVzLnB1c2goYmF0Y2hEYXRhW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB5aWVsZCB7XG4gICAgICAuLi5iYXRjaCxcbiAgICAgIC4uLihiYXRjaC5zY2hlbWEgPyB7aGVhZGVyczogT2JqZWN0LmtleXMoYmF0Y2guc2NoZW1hKX0gOiB7fSksXG4gICAgICBmaWxlTmFtZSxcbiAgICAgIC8vIGlmIGRhdGFzZXQgaXMgQ1NWLCBkYXRhIGlzIHNldCB0byB0aGUgcmF3IGJhdGNoZXNcbiAgICAgIGRhdGE6IHJlc3VsdCA/IHJlc3VsdCA6IGJhdGNoZXNcbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkRmlsZUluQmF0Y2hlcyh7XG4gIGZpbGUsXG4gIGxvYWRlcnMgPSBbXSxcbiAgbG9hZE9wdGlvbnMgPSB7fVxufToge1xuICBmaWxlOiBGaWxlO1xuICBmaWxlQ2FjaGU6IEZpbGVDYWNoZUl0ZW1bXTtcbiAgbG9hZGVyczogTG9hZGVyW107XG4gIGxvYWRPcHRpb25zOiBhbnk7XG59KTogUHJvbWlzZTxBc3luY0dlbmVyYXRvcj4ge1xuICBsb2FkZXJzID0gW0pTT05Mb2FkZXIsIENTVkxvYWRlciwgR2VvQXJyb3dMb2FkZXIsIFBhcnF1ZXRXYXNtTG9hZGVyLCAuLi5sb2FkZXJzXTtcbiAgbG9hZE9wdGlvbnMgPSB7XG4gICAgY3N2OiBDU1ZfTE9BREVSX09QVElPTlMsXG4gICAgYXJyb3c6IEFSUk9XX0xPQURFUl9PUFRJT05TLFxuICAgIGpzb246IEpTT05fTE9BREVSX09QVElPTlMsXG4gICAgcGFycXVldDogUEFSUVVFVF9MT0FERVJfT1BUSU9OUyxcbiAgICBtZXRhZGF0YTogdHJ1ZSxcbiAgICAuLi5sb2FkT3B0aW9uc1xuICB9O1xuXG4gIGNvbnN0IGJhdGNoSXRlcmF0b3IgPSBhd2FpdCBwYXJzZUluQmF0Y2hlcyhmaWxlLCBsb2FkZXJzLCBsb2FkT3B0aW9ucyk7XG4gIGNvbnN0IHByb2dyZXNzSXRlcmF0b3IgPSBtYWtlUHJvZ3Jlc3NJdGVyYXRvcihiYXRjaEl0ZXJhdG9yLCB7c2l6ZTogZmlsZS5zaXplfSk7XG5cbiAgcmV0dXJuIHJlYWRCYXRjaChwcm9ncmVzc0l0ZXJhdG9yLCBmaWxlLm5hbWUpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0ZpbGVEYXRhKHtcbiAgY29udGVudCxcbiAgZmlsZUNhY2hlXG59OiB7XG4gIGNvbnRlbnQ6IFByb2Nlc3NGaWxlRGF0YUNvbnRlbnQ7XG4gIGZpbGVDYWNoZTogRmlsZUNhY2hlSXRlbVtdO1xufSk6IFByb21pc2U8RmlsZUNhY2hlSXRlbVtdPiB7XG4gIGNvbnN0IHtmaWxlTmFtZSwgZGF0YX0gPSBjb250ZW50O1xuICBsZXQgZm9ybWF0OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGxldCBwcm9jZXNzb3I6ICgoZGF0YTogYW55KSA9PiBQcm9jZXNzb3JSZXN1bHQgfCBMb2FkZWRNYXAgfCBudWxsKSB8IHVuZGVmaW5lZDtcbiAgLy8gZ2VuZXJhdGUgdW5pcXVlIGlkIHdpdGggbGVuZ3RoIG9mIDQgdXNpbmcgZmlsZU5hbWUgc3RyaW5nXG4gIGNvbnN0IGlkID0gZ2VuZXJhdGVIYXNoSWRGcm9tU3RyaW5nKGZpbGVOYW1lKTtcbiAgLy8gZGVjaWRlIG9uIHdoaWNoIHRhYmxlIGNsYXNzIHRvIHVzZSBiYXNlZCBvbiBhcHBsaWNhdGlvbiBjb25maWdcbiAgY29uc3QgdGFibGUgPSBnZXRBcHBsaWNhdGlvbkNvbmZpZygpLnRhYmxlID8/IEtlcGxlclRhYmxlO1xuXG4gIGlmICh0eXBlb2YgdGFibGUuZ2V0RmlsZVByb2Nlc3NvciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIC8vIHVzZSBjdXN0b20gcHJvY2Vzc29ycyBmcm9tIHRhYmxlIGNsYXNzXG4gICAgY29uc3QgcHJvY2Vzc29yUmVzdWx0ID0gdGFibGUuZ2V0RmlsZVByb2Nlc3NvcihkYXRhKTtcbiAgICBmb3JtYXQgPSBwcm9jZXNzb3JSZXN1bHQuZm9ybWF0O1xuICAgIHByb2Nlc3NvciA9IHByb2Nlc3NvclJlc3VsdC5wcm9jZXNzb3I7XG4gIH0gZWxzZSB7XG4gICAgLy8gdXNlIGRlZmF1bHQgcHJvY2Vzc29yc1xuICAgIGlmIChpc0Fycm93RGF0YShkYXRhKSkge1xuICAgICAgZm9ybWF0ID0gREFUQVNFVF9GT1JNQVRTLmFycm93O1xuICAgICAgcHJvY2Vzc29yID0gcHJvY2Vzc0Fycm93QmF0Y2hlcztcbiAgICB9IGVsc2UgaWYgKGlzS2VwbGVyR2xNYXAoZGF0YSkpIHtcbiAgICAgIGZvcm1hdCA9IERBVEFTRVRfRk9STUFUUy5rZXBsZXJnbDtcbiAgICAgIHByb2Nlc3NvciA9IHByb2Nlc3NLZXBsZXJnbEpTT047XG4gICAgfSBlbHNlIGlmIChpc1Jvd09iamVjdChkYXRhKSkge1xuICAgICAgLy8gY3N2IGZpbGUgZ29lcyBoZXJlXG4gICAgICBmb3JtYXQgPSBEQVRBU0VUX0ZPUk1BVFMucm93O1xuICAgICAgcHJvY2Vzc29yID0gcHJvY2Vzc1Jvd09iamVjdDtcbiAgICB9IGVsc2UgaWYgKGlzR2VvSnNvbihkYXRhKSkge1xuICAgICAgZm9ybWF0ID0gREFUQVNFVF9GT1JNQVRTLmdlb2pzb247XG4gICAgICBwcm9jZXNzb3IgPSBwcm9jZXNzR2VvanNvbjtcbiAgICB9XG4gIH1cbiAgaWYgKGZvcm1hdCAmJiBwcm9jZXNzb3IpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1jYXRjaFxuICAgIGxldCByZXN1bHQ7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IHByb2Nlc3NvcihkYXRhKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4gbm90IHByb2Nlc3MgdXBsb2FkZWQgZmlsZSwgJHtnZXRFcnJvcihlcnJvciBhcyBFcnJvcil9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtcbiAgICAgIC4uLmZpbGVDYWNoZSxcbiAgICAgIHtcbiAgICAgICAgZGF0YTogcmVzdWx0LFxuICAgICAgICBpbmZvOiB7XG4gICAgICAgICAgaWQsXG4gICAgICAgICAgbGFiZWw6IGNvbnRlbnQuZmlsZU5hbWUsXG4gICAgICAgICAgZm9ybWF0XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICBdO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBwcm9jZXNzIHVwbG9hZGVkIGZpbGUsIHVua25vd24gZmlsZSBmb3JtYXQnKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZmlsZXNUb0RhdGFQYXlsb2FkKGZpbGVDYWNoZTogRmlsZUNhY2hlSXRlbVtdKTogQWRkRGF0YVRvTWFwUGF5bG9hZFtdIHtcbiAgLy8gc2VwZXJhdGUgb3V0IGZpbGVzIHdoaWNoIGNvdWxkIGJlIGEgc2luZ2xlIGRhdGFzZXRzLiBvciBhIGtlcGxlcmdsIG1hcCBqc29uXG4gIGNvbnN0IGNvbGxlY3Rpb24gPSBmaWxlQ2FjaGUucmVkdWNlPHtcbiAgICBkYXRhc2V0czogRmlsZUNhY2hlSXRlbVtdO1xuICAgIGtlcGxlck1hcHM6IEFkZERhdGFUb01hcFBheWxvYWRbXTtcbiAgfT4oXG4gICAgKGFjY3UsIGZpbGUpID0+IHtcbiAgICAgIGNvbnN0IHtkYXRhLCBpbmZvfSA9IGZpbGU7XG4gICAgICBpZiAoaW5mbz8uZm9ybWF0ID09PSBEQVRBU0VUX0ZPUk1BVFMua2VwbGVyZ2wpIHtcbiAgICAgICAgLy8gaWYgZmlsZSBjb250YWlucyBhIHNpbmdsZSBrZXBsZXIgbWFwIGRhdGFzZXQgJiBjb25maWdcbiAgICAgICAgYWNjdS5rZXBsZXJNYXBzLnB1c2goe1xuICAgICAgICAgIC4uLmRhdGEsXG4gICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgY2VudGVyTWFwOiAhKGRhdGEuY29uZmlnICYmIGRhdGEuY29uZmlnLm1hcFN0YXRlKVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKERBVEFTRVRfRk9STUFUU1tpbmZvPy5mb3JtYXRdKSB7XG4gICAgICAgIC8vIGlmIGZpbGUgY29udGFpbnMgb25seSBkYXRhXG4gICAgICAgIGNvbnN0IG5ld0RhdGFzZXQgPSB7XG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBpbmZvOiB7XG4gICAgICAgICAgICBpZDogaW5mbz8uaWQgfHwgZ2VuZXJhdGVIYXNoSWQoNCksXG4gICAgICAgICAgICAuLi4oaW5mbyB8fCB7fSlcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGFjY3UuZGF0YXNldHMucHVzaChuZXdEYXRhc2V0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2N1O1xuICAgIH0sXG4gICAge2RhdGFzZXRzOiBbXSwga2VwbGVyTWFwczogW119XG4gICk7XG5cbiAgLy8gYWRkIGtlcGxlciBtYXAgZmlyc3Qgd2l0aCBjb25maWdcbiAgLy8gYWRkIGRhdGFzZXRzIGxhdGVyIGluIG9uZSBhZGQgZGF0YSBjYWxsXG4gIHJldHVybiBjb2xsZWN0aW9uLmtlcGxlck1hcHMuY29uY2F0KHtkYXRhc2V0czogY29sbGVjdGlvbi5kYXRhc2V0c30pO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEsS0FBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsS0FBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsS0FBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsSUFBQSxHQUFBSCxPQUFBO0FBQ0Es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