UNPKG

kepler.gl

Version:

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

303 lines (237 loc) 29.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.unique = unique; exports.findMapBounds = findMapBounds; exports.getLatLngBounds = getLatLngBounds; exports.clamp = clamp; exports.getSampleData = getSampleData; exports.timeToUnixMilli = timeToUnixMilli; exports.maybeToDate = maybeToDate; exports.notNullorUndefined = notNullorUndefined; exports.isPlainObject = isPlainObject; exports.numberSort = numberSort; exports.getSortingFunction = getSortingFunction; exports.preciseRound = preciseRound; exports.getRoundingDecimalFromStep = getRoundingDecimalFromStep; exports.roundValToStep = roundValToStep; exports.findFirstNoneEmpty = findFirstNoneEmpty; exports.arrayMove = exports.parseFieldValue = exports.FIELD_DISPLAY_FORMAT = void 0; 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; } // clamp to limit return [Math.max(lats[0], limit[0]), Math.min(lats[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 = (_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 {*} */ exports.FIELD_DISPLAY_FORMAT = FIELD_DISPLAY_FORMAT; var parseFieldValue = function parseFieldValue(value, type) { if (!notNullorUndefined(value)) { return ''; } return FIELD_DISPLAY_FORMAT[type] ? FIELD_DISPLAY_FORMAT[type](value) : String(value); }; exports.parseFieldValue = parseFieldValue; var arrayMoveMutate = function arrayMoveMutate(array, from, to) { array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]); }; var arrayMove = function arrayMove(array, from, to) { array = array.slice(); arrayMoveMutate(array, from, to); return array; }; exports.arrayMove = arrayMove; function findFirstNoneEmpty(data) { var count = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; var getValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : identity; var c = 0; var found = []; while (c < count && c < data.length) { var value = getValue(data[c]); if (notNullorUndefined(value)) { found.push(value); } c++; } return found; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9kYXRhLXV0aWxzLmpzIl0sIm5hbWVzIjpbIk1BWF9MQVRJVFVERSIsIk1JTl9MQVRJVFVERSIsIk1BWF9MT05HSVRVREUiLCJNSU5fTE9OR0lUVURFIiwidW5pcXVlIiwidmFsdWVzIiwicmVzdWx0cyIsImZvckVhY2giLCJ2IiwiaW5jbHVkZXMiLCJub3ROdWxsb3JVbmRlZmluZWQiLCJwdXNoIiwiZmluZE1hcEJvdW5kcyIsImxheWVycyIsImF2YWlsYWJsZUxheWVyQm91bmRzIiwicmVkdWNlIiwicmVzIiwibCIsIm1ldGEiLCJib3VuZHMiLCJsZW5ndGgiLCJuZXdCb3VuZHMiLCJiIiwiTWF0aCIsIm1pbiIsIm1heCIsImdldExhdExuZ0JvdW5kcyIsInBvaW50cyIsImlkeCIsImxpbWl0IiwibGF0cyIsIm1hcCIsImQiLCJBcnJheSIsImlzQXJyYXkiLCJmaWx0ZXIiLCJOdW1iZXIiLCJpc0Zpbml0ZSIsInNvcnQiLCJudW1iZXJTb3J0IiwiY2xhbXAiLCJ2YWwiLCJnZXRTYW1wbGVEYXRhIiwiZGF0YSIsInNhbXBsZVNpemUiLCJnZXRWYWx1ZSIsInNhbXBsZVN0ZXAiLCJmbG9vciIsIm91dHB1dCIsImkiLCJ0aW1lVG9Vbml4TWlsbGkiLCJ2YWx1ZSIsImZvcm1hdCIsIm1vbWVudCIsInV0YyIsInZhbHVlT2YiLCJtYXliZVRvRGF0ZSIsImlzVGltZSIsImZpZWxkSWR4IiwidW5kZWZpbmVkIiwiaXNQbGFpbk9iamVjdCIsIm9iaiIsIk9iamVjdCIsImEiLCJnZXRTb3J0aW5nRnVuY3Rpb24iLCJmaWVsZFR5cGUiLCJBTExfRklFTERfVFlQRVMiLCJyZWFsIiwiaW50ZWdlciIsInRpbWVzdGFtcCIsInByZWNpc2VSb3VuZCIsIm51bSIsImRlY2ltYWxzIiwidCIsInBvdyIsInJvdW5kIiwic2lnbiIsInRvRml4ZWQiLCJnZXRSb3VuZGluZ0RlY2ltYWxGcm9tU3RlcCIsInN0ZXAiLCJpc05hTiIsInNwbGl0WmVybyIsInRvU3RyaW5nIiwic3BsaXQiLCJyb3VuZFZhbFRvU3RlcCIsIm1pblZhbHVlIiwiZGVjaW1hbCIsInN0ZXBzIiwicmVtYWluIiwiY2xvc2VzdCIsInJvdW5kZWQiLCJpZGVudGl0eSIsIkZJRUxEX0RJU1BMQVlfRk9STUFUIiwic3RyaW5nIiwiU3RyaW5nIiwiZGF0ZSIsImdlb2pzb24iLCJKU09OIiwic3RyaW5naWZ5IiwicGFyc2VGaWVsZFZhbHVlIiwidHlwZSIsImFycmF5TW92ZU11dGF0ZSIsImFycmF5IiwiZnJvbSIsInRvIiwic3BsaWNlIiwiYXJyYXlNb3ZlIiwic2xpY2UiLCJmaW5kRmlyc3ROb25lRW1wdHkiLCJjb3VudCIsImMiLCJmb3VuZCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTs7QUFDQTs7QUFDQTs7OztBQUVBLElBQU1BLFlBQVksR0FBRyxFQUFyQjtBQUNBLElBQU1DLFlBQVksR0FBRyxDQUFDLEVBQXRCO0FBQ0EsSUFBTUMsYUFBYSxHQUFHLEdBQXRCO0FBQ0EsSUFBTUMsYUFBYSxHQUFHLENBQUMsR0FBdkI7QUFFQTs7Ozs7OztBQU1PLFNBQVNDLE1BQVQsQ0FBZ0JDLE1BQWhCLEVBQXdCO0FBQzdCLE1BQU1DLE9BQU8sR0FBRyxFQUFoQjtBQUNBRCxFQUFBQSxNQUFNLENBQUNFLE9BQVAsQ0FBZSxVQUFBQyxDQUFDLEVBQUk7QUFDbEIsUUFBSSxDQUFDRixPQUFPLENBQUNHLFFBQVIsQ0FBaUJELENBQWpCLENBQUQsSUFBd0JFLGtCQUFrQixDQUFDRixDQUFELENBQTlDLEVBQW1EO0FBQ2pERixNQUFBQSxPQUFPLENBQUNLLElBQVIsQ0FBYUgsQ0FBYjtBQUNEO0FBQ0YsR0FKRDtBQU1BLFNBQU9GLE9BQVA7QUFDRDtBQUVEOztBQUNBOzs7Ozs7OztBQU1PLFNBQVNNLGFBQVQsQ0FBdUJDLE1BQXZCLEVBQStCO0FBQ3BDO0FBQ0E7QUFDQSxNQUFNQyxvQkFBb0IsR0FBR0QsTUFBTSxDQUFDRSxNQUFQLENBQWMsVUFBQ0MsR0FB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aHQgKGMpIDIwMjAgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQge0FMTF9GSUVMRF9UWVBFU30gZnJvbSAnY29uc3RhbnRzL2RlZmF1bHQtc2V0dGluZ3MnO1xuXG5jb25zdCBNQVhfTEFUSVRVREUgPSA5MDtcbmNvbnN0IE1JTl9MQVRJVFVERSA9IC05MDtcbmNvbnN0IE1BWF9MT05HSVRVREUgPSAxODA7XG5jb25zdCBNSU5fTE9OR0lUVURFID0gLTE4MDtcblxuLyoqXG4gKiBzaW1wbGUgZ2V0dGluZyB1bmlxdWUgdmFsdWVzIG9mIGFuIGFycmF5XG4gKlxuICogQHBhcmFtIHthcnJheX0gdmFsdWVzXG4gKiBAcmV0dXJucyB7YXJyYXl9IHVuaXF1ZSB2YWx1ZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuaXF1ZSh2YWx1ZXMpIHtcbiAgY29uc3QgcmVzdWx0cyA9IFtdO1xuICB2YWx1ZXMuZm9yRWFjaCh2ID0+IHtcbiAgICBpZiAoIXJlc3VsdHMuaW5jbHVkZXModikgJiYgbm90TnVsbG9yVW5kZWZpbmVkKHYpKSB7XG4gICAgICByZXN1bHRzLnB1c2godik7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gcmVzdWx0cztcbn1cblxuLyogZXNsaW50LWRpc2FibGUgbWF4LXN0YXRlbWVudHMgKi9cbi8qKlxuICogcmV0dXJuIGNlbnRlciBvZiBtYXAgZnJvbSBnaXZlbiBwb2ludHNcbiAqIEBwYXJhbSB7YXJyYXl9IGxheWVyc1xuICogQHBhcmFtIHtzdHJpbmd9IGRhdGFJZFxuICogQHJldHVybnMge29iamVjdH0gY29vcmRpbmF0ZXMgb2YgbWFwIGNlbnRlciwgZW1wdHkgaWYgbm90IGZvdW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kTWFwQm91bmRzKGxheWVycykge1xuICAvLyBmaW5kIGJvdW5kcyBpbiBmb3JtYXR0ZWQgbGF5ZXJEYXRhXG4gIC8vIHRha2UgQUxMIGxheWVycyBpbnRvIGFjY291bnQgd2hlbiBmaW5kaW5nIG1hcCBib3VuZHNcbiAgY29uc3QgYXZhaWxhYmxlTGF5ZXJCb3VuZHMgPSBsYXllcnMucmVkdWNlKChyZXMsIGwpID0+IHtcbiAgICBpZiAobC5tZXRhICYmIGwubWV0YS5ib3VuZHMpIHtcbiAgICAgIHJlcy5wdXNoKGwubWV0YS5ib3VuZHMpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xuICB9LCBbXSk7XG4gIC8vIHJldHVybiBudWxsIGlmIG5vIGxheWVyIGlzIGF2YWlsYWJsZVxuICBpZiAoYXZhaWxhYmxlTGF5ZXJCb3VuZHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgLy8gbWVyZ2UgYm91bmRzIGluIGVhY2ggbGF5ZXJcbiAgY29uc3QgbmV3Qm91bmRzID0gYXZhaWxhYmxlTGF5ZXJCb3VuZHMucmVkdWNlKFxuICAgIChyZXMsIGIpID0+IHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIE1hdGgubWluKHJlc1swXSwgYlswXSksXG4gICAgICAgIE1hdGgubWluKHJlc1sxXSwgYlsxXSksXG4gICAgICAgIE1hdGgubWF4KHJlc1syXSwgYlsyXSksXG4gICAgICAgIE1hdGgubWF4KHJlc1szXSwgYlszXSlcbiAgICAgIF07XG4gICAgfSxcbiAgICBbTUFYX0xPTkdJVFVERSwgTUFYX0xBVElUVURFLCBNSU5fTE9OR0lUVURFLCBNSU5fTEFUSVRVREVdXG4gICk7XG4gIHJldHVybiBuZXdCb3VuZHM7XG59XG4vKiBlc2xpbnQtZW5hYmxlIG1heC1zdGF0ZW1lbnRzICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMYXRMbmdCb3VuZHMocG9pbnRzLCBpZHgsIGxpbWl0KSB7XG4gIGNvbnN0IGxhdHMgPSBwb2ludHNcbiAgICAubWFwKGQgPT4gQXJyYXkuaXNBcnJheShkKSAmJiBkW2lkeF0pXG4gICAgLmZpbHRlcihOdW1iZXIuaXNGaW5pdGUpXG4gICAgLnNvcnQobnVtYmVyU29ydCk7XG5cbiAgaWYgKCFsYXRzLmxlbmd0aCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLy8gY2xhbXAgdG8gbGltaXRcbiAgcmV0dXJuIFtNYXRoLm1heChsYXRzWzBdLCBsaW1pdFswXSksIE1hdGgubWluKGxhdHNbbGF0cy5sZW5ndGggLSAxXSwgbGltaXRbMV0pXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNsYW1wKFttaW4sIG1heF0sIHZhbCkge1xuICByZXR1cm4gdmFsIDw9IG1pbiA/IG1pbiA6IHZhbCA+PSBtYXggPyBtYXggOiB2YWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTYW1wbGVEYXRhKGRhdGEsIHNhbXBsZVNpemUgPSA1MDAsIGdldFZhbHVlID0gZCA9PiBkKSB7XG4gIGNvbnN0IHNhbXBsZVN0ZXAgPSBNYXRoLm1heChNYXRoLmZsb29yKGRhdGEubGVuZ3RoIC8gc2FtcGxlU2l6ZSksIDEpO1xuICBjb25zdCBvdXRwdXQgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSArPSBzYW1wbGVTdGVwKSB7XG4gICAgb3V0cHV0LnB1c2goZ2V0VmFsdWUoZGF0YVtpXSkpO1xuICB9XG5cbiAgcmV0dXJuIG91dHB1dDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGRpZmZlcmVudCB0aW1lIGZvcm1hdCB0byB1bml4IG1pbGxpc2Vjb25kc1xuICogQHBhcmFtIHsqfSB2YWx1ZVxuICogQHBhcmFtIHsqfSBmb3JtYXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbWVUb1VuaXhNaWxsaSh2YWx1ZSwgZm9ybWF0KSB7XG4gIGlmIChub3ROdWxsb3JVbmRlZmluZWQodmFsdWUpKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZydcbiAgICAgID8gbW9tZW50LnV0Yyh2YWx1ZSwgZm9ybWF0KS52YWx1ZU9mKClcbiAgICAgIDogZm9ybWF0ID09PSAneCdcbiAgICAgID8gdmFsdWUgKiAxMDAwXG4gICAgICA6IHZhbHVlO1xuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF5YmVUb0RhdGUoaXNUaW1lLCBmaWVsZElkeCwgZm9ybWF0LCBkKSB7XG4gIGlmIChpc1RpbWUpIHtcbiAgICByZXR1cm4gdGltZVRvVW5peE1pbGxpKGRbZmllbGRJZHhdLCBmb3JtYXQpO1xuICB9XG5cbiAgcmV0dXJuIGRbZmllbGRJZHhdO1xufVxuXG4vKipcbiAqIHdoZXRoZXIgbnVsbCBvciB1bmRlZmluZWRcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIHllcyBvciBub1xuICovXG5leHBvcnQgZnVuY3Rpb24gbm90TnVsbG9yVW5kZWZpbmVkKGQpIHtcbiAgcmV0dXJuIGQgIT09IHVuZGVmaW5lZCAmJiBkICE9PSBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNQbGFpbk9iamVjdChvYmopIHtcbiAgcmV0dXJuIG9iaiA9PT0gT2JqZWN0KG9iaikgJiYgdHlwZW9mIG9iaiAhPT0gJ2Z1bmN0aW9uJyAmJiAhQXJyYXkuaXNBcnJheShvYmopO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbnVtYmVyU29ydChhLCBiKSB7XG4gIHJldHVybiBhIC0gYjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNvcnRpbmdGdW5jdGlvbihmaWVsZFR5cGUpIHtcbiAgc3dpdGNoIChmaWVsZFR5cGUpIHtcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5yZWFsOlxuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmludGVnZXI6XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMudGltZXN0YW1wOlxuICAgICAgcmV0dXJuIG51bWJlclNvcnQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiByb3VuZCBudW1iZXIgd2l0aCBleGFjdCBudW1iZXIgb2YgZGVjaW1hbHNcbiAqIHJldHVybiBhcyBhIHN0cmluZ1xuICogQHBhcmFtIHtudW1iZXJ9IG51bVxuICogQHBhcmFtIHtudW1iZXJ9IGRlY2ltYWxzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIGEgcm91bmRlZCBudW1iZXIgaW4gc3RyaW5nIGZvcm1hdFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlY2lzZVJvdW5kKG51bSwgZGVjaW1hbHMpIHtcbiAgY29uc3QgdCA9IE1hdGgucG93KDEwLCBkZWNpbWFscyk7XG4gIHJldHVybiAoXG4gICAgTWF0aC5yb3VuZChcbiAgICAgIG51bSAqIHQgKyAoZGVjaW1hbHMgPiAwID8gMSA6IDApICogKE1hdGguc2lnbihudW0pICogKDEwIC8gTWF0aC5wb3coMTAwLCBkZWNpbWFscykpKVxuICAgICkgLyB0XG4gICkudG9GaXhlZChkZWNpbWFscyk7XG59XG5cbi8qKlxuICogZ2V0IG51bWJlciBvZiBkZWNpbWFscyB0byByb3VuZCB0byBmb3Igc2xpZGVyIGZyb20gc3RlcFxuICogQHBhcmFtIHtudW1iZXJ9IHN0ZXBcbiAqIEByZXR1cm5zIHtudW1iZXJ9IC0gbnVtYmVyIG9mIGRlY2ltYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFJvdW5kaW5nRGVjaW1hbEZyb21TdGVwKHN0ZXApIHtcbiAgaWYgKGlzTmFOKHN0ZXApKSB7XG4gICAgYXNzZXJ0KCdzdGVwIGlzIG5vdCBhIG51bWJlcicpO1xuICAgIGFzc2VydChzdGVwKTtcbiAgfVxuXG4gIGNvbnN0IHNwbGl0WmVybyA9IHN0ZXAudG9TdHJpbmcoKS5zcGxpdCgnLicpO1xuICBpZiAoc3BsaXRaZXJvLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiAwO1xuICB9XG4gIHJldHVybiBzcGxpdFplcm9bMV0ubGVuZ3RoO1xufVxuXG4vKipcbiAqIHJvdW5kIHRoZSB2YWx1ZSB0byBzdGVwIGZvciB0aGUgc2xpZGVyXG4gKiBAcGFyYW0ge251bWJlcn0gbWluVmFsdWVcbiAqIEBwYXJhbSB7bnVtYmVyfSBzdGVwXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsXG4gKiBAcmV0dXJucyB7bnVtYmVyfSAtIHJvdW5kZWQgbnVtYmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByb3VuZFZhbFRvU3RlcChtaW5WYWx1ZSwgc3RlcCwgdmFsKSB7XG4gIGlmIChpc05hTihzdGVwKSkge1xuICAgIHJldHVybiB2YWw7XG4gIH1cblxuICBjb25zdCBkZWNpbWFsID0gZ2V0Um91bmRpbmdEZWNpbWFsRnJvbVN0ZXAoc3RlcCk7XG4gIGNvbnN0IHN0ZXBzID0gTWF0aC5mbG9vcigodmFsIC0gbWluVmFsdWUpIC8gc3RlcCk7XG4gIGxldCByZW1haW4gPSB2YWwgLSAoc3RlcHMgKiBzdGVwICsgbWluVmFsdWUpO1xuXG4gIC8vIGhhcyB0byByb3VuZCBiZWNhdXNlIGphdmFzY3JpcHQgdHVybnMgMC4xIGludG8gMC45OTk5OTk5OTk5OTk5OTg3XG4gIHJlbWFpbiA9IE51bWJlcihwcmVjaXNlUm91bmQocmVtYWluLCA4KSk7XG5cbiAgbGV0IGNsb3Nlc3Q7XG4gIGlmIChyZW1haW4gPT09IDApIHtcbiAgICBjbG9zZXN0ID0gdmFsO1xuICB9IGVsc2UgaWYgKHJlbWFpbiA8IHN0ZXAgLyAyKSB7XG4gICAgY2xvc2VzdCA9IHN0ZXBzICogc3RlcCArIG1pblZhbHVlO1xuICB9IGVsc2Uge1xuICAgIGNsb3Nlc3QgPSAoc3RlcHMgKyAxKSAqIHN0ZXAgKyBtaW5WYWx1ZTtcbiAgfVxuXG4gIC8vIHByZWNpc2Ugcm91bmQgcmV0dXJuIGEgc3RyaW5nIHJvdW5kZWQgdG8gdGhlIGRlZmluZWQgZGVjaW1hbFxuICBjb25zdCByb3VuZGVkID0gcHJlY2lzZVJvdW5kKGNsb3Nlc3QsIGRlY2ltYWwpO1xuXG4gIHJldHVybiBOdW1iZXIocm91bmRlZCk7XG59XG5cbmNvbnN0IGlkZW50aXR5ID0gZCA9PiBkO1xuXG5leHBvcnQgY29uc3QgRklFTERfRElTUExBWV9GT1JNQVQgPSB7XG4gIFtBTExfRklFTERfVFlQRVMuc3RyaW5nXTogaWRlbnRpdHksXG4gIFtBTExfRklFTERfVFlQRVMudGltZXN0YW1wXTogaWRlbnRpdHksXG4gIFtBTExfRklFTERfVFlQRVMuaW50ZWdlcl06IGlkZW50aXR5LFxuICBbQUxMX0ZJRUxEX1RZUEVTLnJlYWxdOiBpZGVudGl0eSxcbiAgW0FMTF9GSUVMRF9UWVBFUy5ib29sZWFuXTogZCA9PiBTdHJpbmcoZCksXG4gIFtBTExfRklFTERfVFlQRVMuZGF0ZV06IGlkZW50aXR5LFxuICBbQUxMX0ZJRUxEX1RZUEVTLmdlb2pzb25dOiBkID0+XG4gICAgdHlwZW9mIGQgPT09ICdzdHJpbmcnXG4gICAgICA/IGRcbiAgICAgIDogaXNQbGFpbk9iamVjdChkKVxuICAgICAgPyBKU09OLnN0cmluZ2lmeShkKVxuICAgICAgOiBBcnJheS5pc0FycmF5KGQpXG4gICAgICA/IGBbJHtTdHJpbmcoZCl9XWBcbiAgICAgIDogJydcbn07XG5cbi8qKlxuICogUGFyc2UgZmllbGQgdmFsdWUgYW5kIHR5cGUgYW5kIHJldHVybiBhIHN0cmluZyByZXByZXNlbnRhdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIHRoZSBmaWVsZCB2YWx1ZVxuICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgdGhlIGZpZWxkIHR5cGVcbiAqIEByZXR1cm4geyp9XG4gKi9cbmV4cG9ydCBjb25zdCBwYXJzZUZpZWxkVmFsdWUgPSAodmFsdWUsIHR5cGUpID0+IHtcbiAgaWYgKCFub3ROdWxsb3JVbmRlZmluZWQodmFsdWUpKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgcmV0dXJuIEZJRUxEX0RJU1BMQVlfRk9STUFUW3R5cGVdID8gRklFTERfRElTUExBWV9GT1JNQVRbdHlwZV0odmFsdWUpIDogU3RyaW5nKHZhbHVlKTtcbn07XG5cbmNvbnN0IGFycmF5TW92ZU11dGF0ZSA9IChhcnJheSwgZnJvbSwgdG8pID0+IHtcbiAgYXJyYXkuc3BsaWNlKHRvIDwgMCA/IGFycmF5Lmxlbmd0aCArIHRvIDogdG8sIDAsIGFycmF5LnNwbGljZShmcm9tLCAxKVswXSk7XG59O1xuXG5leHBvcnQgY29uc3QgYXJyYXlNb3ZlID0gKGFycmF5LCBmcm9tLCB0bykgPT4ge1xuICBhcnJheSA9IGFycmF5LnNsaWNlKCk7XG4gIGFycmF5TW92ZU11dGF0ZShhcnJheSwgZnJvbSwgdG8pO1xuICByZXR1cm4gYXJyYXk7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZmluZEZpcnN0Tm9uZUVtcHR5KGRhdGEsIGNvdW50ID0gMSwgZ2V0VmFsdWUgPSBpZGVudGl0eSkge1xuICBsZXQgYyA9IDA7XG4gIGNvbnN0IGZvdW5kID0gW107XG4gIHdoaWxlIChjIDwgY291bnQgJiYgYyA8IGRhdGEubGVuZ3RoKSB7XG4gICAgY29uc3QgdmFsdWUgPSBnZXRWYWx1ZShkYXRhW2NdKTtcbiAgICBpZiAobm90TnVsbG9yVW5kZWZpbmVkKHZhbHVlKSkge1xuICAgICAgZm91bmQucHVzaCh2YWx1ZSk7XG4gICAgfVxuICAgIGMrKztcbiAgfVxuICByZXR1cm4gZm91bmQ7XG59XG4iXX0=