kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
532 lines (509 loc) • 61.3 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MIN_LONGITUDE = exports.MIN_LATITUDE = exports.MAX_LONGITUDE = exports.MAX_LATITUDE = exports.FIELD_DISPLAY_FORMAT = void 0;
exports.applyCustomFormat = applyCustomFormat;
exports.applyDefaultFormat = applyDefaultFormat;
exports.applyValueMap = applyValueMap;
exports.clamp = clamp;
exports.datetimeFormatter = datetimeFormatter;
exports.floatFormatter = exports.defaultFormatter = void 0;
exports.formatNumber = formatNumber;
exports.getBooleanFormatter = getBooleanFormatter;
exports.getColumnFormatter = getColumnFormatter;
exports.getFormatter = getFormatter;
exports.getLatLngBounds = getLatLngBounds;
exports.getRoundingDecimalFromStep = getRoundingDecimalFromStep;
exports.getSampleData = getSampleData;
exports.getSortingFunction = getSortingFunction;
exports.hasOwnProperty = hasOwnProperty;
exports.isNumber = isNumber;
exports.normalizeSliderValue = normalizeSliderValue;
exports.numberSort = numberSort;
exports.parseFieldValue = void 0;
exports.preciseRound = preciseRound;
exports.reverseFormatNumber = reverseFormatNumber;
exports.roundToFour = roundToFour;
exports.roundValToStep = roundValToStep;
exports.timeToUnixMilli = timeToUnixMilli;
exports.uint8ArrayToHex = uint8ArrayToHex;
exports.unique = unique;
exports.validateCoordinate = validateCoordinate;
exports.validateLatitude = validateLatitude;
exports.validateLongitude = validateLongitude;
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _assert = _interopRequireDefault(require("assert"));
var _d3Format = require("d3-format");
var _momentTimezone = _interopRequireDefault(require("moment-timezone"));
var _arrow = require("@loaders.gl/arrow");
var _constants = require("@kepler.gl/constants");
var _commonUtils = require("@kepler.gl/common-utils");
var _plot = require("./plot");
var _utils = require("./utils");
var _arrowDataContainer = require("./arrow-data-container");
var _FIELD_DISPLAY_FORMAT; // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
// We need threat latitude differently otherwise mercator project view throws
// a projection matrix error
// Uncaught Error: Pixel project matrix not invertible
// at WebMercatorViewport16.Viewport6 (viewport.js:81:13)
var MAX_LATITUDE = exports.MAX_LATITUDE = 89.9;
var MIN_LATITUDE = exports.MIN_LATITUDE = -89.9;
var MAX_LONGITUDE = exports.MAX_LONGITUDE = 180;
var MIN_LONGITUDE = exports.MIN_LONGITUDE = -180;
/**
* Validates a latitude value.
* Ensures that the latitude is within the defined minimum and maximum latitude bounds.
* If the value is out of bounds, it returns the nearest bound value.
* @param latitude - The latitude value to validate.
* @returns The validated latitude value.
*/
function validateLatitude(latitude) {
return validateCoordinate(latitude !== null && latitude !== void 0 ? latitude : 0, MIN_LATITUDE, MAX_LATITUDE);
}
/**
* Validates a longitude value.
* Ensures that the longitude is within the defined minimum and maximum longitude bounds.
* If the value is out of bounds, it returns the nearest bound value.
* @param longitude - The longitude value to validate.
* @returns The validated longitude value.
*/
function validateLongitude(longitude) {
return validateCoordinate(longitude !== null && longitude !== void 0 ? longitude : 0, MIN_LONGITUDE, MAX_LONGITUDE);
}
/**
* Validates a coordinate value.
* Ensures that the value is within the specified minimum and maximum bounds.
* If the value is out of bounds, it returns the nearest bound value.
* @param value - The coordinate value to validate.
* @param minValue - The minimum bound for the value.
* @param maxValue - The maximum bound for the value.
* @returns The validated coordinate value.
*/
function validateCoordinate(value, minValue, maxValue) {
if (value <= minValue) {
return minValue;
}
if (value >= maxValue) {
return maxValue;
}
return value;
}
/**
* simple getting unique values of an array
* Note: filters out null and undefined values
*
* @param values
* @returns unique values
*/
function unique(values) {
var results = [];
var uniqueSet = new Set(values);
uniqueSet.forEach(function (v) {
if ((0, _commonUtils.notNullorUndefined)(v)) {
results.push(v);
}
});
return results;
}
function getLatLngBounds(points, idx, limit) {
var lats = points.map(function (d) {
return Number(Array.isArray(d)) && d[idx];
}).filter(Number.isFinite).sort(numberSort);
if (!lats.length) {
return null;
}
// clamp to limit
return [Math.max(lats[0], limit[0]), Math.min(lats[lats.length - 1], limit[1])];
}
function clamp(_ref) {
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
min = _ref2[0],
max = _ref2[1];
var val = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return val <= min ? min : val >= max ? max : val;
}
function getSampleData(data) {
var sampleSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 500;
var getValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function (d) {
return d;
};
var sampleStep = Math.max(Math.floor(data.length / sampleSize), 1);
var output = [];
for (var i = 0; i < data.length; i += sampleStep) {
output.push(getValue(data[i]));
}
return output;
}
/**
* Convert different time format to unix milliseconds
*/
function timeToUnixMilli(value, format) {
if ((0, _commonUtils.notNullorUndefined)(value)) {
if (typeof value === 'string') {
return _momentTimezone["default"].utc(value, format).valueOf();
}
if (typeof value === 'number') {
return format === 'x' ? value * 1000 : value;
}
if (value instanceof Date) {
return value.valueOf();
}
}
return null;
}
/**
* Whether d is a number, this filtered out NaN as well
*/
function isNumber(d) {
return Number.isFinite(d);
}
/**
* whether object has property
* @param {string} prop
* @returns {boolean} - yes or no
*/
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
function numberSort(a, b) {
return a - b;
}
function getSortingFunction(fieldType) {
switch (fieldType) {
case _constants.ALL_FIELD_TYPES.real:
case _constants.ALL_FIELD_TYPES.integer:
case _constants.ALL_FIELD_TYPES.timestamp:
return numberSort;
default:
return undefined;
}
}
/**
* round number with exact number of decimals
* return as a string
*/
function preciseRound(num, decimals) {
var t = Math.pow(10, decimals);
return (Math.round(num * t + (decimals > 0 ? 1 : 0) * (Math.sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
}
/**
* round a giving number at most 4 decimal places
* e.g. 10 -> 10, 1.12345 -> 1.2345, 2.0 -> 2
*/
function roundToFour(num) {
// @ts-expect-error
return Number("".concat(Math.round("".concat(num, "e+4")), "e-4"));
}
/**
* get number of decimals to round to for slider from step
* @param step
* @returns- number of decimal
*/
function getRoundingDecimalFromStep(step) {
if (isNaN(step)) {
(0, _assert["default"])('step is not a number');
(0, _assert["default"])(step);
}
var stepStr = step.toString();
// in case the step is a very small number e.g. 1e-7, return decimal e.g. 7 directly
var splitExponential = stepStr.split('e-');
if (splitExponential.length === 2) {
var coeffZero = splitExponential[0].split('.');
var coeffDecimal = coeffZero.length === 1 ? 0 : coeffZero[1].length;
return parseInt(splitExponential[1], 10) + coeffDecimal;
}
var splitZero = stepStr.split('.');
if (splitZero.length === 1) {
return 0;
}
return splitZero[1].length;
}
/**
* If marks is provided, snap to marks, if not normalize to step
* @param val
* @param minValue
* @param step
* @param marks
*/
function normalizeSliderValue(val, minValue, step, marks) {
if (marks && marks.length) {
// Use in slider, given a number and an array of numbers, return the nears number from the array
return (0, _plot.snapToMarks)(val, marks);
}
return roundValToStep(minValue, step, val);
}
/**
* round the value to step for the slider
* @param minValue
* @param step
* @param val
* @returns - rounded number
*/
function roundValToStep(minValue, step, val) {
if (!isNumber(step) || !isNumber(minValue)) {
return val;
}
var decimal = getRoundingDecimalFromStep(step);
var steps = Math.floor((val - minValue) / step);
var remain = val - (steps * step + minValue);
// has to round because javascript turns 0.1 into 0.9999999999999987
remain = Number(preciseRound(remain, 8));
var closest;
if (remain === 0) {
closest = val;
} else if (remain < step / 2) {
closest = steps * step + minValue;
} else {
closest = (steps + 1) * step + minValue;
}
// precise round return a string rounded to the defined decimal
var rounded = preciseRound(closest, decimal);
return Number(rounded);
}
/**
* Get the value format based on field and format options
* Used in render tooltip value
*/
var defaultFormatter = exports.defaultFormatter = function defaultFormatter(v) {
return (0, _commonUtils.notNullorUndefined)(v) ? String(v) : '';
};
var floatFormatter = exports.floatFormatter = function floatFormatter(v) {
return isNumber(v) ? String(roundToFour(v)) : '';
};
/**
* Transforms a WKB in Uint8Array form into a hex WKB string.
* @param uint8Array WKB in Uint8Array form.
* @returns hex WKB string.
*/
function uint8ArrayToHex(data) {
return Array.from(data).map(function (_byte) {
return _byte.toString(16).padStart(2, '0');
}).join('');
}
var FIELD_DISPLAY_FORMAT = exports.FIELD_DISPLAY_FORMAT = (_FIELD_DISPLAY_FORMAT = {}, (0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])(_FIELD_DISPLAY_FORMAT, _constants.ALL_FIELD_TYPES.string, defaultFormatter), _constants.ALL_FIELD_TYPES.timestamp, defaultFormatter), _constants.ALL_FIELD_TYPES.integer, defaultFormatter), _constants.ALL_FIELD_TYPES.real, defaultFormatter), _constants.ALL_FIELD_TYPES["boolean"], defaultFormatter), _constants.ALL_FIELD_TYPES.date, defaultFormatter), _constants.ALL_FIELD_TYPES.geojson, function (d) {
return typeof d === 'string' ? d : (0, _utils.isPlainObject)(d) ? JSON.stringify(d) : Array.isArray(d) ? "[".concat(String(d), "]") : '';
}), _constants.ALL_FIELD_TYPES.geoarrow, function (data, field) {
if ((0, _arrowDataContainer.isArrowVector)(data)) {
try {
var _field$metadata;
var encoding = field === null || field === void 0 || (_field$metadata = field.metadata) === null || _field$metadata === void 0 ? void 0 : _field$metadata.get('ARROW:extension:name');
if (encoding) {
var geometry = (0, _arrow.parseGeometryFromArrow)(data, encoding);
return JSON.stringify(geometry);
}
} catch (error) {
// ignore for now
}
} else if (data instanceof Uint8Array) {
return uint8ArrayToHex(data);
}
return data;
}), _constants.ALL_FIELD_TYPES.object, function (value) {
try {
return JSON.stringify(value);
} catch (e) {
return String(value);
}
}), _constants.ALL_FIELD_TYPES.array, function (d) {
return JSON.stringify(d);
}), (0, _defineProperty2["default"])(_FIELD_DISPLAY_FORMAT, _constants.ALL_FIELD_TYPES.h3, defaultFormatter));
/**
* Parse field value and type and return a string representation
*/
var parseFieldValue = exports.parseFieldValue = function parseFieldValue(value, type, field) {
if (!(0, _commonUtils.notNullorUndefined)(value)) {
return '';
}
// BigInt values cannot be serialized with JSON.stringify() directly
// We need to explicitly convert them to strings using .toString()
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json
if (typeof value === 'bigint') {
return value.toString();
}
return FIELD_DISPLAY_FORMAT[type] ? FIELD_DISPLAY_FORMAT[type](value, field) : String(value);
};
/**
* Get the value format based on field and format options
* Used in render tooltip value
* @param format
* @param field
*/
function getFormatter(format, field) {
if (!format) {
return defaultFormatter;
}
var tooltipFormat = Object.values(_constants.TOOLTIP_FORMATS).find(function (f) {
return f[_constants.TOOLTIP_KEY] === format;
});
if (tooltipFormat) {
return applyDefaultFormat(tooltipFormat);
} else if (typeof format === 'string' && field) {
return applyCustomFormat(format, field);
}
return defaultFormatter;
}
function getColumnFormatter(field) {
var format = field.format,
displayFormat = field.displayFormat;
if (!format && !displayFormat) {
return FIELD_DISPLAY_FORMAT[field.type];
}
var tooltipFormat = Object.values(_constants.TOOLTIP_FORMATS).find(function (f) {
return f[_constants.TOOLTIP_KEY] === displayFormat;
});
if (tooltipFormat) {
return applyDefaultFormat(tooltipFormat);
} else if (typeof displayFormat === 'string' && field) {
return applyCustomFormat(displayFormat, field);
} else if ((0, _typeof2["default"])(displayFormat) === 'object') {
return applyValueMap(displayFormat);
}
return defaultFormatter;
}
function applyValueMap(format) {
return function (v) {
return format[v];
};
}
function applyDefaultFormat(tooltipFormat) {
if (!tooltipFormat || !tooltipFormat.format) {
return defaultFormatter;
}
switch (tooltipFormat.type) {
case _constants.TOOLTIP_FORMAT_TYPES.DECIMAL:
return (0, _d3Format.format)(tooltipFormat.format);
case _constants.TOOLTIP_FORMAT_TYPES.DATE:
case _constants.TOOLTIP_FORMAT_TYPES.DATE_TIME:
return datetimeFormatter(null)(tooltipFormat.format);
case _constants.TOOLTIP_FORMAT_TYPES.PERCENTAGE:
return function (v) {
return "".concat((0, _d3Format.format)(_constants.TOOLTIP_FORMATS.DECIMAL_DECIMAL_FIXED_2.format)(v), "%");
};
case _constants.TOOLTIP_FORMAT_TYPES.BOOLEAN:
return getBooleanFormatter(tooltipFormat.format);
default:
return defaultFormatter;
}
}
function getBooleanFormatter(format) {
switch (format) {
case '01':
return function (v) {
return v ? '1' : '0';
};
case 'yn':
return function (v) {
return v ? 'yes' : 'no';
};
default:
return defaultFormatter;
}
}
// Allow user to specify custom tooltip format via config
function applyCustomFormat(format, field) {
switch (field.type) {
case _constants.ALL_FIELD_TYPES.real:
case _constants.ALL_FIELD_TYPES.integer:
return (0, _d3Format.format)(format);
case _constants.ALL_FIELD_TYPES.date:
case _constants.ALL_FIELD_TYPES.timestamp:
return datetimeFormatter(null)(format);
default:
return function (v) {
return v;
};
}
}
function formatLargeNumber(n) {
// SI-prefix with 4 significant digits
return (0, _d3Format.format)('.4~s')(n);
}
function formatNumber(n, type) {
switch (type) {
case _constants.ALL_FIELD_TYPES.integer:
if (n < 0) {
return "-".concat(formatNumber(-n, 'integer'));
}
if (n < 1000) {
return "".concat(Math.round(n));
}
if (n < 10 * 1000) {
return (0, _d3Format.format)(',')(Math.round(n));
}
return formatLargeNumber(n);
case _constants.ALL_FIELD_TYPES.real:
if (n < 0) {
return "-".concat(formatNumber(-n, 'number'));
}
if (n < 1000) {
return (0, _d3Format.format)('.4~r')(n);
}
if (n < 10 * 1000) {
return (0, _d3Format.format)(',.2~f')(n);
}
return formatLargeNumber(n);
default:
return formatNumber(n, 'real');
}
}
var transformation = {
Y: Math.pow(10, 24),
Z: Math.pow(10, 21),
E: Math.pow(10, 18),
P: Math.pow(10, 15),
T: Math.pow(10, 12),
G: Math.pow(10, 9),
M: Math.pow(10, 6),
k: Math.pow(10, 3),
h: Math.pow(10, 2),
da: Math.pow(10, 1),
d: Math.pow(10, -1),
c: Math.pow(10, -2),
m: Math.pow(10, -3),
μ: Math.pow(10, -6),
n: Math.pow(10, -9),
p: Math.pow(10, -12),
f: Math.pow(10, -15),
a: Math.pow(10, -18),
z: Math.pow(10, -21),
y: Math.pow(10, -24)
};
/**
* Convert a formatted number from string back to number
*/
function reverseFormatNumber(str) {
var returnValue = null;
var strNum = str.trim().replace(/,/g, '');
Object.entries(transformation).forEach(function (d) {
if (strNum.includes(d[0])) {
returnValue = parseFloat(strNum) * d[1];
return true;
}
return false;
});
// if no transformer found, convert to nuber regardless
return returnValue === null ? Number(strNum) : returnValue;
}
/**
* Format epoch milliseconds with a format string
* @type timezone
*/
function datetimeFormatter(timezone) {
return timezone ? function (format) {
return function (ts) {
return _momentTimezone["default"].utc(ts).tz(timezone).format(format);
};
} :
// return empty string instead of 'Invalid date' if ts is undefined/null
function (format) {
return function (ts) {
return ts ? _momentTimezone["default"].utc(ts).format(format) : '';
};
};
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfYXNzZXJ0IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfZDNGb3JtYXQiLCJfbW9tZW50VGltZXpvbmUiLCJfYXJyb3ciLCJfY29uc3RhbnRzIiwiX2NvbW1vblV0aWxzIiwiX3Bsb3QiLCJfdXRpbHMiLCJfYXJyb3dEYXRhQ29udGFpbmVyIiwiX0ZJRUxEX0RJU1BMQVlfRk9STUFUIiwiTUFYX0xBVElUVURFIiwiZXhwb3J0cyIsIk1JTl9MQVRJVFVERSIsIk1BWF9MT05HSVRVREUiLCJNSU5fTE9OR0lUVURFIiwidmFsaWRhdGVMYXRpdHVkZSIsImxhdGl0dWRlIiwidmFsaWRhdGVDb29yZGluYXRlIiwidmFsaWRhdGVMb25naXR1ZGUiLCJsb25naXR1ZGUiLCJ2YWx1ZSIsIm1pblZhbHVlIiwibWF4VmFsdWUiLCJ1bmlxdWUiLCJ2YWx1ZXMiLCJyZXN1bHRzIiwidW5pcXVlU2V0IiwiU2V0IiwiZm9yRWFjaCIsInYiLCJub3ROdWxsb3JVbmRlZmluZWQiLCJwdXNoIiwiZ2V0TGF0TG5nQm91bmRzIiwicG9pbnRzIiwiaWR4IiwibGltaXQiLCJsYXRzIiwibWFwIiwiZCIsIk51bWJlciIsIkFycmF5IiwiaXNBcnJheSIsImZpbHRlciIsImlzRmluaXRlIiwic29ydCIsIm51bWJlclNvcnQiLCJsZW5ndGgiLCJNYXRoIiwibWF4IiwibWluIiwiY2xhbXAiLCJfcmVmIiwiX3JlZjIiLCJfc2xpY2VkVG9BcnJheTIiLCJ2YWwiLCJhcmd1bWVudHMiLCJ1bmRlZmluZWQiLCJnZXRTYW1wbGVEYXRhIiwiZGF0YSIsInNhbXBsZVNpemUiLCJnZXRWYWx1ZSIsInNhbXBsZVN0ZXAiLCJmbG9vciIsIm91dHB1dCIsImkiLCJ0aW1lVG9Vbml4TWlsbGkiLCJmb3JtYXQiLCJtb21lbnQiLCJ1dGMiLCJ2YWx1ZU9mIiwiRGF0ZSIsImlzTnVtYmVyIiwiaGFzT3duUHJvcGVydHkiLCJvYmoiLCJwcm9wIiwiT2JqZWN0IiwicHJvdG90eXBlIiwiY2FsbCIsImEiLCJiIiwiZ2V0U29ydGluZ0Z1bmN0aW9uIiwiZmllbGRUeXBlIiwiQUxMX0ZJRUxEX1RZUEVTIiwicmVhbCIsImludGVnZXIiLCJ0aW1lc3RhbXAiLCJwcmVjaXNlUm91bmQiLCJudW0iLCJkZWNpbWFscyIsInQiLCJwb3ciLCJyb3VuZCIsInNpZ24iLCJ0b0ZpeGVkIiwicm91bmRUb0ZvdXIiLCJjb25jYXQiLCJnZXRSb3VuZGluZ0RlY2ltYWxGcm9tU3RlcCIsInN0ZXAiLCJpc05hTiIsImFzc2VydCIsInN0ZXBTdHIiLCJ0b1N0cmluZyIsInNwbGl0RXhwb25lbnRpYWwiLCJzcGxpdCIsImNvZWZmWmVybyIsImNvZWZmRGVjaW1hbCIsInBhcnNlSW50Iiwic3BsaXRaZXJvIiwibm9ybWFsaXplU2xpZGVyVmFsdWUiLCJtYXJrcyIsInNuYXBUb01hcmtzIiwicm91bmRWYWxUb1N0ZXAiLCJkZWNpbWFsIiwic3RlcHMiLCJyZW1haW4iLCJjbG9zZXN0Iiwicm91bmRlZCIsImRlZmF1bHRGb3JtYXR0ZXIiLCJTdHJpbmciLCJmbG9hdEZvcm1hdHRlciIsInVpbnQ4QXJyYXlUb0hleCIsImZyb20iLCJieXRlIiwicGFkU3RhcnQiLCJqb2luIiwiRklFTERfRElTUExBWV9GT1JNQVQiLCJfZGVmaW5lUHJvcGVydHkyIiwic3RyaW5nIiwiZGF0ZSIsImdlb2pzb24iLCJpc1BsYWluT2JqZWN0IiwiSlNPTiIsInN0cmluZ2lmeSIsImdlb2Fycm93IiwiZmllbGQiLCJpc0Fycm93VmVjdG9yIiwiX2ZpZWxkJG1ldGFkYXRhIiwiZW5jb2RpbmciLCJtZXRhZGF0YSIsImdldCIsImdlb21ldHJ5IiwicGFyc2VHZW9tZXRyeUZyb21BcnJvdyIsImVycm9yIiwiVWludDhBcnJheSIsIm9iamVjdCIsImUiLCJhcnJheSIsImgzIiwicGFyc2VGaWVsZFZhbHVlIiwidHlwZSIsImdldEZvcm1hdHRlciIsInRvb2x0aXBGb3JtYXQiLCJUT09MVElQX0ZPUk1BVFMiLCJmaW5kIiwiZiIsIlRPT0xUSVBfS0VZIiwiYXBwbHlEZWZhdWx0Rm9ybWF0IiwiYXBwbHlDdXN0b21Gb3JtYXQiLCJnZXRDb2x1bW5Gb3JtYXR0ZXIiLCJkaXNwbGF5Rm9ybWF0IiwiX3R5cGVvZjIiLCJhcHBseVZhbHVlTWFwIiwiVE9PTFRJUF9GT1JNQVRfVFlQRVMiLCJERUNJTUFMIiwiZDNGb3JtYXQiLCJEQVRFIiwiREFURV9USU1FIiwiZGF0ZXRpbWVGb3JtYXR0ZXIiLCJQRVJDRU5UQUdFIiwiREVDSU1BTF9ERUNJTUFMX0ZJWEVEXzIiLCJCT09MRUFOIiwiZ2V0Qm9vbGVhbkZvcm1hdHRlciIsImZvcm1hdExhcmdlTnVtYmVyIiwibiIsImZvcm1hdE51bWJlciIsInRyYW5zZm9ybWF0aW9uIiwiWSIsIloiLCJFIiwiUCIsIlQiLCJHIiwiTSIsImsiLCJoIiwiZGEiLCJjIiwibSIsIs68IiwicCIsInoiLCJ5IiwicmV2ZXJzZUZvcm1hdE51bWJlciIsInN0ciIsInJldHVyblZhbHVlIiwic3RyTnVtIiwidHJpbSIsInJlcGxhY2UiLCJlbnRyaWVzIiwiaW5jbHVkZXMiLCJwYXJzZUZsb2F0IiwidGltZXpvbmUiLCJ0cyIsInR6Il0sInNvdXJjZXMiOlsiLi4vc3JjL2RhdGEtdXRpbHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHtmb3JtYXQgYXMgZDNGb3JtYXR9IGZyb20gJ2QzLWZvcm1hdCc7XG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudC10aW1lem9uZSc7XG5cbmltcG9ydCB7cGFyc2VHZW9tZXRyeUZyb21BcnJvd30gZnJvbSAnQGxvYWRlcnMuZ2wvYXJyb3cnO1xuXG5pbXBvcnQge1xuICBBTExfRklFTERfVFlQRVMsXG4gIFRPT0xUSVBfRk9STUFUUyxcbiAgVE9PTFRJUF9GT1JNQVRfVFlQRVMsXG4gIFRPT0xUSVBfS0VZLFxuICBUb29sdGlwRm9ybWF0XG59IGZyb20gJ0BrZXBsZXIuZ2wvY29uc3RhbnRzJztcbmltcG9ydCB7bm90TnVsbG9yVW5kZWZpbmVkfSBmcm9tICdAa2VwbGVyLmdsL2NvbW1vbi11dGlscyc7XG5pbXBvcnQge0ZpZWxkLCBNaWxsaXNlY29uZCwgUHJvdG9EYXRhc2V0RmllbGR9IGZyb20gJ0BrZXBsZXIuZ2wvdHlwZXMnO1xuXG5pbXBvcnQge3NuYXBUb01hcmtzfSBmcm9tICcuL3Bsb3QnO1xuaW1wb3J0IHtpc1BsYWluT2JqZWN0fSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7aXNBcnJvd1ZlY3Rvcn0gZnJvbSAnLi9hcnJvdy1kYXRhLWNvbnRhaW5lcic7XG5cbmV4cG9ydCB0eXBlIEZpZWxkRm9ybWF0dGVyID0gKHZhbHVlOiBhbnksIGZpZWxkPzogUHJvdG9EYXRhc2V0RmllbGQpID0+IHN0cmluZztcblxuLy8gV2UgbmVlZCB0aHJlYXQgbGF0aXR1ZGUgZGlmZmVyZW50bHkgb3RoZXJ3aXNlIG1lcmNhdG9yIHByb2plY3QgdmlldyB0aHJvd3Ncbi8vIGEgcHJvamVjdGlvbiBtYXRyaXggZXJyb3Jcbi8vIFVuY2F1Z2h0IEVycm9yOiBQaXhlbCBwcm9qZWN0IG1hdHJpeCBub3QgaW52ZXJ0aWJsZVxuLy8gYXQgV2ViTWVyY2F0b3JWaWV3cG9ydDE2LlZpZXdwb3J0NiAodmlld3BvcnQuanM6ODE6MTMpXG5leHBvcnQgY29uc3QgTUFYX0xBVElUVURFID0gODkuOTtcbmV4cG9ydCBjb25zdCBNSU5fTEFUSVRVREUgPSAtODkuOTtcbmV4cG9ydCBjb25zdCBNQVhfTE9OR0lUVURFID0gMTgwO1xuZXhwb3J0IGNvbnN0IE1JTl9MT05HSVRVREUgPSAtMTgwO1xuXG4vKipcbiAqIFZhbGlkYXRlcyBhIGxhdGl0dWRlIHZhbHVlLlxuICogRW5zdXJlcyB0aGF0IHRoZSBsYXRpdHVkZSBpcyB3aXRoaW4gdGhlIGRlZmluZWQgbWluaW11bSBhbmQgbWF4aW11bSBsYXRpdHVkZSBib3VuZHMuXG4gKiBJZiB0aGUgdmFsdWUgaXMgb3V0IG9mIGJvdW5kcywgaXQgcmV0dXJucyB0aGUgbmVhcmVzdCBib3VuZCB2YWx1ZS5cbiAqIEBwYXJhbSBsYXRpdHVkZSAtIFRoZSBsYXRpdHVkZSB2YWx1ZSB0byB2YWxpZGF0ZS5cbiAqIEByZXR1cm5zIFRoZSB2YWxpZGF0ZWQgbGF0aXR1ZGUgdmFsdWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUxhdGl0dWRlKGxhdGl0dWRlOiBudW1iZXIgfCB1bmRlZmluZWQpOiBudW1iZXIge1xuICByZXR1cm4gdmFsaWRhdGVDb29yZGluYXRlKGxhdGl0dWRlID8/IDAsIE1JTl9MQVRJVFVERSwgTUFYX0xBVElUVURFKTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYSBsb25naXR1ZGUgdmFsdWUuXG4gKiBFbnN1cmVzIHRoYXQgdGhlIGxvbmdpdHVkZSBpcyB3aXRoaW4gdGhlIGRlZmluZWQgbWluaW11bSBhbmQgbWF4aW11bSBsb25naXR1ZGUgYm91bmRzLlxuICogSWYgdGhlIHZhbHVlIGlzIG91dCBvZiBib3VuZHMsIGl0IHJldHVybnMgdGhlIG5lYXJlc3QgYm91bmQgdmFsdWUuXG4gKiBAcGFyYW0gbG9uZ2l0dWRlIC0gVGhlIGxvbmdpdHVkZSB2YWx1ZSB0byB2YWxpZGF0ZS5cbiAqIEByZXR1cm5zIFRoZSB2YWxpZGF0ZWQgbG9uZ2l0dWRlIHZhbHVlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVMb25naXR1ZGUobG9uZ2l0dWRlOiBudW1iZXIgfCB1bmRlZmluZWQpOiBudW1iZXIge1xuICByZXR1cm4gdmFsaWRhdGVDb29yZGluYXRlKGxvbmdpdHVkZSA/PyAwLCBNSU5fTE9OR0lUVURFLCBNQVhfTE9OR0lUVURFKTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYSBjb29yZGluYXRlIHZhbHVlLlxuICogRW5zdXJlcyB0aGF0IHRoZSB2YWx1ZSBpcyB3aXRoaW4gdGhlIHNwZWNpZmllZCBtaW5pbXVtIGFuZCBtYXhpbXVtIGJvdW5kcy5cbiAqIElmIHRoZSB2YWx1ZSBpcyBvdXQgb2YgYm91bmRzLCBpdCByZXR1cm5zIHRoZSBuZWFyZXN0IGJvdW5kIHZhbHVlLlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIGNvb3JkaW5hdGUgdmFsdWUgdG8gdmFsaWRhdGUuXG4gKiBAcGFyYW0gbWluVmFsdWUgLSBUaGUgbWluaW11bSBib3VuZCBmb3IgdGhlIHZhbHVlLlxuICogQHBhcmFtIG1heFZhbHVlIC0gVGhlIG1heGltdW0gYm91bmQgZm9yIHRoZSB2YWx1ZS5cbiAqIEByZXR1cm5zIFRoZSB2YWxpZGF0ZWQgY29vcmRpbmF0ZSB2YWx1ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlQ29vcmRpbmF0ZSh2YWx1ZTogbnVtYmVyLCBtaW5WYWx1ZTogbnVtYmVyLCBtYXhWYWx1ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgaWYgKHZhbHVlIDw9IG1pblZhbHVlKSB7XG4gICAgcmV0dXJuIG1pblZhbHVlO1xuICB9XG4gIGlmICh2YWx1ZSA+PSBtYXhWYWx1ZSkge1xuICAgIHJldHVybiBtYXhWYWx1ZTtcbiAgfVxuXG4gIHJldHVybiB2YWx1ZTtcbn1cblxuLyoqXG4gKiBzaW1wbGUgZ2V0dGluZyB1bmlxdWUgdmFsdWVzIG9mIGFuIGFycmF5XG4gKiBOb3RlOiBmaWx0ZXJzIG91dCBudWxsIGFuZCB1bmRlZmluZWQgdmFsdWVzXG4gKlxuICogQHBhcmFtIHZhbHVlc1xuICogQHJldHVybnMgdW5pcXVlIHZhbHVlc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pcXVlPFQ+KHZhbHVlczogVFtdKSB7XG4gIGNvbnN0IHJlc3VsdHM6IFRbXSA9IFtdO1xuICBjb25zdCB1bmlxdWVTZXQgPSBuZXcgU2V0KHZhbHVlcyk7XG4gIHVuaXF1ZVNldC5mb3JFYWNoKHYgPT4ge1xuICAgIGlmIChub3ROdWxsb3JVbmRlZmluZWQodikpIHtcbiAgICAgIHJlc3VsdHMucHVzaCh2KTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gcmVzdWx0cztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExhdExuZ0JvdW5kcyhcbiAgcG9pbnRzOiBudW1iZXJbXVtdLFxuICBpZHg6IG51bWJlcixcbiAgbGltaXQ6IFtudW1iZXIsIG51bWJlcl1cbik6IFtudW1iZXIsIG51bWJlcl0gfCBudWxsIHtcbiAgY29uc3QgbGF0cyA9IHBvaW50c1xuICAgIC5tYXAoZCA9PiBOdW1iZXIoQXJyYXkuaXNBcnJheShkKSkgJiYgZFtpZHhdKVxuICAgIC5maWx0ZXIoTnVtYmVyLmlzRmluaXRlKVxuICAgIC5zb3J0KG51bWJlclNvcnQpO1xuXG4gIGlmICghbGF0cy5sZW5ndGgpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8vIGNsYW1wIHRvIGxpbWl0XG4gIHJldHVybiBbTWF0aC5tYXgobGF0c1swXSwgbGltaXRbMF0pLCBNYXRoLm1pbihsYXRzW2xhdHMubGVuZ3RoIC0gMV0sIGxpbWl0WzFdKV07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjbGFtcChbbWluLCBtYXhdOiBbbnVtYmVyLCBudW1iZXJdLCB2YWwgPSAwKTogbnVtYmVyIHtcbiAgcmV0dXJuIHZhbCA8PSBtaW4gPyBtaW4gOiB2YWwgPj0gbWF4ID8gbWF4IDogdmFsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2FtcGxlRGF0YShkYXRhLCBzYW1wbGVTaXplID0gNTAwLCBnZXRWYWx1ZSA9IGQgPT4gZCkge1xuICBjb25zdCBzYW1wbGVTdGVwID0gTWF0aC5tYXgoTWF0aC5mbG9vcihkYXRhLmxlbmd0aCAvIHNhbXBsZVNpemUpLCAxKTtcbiAgY29uc3Qgb3V0cHV0OiBhbnlbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpICs9IHNhbXBsZVN0ZXApIHtcbiAgICBvdXRwdXQucHVzaChnZXRWYWx1ZShkYXRhW2ldKSk7XG4gIH1cblxuICByZXR1cm4gb3V0cHV0O1xufVxuXG4vKipcbiAqIENvbnZlcnQgZGlmZmVyZW50IHRpbWUgZm9ybWF0IHRvIHVuaXggbWlsbGlzZWNvbmRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aW1lVG9Vbml4TWlsbGkodmFsdWU6IHN0cmluZyB8IG51bWJlciB8IERhdGUsIGZvcm1hdDogc3RyaW5nKTogTWlsbGlzZWNvbmQgfCBudWxsIHtcbiAgaWYgKG5vdE51bGxvclVuZGVmaW5lZCh2YWx1ZSkpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIG1vbWVudC51dGModmFsdWUsIGZvcm1hdCkudmFsdWVPZigpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuIGZvcm1hdCA9PT0gJ3gnID8gdmFsdWUgKiAxMDAwIDogdmFsdWU7XG4gICAgfVxuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgIHJldHVybiB2YWx1ZS52YWx1ZU9mKCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgZCBpcyBhIG51bWJlciwgdGhpcyBmaWx0ZXJlZCBvdXQgTmFOIGFzIHdlbGxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTnVtYmVyKGQ6IHVua25vd24pOiBkIGlzIG51bWJlciB7XG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUoZCk7XG59XG5cbi8qKlxuICogd2hldGhlciBvYmplY3QgaGFzIHByb3BlcnR5XG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcFxuICogQHJldHVybnMge2Jvb2xlYW59IC0geWVzIG9yIG5vXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNPd25Qcm9wZXJ0eTxYIGV4dGVuZHMgb2JqZWN0LCBZIGV4dGVuZHMgUHJvcGVydHlLZXk+KFxuICBvYmo6IFgsXG4gIHByb3A6IFlcbik6IG9iaiBpcyBYICYgUmVjb3JkPFksIHVua25vd24+IHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbnVtYmVyU29ydChhOiBudW1iZXIsIGI6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBhIC0gYjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNvcnRpbmdGdW5jdGlvbihmaWVsZFR5cGU6IHN0cmluZyk6IHR5cGVvZiBudW1iZXJTb3J0IHwgdW5kZWZpbmVkIHtcbiAgc3dpdGNoIChmaWVsZFR5cGUpIHtcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5yZWFsOlxuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmludGVnZXI6XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMudGltZXN0YW1wOlxuICAgICAgcmV0dXJuIG51bWJlclNvcnQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiByb3VuZCBudW1iZXIgd2l0aCBleGFjdCBudW1iZXIgb2YgZGVjaW1hbHNcbiAqIHJldHVybiBhcyBhIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlY2lzZVJvdW5kKG51bTogbnVtYmVyLCBkZWNpbWFsczogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgdCA9IE1hdGgucG93KDEwLCBkZWNpbWFscyk7XG4gIHJldHVybiAoXG4gICAgTWF0aC5yb3VuZChcbiAgICAgIG51bSAqIHQgKyAoZGVjaW1hbHMgPiAwID8gMSA6IDApICogKE1hdGguc2lnbihudW0pICogKDEwIC8gTWF0aC5wb3coMTAwLCBkZWNpbWFscykpKVxuICAgICkgLyB0XG4gICkudG9GaXhlZChkZWNpbWFscyk7XG59XG5cbi8qKlxuICogcm91bmQgYSBnaXZpbmcgbnVtYmVyIGF0IG1vc3QgNCBkZWNpbWFsIHBsYWNlc1xuICogZS5nLiAxMCAtPiAxMCwgMS4xMjM0NSAtPiAxLjIzNDUsIDIuMCAtPiAyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByb3VuZFRvRm91cihudW06IG51bWJlcik6IG51bWJlciB7XG4gIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgcmV0dXJuIE51bWJlcihgJHtNYXRoLnJvdW5kKGAke251bX1lKzRgKX1lLTRgKTtcbn1cbi8qKlxuICogZ2V0IG51bWJlciBvZiBkZWNpbWFscyB0byByb3VuZCB0byBmb3Igc2xpZGVyIGZyb20gc3RlcFxuICogQHBhcmFtIHN0ZXBcbiAqIEByZXR1cm5zLSBudW1iZXIgb2YgZGVjaW1hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Um91bmRpbmdEZWNpbWFsRnJvbVN0ZXAoc3RlcDogbnVtYmVyKTogbnVtYmVyIHtcbiAgaWYgKGlzTmFOKHN0ZXApKSB7XG4gICAgYXNzZXJ0KCdzdGVwIGlzIG5vdCBhIG51bWJlcicpO1xuICAgIGFzc2VydChzdGVwKTtcbiAgfVxuXG4gIGNvbnN0IHN0ZXBTdHIgPSBzdGVwLnRvU3RyaW5nKCk7XG5cbiAgLy8gaW4gY2FzZSB0aGUgc3RlcCBpcyBhIHZlcnkgc21hbGwgbnVtYmVyIGUuZy4gMWUtNywgcmV0dXJuIGRlY2ltYWwgZS5nLiA3IGRpcmVjdGx5XG4gIGNvbnN0IHNwbGl0RXhwb25lbnRpYWwgPSBzdGVwU3RyLnNwbGl0KCdlLScpO1xuICBpZiAoc3BsaXRFeHBvbmVudGlhbC5sZW5ndGggPT09IDIpIHtcbiAgICBjb25zdCBjb2VmZlplcm8gPSBzcGxpdEV4cG9uZW50aWFsWzBdLnNwbGl0KCcuJyk7XG4gICAgY29uc3QgY29lZmZEZWNpbWFsID0gY29lZmZaZXJvLmxlbmd0aCA9PT0gMSA/IDAgOiBjb2VmZlplcm9bMV0ubGVuZ3RoO1xuICAgIHJldHVybiBwYXJzZUludChzcGxpdEV4cG9uZW50aWFsWzFdLCAxMCkgKyBjb2VmZkRlY2ltYWw7XG4gIH1cblxuICBjb25zdCBzcGxpdFplcm8gPSBzdGVwU3RyLnNwbGl0KCcuJyk7XG4gIGlmIChzcGxpdFplcm8ubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgcmV0dXJuIHNwbGl0WmVyb1sxXS5sZW5ndGg7XG59XG5cbi8qKlxuICogSWYgbWFya3MgaXMgcHJvdmlkZWQsIHNuYXAgdG8gbWFya3MsIGlmIG5vdCBub3JtYWxpemUgdG8gc3RlcFxuICogQHBhcmFtIHZhbFxuICogQHBhcmFtIG1pblZhbHVlXG4gKiBAcGFyYW0gc3RlcFxuICogQHBhcmFtIG1hcmtzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVTbGlkZXJWYWx1ZShcbiAgdmFsOiBudW1iZXIsXG4gIG1pblZhbHVlOiBudW1iZXIgfCB1bmRlZmluZWQsXG4gIHN0ZXA6IG51bWJlcixcbiAgbWFya3M/OiBudW1iZXJbXSB8IG51bGxcbik6IG51bWJlciB7XG4gIGlmIChtYXJrcyAmJiBtYXJrcy5sZW5ndGgpIHtcbiAgICAvLyBVc2UgaW4gc2xpZGVyLCBnaXZlbiBhIG51bWJlciBhbmQgYW4gYXJyYXkgb2YgbnVtYmVycywgcmV0dXJuIHRoZSBuZWFycyBudW1iZXIgZnJvbSB0aGUgYXJyYXlcbiAgICByZXR1cm4gc25hcFRvTWFya3ModmFsLCBtYXJrcyk7XG4gIH1cblxuICByZXR1cm4gcm91bmRWYWxUb1N0ZXAobWluVmFsdWUsIHN0ZXAsIHZhbCk7XG59XG5cbi8qKlxuICogcm91bmQgdGhlIHZhbHVlIHRvIHN0ZXAgZm9yIHRoZSBzbGlkZXJcbiAqIEBwYXJhbSBtaW5WYWx1ZVxuICogQHBhcmFtIHN0ZXBcbiAqIEBwYXJhbSB2YWxcbiAqIEByZXR1cm5zIC0gcm91bmRlZCBudW1iZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdW5kVmFsVG9TdGVwKG1pblZhbHVlOiBudW1iZXIgfCB1bmRlZmluZWQsIHN0ZXA6IG51bWJlciwgdmFsOiBudW1iZXIpOiBudW1iZXIge1xuICBpZiAoIWlzTnVtYmVyKHN0ZXApIHx8ICFpc051bWJlcihtaW5WYWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsO1xuICB9XG5cbiAgY29uc3QgZGVjaW1hbCA9IGdldFJvdW5kaW5nRGVjaW1hbEZyb21TdGVwKHN0ZXApO1xuICBjb25zdCBzdGVwcyA9IE1hdGguZmxvb3IoKHZhbCAtIG1pblZhbHVlKSAvIHN0ZXApO1xuICBsZXQgcmVtYWluID0gdmFsIC0gKHN0ZXBzICogc3RlcCArIG1pblZhbHVlKTtcblxuICAvLyBoYXMgdG8gcm91bmQgYmVjYXVzZSBqYXZhc2NyaXB0IHR1cm5zIDAuMSBpbnRvIDAuOTk5OTk5OTk5OTk5OTk4N1xuICByZW1haW4gPSBOdW1iZXIocHJlY2lzZVJvdW5kKHJlbWFpbiwgOCkpO1xuXG4gIGxldCBjbG9zZXN0OiBudW1iZXI7XG4gIGlmIChyZW1haW4gPT09IDApIHtcbiAgICBjbG9zZXN0ID0gdmFsO1xuICB9IGVsc2UgaWYgKHJlbWFpbiA8IHN0ZXAgLyAyKSB7XG4gICAgY2xvc2VzdCA9IHN0ZXBzICogc3RlcCArIG1pblZhbHVlO1xuICB9IGVsc2Uge1xuICAgIGNsb3Nlc3QgPSAoc3RlcHMgKyAxKSAqIHN0ZXAgKyBtaW5WYWx1ZTtcbiAgfVxuXG4gIC8vIHByZWNpc2Ugcm91bmQgcmV0dXJuIGEgc3RyaW5nIHJvdW5kZWQgdG8gdGhlIGRlZmluZWQgZGVjaW1hbFxuICBjb25zdCByb3VuZGVkID0gcHJlY2lzZVJvdW5kKGNsb3Nlc3QsIGRlY2ltYWwpO1xuXG4gIHJldHVybiBOdW1iZXIocm91bmRlZCk7XG59XG5cbi8qKlxuICogR2V0IHRoZSB2YWx1ZSBmb3JtYXQgYmFzZWQgb24gZmllbGQgYW5kIGZvcm1hdCBvcHRpb25zXG4gKiBVc2VkIGluIHJlbmRlciB0b29sdGlwIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCBkZWZhdWx0Rm9ybWF0dGVyOiBGaWVsZEZvcm1hdHRlciA9IHYgPT4gKG5vdE51bGxvclVuZGVmaW5lZCh2KSA/IFN0cmluZyh2KSA6ICcnKTtcblxuZXhwb3J0IGNvbnN0IGZsb2F0Rm9ybWF0dGVyID0gdiA9PiAoaXNOdW1iZXIodikgPyBTdHJpbmcocm91bmRUb0ZvdXIodikpIDogJycpO1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgYSBXS0IgaW4gVWludDhBcnJheSBmb3JtIGludG8gYSBoZXggV0tCIHN0cmluZy5cbiAqIEBwYXJhbSB1aW50OEFycmF5IFdLQiBpbiBVaW50OEFycmF5IGZvcm0uXG4gKiBAcmV0dXJucyBoZXggV0tCIHN0cmluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVpbnQ4QXJyYXlUb0hleChkYXRhOiBVaW50OEFycmF5KTogc3RyaW5nIHtcbiAgcmV0dXJuIEFycmF5LmZyb20oZGF0YSlcbiAgICAubWFwKGJ5dGUgPT4gKGJ5dGUgYXMgYW55KS50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKSlcbiAgICAuam9pbignJyk7XG59XG5cbmV4cG9ydCBjb25zdCBGSUVMRF9ESVNQTEFZX0ZPUk1BVDoge1xuICBba2V5OiBzdHJpbmddOiBGaWVsZEZvcm1hdHRlcjtcbn0gPSB7XG4gIFtBTExfRklFTERfVFlQRVMuc3RyaW5nXTogZGVmYXVsdEZvcm1hdHRlcixcbiAgW0FMTF9GSUVMRF9UWVBFUy50aW1lc3RhbXBdOiBkZWZhdWx0Rm9ybWF0dGVyLFxuICBbQUxMX0ZJRUxEX1RZUEVTLmludGVnZXJdOiBkZWZhdWx0Rm9ybWF0dGVyLFxuICBbQUxMX0ZJRUxEX1RZUEVTLnJlYWxdOiBkZWZhdWx0Rm9ybWF0dGVyLFxuICBbQUxMX0ZJRUxEX1RZUEVTLmJvb2xlYW5dOiBkZWZhdWx0Rm9ybWF0dGVyLFxuICBbQUxMX0ZJRUxEX1RZUEVTLmRhdGVdOiBkZWZhdWx0Rm9ybWF0dGVyLFxuICBbQUxMX0ZJRUxEX1RZUEVTLmdlb2pzb25dOiBkID0+XG4gICAgdHlwZW9mIGQgPT09ICdzdHJpbmcnXG4gICAgICA/IGRcbiAgICAgIDogaXNQbGFpbk9iamVjdChkKVxuICAgICAgPyBKU09OLnN0cmluZ2lmeShkKVxuICAgICAgOiBBcnJheS5pc0FycmF5KGQpXG4gICAgICA/IGBbJHtTdHJpbmcoZCl9XWBcbiAgICAgIDogJycsXG4gIFtBTExfRklFTERfVFlQRVMuZ2VvYXJyb3ddOiAoZGF0YSwgZmllbGQpID0+IHtcbiAgICBpZiAoaXNBcnJvd1ZlY3RvcihkYXRhKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZW5jb2RpbmcgPSBmaWVsZD8ubWV0YWRhdGE/LmdldCgnQVJST1c6ZXh0ZW5zaW9uOm5hbWUnKTtcbiAgICAgICAgaWYgKGVuY29kaW5nKSB7XG4gICAgICAgICAgY29uc3QgZ2VvbWV0cnkgPSBwYXJzZUdlb21ldHJ5RnJvbUFycm93KGRhdGEsIGVuY29kaW5nKTtcbiAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoZ2VvbWV0cnkpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBpZ25vcmUgZm9yIG5vd1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICAgIHJldHVybiB1aW50OEFycmF5VG9IZXgoZGF0YSk7XG4gICAgfVxuICAgIHJldHVybiBkYXRhO1xuICB9LFxuICBbQUxMX0ZJRUxEX1RZUEVTLm9iamVjdF06ICh2YWx1ZTogYW55KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XG4gICAgfVxuICB9LFxuICBbQUxMX0ZJRUxEX1RZUEVTLmFycmF5XTogZCA9PiBKU09OLnN0cmluZ2lmeShkKSxcbiAgW0FMTF9GSUVMRF9UWVBFUy5oM106IGRlZmF1bHRGb3JtYXR0ZXJcbn07XG5cbi8qKlxuICogUGFyc2UgZmllbGQgdmFsdWUgYW5kIHR5cGUgYW5kIHJldHVybiBhIHN0cmluZyByZXByZXNlbnRhdGlvblxuICovXG5leHBvcnQgY29uc3QgcGFyc2VGaWVsZFZhbHVlID0gKHZhbHVlOiBhbnksIHR5cGU6IHN0cmluZywgZmllbGQ/OiBGaWVsZCk6IHN0cmluZyA9PiB7XG4gIGlmICghbm90TnVsbG9yVW5kZWZpbmVkKHZhbHVlKSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuICAvLyBCaWdJbnQgdmFsdWVzIGNhbm5vdCBiZSBzZXJpYWxpemVkIHdpdGggSlNPTi5zdHJpbmdpZnkoKSBkaXJlY3RseVxuICAvLyBXZSBuZWVkIHRvIGV4cGxpY2l0bHkgY29udmVydCB0aGVtIHRvIHN0cmluZ3MgdXNpbmcgLnRvU3RyaW5nKClcbiAgLy8gU2VlOiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9CaWdJbnQjdXNlX3dpdGhpbl9qc29uXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdiaWdpbnQnKSB7XG4gICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7XG4gIH1cbiAgcmV0dXJuIEZJRUxEX0RJU1BMQVlfRk9STUFUW3R5cGVdID8gRklFTERfRElTUExBWV9GT1JNQVRbdHlwZV0odmFsdWUsIGZpZWxkKSA6IFN0cmluZyh2YWx1ZSk7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgdmFsdWUgZm9ybWF0IGJhc2VkIG9uIGZpZWxkIGFuZCBmb3JtYXQgb3B0aW9uc1xuICogVXNlZCBpbiByZW5kZXIgdG9vbHRpcCB2YWx1ZVxuICogQHBhcmFtIGZvcm1hdFxuICogQHBhcmFtIGZpZWxkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRGb3JtYXR0ZXIoXG4gIGZvcm1hdD86IHN0cmluZyB8IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsLFxuICBmaWVsZD86IEZpZWxkXG4pOiBGaWVsZEZvcm1hdHRlciB7XG4gIGlmICghZm9ybWF0KSB7XG4gICAgcmV0dXJuIGRlZmF1bHRGb3JtYXR0ZXI7XG4gIH1cbiAgY29uc3QgdG9vbHRpcEZvcm1hdCA9IE9iamVjdC52YWx1ZXMoVE9PTFRJUF9GT1JNQVRTKS5maW5kKGYgPT4gZltUT09MVElQX0tFWV0gPT09IGZvcm1hdCk7XG5cbiAgaWYgKHRvb2x0aXBGb3JtYXQpIHtcbiAgICByZXR1cm4gYXBwbHlEZWZhdWx0Rm9ybWF0KHRvb2x0aXBGb3JtYXQgYXMgVG9vbHRpcEZvcm1hdCk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGZvcm1hdCA9PT0gJ3N0cmluZycgJiYgZmllbGQpIHtcbiAgICByZXR1cm4gYXBwbHlDdXN0b21Gb3JtYXQoZm9ybWF0LCBmaWVsZCk7XG4gIH1cblxuICByZXR1cm4gZGVmYXVsdEZvcm1hdHRlcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENvbHVtbkZvcm1hdHRlcihcbiAgZmllbGQ6IFBpY2s8RmllbGQsICd0eXBlJz4gJiBQYXJ0aWFsPFBpY2s8RmllbGQsICdmb3JtYXQnIHwgJ2Rpc3BsYXlGb3JtYXQnPj5cbik6IEZpZWxkRm9ybWF0dGVyIHtcbiAgY29uc3Qge2Zvcm1hdCwgZGlzcGxheUZvcm1hdH0gPSBmaWVsZDtcblxuICBpZiAoIWZvcm1hdCAmJiAhZGlzcGxheUZvcm1hdCkge1xuICAgIHJldHVybiBGSUVMRF9ESVNQTEFZX0ZPUk1BVFtmaWVsZC50eXBlXTtcbiAgfVxuICBjb25zdCB0b29sdGlwRm9ybWF0ID0gT2JqZWN0LnZhbHVlcyhUT09MVElQX0ZPUk1BVFMpLmZpbmQoZiA9PiBmW1RPT0xUSVBfS0VZXSA9PT0gZGlzcGxheUZvcm1hdCk7XG5cbiAgaWYgKHRvb2x0aXBGb3JtYXQpIHtcbiAgICByZXR1cm4gYXBwbHlEZWZhdWx0Rm9ybWF0KHRvb2x0aXBGb3JtYXQpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBkaXNwbGF5Rm9ybWF0ID09PSAnc3RyaW5nJyAmJiBmaWVsZCkge1xuICAgIHJldHVybiBhcHBseUN1c3RvbUZvcm1hdChkaXNwbGF5Rm9ybWF0LCBmaWVsZCk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGRpc3BsYXlGb3JtYXQgPT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIGFwcGx5VmFsdWVNYXAoZGlzcGxheUZvcm1hdCk7XG4gIH1cblxuICByZXR1cm4gZGVmYXVsdEZvcm1hdHRlcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5VmFsdWVNYXAoZm9ybWF0KSB7XG4gIHJldHVybiB2ID0+IGZvcm1hdFt2XTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5RGVmYXVsdEZvcm1hdCh0b29sdGlwRm9ybWF0OiBUb29sdGlwRm9ybWF0KTogKHY6IGFueSkgPT4gc3RyaW5nIHtcbiAgaWYgKCF0b29sdGlwRm9ybWF0IHx8ICF0b29sdGlwRm9ybWF0LmZvcm1hdCkge1xuICAgIHJldHVybiBkZWZhdWx0Rm9ybWF0dGVyO1xuICB9XG5cbiAgc3dpdGNoICh0b29sdGlwRm9ybWF0LnR5cGUpIHtcbiAgICBjYXNlIFRPT0xUSVBfRk9STUFUX1RZUEVTLkRFQ0lNQUw6XG4gICAgICByZXR1cm4gZDNGb3JtYXQodG9vbHRpcEZvcm1hdC5mb3JtYXQpO1xuICAgIGNhc2UgVE9PTFRJUF9GT1JNQVRfVFlQRVMuREFURTpcbiAgICBjYXNlIFRPT0xUSVBfRk9STUFUX1RZUEVTLkRBVEVfVElNRTpcbiAgICAgIHJldHVybiBkYXRldGltZUZvcm1hdHRlcihudWxsKSh0b29sdGlwRm9ybWF0LmZvcm1hdCk7XG4gICAgY2FzZSBUT09MVElQX0ZPUk1BVF9UWVBFUy5QRVJDRU5UQUdFOlxuICAgICAgcmV0dXJuIHYgPT4gYCR7ZDNGb3JtYXQoVE9PTFRJUF9GT1JNQVRTLkRFQ0lNQUxfREVDSU1BTF9GSVhFRF8yLmZvcm1hdCkodil9JWA7XG4gICAgY2FzZSBUT09MVElQX0ZPUk1BVF9UWVBFUy5CT09MRUFOOlxuICAgICAgcmV0dXJuIGdldEJvb2xlYW5Gb3JtYXR0ZXIodG9vbHRpcEZvcm1hdC5mb3JtYXQpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZGVmYXVsdEZvcm1hdHRlcjtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Qm9vbGVhbkZvcm1hdHRlcihmb3JtYXQ6IHN0cmluZyk6IEZpZWxkRm9ybWF0dGVyIHtcbiAgc3dpdGNoIChmb3JtYXQpIHtcbiAgICBjYXNlICcwMSc6XG4gICAgICByZXR1cm4gKHY6IGJvb2xlYW4pID0+ICh2ID8gJzEnIDogJzAnKTtcbiAgICBjYXNlICd5bic6XG4gICAgICByZXR1cm4gKHY6IGJvb2xlYW4pID0+ICh2ID8gJ3llcycgOiAnbm8nKTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGRlZmF1bHRGb3JtYXR0ZXI7XG4gIH1cbn1cbi8vIEFsbG93IHVzZXIgdG8gc3BlY2lmeSBjdXN0b20gdG9vbHRpcCBmb3JtYXQgdmlhIGNvbmZpZ1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5Q3VzdG9tRm9ybWF0KGZvcm1hdCwgZmllbGQ6IHt0eXBlPzogc3RyaW5nfSk6IEZpZWxkRm9ybWF0dGVyIHtcbiAgc3dpdGNoIChmaWVsZC50eXBlKSB7XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMucmVhbDpcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5pbnRlZ2VyOlxuICAgICAgcmV0dXJuIGQzRm9ybWF0KGZvcm1hdCk7XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMuZGF0ZTpcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy50aW1lc3RhbXA6XG4gICAgICByZXR1cm4gZGF0ZXRpbWVGb3JtYXR0ZXIobnVsbCkoZm9ybWF0KTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHYgPT4gdjtcbiAgfVxufVxuXG5mdW5jdGlvbiBmb3JtYXRMYXJnZU51bWJlcihuKSB7XG4gIC8vIFNJLXByZWZpeCB3aXRoIDQgc2lnbmlmaWNhbnQgZGlnaXRzXG4gIHJldHVybiBkM0Zvcm1hdCgnLjR+cycpKG4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0TnVtYmVyKG46IG51bWJlciwgdHlwZT86IHN0cmluZyk6IHN0cmluZyB7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmludGVnZXI6XG4gICAgICBpZiAobiA8IDApIHtcbiAgICAgICAgcmV0dXJuIGAtJHtmb3JtYXROdW1iZXIoLW4sICdpbnRlZ2VyJyl9YDtcbiAgICAgIH1cbiAgICAgIGlmIChuIDwgMTAwMCkge1xuICAgICAgICByZXR1cm4gYCR7TWF0aC5yb3VuZChuKX1gO1xuICAgICAgfVxuICAgICAgaWYgKG4gPCAxMCAqIDEwMDApIHtcbiAgICAgICAgcmV0dXJuIGQzRm9ybWF0KCcsJykoTWF0aC5yb3VuZChuKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZm9ybWF0TGFyZ2VOdW1iZXIobik7XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMucmVhbDpcbiAgICAgIGlmIChuIDwgMCkge1xuICAgICAgICByZXR1cm4gYC0ke2Zvcm1hdE51bWJlcigtbiwgJ251bWJlcicpfWA7XG4gICAgICB9XG4gICAgICBpZiAobiA8IDEwMDApIHtcbiAgICAgICAgcmV0dXJuIGQzRm9ybWF0KCcuNH5yJykobik7XG4gICAgICB9XG4gICAgICBpZiAobiA8IDEwICogMTAwMCkge1xuICAgICAgICByZXR1cm4gZDNGb3JtYXQoJywuMn5mJykobik7XG4gICAgICB9XG4gICAgICByZXR1cm4gZm9ybWF0TGFyZ2VOdW1iZXIobik7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZvcm1hdE51bWJlcihuLCAncmVhbCcpO1xuICB9XG59XG5cbmNvbnN0IHRyYW5zZm9ybWF0aW9uID0ge1xuICBZOiBNYXRoLnBvdygxMCwgMjQpLFxuICBaOiBNYXRoLnBvdygxMCwgMjEpLFxuICBFOiBNYXRoLnBvdygxMCwgMTgpLFxuICBQOiBNYXRoLnBvdygxMCwgMTUpLFxuICBUOiBNYXRoLnBvdygxMCwgMTIpLFxuICBHOiBNYXRoLnBvdygxMCwgOSksXG4gIE06IE1hdGgucG93KDEwLCA2KSxcbiAgazogTWF0aC5wb3coMTAsIDMpLFxuICBoOiBNYXRoLnBvdygxMCwgMiksXG4gIGRhOiBNYXRoLnBvdygxMCwgMSksXG4gIGQ6IE1hdGgucG93KDEwLCAtMSksXG4gIGM6IE1hdGgucG93KDEwLCAtMiksXG4gIG06IE1hdGgucG93KDEwLCAtMyksXG4gIM68OiBNYXRoLnBvdygxMCwgLTYpLFxuICBuOiBNYXRoLnBvdygxMCwgLTkpLFxuICBwOiBNYXRoLnBvdygxMCwgLTEyKSxcbiAgZjogTWF0aC5wb3coMTAsIC0xNSksXG4gIGE6IE1hdGgucG93KDEwLCAtMTgpLFxuICB6OiBNYXRoLnBvdygxMCwgLTIxKSxcbiAgeTogTWF0aC5wb3coMTAsIC0yNClcbn07XG5cbi8qKlxuICogQ29udmVydCBhIGZvcm1hdHRlZCBudW1iZXIgZnJvbSBzdHJpbmcgYmFjayB0byBudW1iZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldmVyc2VGb3JtYXROdW1iZXIoc3RyOiBzdHJpbmcpOiBudW1iZXIge1xuICBsZXQgcmV0dXJuVmFsdWU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBjb25zdCBzdHJOdW0gPSBzdHIudHJpbSgpLnJlcGxhY2UoLywvZywgJycpO1xuICBPYmplY3QuZW50cmllcyh0cmFuc2Zvcm1hdGlvbikuZm9yRWFjaChkID0+IHtcbiAgICBpZiAoc3RyTnVtLmluY2x1ZGVzKGRbMF0pKSB7XG4gICAgICByZXR1cm5WYWx1ZSA9IHBhcnNlRmxvYXQoc3RyTnVtKSAqIGRbMV07XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9KTtcblxuICAvLyBpZiBubyB0cmFuc2Zvcm1lciBmb3VuZCwgY29udmVydCB0byBudWJlciByZWdhcmRsZXNzXG4gIHJldHVybiByZXR1cm5WYWx1ZSA9PT0gbnVsbCA/IE51bWJlcihzdHJOdW0pIDogcmV0dXJuVmFsdWU7XG59XG5cbi8qKlxuICogRm9ybWF0IGVwb2NoIG1pbGxpc2Vjb25kcyB3aXRoIGEgZm9ybWF0IHN0cmluZ1xuICogQHR5cGUgdGltZXpvbmVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRhdGV0aW1lRm9ybWF0dGVyKFxuICB0aW1lem9uZT86IHN0cmluZyB8IG51bGxcbik6IChmb3JtYXQ/OiBzdHJpbmcpID0+ICh0czogbnVtYmVyKSA9PiBzdHJpbmcge1xuICByZXR1cm4gdGltZXpvbmVcbiAgICA/IGZvcm1hdCA9PiB0cyA9PiBtb21lbnQudXRjKHRzKS50eih0aW1lem9uZSkuZm9ybWF0KGZvcm1hdClcbiAgICA6IC8vIHJldHVybiBlbXB0eSBzdHJpbmcgaW5zdGVhZCBvZiAnSW52YWxpZCBkYXRlJyBpZiB0cyBpcyB1bmRlZmluZWQvbnVsbFxuICAgICAgZm9ybWF0ID0+IHRzID0+IHRzID8gbW9tZW50LnV0Yyh0cykuZm9ybWF0KGZvcm1hdCkgOiAnJztcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEsT0FBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsU0FBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsZUFBQSxHQUFBSCxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUcsTUFBQSxHQUFBSCxPQUFBO0FBRUEsSUFBQUksVUFBQSxHQUFBSixPQUFBO0FBT0EsSUFBQUssWUFBQSxHQUFBTCxPQUFBO0FBR0EsSUFBQU0sS0FBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8sTUFBQSxHQUFBUCxPQUFBO0FBQ0EsSUFBQVEsbUJBQUEsR0FBQVIsT0FBQTtBQUFxRCxJQUFBUyxxQkFBQSxFQXJCckQ7QUFDQTtBQXdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNPLElBQU1DLFlBQVksR0FBQUMsT0FBQSxDQUFBRCxZQUFBLEdBQUcsSUFBSTtBQUN6QixJQUFNRSxZQUFZLEdBQUFELE9BQUEsQ0FBQUMsWUFBQSxHQUFHLENBQUMsSUFBSTtBQUMxQixJQUFNQyxhQUFhLEdBQUFGLE9BQUEsQ0FBQUUsYUFBQSxHQUFHLEdBQUc7QUFDekIsSUFBTUMsYUFBYSxHQUFBSCxPQUFBLENBQUFHLGFBQUEsR0FBRyxDQUFDLEdBQUc7O0FBRWpDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBU0MsZ0JBQWdCQSxDQUFDQyxRQUE0QixFQUFVO0VBQ3JFLE9BQU9DLGtCQUFrQixDQUFDRCxRQUFRLGFBQVJBLFFBQVEsY0FBUkEsUUFBUSxHQUFJLENBQUMsRUFBRUosWUFBWSxFQUFFRixZQUFZLENBQUM7QUFDdEU7O0FBRUE7QUFD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