kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
279 lines (221 loc) • 28.7 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.arrayMove = exports.FIELD_DISPLAY_FORMAT = void 0;
exports.clamp = clamp;
exports.findMapBounds = findMapBounds;
exports.getLatLngBounds = getLatLngBounds;
exports.getRoundingDecimalFromStep = getRoundingDecimalFromStep;
exports.getSampleData = getSampleData;
exports.getSortingFunction = getSortingFunction;
exports.isPlainObject = isPlainObject;
exports.maybeToDate = maybeToDate;
exports.notNullorUndefined = notNullorUndefined;
exports.numberSort = numberSort;
exports.parseFieldValue = void 0;
exports.preciseRound = preciseRound;
exports.roundValToStep = roundValToStep;
exports.timeToUnixMilli = timeToUnixMilli;
exports.unique = unique;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _moment = _interopRequireDefault(require("moment"));
var _assert = _interopRequireDefault(require("assert"));
var _defaultSettings = require("../constants/default-settings");
var _FIELD_DISPLAY_FORMAT;
var MAX_LATITUDE = 90;
var MIN_LATITUDE = -90;
var MAX_LONGITUDE = 180;
var MIN_LONGITUDE = -180;
/**
* simple getting unique values of an array
*
* @param {array} values
* @returns {array} unique values
*/
function unique(values) {
var results = [];
values.forEach(function (v) {
if (!results.includes(v) && notNullorUndefined(v)) {
results.push(v);
}
});
return results;
}
/* eslint-disable max-statements */
/**
* return center of map from given points
* @param {array} layers
* @param {string} dataId
* @returns {object} coordinates of map center, empty if not found
*/
function findMapBounds(layers) {
// find bounds in formatted layerData
// take ALL layers into account when finding map bounds
var availableLayerBounds = layers.reduce(function (res, l) {
if (l.meta && l.meta.bounds) {
res.push(l.meta.bounds);
}
return res;
}, []); // return null if no layer is available
if (availableLayerBounds.length === 0) {
return null;
} // merge bounds in each layer
var newBounds = availableLayerBounds.reduce(function (res, b) {
return [Math.min(res[0], b[0]), Math.min(res[1], b[1]), Math.max(res[2], b[2]), Math.max(res[3], b[3])];
}, [MAX_LONGITUDE, MAX_LATITUDE, MIN_LONGITUDE, MIN_LATITUDE]);
return newBounds;
}
/* eslint-enable max-statements */
function getLatLngBounds(points, idx, limit) {
var lats = points.map(function (d) {
return Array.isArray(d) && d[idx];
}).filter(Number.isFinite).sort(numberSort);
if (!lats.length) {
return null;
} // use 99 percentile to filter out outliers
// clamp to limit
return [Math.max(lats[Math.floor(0.01 * (lats.length - 1))], limit[0]), Math.min(lats[Math.ceil(0.99 * (lats.length - 1))], limit[1])];
}
function clamp(_ref, val) {
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
min = _ref2[0],
max = _ref2[1];
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
* @param {*} value
* @param {*} format
*/
function timeToUnixMilli(value, format) {
if (notNullorUndefined(value)) {
return typeof value === 'string' ? _moment["default"].utc(value, format).valueOf() : format === 'x' ? value * 1000 : value;
}
return null;
}
function maybeToDate(isTime, fieldIdx, format, d) {
if (isTime) {
return timeToUnixMilli(d[fieldIdx], format);
}
return d[fieldIdx];
}
/**
* whether null or undefined
* @returns {boolean} - yes or no
*/
function notNullorUndefined(d) {
return d !== undefined && d !== null;
}
function isPlainObject(obj) {
return obj === Object(obj) && typeof obj !== 'function' && !Array.isArray(obj);
}
function numberSort(a, b) {
return a - b;
}
function getSortingFunction(fieldType) {
switch (fieldType) {
case _defaultSettings.ALL_FIELD_TYPES.real:
case _defaultSettings.ALL_FIELD_TYPES.integer:
case _defaultSettings.ALL_FIELD_TYPES.timestamp:
return numberSort;
default:
return undefined;
}
}
/**
* round number with exact number of decimals
* return as a string
* @param {number} num
* @param {number} decimals
* @returns {string} - a rounded number in string format
*/
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);
}
/**
* get number of decimals to round to for slider from step
* @param {number} step
* @returns {number} - number of decimal
*/
function getRoundingDecimalFromStep(step) {
if (isNaN(step)) {
(0, _assert["default"])('step is not a number');
(0, _assert["default"])(step);
}
var splitZero = step.toString().split('.');
if (splitZero.length === 1) {
return 0;
}
return splitZero[1].length;
}
/**
* round the value to step for the slider
* @param {number} minValue
* @param {number} step
* @param {number} val
* @returns {number} - rounded number
*/
function roundValToStep(minValue, step, val) {
if (isNaN(step)) {
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);
}
var identity = function identity(d) {
return d;
};
var FIELD_DISPLAY_FORMAT = exports.FIELD_DISPLAY_FORMAT = (_FIELD_DISPLAY_FORMAT = {}, (0, _defineProperty2["default"])(_FIELD_DISPLAY_FORMAT, _defaultSettings.ALL_FIELD_TYPES.string, identity), (0, _defineProperty2["default"])(_FIELD_DISPLAY_FORMAT, _defaultSettings.ALL_FIELD_TYPES.timestamp, identity), (0, _defineProperty2["default"])(_FIELD_DISPLAY_FORMAT, _defaultSettings.ALL_FIELD_TYPES.integer, identity), (0, _defineProperty2["default"])(_FIELD_DISPLAY_FORMAT, _defaultSettings.ALL_FIELD_TYPES.real, identity), (0, _defineProperty2["default"])(_FIELD_DISPLAY_FORMAT, _defaultSettings.ALL_FIELD_TYPES["boolean"], function (d) {
return String(d);
}), (0, _defineProperty2["default"])(_FIELD_DISPLAY_FORMAT, _defaultSettings.ALL_FIELD_TYPES.date, identity), (0, _defineProperty2["default"])(_FIELD_DISPLAY_FORMAT, _defaultSettings.ALL_FIELD_TYPES.geojson, function (d) {
return typeof d === 'string' ? d : isPlainObject(d) ? JSON.stringify(d) : Array.isArray(d) ? "[".concat(String(d), "]") : '';
}), _FIELD_DISPLAY_FORMAT);
/**
* Parse field value and type and return a string representation
* @param {string} value the field value
* @param {string} type the field type
* @return {*}
*/
var parseFieldValue = exports.parseFieldValue = function parseFieldValue(value, type) {
if (!notNullorUndefined(value)) {
return '';
}
return FIELD_DISPLAY_FORMAT[type] ? FIELD_DISPLAY_FORMAT[type](value) : String(value);
};
var arrayMoveMutate = function arrayMoveMutate(array, from, to) {
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
};
var arrayMove = exports.arrayMove = function arrayMove(array, from, to) {
array = array.slice();
arrayMoveMutate(array, from, to);
return array;
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9kYXRhLXV0aWxzLmpzIl0sIm5hbWVzIjpbIk1BWF9MQVRJVFVERSIsIk1JTl9MQVRJVFVERSIsIk1BWF9MT05HSVRVREUiLCJNSU5fTE9OR0lUVURFIiwidW5pcXVlIiwidmFsdWVzIiwicmVzdWx0cyIsImZvckVhY2giLCJ2IiwiaW5jbHVkZXMiLCJub3ROdWxsb3JVbmRlZmluZWQiLCJwdXNoIiwiZmluZE1hcEJvdW5kcyIsImxheWVycyIsImF2YWlsYWJsZUxheWVyQm91bmRzIiwicmVkdWNlIiwicmVzIiwibCIsIm1ldGEiLCJib3VuZHMiLCJsZW5ndGgiLCJuZXdCb3VuZHMiLCJiIiwiTWF0aCIsIm1pbiIsIm1heCIsImdldExhdExuZ0JvdW5kcyIsInBvaW50cyIsImlkeCIsImxpbWl0IiwibGF0cyIsIm1hcCIsImQiLCJBcnJheSIsImlzQXJyYXkiLCJmaWx0ZXIiLCJOdW1iZXIiLCJpc0Zpbml0ZSIsInNvcnQiLCJudW1iZXJTb3J0IiwiZmxvb3IiLCJjZWlsIiwiY2xhbXAiLCJ2YWwiLCJnZXRTYW1wbGVEYXRhIiwiZGF0YSIsInNhbXBsZVNpemUiLCJnZXRWYWx1ZSIsInNhbXBsZVN0ZXAiLCJvdXRwdXQiLCJpIiwidGltZVRvVW5peE1pbGxpIiwidmFsdWUiLCJmb3JtYXQiLCJtb21lbnQiLCJ1dGMiLCJ2YWx1ZU9mIiwibWF5YmVUb0RhdGUiLCJpc1RpbWUiLCJmaWVsZElkeCIsInVuZGVmaW5lZCIsImlzUGxhaW5PYmplY3QiLCJvYmoiLCJPYmplY3QiLCJhIiwiZ2V0U29ydGluZ0Z1bmN0aW9uIiwiZmllbGRUeXBlIiwiQUxMX0ZJRUxEX1RZUEVTIiwicmVhbCIsImludGVnZXIiLCJ0aW1lc3RhbXAiLCJwcmVjaXNlUm91bmQiLCJudW0iLCJkZWNpbWFscyIsInQiLCJwb3ciLCJyb3VuZCIsInNpZ24iLCJ0b0ZpeGVkIiwiZ2V0Um91bmRpbmdEZWNpbWFsRnJvbVN0ZXAiLCJzdGVwIiwiaXNOYU4iLCJzcGxpdFplcm8iLCJ0b1N0cmluZyIsInNwbGl0Iiwicm91bmRWYWxUb1N0ZXAiLCJtaW5WYWx1ZSIsImRlY2ltYWwiLCJzdGVwcyIsInJlbWFpbiIsImNsb3Nlc3QiLCJyb3VuZGVkIiwiaWRlbnRpdHkiLCJGSUVMRF9ESVNQTEFZX0ZPUk1BVCIsInN0cmluZyIsIlN0cmluZyIsImRhdGUiLCJnZW9qc29uIiwiSlNPTiIsInN0cmluZ2lmeSIsInBhcnNlRmllbGRWYWx1ZSIsInR5cGUiLCJhcnJheU1vdmVNdXRhdGUiLCJhcnJheSIsImZyb20iLCJ0byIsInNwbGljZSIsImFycmF5TW92ZSIsInNsaWNlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOztBQUNBOztBQUNBOzs7O0FBRUEsSUFBTUEsWUFBWSxHQUFHLEVBQXJCO0FBQ0EsSUFBTUMsWUFBWSxHQUFHLENBQUMsRUFBdEI7QUFDQSxJQUFNQyxhQUFhLEdBQUcsR0FBdEI7QUFDQSxJQUFNQyxhQUFhLEdBQUcsQ0FBQyxHQUF2QjtBQUVBOzs7Ozs7O0FBTU8sU0FBU0MsTUFBVCxDQUFnQkMsTUFBaEIsRUFBd0I7QUFDN0IsTUFBTUMsT0FBTyxHQUFHLEVBQWhCO0FBQ0FELEVBQUFBLE1BQU0sQ0FBQ0UsT0FBUCxDQUFlLFVBQUFDLENBQUMsRUFBSTtBQUNsQixRQUFJLENBQUNGLE9BQU8sQ0FBQ0csUUFBUixDQUFpQkQsQ0FBakIsQ0FBRCxJQUF3QkUsa0JBQWtCLENBQUNGLENBQUQsQ0FBOUMsRUFBbUQ7QUFDakRGLE1BQUFBLE9BQU8sQ0FBQ0ssSUFBUixDQUFhSCxDQUFiO0FBQ0Q7QUFDRixHQUpEO0FBTUEsU0FBT0YsT0FBUDtBQUNEO0FBRUQ7O0FBQ0E7Ozs7Ozs7O0FBTU8sU0FBU00sYUFBVCxDQUF1QkMsTUFBdkIsRUFBK0I7QUFDcEM7QUFDQTtBQUNBLE1BQU1DLG9CQUFvQixHQUFHRCxNQUFNLENBQUNFLE1BQVAsQ0FBYyxVQUFDQyxHQUFELEVBQU1DLENBQU4sRUFBWTtBQUNyRCxRQUFJQSxDQUFD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Q0FERyxHQUVIMkMsTUFBTSxDQUFDM0MsS0FBRCxDQUZWO0FBR0QsQ0FSTTs7QUFVUCxJQUFNa0QsZUFBZSxHQUFHLFNBQWxCQSxlQUFrQixDQUFDQyxLQUFELEVBQVFDLElBQVIsRUFBY0MsRUFBZCxFQUFxQjtBQUMzQ0YsRUFBQUEsS0FBSyxDQUFDRyxNQUFOLENBQWFELEVBQUUsR0FBRyxDQUFMLEdBQVNGLEtBQUssQ0FBQ25GLE1BQU4sR0FBZXFGLEVBQXhCLEdBQTZCQSxFQUExQyxFQUE4QyxDQUE5QyxFQUFpREYsS0FBSyxDQUFDRyxNQUFOLENBQWFGLElBQWIsRUFBbUIsQ0FBbkIsRUFBc0IsQ0FBdEIsQ0FBakQ7QUFDRCxDQUZEOztBQUlPLElBQU1HLFNBQVMsdUJBQUcsU0FBWkEsU0FBWSxDQUFDSixLQUFELEVBQVFDLElBQVIsRUFBY0MsRUFBZCxFQUFxQjtBQUM1Q0YsRUFBQUEsS0FBSyxHQUFHQSxLQUFLLENBQUNLLEtBQU4sRUFBUjtBQUNBTixFQUFBQSxlQUFlLENBQUNDLEtBQUQsRUFBUUMsSUFBUixFQUFjQyxFQUFkLENBQWY7QUFDQSxTQUFPRixLQUFQO0FBQ0QsQ0FKTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAyMyBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7QUxMX0ZJRUxEX1RZUEVTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5cbmNvbnN0IE1BWF9MQVRJVFVERSA9IDkwO1xuY29uc3QgTUlOX0xBVElUVURFID0gLTkwO1xuY29uc3QgTUFYX0xPTkdJVFVERSA9IDE4MDtcbmNvbnN0IE1JTl9MT05HSVRVREUgPSAtMTgwO1xuXG4vKipcbiAqIHNpbXBsZSBnZXR0aW5nIHVuaXF1ZSB2YWx1ZXMgb2YgYW4gYXJyYXlcbiAqXG4gKiBAcGFyYW0ge2FycmF5fSB2YWx1ZXNcbiAqIEByZXR1cm5zIHthcnJheX0gdW5pcXVlIHZhbHVlc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pcXVlKHZhbHVlcykge1xuICBjb25zdCByZXN1bHRzID0gW107XG4gIHZhbHVlcy5mb3JFYWNoKHYgPT4ge1xuICAgIGlmICghcmVzdWx0cy5pbmNsdWRlcyh2KSAmJiBub3ROdWxsb3JVbmRlZmluZWQodikpIHtcbiAgICAgIHJlc3VsdHMucHVzaCh2KTtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiByZXN1bHRzO1xufVxuXG4vKiBlc2xpbnQtZGlzYWJsZSBtYXgtc3RhdGVtZW50cyAqL1xuLyoqXG4gKiByZXR1cm4gY2VudGVyIG9mIG1hcCBmcm9tIGdpdmVuIHBvaW50c1xuICogQHBhcmFtIHthcnJheX0gbGF5ZXJzXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YUlkXG4gKiBAcmV0dXJucyB7b2JqZWN0fSBjb29yZGluYXRlcyBvZiBtYXAgY2VudGVyLCBlbXB0eSBpZiBub3QgZm91bmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmRNYXBCb3VuZHMobGF5ZXJzKSB7XG4gIC8vIGZpbmQgYm91bmRzIGluIGZvcm1hdHRlZCBsYXllckRhdGFcbiAgLy8gdGFrZSBBTEwgbGF5ZXJzIGludG8gYWNjb3VudCB3aGVuIGZpbmRpbmcgbWFwIGJvdW5kc1xuICBjb25zdCBhdmFpbGFibGVMYXllckJvdW5kcyA9IGxheWVycy5yZWR1Y2UoKHJlcywgbCkgPT4ge1xuICAgIGlmIChsLm1ldGEgJiYgbC5tZXRhLmJvdW5kcykge1xuICAgICAgcmVzLnB1c2gobC5tZXRhLmJvdW5kcyk7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG4gIH0sIFtdKTtcbiAgLy8gcmV0dXJuIG51bGwgaWYgbm8gbGF5ZXIgaXMgYXZhaWxhYmxlXG4gIGlmIChhdmFpbGFibGVMYXllckJvdW5kcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICAvLyBtZXJnZSBib3VuZHMgaW4gZWFjaCBsYXllclxuICBjb25zdCBuZXdCb3VuZHMgPSBhdmFpbGFibGVMYXllckJvdW5kcy5yZWR1Y2UoXG4gICAgKHJlcywgYikgPT4ge1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAgTWF0aC5taW4ocmVzWzBdLCBiWzBdKSxcbiAgICAgICAgTWF0aC5taW4ocmVzWzFdLCBiWzFdKSxcbiAgICAgICAgTWF0aC5tYXgocmVzWzJdLCBiWzJdKSxcbiAgICAgICAgTWF0aC5tYXgocmVzWzNdLCBiWzNdKVxuICAgICAgXTtcbiAgICB9LFxuICAgIFtNQVhfTE9OR0lUVURFLCBNQVhfTEFUSVRVREUsIE1JTl9MT05HSVRVREUsIE1JTl9MQVRJVFVERV1cbiAgKTtcbiAgcmV0dXJuIG5ld0JvdW5kcztcbn1cbi8qIGVzbGludC1lbmFibGUgbWF4LXN0YXRlbWVudHMgKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExhdExuZ0JvdW5kcyhwb2ludHMsIGlkeCwgbGltaXQpIHtcbiAgY29uc3QgbGF0cyA9IHBvaW50c1xuICAgIC5tYXAoZCA9PiBBcnJheS5pc0FycmF5KGQpICYmIGRbaWR4XSlcbiAgICAuZmlsdGVyKE51bWJlci5pc0Zpbml0ZSlcbiAgICAuc29ydChudW1iZXJTb3J0KTtcblxuICBpZiAoIWxhdHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgLy8gdXNlIDk5IHBlcmNlbnRpbGUgdG8gZmlsdGVyIG91dCBvdXRsaWVyc1xuICAvLyBjbGFtcCB0byBsaW1pdFxuICByZXR1cm4gW1xuICAgIE1hdGgubWF4KGxhdHNbTWF0aC5mbG9vcigwLjAxICogKGxhdHMubGVuZ3RoIC0gMSkpXSwgbGltaXRbMF0pLFxuICAgIE1hdGgubWluKGxhdHNbTWF0aC5jZWlsKDAuOTkgKiAobGF0cy5sZW5ndGggLSAxKSldLCBsaW1pdFsxXSlcbiAgXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNsYW1wKFttaW4sIG1heF0sIHZhbCkge1xuICByZXR1cm4gdmFsIDw9IG1pbiA/IG1pbiA6IHZhbCA+PSBtYXggPyBtYXggOiB2YWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTYW1wbGVEYXRhKGRhdGEsIHNhbXBsZVNpemUgPSA1MDAsIGdldFZhbHVlID0gZCA9PiBkKSB7XG4gIGNvbnN0IHNhbXBsZVN0ZXAgPSBNYXRoLm1heChNYXRoLmZsb29yKGRhdGEubGVuZ3RoIC8gc2FtcGxlU2l6ZSksIDEpO1xuICBjb25zdCBvdXRwdXQgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSArPSBzYW1wbGVTdGVwKSB7XG4gICAgb3V0cHV0LnB1c2goZ2V0VmFsdWUoZGF0YVtpXSkpO1xuICB9XG5cbiAgcmV0dXJuIG91dHB1dDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGRpZmZlcmVudCB0aW1lIGZvcm1hdCB0byB1bml4IG1pbGxpc2Vjb25kc1xuICogQHBhcmFtIHsqfSB2YWx1ZVxuICogQHBhcmFtIHsqfSBmb3JtYXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbWVUb1VuaXhNaWxsaSh2YWx1ZSwgZm9ybWF0KSB7XG4gIGlmIChub3ROdWxsb3JVbmRlZmluZWQodmFsdWUpKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZydcbiAgICAgID8gbW9tZW50LnV0Yyh2YWx1ZSwgZm9ybWF0KS52YWx1ZU9mKClcbiAgICAgIDogZm9ybWF0ID09PSAneCdcbiAgICAgID8gdmFsdWUgKiAxMDAwXG4gICAgICA6IHZhbHVlO1xuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF5YmVUb0RhdGUoaXNUaW1lLCBmaWVsZElkeCwgZm9ybWF0LCBkKSB7XG4gIGlmIChpc1RpbWUpIHtcbiAgICByZXR1cm4gdGltZVRvVW5peE1pbGxpKGRbZmllbGRJZHhdLCBmb3JtYXQpO1xuICB9XG5cbiAgcmV0dXJuIGRbZmllbGRJZHhdO1xufVxuXG4vKipcbiAqIHdoZXRoZXIgbnVsbCBvciB1bmRlZmluZWRcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIHllcyBvciBub1xuICovXG5leHBvcnQgZnVuY3Rpb24gbm90TnVsbG9yVW5kZWZpbmVkKGQpIHtcbiAgcmV0dXJuIGQgIT09IHVuZGVmaW5lZCAmJiBkICE9PSBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNQbGFpbk9iamVjdChvYmopIHtcbiAgcmV0dXJuIChcbiAgICBvYmogPT09IE9iamVjdChvYmopICYmIHR5cGVvZiBvYmogIT09ICdmdW5jdGlvbicgJiYgIUFycmF5LmlzQXJyYXkob2JqKVxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbnVtYmVyU29ydChhLCBiKSB7XG4gIHJldHVybiBhIC0gYjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNvcnRpbmdGdW5jdGlvbihmaWVsZFR5cGUpIHtcbiAgc3dpdGNoIChmaWVsZFR5cGUpIHtcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5yZWFsOlxuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmludGVnZXI6XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMudGltZXN0YW1wOlxuICAgICAgcmV0dXJuIG51bWJlclNvcnQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiByb3VuZCBudW1iZXIgd2l0aCBleGFjdCBudW1iZXIgb2YgZGVjaW1hbHNcbiAqIHJldHVybiBhcyBhIHN0cmluZ1xuICogQHBhcmFtIHtudW1iZXJ9IG51bVxuICogQHBhcmFtIHtudW1iZXJ9IGRlY2ltYWxzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIGEgcm91bmRlZCBudW1iZXIgaW4gc3RyaW5nIGZvcm1hdFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlY2lzZVJvdW5kKG51bSwgZGVjaW1hbHMpIHtcbiAgY29uc3QgdCA9IE1hdGgucG93KDEwLCBkZWNpbWFscyk7XG4gIHJldHVybiAoXG4gICAgTWF0aC5yb3VuZChcbiAgICAgIG51bSAqIHQgK1xuICAgICAgICAoZGVjaW1hbHMgPiAwID8gMSA6IDApICpcbiAgICAgICAgICAoTWF0aC5zaWduKG51bSkgKiAoMTAgLyBNYXRoLnBvdygxMDAsIGRlY2ltYWxzKSkpXG4gICAgKSAvIHRcbiAgKS50b0ZpeGVkKGRlY2ltYWxzKTtcbn1cblxuLyoqXG4gKiBnZXQgbnVtYmVyIG9mIGRlY2ltYWxzIHRvIHJvdW5kIHRvIGZvciBzbGlkZXIgZnJvbSBzdGVwXG4gKiBAcGFyYW0ge251bWJlcn0gc3RlcFxuICogQHJldHVybnMge251bWJlcn0gLSBudW1iZXIgb2YgZGVjaW1hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Um91bmRpbmdEZWNpbWFsRnJvbVN0ZXAoc3RlcCkge1xuICBpZiAoaXNOYU4oc3RlcCkpIHtcbiAgICBhc3NlcnQoJ3N0ZXAgaXMgbm90IGEgbnVtYmVyJyk7XG4gICAgYXNzZXJ0KHN0ZXApO1xuICB9XG5cbiAgY29uc3Qgc3BsaXRaZXJvID0gc3RlcC50b1N0cmluZygpLnNwbGl0KCcuJyk7XG4gIGlmIChzcGxpdFplcm8ubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgcmV0dXJuIHNwbGl0WmVyb1sxXS5sZW5ndGg7XG59XG5cbi8qKlxuICogcm91bmQgdGhlIHZhbHVlIHRvIHN0ZXAgZm9yIHRoZSBzbGlkZXJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtaW5WYWx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IHN0ZXBcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWxcbiAqIEByZXR1cm5zIHtudW1iZXJ9IC0gcm91bmRlZCBudW1iZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdW5kVmFsVG9TdGVwKG1pblZhbHVlLCBzdGVwLCB2YWwpIHtcbiAgaWYgKGlzTmFOKHN0ZXApKSB7XG4gICAgcmV0dXJuIHZhbDtcbiAgfVxuXG4gIGNvbnN0IGRlY2ltYWwgPSBnZXRSb3VuZGluZ0RlY2ltYWxGcm9tU3RlcChzdGVwKTtcbiAgY29uc3Qgc3RlcHMgPSBNYXRoLmZsb29yKCh2YWwgLSBtaW5WYWx1ZSkgLyBzdGVwKTtcbiAgbGV0IHJlbWFpbiA9IHZhbCAtIChzdGVwcyAqIHN0ZXAgKyBtaW5WYWx1ZSk7XG5cbiAgLy8gaGFzIHRvIHJvdW5kIGJlY2F1c2UgamF2YXNjcmlwdCB0dXJucyAwLjEgaW50byAwLjk5OTk5OTk5OTk5OTk5ODdcbiAgcmVtYWluID0gTnVtYmVyKHByZWNpc2VSb3VuZChyZW1haW4sIDgpKTtcblxuICBsZXQgY2xvc2VzdDtcbiAgaWYgKHJlbWFpbiA9PT0gMCkge1xuICAgIGNsb3Nlc3QgPSB2YWw7XG4gIH0gZWxzZSBpZiAocmVtYWluIDwgc3RlcCAvIDIpIHtcbiAgICBjbG9zZXN0ID0gc3RlcHMgKiBzdGVwICsgbWluVmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgY2xvc2VzdCA9IChzdGVwcyArIDEpICogc3RlcCArIG1pblZhbHVlO1xuICB9XG5cbiAgLy8gcHJlY2lzZSByb3VuZCByZXR1cm4gYSBzdHJpbmcgcm91bmRlZCB0byB0aGUgZGVmaW5lZCBkZWNpbWFsXG4gIGNvbnN0IHJvdW5kZWQgPSBwcmVjaXNlUm91bmQoY2xvc2VzdCwgZGVjaW1hbCk7XG5cbiAgcmV0dXJuIE51bWJlcihyb3VuZGVkKTtcbn1cblxuY29uc3QgaWRlbnRpdHkgPSBkID0+IGQ7XG5cbmV4cG9ydCBjb25zdCBGSUVMRF9ESVNQTEFZX0ZPUk1BVCA9IHtcbiAgW0FMTF9GSUVMRF9UWVBFUy5zdHJpbmddOiBpZGVudGl0eSxcbiAgW0FMTF9GSUVMRF9UWVBFUy50aW1lc3RhbXBdOiBpZGVudGl0eSxcbiAgW0FMTF9GSUVMRF9UWVBFUy5pbnRlZ2VyXTogaWRlbnRpdHksXG4gIFtBTExfRklFTERfVFlQRVMucmVhbF06IGlkZW50aXR5LFxuICBbQUxMX0ZJRUxEX1RZUEVTLmJvb2xlYW5dOiBkID0+IFN0cmluZyhkKSxcbiAgW0FMTF9GSUVMRF9UWVBFUy5kYXRlXTogaWRlbnRpdHksXG4gIFtBTExfRklFTERfVFlQRVMuZ2VvanNvbl06IGQgPT5cbiAgICB0eXBlb2YgZCA9PT0gJ3N0cmluZydcbiAgICAgID8gZFxuICAgICAgOiBpc1BsYWluT2JqZWN0KGQpXG4gICAgICA/IEpTT04uc3RyaW5naWZ5KGQpXG4gICAgICA6IEFycmF5LmlzQXJyYXkoZClcbiAgICAgID8gYFske1N0cmluZyhkKX1dYFxuICAgICAgOiAnJ1xufTtcblxuLyoqXG4gKiBQYXJzZSBmaWVsZCB2YWx1ZSBhbmQgdHlwZSBhbmQgcmV0dXJuIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgdGhlIGZpZWxkIHZhbHVlXG4gKiBAcGFyYW0ge3N0cmluZ30gdHlwZSB0aGUgZmllbGQgdHlwZVxuICogQHJldHVybiB7Kn1cbiAqL1xuZXhwb3J0IGNvbnN0IHBhcnNlRmllbGRWYWx1ZSA9ICh2YWx1ZSwgdHlwZSkgPT4ge1xuICBpZiAoIW5vdE51bGxvclVuZGVmaW5lZCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICByZXR1cm4gRklFTERfRElTUExBWV9GT1JNQVRbdHlwZV1cbiAgICA/IEZJRUxEX0RJU1BMQVlfRk9STUFUW3R5cGVdKHZhbHVlKVxuICAgIDogU3RyaW5nKHZhbHVlKTtcbn07XG5cbmNvbnN0IGFycmF5TW92ZU11dGF0ZSA9IChhcnJheSwgZnJvbSwgdG8pID0+IHtcbiAgYXJyYXkuc3BsaWNlKHRvIDwgMCA/IGFycmF5Lmxlbmd0aCArIHRvIDogdG8sIDAsIGFycmF5LnNwbGljZShmcm9tLCAxKVswXSk7XG59O1xuXG5leHBvcnQgY29uc3QgYXJyYXlNb3ZlID0gKGFycmF5LCBmcm9tLCB0bykgPT4ge1xuICBhcnJheSA9IGFycmF5LnNsaWNlKCk7XG4gIGFycmF5TW92ZU11dGF0ZShhcnJheSwgZnJvbSwgdG8pO1xuICByZXR1cm4gYXJyYXk7XG59O1xuIl19