kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
198 lines (160 loc) • 20.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.containValidTime = containValidTime;
exports.coordHasLength4 = coordHasLength4;
exports.getAnimationDomainFromTimestamps = getAnimationDomainFromTimestamps;
exports.isTripGeoJsonField = isTripGeoJsonField;
exports.parseTripGeoJsonTimestamp = parseTripGeoJsonTimestamp;
var _typeAnalyzer = require("type-analyzer");
var _dataUtils = require("../../utils/data-utils");
var _geojsonUtils = require("../geojson-layer/geojson-utils");
// Copyright (c) 2023 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} geojson 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} data array to be tested if its elements are timestamp
* @returns {string} 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 {array} features array of geojson feature objects
* @returns {boolean} whether it is trip layer animatable
*/
function isTripGeoJsonField() {
var allData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var field = arguments.length > 1 ? arguments[1] : undefined;
if (!allData.length) {
return false;
}
var getValue = function getValue(d) {
return d[field.tableFieldIndex - 1];
};
var maxCount = 10000;
var sampleRawFeatures = allData.length > maxCount ? (0, _dataUtils.getSampleData)(allData, maxCount, getValue) : allData.map(getValue);
var features = sampleRawFeatures.map(_geojsonUtils.parseGeoJsonRawFeature);
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 {Array<Number>} unix timestamp in milliseconds
*/
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(_dataUtils.notNullorUndefined) || 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])) {
return list[i];
}
i--;
}
return null;
}
function getAnimationDomainFromTimestamps() {
var dataToTimeStamp = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
return dataToTimeStamp.reduce(function (accu, tss) {
accu[0] = Math.min(accu[0], findMinFromSorted(tss));
accu[1] = Math.max(accu[1], findMaxFromSorted(tss));
return accu;
}, [Infinity, -Infinity]);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvdHJpcC1sYXllci90cmlwLXV0aWxzLmpzIl0sIm5hbWVzIjpbImNvb3JkSGFzTGVuZ3RoNCIsInNhbXBsZXMiLCJoYXNMZW5ndGg0IiwiaSIsImxlbmd0aCIsImdlb21ldHJ5IiwiY29vcmRpbmF0ZXMiLCJmaW5kIiwiYyIsImNvbnRhaW5WYWxpZFRpbWUiLCJ0aW1lc3RhbXBzIiwiZm9ybWF0dGVkVGltZVN0YW1wcyIsIm1hcCIsInRzIiwiaWdub3JlZERhdGFUeXBlcyIsIk9iamVjdCIsImtleXMiLCJEQVRBX1RZUEVTIiwiZmlsdGVyIiwidHlwZSIsIlRJTUUiLCJEQVRFVElNRSIsImluY2x1ZGVzIiwiYW5hbHl6ZWRUeXBlIiwiQW5hbHl6ZXIiLCJjb21wdXRlQ29sTWV0YSIsImNhdGVnb3J5IiwiaXNUcmlwR2VvSnNvbkZpZWxkIiwiYWxsRGF0YSIsImZpZWxkIiwiZ2V0VmFsdWUiLCJkIiwidGFibGVGaWVsZEluZGV4IiwibWF4Q291bnQiLCJzYW1wbGVSYXdGZWF0dXJlcyIsImZlYXR1cmVzIiwicGFyc2VHZW9Kc29uUmF3RmVhdHVyZSIsImZlYXR1cmVUeXBlcyIsImxpbmUiLCJ0c0hvbGRlciIsImNvb3JkIiwiQm9vbGVhbiIsInBhcnNlVHJpcEdlb0pzb25UaW1lc3RhbXAiLCJkYXRhVG9GZWF0dXJlIiwiZW1wdHkiLCJkYXRhVG9UaW1lU3RhbXAiLCJhbmltYXRpb25Eb21haW4iLCJzYW1wbGVUcmlwIiwiZiIsImZvcm1hdCIsImdldFRpbWVWYWx1ZSIsIkFycmF5IiwiaXNBcnJheSIsImdldEFuaW1hdGlvbkRvbWFpbkZyb21UaW1lc3RhbXBzIiwiZmluZE1pbkZyb21Tb3J0ZWQiLCJsaXN0Iiwibm90TnVsbG9yVW5kZWZpbmVkIiwiZmluZE1heEZyb21Tb3J0ZWQiLCJyZWR1Y2UiLCJhY2N1IiwidHNzIiwiTWF0aCIsIm1pbiIsIm1heCIsIkluZmluaXR5Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztB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QUFFTSxTQUFTa0QsZ0NBQVQsR0FBZ0U7QUFBQSxNQUF0QlIsZUFBc0IsdUVBQUosRUFBSTtBQUNyRSxTQUFPQSxlQUFlLENBQUNhLE1BQWhCLENBQ0wsVUFBQ0MsSUFBRCxFQUFPQyxHQUFQLEVBQWU7QUFDYkQsSUFBQUEsSUFBSSxDQUFDLENBQUQsQ0FBSixHQUFVRSxJQUFJLENBQUNDLEdBQUwsQ0FBU0gsSUFBSSxDQUFDLENBQUQsQ0FBYixFQUFrQkwsaUJBQWlCLENBQUNNLEdBQUQsQ0FBbkMsQ0FBVjtBQUNBRCxJQUFBQSxJQUFJLENBQUMsQ0FBRCxDQUFKLEdBQVVFLElBQUksQ0FBQ0UsR0FBTCxDQUFTSixJQUFJLENBQUMsQ0FBRCxDQUFiLEVBQWtCRixpQkFBaUIsQ0FBQ0csR0FBRCxDQUFuQyxDQUFWO0FBQ0EsV0FBT0QsSUFBUDtBQUNELEdBTEksRUFNTCxDQUFDSyxRQUFELEVBQVcsQ0FBQ0EsUUFBWixDQU5LLENBQVA7QUFRRCIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAyMyBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7QW5hbHl6ZXIsIERBVEFfVFlQRVN9IGZyb20gJ3R5cGUtYW5hbHl6ZXInO1xuXG5pbXBvcnQge1xuICBnZXRTYW1wbGVEYXRhLFxuICB0aW1lVG9Vbml4TWlsbGksXG4gIG5vdE51bGxvclVuZGVmaW5lZFxufSBmcm9tICd1dGlscy9kYXRhLXV0aWxzJztcblxuaW1wb3J0IHtcbiAgcGFyc2VHZW9Kc29uUmF3RmVhdHVyZSxcbiAgZ2V0R2VvanNvbkZlYXR1cmVUeXBlc1xufSBmcm9tICdsYXllcnMvZ2VvanNvbi1sYXllci9nZW9qc29uLXV0aWxzJztcblxuLyoqXG4gKiBQYXJzZSBnZW9qc29uIGZyb20gc3RyaW5nXG4gKiBAcGFyYW0ge2FycmF5fSBnZW9qc29uIGZlYXR1cmUgb2JqZWN0IHZhbHVlc1xuICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgdGhlIGdlb21ldHJ5IGNvb3JkaW5hdGVzIGhhcyBsZW5ndGggb2YgNFxuICovXG5leHBvcnQgZnVuY3Rpb24gY29vcmRIYXNMZW5ndGg0KHNhbXBsZXMpIHtcbiAgbGV0IGhhc0xlbmd0aDQgPSB0cnVlO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHNhbXBsZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICBoYXNMZW5ndGg0ID0gIXNhbXBsZXNbaV0uZ2VvbWV0cnkuY29vcmRpbmF0ZXMuZmluZChjID0+IGMubGVuZ3RoIDwgNCk7XG4gICAgaWYgKCFoYXNMZW5ndGg0KSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGhhc0xlbmd0aDQ7XG59XG5cbi8qKlxuICogQ2hlY2sgd2hldGhlciBnZW9qc29uIGxpbmVzdHJpbmcncyA0dGggY29vcmRpbmF0ZSBpcyAxKSBub3QgdGltZXN0YW1wIDIpIHVuaXggdGltZSBzdGFtcCAzKSByZWFsIGRhdGUgdGltZVxuICogQHBhcmFtIHthcnJheX0gZGF0YSBhcnJheSB0byBiZSB0ZXN0ZWQgaWYgaXRzIGVsZW1lbnRzIGFyZSB0aW1lc3RhbXBcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSB0eXBlIG9mIHRpbWVzdGFtcDogdW5peC9kYXRldGltZS9pbnZhbGlkKG5vdCB0aW1lc3RhbXApXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5WYWxpZFRpbWUodGltZXN0YW1wcykge1xuICBjb25zdCBmb3JtYXR0ZWRUaW1lU3RhbXBzID0gdGltZXN0YW1wcy5tYXAodHMgPT4gKHt0c30pKTtcbiAgY29uc3QgaWdub3JlZERhdGFUeXBlcyA9IE9iamVjdC5rZXlzKERBVEFfVFlQRVMpLmZpbHRlcih0eXBlID0+XG4gICAgIVtEQVRBX1RZUEVTLlRJTUUsIERBVEFfVFlQRVMuREFURVRJTUVdLmluY2x1ZGVzKHR5cGUpKTtcblxuICAvLyBpZ25vcmUgYWxsIHR5cGVzIGJ1dCBUSU1FIHRvIGltcHJvdmUgcGVyZm9ybWFuY2VcbiAgY29uc3QgYW5hbHl6ZWRUeXBlID0gQW5hbHl6ZXIuY29tcHV0ZUNvbE1ldGEoZm9ybWF0dGVkVGltZVN0YW1wcywgW10sIHtpZ25vcmVkRGF0YVR5cGVzfSlbMF07XG5cbiAgaWYgKCFhbmFseXplZFR5cGUgfHwgYW5hbHl6ZWRUeXBlLmNhdGVnb3J5ICE9PSAnVElNRScpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIGFuYWx5emVkVHlwZTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBnZW9qc29uIGZlYXR1cmVzIGFyZSB0cmlwIGxheWVyIGFuaW1hdGFibGUgYnkgbWVldGluZyAzIGNvbmRpdGlvbnNcbiAqIEBwYXJhbSB7YXJyYXl9IGZlYXR1cmVzIGFycmF5IG9mIGdlb2pzb24gZmVhdHVyZSBvYmplY3RzXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gd2hldGhlciBpdCBpcyB0cmlwIGxheWVyIGFuaW1hdGFibGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHJpcEdlb0pzb25GaWVsZChhbGxEYXRhID0gW10sIGZpZWxkKSB7XG4gIGlmICghYWxsRGF0YS5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgY29uc3QgZ2V0VmFsdWUgPSBkID0+IGRbZmllbGQudGFibGVGaWVsZEluZGV4IC0gMV07XG4gIGNvbnN0IG1heENvdW50ID0gMTAwMDA7XG4gIGNvbnN0IHNhbXBsZVJhd0ZlYXR1cmVzID1cbiAgICBhbGxEYXRhLmxlbmd0aCA+IG1heENvdW50ID8gZ2V0U2FtcGxlRGF0YShhbGxEYXRhLCBtYXhDb3VudCwgZ2V0VmFsdWUpIDogYWxsRGF0YS5tYXAoZ2V0VmFsdWUpO1xuXG4gIGNvbnN0IGZlYXR1cmVzID0gc2FtcGxlUmF3RmVhdHVyZXMubWFwKHBhcnNlR2VvSnNvblJhd0ZlYXR1cmUpO1xuXG4gIGNvbnN0IGZlYXR1cmVUeXBlcyA9IGdldEdlb2pzb25GZWF0dXJlVHlwZXMoZmVhdHVyZXMpO1xuXG4gIC8vIGNvbmRpdGlvbiAxOiBjb250YWluIGxpbmUgc3RyaW5nXG4gIGlmICghZmVhdHVyZVR5cGVzLmxpbmUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBjb25kaXRpb24gMjpzYW1wbGUgbGluZSBzdHJpbmdzIGNvbnRhaW4gNCBjb29yZGluYXRlc1xuICBpZiAoIWNvb3JkSGFzTGVuZ3RoNChmZWF0dXJlcykpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBjb25kaXRpb24gMzp0aGUgNHRoIGNvb3JkaW5hdGUgb2YgdGhlIGZpcnN0IGZlYXR1cmUgbGluZSBzdHJpbmdzIGlzIHZhbGlkIHRpbWVcbiAgY29uc3QgdHNIb2xkZXIgPSBmZWF0dXJlc1swXS5nZW9tZXRyeS5jb29yZGluYXRlcy5tYXAoXG4gICAgY29vcmQgPT4gY29vcmRbM11cbiAgKTtcblxuICByZXR1cm4gQm9vbGVhbihjb250YWluVmFsaWRUaW1lKHRzSG9sZGVyKSk7XG59XG5cbi8qKlxuICogR2V0IHVuaXggdGltZXN0YW1wIGZyb20gYW5pbWF0YWJsZSBnZW9qc29uIGZvciBkZWNrLmdsIHRyaXAgbGF5ZXJcbiAqIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gZGF0YVRvRmVhdHVyZSBhcnJheSBvZiBnZW9qc29uIGZlYXR1cmUgb2JqZWN0cywgY2FuIGJlIG51bGxcbiAqIEByZXR1cm5zIHtBcnJheTxOdW1iZXI+fSB1bml4IHRpbWVzdGFtcCBpbiBtaWxsaXNlY29uZHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVHJpcEdlb0pzb25UaW1lc3RhbXAoZGF0YVRvRmVhdHVyZSkge1xuICAvLyBBbmFseXplIHR5cGUgYmFzZWQgb24gY29vcmRpbmF0ZXMgb2YgdGhlIDFzdCBsaW5lU3RyaW5nXG4gIC8vIHNlbGVjdCBhIHNhbXBsZSB0cmlwIHRvIGFuYWx5emUgdGltZSBmb3JtYXRcbiAgY29uc3QgZW1wdHkgPSB7ZGF0YVRvVGltZVN0YW1wOiBbXSwgYW5pbWF0aW9uRG9tYWluOiBudWxsfTtcbiAgY29uc3Qgc2FtcGxlVHJpcCA9IGRhdGFUb0ZlYXR1cmUuZmluZChcbiAgICBmID0+XG4gICAgICBmICYmXG4gICAgICBmLmdlb21ldHJ5ICYmXG4gICAgICBmLmdlb21ldHJ5LmNvb3JkaW5hdGVzICYmXG4gICAgICBmLmdlb21ldHJ5LmNvb3JkaW5hdGVzLmxlbmd0aCA+PSAzXG4gICk7XG5cbiAgLy8gaWYgbm8gdmFsaWQgZ2VvbWV0cnlcbiAgaWYgKCFzYW1wbGVUcmlwKSB7XG4gICAgcmV0dXJuIGVtcHR5O1xuICB9XG5cbiAgY29uc3QgYW5hbHl6ZWRUeXBlID0gY29udGFpblZhbGlkVGltZShcbiAgICBzYW1wbGVUcmlwLmdlb21ldHJ5LmNvb3JkaW5hdGVzLm1hcChjb29yZCA9PiBjb29yZFszXSlcbiAgKTtcblxuICBpZiAoIWFuYWx5emVkVHlwZSkge1xuICAgIHJldHVybiBlbXB0eTtcbiAgfVxuXG4gIGNvbnN0IHtmb3JtYXR9ID0gYW5hbHl6ZWRUeXBlO1xuICBjb25zdCBnZXRUaW1lVmFsdWUgPSBjb29yZCA9PlxuICAgIGNvb3JkICYmIG5vdE51bGxvclVuZGVmaW5lZChjb29yZFszXSlcbiAgICAgID8gdGltZVRvVW5peE1pbGxpKGNvb3JkWzNdLCBmb3JtYXQpXG4gICAgICA6IG51bGw7XG5cbiAgY29uc3QgZGF0YVRvVGltZVN0YW1wID0gZGF0YVRvRmVhdHVyZS5tYXAoZiA9PlxuICAgIGYgJiYgZi5nZW9tZXRyeSAmJiBBcnJheS5pc0FycmF5KGYuZ2VvbWV0cnkuY29vcmRpbmF0ZXMpXG4gICAgICA/IGYuZ2VvbWV0cnkuY29vcmRpbmF0ZXMubWFwKGdldFRpbWVWYWx1ZSlcbiAgICAgIDogbnVsbFxuICApO1xuXG4gIGNvbnN0IGFuaW1hdGlvbkRvbWFpbiA9IGdldEFuaW1hdGlvbkRvbWFpbkZyb21UaW1lc3RhbXBzKGRhdGFUb1RpbWVTdGFtcCk7XG5cbiAgcmV0dXJuIHtkYXRhVG9UaW1lU3RhbXAsIGFuaW1hdGlvbkRvbWFpbn07XG59XG5cbmZ1bmN0aW9uIGZpbmRNaW5Gcm9tU29ydGVkKGxpc3QgPSBbXSkge1xuICByZXR1cm4gbGlzdC5maW5kKG5vdE51bGxvclVuZGVmaW5lZCkgfHwgbnVsbDtcbn1cblxuZnVuY3Rpb24gZmluZE1heEZyb21Tb3J0ZWQobGlzdCA9IFtdKSB7XG4gIGxldCBpID0gbGlzdC5sZW5ndGggLSAxO1xuICB3aGlsZSAoaSA+IDApIHtcbiAgICBpZiAobm90TnVsbG9yVW5kZWZpbmVkKGxpc3RbaV0pKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXVxuICAgIH1cbiAgICBpLS07XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRBbmltYXRpb25Eb21haW5Gcm9tVGltZXN0YW1wcyhkYXRhVG9UaW1lU3RhbXAgPSBbXSkge1xuICByZXR1cm4gZGF0YVRvVGltZVN0YW1wLnJlZHVjZShcbiAgICAoYWNjdSwgdHNzKSA9PiB7XG4gICAgICBhY2N1WzBdID0gTWF0aC5taW4oYWNjdVswXSwgZmluZE1pbkZyb21Tb3J0ZWQodHNzKSk7XG4gICAgICBhY2N1WzFdID0gTWF0aC5tYXgoYWNjdVsxXSwgZmluZE1heEZyb21Tb3J0ZWQodHNzKSk7XG4gICAgICByZXR1cm4gYWNjdTtcbiAgICB9LFxuICAgIFtJbmZpbml0eSwgLUluZmluaXR5XVxuICApO1xufVxuIl19