UNPKG

kepler.gl

Version:

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

223 lines (190 loc) 22.2 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.unique = unique; exports.findMapBounds = findMapBounds; exports.getLatLngBounds = getLatLngBounds; exports.getSampleData = getSampleData; exports.maybeToDate = maybeToDate; exports.notNullorUndefined = notNullorUndefined; exports.isPlainObject = isPlainObject; exports.numberSort = numberSort; exports.getSortingFunction = getSortingFunction; exports.preciseRound = preciseRound; exports.getRoundingDecimalFromStep = getRoundingDecimalFromStep; exports.roundValToStep = roundValToStep; var _moment = require('moment'); var _moment2 = _interopRequireDefault(_moment); var _assert = require('assert'); var _assert2 = _interopRequireDefault(_assert); var _defaultSettings = require('../constants/default-settings'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var MAX_LATITUDE = 90; // Copyright (c) 2018 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. 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) && v !== null && v !== undefined) { 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 getSampleData(data) { var sampleSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 500; var sampleStep = Math.max(Math.floor(data.length / sampleSize), 1); var output = []; for (var i = 0; i < data.length; i += sampleStep) { output.push(data[i]); } return output; } function maybeToDate(isTime, fieldIdx, format, d) { if (isTime) { if (notNullorUndefined(d[fieldIdx])) { return typeof d[fieldIdx] === 'string' ? _moment2.default.utc(d[fieldIdx], format).valueOf() : format === 'x' ? d[fieldIdx] * 1000 : d[fieldIdx]; } return null; } return d[fieldIdx]; } 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, _assert2.default)('step is not a number'); (0, _assert2.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 = void 0; 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); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9kYXRhLXV0aWxzLmpzIl0sIm5hbWVzIjpbInVuaXF1ZSIsImZpbmRNYXBCb3VuZHMiLCJnZXRMYXRMbmdCb3VuZHMiLCJnZXRTYW1wbGVEYXRhIiwibWF5YmVUb0RhdGUiLCJub3ROdWxsb3JVbmRlZmluZWQiLCJpc1BsYWluT2JqZWN0IiwibnVtYmVyU29ydCIsImdldFNvcnRpbmdGdW5jdGlvbiIsInByZWNpc2VSb3VuZCIsImdldFJvdW5kaW5nRGVjaW1hbEZyb21TdGVwIiwicm91bmRWYWxUb1N0ZXAiLCJNQVhfTEFUSVRVREUiLCJNSU5fTEFUSVRVREUiLCJNQVhfTE9OR0lUVURFIiwiTUlOX0xPTkdJVFVERSIsInZhbHVlcyIsInJlc3VsdHMiLCJmb3JFYWNoIiwiaW5jbHVkZXMiLCJ2IiwidW5kZWZpbmVkIiwicHVzaCIsImxheWVycyIsImF2YWlsYWJsZUxheWVyQm91bmRzIiwicmVkdWNlIiwicmVzIiwibCIsIm1ldGEiLCJib3VuZHMiLCJsZW5ndGgiLCJuZXdCb3VuZHMiLCJiIiwiTWF0aCIsIm1pbiIsIm1heCIsInBvaW50cyIsImlkeCIsImxpbWl0IiwibGF0cyIsIm1hcCIsIkFycmF5IiwiaXNBcnJheSIsImQiLCJmaWx0ZXIiLCJOdW1iZXIiLCJpc0Zpbml0ZSIsInNvcnQiLCJmbG9vciIsImNlaWwiLCJkYXRhIiwic2FtcGxlU2l6ZSIsInNhbXBsZVN0ZXAiLCJvdXRwdXQiLCJpIiwiaXNUaW1lIiwiZmllbGRJZHgiLCJmb3JtYXQiLCJtb21lbnQiLCJ1dGMiLCJ2YWx1ZU9mIiwib2JqIiwiT2JqZWN0IiwiYSIsImZpZWxkVHlwZSIsIkFMTF9GSUVMRF9UWVBFUyIsInJlYWwiLCJpbnRlZ2VyIiwidGltZXN0YW1wIiwibnVtIiwiZGVjaW1hbHMiLCJ0IiwicG93Iiwicm91bmQiLCJzaWduIiwidG9GaXhlZCIsInN0ZXAiLCJpc05hTiIsInNwbGl0WmVybyIsInRvU3RyaW5nIiwic3BsaXQiLCJtaW5WYWx1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LEdBQXFCSyxRQUEvQjtBQUNEOztBQUVEO0FBQ0EsTUFBTU0sVUFBVTlFLGFBQWE2RSxPQUFiLEVBQXNCSCxPQUF0QixDQUFoQjs7QUFFQSxTQUFPdEMsT0FBTzBDLE9BQVAsQ0FBUDtBQUNEIiwiZmlsZSI6ImRhdGEtdXRpbHMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMTggVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQge0FMTF9GSUVMRF9UWVBFU30gZnJvbSAnY29uc3RhbnRzL2RlZmF1bHQtc2V0dGluZ3MnO1xuXG5jb25zdCBNQVhfTEFUSVRVREUgPSA5MDtcbmNvbnN0IE1JTl9MQVRJVFVERSA9IC05MDtcbmNvbnN0IE1BWF9MT05HSVRVREUgPSAxODA7XG5jb25zdCBNSU5fTE9OR0lUVURFID0gLTE4MDtcblxuLyoqXG4gKiBzaW1wbGUgZ2V0dGluZyB1bmlxdWUgdmFsdWVzIG9mIGFuIGFycmF5XG4gKlxuICogQHBhcmFtIHthcnJheX0gdmFsdWVzXG4gKiBAcmV0dXJucyB7YXJyYXl9IHVuaXF1ZSB2YWx1ZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuaXF1ZSh2YWx1ZXMpIHtcbiAgY29uc3QgcmVzdWx0cyA9IFtdO1xuICB2YWx1ZXMuZm9yRWFjaCh2ID0+IHtcbiAgICBpZiAoIXJlc3VsdHMuaW5jbHVkZXModikgJiYgdiAhPT0gbnVsbCAmJiB2ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlc3VsdHMucHVzaCh2KTtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiByZXN1bHRzO1xufVxuXG4vKiBlc2xpbnQtZGlzYWJsZSBtYXgtc3RhdGVtZW50cyAqL1xuLyoqXG4gKiByZXR1cm4gY2VudGVyIG9mIG1hcCBmcm9tIGdpdmVuIHBvaW50c1xuICogQHBhcmFtIHthcnJheX0gbGF5ZXJzXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YUlkXG4gKiBAcmV0dXJucyB7b2JqZWN0fSBjb29yZGluYXRlcyBvZiBtYXAgY2VudGVyLCBlbXB0eSBpZiBub3QgZm91bmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmRNYXBCb3VuZHMobGF5ZXJzKSB7XG4gIC8vIGZpbmQgYm91bmRzIGluIGZvcm1hdHRlZCBsYXllckRhdGFcbiAgLy8gdGFrZSBBTEwgbGF5ZXJzIGludG8gYWNjb3VudCB3aGVuIGZpbmRpbmcgbWFwIGJvdW5kc1xuICBjb25zdCBhdmFpbGFibGVMYXllckJvdW5kcyA9IGxheWVycy5yZWR1Y2UoKHJlcywgbCkgPT4ge1xuICAgIGlmIChsLm1ldGEgJiYgbC5tZXRhLmJvdW5kcykge1xuICAgICAgcmVzLnB1c2gobC5tZXRhLmJvdW5kcyk7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG4gIH0sIFtdKVxuICAvLyByZXR1cm4gbnVsbCBpZiBubyBsYXllciBpcyBhdmFpbGFibGVcbiAgaWYgKGF2YWlsYWJsZUxheWVyQm91bmRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIC8vIG1lcmdlIGJvdW5kcyBpbiBlYWNoIGxheWVyXG4gIGNvbnN0IG5ld0JvdW5kcyA9IGF2YWlsYWJsZUxheWVyQm91bmRzLnJlZHVjZSgocmVzLCBiKSA9PiB7XG4gICAgcmV0dXJuIFtcbiAgICAgIE1hdGgubWluKHJlc1swXSwgYlswXSksXG4gICAgICBNYXRoLm1pbihyZXNbMV0sIGJbMV0pLFxuICAgICAgTWF0aC5tYXgocmVzWzJdLCBiWzJdKSxcbiAgICAgIE1hdGgubWF4KHJlc1szXSwgYlszXSlcbiAgICBdO1xuICB9LCBbTUFYX0xPTkdJVFVERSwgTUFYX0xBVElUVURFLCBNSU5fTE9OR0lUVURFLCBNSU5fTEFUSVRVREVdKTtcbiAgcmV0dXJuIG5ld0JvdW5kcztcbn1cbi8qIGVzbGludC1lbmFibGUgbWF4LXN0YXRlbWVudHMgKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExhdExuZ0JvdW5kcyhwb2ludHMsIGlkeCwgbGltaXQpIHtcbiAgY29uc3QgbGF0cyA9IHBvaW50c1xuICAgIC5tYXAoZCA9PiBBcnJheS5pc0FycmF5KGQpICYmIGRbaWR4XSlcbiAgICAuZmlsdGVyKE51bWJlci5pc0Zpbml0ZSlcbiAgICAuc29ydChudW1iZXJTb3J0KTtcblxuICBpZiAoIWxhdHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgLy8gdXNlIDk5IHBlcmNlbnRpbGUgdG8gZmlsdGVyIG91dCBvdXRsaWVyc1xuICAvLyBjbGFtcCB0byBsaW1pdFxuICByZXR1cm4gW1xuICAgIE1hdGgubWF4KGxhdHNbTWF0aC5mbG9vcigwLjAxICogKGxhdHMubGVuZ3RoIC0gMSkpXSwgbGltaXRbMF0pLFxuICAgIE1hdGgubWluKGxhdHNbTWF0aC5jZWlsKDAuOTkgKiAobGF0cy5sZW5ndGggLSAxKSldLCBsaW1pdFsxXSlcbiAgXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNhbXBsZURhdGEoZGF0YSwgc2FtcGxlU2l6ZSA9IDUwMCkge1xuICBjb25zdCBzYW1wbGVTdGVwID0gTWF0aC5tYXgoTWF0aC5mbG9vcihkYXRhLmxlbmd0aCAvIHNhbXBsZVNpemUpLCAxKTtcbiAgY29uc3Qgb3V0cHV0ID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkgKz0gc2FtcGxlU3RlcCkge1xuICAgIG91dHB1dC5wdXNoKGRhdGFbaV0pO1xuICB9XG5cbiAgcmV0dXJuIG91dHB1dDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1heWJlVG9EYXRlKGlzVGltZSwgZmllbGRJZHgsIGZvcm1hdCwgZCkge1xuICBpZiAoaXNUaW1lKSB7XG4gICAgaWYgKG5vdE51bGxvclVuZGVmaW5lZChkW2ZpZWxkSWR4XSkpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgZFtmaWVsZElkeF0gPT09ICdzdHJpbmcnXG4gICAgICAgID8gbW9tZW50LnV0YyhkW2ZpZWxkSWR4XSwgZm9ybWF0KS52YWx1ZU9mKClcbiAgICAgICAgOiBmb3JtYXQgPT09ICd4JyA/IGRbZmllbGRJZHhdICogMTAwMCA6IGRbZmllbGRJZHhdO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIGRbZmllbGRJZHhdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbm90TnVsbG9yVW5kZWZpbmVkKGQpIHtcbiAgcmV0dXJuIGQgIT09IHVuZGVmaW5lZCAmJiBkICE9PSBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNQbGFpbk9iamVjdChvYmopIHtcbiAgcmV0dXJuIChcbiAgICBvYmogPT09IE9iamVjdChvYmopICYmIHR5cGVvZiBvYmogIT09ICdmdW5jdGlvbicgJiYgIUFycmF5LmlzQXJyYXkob2JqKVxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbnVtYmVyU29ydChhLCBiKSB7XG4gIHJldHVybiBhIC0gYjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNvcnRpbmdGdW5jdGlvbihmaWVsZFR5cGUpIHtcbiAgc3dpdGNoIChmaWVsZFR5cGUpIHtcbiAgICBjYXNlIEFMTF9GSUVMRF9UWVBFUy5yZWFsOlxuICAgIGNhc2UgQUxMX0ZJRUxEX1RZUEVTLmludGVnZXI6XG4gICAgY2FzZSBBTExfRklFTERfVFlQRVMudGltZXN0YW1wOlxuICAgICAgcmV0dXJuIG51bWJlclNvcnQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiByb3VuZCBudW1iZXIgd2l0aCBleGFjdCBudW1iZXIgb2YgZGVjaW1hbHNcbiAqIHJldHVybiBhcyBhIHN0cmluZ1xuICogQHBhcmFtIHtudW1iZXJ9IG51bVxuICogQHBhcmFtIHtudW1iZXJ9IGRlY2ltYWxzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIGEgcm91bmRlZCBudW1iZXIgaW4gc3RyaW5nIGZvcm1hdFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlY2lzZVJvdW5kKG51bSwgZGVjaW1hbHMpIHtcbiAgY29uc3QgdCA9IE1hdGgucG93KDEwLCBkZWNpbWFscyk7XG4gIHJldHVybiAoXG4gICAgTWF0aC5yb3VuZChcbiAgICAgIG51bSAqIHQgK1xuICAgICAgICAoZGVjaW1hbHMgPiAwID8gMSA6IDApICpcbiAgICAgICAgICAoTWF0aC5zaWduKG51bSkgKiAoMTAgLyBNYXRoLnBvdygxMDAsIGRlY2ltYWxzKSkpXG4gICAgKSAvIHRcbiAgKS50b0ZpeGVkKGRlY2ltYWxzKTtcbn1cblxuLyoqXG4gKiBnZXQgbnVtYmVyIG9mIGRlY2ltYWxzIHRvIHJvdW5kIHRvIGZvciBzbGlkZXIgZnJvbSBzdGVwXG4gKiBAcGFyYW0ge251bWJlcn0gc3RlcFxuICogQHJldHVybnMge251bWJlcn0gLSBudW1iZXIgb2YgZGVjaW1hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Um91bmRpbmdEZWNpbWFsRnJvbVN0ZXAoc3RlcCkge1xuICBpZiAoaXNOYU4oc3RlcCkpIHtcbiAgICBhc3NlcnQoJ3N0ZXAgaXMgbm90IGEgbnVtYmVyJyk7XG4gICAgYXNzZXJ0KHN0ZXApO1xuICB9XG5cbiAgY29uc3Qgc3BsaXRaZXJvID0gc3RlcC50b1N0cmluZygpLnNwbGl0KCcuJyk7XG4gIGlmIChzcGxpdFplcm8ubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgcmV0dXJuIHNwbGl0WmVyb1sxXS5sZW5ndGg7XG59XG5cbi8qKlxuICogcm91bmQgdGhlIHZhbHVlIHRvIHN0ZXAgZm9yIHRoZSBzbGlkZXJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtaW5WYWx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IHN0ZXBcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWxcbiAqIEByZXR1cm5zIHtudW1iZXJ9IC0gcm91bmRlZCBudW1iZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdW5kVmFsVG9TdGVwKG1pblZhbHVlLCBzdGVwLCB2YWwpIHtcbiAgaWYgKGlzTmFOKHN0ZXApKSB7XG4gICAgcmV0dXJuIHZhbDtcbiAgfVxuXG4gIGNvbnN0IGRlY2ltYWwgPSBnZXRSb3VuZGluZ0RlY2ltYWxGcm9tU3RlcChzdGVwKTtcbiAgY29uc3Qgc3RlcHMgPSBNYXRoLmZsb29yKCh2YWwgLSBtaW5WYWx1ZSkgLyBzdGVwKTtcbiAgbGV0IHJlbWFpbiA9IHZhbCAtIChzdGVwcyAqIHN0ZXAgKyBtaW5WYWx1ZSk7XG5cbiAgLy8gaGFzIHRvIHJvdW5kIGJlY2F1c2UgamF2YXNjcmlwdCB0dXJucyAwLjEgaW50byAwLjk5OTk5OTk5OTk5OTk5ODdcbiAgcmVtYWluID0gTnVtYmVyKHByZWNpc2VSb3VuZChyZW1haW4sIDgpKTtcblxuICBsZXQgY2xvc2VzdDtcbiAgaWYgKHJlbWFpbiA9PT0gMCkge1xuICAgIGNsb3Nlc3QgPSB2YWw7XG4gIH0gZWxzZSBpZiAocmVtYWluIDwgc3RlcCAvIDIpIHtcbiAgICBjbG9zZXN0ID0gc3RlcHMgKiBzdGVwICsgbWluVmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgY2xvc2VzdCA9IChzdGVwcyArIDEpICogc3RlcCArIG1pblZhbHVlO1xuICB9XG5cbiAgLy8gcHJlY2lzZSByb3VuZCByZXR1cm4gYSBzdHJpbmcgcm91bmRlZCB0byB0aGUgZGVmaW5lZCBkZWNpbWFsXG4gIGNvbnN0IHJvdW5kZWQgPSBwcmVjaXNlUm91bmQoY2xvc2VzdCwgZGVjaW1hbCk7XG5cbiAgcmV0dXJuIE51bWJlcihyb3VuZGVkKTtcbn1cbiJdfQ==