UNPKG

kepler.gl

Version:

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

183 lines (175 loc) 29.3 kB
"use strict"; 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 _src = require("/Users/ihordykhta/Desktop/unfolded/kepler.gl/src/utils/src"); 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, _src.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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZG9jdW1lbnQiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9zcmMiLCJvd25LZXlzIiwiZSIsInIiLCJ0IiwiT2JqZWN0Iiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJkZWZpbmVQcm9wZXJ0eSIsIk1JTl9HSE9TVF9DRUxMX1NJWkUiLCJNSU5fQ0VMTF9TSVpFIiwiRURHRV9DT0xVTU5fUEFERElORyIsIk1BWF9FTVBUWV9DT0xVTU5fU1BBQ0UiLCJyZW5kZXJlZFNpemUiLCJfcmVmIiwiX3JlZiR0ZXh0IiwidGV4dCIsImRhdGFDb250YWluZXIiLCJjb2x1bW4iLCJfcmVmJHR5cGUiLCJ0eXBlIiwiY29sSWR4IiwiX3JlZiRudW1Sb3dzVG9DYWxjdWxhIiwibnVtUm93c1RvQ2FsY3VsYXRlIiwiX3JlZiRmb250U2l6ZSIsImZvbnRTaXplIiwiX3JlZiRmb250IiwiZm9udCIsIl9yZWYkY2VsbFBhZGRpbmciLCJjZWxsUGFkZGluZyIsIl9yZWYkbWF4Q2VsbFNpemUiLCJtYXhDZWxsU2l6ZSIsIl9yZWYkbWF4SGVhZGVyU2l6ZSIsIm1heEhlYWRlclNpemUiLCJfcmVmJG1pbkNlbGxTaXplIiwibWluQ2VsbFNpemUiLCJfcmVmJG9wdGlvbnNCdXR0b24iLCJvcHRpb25zQnV0dG9uIiwiZG9jdW1lbnQiLCJyb3ciLCJoZWFkZXIiLCJ0ZXh0Q2FudmFzIiwiY3JlYXRlRWxlbWVudCIsImJvZHkiLCJhcHBlbmRDaGlsZCIsImNvbnRleHQiLCJnZXRDb250ZXh0Iiwiam9pbiIsInJvd3NUb1NhbXBsZSIsIl90b0NvbnN1bWFibGVBcnJheTIiLCJBcnJheSIsIm1hcCIsIk1hdGgiLCJmbG9vciIsInJhbmRvbSIsIm51bVJvd3MiLCJmcm9tIiwicm93V2lkdGgiLCJtYXgiLCJyb3dJZHgiLCJ2YWx1ZSIsInBhcnNlRmllbGRWYWx1ZSIsInZhbHVlQXQiLCJ0ZXh0V2lkdGgiLCJtZWFzdXJlVGV4dCIsIndpZHRoIiwiY2VpbCIsImhlYWRlcldpZHRoIiwibWluUm93V2lkdGgiLCJtaW5IZWFkZXJXaWR0aCIsImNsYW1wZWRSb3dXaWR0aCIsImNsYW1wIiwiY2xhbXBlZEhlYWRlcldpZHRoIiwicGFyZW50RWxlbWVudCIsInJlbW92ZUNoaWxkIiwibWluIiwiZ2V0Q29sdW1uT3JkZXIiLCJwaW5uZWRDb2x1bW5zIiwidW5kZWZpbmVkIiwidW5waW5uZWRDb2x1bW5zIiwiY29uY2F0IiwiZ2V0TWluQ2VsbFNpemUiLCJjZWxsU2l6ZUNhY2hlIiwicmVkdWNlIiwiYWNjdSIsImNvbCIsImdldFNpemVTdW0iLCJzaXplQ2FjaGUiLCJrZXkiLCJhY2MiLCJ2YWwiLCJleHBhbmRDZWxsU2l6ZSIsImNvbHVtbk9yZGVyIiwiY29udGFpbmVyV2lkdGgiLCJyb29tVG9GaWxsIiwicmVtYWluaW5nIiwiZXhwYW5kZWRDZWxsU2l6ZSIsInNpemUiLCJnaG9zdCIsImxhc3RDZWxsIiwiYWRkUGFkZGluZ1RvRmlyc3RDb2x1bW4iLCJmaXJzdENvbCIsImFkanVzdENlbGxzVG9Db250YWluZXIiLCJwYWRkZWRDZWxsU2l6ZSIsIm1pblJvd1N1bSJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3NyYy9jb21tb24vZGF0YS10YWJsZS9jZWxsLXNpemUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0IGRvY3VtZW50IGZyb20gJ2dsb2JhbC9kb2N1bWVudCc7XG5pbXBvcnQge0RhdGFDb250YWluZXJJbnRlcmZhY2UsIHBhcnNlRmllbGRWYWx1ZX0gZnJvbSAnQGtlcGxlci5nbC91dGlscyc7XG5cbmNvbnN0IE1JTl9HSE9TVF9DRUxMX1NJWkUgPSAyMDA7XG5jb25zdCBNSU5fQ0VMTF9TSVpFID0gNDU7XG4vLyBmaXJzdCBjb2x1bW4gaGF2ZSBwYWRkaW5nIG9uIHRoZSBsZWZ0XG5jb25zdCBFREdFX0NPTFVNTl9QQURESU5HID0gMTA7XG5cbi8vIGluIGNhc2UgY2VsbCBjb250ZW50IGlzIHNtYWxsLCBjb2x1bW4gbmFtZSBpcyBiaWcsIHdlIGFsbG93IG1heCBlbXB0eSBzcGFjZSB0b1xuLy8gYmUgYWRkZWQgdG8gbWluIGNlbGwgd2lkdGggaW4gb3JkZXIgdG8gc2hvdyBjb2x1bW4gbmFtZVxuY29uc3QgTUFYX0VNUFRZX0NPTFVNTl9TUEFDRSA9IDYwO1xuXG50eXBlIFJlbmRlclNpemVQYXJhbSA9IHtcbiAgdGV4dDoge2RhdGFDb250YWluZXI6IERhdGFDb250YWluZXJJbnRlcmZhY2U7IGNvbHVtbjogc3RyaW5nfTtcbiAgdHlwZT86IHN0cmluZztcbiAgY29sSWR4OiBudW1iZXI7XG4gIG51bVJvd3NUb0NhbGN1bGF0ZT86IG51bWJlcjtcbiAgZm9udFNpemU/OiBudW1iZXI7XG4gIGZvbnQ/OiBzdHJpbmc7XG4gIGNlbGxQYWRkaW5nPzogbnVtYmVyO1xuICBtYXhDZWxsU2l6ZT86IG51bWJlcjtcbiAgbWF4SGVhZGVyU2l6ZT86IG51bWJlcjtcbiAgbWluQ2VsbFNpemU/OiBudW1iZXI7XG4gIG9wdGlvbnNCdXR0b24/OiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBDZWxsU2l6ZUNhY2hlID0ge1xuICBba2V5OiBzdHJpbmddOiB7XG4gICAgcm93OiBudW1iZXI7XG4gICAgaGVhZGVyOiBudW1iZXI7XG4gIH07XG59O1xuXG4vKipcbiAqIE1lYXN1cmUgcm93cyBhbmQgY29sdW1uIGNvbnRlbnQgdG8gZGV0ZXJtaW5lIG1pbiB3aWR0aCBmb3IgZWFjaCBjb2x1bW5cbiAqIEBwYXJhbSB7UmVuZGVyU2l6ZVBhcmFtfSBwYXJhbTBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlcmVkU2l6ZSh7XG4gIHRleHQ6IHtkYXRhQ29udGFpbmVyLCBjb2x1bW59LFxuICB0eXBlID0gJ3N0cmluZycsXG4gIGNvbElkeCxcbiAgbnVtUm93c1RvQ2FsY3VsYXRlID0gMTAsXG4gIGZvbnRTaXplID0gMTIsXG4gIGZvbnQgPSAnTGF0bycsXG4gIGNlbGxQYWRkaW5nID0gNDAsXG4gIG1heENlbGxTaXplID0gNTAwLFxuICBtYXhIZWFkZXJTaXplID0gNTAwLFxuICBtaW5DZWxsU2l6ZSA9IE1JTl9DRUxMX1NJWkUsXG4gIG9wdGlvbnNCdXR0b24gPSA0NFxufTogUmVuZGVyU2l6ZVBhcmFtKToge3JvdzogbnVtYmVyOyBoZWFkZXI6IG51bWJlcn0ge1xuICBpZiAoIWRvY3VtZW50KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJvdzogMCxcbiAgICAgIGhlYWRlcjogMFxuICAgIH07XG4gIH1cblxuICBjb25zdCB0ZXh0Q2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGV4dENhbnZhcyk7XG4gIGNvbnN0IGNvbnRleHQgPSB0ZXh0Q2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gIGNvbnRleHQuZm9udCA9IFtmb250U2l6ZSwgZm9udF0uam9pbigncHggJyk7XG5cbiAgbGV0IHJvd3NUb1NhbXBsZSA9IFsuLi5BcnJheShudW1Sb3dzVG9DYWxjdWxhdGUpXS5tYXAoKCkgPT5cbiAgICBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAoZGF0YUNvbnRhaW5lci5udW1Sb3dzKCkgLSAxKSlcbiAgKTtcblxuICAvLyBJZiB3ZSBoYXZlIGxlc3MgdGhhbiAxMCByb3dzLCBsZXRzIG1lYXN1cmUgYWxsIG9mIHRoZW1cbiAgaWYgKGRhdGFDb250YWluZXIubnVtUm93cygpIDw9IG51bVJvd3NUb0NhbGN1bGF0ZSkge1xuICAgIHJvd3NUb1NhbXBsZSA9IEFycmF5LmZyb20oQXJyYXkoZGF0YUNvbnRhaW5lci5udW1Sb3dzKCkpLmtleXMoKSk7XG4gIH1cbiAgY29uc3Qgcm93V2lkdGggPSBNYXRoLm1heChcbiAgICAuLi5yb3dzVG9TYW1wbGUubWFwKHJvd0lkeCA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHBhcnNlRmllbGRWYWx1ZShkYXRhQ29udGFpbmVyLnZhbHVlQXQocm93SWR4LCBjb2xJZHgpLCB0eXBlKTtcbiAgICAgIC8vIG1lYXN1cmluZyBsYXJnZSB0ZXh0IGNhdXNlIHNsb3cgcGVyZm9ybWFuY2VcbiAgICAgIGlmICh2YWx1ZS5sZW5ndGggPiBtYXhDZWxsU2l6ZSkge1xuICAgICAgICByZXR1cm4gbWF4Q2VsbFNpemU7XG4gICAgICB9XG4gICAgICBjb25zdCB0ZXh0V2lkdGggPSBjb250ZXh0Lm1lYXN1cmVUZXh0KHZhbHVlKS53aWR0aDtcbiAgICAgIHJldHVybiBNYXRoLmNlaWwodGV4dFdpZHRoKSArIGNlbGxQYWRkaW5nO1xuICAgIH0pXG4gICk7XG4gIC8vIGhlYWRlciBjZWxsIG9ubHkgaGFzIGxlZnQgcGFkZGluZ1xuICBjb25zdCBoZWFkZXJXaWR0aCA9XG4gICAgTWF0aC5jZWlsKGNvbnRleHQubWVhc3VyZVRleHQoY29sdW1uKS53aWR0aCkgKyBjZWxsUGFkZGluZyAvIDIgKyBvcHRpb25zQnV0dG9uO1xuXG4gIC8vIG1pbiByb3cgd2lkdGggaXMgbWVhc3VyZWQgYnkgY2VsbCBjb250ZW50XG4gIGNvbnN0IG1pblJvd1dpZHRoID0gbWluQ2VsbFNpemUgKyBjZWxsUGFkZGluZztcbiAgLy8gbWluIGhlYWRlciB3aWR0aCBpcyBtZWFzdXJlZCBieSBjZWxsXG4gIGNvbnN0IG1pbkhlYWRlcldpZHRoID0gbWluQ2VsbFNpemUgKyBjZWxsUGFkZGluZyAvIDIgKyBvcHRpb25zQnV0dG9uO1xuXG4gIGNvbnN0IGNsYW1wZWRSb3dXaWR0aCA9IGNsYW1wKG1pblJvd1dpZHRoLCBtYXhDZWxsU2l6ZSwgcm93V2lkdGgpO1xuICBjb25zdCBjbGFtcGVkSGVhZGVyV2lkdGggPSBjbGFtcChtaW5IZWFkZXJXaWR0aCwgbWF4SGVhZGVyU2l6ZSwgaGVhZGVyV2lkdGgpO1xuXG4gIC8vIGNsZWFudXBcbiAgdGV4dENhbnZhcy5wYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKHRleHRDYW52YXMpO1xuXG4gIHJldHVybiB7XG4gICAgcm93OiBjbGFtcGVkUm93V2lkdGgsXG4gICAgaGVhZGVyOiBjbGFtcGVkSGVhZGVyV2lkdGhcbiAgfTtcbn1cblxuZnVuY3Rpb24gY2xhbXAobWluLCBtYXgsIHZhbHVlKSB7XG4gIHJldHVybiBNYXRoLm1heChNYXRoLm1pbihtYXgsIHZhbHVlKSwgbWluKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q29sdW1uT3JkZXIocGlubmVkQ29sdW1uczogc3RyaW5nW10gPSBbXSwgdW5waW5uZWRDb2x1bW5zOiBzdHJpbmdbXSA9IFtdKSB7XG4gIHJldHVybiBbLi4ucGlubmVkQ29sdW1ucywgLi4udW5waW5uZWRDb2x1bW5zXTtcbn1cblxuLy8gSWYgdG90YWwgbWluIGNlbGwgc2l6ZSBpcyBiaWdnZXIgdGhhbiBjb250YWluZXJXaWR0aCBhZGp1c3QgY29sdW1uXG5mdW5jdGlvbiBnZXRNaW5DZWxsU2l6ZShjZWxsU2l6ZUNhY2hlOiBDZWxsU2l6ZUNhY2hlKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhjZWxsU2l6ZUNhY2hlKS5yZWR1Y2UoXG4gICAgKGFjY3UsIGNvbCkgPT4gKHtcbiAgICAgIC4uLmFjY3UsXG4gICAgICAvLyBpZiByb3cgaXMgbGFyZ2VyIHRoYW4gaGVhZGVyLCB1c2Ugcm93XG4gICAgICBbY29sXTpcbiAgICAgICAgY2VsbFNpemVDYWNoZVtjb2xdLnJvdyA+IGNlbGxTaXplQ2FjaGVbY29sXS5oZWFkZXJcbiAgICAgICAgICA/IGNlbGxTaXplQ2FjaGVbY29sXS5yb3dcbiAgICAgICAgICA6IC8vIGlmIHJvdyBpcyBzbWFsbGVyIHRoYW4gaGVhZGVyLCB1c2UgdGhlIHNtYWxsZXIgb2YgTUFYX0VNUFRZX0NPTFVNTl9TUEFDRSArIHJvdyB3aWR0aCBhbmQgaGVhZGVyXG4gICAgICAgICAgICBNYXRoLm1pbihjZWxsU2l6ZUNhY2hlW2NvbF0uaGVhZGVyLCBjZWxsU2l6ZUNhY2hlW2NvbF0ucm93ICsgTUFYX0VNUFRZX0NPTFVNTl9TUEFDRSlcbiAgICB9KSxcbiAgICB7fVxuICApO1xufVxuXG5mdW5jdGlvbiBnZXRTaXplU3VtKHNpemVDYWNoZSwga2V5KSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhzaXplQ2FjaGUpLnJlZHVjZShcbiAgICAoYWNjLCB2YWwpID0+IGFjYyArIChrZXkgPyBzaXplQ2FjaGVbdmFsXVtrZXldIDogc2l6ZUNhY2hlW3ZhbF0pLFxuICAgIDBcbiAgKTtcbn1cblxuLyoqXG4gKiBFeHBhbmQgY2VsbCB0byBmaXQgYm90aCByb3cgYW5kIGhlYWRlciwgaWYgdGhlcmUgaXMgc3RpbGwgcm9vbSBsZWZ0LFxuICogZXhwYW5kIGxhc3QgY2VsbCB0byBmaXQgdGhlIGVudGlyZSB3aWR0aCBvZiB0aGUgY29udGFpbmVyXG4gKiBAcGFyYW0ge0NlbGxTaXplQ2FjaGV9IGNlbGxTaXplQ2FjaGVcbiAqIEBwYXJhbSB7c3RyaW5nW119IGNvbHVtbk9yZGVyXG4gKiBAcGFyYW0ge251bWJlcn0gY29udGFpbmVyV2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSByb29tVG9GaWxsXG4gKi9cbmZ1bmN0aW9uIGV4cGFuZENlbGxTaXplKFxuICBjZWxsU2l6ZUNhY2hlOiBDZWxsU2l6ZUNhY2hlLFxuICBjb2x1bW5PcmRlcjogc3RyaW5nW10sXG4gIGNvbnRhaW5lcldpZHRoOiBudW1iZXIsXG4gIHJvb21Ub0ZpbGw6IG51bWJlclxuKToge1xuICBjZWxsU2l6ZUNhY2hlOiBDZWxsU2l6ZUNhY2hlO1xuICBnaG9zdDogbnVtYmVyIHwgbnVsbDtcbn0ge1xuICBsZXQgcmVtYWluaW5nID0gcm9vbVRvRmlsbDtcblxuICBjb25zdCBleHBhbmRlZENlbGxTaXplID0gY29sdW1uT3JkZXIucmVkdWNlKChhY2N1LCBjb2wpID0+IHtcbiAgICBsZXQgc2l6ZSA9IGNlbGxTaXplQ2FjaGVbY29sXS5yb3c7XG4gICAgaWYgKGNlbGxTaXplQ2FjaGVbY29sXS5yb3cgPCBjZWxsU2l6ZUNhY2hlW2NvbF0uaGVhZGVyICYmIHJlbWFpbmluZyA+IDApIHtcbiAgICAgIC8vIGlmIHdlIGFyZSBjdXR0aW5nIG9mZiB0aGUgaGVhZGVyLCBleHBhbmQgdG8gZml0IGl0XG4gICAgICBzaXplID1cbiAgICAgICAgY2VsbFNpemVDYWNoZVtjb2xdLmhlYWRlciAtIGNlbGxTaXplQ2FjaGVbY29sXS5yb3cgPCByZW1haW5pbmdcbiAgICAgICAgICA/IGNlbGxTaXplQ2FjaGVbY29sXS5oZWFkZXJcbiAgICAgICAgICA6IGNlbGxTaXplQ2FjaGVbY29sXS5yb3cgKyByZW1haW5pbmc7XG4gICAgICByZW1haW5pbmcgLT0gc2l6ZSAtIGNlbGxTaXplQ2FjaGVbY29sXS5yb3c7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmFjY3UsXG4gICAgICBbY29sXTogc2l6ZVxuICAgIH07XG4gIH0sIHt9KTtcblxuICBsZXQgZ2hvc3Q6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBpZiAocmVtYWluaW5nID4gMCAmJiByZW1haW5pbmcgPCBNSU5fR0hPU1RfQ0VMTF9TSVpFKSB7XG4gICAgLy8gZXhwYW5kIGxhc3QgY2VsbFxuICAgIGNvbnN0IGxhc3RDZWxsID0gY29sdW1uT3JkZXJbY29sdW1uT3JkZXIubGVuZ3RoIC0gMV07XG4gICAgZXhwYW5kZWRDZWxsU2l6ZVtsYXN0Q2VsbF0gKz0gcmVtYWluaW5nO1xuICB9IGVsc2UgaWYgKHJlbWFpbmluZyA+PSBNSU5fR0hPU1RfQ0VMTF9TSVpFKSB7XG4gICAgLy8gaWYgdG9vIG11Y2ggbGVmdCBhZGQgYSBnaG9zdCBjZWxsXG4gICAgZ2hvc3QgPSByZW1haW5pbmc7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGNlbGxTaXplQ2FjaGU6IGV4cGFuZGVkQ2VsbFNpemUsXG4gICAgZ2hvc3RcbiAgfTtcbn1cblxuZnVuY3Rpb24gYWRkUGFkZGluZ1RvRmlyc3RDb2x1bW4oXG4gIGNlbGxTaXplQ2FjaGU6IENlbGxTaXplQ2FjaGUsXG4gIGNvbHVtbk9yZGVyOiBzdHJpbmdbXSA9IFtdXG4pOiBDZWxsU2l6ZUNhY2hlIHtcbiAgY29uc3QgZmlyc3RDb2wgPSBjb2x1bW5PcmRlclswXTtcblxuICBpZiAoZmlyc3RDb2wgJiYgY2VsbFNpemVDYWNoZVtmaXJzdENvbF0pIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uY2VsbFNpemVDYWNoZSxcbiAgICAgIFtmaXJzdENvbF06IHtcbiAgICAgICAgaGVhZGVyOiBjZWxsU2l6ZUNhY2hlW2ZpcnN0Q29sXS5oZWFkZXIgKyBFREdFX0NPTFVNTl9QQURESU5HLFxuICAgICAgICByb3c6IGNlbGxTaXplQ2FjaGVbZmlyc3RDb2xdLnJvdyArIEVER0VfQ09MVU1OX1BBRERJTkdcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIHJldHVybiBjZWxsU2l6ZUNhY2hlO1xufVxuXG4vKipcbiAqIEFkanVzdCBjZWxsIHNpemUgYmFzZWQgb24gY29udGFpbmVyIHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gY29udGFpbmVyV2lkdGhcbiAqIEBwYXJhbSB7Q2VsbFNpemVDYWNoZX0gY2VsbFNpemVDYWNoZVxuICogQHBhcmFtIHtzdHJpbmdbXX0gcGlubmVkQ29sdW1uc1xuICogQHBhcmFtIHtzdHJpbmdbXX0gdW5waW5uZWRDb2x1bW5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGp1c3RDZWxsc1RvQ29udGFpbmVyKFxuICBjb250YWluZXJXaWR0aDogbnVtYmVyLFxuICBjZWxsU2l6ZUNhY2hlOiBDZWxsU2l6ZUNhY2hlLFxuICBwaW5uZWRDb2x1bW5zOiBzdHJpbmdbXSxcbiAgdW5waW5uZWRDb2x1bW5zOiBzdHJpbmdbXVxuKToge1xuICBjZWxsU2l6ZUNhY2hlOiBDZWxsU2l6ZUNhY2hlO1xuICBnaG9zdD86IG51bWJlciB8IG51bGw7XG59IHtcbiAgY29uc3QgY29sdW1uT3JkZXIgPSBnZXRDb2x1bW5PcmRlcihwaW5uZWRDb2x1bW5zLCB1bnBpbm5lZENvbHVtbnMpO1xuICBjb25zdCBwYWRkZWRDZWxsU2l6ZSA9IGFkZFBhZGRpbmdUb0ZpcnN0Q29sdW1uKGNlbGxTaXplQ2FjaGUsIGNvbHVtbk9yZGVyKTtcbiAgY29uc3QgbWluUm93U3VtID0gZ2V0U2l6ZVN1bShwYWRkZWRDZWxsU2l6ZSwgJ3JvdycpO1xuXG4gIGlmIChtaW5Sb3dTdW0gPj0gY29udGFpbmVyV2lkdGgpIHtcbiAgICAvLyB3ZSBhcHBseSB0aGUgbWluIFdpZHRoIHRvIGFsbCBjZWxsc1xuICAgIHJldHVybiB7Y2VsbFNpemVDYWNoZTogZ2V0TWluQ2VsbFNpemUocGFkZGVkQ2VsbFNpemUpfTtcbiAgfVxuICAvLyBpZiB3ZSBoYXZlIHNvbWUgcm9vbSB0byBleHBhbmRcbiAgcmV0dXJuIGV4cGFuZENlbGxTaXplKHBhZGRlZENlbGxTaXplLCBjb2x1bW5PcmRlciwgY29udGFpbmVyV2lkdGgsIGNvbnRhaW5lcldpZHRoIC0gbWluUm93U3VtKTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUdBLElBQUFBLFNBQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLElBQUEsR0FBQUQsT0FBQTtBQUF5RSxTQUFBRSxRQUFBQyxDQUFBLEVBQUFDLENBQUEsUUFBQUMsQ0FBQSxHQUFBQyxNQUFBLENBQUFDLElBQUEsQ0FBQUosQ0FBQSxPQUFBRyxNQUFBLENBQUFFLHFCQUFBLFFBQUFDLENBQUEsR0FBQUgsTUFBQSxDQUFBRSxxQkFBQSxDQUFBTCxDQUFBLEdBQUFDLENBQUEsS0FBQUssQ0FBQSxHQUFBQSxDQUFBLENBQUFDLE1BQUEsV0FBQU4sQ0FBQSxXQUFBRSxNQUFBLENBQUFLLHdCQUFBLENBQUFSLENBQUEsRUFBQUMsQ0FBQSxFQUFBUSxVQUFBLE9BQUFQLENBQUEsQ0FBQVEsSUFBQSxDQUFBQyxLQUFBLENBQUFULENBQUEsRUFBQUksQ0FBQSxZQUFBSixDQUFBO0FBQUEsU0FBQVUsY0FBQVosQ0FBQSxhQUFBQyxDQUFBLE1BQUFBLENBQUEsR0FBQVksU0FBQSxDQUFBQyxNQUFBLEVBQUFiLENBQUEsVUFBQUMsQ0FBQSxXQUFBVyxTQUFBLENBQUFaLENBQUEsSUFBQVksU0FBQSxDQUFBWixDQUFBLFFBQUFBLENBQUEsT0FBQUYsT0FBQSxDQUFBSSxNQUFBLENBQUFELENBQUEsT0FBQWEsT0FBQSxXQUFBZCxDQUFBLFFBQUFlLGdCQUFBLGFBQUFoQixDQUFBLEVBQUFDLENBQUEsRUFBQUMsQ0FBQSxDQUFBRCxDQUFBLFNBQUFFLE1BQUEsQ0FBQWMseUJBQUEsR0FBQWQsTUFBQSxDQUFBZSxnQkFBQSxDQUFBbEIsQ0FBQSxFQUFBRyxNQUFBLENBQUFjLHlCQUFBLENBQUFmLENBQUEsS0FBQUgsT0FBQSxDQUFBSSxNQUFBLENBQUFELENBQUEsR0FBQWEsT0FBQSxXQUFBZCxDQUFBLElBQUFFLE1BQUEsQ0FBQWdCLGNBQUEsQ0FBQW5CLENBQUEsRUFBQUMsQ0FBQSxFQUFBRSxNQUFBLENBQUFLLHdCQUFBLENBQUFOLENBQUEsRUFBQUQsQ0FBQSxpQkFBQUQsQ0FBQSxJQUp6RTtBQUNBO0FBS0EsSUFBTW9CLG1CQUFtQixHQUFHLEdBQUc7QUFDL0IsSUFBTUMsYUFBYSxHQUFHLEVBQUU7QUFDeEI7QUFDQSxJQUFNQyxtQkFBbUIsR0FBRyxFQUFFOztBQUU5QjtBQUNBO0FBQ0EsSUFBTUMsc0JBQXNCLEdBQUcsRUFBRTtBQXVCakM7QUFDQTtBQUNBO0FBQ0E7QUFDTyxTQUFTQyxZQUFZQSxDQUFBQyxJQUFBLEVBWXVCO0VBQUEsSUFBQUMsU0FBQSxHQUFBRCxJQUFBLENBWGpERSxJQUFJO0lBQUdDLGFBQWEsR0FBQUYsU0FBQSxDQUFiRSxhQUFhO0lBQUVDLE1BQU0sR0FBQUgsU0FBQSxDQUFORyxNQUFNO0lBQUFDLFNBQUEsR0FBQUwsSUFBQSxDQUM1Qk0sSUFBSTtJQUFKQSxJQUFJLEdBQUFELFNBQUEsY0FBRyxRQUFRLEdBQUFBLFNBQUE7SUFDZkUsTUFBTSxHQUFBUCxJQUFBLENBQU5PLE1BQU07SUFBQUMscUJBQUEsR0FBQVIsSUFBQSxDQUNOUyxrQkFBa0I7SUFBbEJBLGtCQUFrQixHQUFBRCxxQkFBQSxjQUFHLEVBQUUsR0FBQUEscUJBQUE7SUFBQUUsYUFBQSxHQUFBVixJQUFBLENBQ3ZCVyxRQUFRO0lBQVJBLFFBQVEsR0FBQUQsYUFBQSxjQUFHLEVBQUUsR0FBQUEsYUFBQTtJQUFBRSxTQUFBLEdBQUFaLElBQUEsQ0FDYmEsSUFBSTtJQUFKQSxJQUFJLEdBQUFELFNBQUEsY0FBRyxNQUFNLEdBQUFBLFNBQUE7SUFBQUUsZ0JBQUEsR0FBQWQsSUFBQSxDQUNiZSxXQUFXO0lBQVhBLFdBQVcsR0FBQUQsZ0JBQUEsY0FBRyxFQUFFLEdBQUFBLGdCQUFBO0lBQUFFLGdCQUFBLEdBQUFoQixJQUFBLENBQ2hCaUIsV0FBVztJQUFYQSxXQUFXLEdBQUFELGdCQUFBLGNBQUcsR0FBRyxHQUFBQSxnQkFBQTtJQUFBRSxrQkFBQSxHQUFBbEIsSUFBQSxDQUNqQm1CLGFBQWE7SUFBYkEsYUFBYSxHQUFBRCxrQkFBQSxjQUFHLEdBQUcsR0FBQUEsa0JBQUE7SUFBQUUsZ0JBQUEsR0FBQXBCLElBQUEsQ0FDbkJxQixXQUFXO0lBQVhBLFdBQVcsR0FBQUQsZ0JBQUEsY0FBR3hCLGFBQWEsR0FBQXdCLGdCQUFBO0lBQUFFLGtCQUFBLEdBQUF0QixJQUFBLENBQzNCdUIsYUFBYTtJQUFiQSxhQUFhLEdBQUFELGtCQUFBLGNBQUcsRUFBRSxHQUFBQSxrQkFBQTtFQUVsQixJQUFJLENBQUNFLG9CQUFRLEVBQUU7SUFDYixPQUFPO01BQ0xDLEdBQUcsRUFBRSxDQUFDO01BQ05DLE1BQU0sRUFBRTtJQUNWLENBQUM7RUFDSDtFQUVBLElBQU1DLFVBQVUsR0FBR0gsb0JBQVEsQ0FBQ0ksYUFBYSxDQUFDLFFBQVEsQ0FBQztFQUNuREosb0JBQVEsQ0FBQ0ssSUFBSSxDQUFDQyxXQUFXLENBQUNILFVBQVUsQ0FBQztFQUNyQyxJQUFNSSxPQUFPLEdBQUdKLFVBQVUsQ0FBQ0ssVUFBVSxDQUFDLElBQUksQ0FBQztFQUMzQ0QsT0FBTyxDQUFDbEIsSUFBSSxHQUFHLENBQUNGLFFBQVEsRUFBRUUsSUFBSSxDQUFDLENBQUNvQixJQUFJLENBQUMsS0FBSyxDQUFDO0VBRTNDLElBQUlDLFlBQVksR0FBRyxJQUFBQyxtQkFBQSxhQUFJQyxLQUFLLENBQUMzQixrQkFBa0IsQ0FBQyxFQUFFNEIsR0FBRyxDQUFDO0lBQUEsT0FDcERDLElBQUksQ0FBQ0MsS0FBSyxDQUFDRCxJQUFJLENBQUNFLE1BQU0sQ0FBQyxDQUFDLElBQUlyQyxhQUFhLENBQUNzQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0VBQUEsQ0FDM0QsQ0FBQzs7RUFFRDtFQUNBLElBQUl0QyxhQUFhLENBQUNzQyxPQUFPLENBQUMsQ0FBQyxJQUFJaEMsa0JBQWtCLEVBQUU7SUFDakR5QixZQUFZLEdBQUdFLEtBQUssQ0FBQ00sSUFBSSxDQUFDTixLQUFLLENBQUNqQyxhQUFhLENBQUNzQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM5RCxJQUFJLENBQUMsQ0FBQyxDQUFDO0VBQ2xFO0VBQ0EsSUFBTWdFLFFBQVEsR0FBR0wsSUFBSSxDQUFDTSxHQUFHLENBQUExRCxLQUFBLENBQVJvRCxJQUFJLE1BQUFILG1CQUFBLGFBQ2hCRCxZQUFZLENBQUNHLEdBQUcsQ0FBQyxVQUFBUSxNQUFNLEVBQUk7SUFDNUIsSUFBTUMsS0FBSyxHQUFHLElBQUFDLG9CQUFlLEVBQUM1QyxhQUFhLENBQUM2QyxPQUFPLENBQUNILE1BQU0sRUFBRXRDLE1BQU0sQ0FBQyxFQUFFRCxJQUFJLENBQUM7SUFDMUU7SUFDQSxJQUFJd0MsS0FBSyxDQUFDekQsTUFBTSxHQUFHNEIsV0FBVyxFQUFFO01BQzlCLE9BQU9BLFdBQVc7SUFDcEI7SUFDQSxJQUFNZ0MsU0FBUyxHQUFHbEIsT0FBTyxDQUFDbUIsV0FBVyxDQUFDSixLQUFLLENBQUMsQ0FBQ0ssS0FBSztJQUNsRCxPQUFPYixJQUFJLENBQUNjLElBQUksQ0FBQ0gsU0FBUyxDQUFDLEdBQUdsQyxXQUFXO0VBQzNDLENBQUMsQ0FBQyxDQUNKLENBQUM7RUFDRDtFQUNBLElBQU1zQyxXQUFXLEdBQ2ZmLElBQUksQ0FBQ2MsSUFBSSxDQUFDckIsT0FBTyxDQUFDbUIsV0FBVyxDQUFDOUMsTUFBTSxDQUFDLENBQUMrQyxLQUFLLENBQUMsR0FBR3BDLFdBQVcsR0FBRyxDQUFDLEdBQUdRLGFBQWE7O0VBRWhGO0VBQ0EsSUFBTStCLFdBQVcsR0FBR2pDLFdBQVcsR0FBR04sV0FBVztFQUM3QztFQUNBLElBQU13QyxjQUFjLEdBQUdsQyxXQUFXLEdBQUdOLFdBQVcsR0FBRyxDQUFDLEdBQUdRLGFBQWE7RUFFcEUsSUFBTWlDLGVBQWUsR0FBR0MsS0FBSyxDQUFDSCxXQUFXLEVBQUVyQyxXQUFXLEVBQUUwQixRQUFRLENBQUM7RUFDakUsSUFBTWUsa0JBQWtCLEdBQUdELEtBQUssQ0FBQ0YsY0FBYyxFQUFFcEMsYUFBYSxFQUFFa0MsV0FBVyxDQUFDOztFQUU1RTtFQUNBMUIsVUFBVSxDQUFDZ0MsYUFBYSxDQUFDQyxXQUFXLENBQUNqQyxVQUFVLENBQUM7RUFFaEQsT0FBTztJQUNMRixHQUFHLEVBQUUrQixlQUFlO0lBQ3BCOUIsTUFBTSxFQUFFZ0M7RUFDVixDQUFDO0FBQ0g7QUFFQSxTQUFTRCxLQUFLQSxDQUFDSSxHQUFHLEVBQUVqQixHQUFHLEVBQUVFLEtBQUssRUFBRTtFQUM5QixPQUFPUixJQUFJLENBQUNNLEdBQUcsQ0FBQ04sSUFBSSxDQUFDdUIsR0FBRyxDQUFDakIsR0FBRyxFQUFFRSxLQUFLLENBQUMsRUFBRWUsR0FBRyxDQUFDO0FBQzVDO0FBRUEsU0FBU0MsY0FBY0EsQ0FBQSxFQUErRDtFQUFBLElBQTlEQyxhQUF1QixHQUFBM0UsU0FBQSxDQUFBQyxNQUFBLFFBQUFELFNBQUEsUUFBQTRFLFNBQUEsR0FBQTVFLFNBQUEsTUFBRyxFQUFFO0VBQUEsSUFBRTZFLGVBQXlCLEdBQUE3RSxTQUFBLENBQUFDLE1BQUEsUUFBQUQsU0FBQSxRQUFBNEUsU0FBQSxHQUFBNUUsU0FBQSxNQUFHLEVBQUU7RUFDbEYsVUFBQThFLE1BQUEsS0FBQS9CLG1CQUFBLGFBQVc0QixhQUFhLE9BQUE1QixtQkFBQSxhQUFLOEIsZUFBZTtBQUM5Qzs7QUFFQTtBQUNBLFNBQVNFLGNBQWNBLENBQUNDLGFBQTRCLEVBQUU7RUFDcEQsT0FBTzFGLE1BQU0sQ0FBQ0MsSUFBSSxDQUFDeUYsYUFBYSxDQUFDLENBQUNDLE1BQU0sQ0FDdEMsVUFBQ0MsSUFBSSxFQUFFQyxHQUFHO0lBQUEsT0FBQXBGLGFBQUEsQ0FBQUEsYUFBQSxLQUNMbUYsSUFBSSxXQUFBL0UsZ0JBQUEsaUJBRU5nRixHQUFHLEVBQ0ZILGFBQWEsQ0FBQ0csR0FBRyxDQUFDLENBQUM5QyxHQUFHLEdBQUcyQyxhQUFhLENBQUNHLEdBQUcsQ0FBQyxDQUFDN0MsTUFBTSxHQUM5QzBDLGFBQWEsQ0FBQ0csR0FBRyxDQUFDLENBQUM5QyxHQUFHO0lBQ3RCO0lBQ0FhLElBQUksQ0FBQ3VCLEdBQUcsQ0FBQ08sYUFBYSxDQUFDRyxHQUFHLENBQUMsQ0FBQzdDLE1BQU0sRUFBRTBDLGFBQWEsQ0FBQ0csR0FBRyxDQUFDLENBQUM5QyxHQUFHLEdBQUczQixzQkFBc0IsQ0FBQztFQUFBLENBQzFGLEVBQ0YsQ0FBQyxDQUNILENBQUM7QUFDSDtBQUVBLFNBQVMwRSxVQUFVQSxDQUFDQyxTQUFTLEVBQUVDLEdBQUcsRUFBRTtFQUNsQyxPQUFPaEcsTUFBTSxDQUFDQyxJQUFJLENBQUM4RixTQUFTLENBQUMsQ0FBQ0osTUFBTSxDQUNsQyxVQUFDTSxHQUFHLEVBQUVDLEdBQUc7SUFBQSxPQUFLRCxHQUFHLElBQUlELEdBQUcsR0FBR0QsU0FBUyxDQUFDRyxHQUFHLENBQUMsQ0FBQ0YsR0FBRyxDQUFDLEdBQUdELFNBQVMsQ0FBQ0csR0FBRyxDQUFDLENBQUM7RUFBQSxHQUNoRSxDQUNGLENBQUM7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsY0FBY0EsQ0FDckJULGFBQTRCLEVBQzVCVSxXQUFxQixFQUNyQkMsY0FBc0IsRUFDdEJDLFVBQWtCLEVBSWxCO0VBQ0EsSUFBSUMsU0FBUyxHQUFHRCxVQUFVO0VBRTFCLElBQU1FLGdCQUFnQixHQUFHSixXQUFXLENBQUNULE1BQU0sQ0FBQyxVQUFDQyxJQUFJLEVBQUVDLEdBQUcsRUFBSztJQUN6RCxJQUFJWSxJQUFJLEdBQUdmLGFBQWEsQ0FBQ0csR0FBRyxDQUFDLENBQUM5QyxHQUFHO0lBQ2pDLElBQUkyQyxhQUFhLENBQUNHLEdBQUcsQ0FBQyxDQUFDOUMsR0FBRyxHQUFHMkMsYUFBYSxDQUFDRyxHQUFHLENBQUMsQ0FBQzdDLE1BQU0sSUFBSXVELFNBQVMsR0FBRyxDQUFDLEVBQUU7TUFDdkU7TUFDQUUsSUFBSSxHQUNGZixhQUFhLENBQUNHLEdBQUcsQ0FBQyxDQUFDN0MsTUFBTSxHQUFHMEMsYUFBYSxDQUFDRyxHQUFHLENBQUMsQ0FBQzlDLEdBQUcsR0FBR3dELFNBQVMsR0FDMURiLGFBQWEsQ0FBQ0csR0FBRyxDQUFDLENBQUM3QyxNQUFNLEdBQ3pCMEMsYUFBYSxDQUFDRyxHQUFHLENBQUMsQ0FBQzlDLEdBQUcsR0FBR3dELFNBQVM7TUFDeENBLFNBQVMsSUFBSUUsSUFBSSxHQUFHZixhQUFhLENBQUNHLEdBQUcsQ0FBQyxDQUFDOUMsR0FBRztJQUM1QztJQUVBLE9BQUF0QyxhQUFBLENBQUFBLGFBQUEsS0FDS21GLElBQUksV0FBQS9FLGdCQUFBLGlCQUNOZ0YsR0FBRyxFQUFHWSxJQUFJO0VBRWYsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0VBRU4sSUFBSUMsS0FBb0IsR0FBRyxJQUFJO0VBQy9CLElBQUlILFNBQVMsR0FBRyxDQUFDLElBQUlBLFNBQVMsR0FBR3RGLG1CQUFtQixFQUFFO0lBQ3BEO0lBQ0EsSUFBTTBGLFFBQVEsR0FBR1AsV0FBVyxDQUFDQSxXQUFXLENBQUN6RixNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ3BENkYsZ0JBQWdCLENBQUNHLFFBQVEsQ0FBQyxJQUFJSixTQUFTO0VBQ3pDLENBQUMsTUFBTSxJQUFJQSxTQUFTLElBQUl0RixtQkFBbUIsRUFBRTtJQUMzQztJQUNBeUYsS0FBSyxHQUFHSCxTQUFTO0VBQ25CO0VBRUEsT0FBTztJQUNMYixhQUFhLEVBQUVjLGdCQUFnQjtJQUMvQkUsS0FBSyxFQUFMQTtFQUNGLENBQUM7QUFDSDtBQUVBLFNBQVNFLHVCQUF1QkEsQ0FDOUJsQixhQUE0QixFQUViO0VBQUEsSUFEZlUsV0FBcUIsR0FBQTFGLFNBQUEsQ0FBQUMsTUFBQSxRQUFBRCxTQUFBLFFBQUE0RSxTQUFBLEdBQUE1RSxTQUFBLE1BQUcsRUFBRTtFQUUxQixJQUFNbUcsUUFBUSxHQUFHVCxXQUFXLENBQUMsQ0FBQyxDQUFDO0VBRS9CLElBQUlTLFFBQVEsSUFBSW5CLGFBQWEsQ0FBQ21CLFFBQVEsQ0FBQyxFQUFFO0lBQ3ZDLE9BQUFwRyxhQUFBLENBQUFBLGFBQUEsS0FDS2lGLGFBQWEsV0FBQTdFLGdCQUFBLGlCQUNmZ0csUUFBUSxFQUFHO01BQ1Y3RCxNQUFNLEVBQUUwQyxhQUFhLENBQUNtQixRQUFRLENBQUMsQ0FBQzdELE1BQU0sR0FBRzdCLG1CQUFtQjtNQUM1RDRCLEdBQUcsRUFBRTJDLGFBQWEsQ0FBQ21CLFFBQVEsQ0FBQyxDQUFDOUQsR0FBRyxHQUFHNUI7SUFDckMsQ0FBQztFQUVMO0VBQ0EsT0FBT3VFLGFBQWE7QUFDdEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxTQUFTb0Isc0JBQXNCQSxDQUNwQ1QsY0FBc0IsRUFDdEJYLGFBQTRCLEVBQzVCTCxhQUF1QixFQUN2QkUsZUFBeUIsRUFJekI7RUFDQSxJQUFNYSxXQUFXLEdBQUdoQixjQUFjLENBQUNDLGFBQWEsRUFBRUUsZUFBZSxDQUFDO0VBQ2xFLElBQU13QixjQUFjLEdBQUdILHVCQUF1QixDQUFDbEIsYUFBYSxFQUFFVSxXQUFXLENBQUM7RUFDMUUsSUFBTVksU0FBUyxHQUFHbEIsVUFBVSxDQUFDaUIsY0FBYyxFQUFFLEtBQUssQ0FBQztFQUVuRCxJQUFJQyxTQUFTLElBQUlYLGNBQWMsRUFBRTtJQUMvQjtJQUNBLE9BQU87TUFBQ1gsYUFBYSxFQUFFRCxjQUFjLENBQUNzQixjQUFjO0lBQUMsQ0FBQztFQUN4RDtFQUNBO0VBQ0EsT0FBT1osY0FBYyxDQUFDWSxjQUFjLEVBQUVYLFdBQVcsRUFBRUMsY0FBYyxFQUFFQSxjQUFjLEdBQUdXLFNBQVMsQ0FBQztBQUNoRyIsImlnbm9yZUxpc3QiOltdfQ==