kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
204 lines (165 loc) • 22.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.coordHasLength4 = coordHasLength4;
exports.containValidTime = containValidTime;
exports.isTripGeoJsonField = isTripGeoJsonField;
exports.parseTripGeoJsonTimestamp = parseTripGeoJsonTimestamp;
exports.getAnimationDomainFromTimestamps = getAnimationDomainFromTimestamps;
var _typeAnalyzer = require("type-analyzer");
var _dataUtils = require("../../utils/data-utils");
var _dataContainerUtils = require("../../utils/table-utils/data-container-utils");
var _geojsonUtils = require("../geojson-layer/geojson-utils");
// Copyright (c) 2021 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.
/**
* Parse geojson from string
* @param {array} samples feature object values
* @returns {boolean} whether the geometry coordinates has length of 4
*/
function coordHasLength4(samples) {
var hasLength4 = true;
for (var i = 0; i < samples.length; i += 1) {
hasLength4 = !samples[i].geometry.coordinates.find(function (c) {
return c.length < 4;
});
if (!hasLength4) {
break;
}
}
return hasLength4;
}
/**
* Check whether geojson linestring's 4th coordinate is 1) not timestamp 2) unix time stamp 3) real date time
* @param {array} timestamps array to be tested if its elements are timestamp
* @returns {object | boolean} the type of timestamp: unix/datetime/invalid(not timestamp)
*/
function containValidTime(timestamps) {
var formattedTimeStamps = timestamps.map(function (ts) {
return {
ts: ts
};
});
var ignoredDataTypes = Object.keys(_typeAnalyzer.DATA_TYPES).filter(function (type) {
return ![_typeAnalyzer.DATA_TYPES.TIME, _typeAnalyzer.DATA_TYPES.DATETIME].includes(type);
}); // ignore all types but TIME to improve performance
var analyzedType = _typeAnalyzer.Analyzer.computeColMeta(formattedTimeStamps, [], {
ignoredDataTypes: ignoredDataTypes
})[0];
if (!analyzedType || analyzedType.category !== 'TIME') {
return false;
}
return analyzedType;
}
/**
* Check if geojson features are trip layer animatable by meeting 3 conditions
* @param {import('utils/table-utils/data-container-interface').DataContainerInterface} dataContainer geojson feature objects container
* @param {object} field array of geojson feature objects
* @returns {boolean} whether it is trip layer animatable
*/
function isTripGeoJsonField(dataContainer, field) {
if (dataContainer.numRows() < 1) {
return false;
}
var maxCount = 10000;
var sampleRawFeatures = dataContainer.numRows() > maxCount ? (0, _dataContainerUtils.getSampleData)(dataContainer, maxCount) : dataContainer;
var features = sampleRawFeatures.mapIndex(field.valueAccessor).map(_geojsonUtils.parseGeoJsonRawFeature).filter(function (f) {
return f;
});
var featureTypes = (0, _geojsonUtils.getGeojsonFeatureTypes)(features); // condition 1: contain line string
if (!featureTypes.line) {
return false;
} // condition 2:sample line strings contain 4 coordinates
if (!coordHasLength4(features)) {
return false;
} // condition 3:the 4th coordinate of the first feature line strings is valid time
var tsHolder = features[0].geometry.coordinates.map(function (coord) {
return coord[3];
});
return Boolean(containValidTime(tsHolder));
}
/**
* Get unix timestamp from animatable geojson for deck.gl trip layer
* @param {Array<Object>} dataToFeature array of geojson feature objects, can be null
* @returns {{dataToTimeStamp: Array[Number], animationDomain: null | Array<Number>}} {dataToTimeStamp: [], animationDomain: null}
*/
function parseTripGeoJsonTimestamp(dataToFeature) {
// Analyze type based on coordinates of the 1st lineString
// select a sample trip to analyze time format
var empty = {
dataToTimeStamp: [],
animationDomain: null
};
var sampleTrip = dataToFeature.find(function (f) {
return f && f.geometry && f.geometry.coordinates && f.geometry.coordinates.length >= 3;
}); // if no valid geometry
if (!sampleTrip) {
return empty;
}
var analyzedType = containValidTime(sampleTrip.geometry.coordinates.map(function (coord) {
return coord[3];
}));
if (!analyzedType) {
return empty;
}
var format = analyzedType.format;
var getTimeValue = function getTimeValue(coord) {
return coord && (0, _dataUtils.notNullorUndefined)(coord[3]) ? (0, _dataUtils.timeToUnixMilli)(coord[3], format) : null;
};
var dataToTimeStamp = dataToFeature.map(function (f) {
return f && f.geometry && Array.isArray(f.geometry.coordinates) ? f.geometry.coordinates.map(getTimeValue) : null;
});
var animationDomain = getAnimationDomainFromTimestamps(dataToTimeStamp);
return {
dataToTimeStamp: dataToTimeStamp,
animationDomain: animationDomain
};
}
function findMinFromSorted() {
var list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
return list.find(function (d) {
return (0, _dataUtils.notNullorUndefined)(d) && Number.isFinite(d);
}) || null;
}
function findMaxFromSorted() {
var list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var i = list.length - 1;
while (i > 0) {
if ((0, _dataUtils.notNullorUndefined)(list[i]) && Number.isFinite(list[i])) {
return list[i];
}
i--;
}
return null;
}
function getAnimationDomainFromTimestamps() {
var dataToTimeStamp = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
return dataToTimeStamp.reduce(function (accu, tss) {
var tsMin = findMinFromSorted(tss);
var tsMax = findMaxFromSorted(tss);
if (Number.isFinite(tsMin) && Number.isFinite(tsMax)) {
accu[0] = Math.min(accu[0], tsMin);
accu[1] = Math.max(accu[1], tsMax);
}
return accu;
}, [Infinity, -Infinity]);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvdHJpcC1sYXllci90cmlwLXV0aWxzLmpzIl0sIm5hbWVzIjpbImNvb3JkSGFzTGVuZ3RoNCIsInNhbXBsZXMiLCJoYXNMZW5ndGg0IiwiaSIsImxlbmd0aCIsImdlb21ldHJ5IiwiY29vcmRpbmF0ZXMiLCJmaW5kIiwiYyIsImNvbnRhaW5WYWxpZFRpbWUiLCJ0aW1lc3RhbXBzIiwiZm9ybWF0dGVkVGltZVN0YW1wcyIsIm1hcCIsInRzIiwiaWdub3JlZERhdGFUeXBlcyIsIk9iamVjdCIsImtleXMiLCJEQVRBX1RZUEVTIiwiZmlsdGVyIiwidHlwZSIsIlRJTUUiLCJEQVRFVElNRSIsImluY2x1ZGVzIiwiYW5hbHl6ZWRUeXBlIiwiQW5hbHl6ZXIiLCJjb21wdXRlQ29sTWV0YSIsImNhdGVnb3J5IiwiaXNUcmlwR2VvSnNvbkZpZWxkIiwiZGF0YUNvbnRhaW5lciIsImZpZWxkIiwibnVtUm93cyIsIm1heENvdW50Iiwic2FtcGxlUmF3RmVhdHVyZXMiLCJmZWF0dXJlcyIsIm1hcEluZGV4IiwidmFsdWVBY2Nlc3NvciIsInBhcnNlR2VvSnNvblJhd0ZlYXR1cmUiLCJmIiwiZmVhdHVyZVR5cGVzIiwibGluZSIsInRzSG9sZGVyIiwiY29vcmQiLCJCb29sZWFuIiwicGFyc2VUcmlwR2VvSnNvblRpbWVzdGFtcCIsImRhdGFUb0ZlYXR1cmUiLCJlbXB0eSIsImRhdGFUb1RpbWVTdGFtcCIsImFuaW1hdGlvbkRvbWFpbiIsInNhbXBsZVRyaXAiLCJmb3JtYXQiLCJnZXRUaW1lVmFsdWUiLCJBcnJheSIsImlzQXJyYXkiLCJnZXRBbmltYXRpb25Eb21haW5Gcm9tVGltZXN0YW1wcyIsImZpbmRNaW5Gcm9tU29ydGVkIiwibGlzdCIsImQiLCJOdW1iZXIiLCJpc0Zpbml0ZSIsImZpbmRNYXhGcm9tU29ydGVkIiwicmVkdWNlIiwiYWNjdSIsInRzcyIsInRzTWluIiwidHNNYXgiLCJNYXRoIiwibWluIiwibWF4IiwiSW5maW5p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SUFBSSxDQUFDcEQsQ0FBRCxDQUF2QixLQUErQnNELE1BQU0sQ0FBQ0MsUUFBUCxDQUFnQkgsSUFBSSxDQUFDcEQsQ0FBRCxDQUFwQixDQUFuQyxFQUE2RDtBQUMzRCxhQUFPb0QsSUFBSSxDQUFDcEQsQ0FBRCxDQUFYO0FBQ0Q7O0FBQ0RBLElBQUFBLENBQUM7QUFDRjs7QUFDRCxTQUFPLElBQVA7QUFDRDs7QUFFTSxTQUFTa0QsZ0NBQVQsR0FBZ0U7QUFBQSxNQUF0QlAsZUFBc0IsdUVBQUosRUFBSTtBQUNyRSxTQUFPQSxlQUFlLENBQUNjLE1BQWhCLENBQ0wsVUFBQ0MsSUFBRCxFQUFPQyxHQUFQLEVBQWU7QUFDYixRQUFNQyxLQUFLLEdBQUdULGlCQUFpQixDQUFDUSxHQUFELENBQS9CO0FBQ0EsUUFBTUUsS0FBSyxHQUFHTCxpQkFBaUIsQ0FBQ0csR0FBRCxDQUEvQjs7QUFDQSxRQUFJTCxNQUFNLENBQUNDLFFBQVAsQ0FBZ0JLLEtBQWhCLEtBQTBCTixNQUFNLENBQUNDLFFBQVAsQ0FBZ0JNLEtBQWhCLENBQTlCLEVBQXNEO0FBQ3BESCxNQUFBQSxJQUFJLENBQUMsQ0FBRCxDQUFKLEdBQVVJLElBQUksQ0FBQ0MsR0FBTCxDQUFTTCxJQUFJLENBQUMsQ0FBRCxDQUFiLEVBQWtCRSxLQUFsQixDQUFWO0FBQ0FGLE1BQUFBLElBQUksQ0FBQyxDQUFELENBQUosR0FBVUksSUFBSSxDQUFDRSxHQUFMLENBQVNOLElBQUksQ0FBQyxDQUFELENBQWIsRUFBa0JHLEtBQWxCLENBQVY7QUFDRDs7QUFDRCxXQUFPSCxJQUFQO0FBQ0QsR0FUSSxFQVVMLENBQUNPLFFBQUQsRUFBVyxDQUFDQSxRQUFaLENBVkssQ0FBUDtBQVlEIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDIxIFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtBbmFseXplciwgREFUQV9UWVBFU30gZnJvbSAndHlwZS1hbmFseXplcic7XG5cbmltcG9ydCB7dGltZVRvVW5peE1pbGxpLCBub3ROdWxsb3JVbmRlZmluZWR9IGZyb20gJ3V0aWxzL2RhdGEtdXRpbHMnO1xuaW1wb3J0IHtnZXRTYW1wbGVEYXRhfSBmcm9tICd1dGlscy90YWJsZS11dGlscy9kYXRhLWNvbnRhaW5lci11dGlscyc7XG5cbmltcG9ydCB7cGFyc2VHZW9Kc29uUmF3RmVhdHVyZSwgZ2V0R2VvanNvbkZlYXR1cmVUeXBlc30gZnJvbSAnbGF5ZXJzL2dlb2pzb24tbGF5ZXIvZ2VvanNvbi11dGlscyc7XG5cbi8qKlxuICogUGFyc2UgZ2VvanNvbiBmcm9tIHN0cmluZ1xuICogQHBhcmFtIHthcnJheX0gc2FtcGxlcyBmZWF0dXJlIG9iamVjdCB2YWx1ZXNcbiAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIHRoZSBnZW9tZXRyeSBjb29yZGluYXRlcyBoYXMgbGVuZ3RoIG9mIDRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvb3JkSGFzTGVuZ3RoNChzYW1wbGVzKSB7XG4gIGxldCBoYXNMZW5ndGg0ID0gdHJ1ZTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzYW1wbGVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgaGFzTGVuZ3RoNCA9ICFzYW1wbGVzW2ldLmdlb21ldHJ5LmNvb3JkaW5hdGVzLmZpbmQoYyA9PiBjLmxlbmd0aCA8IDQpO1xuICAgIGlmICghaGFzTGVuZ3RoNCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiBoYXNMZW5ndGg0O1xufVxuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgZ2VvanNvbiBsaW5lc3RyaW5nJ3MgNHRoIGNvb3JkaW5hdGUgaXMgMSkgbm90IHRpbWVzdGFtcCAyKSB1bml4IHRpbWUgc3RhbXAgMykgcmVhbCBkYXRlIHRpbWVcbiAqIEBwYXJhbSB7YXJyYXl9IHRpbWVzdGFtcHMgYXJyYXkgdG8gYmUgdGVzdGVkIGlmIGl0cyBlbGVtZW50cyBhcmUgdGltZXN0YW1wXG4gKiBAcmV0dXJucyB7b2JqZWN0IHwgYm9vbGVhbn0gdGhlIHR5cGUgb2YgdGltZXN0YW1wOiB1bml4L2RhdGV0aW1lL2ludmFsaWQobm90IHRpbWVzdGFtcClcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY29udGFpblZhbGlkVGltZSh0aW1lc3RhbXBzKSB7XG4gIGNvbnN0IGZvcm1hdHRlZFRpbWVTdGFtcHMgPSB0aW1lc3RhbXBzLm1hcCh0cyA9PiAoe3RzfSkpO1xuICBjb25zdCBpZ25vcmVkRGF0YVR5cGVzID0gT2JqZWN0LmtleXMoREFUQV9UWVBFUykuZmlsdGVyKFxuICAgIHR5cGUgPT4gIVtEQVRBX1RZUEVTLlRJTUUsIERBVEFfVFlQRVMuREFURVRJTUVdLmluY2x1ZGVzKHR5cGUpXG4gICk7XG5cbiAgLy8gaWdub3JlIGFsbCB0eXBlcyBidXQgVElNRSB0byBpbXByb3ZlIHBlcmZvcm1hbmNlXG4gIGNvbnN0IGFuYWx5emVkVHlwZSA9IEFuYWx5emVyLmNvbXB1dGVDb2xNZXRhKGZvcm1hdHRlZFRpbWVTdGFtcHMsIFtdLCB7aWdub3JlZERhdGFUeXBlc30pWzBdO1xuXG4gIGlmICghYW5hbHl6ZWRUeXBlIHx8IGFuYWx5emVkVHlwZS5jYXRlZ29yeSAhPT0gJ1RJTUUnKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiBhbmFseXplZFR5cGU7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgZ2VvanNvbiBmZWF0dXJlcyBhcmUgdHJpcCBsYXllciBhbmltYXRhYmxlIGJ5IG1lZXRpbmcgMyBjb25kaXRpb25zXG4gKiBAcGFyYW0ge2ltcG9ydCgndXRpbHMvdGFibGUtdXRpbHMvZGF0YS1jb250YWluZXItaW50ZXJmYWNlJykuRGF0YUNvbnRhaW5lckludGVyZmFjZX0gZGF0YUNvbnRhaW5lciBnZW9qc29uIGZlYXR1cmUgb2JqZWN0cyBjb250YWluZXJcbiAqIEBwYXJhbSB7b2JqZWN0fSBmaWVsZCBhcnJheSBvZiBnZW9qc29uIGZlYXR1cmUgb2JqZWN0c1xuICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgaXQgaXMgdHJpcCBsYXllciBhbmltYXRhYmxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1RyaXBHZW9Kc29uRmllbGQoZGF0YUNvbnRhaW5lciwgZmllbGQpIHtcbiAgaWYgKGRhdGFDb250YWluZXIubnVtUm93cygpIDwgMSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IG1heENvdW50ID0gMTAwMDA7XG4gIGNvbnN0IHNhbXBsZVJhd0ZlYXR1cmVzID1cbiAgICBkYXRhQ29udGFpbmVyLm51bVJvd3MoKSA+IG1heENvdW50ID8gZ2V0U2FtcGxlRGF0YShkYXRhQ29udGFpbmVyLCBtYXhDb3VudCkgOiBkYXRhQ29udGFpbmVyO1xuXG4gIGNvbnN0IGZlYXR1cmVzID0gc2FtcGxlUmF3RmVhdHVyZXNcbiAgICAubWFwSW5kZXgoZmllbGQudmFsdWVBY2Nlc3NvcilcbiAgICAubWFwKHBhcnNlR2VvSnNvblJhd0ZlYXR1cmUpXG4gICAgLmZpbHRlcihmID0+IGYpO1xuICBjb25zdCBmZWF0dXJlVHlwZXMgPSBnZXRHZW9qc29uRmVhdHVyZVR5cGVzKGZlYXR1cmVzKTtcblxuICAvLyBjb25kaXRpb24gMTogY29udGFpbiBsaW5lIHN0cmluZ1xuICBpZiAoIWZlYXR1cmVUeXBlcy5saW5lKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy8gY29uZGl0aW9uIDI6c2FtcGxlIGxpbmUgc3RyaW5ncyBjb250YWluIDQgY29vcmRpbmF0ZXNcbiAgaWYgKCFjb29yZEhhc0xlbmd0aDQoZmVhdHVyZXMpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy8gY29uZGl0aW9uIDM6dGhlIDR0aCBjb29yZGluYXRlIG9mIHRoZSBmaXJzdCBmZWF0dXJlIGxpbmUgc3RyaW5ncyBpcyB2YWxpZCB0aW1lXG4gIGNvbnN0IHRzSG9sZGVyID0gZmVhdHVyZXNbMF0uZ2VvbWV0cnkuY29vcmRpbmF0ZXMubWFwKGNvb3JkID0+IGNvb3JkWzNdKTtcblxuICByZXR1cm4gQm9vbGVhbihjb250YWluVmFsaWRUaW1lKHRzSG9sZGVyKSk7XG59XG5cbi8qKlxuICogR2V0IHVuaXggdGltZXN0YW1wIGZyb20gYW5pbWF0YWJsZSBnZW9qc29uIGZvciBkZWNrLmdsIHRyaXAgbGF5ZXJcbiAqIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gZGF0YVRvRmVhdHVyZSBhcnJheSBvZiBnZW9qc29uIGZlYXR1cmUgb2JqZWN0cywgY2FuIGJlIG51bGxcbiAqIEByZXR1cm5zIHt7ZGF0YVRvVGltZVN0YW1wOiBBcnJheVtOdW1iZXJdLCBhbmltYXRpb25Eb21haW46IG51bGwgfCBBcnJheTxOdW1iZXI+fX0ge2RhdGFUb1RpbWVTdGFtcDogW10sIGFuaW1hdGlvbkRvbWFpbjogbnVsbH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVHJpcEdlb0pzb25UaW1lc3RhbXAoZGF0YVRvRmVhdHVyZSkge1xuICAvLyBBbmFseXplIHR5cGUgYmFzZWQgb24gY29vcmRpbmF0ZXMgb2YgdGhlIDFzdCBsaW5lU3RyaW5nXG4gIC8vIHNlbGVjdCBhIHNhbXBsZSB0cmlwIHRvIGFuYWx5emUgdGltZSBmb3JtYXRcbiAgY29uc3QgZW1wdHkgPSB7ZGF0YVRvVGltZVN0YW1wOiBbXSwgYW5pbWF0aW9uRG9tYWluOiBudWxsfTtcbiAgY29uc3Qgc2FtcGxlVHJpcCA9IGRhdGFUb0ZlYXR1cmUuZmluZChcbiAgICBmID0+IGYgJiYgZi5nZW9tZXRyeSAmJiBmLmdlb21ldHJ5LmNvb3JkaW5hdGVzICYmIGYuZ2VvbWV0cnkuY29vcmRpbmF0ZXMubGVuZ3RoID49IDNcbiAgKTtcblxuICAvLyBpZiBubyB2YWxpZCBnZW9tZXRyeVxuICBpZiAoIXNhbXBsZVRyaXApIHtcbiAgICByZXR1cm4gZW1wdHk7XG4gIH1cblxuICBjb25zdCBhbmFseXplZFR5cGUgPSBjb250YWluVmFsaWRUaW1lKHNhbXBsZVRyaXAuZ2VvbWV0cnkuY29vcmRpbmF0ZXMubWFwKGNvb3JkID0+IGNvb3JkWzNdKSk7XG5cbiAgaWYgKCFhbmFseXplZFR5cGUpIHtcbiAgICByZXR1cm4gZW1wdHk7XG4gIH1cblxuICBjb25zdCB7Zm9ybWF0fSA9IGFuYWx5emVkVHlwZTtcbiAgY29uc3QgZ2V0VGltZVZhbHVlID0gY29vcmQgPT5cbiAgICBjb29yZCAmJiBub3ROdWxsb3JVbmRlZmluZWQoY29vcmRbM10pID8gdGltZVRvVW5peE1pbGxpKGNvb3JkWzNdLCBmb3JtYXQpIDogbnVsbDtcblxuICBjb25zdCBkYXRhVG9UaW1lU3RhbXAgPSBkYXRhVG9GZWF0dXJlLm1hcChmID0+XG4gICAgZiAmJiBmLmdlb21ldHJ5ICYmIEFycmF5LmlzQXJyYXkoZi5nZW9tZXRyeS5jb29yZGluYXRlcylcbiAgICAgID8gZi5nZW9tZXRyeS5jb29yZGluYXRlcy5tYXAoZ2V0VGltZVZhbHVlKVxuICAgICAgOiBudWxsXG4gICk7XG5cbiAgY29uc3QgYW5pbWF0aW9uRG9tYWluID0gZ2V0QW5pbWF0aW9uRG9tYWluRnJvbVRpbWVzdGFtcHMoZGF0YVRvVGltZVN0YW1wKTtcblxuICByZXR1cm4ge2RhdGFUb1RpbWVTdGFtcCwgYW5pbWF0aW9uRG9tYWlufTtcbn1cblxuZnVuY3Rpb24gZmluZE1pbkZyb21Tb3J0ZWQobGlzdCA9IFtdKSB7XG4gIHJldHVybiBsaXN0LmZpbmQoZCA9PiBub3ROdWxsb3JVbmRlZmluZWQoZCkgJiYgTnVtYmVyLmlzRmluaXRlKGQpKSB8fCBudWxsO1xufVxuXG5mdW5jdGlvbiBmaW5kTWF4RnJvbVNvcnRlZChsaXN0ID0gW10pIHtcbiAgbGV0IGkgPSBsaXN0Lmxlbmd0aCAtIDE7XG4gIHdoaWxlIChpID4gMCkge1xuICAgIGlmIChub3ROdWxsb3JVbmRlZmluZWQobGlzdFtpXSkgJiYgTnVtYmVyLmlzRmluaXRlKGxpc3RbaV0pKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gICAgaS0tO1xuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QW5pbWF0aW9uRG9tYWluRnJvbVRpbWVzdGFtcHMoZGF0YVRvVGltZVN0YW1wID0gW10pIHtcbiAgcmV0dXJuIGRhdGFUb1RpbWVTdGFtcC5yZWR1Y2UoXG4gICAgKGFjY3UsIHRzcykgPT4ge1xuICAgICAgY29uc3QgdHNNaW4gPSBmaW5kTWluRnJvbVNvcnRlZCh0c3MpO1xuICAgICAgY29uc3QgdHNNYXggPSBmaW5kTWF4RnJvbVNvcnRlZCh0c3MpO1xuICAgICAgaWYgKE51bWJlci5pc0Zpbml0ZSh0c01pbikgJiYgTnVtYmVyLmlzRmluaXRlKHRzTWF4KSkge1xuICAgICAgICBhY2N1WzBdID0gTWF0aC5taW4oYWNjdVswXSwgdHNNaW4pO1xuICAgICAgICBhY2N1WzFdID0gTWF0aC5tYXgoYWNjdVsxXSwgdHNNYXgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3U7XG4gICAgfSxcbiAgICBbSW5maW5pdHksIC1JbmZpbml0eV1cbiAgKTtcbn1cbiJdfQ==