kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
480 lines (475 loc) • 66 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof3 = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.KeplerGlDuckDbTable = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
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 _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var arrow = _interopRequireWildcard(require("apache-arrow"));
var _constants = require("@kepler.gl/constants");
var _processors = require("@kepler.gl/processors");
var _table = require("@kepler.gl/table");
var _init = require("../init");
var _dataProcessor = require("../processors/data-processor");
var _duckdbTableUtils = require("./duckdb-table-utils");
var _duckdbTableUtils2 = require("../table/duckdb-table-utils");
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" != _typeof3(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 _callSuper(t, o, e) { return o = (0, _getPrototypeOf2["default"])(o), (0, _possibleConstructorReturn2["default"])(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2["default"])(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function _superPropGet(t, e, r, o) { var p = (0, _get2["default"])((0, _getPrototypeOf2["default"])(1 & o ? t.prototype : t), e, r); return 2 & o ? function (t) { return p.apply(r, t); } : p; } // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
// TODO use files from disk or url directly, without parsing by loaders and then ingection into DeckDb
/**
* Default DuckDb geometry columns created by ST_READ
*/
var DUCKDB_GEOM_COLUMN = 'geom';
var DUCKDB_WKB_COLUMN = 'wkb_geometry';
/**
Default column name for processed geojson in Kepler.
Use this name to rename default 'geom' column from DuckDb
in order to support Kepler maps saved before introduction of DuckDb plugin.
*/
var KEPLER_GEOM_FROM_GEOJSON_COLUMN = '_geojson';
/**
* Names of columns that most likely contain binary wkb geometry
*/
var SUGGESTED_GEOM_COLUMNS = (0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])({}, KEPLER_GEOM_FROM_GEOJSON_COLUMN, _constants.GEOARROW_EXTENSIONS.WKB), DUCKDB_GEOM_COLUMN, _constants.GEOARROW_EXTENSIONS.WKB), "geometry", _constants.GEOARROW_EXTENSIONS.WKB);
var KeplerGlDuckDbTable = exports.KeplerGlDuckDbTable = /*#__PURE__*/function (_KeplerTable) {
function KeplerGlDuckDbTable(props) {
(0, _classCallCheck2["default"])(this, KeplerGlDuckDbTable);
return _callSuper(this, KeplerGlDuckDbTable, [props]);
}
(0, _inherits2["default"])(KeplerGlDuckDbTable, _KeplerTable);
return (0, _createClass2["default"])(KeplerGlDuckDbTable, [{
key: "importRowData",
value: function () {
var _importRowData = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(_ref) {
var data, db, c, fields, rows, rowsForDb, columns, createTableSql;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
data = _ref.data, db = _ref.db, c = _ref.c;
_context.prev = 1;
fields = data.fields, rows = data.rows; // DATASET_FORMATS.keplergl loads data as any[][] instead of [{}]
// TODO potential memory usage explosion: original data, new object and then DuckDb table
rowsForDb = Array.isArray(rows[0]) ? rows.map(function (row) {
var newRow = {};
row.forEach(function (value, index) {
newRow[fields[index].name] = value;
});
return newRow;
}) : rows;
_context.next = 6;
return db.registerFileText(this.id, JSON.stringify(rowsForDb));
case 6:
columns = fields.reduce(function (acc, field, index) {
// @ts-expect-error TODO extend fields to contain duckDBColumnType
return "".concat(acc).concat(index > 0 ? ',' : '', " '").concat(field.name, "': '").concat(field.duckDBColumnType, "'");
}, '');
createTableSql = "\n CREATE TABLE '".concat(this.label, "' AS\n SELECT *\n FROM read_json('").concat(this.id, "',\n columns = {").concat(columns, "});\n ");
_context.next = 10;
return c.query(createTableSql);
case 10:
_context.next = 15;
break;
case 12:
_context.prev = 12;
_context.t0 = _context["catch"](1);
console.log('importRowData', _context.t0);
case 15:
case "end":
return _context.stop();
}
}, _callee, this, [[1, 12]]);
}));
function importRowData(_x) {
return _importRowData.apply(this, arguments);
}
return importRowData;
}()
}, {
key: "importGeoJsonData",
value: function () {
var _importGeoJsonData = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(_ref2) {
var data, db, c, rows, createTableSql;
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
data = _ref2.data, db = _ref2.db, c = _ref2.c;
_context2.prev = 1;
rows = data.rows;
_context2.next = 5;
return db.registerFileText(this.id, JSON.stringify(rows));
case 5:
createTableSql = "\n install spatial;\n load spatial;\n CREATE TABLE '".concat(this.label, "' AS \n SELECT *\n FROM ST_READ('").concat(this.id, "', keep_wkb = TRUE);\n ALTER TABLE '").concat(this.label, "' RENAME '").concat(DUCKDB_WKB_COLUMN, "' TO '").concat(KEPLER_GEOM_FROM_GEOJSON_COLUMN, "';\n ");
_context2.next = 8;
return c.query(createTableSql);
case 8:
_context2.next = 13;
break;
case 10:
_context2.prev = 10;
_context2.t0 = _context2["catch"](1);
console.error('importGeoJsonData', _context2.t0);
case 13:
return _context2.abrupt("return", {
// _geojson column is created from geometry with keep_wkb flag and contains valid WKB data.
geoarrowMetadata: (0, _defineProperty2["default"])({}, KEPLER_GEOM_FROM_GEOJSON_COLUMN, _constants.GEOARROW_EXTENSIONS.WKB)
});
case 14:
case "end":
return _context2.stop();
}
}, _callee2, this, [[1, 10]]);
}));
function importGeoJsonData(_x2) {
return _importGeoJsonData.apply(this, arguments);
}
return importGeoJsonData;
}()
}, {
key: "importArrowData",
value: function () {
var _importArrowData = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(_ref3) {
var data, c, adjustedMetadata, arrowTable, setupSql;
return _regenerator["default"].wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
data = _ref3.data, c = _ref3.c;
adjustedMetadata = {};
_context3.prev = 2;
// 1) data.rows contains an arrow table created by Add to Map data from DuckDb query.
// 2) arrow table is in cols & fields when a file is dragged & dropped into Add Data To Map dialog.
arrowTable = data.rows instanceof arrow.Table ? data.rows : (0, _duckdbTableUtils2.restoreArrowTable)(data.cols || [], data.fields, data.arrowSchema); // remove unsupported extensions from an arrow table that throw exceptions in DuckDB.
adjustedMetadata = (0, _duckdbTableUtils2.removeUnsupportedExtensions)(arrowTable);
setupSql = "\n install spatial;\n load spatial;\n ";
_context3.next = 8;
return c.query(setupSql);
case 8:
_context3.next = 10;
return c.insertArrowTable(arrowTable, {
name: this.label
});
case 10:
// restore unsupported extensions that throw exceptions in DuckDb
(0, _duckdbTableUtils2.restoreUnsupportedExtensions)(arrowTable, adjustedMetadata);
_context3.next = 16;
break;
case 13:
_context3.prev = 13;
_context3.t0 = _context3["catch"](2);
// Known issues:
// 1) Arrow Type with extension name: geoarrow.point and format: +w:2 is not currently supported in DuckDB.
console.error('importArrowData', _context3.t0);
case 16:
return _context3.abrupt("return", {
geoarrowMetadata: _objectSpread(_objectSpread({}, SUGGESTED_GEOM_COLUMNS), adjustedMetadata),
// use fields generated from the created arrow table
useNewFields: true
});
case 17:
case "end":
return _context3.stop();
}
}, _callee3, this, [[2, 13]]);
}));
function importArrowData(_x3) {
return _importArrowData.apply(this, arguments);
}
return importArrowData;
}()
/**
* Creates a table from data, returns an arrow table with the data
* @param data
* @returns {Promise<{fields: Field[], cols: any[]}>}
*/
}, {
key: "createTableAndGetArrow",
value: (function () {
var _createTableAndGetArrow = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(data) {
var db, c, tableName, format, _data$rows, _data$rows2, _data$rows3, _data$cols, importDetails, fields, cols, _data$fields, _ref4, _ref4$geoarrowMetadat, geoarrowMetadata, _ref4$useNewFields, useNewFields, duckDbColumns, tableDuckDBTypes, columnsToConvertToWKB, adjustedQuery, arrowResult;
return _regenerator["default"].wrap(function _callee4$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
_context4.next = 2;
return (0, _init.getDuckDB)();
case 2:
db = _context4.sent;
_context4.next = 5;
return db.connect();
case 5:
c = _context4.sent;
tableName = this.label;
_context4.next = 9;
return (0, _duckdbTableUtils2.dropTableIfExists)(c, tableName);
case 9:
format = this.metadata.format;
if (!format) {
// format is missing when we load Kepler.gl examples
if (Array.isArray((_data$rows = data.rows) === null || _data$rows === void 0 ? void 0 : _data$rows[0]) || (0, _typeof2["default"])((_data$rows2 = data.rows) === null || _data$rows2 === void 0 ? void 0 : _data$rows2[0]) === 'object') {
format = _constants.DATASET_FORMATS.row;
} else if (((_data$rows3 = data.rows) === null || _data$rows3 === void 0 ? void 0 : _data$rows3.type) === 'FeatureCollection') {
format = _constants.DATASET_FORMATS.geojson;
} else if (((_data$cols = data.cols) === null || _data$cols === void 0 ? void 0 : _data$cols[0]) instanceof arrow.Vector) {
format = _constants.DATASET_FORMATS.arrow;
}
}
if (!(format === _constants.DATASET_FORMATS.row)) {
_context4.next = 16;
break;
}
_context4.next = 14;
return this.importRowData({
data: data,
db: db,
c: c
});
case 14:
_context4.next = 29;
break;
case 16:
if (!(format === _constants.DATASET_FORMATS.geojson)) {
_context4.next = 22;
break;
}
_context4.next = 19;
return this.importGeoJsonData({
data: data,
db: db,
c: c
});
case 19:
importDetails = _context4.sent;
_context4.next = 29;
break;
case 22:
if (!(format === _constants.DATASET_FORMATS.arrow)) {
_context4.next = 28;
break;
}
_context4.next = 25;
return this.importArrowData({
data: data,
db: db,
c: c
});
case 25:
importDetails = _context4.sent;
_context4.next = 29;
break;
case 28:
console.error('Unrecognized format', format);
case 29:
fields = [];
cols = [];
_context4.prev = 31;
_ref4 = importDetails || {}, _ref4$geoarrowMetadat = _ref4.geoarrowMetadata, geoarrowMetadata = _ref4$geoarrowMetadat === void 0 ? {} : _ref4$geoarrowMetadat, _ref4$useNewFields = _ref4.useNewFields, useNewFields = _ref4$useNewFields === void 0 ? false : _ref4$useNewFields;
_context4.next = 35;
return (0, _duckdbTableUtils2.getDuckDBColumnTypes)(c, tableName);
case 35:
duckDbColumns = _context4.sent;
tableDuckDBTypes = (0, _duckdbTableUtils2.getDuckDBColumnTypesMap)(duckDbColumns);
columnsToConvertToWKB = (0, _duckdbTableUtils2.getGeometryColumns)(duckDbColumns);
adjustedQuery = (0, _duckdbTableUtils2.constructST_asWKBQuery)(tableName, columnsToConvertToWKB);
_context4.next = 41;
return c.query(adjustedQuery);
case 41:
arrowResult = _context4.sent;
// TODO if format is an arrow table then just use the original one, instead of the new table from the query?
restoreGeoarrowMetadata(arrowResult, geoarrowMetadata);
fields = useNewFields ? (0, _processors.arrowSchemaToFields)(arrowResult, tableDuckDBTypes) : (_data$fields = data.fields) !== null && _data$fields !== void 0 ? _data$fields : (0, _processors.arrowSchemaToFields)(arrowResult, tableDuckDBTypes);
cols = (0, _toConsumableArray2["default"])(Array(arrowResult.numCols).keys()).map(function (i) {
return arrowResult.getChildAt(i);
}).filter(function (col) {
return col;
});
_context4.next = 50;
break;
case 47:
_context4.prev = 47;
_context4.t0 = _context4["catch"](31);
console.error('DuckDB table: createTableAndGetArrow', _context4.t0);
case 50:
_context4.next = 52;
return c.close();
case 52:
return _context4.abrupt("return", {
fields: fields,
cols: cols
});
case 53:
case "end":
return _context4.stop();
}
}, _callee4, this, [[31, 47]]);
}));
function createTableAndGetArrow(_x4) {
return _createTableAndGetArrow.apply(this, arguments);
}
return createTableAndGetArrow;
}())
}, {
key: "importData",
value: function () {
var _importData = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(_ref5) {
var data, _yield$this$createTab, fields, cols;
return _regenerator["default"].wrap(function _callee5$(_context5) {
while (1) switch (_context5.prev = _context5.next) {
case 0:
data = _ref5.data;
if (!(this.type === _constants.DatasetType.VECTOR_TILE)) {
_context5.next = 4;
break;
}
_superPropGet(KeplerGlDuckDbTable, "importData", this, 3)([{
data: _objectSpread(_objectSpread({}, data), {}, {
rows: []
})
}]);
return _context5.abrupt("return");
case 4:
_context5.next = 6;
return this.createTableAndGetArrow(data);
case 6:
_yield$this$createTab = _context5.sent;
fields = _yield$this$createTab.fields;
cols = _yield$this$createTab.cols;
_superPropGet(KeplerGlDuckDbTable, "importData", this, 3)([{
data: {
fields: fields,
cols: cols,
rows: []
}
}]);
case 10:
case "end":
return _context5.stop();
}
}, _callee5, this);
}));
function importData(_x5) {
return _importData.apply(this, arguments);
}
return importData;
}()
}, {
key: "update",
value: function () {
var _update = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(data) {
var _yield$this$createTab2, cols;
return _regenerator["default"].wrap(function _callee6$(_context6) {
while (1) switch (_context6.prev = _context6.next) {
case 0:
if (!(this.type === _constants.DatasetType.VECTOR_TILE)) {
_context6.next = 3;
break;
}
_superPropGet(KeplerGlDuckDbTable, "importData", this, 3)([{
data: data
}]);
return _context6.abrupt("return", this);
case 3:
_context6.next = 5;
return this.createTableAndGetArrow(data);
case 5:
_yield$this$createTab2 = _context6.sent;
cols = _yield$this$createTab2.cols;
return _context6.abrupt("return", _superPropGet(KeplerGlDuckDbTable, "update", this, 3)([{
cols: cols,
rows: [],
fields: []
}]));
case 8:
case "end":
return _context6.stop();
}
}, _callee6, this);
}));
function update(_x6) {
return _update.apply(this, arguments);
}
return update;
}()
}]);
}(_table.KeplerTable);
/**
* Try to restore geoarrow metadata lost during DuckDb ingestion.
* Note that this function can generate wrong geometry types.
* @param arrowTable Arrow table to update.
* @param geoarrowMetadata A map with field names that usually used to store geoarrow geometry.
*/
(0, _defineProperty2["default"])(KeplerGlDuckDbTable, "getFileProcessor", function (data, inputFormat) {
var processor;
var format;
if (inputFormat === _constants.DATASET_FORMATS.arrow || (0, _processors.isArrowData)(data)) {
format = _constants.DATASET_FORMATS.arrow;
processor = _processors.processArrowBatches;
} else if (inputFormat === _constants.DATASET_FORMATS.keplergl || (0, _processors.isKeplerGlMap)(data)) {
format = _constants.DATASET_FORMATS.keplergl;
processor = _dataProcessor.processKeplerglJSONforDuckDb;
} else if (inputFormat === _constants.DATASET_FORMATS.row || (0, _processors.isRowObject)(data)) {
// csv file goes here
format = _constants.DATASET_FORMATS.row;
processor = _dataProcessor.processCsvRowObject; // directly import json object into duckdb-wasm
} else if (inputFormat === _constants.DATASET_FORMATS.geojson || (0, _processors.isGeoJson)(data)) {
format = _constants.DATASET_FORMATS.geojson;
processor = _dataProcessor.processGeojson;
}
return {
processor: processor,
format: format
};
});
(0, _defineProperty2["default"])(KeplerGlDuckDbTable, "getInputDataValidator", function () {
// In DuckDB mode data is validated later during import.
return function (d) {
return d;
};
});
var restoreGeoarrowMetadata = /*#__PURE__*/function () {
var _ref6 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee7(arrowTable, geoarrowMetadata) {
return _regenerator["default"].wrap(function _callee7$(_context7) {
while (1) switch (_context7.prev = _context7.next) {
case 0:
arrowTable.schema.fields.forEach(function (f) {
if (arrow.DataType.isBinary(f.type) && geoarrowMetadata[f.name]) {
f.metadata.set(_constants.GEOARROW_METADATA_KEY, geoarrowMetadata[f.name]);
} else if ((0, _duckdbTableUtils.isGeoArrowPoint)(f.type)) {
f.metadata.set(_constants.GEOARROW_METADATA_KEY, _constants.GEOARROW_EXTENSIONS.POINT);
} else if ((0, _duckdbTableUtils.isGeoArrowLineString)(f.type)) {
f.metadata.set(_constants.GEOARROW_METADATA_KEY, _constants.GEOARROW_EXTENSIONS.LINESTRING);
} else if ((0, _duckdbTableUtils.isGeoArrowPolygon)(f.type)) {
f.metadata.set(_constants.GEOARROW_METADATA_KEY, _constants.GEOARROW_EXTENSIONS.POLYGON);
} else if ((0, _duckdbTableUtils.isGeoArrowMultiPoint)(f.type)) {
f.metadata.set(_constants.GEOARROW_METADATA_KEY, _constants.GEOARROW_EXTENSIONS.MULTIPOINT);
} else if ((0, _duckdbTableUtils.isGeoArrowMultiLineString)(f.type)) {
f.metadata.set(_constants.GEOARROW_METADATA_KEY, _constants.GEOARROW_EXTENSIONS.MULTILINESTRING);
} else if ((0, _duckdbTableUtils.isGeoArrowMultiPolygon)(f.type)) {
f.metadata.set(_constants.GEOARROW_METADATA_KEY, _constants.GEOARROW_EXTENSIONS.MULTIPOLYGON);
}
});
case 1:
case "end":
return _context7.stop();
}
}, _callee7);
}));
return function restoreGeoarrowMetadata(_x7, _x8) {
return _ref6.apply(this, arguments);
};
}();
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJhcnJvdyIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwicmVxdWlyZSIsIl9jb25zdGFudHMiLCJfcHJvY2Vzc29ycyIsIl90YWJsZSIsIl9pbml0IiwiX2RhdGFQcm9jZXNzb3IiLCJfZHVja2RiVGFibGVVdGlscyIsIl9kdWNrZGJUYWJsZVV0aWxzMiIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiX3R5cGVvZjMiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJvd25LZXlzIiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJfY2FsbFN1cGVyIiwiX2dldFByb3RvdHlwZU9mMiIsIl9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuMiIsIl9pc05hdGl2ZVJlZmxlY3RDb25zdHJ1Y3QiLCJSZWZsZWN0IiwiY29uc3RydWN0IiwiY29uc3RydWN0b3IiLCJCb29sZWFuIiwicHJvdG90eXBlIiwidmFsdWVPZiIsIl9zdXBlclByb3BHZXQiLCJwIiwiX2dldDIiLCJEVUNLREJfR0VPTV9DT0xVTU4iLCJEVUNLREJfV0tCX0NPTFVNTiIsIktFUExFUl9HRU9NX0ZST01fR0VPSlNPTl9DT0xVTU4iLCJTVUdHRVNURURfR0VPTV9DT0xVTU5TIiwiR0VPQVJST1dfRVhURU5TSU9OUyIsIldLQiIsIktlcGxlckdsRHVja0RiVGFibGUiLCJleHBvcnRzIiwiX0tlcGxlclRhYmxlIiwicHJvcHMiLCJfY2xhc3NDYWxsQ2hlY2syIiwiX2luaGVyaXRzMiIsIl9jcmVhdGVDbGFzczIiLCJrZXkiLCJ2YWx1ZSIsIl9pbXBvcnRSb3dEYXRhIiwiX2FzeW5jVG9HZW5lcmF0b3IyIiwiX3JlZ2VuZXJhdG9yIiwibWFyayIsIl9jYWxsZWUiLCJfcmVmIiwiZGF0YSIsImRiIiwiYyIsImZpZWxkcyIsInJvd3MiLCJyb3dzRm9yRGIiLCJjb2x1bW5zIiwiY3JlYXRlVGFibGVTcWwiLCJ3cmFwIiwiX2NhbGxlZSQiLCJfY29udGV4dCIsInByZXYiLCJuZXh0IiwiQXJyYXkiLCJpc0FycmF5IiwibWFwIiwicm93IiwibmV3Um93IiwiaW5kZXgiLCJuYW1lIiwicmVnaXN0ZXJGaWxlVGV4dCIsImlkIiwiSlNPTiIsInN0cmluZ2lmeSIsInJlZHVjZSIsImFjYyIsImZpZWxkIiwiY29uY2F0IiwiZHVja0RCQ29sdW1uVHlwZSIsImxhYmVsIiwicXVlcnkiLCJ0MCIsImNvbnNvbGUiLCJsb2ciLCJzdG9wIiwiaW1wb3J0Um93RGF0YSIsIl94IiwiX2ltcG9ydEdlb0pzb25EYXRhIiwiX2NhbGxlZTIiLCJfcmVmMiIsIl9jYWxsZWUyJCIsIl9jb250ZXh0MiIsImVycm9yIiwiYWJydXB0IiwiZ2VvYXJyb3dNZXRhZGF0YSIsImltcG9ydEdlb0pzb25EYXRhIiwiX3gyIiwiX2ltcG9ydEFycm93RGF0YSIsIl9jYWxsZWUzIiwiX3JlZjMiLCJhZGp1c3RlZE1ldGFkYXRhIiwiYXJyb3dUYWJsZSIsInNldHVwU3FsIiwiX2NhbGxlZTMkIiwiX2NvbnRleHQzIiwiVGFibGUiLCJyZXN0b3JlQXJyb3dUYWJsZSIsImNvbHMiLCJhcnJvd1NjaGVtYSIsInJlbW92ZVVuc3VwcG9ydGVkRXh0ZW5zaW9ucyIsImluc2VydEFycm93VGFibGUiLCJyZXN0b3JlVW5zdXBwb3J0ZWRFeHRlbnNpb25zIiwidXNlTmV3RmllbGRzIiwiaW1wb3J0QXJyb3dEYXRhIiwiX3gzIiwiX2NyZWF0ZVRhYmxlQW5kR2V0QXJyb3ciLCJfY2FsbGVlNCIsInRhYmxlTmFtZSIsImZvcm1hdCIsIl9kYXRhJHJvd3MiLCJfZGF0YSRyb3dzMiIsIl9kYXRhJHJvd3MzIiwiX2RhdGEkY29scyIsImltcG9ydERldGFpbHMiLCJfZGF0YSRmaWVsZHMiLCJfcmVmNCIsIl9yZWY0JGdlb2Fycm93TWV0YWRhdCIsIl9yZWY0JHVzZU5ld0ZpZWxkcyIsImR1Y2tEYkNvbHVtbnMiLCJ0YWJsZUR1Y2tEQlR5cGVzIiwiY29sdW1uc1RvQ29udmVydFRvV0tCIiwiYWRqdXN0ZWRRdWVyeSIsImFycm93UmVzdWx0IiwiX2NhbGxlZTQkIiwiX2NvbnRleHQ0IiwiZ2V0RHVja0RCIiwic2VudCIsImNvbm5lY3QiLCJkcm9wVGFibGVJZkV4aXN0cyIsIm1ldGFkYXRhIiwiX3R5cGVvZjIiLCJEQVRBU0VUX0ZPUk1BVFMiLCJ0eXBlIiwiZ2VvanNvbiIsIlZlY3RvciIsImdldER1Y2tEQkNvbHVtblR5cGVzIiwiZ2V0RHVja0RCQ29sdW1uVHlwZXNNYXAiLCJnZXRHZW9tZXRyeUNvbHVtbnMiLCJjb25zdHJ1Y3RTVF9hc1dLQlF1ZXJ5IiwicmVzdG9yZUdlb2Fycm93TWV0YWRhdGEiLCJhcnJvd1NjaGVtYVRvRmllbGRzIiwiX3RvQ29uc3VtYWJsZUFycmF5MiIsIm51bUNvbHMiLCJnZXRDaGlsZEF0IiwiY29sIiwiY2xvc2UiLCJjcmVhdGVUYWJsZUFuZEdldEFycm93IiwiX3g0IiwiX2ltcG9ydERhdGEiLCJfY2FsbGVlNSIsIl9yZWY1IiwiX3lpZWxkJHRoaXMkY3JlYXRlVGFiIiwiX2NhbGxlZTUkIiwiX2NvbnRleHQ1IiwiRGF0YXNldFR5cGUiLCJWRUNUT1JfVElMRSIsImltcG9ydERhdGEiLCJfeDUiLCJfdXBkYXRlIiwiX2NhbGxlZTYiLCJfeWllbGQkdGhpcyRjcmVhdGVUYWIyIiwiX2NhbGxlZTYkIiwiX2NvbnRleHQ2IiwidXBkYXRlIiwiX3g2IiwiS2VwbGVyVGFibGUiLCJpbnB1dEZvcm1hdCIsInByb2Nlc3NvciIsImlzQXJyb3dEYXRhIiwicHJvY2Vzc0Fycm93QmF0Y2hlcyIsImtlcGxlcmdsIiwiaXNLZXBsZXJHbE1hcCIsInByb2Nlc3NLZXBsZXJnbEpTT05mb3JEdWNrRGIiLCJpc1Jvd09iamVjdCIsInByb2Nlc3NDc3ZSb3dPYmplY3QiLCJpc0dlb0pzb24iLCJwcm9jZXNzR2VvanNvbiIsImQiLCJfcmVmNiIsIl9jYWxsZWU3IiwiX2NhbGxlZTckIiwiX2NvbnRleHQ3Iiwic2NoZW1hIiwiZiIsIkRhdGFUeXBlIiwiaXNCaW5hcnkiLCJHRU9BUlJPV19NRVRBREFUQV9LRVkiLCJpc0dlb0Fycm93UG9pbnQiLCJQT0lOVCIsImlzR2VvQXJyb3dMaW5lU3RyaW5nIiwiTElORVNUUklORyIsImlzR2VvQXJyb3dQb2x5Z29uIiwiUE9MWUdPTiIsImlzR2VvQXJyb3dNdWx0aVBvaW50IiwiTVVMVElQT0lOVCIsImlzR2VvQXJyb3dNdWx0aUxpbmVTdHJpbmciLCJNVUxUSUxJTkVTVFJJTkciLCJpc0dlb0Fycm93TXVsdGlQb2x5Z29uIiwiTVVMVElQT0xZR09OIiwiX3g3IiwiX3g4Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RhYmxlL2R1Y2tkYi10YWJsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQgKiBhcyBhcnJvdyBmcm9tICdhcGFjaGUtYXJyb3cnO1xuaW1wb3J0IHtBc3luY0R1Y2tEQiwgQXN5bmNEdWNrREJDb25uZWN0aW9ufSBmcm9tICdAZHVja2RiL2R1Y2tkYi13YXNtJztcblxuaW1wb3J0IHtcbiAgRGF0YXNldFR5cGUsXG4gIERBVEFTRVRfRk9STUFUUyxcbiAgR0VPQVJST1dfRVhURU5TSU9OUyxcbiAgR0VPQVJST1dfTUVUQURBVEFfS0VZXG59IGZyb20gJ0BrZXBsZXIuZ2wvY29uc3RhbnRzJztcbmltcG9ydCB7XG4gIGFycm93U2NoZW1hVG9GaWVsZHMsXG4gIGlzQXJyb3dEYXRhLFxuICBpc0dlb0pzb24sXG4gIGlzS2VwbGVyR2xNYXAsXG4gIGlzUm93T2JqZWN0LFxuICBwcm9jZXNzQXJyb3dCYXRjaGVzXG59IGZyb20gJ0BrZXBsZXIuZ2wvcHJvY2Vzc29ycyc7XG5pbXBvcnQge0tlcGxlclRhYmxlfSBmcm9tICdAa2VwbGVyLmdsL3RhYmxlJztcbmltcG9ydCB7RmllbGR9IGZyb20gJ0BrZXBsZXIuZ2wvdHlwZXMnO1xuXG5pbXBvcnQge2dldER1Y2tEQn0gZnJvbSAnLi4vaW5pdCc7XG5pbXBvcnQge1xuICBwcm9jZXNzQ3N2Um93T2JqZWN0LFxuICBwcm9jZXNzR2VvanNvbixcbiAgcHJvY2Vzc0tlcGxlcmdsSlNPTmZvckR1Y2tEYixcbiAgUHJvY2Vzc29yUmVzdWx0XG59IGZyb20gJy4uL3Byb2Nlc3NvcnMvZGF0YS1wcm9jZXNzb3InO1xuXG5pbXBvcnQge1xuICBpc0dlb0Fycm93UG9pbnQsXG4gIGlzR2VvQXJyb3dMaW5lU3RyaW5nLFxuICBpc0dlb0Fycm93UG9seWdvbixcbiAgaXNHZW9BcnJvd011bHRpUG9pbnQsXG4gIGlzR2VvQXJyb3dNdWx0aUxpbmVTdHJpbmcsXG4gIGlzR2VvQXJyb3dNdWx0aVBvbHlnb25cbn0gZnJvbSAnLi9kdWNrZGItdGFibGUtdXRpbHMnO1xuXG5pbXBvcnQge1xuICBjb25zdHJ1Y3RTVF9hc1dLQlF1ZXJ5LFxuICBkcm9wVGFibGVJZkV4aXN0cyxcbiAgZ2V0RHVja0RCQ29sdW1uVHlwZXMsXG4gIGdldER1Y2tEQkNvbHVtblR5cGVzTWFwLFxuICBnZXRHZW9tZXRyeUNvbHVtbnMsXG4gIHJlbW92ZVVuc3VwcG9ydGVkRXh0ZW5zaW9ucyxcbiAgcmVzdG9yZUFycm93VGFibGUsXG4gIHJlc3RvcmVVbnN1cHBvcnRlZEV4dGVuc2lvbnNcbn0gZnJvbSAnLi4vdGFibGUvZHVja2RiLXRhYmxlLXV0aWxzJztcblxuLy8gVE9ETyB1c2UgZmlsZXMgZnJvbSBkaXNrIG9yIHVybCBkaXJlY3RseSwgd2l0aG91dCBwYXJzaW5nIGJ5IGxvYWRlcnMgYW5kIHRoZW4gaW5nZWN0aW9uIGludG8gRGVja0RiXG5cbi8qKlxuICogRGVmYXVsdCBEdWNrRGIgZ2VvbWV0cnkgY29sdW1ucyBjcmVhdGVkIGJ5IFNUX1JFQURcbiAqL1xuY29uc3QgRFVDS0RCX0dFT01fQ09MVU1OID0gJ2dlb20nO1xuY29uc3QgRFVDS0RCX1dLQl9DT0xVTU4gPSAnd2tiX2dlb21ldHJ5JztcblxuLyoqXG4gRGVmYXVsdCBjb2x1bW4gbmFtZSBmb3IgcHJvY2Vzc2VkIGdlb2pzb24gaW4gS2VwbGVyLlxuIFVzZSB0aGlzIG5hbWUgdG8gcmVuYW1lIGRlZmF1bHQgJ2dlb20nIGNvbHVtbiBmcm9tIER1Y2tEYlxuIGluIG9yZGVyIHRvIHN1cHBvcnQgS2VwbGVyIG1hcHMgc2F2ZWQgYmVmb3JlIGludHJvZHVjdGlvbiBvZiBEdWNrRGIgcGx1Z2luLlxuICovXG5jb25zdCBLRVBMRVJfR0VPTV9GUk9NX0dFT0pTT05fQ09MVU1OID0gJ19nZW9qc29uJztcblxuLyoqXG4gKiBOYW1lcyBvZiBjb2x1bW5zIHRoYXQgbW9zdCBsaWtlbHkgY29udGFpbiBiaW5hcnkgd2tiIGdlb21ldHJ5XG4gKi9cbmNvbnN0IFNVR0dFU1RFRF9HRU9NX0NPTFVNTlMgPSB7XG4gIFtLRVBMRVJfR0VPTV9GUk9NX0dFT0pTT05fQ09MVU1OXTogR0VPQVJST1dfRVhURU5TSU9OUy5XS0IsXG4gIFtEVUNLREJfR0VPTV9DT0xVTU5dOiBHRU9BUlJPV19FWFRFTlNJT05TLldLQixcbiAgZ2VvbWV0cnk6IEdFT0FSUk9XX0VYVEVOU0lPTlMuV0tCXG59O1xuXG50eXBlIEltcG9ydERhdGFUb0R1Y2tQcm9wcyA9IHtcbiAgZGF0YTogUHJvY2Vzc29yUmVzdWx0ICYge2Fycm93U2NoZW1hOiBhcnJvdy5TY2hlbWF9O1xuICBkYjogQXN5bmNEdWNrREI7XG4gIGM6IEFzeW5jRHVja0RCQ29ubmVjdGlvbjtcbn07XG5cbnR5cGUgSW1wb3J0RGF0YVRvRHVja1Jlc3VsdCA9IHtcbiAgLy8gRHVja0RiIGRyb3BzIGdlb2Fycm93IG1ldGFkYXRhLCBzbyB0cnkgdG8gcHJlc2VydmUgYW5kIHRoZW4gcmVzdG9yZSB0aGUgZXh0ZW5zaW9uIG5hbWVcbiAgZ2VvYXJyb3dNZXRhZGF0YT86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIC8vIFVzZSBmaWVsZHMgZnJvbSBhcnJvdyB0YWJsZSBldmVuIGlmIGZpZWxkcyBhcmUgcHJvdmlkZWRcbiAgdXNlTmV3RmllbGRzPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCBjbGFzcyBLZXBsZXJHbER1Y2tEYlRhYmxlIGV4dGVuZHMgS2VwbGVyVGFibGUge1xuICBkZWNsYXJlIHJlYWRvbmx5IGlkOiBzdHJpbmc7XG4gIGRlY2xhcmUgbGFiZWw6IHN0cmluZztcbiAgZGVjbGFyZSB0eXBlOiBzdHJpbmc7XG4gIGRlY2xhcmUgbWV0YWRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT47XG5cbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcyk7XG4gIH1cblxuICBhc3luYyBpbXBvcnRSb3dEYXRhKHtkYXRhLCBkYiwgY306IEltcG9ydERhdGFUb0R1Y2tQcm9wcyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7ZmllbGRzLCByb3dzfSA9IGRhdGE7XG5cbiAgICAgIC8vIERBVEFTRVRfRk9STUFUUy5rZXBsZXJnbCBsb2FkcyBkYXRhIGFzIGFueVtdW10gaW5zdGVhZCBvZiBbe31dXG4gICAgICAvLyBUT0RPIHBvdGVudGlhbCBtZW1vcnkgdXNhZ2UgZXhwbG9zaW9uOiBvcmlnaW5hbCBkYXRhLCBuZXcgb2JqZWN0IGFuZCB0aGVuIER1Y2tEYiB0YWJsZVxuICAgICAgY29uc3Qgcm93c0ZvckRiID0gQXJyYXkuaXNBcnJheShyb3dzWzBdKVxuICAgICAgICA/IHJvd3MubWFwKHJvdyA9PiB7XG4gICAgICAgICAgICBjb25zdCBuZXdSb3cgPSB7fTtcbiAgICAgICAgICAgIHJvdy5mb3JFYWNoKCh2YWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgbmV3Um93W2ZpZWxkc1tpbmRleF0ubmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIG5ld1JvdztcbiAgICAgICAgICB9KVxuICAgICAgICA6IHJvd3M7XG5cbiAgICAgIGF3YWl0IGRiLnJlZ2lzdGVyRmlsZVRleHQodGhpcy5pZCwgSlNPTi5zdHJpbmdpZnkocm93c0ZvckRiKSk7XG5cbiAgICAgIGNvbnN0IGNvbHVtbnMgPSBmaWVsZHMucmVkdWNlKChhY2MsIGZpZWxkLCBpbmRleCkgPT4ge1xuICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIFRPRE8gZXh0ZW5kIGZpZWxkcyB0byBjb250YWluIGR1Y2tEQkNvbHVtblR5cGVcbiAgICAgICAgcmV0dXJuIGAke2FjY30ke2luZGV4ID4gMCA/ICcsJyA6ICcnfSAnJHtmaWVsZC5uYW1lfSc6ICcke2ZpZWxkLmR1Y2tEQkNvbHVtblR5cGV9J2A7XG4gICAgICB9LCAnJyk7XG5cbiAgICAgIGNvbnN0IGNyZWF0ZVRhYmxlU3FsID0gYFxuICAgICAgICBDUkVBVEUgVEFCTEUgJyR7dGhpcy5sYWJlbH0nIEFTXG4gICAgICAgIFNFTEVDVCAqXG4gICAgICAgIEZST00gcmVhZF9qc29uKCcke3RoaXMuaWR9JyxcbiAgICAgICAgICAgICAgICAgICAgICAgY29sdW1ucyA9IHske2NvbHVtbnN9fSk7XG4gICAgICBgO1xuICAgICAgYXdhaXQgYy5xdWVyeShjcmVhdGVUYWJsZVNxbCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdpbXBvcnRSb3dEYXRhJywgZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGltcG9ydEdlb0pzb25EYXRhKHtkYXRhLCBkYiwgY306IEltcG9ydERhdGFUb0R1Y2tQcm9wcyk6IFByb21pc2U8SW1wb3J0RGF0YVRvRHVja1Jlc3VsdD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7cm93c30gPSBkYXRhO1xuICAgICAgYXdhaXQgZGIucmVnaXN0ZXJGaWxlVGV4dCh0aGlzLmlkLCBKU09OLnN0cmluZ2lmeShyb3dzKSk7XG5cbiAgICAgIGNvbnN0IGNyZWF0ZVRhYmxlU3FsID0gYFxuICAgICAgICBpbnN0YWxsIHNwYXRpYWw7XG4gICAgICAgIGxvYWQgc3BhdGlhbDtcbiAgICAgICAgQ1JFQVRFIFRBQkxFICcke3RoaXMubGFiZWx9JyBBUyBcbiAgICAgICAgU0VMRUNUICpcbiAgICAgICAgRlJPTSBTVF9SRUFEKCcke3RoaXMuaWR9Jywga2VlcF93a2IgPSBUUlVFKTtcbiAgICAgICAgQUxURVIgVEFCTEUgJyR7dGhpcy5sYWJlbH0nIFJFTkFNRSAnJHtEVUNLREJfV0tCX0NPTFVNTn0nIFRPICcke0tFUExFUl9HRU9NX0ZST01fR0VPSlNPTl9DT0xVTU59JztcbiAgICAgIGA7XG4gICAgICBhd2FpdCBjLnF1ZXJ5KGNyZWF0ZVRhYmxlU3FsKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5lcnJvcignaW1wb3J0R2VvSnNvbkRhdGEnLCBlcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC8vIF9nZW9qc29uIGNvbHVtbiBpcyBjcmVhdGVkIGZyb20gZ2VvbWV0cnkgd2l0aCBrZWVwX3drYiBmbGFnIGFuZCBjb250YWlucyB2YWxpZCBXS0IgZGF0YS5cbiAgICAgIGdlb2Fycm93TWV0YWRhdGE6IHtbS0VQTEVSX0dFT01fRlJPTV9HRU9KU09OX0NPTFVNTl06IEdFT0FSUk9XX0VYVEVOU0lPTlMuV0tCfVxuICAgIH07XG4gIH1cblxuICBhc3luYyBpbXBvcnRBcnJvd0RhdGEoe2RhdGEsIGN9OiBJbXBvcnREYXRhVG9EdWNrUHJvcHMpOiBQcm9taXNlPEltcG9ydERhdGFUb0R1Y2tSZXN1bHQ+IHtcbiAgICBsZXQgYWRqdXN0ZWRNZXRhZGF0YSA9IHt9O1xuICAgIHRyeSB7XG4gICAgICAvLyAxKSBkYXRhLnJvd3MgY29udGFpbnMgYW4gYXJyb3cgdGFibGUgY3JlYXRlZCBieSBBZGQgdG8gTWFwIGRhdGEgZnJvbSBEdWNrRGIgcXVlcnkuXG4gICAgICAvLyAyKSBhcnJvdyB0YWJsZSBpcyBpbiBjb2xzICYgZmllbGRzIHdoZW4gYSBmaWxlIGlzIGRyYWdnZWQgJiBkcm9wcGVkIGludG8gQWRkIERhdGEgVG8gTWFwIGRpYWxvZy5cbiAgICAgIGNvbnN0IGFycm93VGFibGUgPVxuICAgICAgICBkYXRhLnJvd3MgaW5zdGFuY2VvZiBhcnJvdy5UYWJsZVxuICAgICAgICAgID8gZGF0YS5yb3dzXG4gICAgICAgICAgOiByZXN0b3JlQXJyb3dUYWJsZShkYXRhLmNvbHMgfHwgW10sIGRhdGEuZmllbGRzLCBkYXRhLmFycm93U2NoZW1hKTtcblxuICAgICAgLy8gcmVtb3ZlIHVuc3VwcG9ydGVkIGV4dGVuc2lvbnMgZnJvbSBhbiBhcnJvdyB0YWJsZSB0aGF0IHRocm93IGV4Y2VwdGlvbnMgaW4gRHVja0RCLlxuICAgICAgYWRqdXN0ZWRNZXRhZGF0YSA9IHJlbW92ZVVuc3VwcG9ydGVkRXh0ZW5zaW9ucyhhcnJvd1RhYmxlKTtcblxuICAgICAgY29uc3Qgc2V0dXBTcWwgPSBgXG4gICAgICAgIGluc3RhbGwgc3BhdGlhbDtcbiAgICAgICAgbG9hZCBzcGF0aWFsO1xuICAgICAgYDtcbiAgICAgIGF3YWl0IGMucXVlcnkoc2V0dXBTcWwpO1xuICAgICAgYXdhaXQgYy5pbnNlcnRBcnJvd1RhYmxlKGFycm93VGFibGUsIHtuYW1lOiB0aGlzLmxhYmVsfSk7XG5cbiAgICAgIC8vIHJlc3RvcmUgdW5zdXBwb3J0ZWQgZXh0ZW5zaW9ucyB0aGF0IHRocm93IGV4Y2VwdGlvbnMgaW4gRHVja0RiXG4gICAgICByZXN0b3JlVW5zdXBwb3J0ZWRFeHRlbnNpb25zKGFycm93VGFibGUsIGFkanVzdGVkTWV0YWRhdGEpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBLbm93biBpc3N1ZXM6XG4gICAgICAvLyAxKSBBcnJvdyBUeXBlIHdpdGggZXh0ZW5zaW9uIG5hbWU6IGdlb2Fycm93LnBvaW50IGFuZCBmb3JtYXQ6ICt3OjIgaXMgbm90IGN1cnJlbnRseSBzdXBwb3J0ZWQgaW4gRHVja0RCLlxuICAgICAgY29uc29sZS5lcnJvcignaW1wb3J0QXJyb3dEYXRhJywgZXJyb3IpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBnZW9hcnJvd01ldGFkYXRhOiB7Li4uU1VHR0VTVEVEX0dFT01fQ09MVU1OUywgLi4uYWRqdXN0ZWRNZXRhZGF0YX0sXG4gICAgICAvLyB1c2UgZmllbGRzIGdlbmVyYXRlZCBmcm9tIHRoZSBjcmVhdGVkIGFycm93IHRhYmxlXG4gICAgICB1c2VOZXdGaWVsZHM6IHRydWVcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSB0YWJsZSBmcm9tIGRhdGEsIHJldHVybnMgYW4gYXJyb3cgdGFibGUgd2l0aCB0aGUgZGF0YVxuICAgKiBAcGFyYW0gZGF0YVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx7ZmllbGRzOiBGaWVsZFtdLCBjb2xzOiBhbnlbXX0+fVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZVRhYmxlQW5kR2V0QXJyb3coZGF0YSk6IFByb21pc2U8e2ZpZWxkczogYW55W107IGNvbHM6IGFycm93LlZlY3RvcltdfT4ge1xuICAgIGNvbnN0IGRiID0gYXdhaXQgZ2V0RHVja0RCKCk7XG4gICAgY29uc3QgYyA9IGF3YWl0IGRiLmNvbm5lY3QoKTtcblxuICAgIGNvbnN0IHRhYmxlTmFtZSA9IHRoaXMubGFiZWw7XG4gICAgYXdhaXQgZHJvcFRhYmxlSWZFeGlzdHMoYywgdGFibGVOYW1lKTtcblxuICAgIGxldCBmb3JtYXQgPSB0aGlzLm1ldGFkYXRhLmZvcm1hdDtcbiAgICBpZiAoIWZvcm1hdCkge1xuICAgICAgLy8gZm9ybWF0IGlzIG1pc3Npbmcgd2hlbiB3ZSBsb2FkIEtlcGxlci5nbCBleGFtcGxlc1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YS5yb3dzPy5bMF0pIHx8IHR5cGVvZiBkYXRhLnJvd3M/LlswXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgZm9ybWF0ID0gREFUQVNFVF9GT1JNQVRTLnJvdztcbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5yb3dzPy50eXBlID09PSAnRmVhdHVyZUNvbGxlY3Rpb24nKSB7XG4gICAgICAgIGZvcm1hdCA9IERBVEFTRVRfRk9STUFUUy5nZW9qc29uO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLmNvbHM/LlswXSBpbnN0YW5jZW9mIGFycm93LlZlY3Rvcikge1xuICAgICAgICBmb3JtYXQgPSBEQVRBU0VUX0ZPUk1BVFMuYXJyb3c7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IGltcG9ydERldGFpbHM6IEltcG9ydERhdGFUb0R1Y2tSZXN1bHQgfCB1bmRlZmluZWQ7XG4gICAgaWYgKGZvcm1hdCA9PT0gREFUQVNFVF9GT1JNQVRTLnJvdykge1xuICAgICAgYXdhaXQgdGhpcy5pbXBvcnRSb3dEYXRhKHtkYXRhLCBkYiwgY30pO1xuICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSBEQVRBU0VUX0ZPUk1BVFMuZ2VvanNvbikge1xuICAgICAgaW1wb3J0RGV0YWlscyA9IGF3YWl0IHRoaXMuaW1wb3J0R2VvSnNvbkRhdGEoe2RhdGEsIGRiLCBjfSk7XG4gICAgfSBlbHNlIGlmIChmb3JtYXQgPT09IERBVEFTRVRfRk9STUFUUy5hcnJvdykge1xuICAgICAgaW1wb3J0RGV0YWlscyA9IGF3YWl0IHRoaXMuaW1wb3J0QXJyb3dEYXRhKHtkYXRhLCBkYiwgY30pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdVbnJlY29nbml6ZWQgZm9ybWF0JywgZm9ybWF0KTtcbiAgICB9XG5cbiAgICBsZXQgZmllbGRzOiBGaWVsZFtdID0gW107XG4gICAgbGV0IGNvbHM6IGFycm93LlZlY3RvcltdID0gW107XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qge2dlb2Fycm93TWV0YWRhdGEgPSB7fSwgdXNlTmV3RmllbGRzID0gZmFsc2V9ID0gaW1wb3J0RGV0YWlscyB8fCB7fTtcblxuICAgICAgY29uc3QgZHVja0RiQ29sdW1ucyA9IGF3YWl0IGdldER1Y2tEQkNvbHVtblR5cGVzKGMsIHRhYmxlTmFtZSk7XG4gICAgICBjb25zdCB0YWJsZUR1Y2tEQlR5cGVzID0gZ2V0RHVja0RCQ29sdW1uVHlwZXNNYXAoZHVja0RiQ29sdW1ucyk7XG4gICAgICBjb25zdCBjb2x1bW5zVG9Db252ZXJ0VG9XS0IgPSBnZXRHZW9tZXRyeUNvbHVtbnMoZHVja0RiQ29sdW1ucyk7XG4gICAgICBjb25zdCBhZGp1c3RlZFF1ZXJ5ID0gY29uc3RydWN0U1RfYXNXS0JRdWVyeSh0YWJsZU5hbWUsIGNvbHVtbnNUb0NvbnZlcnRUb1dLQik7XG4gICAgICBjb25zdCBhcnJvd1Jlc3VsdCA9IGF3YWl0IGMucXVlcnkoYWRqdXN0ZWRRdWVyeSk7XG5cbiAgICAgIC8vIFRPRE8gaWYgZm9ybWF0IGlzIGFuIGFycm93IHRhYmxlIHRoZW4ganVzdCB1c2UgdGhlIG9yaWdpbmFsIG9uZSwgaW5zdGVhZCBvZiB0aGUgbmV3IHRhYmxlIGZyb20gdGhlIHF1ZXJ5P1xuXG4gICAgICByZXN0b3JlR2VvYXJyb3dNZXRhZGF0YShhcnJvd1Jlc3VsdCwgZ2VvYXJyb3dNZXRhZGF0YSk7XG5cbiAgICAgIGZpZWxkcyA9IHVzZU5ld0ZpZWxkc1xuICAgICAgICA/IGFycm93U2NoZW1hVG9GaWVsZHMoYXJyb3dSZXN1bHQsIHRhYmxlRHVja0RCVHlwZXMpXG4gICAgICAgIDogZGF0YS5maWVsZHMgPz8gYXJyb3dTY2hlbWFUb0ZpZWxkcyhhcnJvd1Jlc3VsdCwgdGFibGVEdWNrREJUeXBlcyk7XG4gICAgICBjb2xzID0gWy4uLkFycmF5KGFycm93UmVzdWx0Lm51bUNvbHMpLmtleXMoKV1cbiAgICAgICAgLm1hcChpID0+IGFycm93UmVzdWx0LmdldENoaWxkQXQoaSkpXG4gICAgICAgIC5maWx0ZXIoY29sID0+IGNvbCkgYXMgYXJyb3cuVmVjdG9yW107XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0R1Y2tEQiB0YWJsZTogY3JlYXRlVGFibGVBbmRHZXRBcnJvdycsIGVycm9yKTtcbiAgICB9XG5cbiAgICBhd2FpdCBjLmNsb3NlKCk7XG5cbiAgICByZXR1cm4ge2ZpZWxkcywgY29sc307XG4gIH1cblxuICBhc3luYyBpbXBvcnREYXRhKHtkYXRhfToge2RhdGE6IFByb2Nlc3NvclJlc3VsdH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBWZWN0b3JUaWxlIGlzIGEgc3BlY2lhbCBjYXNlLCBpZ25vcmUgZm9yIG5vd1xuICAgIGlmICh0aGlzLnR5cGUgPT09IERhdGFzZXRUeXBlLlZFQ1RPUl9USUxFKSB7XG4gICAgICBzdXBlci5pbXBvcnREYXRhKHtkYXRhOiB7Li4uZGF0YSwgcm93czogW119fSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qge2ZpZWxkcywgY29sc30gPSBhd2FpdCB0aGlzLmNyZWF0ZVRhYmxlQW5kR2V0QXJyb3coZGF0YSk7XG5cbiAgICBzdXBlci5pbXBvcnREYXRhKHtkYXRhOiB7ZmllbGRzLCBjb2xzLCByb3dzOiBbXX19KTtcbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZShkYXRhKSB7XG4gICAgLy8gVmVjdG9yVGlsZSBpcyBhIHNwZWNpYWwgY2FzZSwgaWdub3JlIGZvciBub3dcbiAgICBpZiAodGhpcy50eXBlID09PSBEYXRhc2V0VHlwZS5WRUNUT1JfVElMRSkge1xuICAgICAgc3VwZXIuaW1wb3J0RGF0YSh7ZGF0YX0pO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgY29uc3Qge2NvbHN9ID0gYXdhaXQgdGhpcy5jcmVhdGVUYWJsZUFuZEdldEFycm93KGRhdGEpO1xuXG4gICAgcmV0dXJuIHN1cGVyLnVwZGF0ZSh7Y29scywgcm93czogW10sIGZpZWxkczogW119KTtcbiAgfVxuXG4gIHN0YXRpYyBnZXRGaWxlUHJvY2Vzc29yID0gZnVuY3Rpb24gKGRhdGE6IGFueSwgaW5wdXRGb3JtYXQ/OiBzdHJpbmcpIHtcbiAgICBsZXQgcHJvY2Vzc29yO1xuICAgIGxldCBmb3JtYXQ7XG4gICAgaWYgKGlucHV0Rm9ybWF0ID09PSBEQVRBU0VUX0ZPUk1BVFMuYXJyb3cgfHwgaXNBcnJvd0RhdGEoZGF0YSkpIHtcbiAgICAgIGZvcm1hdCA9IERBVEFTRVRfRk9STUFUUy5hcnJvdztcbiAgICAgIHByb2Nlc3NvciA9IHByb2Nlc3NBcnJvd0JhdGNoZXM7XG4gICAgfSBlbHNlIGlmIChpbnB1dEZvcm1hdCA9PT0gREFUQVNFVF9GT1JNQVRTLmtlcGxlcmdsIHx8IGlzS2VwbGVyR2xNYXAoZGF0YSkpIHtcbiAgICAgIGZvcm1hdCA9IERBVEFTRVRfRk9STUFUUy5rZXBsZXJnbDtcbiAgICAgIHByb2Nlc3NvciA9IHByb2Nlc3NLZXBsZXJnbEpTT05mb3JEdWNrRGI7XG4gICAgfSBlbHNlIGlmIChpbnB1dEZvcm1hdCA9PT0gREFUQVNFVF9GT1JNQVRTLnJvdyB8fCBpc1Jvd09iamVjdChkYXRhKSkge1xuICAgICAgLy8gY3N2IGZpbGUgZ29lcyBoZXJlXG4gICAgICBmb3JtYXQgPSBEQVRBU0VUX0ZPUk1BVFMucm93O1xuICAgICAgcHJvY2Vzc29yID0gcHJvY2Vzc0NzdlJvd09iamVjdDsgLy8gZGlyZWN0bHkgaW1wb3J0IGpzb24gb2JqZWN0IGludG8gZHVja2RiLXdhc21cbiAgICB9IGVsc2UgaWYgKGlucHV0Rm9ybWF0ID09PSBEQVRBU0VUX0ZPUk1BVFMuZ2VvanNvbiB8fCBpc0dlb0pzb24oZGF0YSkpIHtcbiAgICAgIGZvcm1hdCA9IERBVEFTRVRfRk9STUFUUy5nZW9qc29uO1xuICAgICAgcHJvY2Vzc29yID0gcHJvY2Vzc0dlb2pzb247XG4gICAgfVxuICAgIHJldHVybiB7cHJvY2Vzc29yLCBmb3JtYXR9O1xuICB9O1xuXG4gIHN0YXRpYyBnZXRJbnB1dERhdGFWYWxpZGF0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgLy8gSW4gRHVja0RCIG1vZGUgZGF0YSBpcyB2YWxpZGF0ZWQgbGF0ZXIgZHVyaW5nIGltcG9ydC5cbiAgICByZXR1cm4gZCA9PiBkO1xuICB9O1xufVxuXG4vKipcbiAqIFRyeSB0byByZXN0b3JlIGdlb2Fycm93IG1ldGFkYXRhIGxvc3QgZHVyaW5nIER1Y2tEYiBpbmdlc3Rpb24uXG4gKiBOb3RlIHRoYXQgdGhpcyBmdW5jdGlvbiBjYW4gZ2VuZXJhdGUgd3JvbmcgZ2VvbWV0cnkgdHlwZXMuXG4gKiBAcGFyYW0gYXJyb3dUYWJsZSBBcnJvdyB0YWJsZSB0byB1cGRhdGUuXG4gKiBAcGFyYW0gZ2VvYXJyb3dNZXRhZGF0YSBBIG1hcCB3aXRoIGZpZWxkIG5hbWVzIHRoYXQgdXN1YWxseSB1c2VkIHRvIHN0b3JlIGdlb2Fycm93IGdlb21ldHJ5LlxuICovXG5jb25zdCByZXN0b3JlR2VvYXJyb3dNZXRhZGF0YSA9IGFzeW5jIChcbiAgYXJyb3dUYWJsZTogYXJyb3cuVGFibGUsXG4gIGdlb2Fycm93TWV0YWRhdGE6IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbikgPT4ge1xuICBhcnJvd1RhYmxlLnNjaGVtYS5maWVsZHMuZm9yRWFjaChmID0+IHtcbiAgICBpZiAoYXJyb3cuRGF0YVR5cGUuaXNCaW5hcnkoZi50eXBlKSAmJiBnZW9hcnJvd01ldGFkYXRhW2YubmFtZV0pIHtcbiAgICAgIGYubWV0YWRhdGEuc2V0KEdFT0FSUk9XX01FVEFEQVRBX0tFWSwgZ2VvYXJyb3dNZXRhZGF0YVtmLm5hbWVdKTtcbiAgICB9IGVsc2UgaWYgKGlzR2VvQXJyb3dQb2ludChmLnR5cGUpKSB7XG4gICAgICBmLm1ldGFkYXRhLnNldChHRU9BUlJPV19NRVRBREFUQV9LRVksIEdFT0FSUk9XX0VYVEVOU0lPTlMuUE9JTlQpO1xuICAgIH0gZWxzZSBpZiAoaXNHZW9BcnJvd0xpbmVTdHJpbmcoZi50eXBlKSkge1xuICAgICAgZi5tZXRhZGF0YS5zZXQoR0VPQVJST1dfTUVUQURBVEFfS0VZLCBHRU9BUlJPV19FWFRFTlNJT05TLkxJTkVTVFJJTkcpO1xuICAgIH0gZWxzZSBpZiAoaXNHZW9BcnJvd1BvbHlnb24oZi50eXBlKSkge1xuICAgICAgZi5tZXRhZGF0YS5zZXQoR0VPQVJST1dfTUVUQURBVEFfS0VZLCBHRU9BUlJPV19FWFRFTlNJT05TLlBPTFlHT04pO1xuICAgIH0gZWxzZSBpZiAoaXNHZW9BcnJvd011bHRpUG9pbnQoZi50eXBlKSkge1xuICAgICAgZi5tZXRhZGF0YS5zZXQoR0VPQVJST1dfTUVUQURBVEFfS0VZLCBHRU9BUlJPV19FWFRFTlNJT05TLk1VTFRJUE9JTlQpO1xuICAgIH0gZWxzZSBpZiAoaXNHZW9BcnJvd011bHRpTGluZVN0cmluZyhmLnR5cGUpKSB7XG4gICAgICBmLm1ldGFkYXRhLnNldChHRU9BUlJPV19NRVRBREFUQV9LRVksIEdFT0FSUk9XX0VYVEVOU0lPTlMuTVVMVElMSU5FU1RSSU5HKTtcbiAgICB9IGVsc2UgaWYgKGlzR2VvQXJyb3dNdWx0aVBvbHlnb24oZi50eXBlKSkge1xuICAgICAgZi5tZXRhZGF0YS5zZXQoR0VPQVJST1dfTUVUQURBVEFfS0VZLCBHRU9BUlJPV19FWFRFTlNJT05TLk1VTFRJUE9MWUdPTik7XG4gICAgfVxuICB9KTtcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFHQSxJQUFBQSxLQUFBLEdBQUFDLHVCQUFBLENBQUFDLE9BQUE7QUFHQSxJQUFBQyxVQUFBLEdBQUFELE9BQUE7QUFNQSxJQUFBRSxXQUFBLEdBQUFGLE9BQUE7QUFRQSxJQUFBRyxNQUFBLEdBQUFILE9BQUE7QUFHQSxJQUFBSSxLQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxjQUFBLEdBQUFMLE9BQUE7QUFPQSxJQUFBTSxpQkFBQSxHQUFBTixPQUFBO0FBU0EsSUFBQU8sa0JBQUEsR0FBQVAsT0FBQTtBQVNxQyxTQUFBUSx5QkFBQUMsQ0FBQSw2QkFBQUMsT0FBQSxtQkFBQUMsQ0FBQSxPQUFBRCxPQUFBLElBQUFFLENBQUEsT0FBQUYsT0FBQSxZQUFB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