kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
534 lines (511 loc) • 63.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof3 = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.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 arrow = _interopRequireWildcard(require("apache-arrow"));
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 _FIELD_DISPLAY_FORMAT; // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof3(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
// 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
*
* @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 (data instanceof arrow.Vector) {
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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJhcnJvdyIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwicmVxdWlyZSIsIl9hc3NlcnQiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX2QzRm9ybWF0IiwiX21vbWVudFRpbWV6b25lIiwiX2Fycm93IiwiX2NvbnN0YW50cyIsIl9jb21tb25VdGlscyIsIl9wbG90IiwiX3V0aWxzIiwiX0ZJRUxEX0RJU1BMQVlfRk9STUFUIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJfdHlwZW9mMyIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIk1BWF9MQVRJVFVERSIsImV4cG9ydHMiLCJNSU5fTEFUSVRVREUiLCJNQVhfTE9OR0lUVURFIiwiTUlOX0xPTkdJVFVERSIsInZhbGlkYXRlTGF0aXR1ZGUiLCJsYXRpdHVkZSIsInZhbGlkYXRlQ29vcmRpbmF0ZSIsInZhbGlkYXRlTG9uZ2l0dWRlIiwibG9uZ2l0dWRlIiwidmFsdWUiLCJtaW5WYWx1ZSIsIm1heFZhbHVlIiwidW5pcXVlIiwidmFsdWVzIiwicmVzdWx0cyIsInVuaXF1ZVNldCIsIlNldCIsImZvckVhY2giLCJ2Iiwibm90TnVsbG9yVW5kZWZpbmVkIiwicHVzaCIsImdldExhdExuZ0JvdW5kcyIsInBvaW50cyIsImlkeCIsImxpbWl0IiwibGF0cyIsIm1hcCIsImQiLCJOdW1iZXIiLCJBcnJheSIsImlzQXJyYXkiLCJmaWx0ZXIiLCJpc0Zpbml0ZSIsInNvcnQiLCJudW1iZXJTb3J0IiwibGVuZ3RoIiwiTWF0aCIsIm1heCIsIm1pbiIsImNsYW1wIiwiX3JlZiIsIl9yZWYyIiwiX3NsaWNlZFRvQXJyYXkyIiwidmFsIiwiYXJndW1lbnRzIiwidW5kZWZpbmVkIiwiZ2V0U2FtcGxlRGF0YSIsImRhdGEiLCJzYW1wbGVTaXplIiwiZ2V0VmFsdWUiLCJzYW1wbGVTdGVwIiwiZmxvb3IiLCJvdXRwdXQiLCJ0aW1lVG9Vbml4TWlsbGkiLCJmb3JtYXQiLCJtb21lbnQiLCJ1dGMiLCJ2YWx1ZU9mIiwiRGF0ZSIsImlzTnVtYmVyIiwib2JqIiwicHJvcCIsInByb3RvdHlwZSIsImIiLCJnZXRTb3J0aW5nRnVuY3Rpb24iLCJmaWVsZFR5cGUiLCJBTExfRklFTERfVFlQRVMiLCJyZWFsIiwiaW50ZWdlciIsInRpbWVzdGFtcCIsInByZWNpc2VSb3VuZCIsIm51bSIsImRlY2ltYWxzIiwicG93Iiwicm91bmQiLCJzaWduIiwidG9GaXhlZCIsInJvdW5kVG9Gb3VyIiwiY29uY2F0IiwiZ2V0Um91bmRpbmdEZWNpbWFsRnJvbVN0ZXAiLCJzdGVwIiwiaXNOYU4iLCJhc3NlcnQiLCJzdGVwU3RyIiwidG9TdHJpbmciLCJzcGxpdEV4cG9uZW50aWFsIiwic3BsaXQiLCJjb2VmZlplcm8iLCJjb2VmZkRlY2ltYWwiLCJwYXJzZUludCIsInNwbGl0WmVybyIsIm5vcm1hbGl6ZVNsaWRlclZhbHVlIiwibWFya3MiLCJzbmFwVG9NYXJrcyIsInJvdW5kVmFsVG9TdGVwIiwiZGVjaW1hbCIsInN0ZXBzIiwicmVtYWluIiwiY2xvc2VzdCIsInJvdW5kZWQiLCJkZWZhdWx0Rm9ybWF0dGVyIiwiU3RyaW5nIiwiZmxvYXRGb3JtYXR0ZXIiLCJ1aW50OEFycmF5VG9IZXgiLCJmcm9tIiwiYnl0ZSIsInBhZFN0YXJ0Iiwiam9pbiIsIkZJRUxEX0RJU1BMQVlfRk9STUFUIiwiX2RlZmluZVByb3BlcnR5MiIsInN0cmluZyIsImRhdGUiLCJnZW9qc29uIiwiaXNQbGFpbk9iamVjdCIsIkpTT04iLCJzdHJpbmdpZnkiLCJnZW9hcnJvdyIsImZpZWxkIiwiVmVjdG9yIiwiX2ZpZWxkJG1ldGFkYXRhIiwiZW5jb2RpbmciLCJtZXRhZGF0YSIsImdlb21ldHJ5IiwicGFyc2VHZW9tZXRyeUZyb21BcnJvdyIsImVycm9yIiwiVWludDhBcnJheSIsIm9iamVjdCIsImFycmF5IiwiaDMiLCJwYXJzZUZpZWxkVmFsdWUiLCJ0eXBlIiwiZ2V0Rm9ybWF0dGVyIiwidG9vbHRpcEZvcm1hdCIsIlRPT0xUSVBfRk9STUFUUyIsImZpbmQiLCJmIiwiVE9PTFRJUF9LRVkiLCJhcHBseURlZmF1bHRGb3JtYXQiLCJhcHBseUN1c3RvbUZvcm1hdCIsImdldENvbHVtbkZvcm1hdHRlciIsImRpc3BsYXlGb3JtYXQiLCJfdHlwZW9mMiIsImFwcGx5VmFsdWVNYXAiLCJUT09MVElQX0ZPUk1BVF9UWVBFUyIsIkRFQ0lNQUwiLCJkM0Zvcm1hdCIsIkRBVEUiLCJEQVRFX1RJTUUiLCJkYXRldGltZUZvcm1hdHRlciIsIlBFUkNFTlRBR0UiLCJERUNJTUFMX0RFQ0lNQUxfRklYRURfMiIsIkJPT0xFQU4iLCJnZXRCb29sZWFuRm9ybWF0dGVyIiwiZm9ybWF0TGFyZ2VOdW1iZXIiLCJmb3JtYXROdW1iZXIiLCJ0cmFuc2Zvcm1hdGlvbiIsIlkiLCJaIiwiRSIsIlAiLCJUIiwiRyIsIk0iLCJrIiwiaCIsImRhIiwiYyIsIm0iLCLOvCIsInAiLCJ6IiwieSIsInJldmVyc2VGb3JtYXROdW1iZXIiLCJzdHIiLCJyZXR1cm5WYWx1ZSIsInN0ck51bSIsInRyaW0iLCJyZXBsYWNlIiwiZW50cmllcyIsImluY2x1ZGVzIiwicGFyc2VGbG9hdCIsInRpbWV6b25lIiwidHMiLCJ0eiJdLCJzb3VyY2VzIjpbIi4uL3NyYy9kYXRhLXV0aWxzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCAqIGFzIGFycm93IGZyb20gJ2FwYWNoZS1hcnJvdyc7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQge2Zvcm1hdCBhcyBkM0Zvcm1hdH0gZnJvbSAnZDMtZm9ybWF0JztcbmltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50LXRpbWV6b25lJztcblxuaW1wb3J0IHtwYXJzZUdlb21ldHJ5RnJvbUFycm93fSBmcm9tICdAbG9hZGVycy5nbC9hcnJvdyc7XG5cbmltcG9ydCB7XG4gIEFMTF9GSUVMRF9UWVBFUyxcbiAgVE9PTFRJUF9GT1JNQVRTLFxuICBUT09MVElQX0ZPUk1BVF9UWVBFUyxcbiAgVE9PTFRJUF9LRVksXG4gIFRvb2x0aXBGb3JtYXRcbn0gZnJvbSAnQGtlcGxlci5nbC9jb25zdGFudHMnO1xuaW1wb3J0IHtub3ROdWxsb3JVbmRlZmluZWR9IGZyb20gJ0BrZXBsZXIuZ2wvY29tbW9uLXV0aWxzJztcbmltcG9ydCB7RmllbGQsIE1pbGxpc2Vjb25kLCBQcm90b0RhdGFzZXRGaWVsZH0gZnJvbSAnQGtlcGxlci5nbC90eXBlcyc7XG5cbmltcG9ydCB7c25hcFRvTWFya3N9IGZyb20gJy4vcGxvdCc7XG5pbXBvcnQge2lzUGxhaW5PYmplY3R9IGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgdHlwZSBGaWVsZEZvcm1hdHRlciA9ICh2YWx1ZTogYW55LCBmaWVsZD86IFByb3RvRGF0YXNldEZpZWxkKSA9PiBzdHJpbmc7XG5cbi8vIFdlIG5lZWQgdGhyZWF0IGxhdGl0dWRlIGRpZmZlcmVudGx5IG90aGVyd2lzZSBtZXJjYXRvciBwcm9qZWN0IHZpZXcgdGhyb3dzXG4vLyBhIHByb2plY3Rpb24gbWF0cml4IGVycm9yXG4vLyBVbmNhdWdodCBFcnJvcjogUGl4ZWwgcHJvamVjdCBtYXRyaXggbm90IGludmVydGlibGVcbi8vIGF0IFdlYk1lcmNhdG9yVmlld3BvcnQxNi5WaWV3cG9ydDYgKHZpZXdwb3J0LmpzOjgxOjEzKVxuZXhwb3J0IGNvbnN0IE1BWF9MQVRJVFVERSA9IDg5Ljk7XG5leHBvcnQgY29uc3QgTUlOX0xBVElUVURFID0gLTg5Ljk7XG5leHBvcnQgY29uc3QgTUFYX0xPTkdJVFVERSA9IDE4MDtcbmV4cG9ydCBjb25zdCBNSU5fTE9OR0lUVURFID0gLTE4MDtcblxuLyoqXG4gKiBWYWxpZGF0ZXMgYSBsYXRpdHVkZSB2YWx1ZS5cbiAqIEVuc3VyZXMgdGhhdCB0aGUgbGF0aXR1ZGUgaXMgd2l0aGluIHRoZSBkZWZpbmVkIG1pbmltdW0gYW5kIG1heGltdW0gbGF0aXR1ZGUgYm91bmRzLlxuICogSWYgdGhlIHZhbHVlIGlzIG91dCBvZiBib3VuZHMsIGl0IHJldHVybnMgdGhlIG5lYXJlc3QgYm91bmQgdmFsdWUuXG4gKiBAcGFyYW0gbGF0aXR1ZGUgLSBUaGUgbGF0aXR1ZGUgdmFsdWUgdG8gdmFsaWRhdGUuXG4gKiBAcmV0dXJucyBUaGUgdmFsaWRhdGVkIGxhdGl0dWRlIHZhbHVlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVMYXRpdHVkZShsYXRpdHVkZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcbiAgcmV0dXJuIHZhbGlkYXRlQ29vcmRpbmF0ZShsYXRpdHVkZSA/PyAwLCBNSU5fTEFUSVRVREUsIE1BWF9MQVRJVFVERSk7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIGEgbG9uZ2l0dWRlIHZhbHVlLlxuICogRW5zdXJlcyB0aGF0IHRoZSBsb25naXR1ZGUgaXMgd2l0aGluIHRoZSBkZWZpbmVkIG1pbmltdW0gYW5kIG1heGltdW0gbG9uZ2l0dWRlIGJvdW5kcy5cbiAqIElmIHRoZSB2YWx1ZSBpcyBvdXQgb2YgYm91bmRzLCBpdCByZXR1cm5zIHRoZSBuZWFyZXN0IGJvdW5kIHZhbHVlLlxuICogQHBhcmFtIGxvbmdpdHVkZSAtIFRoZSBsb25naXR1ZGUgdmFsdWUgdG8gdmFsaWRhdGUuXG4gKiBAcmV0dXJucyBUaGUgdmFsaWRhdGVkIGxvbmdpdHVkZSB2YWx1ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlTG9uZ2l0dWRlKGxvbmdpdHVkZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcbiAgcmV0dXJuIHZhbGlkYXRlQ29vcmRpbmF0ZShsb25naXR1ZGUgPz8gMCwgTUlOX0xPTkdJVFVERSwgTUFYX0xPTkdJVFVERSk7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIGEgY29vcmRpbmF0ZSB2YWx1ZS5cbiAqIEVuc3VyZXMgdGhhdCB0aGUgdmFsdWUgaXMgd2l0aGluIHRoZSBzcGVjaWZpZWQgbWluaW11bSBhbmQgbWF4aW11bSBib3VuZHMuXG4gKiBJZiB0aGUgdmFsdWUgaXMgb3V0IG9mIGJvdW5kcywgaXQgcmV0dXJucyB0aGUgbmVhcmVzdCBib3VuZCB2YWx1ZS5cbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBjb29yZGluYXRlIHZhbHVlIHRvIHZhbGlkYXRlLlxuICogQHBhcmFtIG1pblZhbHVlIC0gVGhlIG1pbmltdW0gYm91bmQgZm9yIHRoZSB2YWx1ZS5cbiAqIEBwYXJhbSBtYXhWYWx1ZSAtIFRoZSBtYXhpbXVtIGJvdW5kIGZvciB0aGUgdmFsdWUuXG4gKiBAcmV0dXJucyBUaGUgdmFsaWRhdGVkIGNvb3JkaW5hdGUgdmFsdWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUNvb3JkaW5hdGUodmFsdWU6IG51bWJlciwgbWluVmFsdWU6IG51bWJlciwgbWF4VmFsdWU6IG51bWJlcik6IG51bWJlciB7XG4gIGlmICh2YWx1ZSA8PSBtaW5WYWx1ZSkge1xuICAgIHJldHVybiBtaW5WYWx1ZTtcbiAgfVxuICBpZiAodmFsdWUgPj0gbWF4VmFsdWUpIHtcbiAgICByZXR1cm4gbWF4VmFsdWU7XG4gIH1cblxuICByZXR1cm4gdmFsdWU7XG59XG5cbi8qKlxuICogc2ltcGxlIGdldHRpbmcgdW5pcXVlIHZhbHVlcyBvZiBhbiBhcnJheVxuICpcbiAqIEBwYXJhbSB2YWx1ZXNcbiAqIEByZXR1cm5zIHVuaXF1ZSB2YWx1ZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuaXF1ZTxUPih2YWx1ZXM6IFRbXSkge1xuICBjb25zdCByZXN1bHRzOiBUW10gPSBbXTtcbiAgY29uc3QgdW5pcXVlU2V0ID0gbmV3IFNldCh2YWx1ZXMpO1xuICB1bmlxdWVTZXQuZm9yRWFjaCh2ID0+IHtcbiAgICBpZiAobm90TnVsbG9yVW5kZWZpbmVkKHYpKSB7XG4gICAgICByZXN1bHRzLnB1c2godik7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHJlc3VsdHM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMYXRMbmdCb3VuZHMoXG4gIHBvaW50czogbnVtYmVyW11bXSxcbiAgaWR4OiBudW1iZXIsXG4gIGxpbWl0OiBbbnVtYmVyLCBudW1iZXJdXG4pOiBbbnVtYmVyLCBudW1iZXJdIHwgbnVsbCB7XG4gIGNvbnN0IGxhdHMgPSBwb2ludHNcbiAgICAubWFwKGQgPT4gTnVtYmVyKEFycmF5LmlzQXJyYXkoZCkpICYmIGRbaWR4XSlcbiAgICAuZmlsdGVyKE51bWJlci5pc0Zpbml0ZSlcbiAgICAuc29ydChudW1iZXJTb3J0KTtcblxuICBpZiAoIWxhdHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvLyBjbGFtcCB0byBsaW1pdFxuICByZXR1cm4gW01hdGgubWF4KGxhdHNbMF0sIGxpbWl0WzBdKSwgTWF0aC5taW4obGF0c1tsYXRzLmxlbmd0aCAtIDFdLCBsaW1pdFsxXSldO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2xhbXAoW21pbiwgbWF4XTogW251bWJlciwgbnVtYmVyXSwgdmFsID0gMCk6IG51bWJlciB7XG4gIHJldHVybiB2YWwgPD0gbWluID8gbWluIDogdmFsID49IG1heCA/IG1heCA6IHZhbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNhbXBsZURhdGEoZGF0YSwgc2FtcGxlU2l6ZSA9IDUwMCwgZ2V0VmFsdWUgPSBkID0+IGQpIHtcbiAgY29uc3Qgc2FtcGxlU3RlcCA9IE1hdGgubWF4KE1hdGguZmxvb3IoZGF0YS5sZW5ndGggLyBzYW1wbGVTaXplKSwgMSk7XG4gIGNvbnN0IG91dHB1dDogYW55W10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSArPSBzYW1wbGVTdGVwKSB7XG4gICAgb3V0cHV0LnB1c2goZ2V0VmFsdWUoZGF0YVtpXSkpO1xuICB9XG5cbiAgcmV0dXJuIG91dHB1dDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGRpZmZlcmVudCB0aW1lIGZvcm1hdCB0byB1bml4IG1pbGxpc2Vjb25kc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdGltZVRvVW5peE1pbGxpKHZhbHVlOiBzdHJpbmcgfCBudW1iZXIgfCBEYXRlLCBmb3JtYXQ6IHN0cmluZyk6IE1pbGxpc2Vjb25kIHwgbnVsbCB7XG4gIGlmIChub3ROdWxsb3JVbmRlZmluZWQodmFsdWUpKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBtb21lbnQudXRjKHZhbHVlLCBmb3JtYXQpLnZhbHVlT2YoKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIHJldHVybiBmb3JtYXQgPT09ICd4JyA/IHZhbHVlICogMTAwMCA6IHZhbHVlO1xuICAgIH1cbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICByZXR1cm4gdmFsdWUudmFsdWVPZigpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGQgaXMgYSBudW1iZXIsIHRoaXMgZmlsdGVyZWQgb3V0IE5hTiBhcyB3ZWxsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc051bWJlcihkOiB1bmtub3duKTogZCBpcyBudW1iZXIge1xuICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKGQpO1xufVxuXG4vKipcbiAqIHdoZXRoZXIgb2JqZWN0IGhhcyBwcm9wZXJ0eVxuICogQHBhcmFtIHtzdHJpbmd9IHByb3BcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIHllcyBvciBub1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzT3duUHJvcGVydHk8WCBleHRlbmRzIG9iamVjdCwgWSBleHRlbmRzIFByb3BlcnR5S2V5PihcbiAgb2JqOiBYLFxuICBwcm9wOiBZXG4pOiBvYmogaXMgWCAmIFJlY29yZDxZLCB1bmtub3duPiB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG51bWJlclNvcnQoYTogbnVtYmVyLCBiOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gYSAtIGI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTb3J0aW5nRnVuY3Rpb24oZmllbGRUeXBlOiBzdHJpbmcpOiB0eXBlb2YgbnVtYmVyU29ydCB8IHVuZGVmaW5lZCB7XG4gIHN3aXRjaCAoZmllbGRUeXBlKSB7XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMucmVhbDpcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5pbnRlZ2VyOlxuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLnRpbWVzdGFtcDpcbiAgICAgIHJldHVybiBudW1iZXJTb3J0O1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKlxuICogcm91bmQgbnVtYmVyIHdpdGggZXhhY3QgbnVtYmVyIG9mIGRlY2ltYWxzXG4gKiByZXR1cm4gYXMgYSBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByZWNpc2VSb3VuZChudW06IG51bWJlciwgZGVjaW1hbHM6IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IHQgPSBNYXRoLnBvdygxMCwgZGVjaW1hbHMpO1xuICByZXR1cm4gKFxuICAgIE1hdGgucm91bmQoXG4gICAgICBudW0gKiB0ICsgKGRlY2ltYWxzID4gMCA/IDEgOiAwKSAqIChNYXRoLnNpZ24obnVtKSAqICgxMCAvIE1hdGgucG93KDEwMCwgZGVjaW1hbHMpKSlcbiAgICApIC8gdFxuICApLnRvRml4ZWQoZGVjaW1hbHMpO1xufVxuXG4vKipcbiAqIHJvdW5kIGEgZ2l2aW5nIG51bWJlciBhdCBtb3N0IDQgZGVjaW1hbCBwbGFjZXNcbiAqIGUuZy4gMTAgLT4gMTAsIDEuMTIzNDUgLT4gMS4yMzQ1LCAyLjAgLT4gMlxuICovXG5leHBvcnQgZnVuY3Rpb24gcm91bmRUb0ZvdXIobnVtOiBudW1iZXIpOiBudW1iZXIge1xuICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gIHJldHVybiBOdW1iZXIoYCR7TWF0aC5yb3VuZChgJHtudW19ZSs0YCl9ZS00YCk7XG59XG4vKipcbiAqIGdldCBudW1iZXIgb2YgZGVjaW1hbHMgdG8gcm91bmQgdG8gZm9yIHNsaWRlciBmcm9tIHN0ZXBcbiAqIEBwYXJhbSBzdGVwXG4gKiBAcmV0dXJucy0gbnVtYmVyIG9mIGRlY2ltYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFJvdW5kaW5nRGVjaW1hbEZyb21TdGVwKHN0ZXA6IG51bWJlcik6IG51bWJlciB7XG4gIGlmIChpc05hTihzdGVwKSkge1xuICAgIGFzc2VydCgnc3RlcCBpcyBub3QgYSBudW1iZXInKTtcbiAgICBhc3NlcnQoc3RlcCk7XG4gIH1cblxuICBjb25zdCBzdGVwU3RyID0gc3RlcC50b1N0cmluZygpO1xuXG4gIC8vIGluIGNhc2UgdGhlIHN0ZXAgaXMgYSB2ZXJ5IHNtYWxsIG51bWJlciBlLmcuIDFlLTcsIHJldHVybiBkZWNpbWFsIGUuZy4gNyBkaXJlY3RseVxuICBjb25zdCBzcGxpdEV4cG9uZW50aWFsID0gc3RlcFN0ci5zcGxpdCgnZS0nKTtcbiAgaWYgKHNwbGl0RXhwb25lbnRpYWwubGVuZ3RoID09PSAyKSB7XG4gICAgY29uc3QgY29lZmZaZXJvID0gc3BsaXRFeHBvbmVudGlhbFswXS5zcGxpdCgnLicpO1xuICAgIGNvbnN0IGNvZWZmRGVjaW1hbCA9IGNvZWZmWmVyby5sZW5ndGggPT09IDEgPyAwIDogY29lZmZaZXJvWzFdLmxlbmd0aDtcbiAgICByZXR1cm4gcGFyc2VJbnQoc3BsaXRFeHBvbmVudGlhbFsxXSwgMTApICsgY29lZmZEZWNpbWFsO1xuICB9XG5cbiAgY29uc3Qgc3BsaXRaZXJvID0gc3RlcFN0ci5zcGxpdCgnLicpO1xuICBpZiAoc3BsaXRaZXJvLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiAwO1xuICB9XG4gIHJldHVybiBzcGxpdFplcm9bMV0ubGVuZ3RoO1xufVxuXG4vKipcbiAqIElmIG1hcmtzIGlzIHByb3ZpZGVkLCBzbmFwIHRvIG1hcmtzLCBpZiBub3Qgbm9ybWFsaXplIHRvIHN0ZXBcbiAqIEBwYXJhbSB2YWxcbiAqIEBwYXJhbSBtaW5WYWx1ZVxuICogQHBhcmFtIHN0ZXBcbiAqIEBwYXJhbSBtYXJrc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplU2xpZGVyVmFsdWUoXG4gIHZhbDogbnVtYmVyLFxuICBtaW5WYWx1ZTogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICBzdGVwOiBudW1iZXIsXG4gIG1hcmtzPzogbnVtYmVyW10gfCBudWxsXG4pOiBudW1iZXIge1xuICBpZiAobWFya3MgJiYgbWFya3MubGVuZ3RoKSB7XG4gICAgLy8gVXNlIGluIHNsaWRlciwgZ2l2ZW4gYSBudW1iZXIgYW5kIGFuIGFycmF5IG9mIG51bWJlcnMsIHJldHVybiB0aGUgbmVhcnMgbnVtYmVyIGZyb20gdGhlIGFycmF5XG4gICAgcmV0dXJuIHNuYXBUb01hcmtzKHZhbCwgbWFya3MpO1xuICB9XG5cbiAgcmV0dXJuIHJvdW5kVmFsVG9TdGVwKG1pblZhbHVlLCBzdGVwLCB2YWwpO1xufVxuXG4vKipcbiAqIHJvdW5kIHRoZSB2YWx1ZSB0byBzdGVwIGZvciB0aGUgc2xpZGVyXG4gKiBAcGFyYW0gbWluVmFsdWVcbiAqIEBwYXJhbSBzdGVwXG4gKiBAcGFyYW0gdmFsXG4gKiBAcmV0dXJucyAtIHJvdW5kZWQgbnVtYmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByb3VuZFZhbFRvU3RlcChtaW5WYWx1ZTogbnVtYmVyIHwgdW5kZWZpbmVkLCBzdGVwOiBudW1iZXIsIHZhbDogbnVtYmVyKTogbnVtYmVyIHtcbiAgaWYgKCFpc051bWJlcihzdGVwKSB8fCAhaXNOdW1iZXIobWluVmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbDtcbiAgfVxuXG4gIGNvbnN0IGRlY2ltYWwgPSBnZXRSb3VuZGluZ0RlY2ltYWxGcm9tU3RlcChzdGVwKTtcbiAgY29uc3Qgc3RlcHMgPSBNYXRoLmZsb29yKCh2YWwgLSBtaW5WYWx1ZSkgLyBzdGVwKTtcbiAgbGV0IHJlbWFpbiA9IHZhbCAtIChzdGVwcyAqIHN0ZXAgKyBtaW5WYWx1ZSk7XG5cbiAgLy8gaGFzIHRvIHJvdW5kIGJlY2F1c2UgamF2YXNjcmlwdCB0dXJucyAwLjEgaW50byAwLjk5OTk5OTk5OTk5OTk5ODdcbiAgcmVtYWluID0gTnVtYmVyKHByZWNpc2VSb3VuZChyZW1haW4sIDgpKTtcblxuICBsZXQgY2xvc2VzdDogbnVtYmVyO1xuICBpZiAocmVtYWluID09PSAwKSB7XG4gICAgY2xvc2VzdCA9IHZhbDtcbiAgfSBlbHNlIGlmIChyZW1haW4gPCBzdGVwIC8gMikge1xuICAgIGNsb3Nlc3QgPSBzdGVwcyAqIHN0ZXAgKyBtaW5WYWx1ZTtcbiAgfSBlbHNlIHtcbiAgICBjbG9zZXN0ID0gKHN0ZXBzICsgMSkgKiBzdGVwICsgbWluVmFsdWU7XG4gIH1cblxuICAvLyBwcmVjaXNlIHJvdW5kIHJldHVybiBhIHN0cmluZyByb3VuZGVkIHRvIHRoZSBkZWZpbmVkIGRlY2ltYWxcbiAgY29uc3Qgcm91bmRlZCA9IHByZWNpc2VSb3VuZChjbG9zZXN0LCBkZWNpbWFsKTtcblxuICByZXR1cm4gTnVtYmVyKHJvdW5kZWQpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgdmFsdWUgZm9ybWF0IGJhc2VkIG9uIGZpZWxkIGFuZCBmb3JtYXQgb3B0aW9uc1xuICogVXNlZCBpbiByZW5kZXIgdG9vbHRpcCB2YWx1ZVxuICovXG5leHBvcnQgY29uc3QgZGVmYXVsdEZvcm1hdHRlcjogRmllbGRGb3JtYXR0ZXIgPSB2ID0+IChub3ROdWxsb3JVbmRlZmluZWQodikgPyBTdHJpbmcodikgOiAnJyk7XG5cbmV4cG9ydCBjb25zdCBmbG9hdEZvcm1hdHRlciA9IHYgPT4gKGlzTnVtYmVyKHYpID8gU3RyaW5nKHJvdW5kVG9Gb3VyKHYpKSA6ICcnKTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIGEgV0tCIGluIFVpbnQ4QXJyYXkgZm9ybSBpbnRvIGEgaGV4IFdLQiBzdHJpbmcuXG4gKiBAcGFyYW0gdWludDhBcnJheSBXS0IgaW4gVWludDhBcnJheSBmb3JtLlxuICogQHJldHVybnMgaGV4IFdLQiBzdHJpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1aW50OEFycmF5VG9IZXgoZGF0YTogVWludDhBcnJheSk6IHN0cmluZyB7XG4gIHJldHVybiBBcnJheS5mcm9tKGRhdGEpXG4gICAgLm1hcChieXRlID0+IChieXRlIGFzIGFueSkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICcwJykpXG4gICAgLmpvaW4oJycpO1xufVxuXG5leHBvcnQgY29uc3QgRklFTERfRElTUExBWV9GT1JNQVQ6IHtcbiAgW2tleTogc3RyaW5nXTogRmllbGRGb3JtYXR0ZXI7XG59ID0ge1xuICBbQUxMX0ZJRUxEX1RZUEVTLnN0cmluZ106IGRlZmF1bHRGb3JtYXR0ZXIsXG4gIFtBTExfRklFTERfVFlQRVMudGltZXN0YW1wXTogZGVmYXVsdEZvcm1hdHRlcixcbiAgW0FMTF9GSUVMRF9UWVBFUy5pbnRlZ2VyXTogZGVmYXVsdEZvcm1hdHRlcixcbiAgW0FMTF9GSUVMRF9UWVBFUy5yZWFsXTogZGVmYXVsdEZvcm1hdHRlcixcbiAgW0FMTF9GSUVMRF9UWVBFUy5ib29sZWFuXTogZGVmYXVsdEZvcm1hdHRlcixcbiAgW0FMTF9GSUVMRF9UWVBFUy5kYXRlXTogZGVmYXVsdEZvcm1hdHRlcixcbiAgW0FMTF9GSUVMRF9UWVBFUy5nZW9qc29uXTogZCA9PlxuICAgIHR5cGVvZiBkID09PSAnc3RyaW5nJ1xuICAgICAgPyBkXG4gICAgICA6IGlzUGxhaW5PYmplY3QoZClcbiAgICAgID8gSlNPTi5zdHJpbmdpZnkoZClcbiAgICAgIDogQXJyYXkuaXNBcnJheShkKVxuICAgICAgPyBgWyR7U3RyaW5nKGQpfV1gXG4gICAgICA6ICcnLFxuICBbQUxMX0ZJRUxEX1RZUEVTLmdlb2Fycm93XTogKGRhdGEsIGZpZWxkKSA9PiB7XG4gICAgaWYgKGRhdGEgaW5zdGFuY2VvZiBhcnJvdy5WZWN0b3IpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGVuY29kaW5nID0gZmllbGQ/Lm1ldGFkYXRhPy5nZXQoJ0FSUk9XOmV4dGVuc2lvbjpuYW1lJyk7XG4gICAgICAgIGlmIChlbmNvZGluZykge1xuICAgICAgICAgIGNvbnN0IGdlb21ldHJ5ID0gcGFyc2VHZW9tZXRyeUZyb21BcnJvdyhkYXRhLCBlbmNvZGluZyk7XG4gICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGdlb21ldHJ5KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gaWdub3JlIGZvciBub3dcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGRhdGEgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICByZXR1cm4gdWludDhBcnJheVRvSGV4KGRhdGEpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0YTtcbiAgfSxcbiAgW0FMTF9GSUVMRF9UWVBFUy5vYmplY3RdOiAodmFsdWU6IGFueSkgPT4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICAgIH1cbiAgfSxcbiAgW0FMTF9GSUVMRF9UWVBFUy5hcnJheV06IGQgPT4gSlNPTi5zdHJpbmdpZnkoZCksXG4gIFtBTExfRklFTERfVFlQRVMuaDNdOiBkZWZhdWx0Rm9ybWF0dGVyXG59O1xuXG4vKipcbiAqIFBhcnNlIGZpZWxkIHZhbHVlIGFuZCB0eXBlIGFuZCByZXR1cm4gYSBzdHJpbmcgcmVwcmVzZW50YXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IHBhcnNlRmllbGRWYWx1ZSA9ICh2YWx1ZTogYW55LCB0eXBlOiBzdHJpbmcsIGZpZWxkPzogRmllbGQpOiBzdHJpbmcgPT4ge1xuICBpZiAoIW5vdE51bGxvclVuZGVmaW5lZCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cbiAgLy8gQmlnSW50IHZhbHVlcyBjYW5ub3QgYmUgc2VyaWFsaXplZCB3aXRoIEpTT04uc3RyaW5naWZ5KCkgZGlyZWN0bHlcbiAgLy8gV2UgbmVlZCB0byBleHBsaWNpdGx5IGNvbnZlcnQgdGhlbSB0byBzdHJpbmdzIHVzaW5nIC50b1N0cmluZygpXG4gIC8vIFNlZTogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQmlnSW50I3VzZV93aXRoaW5fanNvblxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnYmlnaW50Jykge1xuICAgIHJldHVybiB2YWx1ZS50b1N0cmluZygpO1xuICB9XG4gIHJldHVybiBGSUVMRF9ESVNQTEFZX0ZPUk1BVFt0eXBlXSA/IEZJRUxEX0RJU1BMQVlfRk9STUFUW3R5cGVdKHZhbHVlLCBmaWVsZCkgOiBTdHJpbmcodmFsdWUpO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIHZhbHVlIGZvcm1hdCBiYXNlZCBvbiBmaWVsZCBhbmQgZm9ybWF0IG9wdGlvbnNcbiAqIFVzZWQgaW4gcmVuZGVyIHRvb2x0aXAgdmFsdWVcbiAqIEBwYXJhbSBmb3JtYXRcbiAqIEBwYXJhbSBmaWVsZFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Rm9ybWF0dGVyKFxuICBmb3JtYXQ/OiBzdHJpbmcgfCBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbCxcbiAgZmllbGQ/OiBGaWVsZFxuKTogRmllbGRGb3JtYXR0ZXIge1xuICBpZiAoIWZvcm1hdCkge1xuICAgIHJldHVybiBkZWZhdWx0Rm9ybWF0dGVyO1xuICB9XG4gIGNvbnN0IHRvb2x0aXBGb3JtYXQgPSBPYmplY3QudmFsdWVzKFRPT0xUSVBfRk9STUFUUykuZmluZChmID0+IGZbVE9PTFRJUF9LRVldID09PSBmb3JtYXQpO1xuXG4gIGlmICh0b29sdGlwRm9ybWF0KSB7XG4gICAgcmV0dXJuIGFwcGx5RGVmYXVsdEZvcm1hdCh0b29sdGlwRm9ybWF0IGFzIFRvb2x0aXBGb3JtYXQpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBmb3JtYXQgPT09ICdzdHJpbmcnICYmIGZpZWxkKSB7XG4gICAgcmV0dXJuIGFwcGx5Q3VzdG9tRm9ybWF0KGZvcm1hdCwgZmllbGQpO1xuICB9XG5cbiAgcmV0dXJuIGRlZmF1bHRGb3JtYXR0ZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb2x1bW5Gb3JtYXR0ZXIoXG4gIGZpZWxkOiBQaWNrPEZpZWxkLCAndHlwZSc+ICYgUGFydGlhbDxQaWNrPEZpZWxkLCAnZm9ybWF0JyB8ICdkaXNwbGF5Rm9ybWF0Jz4+XG4pOiBGaWVsZEZvcm1hdHRlciB7XG4gIGNvbnN0IHtmb3JtYXQsIGRpc3BsYXlGb3JtYXR9ID0gZmllbGQ7XG5cbiAgaWYgKCFmb3JtYXQgJiYgIWRpc3BsYXlGb3JtYXQpIHtcbiAgICByZXR1cm4gRklFTERfRElTUExBWV9GT1JNQVRbZmllbGQudHlwZV07XG4gIH1cbiAgY29uc3QgdG9vbHRpcEZvcm1hdCA9IE9iamVjdC52YWx1ZXMoVE9PTFRJUF9GT1JNQVRTKS5maW5kKGYgPT4gZltUT09MVElQX0tFWV0gPT09IGRpc3BsYXlGb3JtYXQpO1xuXG4gIGlmICh0b29sdGlwRm9ybWF0KSB7XG4gICAgcmV0dXJuIGFwcGx5RGVmYXVsdEZvcm1hdCh0b29sdGlwRm9ybWF0KTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgZGlzcGxheUZvcm1hdCA9PT0gJ3N0cmluZycgJiYgZmllbGQpIHtcbiAgICByZXR1cm4gYXBwbHlDdXN0b21Gb3JtYXQoZGlzcGxheUZvcm1hdCwgZmllbGQpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBkaXNwbGF5Rm9ybWF0ID09PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBhcHBseVZhbHVlTWFwKGRpc3BsYXlGb3JtYXQpO1xuICB9XG5cbiAgcmV0dXJuIGRlZmF1bHRGb3JtYXR0ZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVZhbHVlTWFwKGZvcm1hdCkge1xuICByZXR1cm4gdiA9PiBmb3JtYXRbdl07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseURlZmF1bHRGb3JtYXQodG9vbHRpcEZvcm1hdDogVG9vbHRpcEZvcm1hdCk6ICh2OiBhbnkpID0+IHN0cmluZyB7XG4gIGlmICghdG9vbHRpcEZvcm1hdCB8fCAhdG9vbHRpcEZvcm1hdC5mb3JtYXQpIHtcbiAgICByZXR1cm4gZGVmYXVsdEZvcm1hdHRlcjtcbiAgfVxuXG4gIHN3aXRjaCAodG9vbHRpcEZvcm1hdC50eXBlKSB7XG4gICAgY2FzZSBUT09MVElQX0ZPUk1BVF9UWVBFUy5ERUNJTUFMOlxuICAgICAgcmV0dXJuIGQzRm9ybWF0KHRvb2x0aXBGb3JtYXQuZm9ybWF0KTtcbiAgICBjYXNlIFRPT0xUSVBfRk9STUFUX1RZUEVTLkRBVEU6XG4gICAgY2FzZSBUT09MVElQX0ZPUk1BVF9UWVBFUy5EQVRFX1RJTUU6XG4gICAgICByZXR1cm4gZGF0ZXRpbWVGb3JtYXR0ZXIobnVsbCkodG9vbHRpcEZvcm1hdC5mb3JtYXQpO1xuICAgIGNhc2UgVE9PTFRJUF9GT1JNQVRfVFlQRVMuUEVSQ0VOVEFHRTpcbiAgICAgIHJldHVybiB2ID0+IGAke2QzRm9ybWF0KFRPT0xUSVBfRk9STUFUUy5ERUNJTUFMX0RFQ0lNQUxfRklYRURfMi5mb3JtYXQpKHYpfSVgO1xuICAgIGNhc2UgVE9PTFRJUF9GT1JNQVRfVFlQRVMuQk9PTEVBTjpcbiAgICAgIHJldHVybiBnZXRCb29sZWFuRm9ybWF0dGVyKHRvb2x0aXBGb3JtYXQuZm9ybWF0KTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGRlZmF1bHRGb3JtYXR0ZXI7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEJvb2xlYW5Gb3JtYXR0ZXIoZm9ybWF0OiBzdHJpbmcpOiBGaWVsZEZvcm1hdHRlciB7XG4gIHN3aXRjaCAoZm9ybWF0KSB7XG4gICAgY2FzZSAnMDEnOlxuICAgICAgcmV0dXJuICh2OiBib29sZWFuKSA9PiAodiA/ICcxJyA6ICcwJyk7XG4gICAgY2FzZSAneW4nOlxuICAgICAgcmV0dXJuICh2OiBib29sZWFuKSA9PiAodiA/ICd5ZXMnIDogJ25vJyk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBkZWZhdWx0Rm9ybWF0dGVyO1xuICB9XG59XG4vLyBBbGxvdyB1c2VyIHRvIHNwZWNpZnkgY3VzdG9tIHRvb2x0aXAgZm9ybWF0IHZpYSBjb25maWdcbmV4cG9ydCBmdW5jdGlvbiBhcHBseUN1c3RvbUZvcm1hdChmb3JtYXQsIGZpZWxkOiB7dHlwZT86IHN0cmluZ30pOiBGaWVsZEZvcm1hdHRlciB7XG4gIHN3aXRjaCAoZmllbGQudHlwZSkge1xuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLnJlYWw6XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMuaW50ZWdlcjpcbiAgICAgIHJldHVybiBkM0Zvcm1hdChmb3JtYXQpO1xuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmRhdGU6XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMudGltZXN0YW1wOlxuICAgICAgcmV0dXJuIGRhdGV0aW1lRm9ybWF0dGVyKG51bGwpKGZvcm1hdCk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB2ID0+IHY7XG4gIH1cbn1cblxuZnVuY3Rpb24gZm9ybWF0TGFyZ2VOdW1iZXIobikge1xuICAvLyBTSS1wcmVmaXggd2l0aCA0IHNpZ25pZmljYW50IGRpZ2l0c1xuICByZXR1cm4gZDNGb3JtYXQoJy40fnMnKShuKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdE51bWJlcihuOiBudW1iZXIsIHR5cGU/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5pbnRlZ2VyOlxuICAgICAgaWYgKG4gPCAwKSB7XG4gICAgICAgIHJldHVybiBgLSR7Zm9ybWF0TnVtYmVyKC1uLCAnaW50ZWdlcicpfWA7XG4gICAgICB9XG4gICAgICBpZiAobiA8IDEwMDApIHtcbiAgICAgICAgcmV0dXJuIGAke01hdGgucm91bmQobil9YDtcbiAgICAgIH1cbiAgICAgIGlmIChuIDwgMTAgKiAxMDAwKSB7XG4gICAgICAgIHJldHVybiBkM0Zvcm1hdCgnLCcpKE1hdGgucm91bmQobikpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZvcm1hdExhcmdlTnVtYmVyKG4pO1xuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLnJlYWw6XG4gICAgICBpZiAobiA8IDApIHtcbiAgICAgICAgcmV0dXJuIGAtJHtmb3JtYXROdW1iZXIoLW4sICdudW1iZXInKX1gO1xuICAgICAgfVxuICAgICAgaWYgKG4gPCAxMDAwKSB7XG4gICAgICAgIHJldHVybiBkM0Zvcm1hdCgnLjR+cicpKG4pO1xuICAgICAgfVxuICAgICAgaWYgKG4gPCAxMCAqIDEwMDApIHtcbiAgICAgICAgcmV0dXJuIGQzRm9ybWF0KCcsLjJ+ZicpKG4pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZvcm1hdExhcmdlTnVtYmVyKG4pO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmb3JtYXROdW1iZXIobiwgJ3JlYWwnKTtcbiAgfVxufVxuXG5jb25zdCB0cmFuc2Zvcm1hdGlvbiA9IHtcbiAgWTogTWF0aC5wb3coMTAsIDI0KSxcbiAgWjogTWF0aC5wb3coMTAsIDIxKSxcbiAgRTogTWF0aC5wb3coMTAsIDE4KSxcbiAgUDogTWF0aC5wb3coMTAsIDE1KSxcbiAgVDogTWF0aC5wb3coMTAsIDEyKSxcbiAgRzogTWF0aC5wb3coMTAsIDkpLFxuICBNOiBNYXRoLnBvdygxMCwgNiksXG4gIGs6IE1hdGgucG93KDEwLCAzKSxcbiAgaDogTWF0aC5wb3coMTAsIDIpLFxuICBkYTogTWF0aC5wb3coMTAsIDEpLFxuICBkOiBNYXRoLnBvdygxMCwgLTEpLFxuICBjOiBNYXRoLnBvdygxMCwgLTIpLFxuICBtOiBNYXRoLnBvdygxMCwgLTMpLFxuICDOvDogTWF0aC5wb3coMTAsIC02KSxcbiAgbjogTWF0aC5wb3coMTAsIC05KSxcbiAgcDogTWF0aC5wb3coMTAsIC0xMiksXG4gIGY6IE1hdGgucG93KDEwLCAtMTUpLFxuICBhOiBNYXRoLnBvdygxMCwgLTE4KSxcbiAgejogTWF0aC5wb3coMTAsIC0yMSksXG4gIHk6IE1hdGgucG93KDEwLCAtMjQpXG59O1xuXG4vKipcbiAqIENvbnZlcnQgYSBmb3JtYXR0ZWQgbnVtYmVyIGZyb20gc3RyaW5nIGJhY2sgdG8gbnVtYmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXZlcnNlRm9ybWF0TnVtYmVyKHN0cjogc3RyaW5nKTogbnVtYmVyIHtcbiAgbGV0IHJldHVyblZhbHVlOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgY29uc3Qgc3RyTnVtID0gc3RyLnRyaW0oKS5yZXBsYWNlKC8sL2csICcnKTtcbiAgT2JqZWN0LmVudHJpZXModHJhbnNmb3JtYXRpb24pLmZvckVhY2goZCA9PiB7XG4gICAgaWYgKHN0ck51bS5pbmNsdWRlcyhkWzBdKSkge1xuICAgICAgcmV0dXJuVmFsdWUgPSBwYXJzZUZsb2F0KHN0ck51bSkgKiBkWzFdO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfSk7XG5cbiAgLy8gaWYgbm8gdHJhbnNmb3JtZXIgZm91bmQsIGNvbnZlcnQgdG8gbnViZXIgcmVnYXJkbGVzc1xuICByZXR1cm4gcmV0dXJuVmFsdWUgPT09IG51bGwgPyBOdW1iZXIoc3RyTnVtKSA6IHJldHVyblZhbHVlO1xufVxuXG4vKipcbiAqIEZvcm1hdCBlcG9jaCBtaWxsaXNlY29uZHMgd2l0aCBhIGZvcm1hdCBzdHJpbmdcbiAqIEB0eXBlIHRpbWV6b25lXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkYXRldGltZUZvcm1hdHRlcihcbiAgdGltZXpvbmU/OiBzdHJpbmcgfCBudWxsXG4pOiAoZm9ybWF0Pzogc3RyaW5nKSA9PiAodHM6IG51bWJlcikgPT4gc3RyaW5nIHtcbiAgcmV0dXJuIHRpbWV6b25lXG4gICAgPyBmb3JtYXQgPT4gdHMgPT4gbW9tZW50LnV0Yyh0cykudHoodGltZXpvbmUpLmZvcm1hdChmb3JtYXQpXG4gICAgOiAvLyByZXR1cm4gZW1wdHkgc3RyaW5nIGluc3RlYWQgb2YgJ0ludmFsaWQgZGF0ZScgaWYgdHMgaXMgdW5kZWZpbmVkL251bGxcbiAgICAgIGZvcm1hdCA9PiB0cyA9PiB0cyA/IG1vbWVudC51dGModHMpLmZvcm1hdChmb3JtYXQpIDogJyc7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFHQSxJQUFBQSxLQUFBLEdBQUFDLHVCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFDLHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBRyxTQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxlQUFBLEdBQUFGLHNCQUFBLENBQUFGLE9BQUE7QUFFQSxJQUFBSyxNQUFBLEdBQUFMLE9BQUE7QUFFQSxJQUFBTSxVQUFBLEdBQUFOLE9BQUE7QUFPQSxJQUFBTyxZQUFBLEdBQUFQLE9BQUE7QUFHQSxJQUFBUSxLQUFBLEdBQUFSLE9BQUE7QUFDQSxJQUFBUyxNQUFBLEdBQUFULE9BQUE7QUFBc0MsSUFBQVUscUJBQUEsRUFyQnRDO0FBQ0E7QUFBQSxTQUFBQyx5QkFBQUMsQ0FBQSw2QkFBQUMsT0FBQSxtQkFBQUMsQ0FBQSxPQUFBRCxPQUFBLElBQUFFLENBQUEsT0FBQUYsT0FBQSxZQUFBRix3QkFBQSxZQUFBQSx5QkFBQUMsQ0FBQSxXQUFBQSxDQUFBLEdBQUFHLENBQUEsR0FBQUQsQ0FBQSxLQUFBRixDQUFBO0FBQUEsU0FBQWIsd0JBQUFhLENBQUEsRUFBQUUsQ0FBQSxTQUFBQSxDQUFBLElBQUFGLENBQUEsSUFBQUEsQ0FBQSxDQUFBSSxVQUFBLFNBQUFKLENBQUEsZUFBQUEsQ0FBQSxnQkFBQUssUUFBQSxDQUFBTCxDQUFBLDBCQUFBQSxDQUFBLHNCQUFBQSxDQUFBLFFBQUFHLENBQUEsR0FBQUosd0JBQUEsQ0FBQUcsQ0FBQSxPQUFBQyxDQUFBLElBQUFBLENBQUEsQ0FBQUcsR0FBQSxDQUFBTixDQUFBLFVBQUFHLENBQUEsQ0FBQUksR0FBQSxDQUFBUCxDQUFBLE9BQUFRLENBQUEsS0FBQUMsU0FBQSxVQUFBQyxDQUFBLEdBQUFDLE1BQUEsQ0FBQUMsY0FBQSxJQUFBRCxNQUFBLENBQUFFLHdCQUFBLFdBQUFDLENBQUEsSUFBQWQsQ0FBQSxvQkFBQWMsQ0FBQSxPQUFBQyxjQUFBLENBQUFDLElBQUEsQ0FBQWhCLENBQUEsRUFBQWMsQ0FBQSxTQUFBRyxDQUFBLEdBQUFQLENBQUEsR0FBQUMsTUFBQSxDQUFBRSx3QkFBQSxDQUFBYixDQUFBLEVBQUFjLENBQUEsVUFBQUcsQ0FBQSxLQUFBQSxDQUFBLENBQUFWLEdBQUEsSUFBQVUsQ0FBQSxDQUFBQyxHQUFBLElBQUFQLE1BQUEsQ0FBQUMsY0FBQSxDQUFBSixDQUFBLEVBQUFNLENBQUEsRUFBQUcsQ0FBQSxJQUFBVCxDQUFBLENBQUFNLENBQUEsSUFBQWQsQ0FBQSxDQUFBYyxDQUFBLFlBQUFOLENBQUEsY0FBQVIsQ0FBQSxFQUFBRyxDQUFBLElBQUFBLENBQUEsQ0FBQWUsR0FBQSxDQUFBbEIsQ0FBQSxFQUFBUSxDQUFBLEdBQUFBLENBQUE7QUF3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDTyxJQUFNVyxZQUFZLEdBQUFDLE9BQUEsQ0FBQUQsWUFBQSxHQUFHLElBQUk7QUFDekIsSUFBTUUsWUFBWSxHQUFBRCxPQUFBLENBQUFDLFlBQUEsR0FBRyxDQUFDLElBQUk7QUFDMUIsSUFBTUMsYUFBYSxHQUFBRixPQUFBLENBQUFFLGFBQUEsR0FBRyxHQUFHO0FBQ3pCLElBQU1DLGFBQWEsR0FBQUgsT0FBQSxDQUFBRyxhQUFBLEdBQUcsQ0FBQyxHQUFHOztBQUVqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNPLFNBQVNDLGdCQUFnQkEsQ0FBQ0MsUUFBNEIsRUFBVTtFQUNyRSxPQUFPQyxrQkFBa0IsQ0FBQ0QsUUFBUSxhQUFSQSxRQUFRLGNBQVJBLFFBQVEsR0FBSSxDQUFDLEVBQUVKLFlBQVksRUFBRUYsWUFBWSxDQUFDO0FBQ3RFOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBU1EsaUJBQWlCQSxDQUFDQyxTQUE2QixFQUFVO0VBQ3ZFLE9BQU9GLGtCQUFrQixDQUFDRSxTQUFTLGFBQVRBLFNBQVMsY0FBVEEsU0FBUyxHQUFJLENBQUMsRUFBRUwsYUFBYSxFQUFFRCxhQUFhLENBQUM7QUFDekU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBU0ksa0JBQWtCQSxDQUFDRyxLQUFhLEVBQUVDLFFBQWdCLEVBQUVDLFFBQWdCLEVBQVU7RUFDNUYsSUFBSUYsS0FBSyxJQUFJQyxRQUFRLEVBQUU7SUFDckIsT0FBT0EsUUFBUTtFQUNqQjtFQUNBLElBQUlELEtBQUssSUFBSUUsUUFBUSxFQUFFO0lBQ3JCLE9BQU9BLFFBQVE7RUFDakI7RUFFQSxPQUFPRixLQUFLO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBU0csTUFBTUEsQ0FBSUMsTUFBVyxFQUFFO0VBQ3JDLElBQU1DLE9BQVksR0FBRyxFQUFFO0VBQ3ZCLElBQU1DLFNBQVMsR0FBRyxJQUFJQyxHQUFHLENBQUNILE1BQU0sQ0FBQztFQUNqQ0UsU0FBUyxDQUFDRSxPQUFPLENBQUMsVUFBQUMsQ0FBQyxFQUFJO0lBQ3JCLElBQUksSUFBQUMsK0JBQWtCLEVBQUNELENBQUMsQ0FBQyxFQUFFO01BQ3pCSixPQUFPLENBQUNNLElBQUksQ0FBQ0YsQ0FBQyxDQUFDO0lBQ2pCO0VBQ0YsQ0FBQyxDQUFDO0VBQ0YsT0FBT0osT0FBTztBQUNoQjtBQUVPLFNBQVNPLGVBQWVBLENBQzdCQyxNQUFrQixFQUNsQkMsR0FBVyxFQUNYQyxLQUF1QixFQUNFO0VBQ3pCLElBQU1DLElBQUksR0FBR0gsTUFBTSxDQUNoQkksR0FBRyxDQUFDLFVBQUFDLENBQUM7SUFBQSxPQUFJQyxNQUFNLENBQUNDLEtBQUssQ0FBQ0MsT0FBTyxDQUFDSCxDQUFDLENBQUMsQ0FBQyxJQUFJQSxDQUFDLENBQUNKLEdBQUcsQ0FBQztFQUFBLEVBQUMsQ0FDNUNRLE1BQU0sQ0FBQ0gsTUFBTSxDQUFDSSxRQUFRLENBQUMsQ0FDdkJDLElBQUksQ0FBQ0MsVUFBVSxDQUFDO0VBRW5CLElBQUksQ0FBQ1QsSUFBSSxDQUFDVSxNQUFNLEVBQUU7SUFDaEIsT0FBTyxJQUFJO0VBQ2I7O0VBRUE7RUFDQSxPQUFPLENBQUNDLElBQUksQ0FBQ0MsR0FBRyxDQUFDWixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUVELEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFWSxJQUFJLENBQUNFLEdBQUcsQ0FBQ2IsSUFBSSxDQUFDQSxJQUFJLENBQUNVLE1BQU0sR0FBRyxDQUFDLENBQUMsRUFBRVgsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDakY7QUFFTyxTQUFTZSxLQUFLQSxDQUFBQyxJQUFBLEVBQWdEO0VBQUEsSUFBQUMsS0FBQSxPQUFBQyxlQUFBLGFBQUFGLElBQUE7SUFBOUNGLEdBQUcsR0FBQUcsS0FBQTtJQUFFSixHQUFHLEdBQUFJLEtBQUE7RUFBQSxJQUFxQkUsR0FBRyxHQUFBQyxTQUFBLENBQUFULE1BQUEsUUFBQVMsU0FBQSxRQUFBQyxTQUFBLEdBQUFELFNBQUEsTUFBRyxDQUFDO0VBQ3pELE9BQU9ELEdBQUcsSUFBSUwsR0FBRyxHQUFHQSxHQUFHLEdBQUdLLEdBQUcsSUFBSU4sR0FBRyxHQUFHQSxHQUFHLEdBQUdNLEdBQUc7QUFDbEQ7QUFFTyxTQUFTRyxhQUFhQSxDQUFDQyxJQUFJLEVBQXVDO0VBQUEsSUFBckNDLFVBQVUsR0FBQUosU0FBQSxDQUFBVCxNQUFBLFFBQUFTLFNBQUEsUUFBQUMsU0FBQSxHQUFBRCxTQUFBLE1BQUcsR0FBRztFQUFBLElBQUVLLFFBQVEsR0FBQUwsU0FBQSxDQUFBVCxNQUFBLFFBQUFTLFNBQUEsUUFBQUMsU0FBQSxHQUFBRCxTQUFBLE1BQUcsVUFBQWpCLENBQUM7SUFBQSxPQUFJQSxDQUFDO0VBQUE7RUFDckUsSUFBTXVCLFVBQVUsR0FBR2QsSUFBSSxDQUFDQyxHQUFHLENBQUNELElBQUksQ0FBQ2UsS0FBSyxDQUFDSixJQUFJLENBQUNaLE1BQU0sR0FBR2EsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0VBQ3BFLElBQU1JLE1BQWEsR0FBRyxFQUFFO0VBQ3hCLEtBQUssSUFBSXZELENBQUMsR0FBRyxDQUFDLEVBQUVBLENBQUMsR0FBR2tELElBQUksQ0FBQ1osTUFBTSxFQUFFdEMsQ0FBQyxJQUFJcUQsVUFBVSxFQUFFO0lBQ2hERSxNQUFNLENBQUNoQyxJQUFJLENBQUM2QixRQUFRLENBQUNGLElBQUksQ0FBQ2xELENBQUMsQ0FBQyxDQUFDLENBQUM7RUFDaEM7RUFFQSxPQUFPdUQsTUFBTTtBQUNmOztBQUVBO0FBQ0E7QUFDQTtBQUNPLFNBQVNDLGVBQWVBLENBQUM1QyxLQUE2QixFQUFFNkMsTUFBYyxFQUFzQjtFQUNqRyxJQUFJLElBQUFuQywrQkFBa0IsRUFBQ1YsS0FBSyxDQUFDLEVBQUU7SUFDN0IsSUFBSSxPQUFPQSxLQUFLLEtBQUssUUFBUSxFQUFFO01BQzdCLE9BQU84QywwQkFBTSxDQUFDQyxHQUFHLENBQUMvQyxLQUFLLEVBQUU2QyxNQUFNLENBQUMsQ0FBQ0csT0FBTyxDQUFDLENBQUM7SUFDNUM7SUFDQSxJQUFJLE9BQU9oRCxLQUFLLEtBQUssUUFBUSxFQUFFO01BQzdCLE9BQU82QyxNQUFNLEtBQUssR0FBRyxHQUFHN0MsS0FBSyxHQUFHLElBQUksR0FBR0EsS0FBSztJQUM5QztJQUNBLElBQUlBLEtBQUssWUFBWWlELElBQUksRUFBRTtNQUN6QixPQUFPakQsS0FBSyxDQUFDZ0QsT0FBTyxDQUFDLENBQUM7SUFDeEI7RUFDRjtFQUNBLE9BQU8sSUFBSTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNPLFNBQVNFLFFBQVFBLENBQUNoQyxDQUFVLEVBQWU7RUFDaEQsT0FBT0MsTUFBTSxDQUFDSSxRQUFRLENBQUNMLENBQUMsQ0FBQztBQUMzQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBU2hDLGNBQWNBLENBQzVCaUUsR0FBTSxFQUNOQyxJQUFPLEVBQ3dCO0VBQy9CLE9BQU90RSxNQUFNLENBQUN1RSxTQUFTLENBQUNuRSxjQUFjLENBQUNDLElBQUksQ0FBQ2dFLEdBQUcsRUFBRUMsSUFBSSxDQUFDO0FBQ3hEO0FBRU8sU0FBUzNCLFVBQVVBLENBQUM1QyxDQUFTLEVBQUV5RSxDQUFTLEVBQVU7RUFDdkQsT0FBT3pFLENBQUMsR0FBR3lFLENBQUM7QUFDZDtBQUVPLFNBQVNDLGtCQUFrQkEsQ0FBQ0MsU0FBaUIsRUFBaUM7RUFDbkYsUUFBUUEsU0FBUztJQUNmLEtBQUtDLDBCQUFlLENBQUNDLElBQUk7SUFDekIsS0FBS0QsMEJBQWUsQ0FBQ0UsT0FBTztJQUM1QixLQUFLRiwwQkFBZSxDQUFDRyxTQUFTO01BQzVCLE9BQU9uQyxVQUFVO0lBQ25CO01BQ0UsT0FBT1csU0FBUztFQUNwQjtBQUNGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBU3lCLFlBQVlBLENBQUNDLEdBQVcsRUFBRUMsUUFBZ0IsRUFBVTtFQUNsRSxJQUFNekYsQ0FBQyxHQUFHcUQsSUFBSSxDQUFDcUMsR0FBRyxDQUFDLEVBQUUsRUFBRUQsUUFBUSxDQUFDO0VBQ2hDLE9BQU8sQ0FDTHBDLElBQUksQ0FBQ3NDLEtBQUssQ0FDUkgsR0FBRyxHQUFHeEYsQ0FBQyxHQUFHLENBQUN5RixRQUFRLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUtwQyxJQUFJLENBQUN1QyxJQUFJLENBQUNKLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBR25DLElBQUksQ0FBQ3FDLEdBQUcsQ0FBQyxHQUFHLEVBQUVELFFBQVEsQ0FBQyxDQUFDLENBQ3JGLENBQUMsR0FBR3pGLENBQUMsRUFDTDZGLE9BQU8sQ0FBQ0osUUFBUSxDQUFDO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBU0ssV0FBV0EsQ0FBQ04sR0FBVyxFQUFVO0VBQy9DO0VBQ0EsT0FBTzNDLE1BQU0sSUFBQWtELE1BQUEsQ0FBSTFDLElBQUksQ0FBQ3NDLEtBQUssSUFBQUksTUFBQSxDQUFJUCxHQUFHLFFBQUssQ0FBQyxRQUFLLENBQUM7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQ