UNPKG

webglimpse

Version:

Webglimpse is a data visualization library for the web.

170 lines 21 kB
/* * Copyright (c) 2014, Metron, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // Alias for more readable access to static constants export let GL = WebGLRenderingContext; export function hasval(value) { // Double-equals is weird: ( undefined == null ) is true return (value != null); } export function isNumber(value) { return typeof (value) === 'number'; } export function isString(value) { return typeof (value) === 'string'; } export function isEmpty(array) { return (array.length === 0); } export function notEmpty(array) { return (array.length > 0); } export function alwaysTrue() { return true; } export function alwaysFalse() { return false; } export function constantFn(value) { return function () { return value; }; } export function log10(x) { return Math.log(x) * (1.0 / Math.LN10); } export function order(x) { return Math.floor(log10(x) + 1e-12); } export function clamp(xMin, xMax, x) { return Math.max(xMin, Math.min(xMax, x)); } export function copyArray(values) { return values.slice(0); } export function ensureCapacityFloat32(buffer, minNewCapacity) { // if minNewCapacity is NaN, null, or undefined, don't try to resize the buffer if (!minNewCapacity || buffer.length >= minNewCapacity) { return buffer; } else { const newCapacity = Math.max(minNewCapacity, 2 * buffer.length); return new Float32Array(newCapacity); } } export function ensureCapacityUint32(buffer, minNewCapacity) { // if minNewCapacity is NaN, null, or undefined, don't try to resize the buffer if (!minNewCapacity || buffer.length >= minNewCapacity) { return buffer; } else { const newCapacity = Math.max(minNewCapacity, 2 * buffer.length); return new Uint32Array(newCapacity); } } export function ensureCapacityUint16(buffer, minNewCapacity) { // if minNewCapacity is NaN, null, or undefined, don't try to resize the buffer if (!minNewCapacity || buffer.length >= minNewCapacity) { return buffer; } else { const newCapacity = Math.max(minNewCapacity, 2 * buffer.length); return new Uint16Array(newCapacity); } } export let getObjectId = (function () { const keyName = 'webglimpse_ObjectId'; let nextValue = 0; return function (obj) { let value = obj[keyName]; if (!hasval(value)) { value = (nextValue++).toString(); obj[keyName] = value; } return value; }; })(); export function concatLines(...lines) { return lines.join('\n'); } /** * Parses a timestamp from the format 'YYYY-MM-DDTHH:mm:ss[.SSS]ZZ' into posix-milliseconds. * * Format examples: * - '2014-01-01T00:00:00Z' * - '2014-01-01T00:00:00.000+00:00' * * Use of a colon in numeric timezones is optional. However, it is strongly encouraged, for * compatibility with Date in major browsers. * * Parsing is strict, and will throw an error if the input string does not match the expected * format. A notable example is that the seconds field must not have more than three decimal * places. * */ import moment from 'moment'; export function parseTime_PMILLIS(time_ISO8601) { // Moment's lenient parsing is way too lenient -- but its strict parsing is a little too // strict, so we have to try several possible formats. // // We could pass in multiple formats to try all at once, but Moment's docs warn that that // can be slow. Plus, we expect some formats to be more common than others, so we can make // the common formats fast at the expense of the less common ones. // let m = moment(time_ISO8601, 'YYYY-MM-DDTHH:mm:ssZZ', true); if (m.isValid()) { return m.valueOf(); } m = moment(time_ISO8601, 'YYYY-MM-DDTHH:mm:ss.SSSZZ', true); if (m.isValid()) { return m.valueOf(); } m = moment(time_ISO8601, 'YYYY-MM-DDTHH:mm:ss.SSZZ', true); if (m.isValid()) { return m.valueOf(); } m = moment(time_ISO8601, 'YYYY-MM-DDTHH:mm:ss.SZZ', true); if (m.isValid()) { return m.valueOf(); } throw new Error('Failed to parse time-string: \'' + time_ISO8601 + '\''); } /** * Formats a timestamp from posix-millis into the format 'YYYY-MM-DDThh:mm:ss.SSSZZ' (for * example '2014-01-01T00:00:00.000Z'). * * The input value is effectively truncated (not rounded!) to milliseconds. So for example, * formatTime_ISO8601(12345.999) will return '1970-01-01T00:00:12.345Z' -- exactly the same * as for an input of 12345. * */ export function formatTime_ISO8601(time_PMILLIS) { return moment(time_PMILLIS).toISOString(); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy93ZWJnbGltcHNlL3V0aWwvdXRpbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRCRztBQUdILHFEQUFxRDtBQUNyRCxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcscUJBQXFCLENBQUM7QUFHdEMsTUFBTSxVQUFVLE1BQU0sQ0FBQyxLQUFVO0lBQzdCLHdEQUF3RDtJQUN4RCxPQUFPLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxDQUFDO0FBQzNCLENBQUM7QUFHRCxNQUFNLFVBQVUsUUFBUSxDQUFDLEtBQVU7SUFDL0IsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssUUFBUSxDQUFDO0FBQ3ZDLENBQUM7QUFHRCxNQUFNLFVBQVUsUUFBUSxDQUFDLEtBQVU7SUFDL0IsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssUUFBUSxDQUFDO0FBQ3ZDLENBQUM7QUFHRCxNQUFNLFVBQVUsT0FBTyxDQUFDLEtBQVk7SUFDaEMsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDaEMsQ0FBQztBQUdELE1BQU0sVUFBVSxRQUFRLENBQUMsS0FBWTtJQUNqQyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBR0QsTUFBTSxVQUFVLFVBQVU7SUFDdEIsT0FBTyxJQUFJLENBQUM7QUFDaEIsQ0FBQztBQUdELE1BQU0sVUFBVSxXQUFXO0lBQ3ZCLE9BQU8sS0FBSyxDQUFDO0FBQ2pCLENBQUM7QUFHRCxNQUFNLFVBQVUsVUFBVSxDQUFJLEtBQVE7SUFDbEMsT0FBTztRQUNILE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUMsQ0FBQztBQUNOLENBQUM7QUFHRCxNQUFNLFVBQVUsS0FBSyxDQUFDLENBQVM7SUFDM0IsT0FB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WyIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQsIE1ldHJvbiwgSW5jLlxyXG4gKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKlxyXG4gKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxyXG4gKiBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XHJcbiAqXHJcbiAqIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xyXG4gKiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cclxuICpcclxuICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxyXG4gKiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uXHJcbiAqICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxyXG4gKlxyXG4gKiAzLiBOZWl0aGVyIHRoZSBuYW1lIG9mIHRoZSBjb3B5cmlnaHQgaG9sZGVyIG5vciB0aGUgbmFtZXMgb2YgaXRzIGNvbnRyaWJ1dG9yc1xyXG4gKiAgICBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dFxyXG4gKiAgICBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uXHJcbiAqXHJcbiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxyXG4gKiBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxyXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXHJcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXHJcbiAqIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xyXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XHJcbiAqIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxyXG4gKiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxyXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xyXG4gKiBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cclxuICovXHJcblxyXG5cclxuLy8gQWxpYXMgZm9yIG1vcmUgcmVhZGFibGUgYWNjZXNzIHRvIHN0YXRpYyBjb25zdGFudHNcclxuZXhwb3J0IGxldCBHTCA9IFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gaGFzdmFsKHZhbHVlOiBhbnkpOiBib29sZWFuIHtcclxuICAgIC8vIERvdWJsZS1lcXVhbHMgaXMgd2VpcmQ6ICggdW5kZWZpbmVkID09IG51bGwgKSBpcyB0cnVlXHJcbiAgICByZXR1cm4gKHZhbHVlICE9IG51bGwpO1xyXG59XHJcblxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGlzTnVtYmVyKHZhbHVlOiBhbnkpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0eXBlb2YgKHZhbHVlKSA9PT0gJ251bWJlcic7XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gaXNTdHJpbmcodmFsdWU6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHR5cGVvZiAodmFsdWUpID09PSAnc3RyaW5nJztcclxufVxyXG5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBpc0VtcHR5KGFycmF5OiBhbnlbXSk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIChhcnJheS5sZW5ndGggPT09IDApO1xyXG59XHJcblxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIG5vdEVtcHR5KGFycmF5OiBhbnlbXSk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIChhcnJheS5sZW5ndGggPiAwKTtcclxufVxyXG5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBhbHdheXNUcnVlKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRydWU7XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gYWx3YXlzRmFsc2UoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gY29uc3RhbnRGbjxWPih2YWx1ZTogVik6ICgpID0+IFYge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpOiBWIHtcclxuICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9O1xyXG59XHJcblxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGxvZzEwKHg6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICByZXR1cm4gTWF0aC5sb2coeCkgKiAoMS4wIC8gTWF0aC5MTjEwKTtcclxufVxyXG5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBvcmRlcih4OiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIE1hdGguZmxvb3IobG9nMTAoeCkgKyAxZS0xMik7XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gY2xhbXAoeE1pbjogbnVtYmVyLCB4TWF4OiBudW1iZXIsIHg6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICByZXR1cm4gTWF0aC5tYXgoeE1pbiwgTWF0aC5taW4oeE1heCwgeCkpO1xyXG59XHJcblxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGNvcHlBcnJheTxUPih2YWx1ZXM6IFRbXSk6IFRbXSB7XHJcbiAgICByZXR1cm4gdmFsdWVzLnNsaWNlKDApO1xyXG59XHJcblxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZUNhcGFjaXR5RmxvYXQzMihidWZmZXI6IEZsb2F0MzJBcnJheSwgbWluTmV3Q2FwYWNpdHk6IG51bWJlcik6IEZsb2F0MzJBcnJheSB7XHJcbiAgICAvLyBpZiBtaW5OZXdDYXBhY2l0eSBpcyBOYU4sIG51bGwsIG9yIHVuZGVmaW5lZCwgZG9uJ3QgdHJ5IHRvIHJlc2l6ZSB0aGUgYnVmZmVyXHJcbiAgICBpZiAoIW1pbk5ld0NhcGFjaXR5IHx8IGJ1ZmZlci5sZW5ndGggPj0gbWluTmV3Q2FwYWNpdHkpIHtcclxuICAgICAgICByZXR1cm4gYnVmZmVyO1xyXG4gICAgfVxyXG4gICAgZWxzZSB7XHJcbiAgICAgICAgY29uc3QgbmV3Q2FwYWNpdHkgPSBNYXRoLm1heChtaW5OZXdDYXBhY2l0eSwgMiAqIGJ1ZmZlci5sZW5ndGgpO1xyXG4gICAgICAgIHJldHVybiBuZXcgRmxvYXQzMkFycmF5KG5ld0NhcGFjaXR5KTtcclxuICAgIH1cclxufVxyXG5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVDYXBhY2l0eVVpbnQzMihidWZmZXI6IFVpbnQzMkFycmF5LCBtaW5OZXdDYXBhY2l0eTogbnVtYmVyKTogVWludDMyQXJyYXkge1xyXG4gICAgLy8gaWYgbWluTmV3Q2FwYWNpdHkgaXMgTmFOLCBudWxsLCBvciB1bmRlZmluZWQsIGRvbid0IHRyeSB0byByZXNpemUgdGhlIGJ1ZmZlclxyXG4gICAgaWYgKCFtaW5OZXdDYXBhY2l0eSB8fCBidWZmZXIubGVuZ3RoID49IG1pbk5ld0NhcGFjaXR5KSB7XHJcbiAgICAgICAgcmV0dXJuIGJ1ZmZlcjtcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICAgIGNvbnN0IG5ld0NhcGFjaXR5ID0gTWF0aC5tYXgobWluTmV3Q2FwYWNpdHksIDIgKiBidWZmZXIubGVuZ3RoKTtcclxuICAgICAgICByZXR1cm4gbmV3IFVpbnQzMkFycmF5KG5ld0NhcGFjaXR5KTtcclxuICAgIH1cclxufVxyXG5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVDYXBhY2l0eVVpbnQxNihidWZmZXI6IFVpbnQxNkFycmF5LCBtaW5OZXdDYXBhY2l0eTogbnVtYmVyKTogVWludDE2QXJyYXkge1xyXG4gICAgLy8gaWYgbWluTmV3Q2FwYWNpdHkgaXMgTmFOLCBudWxsLCBvciB1bmRlZmluZWQsIGRvbid0IHRyeSB0byByZXNpemUgdGhlIGJ1ZmZlclxyXG4gICAgaWYgKCFtaW5OZXdDYXBhY2l0eSB8fCBidWZmZXIubGVuZ3RoID49IG1pbk5ld0NhcGFjaXR5KSB7XHJcbiAgICAgICAgcmV0dXJuIGJ1ZmZlcjtcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICAgIGNvbnN0IG5ld0NhcGFjaXR5ID0gTWF0aC5tYXgobWluTmV3Q2FwYWNpdHksIDIgKiBidWZmZXIubGVuZ3RoKTtcclxuICAgICAgICByZXR1cm4gbmV3IFVpbnQxNkFycmF5KG5ld0NhcGFjaXR5KTtcclxuICAgIH1cclxufVxyXG5cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgU3RyaW5nTWFwPFY+IHtcclxuICAgIFtrZXk6IHN0cmluZ106IFY7XHJcbn1cclxuXHJcbmV4cG9ydCB0eXBlIElkRnVuY3Rpb248Vj4gPSAodmFsdWU6IFYpID0+IHN0cmluZztcclxuXHJcblxyXG5leHBvcnQgbGV0IGdldE9iamVjdElkID0gKGZ1bmN0aW9uICgpIHtcclxuICAgIGNvbnN0IGtleU5hbWUgPSAnd2ViZ2xpbXBzZV9PYmplY3RJZCc7XHJcbiAgICBsZXQgbmV4dFZhbHVlID0gMDtcclxuICAgIHJldHVybiBmdW5jdGlvbiAob2JqOiBhbnkpOiBzdHJpbmcge1xyXG4gICAgICAgIGxldCB2YWx1ZSA9IG9ialtrZXlOYW1lXTtcclxuICAgICAgICBpZiAoIWhhc3ZhbCh2YWx1ZSkpIHtcclxuICAgICAgICAgICAgdmFsdWUgPSAobmV4dFZhbHVlKyspLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgIG9ialtrZXlOYW1lXSA9IHZhbHVlO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9O1xyXG59KSgpO1xyXG5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjb25jYXRMaW5lcyguLi5saW5lczogc3RyaW5nW10pIHtcclxuICAgIHJldHVybiBsaW5lcy5qb2luKCdcXG4nKTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBQYXJzZXMgYSB0aW1lc3RhbXAgZnJvbSB0aGUgZm9ybWF0ICdZWVlZLU1NLUREVEhIOm1tOnNzWy5TU1NdWlonIGludG8gcG9zaXgtbWlsbGlzZWNvbmRzLlxyXG4gKlxyXG4gKiBGb3JtYXQgZXhhbXBsZXM6XHJcbiAqICAgLSAnMjAxNC0wMS0wMVQwMDowMDowMFonXHJcbiAqICAgLSAnMjAxNC0wMS0wMVQwMDowMDowMC4wMDArMDA6MDAnXHJcbiAqXHJcbiAqIFVzZSBvZiBhIGNvbG9uIGluIG51bWVyaWMgdGltZXpvbmVzIGlzIG9wdGlvbmFsLiBIb3dldmVyLCBpdCBpcyBzdHJvbmdseSBlbmNvdXJhZ2VkLCBmb3JcclxuICogY29tcGF0aWJpbGl0eSB3aXRoIERhdGUgaW4gbWFqb3IgYnJvd3NlcnMuXHJcbiAqXHJcbiAqIFBhcnNpbmcgaXMgc3RyaWN0LCBhbmQgd2lsbCB0aHJvdyBhbiBlcnJvciBpZiB0aGUgaW5wdXQgc3RyaW5nIGRvZXMgbm90IG1hdGNoIHRoZSBleHBlY3RlZFxyXG4gKiBmb3JtYXQuIEEgbm90YWJsZSBleGFtcGxlIGlzIHRoYXQgdGhlIHNlY29uZHMgZmllbGQgbXVzdCBub3QgaGF2ZSBtb3JlIHRoYW4gdGhyZWUgZGVjaW1hbFxyXG4gKiBwbGFjZXMuXHJcbiAqXHJcbiAqL1xyXG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VUaW1lX1BNSUxMSVModGltZV9JU084NjAxOiBzdHJpbmcpOiBudW1iZXIge1xyXG5cclxuICAgIC8vIE1vbWVudCdzIGxlbmllbnQgcGFyc2luZyBpcyB3YXkgdG9vIGxlbmllbnQgLS0gYnV0IGl0cyBzdHJpY3QgcGFyc2luZyBpcyBhIGxpdHRsZSB0b29cclxuICAgIC8vIHN0cmljdCwgc28gd2UgaGF2ZSB0byB0cnkgc2V2ZXJhbCBwb3NzaWJsZSBmb3JtYXRzLlxyXG4gICAgLy9cclxuICAgIC8vIFdlIGNvdWxkIHBhc3MgaW4gbXVsdGlwbGUgZm9ybWF0cyB0byB0cnkgYWxsIGF0IG9uY2UsIGJ1dCBNb21lbnQncyBkb2NzIHdhcm4gdGhhdCB0aGF0XHJcbiAgICAvLyBjYW4gYmUgc2xvdy4gUGx1cywgd2UgZXhwZWN0IHNvbWUgZm9ybWF0cyB0byBiZSBtb3JlIGNvbW1vbiB0aGFuIG90aGVycywgc28gd2UgY2FuIG1ha2VcclxuICAgIC8vIHRoZSBjb21tb24gZm9ybWF0cyBmYXN0IGF0IHRoZSBleHBlbnNlIG9mIHRoZSBsZXNzIGNvbW1vbiBvbmVzLlxyXG4gICAgLy9cclxuXHJcbiAgICBsZXQgbSA9IG1vbWVudCh0aW1lX0lTTzg2MDEsICdZWVlZLU1NLUREVEhIOm1tOnNzWlonLCB0cnVlKTtcclxuICAgIGlmIChtLmlzVmFsaWQoKSkge1xyXG4gICAgICAgIHJldHVybiBtLnZhbHVlT2YoKTtcclxuICAgIH1cclxuXHJcbiAgICBtID0gbW9tZW50KHRpbWVfSVNPODYwMSwgJ1lZWVktTU0tRERUSEg6bW06c3MuU1NTWlonLCB0cnVlKTtcclxuICAgIGlmIChtLmlzVmFsaWQoKSkge1xyXG4gICAgICAgIHJldHVybiBtLnZhbHVlT2YoKTtcclxuICAgIH1cclxuXHJcbiAgICBtID0gbW9tZW50KHRpbWVfSVNPODYwMSwgJ1lZWVktTU0tRERUSEg6bW06c3MuU1NaWicsIHRydWUpO1xyXG4gICAgaWYgKG0uaXNWYWxpZCgpKSB7XHJcbiAgICAgICAgcmV0dXJuIG0udmFsdWVPZigpO1xyXG4gICAgfVxyXG5cclxuICAgIG0gPSBtb21lbnQodGltZV9JU084NjAxLCAnWVlZWS1NTS1ERFRISDptbTpzcy5TWlonLCB0cnVlKTtcclxuICAgIGlmIChtLmlzVmFsaWQoKSkge1xyXG4gICAgICAgIHJldHVybiBtLnZhbHVlT2YoKTtcclxuICAgIH1cclxuXHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBwYXJzZSB0aW1lLXN0cmluZzogXFwnJyArIHRpbWVfSVNPODYwMSArICdcXCcnKTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBGb3JtYXRzIGEgdGltZXN0YW1wIGZyb20gcG9zaXgtbWlsbGlzIGludG8gdGhlIGZvcm1hdCAnWVlZWS1NTS1ERFRoaDptbTpzcy5TU1NaWicgKGZvclxyXG4gKiBleGFtcGxlICcyMDE0LTAxLTAxVDAwOjAwOjAwLjAwMFonKS5cclxuICpcclxuICogVGhlIGlucHV0IHZhbHVlIGlzIGVmZmVjdGl2ZWx5IHRydW5jYXRlZCAobm90IHJvdW5kZWQhKSB0byBtaWxsaXNlY29uZHMuIFNvIGZvciBleGFtcGxlLFxyXG4gKiBmb3JtYXRUaW1lX0lTTzg2MDEoMTIzNDUuOTk5KSB3aWxsIHJldHVybiAnMTk3MC0wMS0wMVQwMDowMDoxMi4zNDVaJyAtLSBleGFjdGx5IHRoZSBzYW1lXHJcbiAqIGFzIGZvciBhbiBpbnB1dCBvZiAxMjM0NS5cclxuICpcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRUaW1lX0lTTzg2MDEodGltZV9QTUlMTElTOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIG1vbWVudCh0aW1lX1BNSUxMSVMpLnRvSVNPU3RyaW5nKCk7XHJcbn1cclxuXHJcblxyXG5cclxuIl19