kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
183 lines (175 loc) • 29.2 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.adjustCellsToContainer = adjustCellsToContainer;
exports.renderedSize = renderedSize;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _document = _interopRequireDefault(require("global/document"));
var _utils = require("@kepler.gl/utils");
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; } // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
var MIN_GHOST_CELL_SIZE = 200;
var MIN_CELL_SIZE = 45;
// first column have padding on the left
var EDGE_COLUMN_PADDING = 10;
// in case cell content is small, column name is big, we allow max empty space to
// be added to min cell width in order to show column name
var MAX_EMPTY_COLUMN_SPACE = 60;
/**
* Measure rows and column content to determine min width for each column
* @param {RenderSizeParam} param0
*/
function renderedSize(_ref) {
var _ref$text = _ref.text,
dataContainer = _ref$text.dataContainer,
column = _ref$text.column,
_ref$type = _ref.type,
type = _ref$type === void 0 ? 'string' : _ref$type,
colIdx = _ref.colIdx,
_ref$numRowsToCalcula = _ref.numRowsToCalculate,
numRowsToCalculate = _ref$numRowsToCalcula === void 0 ? 10 : _ref$numRowsToCalcula,
_ref$fontSize = _ref.fontSize,
fontSize = _ref$fontSize === void 0 ? 12 : _ref$fontSize,
_ref$font = _ref.font,
font = _ref$font === void 0 ? 'Lato' : _ref$font,
_ref$cellPadding = _ref.cellPadding,
cellPadding = _ref$cellPadding === void 0 ? 40 : _ref$cellPadding,
_ref$maxCellSize = _ref.maxCellSize,
maxCellSize = _ref$maxCellSize === void 0 ? 500 : _ref$maxCellSize,
_ref$maxHeaderSize = _ref.maxHeaderSize,
maxHeaderSize = _ref$maxHeaderSize === void 0 ? 500 : _ref$maxHeaderSize,
_ref$minCellSize = _ref.minCellSize,
minCellSize = _ref$minCellSize === void 0 ? MIN_CELL_SIZE : _ref$minCellSize,
_ref$optionsButton = _ref.optionsButton,
optionsButton = _ref$optionsButton === void 0 ? 44 : _ref$optionsButton;
if (!_document["default"]) {
return {
row: 0,
header: 0
};
}
var textCanvas = _document["default"].createElement('canvas');
_document["default"].body.appendChild(textCanvas);
var context = textCanvas.getContext('2d');
context.font = [fontSize, font].join('px ');
var rowsToSample = (0, _toConsumableArray2["default"])(Array(numRowsToCalculate)).map(function () {
return Math.floor(Math.random() * (dataContainer.numRows() - 1));
});
// If we have less than 10 rows, lets measure all of them
if (dataContainer.numRows() <= numRowsToCalculate) {
rowsToSample = Array.from(Array(dataContainer.numRows()).keys());
}
var rowWidth = Math.max.apply(Math, (0, _toConsumableArray2["default"])(rowsToSample.map(function (rowIdx) {
var value = (0, _utils.parseFieldValue)(dataContainer.valueAt(rowIdx, colIdx), type);
// measuring large text cause slow performance
if (value.length > maxCellSize) {
return maxCellSize;
}
var textWidth = context.measureText(value).width;
return Math.ceil(textWidth) + cellPadding;
})));
// header cell only has left padding
var headerWidth = Math.ceil(context.measureText(column).width) + cellPadding / 2 + optionsButton;
// min row width is measured by cell content
var minRowWidth = minCellSize + cellPadding;
// min header width is measured by cell
var minHeaderWidth = minCellSize + cellPadding / 2 + optionsButton;
var clampedRowWidth = clamp(minRowWidth, maxCellSize, rowWidth);
var clampedHeaderWidth = clamp(minHeaderWidth, maxHeaderSize, headerWidth);
// cleanup
textCanvas.parentElement.removeChild(textCanvas);
return {
row: clampedRowWidth,
header: clampedHeaderWidth
};
}
function clamp(min, max, value) {
return Math.max(Math.min(max, value), min);
}
function getColumnOrder() {
var pinnedColumns = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var unpinnedColumns = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
return [].concat((0, _toConsumableArray2["default"])(pinnedColumns), (0, _toConsumableArray2["default"])(unpinnedColumns));
}
// If total min cell size is bigger than containerWidth adjust column
function getMinCellSize(cellSizeCache) {
return Object.keys(cellSizeCache).reduce(function (accu, col) {
return _objectSpread(_objectSpread({}, accu), {}, (0, _defineProperty2["default"])({}, col, cellSizeCache[col].row > cellSizeCache[col].header ? cellSizeCache[col].row :
// if row is smaller than header, use the smaller of MAX_EMPTY_COLUMN_SPACE + row width and header
Math.min(cellSizeCache[col].header, cellSizeCache[col].row + MAX_EMPTY_COLUMN_SPACE)));
}, {});
}
function getSizeSum(sizeCache, key) {
return Object.keys(sizeCache).reduce(function (acc, val) {
return acc + (key ? sizeCache[val][key] : sizeCache[val]);
}, 0);
}
/**
* Expand cell to fit both row and header, if there is still room left,
* expand last cell to fit the entire width of the container
* @param {CellSizeCache} cellSizeCache
* @param {string[]} columnOrder
* @param {number} containerWidth
* @param {number} roomToFill
*/
function expandCellSize(cellSizeCache, columnOrder, containerWidth, roomToFill) {
var remaining = roomToFill;
var expandedCellSize = columnOrder.reduce(function (accu, col) {
var size = cellSizeCache[col].row;
if (cellSizeCache[col].row < cellSizeCache[col].header && remaining > 0) {
// if we are cutting off the header, expand to fit it
size = cellSizeCache[col].header - cellSizeCache[col].row < remaining ? cellSizeCache[col].header : cellSizeCache[col].row + remaining;
remaining -= size - cellSizeCache[col].row;
}
return _objectSpread(_objectSpread({}, accu), {}, (0, _defineProperty2["default"])({}, col, size));
}, {});
var ghost = null;
if (remaining > 0 && remaining < MIN_GHOST_CELL_SIZE) {
// expand last cell
var lastCell = columnOrder[columnOrder.length - 1];
expandedCellSize[lastCell] += remaining;
} else if (remaining >= MIN_GHOST_CELL_SIZE) {
// if too much left add a ghost cell
ghost = remaining;
}
return {
cellSizeCache: expandedCellSize,
ghost: ghost
};
}
function addPaddingToFirstColumn(cellSizeCache) {
var columnOrder = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var firstCol = columnOrder[0];
if (firstCol && cellSizeCache[firstCol]) {
return _objectSpread(_objectSpread({}, cellSizeCache), {}, (0, _defineProperty2["default"])({}, firstCol, {
header: cellSizeCache[firstCol].header + EDGE_COLUMN_PADDING,
row: cellSizeCache[firstCol].row + EDGE_COLUMN_PADDING
}));
}
return cellSizeCache;
}
/**
* Adjust cell size based on container width
* @param {number} containerWidth
* @param {CellSizeCache} cellSizeCache
* @param {string[]} pinnedColumns
* @param {string[]} unpinnedColumns
*/
function adjustCellsToContainer(containerWidth, cellSizeCache, pinnedColumns, unpinnedColumns) {
var columnOrder = getColumnOrder(pinnedColumns, unpinnedColumns);
var paddedCellSize = addPaddingToFirstColumn(cellSizeCache, columnOrder);
var minRowSum = getSizeSum(paddedCellSize, 'row');
if (minRowSum >= containerWidth) {
// we apply the min Width to all cells
return {
cellSizeCache: getMinCellSize(paddedCellSize)
};
}
// if we have some room to expand
return expandCellSize(paddedCellSize, columnOrder, containerWidth, containerWidth - minRowSum);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZG9jdW1lbnQiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl91dGlscyIsIm93bktleXMiLCJlIiwiciIsInQiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsImRlZmluZVByb3BlcnR5IiwiTUlOX0dIT1NUX0NFTExfU0laRSIsIk1JTl9DRUxMX1NJWkUiLCJFREdFX0NPTFVNTl9QQURESU5HIiwiTUFYX0VNUFRZX0NPTFVNTl9TUEFDRSIsInJlbmRlcmVkU2l6ZSIsIl9yZWYiLCJfcmVmJHRleHQiLCJ0ZXh0IiwiZGF0YUNvbnRhaW5lciIsImNvbHVtbiIsIl9yZWYkdHlwZSIsInR5cGUiLCJjb2xJZHgiLCJfcmVmJG51bVJvd3NUb0NhbGN1bGEiLCJudW1Sb3dzVG9DYWxjdWxhdGUiLCJfcmVmJGZvbnRTaXplIiwiZm9udFNpemUiLCJfcmVmJGZvbnQiLCJmb250IiwiX3JlZiRjZWxsUGFkZGluZyIsImNlbGxQYWRkaW5nIiwiX3JlZiRtYXhDZWxsU2l6ZSIsIm1heENlbGxTaXplIiwiX3JlZiRtYXhIZWFkZXJTaXplIiwibWF4SGVhZGVyU2l6ZSIsIl9yZWYkbWluQ2VsbFNpemUiLCJtaW5DZWxsU2l6ZSIsIl9yZWYkb3B0aW9uc0J1dHRvbiIsIm9wdGlvbnNCdXR0b24iLCJkb2N1bWVudCIsInJvdyIsImhlYWRlciIsInRleHRDYW52YXMiLCJjcmVhdGVFbGVtZW50IiwiYm9keSIsImFwcGVuZENoaWxkIiwiY29udGV4dCIsImdldENvbnRleHQiLCJqb2luIiwicm93c1RvU2FtcGxlIiwiX3RvQ29uc3VtYWJsZUFycmF5MiIsIkFycmF5IiwibWFwIiwiTWF0aCIsImZsb29yIiwicmFuZG9tIiwibnVtUm93cyIsImZyb20iLCJyb3dXaWR0aCIsIm1heCIsInJvd0lkeCIsInZhbHVlIiwicGFyc2VGaWVsZFZhbHVlIiwidmFsdWVBdCIsInRleHRXaWR0aCIsIm1lYXN1cmVUZXh0Iiwid2lkdGgiLCJjZWlsIiwiaGVhZGVyV2lkdGgiLCJtaW5Sb3dXaWR0aCIsIm1pbkhlYWRlcldpZHRoIiwiY2xhbXBlZFJvd1dpZHRoIiwiY2xhbXAiLCJjbGFtcGVkSGVhZGVyV2lkdGgiLCJwYXJlbnRFbGVtZW50IiwicmVtb3ZlQ2hpbGQiLCJtaW4iLCJnZXRDb2x1bW5PcmRlciIsInBpbm5lZENvbHVtbnMiLCJ1bmRlZmluZWQiLCJ1bnBpbm5lZENvbHVtbnMiLCJjb25jYXQiLCJnZXRNaW5DZWxsU2l6ZSIsImNlbGxTaXplQ2FjaGUiLCJyZWR1Y2UiLCJhY2N1IiwiY29sIiwiZ2V0U2l6ZVN1bSIsInNpemVDYWNoZSIsImtleSIsImFjYyIsInZhbCIsImV4cGFuZENlbGxTaXplIiwiY29sdW1uT3JkZXIiLCJjb250YWluZXJXaWR0aCIsInJvb21Ub0ZpbGwiLCJyZW1haW5pbmciLCJleHBhbmRlZENlbGxTaXplIiwic2l6ZSIsImdob3N0IiwibGFzdENlbGwiLCJhZGRQYWRkaW5nVG9GaXJzdENvbHVtbiIsImZpcnN0Q29sIiwiYWRqdXN0Q2VsbHNUb0NvbnRhaW5lciIsInBhZGRlZENlbGxTaXplIiwibWluUm93U3VtIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1vbi9kYXRhLXRhYmxlL2NlbGwtc2l6ZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQgZG9jdW1lbnQgZnJvbSAnZ2xvYmFsL2RvY3VtZW50JztcbmltcG9ydCB7RGF0YUNvbnRhaW5lckludGVyZmFjZSwgcGFyc2VGaWVsZFZhbHVlfSBmcm9tICdAa2VwbGVyLmdsL3V0aWxzJztcblxuY29uc3QgTUlOX0dIT1NUX0NFTExfU0laRSA9IDIwMDtcbmNvbnN0IE1JTl9DRUxMX1NJWkUgPSA0NTtcbi8vIGZpcnN0IGNvbHVtbiBoYXZlIHBhZGRpbmcgb24gdGhlIGxlZnRcbmNvbnN0IEVER0VfQ09MVU1OX1BBRERJTkcgPSAxMDtcblxuLy8gaW4gY2FzZSBjZWxsIGNvbnRlbnQgaXMgc21hbGwsIGNvbHVtbiBuYW1lIGlzIGJpZywgd2UgYWxsb3cgbWF4IGVtcHR5IHNwYWNlIHRvXG4vLyBiZSBhZGRlZCB0byBtaW4gY2VsbCB3aWR0aCBpbiBvcmRlciB0byBzaG93IGNvbHVtbiBuYW1lXG5jb25zdCBNQVhfRU1QVFlfQ09MVU1OX1NQQUNFID0gNjA7XG5cbnR5cGUgUmVuZGVyU2l6ZVBhcmFtID0ge1xuICB0ZXh0OiB7ZGF0YUNvbnRhaW5lcjogRGF0YUNvbnRhaW5lckludGVyZmFjZTsgY29sdW1uOiBzdHJpbmd9O1xuICB0eXBlPzogc3RyaW5nO1xuICBjb2xJZHg6IG51bWJlcjtcbiAgbnVtUm93c1RvQ2FsY3VsYXRlPzogbnVtYmVyO1xuICBmb250U2l6ZT86IG51bWJlcjtcbiAgZm9udD86IHN0cmluZztcbiAgY2VsbFBhZGRpbmc/OiBudW1iZXI7XG4gIG1heENlbGxTaXplPzogbnVtYmVyO1xuICBtYXhIZWFkZXJTaXplPzogbnVtYmVyO1xuICBtaW5DZWxsU2l6ZT86IG51bWJlcjtcbiAgb3B0aW9uc0J1dHRvbj86IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIENlbGxTaXplQ2FjaGUgPSB7XG4gIFtrZXk6IHN0cmluZ106IHtcbiAgICByb3c6IG51bWJlcjtcbiAgICBoZWFkZXI6IG51bWJlcjtcbiAgfTtcbn07XG5cbi8qKlxuICogTWVhc3VyZSByb3dzIGFuZCBjb2x1bW4gY29udGVudCB0byBkZXRlcm1pbmUgbWluIHdpZHRoIGZvciBlYWNoIGNvbHVtblxuICogQHBhcmFtIHtSZW5kZXJTaXplUGFyYW19IHBhcmFtMFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyZWRTaXplKHtcbiAgdGV4dDoge2RhdGFDb250YWluZXIsIGNvbHVtbn0sXG4gIHR5cGUgPSAnc3RyaW5nJyxcbiAgY29sSWR4LFxuICBudW1Sb3dzVG9DYWxjdWxhdGUgPSAxMCxcbiAgZm9udFNpemUgPSAxMixcbiAgZm9udCA9ICdMYXRvJyxcbiAgY2VsbFBhZGRpbmcgPSA0MCxcbiAgbWF4Q2VsbFNpemUgPSA1MDAsXG4gIG1heEhlYWRlclNpemUgPSA1MDAsXG4gIG1pbkNlbGxTaXplID0gTUlOX0NFTExfU0laRSxcbiAgb3B0aW9uc0J1dHRvbiA9IDQ0XG59OiBSZW5kZXJTaXplUGFyYW0pOiB7cm93OiBudW1iZXI7IGhlYWRlcjogbnVtYmVyfSB7XG4gIGlmICghZG9jdW1lbnQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgcm93OiAwLFxuICAgICAgaGVhZGVyOiAwXG4gICAgfTtcbiAgfVxuXG4gIGNvbnN0IHRleHRDYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCh0ZXh0Q2FudmFzKTtcbiAgY29uc3QgY29udGV4dCA9IHRleHRDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgY29udGV4dC5mb250ID0gW2ZvbnRTaXplLCBmb250XS5qb2luKCdweCAnKTtcblxuICBsZXQgcm93c1RvU2FtcGxlID0gWy4uLkFycmF5KG51bVJvd3NUb0NhbGN1bGF0ZSldLm1hcCgoKSA9PlxuICAgIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIChkYXRhQ29udGFpbmVyLm51bVJvd3MoKSAtIDEpKVxuICApO1xuXG4gIC8vIElmIHdlIGhhdmUgbGVzcyB0aGFuIDEwIHJvd3MsIGxldHMgbWVhc3VyZSBhbGwgb2YgdGhlbVxuICBpZiAoZGF0YUNvbnRhaW5lci5udW1Sb3dzKCkgPD0gbnVtUm93c1RvQ2FsY3VsYXRlKSB7XG4gICAgcm93c1RvU2FtcGxlID0gQXJyYXkuZnJvbShBcnJheShkYXRhQ29udGFpbmVyLm51bVJvd3MoKSkua2V5cygpKTtcbiAgfVxuICBjb25zdCByb3dXaWR0aCA9IE1hdGgubWF4KFxuICAgIC4uLnJvd3NUb1NhbXBsZS5tYXAocm93SWR4ID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlID0gcGFyc2VGaWVsZFZhbHVlKGRhdGFDb250YWluZXIudmFsdWVBdChyb3dJZHgsIGNvbElkeCksIHR5cGUpO1xuICAgICAgLy8gbWVhc3VyaW5nIGxhcmdlIHRleHQgY2F1c2Ugc2xvdyBwZXJmb3JtYW5jZVxuICAgICAgaWYgKHZhbHVlLmxlbmd0aCA+IG1heENlbGxTaXplKSB7XG4gICAgICAgIHJldHVybiBtYXhDZWxsU2l6ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRleHRXaWR0aCA9IGNvbnRleHQubWVhc3VyZVRleHQodmFsdWUpLndpZHRoO1xuICAgICAgcmV0dXJuIE1hdGguY2VpbCh0ZXh0V2lkdGgpICsgY2VsbFBhZGRpbmc7XG4gICAgfSlcbiAgKTtcbiAgLy8gaGVhZGVyIGNlbGwgb25seSBoYXMgbGVmdCBwYWRkaW5nXG4gIGNvbnN0IGhlYWRlcldpZHRoID1cbiAgICBNYXRoLmNlaWwoY29udGV4dC5tZWFzdXJlVGV4dChjb2x1bW4pLndpZHRoKSArIGNlbGxQYWRkaW5nIC8gMiArIG9wdGlvbnNCdXR0b247XG5cbiAgLy8gbWluIHJvdyB3aWR0aCBpcyBtZWFzdXJlZCBieSBjZWxsIGNvbnRlbnRcbiAgY29uc3QgbWluUm93V2lkdGggPSBtaW5DZWxsU2l6ZSArIGNlbGxQYWRkaW5nO1xuICAvLyBtaW4gaGVhZGVyIHdpZHRoIGlzIG1lYXN1cmVkIGJ5IGNlbGxcbiAgY29uc3QgbWluSGVhZGVyV2lkdGggPSBtaW5DZWxsU2l6ZSArIGNlbGxQYWRkaW5nIC8gMiArIG9wdGlvbnNCdXR0b247XG5cbiAgY29uc3QgY2xhbXBlZFJvd1dpZHRoID0gY2xhbXAobWluUm93V2lkdGgsIG1heENlbGxTaXplLCByb3dXaWR0aCk7XG4gIGNvbnN0IGNsYW1wZWRIZWFkZXJXaWR0aCA9IGNsYW1wKG1pbkhlYWRlcldpZHRoLCBtYXhIZWFkZXJTaXplLCBoZWFkZXJXaWR0aCk7XG5cbiAgLy8gY2xlYW51cFxuICB0ZXh0Q2FudmFzLnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQodGV4dENhbnZhcyk7XG5cbiAgcmV0dXJuIHtcbiAgICByb3c6IGNsYW1wZWRSb3dXaWR0aCxcbiAgICBoZWFkZXI6IGNsYW1wZWRIZWFkZXJXaWR0aFxuICB9O1xufVxuXG5mdW5jdGlvbiBjbGFtcChtaW4sIG1heCwgdmFsdWUpIHtcbiAgcmV0dXJuIE1hdGgubWF4KE1hdGgubWluKG1heCwgdmFsdWUpLCBtaW4pO1xufVxuXG5mdW5jdGlvbiBnZXRDb2x1bW5PcmRlcihwaW5uZWRDb2x1bW5zOiBzdHJpbmdbXSA9IFtdLCB1bnBpbm5lZENvbHVtbnM6IHN0cmluZ1tdID0gW10pIHtcbiAgcmV0dXJuIFsuLi5waW5uZWRDb2x1bW5zLCAuLi51bnBpbm5lZENvbHVtbnNdO1xufVxuXG4vLyBJZiB0b3RhbCBtaW4gY2VsbCBzaXplIGlzIGJpZ2dlciB0aGFuIGNvbnRhaW5lcldpZHRoIGFkanVzdCBjb2x1bW5cbmZ1bmN0aW9uIGdldE1pbkNlbGxTaXplKGNlbGxTaXplQ2FjaGU6IENlbGxTaXplQ2FjaGUpIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKGNlbGxTaXplQ2FjaGUpLnJlZHVjZShcbiAgICAoYWNjdSwgY29sKSA9PiAoe1xuICAgICAgLi4uYWNjdSxcbiAgICAgIC8vIGlmIHJvdyBpcyBsYXJnZXIgdGhhbiBoZWFkZXIsIHVzZSByb3dcbiAgICAgIFtjb2xdOlxuICAgICAgICBjZWxsU2l6ZUNhY2hlW2NvbF0ucm93ID4gY2VsbFNpemVDYWNoZVtjb2xdLmhlYWRlclxuICAgICAgICAgID8gY2VsbFNpemVDYWNoZVtjb2xdLnJvd1xuICAgICAgICAgIDogLy8gaWYgcm93IGlzIHNtYWxsZXIgdGhhbiBoZWFkZXIsIHVzZSB0aGUgc21hbGxlciBvZiBNQVhfRU1QVFlfQ09MVU1OX1NQQUNFICsgcm93IHdpZHRoIGFuZCBoZWFkZXJcbiAgICAgICAgICAgIE1hdGgubWluKGNlbGxTaXplQ2FjaGVbY29sXS5oZWFkZXIsIGNlbGxTaXplQ2FjaGVbY29sXS5yb3cgKyBNQVhfRU1QVFlfQ09MVU1OX1NQQUNFKVxuICAgIH0pLFxuICAgIHt9XG4gICk7XG59XG5cbmZ1bmN0aW9uIGdldFNpemVTdW0oc2l6ZUNhY2hlLCBrZXkpIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKHNpemVDYWNoZSkucmVkdWNlKFxuICAgIChhY2MsIHZhbCkgPT4gYWNjICsgKGtleSA/IHNpemVDYWNoZVt2YWxdW2tleV0gOiBzaXplQ2FjaGVbdmFsXSksXG4gICAgMFxuICApO1xufVxuXG4vKipcbiAqIEV4cGFuZCBjZWxsIHRvIGZpdCBib3RoIHJvdyBhbmQgaGVhZGVyLCBpZiB0aGVyZSBpcyBzdGlsbCByb29tIGxlZnQsXG4gKiBleHBhbmQgbGFzdCBjZWxsIHRvIGZpdCB0aGUgZW50aXJlIHdpZHRoIG9mIHRoZSBjb250YWluZXJcbiAqIEBwYXJhbSB7Q2VsbFNpemVDYWNoZX0gY2VsbFNpemVDYWNoZVxuICogQHBhcmFtIHtzdHJpbmdbXX0gY29sdW1uT3JkZXJcbiAqIEBwYXJhbSB7bnVtYmVyfSBjb250YWluZXJXaWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IHJvb21Ub0ZpbGxcbiAqL1xuZnVuY3Rpb24gZXhwYW5kQ2VsbFNpemUoXG4gIGNlbGxTaXplQ2FjaGU6IENlbGxTaXplQ2FjaGUsXG4gIGNvbHVtbk9yZGVyOiBzdHJpbmdbXSxcbiAgY29udGFpbmVyV2lkdGg6IG51bWJlcixcbiAgcm9vbVRvRmlsbDogbnVtYmVyXG4pOiB7XG4gIGNlbGxTaXplQ2FjaGU6IENlbGxTaXplQ2FjaGU7XG4gIGdob3N0OiBudW1iZXIgfCBudWxsO1xufSB7XG4gIGxldCByZW1haW5pbmcgPSByb29tVG9GaWxsO1xuXG4gIGNvbnN0IGV4cGFuZGVkQ2VsbFNpemUgPSBjb2x1bW5PcmRlci5yZWR1Y2UoKGFjY3UsIGNvbCkgPT4ge1xuICAgIGxldCBzaXplID0gY2VsbFNpemVDYWNoZVtjb2xdLnJvdztcbiAgICBpZiAoY2VsbFNpemVDYWNoZVtjb2xdLnJvdyA8IGNlbGxTaXplQ2FjaGVbY29sXS5oZWFkZXIgJiYgcmVtYWluaW5nID4gMCkge1xuICAgICAgLy8gaWYgd2UgYXJlIGN1dHRpbmcgb2ZmIHRoZSBoZWFkZXIsIGV4cGFuZCB0byBmaXQgaXRcbiAgICAgIHNpemUgPVxuICAgICAgICBjZWxsU2l6ZUNhY2hlW2NvbF0uaGVhZGVyIC0gY2VsbFNpemVDYWNoZVtjb2xdLnJvdyA8IHJlbWFpbmluZ1xuICAgICAgICAgID8gY2VsbFNpemVDYWNoZVtjb2xdLmhlYWRlclxuICAgICAgICAgIDogY2VsbFNpemVDYWNoZVtjb2xdLnJvdyArIHJlbWFpbmluZztcbiAgICAgIHJlbWFpbmluZyAtPSBzaXplIC0gY2VsbFNpemVDYWNoZVtjb2xdLnJvdztcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uYWNjdSxcbiAgICAgIFtjb2xdOiBzaXplXG4gICAgfTtcbiAgfSwge30pO1xuXG4gIGxldCBnaG9zdDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gIGlmIChyZW1haW5pbmcgPiAwICYmIHJlbWFpbmluZyA8IE1JTl9HSE9TVF9DRUxMX1NJWkUpIHtcbiAgICAvLyBleHBhbmQgbGFzdCBjZWxsXG4gICAgY29uc3QgbGFzdENlbGwgPSBjb2x1bW5PcmRlcltjb2x1bW5PcmRlci5sZW5ndGggLSAxXTtcbiAgICBleHBhbmRlZENlbGxTaXplW2xhc3RDZWxsXSArPSByZW1haW5pbmc7XG4gIH0gZWxzZSBpZiAocmVtYWluaW5nID49IE1JTl9HSE9TVF9DRUxMX1NJWkUpIHtcbiAgICAvLyBpZiB0b28gbXVjaCBsZWZ0IGFkZCBhIGdob3N0IGNlbGxcbiAgICBnaG9zdCA9IHJlbWFpbmluZztcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY2VsbFNpemVDYWNoZTogZXhwYW5kZWRDZWxsU2l6ZSxcbiAgICBnaG9zdFxuICB9O1xufVxuXG5mdW5jdGlvbiBhZGRQYWRkaW5nVG9GaXJzdENvbHVtbihcbiAgY2VsbFNpemVDYWNoZTogQ2VsbFNpemVDYWNoZSxcbiAgY29sdW1uT3JkZXI6IHN0cmluZ1tdID0gW11cbik6IENlbGxTaXplQ2FjaGUge1xuICBjb25zdCBmaXJzdENvbCA9IGNvbHVtbk9yZGVyWzBdO1xuXG4gIGlmIChmaXJzdENvbCAmJiBjZWxsU2l6ZUNhY2hlW2ZpcnN0Q29sXSkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5jZWxsU2l6ZUNhY2hlLFxuICAgICAgW2ZpcnN0Q29sXToge1xuICAgICAgICBoZWFkZXI6IGNlbGxTaXplQ2FjaGVbZmlyc3RDb2xdLmhlYWRlciArIEVER0VfQ09MVU1OX1BBRERJTkcsXG4gICAgICAgIHJvdzogY2VsbFNpemVDYWNoZVtmaXJzdENvbF0ucm93ICsgRURHRV9DT0xVTU5fUEFERElOR1xuICAgICAgfVxuICAgIH07XG4gIH1cbiAgcmV0dXJuIGNlbGxTaXplQ2FjaGU7XG59XG5cbi8qKlxuICogQWRqdXN0IGNlbGwgc2l6ZSBiYXNlZCBvbiBjb250YWluZXIgd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBjb250YWluZXJXaWR0aFxuICogQHBhcmFtIHtDZWxsU2l6ZUNhY2hlfSBjZWxsU2l6ZUNhY2hlXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBwaW5uZWRDb2x1bW5zXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSB1bnBpbm5lZENvbHVtbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkanVzdENlbGxzVG9Db250YWluZXIoXG4gIGNvbnRhaW5lcldpZHRoOiBudW1iZXIsXG4gIGNlbGxTaXplQ2FjaGU6IENlbGxTaXplQ2FjaGUsXG4gIHBpbm5lZENvbHVtbnM6IHN0cmluZ1tdLFxuICB1bnBpbm5lZENvbHVtbnM6IHN0cmluZ1tdXG4pOiB7XG4gIGNlbGxTaXplQ2FjaGU6IENlbGxTaXplQ2FjaGU7XG4gIGdob3N0PzogbnVtYmVyIHwgbnVsbDtcbn0ge1xuICBjb25zdCBjb2x1bW5PcmRlciA9IGdldENvbHVtbk9yZGVyKHBpbm5lZENvbHVtbnMsIHVucGlubmVkQ29sdW1ucyk7XG4gIGNvbnN0IHBhZGRlZENlbGxTaXplID0gYWRkUGFkZGluZ1RvRmlyc3RDb2x1bW4oY2VsbFNpemVDYWNoZSwgY29sdW1uT3JkZXIpO1xuICBjb25zdCBtaW5Sb3dTdW0gPSBnZXRTaXplU3VtKHBhZGRlZENlbGxTaXplLCAncm93Jyk7XG5cbiAgaWYgKG1pblJvd1N1bSA+PSBjb250YWluZXJXaWR0aCkge1xuICAgIC8vIHdlIGFwcGx5IHRoZSBtaW4gV2lkdGggdG8gYWxsIGNlbGxzXG4gICAgcmV0dXJuIHtjZWxsU2l6ZUNhY2hlOiBnZXRNaW5DZWxsU2l6ZShwYWRkZWRDZWxsU2l6ZSl9O1xuICB9XG4gIC8vIGlmIHdlIGhhdmUgc29tZSByb29tIHRvIGV4cGFuZFxuICByZXR1cm4gZXhwYW5kQ2VsbFNpemUocGFkZGVkQ2VsbFNpemUsIGNvbHVtbk9yZGVyLCBjb250YWluZXJXaWR0aCwgY29udGFpbmVyV2lkdGggLSBtaW5Sb3dTdW0pO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBR0EsSUFBQUEsU0FBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsTUFBQSxHQUFBRCxPQUFBO0FBQXlFLFNBQUFFLFFBQUFDLENBQUEsRUFBQUMsQ0FBQSxRQUFBQyxDQUFBLEdBQUFDLE1BQUEsQ0FBQUMsSUFBQSxDQUFBSixDQUFBLE9BQUFHLE1BQUEsQ0FBQUUscUJBQUEsUUFBQUMsQ0FBQSxHQUFBSCxNQUFBLENBQUFFLHFCQUFBLENBQUFMLENBQUEsR0FBQUMsQ0FBQSxLQUFBSyxDQUFBLEdBQUFBLENBQUEsQ0FBQUMsTUFBQSxXQUFBTixDQUFBLFdBQUFFLE1BQUEsQ0FBQUssd0JBQUEsQ0FBQVIsQ0FBQSxFQUFBQyxDQUFBLEVBQUFRLFVBQUEsT0FBQVAsQ0FB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Z0IsQ0FBQ0csUUFBUSxDQUFDLElBQUlKLFNBQVM7RUFDekMsQ0FBQyxNQUFNLElBQUlBLFNBQVMsSUFBSXRGLG1CQUFtQixFQUFFO0lBQzNDO0lBQ0F5RixLQUFLLEdBQUdILFNBQVM7RUFDbkI7RUFFQSxPQUFPO0lBQ0xiLGFBQWEsRUFBRWMsZ0JBQWdCO0lBQy9CRSxLQUFLLEVBQUxBO0VBQ0YsQ0FBQztBQUNIO0FBRUEsU0FBU0UsdUJBQXVCQSxDQUM5QmxCLGFBQTRCLEVBRWI7RUFBQSxJQURmVSxXQUFxQixHQUFBMUYsU0FBQSxDQUFBQyxNQUFBLFFBQUFELFNBQUEsUUFBQTRFLFNBQUEsR0FBQTVFLFNBQUEsTUFBRyxFQUFFO0VBRTFCLElBQU1tRyxRQUFRLEdBQUdULFdBQVcsQ0FBQyxDQUFDLENBQUM7RUFFL0IsSUFBSVMsUUFBUSxJQUFJbkIsYUFBYSxDQUFDbUIsUUFBUSxDQUFDLEVBQUU7SUFDdkMsT0FBQXBHLGFBQUEsQ0FBQUEsYUFBQSxLQUNLaUYsYUFBYSxXQUFBN0UsZ0JBQUEsaUJBQ2ZnRyxRQUFRLEVBQUc7TUFDVjdELE1BQU0sRUFBRTBDLGFBQWEsQ0FBQ21CLFFBQVEsQ0FBQyxDQUFDN0QsTUFBTSxHQUFHN0IsbUJBQW1CO01BQzVENEIsR0FBRyxFQUFFMkMsYUFBYSxDQUFDbUIsUUFBUSxDQUFDLENBQUM5RCxHQUFHLEdBQUc1QjtJQUNyQyxDQUFDO0VBRUw7RUFDQSxPQUFPdUUsYUFBYTtBQUN0Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNPLFNBQVNvQixzQkFBc0JBLENBQ3BDVCxjQUFzQixFQUN0QlgsYUFBNEIsRUFDNUJMLGFBQXVCLEVBQ3ZCRSxlQUF5QixFQUl6QjtFQUNBLElBQU1hLFdBQVcsR0FBR2hCLGNBQWMsQ0FBQ0MsYUFBYSxFQUFFRSxlQUFlLENBQUM7RUFDbEUsSUFBTXdCLGNBQWMsR0FBR0gsdUJBQXVCLENBQUNsQixhQUFhLEVBQUVVLFdBQVcsQ0FBQztFQUMxRSxJQUFNWSxTQUFTLEdBQUdsQixVQUFVLENBQUNpQixjQUFjLEVBQUUsS0FBSyxDQUFDO0VBRW5ELElBQUlDLFNBQVMsSUFBSVgsY0FBYyxFQUFFO0lBQy9CO0lBQ0EsT0FBTztNQUFDWCxhQUFhLEVBQUVELGNBQWMsQ0FBQ3NCLGNBQWM7SUFBQyxDQUFDO0VBQ3hEO0VBQ0E7RUFDQSxPQUFPWixjQUFjLENBQUNZLGNBQWMsRUFBRVgsV0FBVyxFQUFFQyxjQUFjLEVBQUVBLGNBQWMsR0FBR1csU0FBUyxDQUFDO0FBQ2hHIiwiaWdub3JlTGlzdCI6W119
;