UNPKG

unitspan

Version:

Create differential spans for units of measurement, including time measurements, digital (binary) measurements, and more.

727 lines (724 loc) 81.6 kB
// src/unitspan.js var UnitSpan = class { /** * An object with values of numbers or functions. At least one property should map to the value of `1` and that property should * be the base unit of measurement in this class (i.o.w., `__baseUnitValue` should store this unit of measurement.) * @type {T} */ #converter; /** * An object with the same keys as the `converter` object, but with values being objects holding * configurations for how the formatted strings should be handled. * @type {{[K in keyof T]: { padStart: number }}} */ #formatter; /** @type {number} */ #precision; /** * Stored value of units, this should always be in one type of unit. * * For example, in the `TempSpan` class, this value will always be measured in units of `Kelvin`. * @protected * @type {number} */ __baseUnitValue; /** * @protected * @param {number} quantity * @param {T} converter * @param {{[K in keyof T]: { padStart: number }}} formatter * @param {number} precision */ constructor(quantity, converter, formatter, precision = 5) { this.#converter = converter; this.#formatter = formatter; this.#precision = 10 ** precision; this.__baseUnitValue = quantity; } /** * @param {(obj: {[K in keyof T]: (quantity: number) => void}) => void} callback * @returns {this} */ add(callback) { const clone = this.#clone(); const t = new Proxy( /** @type {any} */ { ...clone.#converter }, { get: (t2, p, r) => { if (typeof p !== "string") { throw new Error(`Property "${String(p)}" is not of type string.`); } return (quantity) => { const converter = clone.#converter[p]; if (Array.isArray(converter)) { const [convertToBaseUnits, convertFromBaseUnits] = converter; clone.__baseUnitValue = convertToBaseUnits(convertFromBaseUnits(clone.__baseUnitValue) + quantity); } else if (typeof converter === "number") { clone.__baseUnitValue += quantity / converter; } }; } } ); callback(t); return ( /** @type {any} */ clone ); } /** * @param {(obj: {[K in keyof T]: (quantity: number) => void}) => void} callback * @returns {this} */ sub(callback) { const clone = this.#clone(); const t = new Proxy( /** @type {any} */ { ...clone.#converter }, { get: (t2, p, r) => { if (typeof p !== "string") { throw new Error(`Property "${String(p)}" is not of type string.`); } return (quantity) => { const converter = clone.#converter[p]; if (Array.isArray(converter)) { const [convertToBaseUnits, convertFromBaseUnits] = converter; console.log(p, clone.__baseUnitValue, convertToBaseUnits(quantity)); clone.__baseUnitValue = convertToBaseUnits(convertFromBaseUnits(clone.__baseUnitValue) - quantity); } else if (typeof converter === "number") { clone.__baseUnitValue -= quantity / converter; } }; } } ); callback(t); return ( /** @type {any} */ clone ); } /** * @overload Overload 1 * @param {(model: PropertyRetriever<T>) => keyof T} callback * Callback used to get the type of conversion (or otherwise, the key of conversion) to use when converting. * @returns {number} * The converted number from the unit quantity held by this UnitSpan class object. * * @overload * @param {(model: PropertyRetriever<T>) => string} callback * Callback used to get the type of conversion (or otherwise, the key of conversion) to use when converting. * @returns {string} * The converted number from the unit quantity held by this UnitSpan class object. * * @overload * @param {keyof T} key * Some string property of the conversion object to use when converting. * @returns {number} * * @overload * @param {string} key * @returns {string} * The converted number from the unit quantity held by this UnitSpan class object. * * Get the conversion of units as specified from the property reference (and return value) from the `model` parameter used in `callback`. * @param {((model: PropertyRetriever<T>) => keyof T|string)|keyof T|string} callback * @returns {string|number} */ to(callback) { let val = 0; if (typeof callback === "function") { const t = new Proxy( /** @type {any} */ { ...this.#converter }, { get: (t2, p, r) => { return `{{${String(p)}}}`; } } ); let keyOrString = callback(t); if (typeof keyOrString !== "string") { throw new Error(`Expected a string, but got "${typeof keyOrString}".`); } const replacedKeyOrString = keyOrString.replace(/\{\{([^\{\}]*)\}\}/, "$1"); if (replacedKeyOrString in this.#converter) { return handleOverload1_3.bind(this)(replacedKeyOrString); } else { return handleOverload2_4.bind(this)(keyOrString); } } else { if (typeof callback !== "string") { callback = String(callback); } if (callback in this.#converter) { return handleOverload1_3.bind(this)(callback); } else { return handleOverload2_4.bind(this)(callback); } } function handleOverload1_3(key) { const converter = this.#converter[key]; if (Array.isArray(converter)) { const [, convertFromBaseUnits] = converter; const { decimal, fraction } = convertFromBaseUnits(this.__baseUnitValue); val = decimal + Math.floor(fraction * this.#precision) / this.#precision; } else if (typeof converter === "number") { val = converter * this.__baseUnitValue; } return Math.round(val * this.#precision) / this.#precision; } function handleOverload2_4(formatString) { const entries = Object.entries(this.#converter).sort(([k1, v1], [k2, v2]) => { if (typeof v1 === "number" && typeof v2 === "number") { return v1 - v2; } if (typeof v1 !== "number") { const [, convertFromBaseUnits] = v1; const { decimal, fraction, remainder } = convertFromBaseUnits(this.__baseUnitValue); v1 = decimal + Math.floor(fraction * this.#precision) / this.#precision; } if (typeof v2 !== "number") { const [, convertFromBaseUnits] = v2; const { decimal, fraction, remainder } = convertFromBaseUnits(this.__baseUnitValue); v2 = decimal + Math.floor(fraction * this.#precision) / this.#precision; } return v2 - v1; }); let currentBaseUnitValue = this.__baseUnitValue; for (const [key, converter] of entries) { if (!formatString.includes(key)) { continue; } if (Array.isArray(converter)) { const [, convertFromBaseUnits] = converter; const { decimal, remainder } = convertFromBaseUnits(currentBaseUnitValue); formatString = formatString.replaceAll(`{{${key}}}`, Math.floor(decimal).toString().padStart(this.#formatter[key].padStart, "0")); currentBaseUnitValue = remainder; } else if (typeof converter === "number") { let val2 = converter * currentBaseUnitValue; if (Number.isInteger(val2)) { currentBaseUnitValue = 0; } else { if (Math.floor(val2) === 0) { val2 = 0; } else { const frac = val2 - Math.floor(val2); const remainder = Math.floor(frac * this.#precision) / this.#precision; currentBaseUnitValue = remainder / val2 * currentBaseUnitValue; val2 = Math.floor(val2); } } formatString = formatString.replaceAll(`{{${key}}}`, val2.toString().padStart(this.#formatter[key].padStart, "0")); } } return formatString; } } /** * Set the precision of the resulting conversions. * @param {number} numDigits * @returns {this} */ precision(numDigits) { const clone = this.#clone(); clone.#precision = 10 ** numDigits; return ( /** @type {any} */ clone ); } /** * */ #clone() { const clone = new /** @type {any} */ this.constructor(this.#converter); clone.__baseUnitValue = this.__baseUnitValue; return clone; } }; // src/digi.js var DigiSpan = class _DigiSpan extends UnitSpan { /** * @param {number} numBits */ static fromBits(numBits) { return new _DigiSpan(numBits); } /** * @param {number} numBytes */ static fromBytes(numBytes) { return new _DigiSpan(numBytes / DigitalSpanUnitsConverter.Bytes); } /** * @param {number} numKibiBytes */ static fromKibiBytes(numKibiBytes) { return new _DigiSpan(numKibiBytes / DigitalSpanUnitsConverter.Kibibytes); } /** * @param {number} numMebiBytes */ static fromMebiBytes(numMebiBytes) { return new _DigiSpan(numMebiBytes / DigitalSpanUnitsConverter.Mebibytes); } /** * @param {number} numGibiBytes */ static fromGibiBytes(numGibiBytes) { return new _DigiSpan(numGibiBytes / DigitalSpanUnitsConverter.Gibibytes); } /** * @param {number} numTebiBytes */ static fromTebibytes(numTebiBytes) { return new _DigiSpan(numTebiBytes / DigitalSpanUnitsConverter.Tebibytes); } /** * @param {number} numKiloBytes */ static fromKiloBytes(numKiloBytes) { return new _DigiSpan(numKiloBytes / DigitalSpanUnitsConverter.Kilobytes); } /** * @param {number} numMegaBytes */ static fromMegaBytes(numMegaBytes) { return new _DigiSpan(numMegaBytes / DigitalSpanUnitsConverter.Megabytes); } /** * @param {number} numGigaBytes */ static fromGigaBytes(numGigaBytes) { return new _DigiSpan(numGigaBytes / DigitalSpanUnitsConverter.Gigabytes); } /** * @param {number} numTeraBytes */ static fromTeraBytes(numTeraBytes) { return new _DigiSpan(numTeraBytes / DigitalSpanUnitsConverter.Terabytes); } /** * * @param {Uint8Array|Buffer} buffer */ static fromBuffer(buffer) { return new _DigiSpan(buffer.byteLength / DigitalSpanUnitsConverter.Bytes); } /** * @param {number} quantity * @protected */ constructor(quantity) { super( quantity, DigitalSpanUnitsConverter, DigitalSpanUnitsFormatter ); } buffer() { return new Uint8Array(Math.ceil(this.to((m) => m.Bytes))); } }; var DigitalSpanUnitsConverter = Object.freeze({ Bits: 1, Bytes: 1 / 8, Kibibytes: 1 / 1024 / 8, Mebibytes: 1 / 1024 / 1024 / 8, Gibibytes: 1 / 1024 / 1024 / 1024 / 8, Tebibytes: 1 / 1024 / 1024 / 1024 / 1024 / 8, Kilobytes: 1 / 1e3 / 8, Megabytes: 1 / 1e3 / 1e3 / 8, Gigabytes: 1 / 1e3 / 1e3 / 1e3 / 8, Terabytes: 1 / 1e3 / 1e3 / 1e3 / 1e3 / 8 }); var DigitalSpanUnitsFormatter = Object.freeze({ Bits: { padStart: 1 }, Bytes: { padStart: 1 }, Kibibytes: { padStart: 1 }, Mebibytes: { padStart: 1 }, Gibibytes: { padStart: 1 }, Tebibytes: { padStart: 1 }, Kilobytes: { padStart: 1 }, Megabytes: { padStart: 1 }, Gigabytes: { padStart: 1 }, Terabytes: { padStart: 1 } }); // src/time.js var TimeSpan = class _TimeSpan extends UnitSpan { /** * Create a differential time span between two dates, `date1` and `date2`. * @param {Date} date1 * Start date * @param {Date} date2 * End date * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static between(date1, date2) { return new _TimeSpan((date1.getTime() - date2.getTime()) / TimeSpanUnitsConverter.Milliseconds); } /** * Create a differential time span between `January 1st, 1970 00:00:00 UTC` and now. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static sinceEpoch() { return new _TimeSpan(Date.now() / TimeSpanUnitsConverter.Milliseconds); } /** * Create a differential time span between a given date, `date`, and now. * @param {Date} date * Date to differentiate between now. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static since(date) { const time = Date.now() - date.getTime(); return new _TimeSpan(time / TimeSpanUnitsConverter.Milliseconds); } /** * Create a differential time span between now and a date in the future. * @param {Date} date * Date to differentiate between now. (This can be in the past, it will just have negative units) * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static until(date) { const time = date.getTime() - Date.now(); return new _TimeSpan(time / TimeSpanUnitsConverter.Milliseconds); } /** * Create a TimeSpan class with the initial number of nanoseconds. * @param {number} numNanoseconds * Number of nanoseconds to initialize with. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static fromNanoseconds(numNanoseconds) { return new _TimeSpan(numNanoseconds); } /** * Create a TimeSpan class with the initial number of microseconds. * @param {number} numMicroseconds * Number of microseconds to initialize with. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static fromMicroseconds(numMicroseconds) { return new _TimeSpan(numMicroseconds / TimeSpanUnitsConverter.Microseconds); } /** * Create a TimeSpan class with the initial number of milliseconds. * @param {number} numMilliseconds * Number of milliseconds to initialize with. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static fromMilliseconds(numMilliseconds) { return new _TimeSpan(numMilliseconds / TimeSpanUnitsConverter.Milliseconds); } /** * Create a TimeSpan class with the initial number of seconds. * @param {number} numSeconds * Number of seconds to initialize with. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static fromSeconds(numSeconds) { return new _TimeSpan(numSeconds / TimeSpanUnitsConverter.Seconds); } /** * Create a TimeSpan class with the initial number of minutes. * @param {number} numMinutes * Number of minutes to initialize with. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static fromMinutes(numMinutes) { return new _TimeSpan(numMinutes / TimeSpanUnitsConverter.Minutes); } /** * Create a TimeSpan class with the initial number of hours. * @param {number} numHours * Number of hours to initialize with. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static fromHours(numHours) { return new _TimeSpan(numHours / TimeSpanUnitsConverter.Hours); } /** * Create a TimeSpan class with the initial number of days. * @param {number} numDays * Number of days to initialize with. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static fromDays(numDays) { return new _TimeSpan(numDays / TimeSpanUnitsConverter.Days); } /** * Create a TimeSpan class with the initial number of weeks. * @param {number} numWeeks * Number of weeks to initialize with. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static fromWeeks(numWeeks) { return new _TimeSpan(numWeeks / TimeSpanUnitsConverter.Weeks); } /** * Create a TimeSpan class with the initial number of months. * @param {number} numMonths * Number of months to initialize with. * @returns {TimeSpan} * New {@link TimeSpan} class object that can convert between other units of measurement per {@link TimeSpanUnitsConverter} */ static fromMonths(numMonths) { return new _TimeSpan(numMonths / TimeSpanUnitsConverter.Months); } /** * @protected * @param {number} quantity */ constructor(quantity) { super( quantity, TimeSpanUnitsConverter, TimeSpanUnitsFormatter ); } /** * Create a timeout where `callback` is ran only after the time that this TimeSpan object holds has passed. * @usage * ```js * TimeSpan.fromSeconds(10).timeout(() => { * console.log(`This will only print after 10 seconds`); * }); * ``` * @param {() => void|Promise<void>} callback * Function * @returns {TimeoutController} * Object with `clear` and `refresh` functions to control the timeout. * */ timeout(callback) { let timeout = setTimeout(callback, Math.floor(this.to((m) => m.Milliseconds))); const timeoutController = { cancel: () => { clearTimeout(timeout); }, refresh: () => { clearTimeout(timeout); timeout = setTimeout(callback, Math.floor(this.to((m) => m.Milliseconds))); return timeoutController; } }; return timeoutController; } /** * Create an interval where `callback` is ran for every time after the time that this TimeSpan object holds has passed. * @usage * ```js * let i = 0; * const unsubscribe = TimeSpan.fromSeconds(10).interval(() => { * console.log(`Printing ${i}/3`); * if(++i === 3) { * unsubscribe(); * } * }); * * // will print each line every 10 seconds: * // Printing 1/3 * // Printing 2/3 * // Printing 3/3 * ``` * @param {() => void|Promise<void>} callback * @returns {IntervalController} Function to unsubscribe from the interval. */ interval(callback) { let interval = setInterval(callback, Math.floor(this.to((m) => m.Milliseconds))); const intervalController = { cancel: () => { clearInterval(interval); interval = void 0; }, start: () => { if (interval) { clearInterval(interval); } interval = setInterval(callback, Math.floor(this.to((m) => m.Milliseconds))); return intervalController; }, get isStarted() { return interval !== void 0; }, get isStopped() { return interval === void 0; } }; return intervalController; } /** * Create a Promise that will only resolve after the time that this TimeSpan object holds has passed. * @returns {Promise<void>} */ delay() { return new Promise((resolve) => this.timeout(resolve)); } toYears() { return this.to((m) => m.Years); } toMonths() { return this.to((m) => m.Months); } toWeeks() { return this.to((m) => m.Weeks); } toDays() { return this.to((m) => m.Days); } toHours() { return this.to((m) => m.Hours); } toMinutes() { return this.to((m) => m.Minutes); } toSeconds() { return this.to((m) => m.Seconds); } toMilliseconds() { return this.to((m) => m.Milliseconds); } toMicroseconds() { return this.to((m) => m.Microseconds); } toNanoseconds() { return this.to((m) => m.Nanoseconds); } toString() { return this.to((m) => `${m.hours}:${m.minutes}:${m.seconds}.${m.milliseconds}`); } }; var TimeSpanUnitsConverter = Object.freeze({ /** @deprecated */ Nanoseconds: 1, /** @deprecated */ Microseconds: 1 / 1e3, /** @deprecated */ Milliseconds: 1 / 1e3 / 1e3, /** @deprecated */ Seconds: 1 / 1e3 / 1e3 / 1e3, /** @deprecated */ Minutes: 1 / 60 / 1e3 / 1e3 / 1e3, /** @deprecated */ Hours: 1 / 60 / 60 / 1e3 / 1e3 / 1e3, /** @deprecated */ Days: 1 / 24 / 60 / 60 / 1e3 / 1e3 / 1e3, /** @deprecated */ Weeks: 1 / 7 / 24 / 60 / 60 / 1e3 / 1e3 / 1e3, /** @deprecated */ Months: 1 / 30.437 / 24 / 60 / 60 / 1e3 / 1e3 / 1e3, /** @deprecated */ Years: 1 / 365.2425 / 24 / 60 / 60 / 1e3 / 1e3 / 1e3, nanoseconds: 1, microseconds: 1 / 1e3, milliseconds: 1 / 1e3 / 1e3, seconds: 1 / 1e3 / 1e3 / 1e3, minutes: 1 / 60 / 1e3 / 1e3 / 1e3, hours: 1 / 60 / 60 / 1e3 / 1e3 / 1e3, days: 1 / 24 / 60 / 60 / 1e3 / 1e3 / 1e3, weeks: 1 / 7 / 24 / 60 / 60 / 1e3 / 1e3 / 1e3, months: 1 / 30.437 / 24 / 60 / 60 / 1e3 / 1e3 / 1e3, years: 1 / 365.2425 / 24 / 60 / 60 / 1e3 / 1e3 / 1e3 }); var TimeSpanUnitsFormatter = { Nanoseconds: { padStart: 3 }, Microseconds: { padStart: 3 }, Milliseconds: { padStart: 3 }, Seconds: { padStart: 2 }, Minutes: { padStart: 2 }, Hours: { padStart: 2 }, Days: { padStart: 2 }, Weeks: { padStart: 2 }, Months: { padStart: 2 }, Years: { padStart: 0 }, nanoseconds: { padStart: 3 }, microseconds: { padStart: 3 }, milliseconds: { padStart: 3 }, seconds: { padStart: 2 }, minutes: { padStart: 2 }, hours: { padStart: 2 }, days: { padStart: 2 }, weeks: { padStart: 2 }, months: { padStart: 2 }, years: { padStart: 0 } }; export { DigiSpan, TimeSpan }; //# sourceMappingURL=index.js.map //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy91bml0c3Bhbi5qcyIsIi4uL3NyYy9kaWdpLmpzIiwiLi4vc3JjL3RpbWUuanMiXSwibmFtZXMiOlsidCIsInZhbCJdLCJtYXBwaW5ncyI6IjtBQU9PLElBQU0sV0FBTixNQUFlO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTWxCLFVBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFNQSxVQUFBO0FBQUE7QUFBQSxFQUVBLFVBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBUUEsZUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFTQSxXQUFZLENBQUEsUUFBQSxFQUFVLFNBQVcsRUFBQSxTQUFBLEVBQVcsWUFBVSxDQUFHLEVBQUE7QUFDckQsSUFBQSxJQUFBLENBQUssVUFBYSxHQUFBLFNBQUE7QUFDbEIsSUFBQSxJQUFBLENBQUssVUFBYSxHQUFBLFNBQUE7QUFDbEIsSUFBQSxJQUFBLENBQUssYUFBYSxFQUFNLElBQUEsU0FBQTtBQUN4QixJQUFBLElBQUEsQ0FBSyxlQUFrQixHQUFBLFFBQUE7QUFBQTtBQUMzQjtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTUEsSUFBSSxRQUFVLEVBQUE7QUFDVixJQUFNLE1BQUEsS0FBQSxHQUFRLEtBQUssTUFBTyxFQUFBO0FBQzFCLElBQUEsTUFBTSxJQUFJLElBQUksS0FBQTtBQUFBO0FBQUEsTUFBeUIsRUFBQyxHQUFHLEtBQUEsQ0FBTSxVQUFVLEVBQUE7QUFBQSxNQUFJO0FBQUEsUUFDM0QsR0FBSyxFQUFBLENBQUNBLEVBQUUsRUFBQSxDQUFBLEVBQUUsQ0FBTSxLQUFBO0FBQ1osVUFBRyxJQUFBLE9BQU8sTUFBTSxRQUFVLEVBQUE7QUFDdEIsWUFBQSxNQUFNLElBQUksS0FBTSxDQUFBLENBQUEsVUFBQSxFQUFhLE1BQU8sQ0FBQSxDQUFDLENBQUMsQ0FBMEIsd0JBQUEsQ0FBQSxDQUFBO0FBQUE7QUFF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QUFBQSxFQUNBLE9BQVMsRUFBQTtBQUFBLElBQ0wsUUFBVSxFQUFBO0FBQUEsR0FDZDtBQUFBLEVBQ0EsS0FBTyxFQUFBO0FBQUEsSUFDSCxRQUFVLEVBQUE7QUFBQSxHQUNkO0FBQUEsRUFDQSxJQUFNLEVBQUE7QUFBQSxJQUNGLFFBQVUsRUFBQTtBQUFBLEdBQ2Q7QUFBQSxFQUNBLEtBQU8sRUFBQTtBQUFBLElBQ0gsUUFBVSxFQUFBO0FBQUEsR0FDZDtBQUFBLEVBQ0EsTUFBUSxFQUFBO0FBQUEsSUFDSixRQUFVLEVBQUE7QUFBQSxHQUNkO0FBQUEsRUFDQSxLQUFPLEVBQUE7QUFBQSxJQUNILFFBQVUsRUFBQTtBQUFBLEdBQ2Q7QUFBQSxFQUVBLFdBQWEsRUFBQTtBQUFBLElBQ1QsUUFBVSxFQUFBO0FBQUEsR0FDZDtBQUFBLEVBQ0EsWUFBYyxFQUFBO0FBQUEsSUFDVixRQUFVLEVBQUE7QUFBQSxHQUNkO0FBQUEsRUFDQSxZQUFjLEVBQUE7QUFBQSxJQUNWLFFBQVUsRUFBQTtBQUFBLEdBQ2Q7QUFBQSxFQUNBLE9BQVMsRUFBQTtBQUFBLElBQ0wsUUFBVSxFQUFBO0FBQUEsR0FDZDtBQUFBLEVBQ0EsT0FBUyxFQUFBO0FBQUEsSUFDTCxRQUFVLEVBQUE7QUFBQSxHQUNkO0FBQUEsRUFDQSxLQUFPLEVBQUE7QUFBQSxJQUNILFFBQVUsRUFBQTtBQUFBLEdBQ2Q7QUFBQSxFQUNBLElBQU0sRUFBQTtBQUFBLElBQ0YsUUFBVSxFQUFBO0FBQUEsR0FDZDtBQUFBLEVBQ0EsS0FBTyxFQUFBO0FBQUEsSUFDSCxRQUFVLEVBQUE7QUFBQSxHQUNkO0FBQUEsRUFDQSxNQUFRLEVBQUE7QUFBQSxJQUNKLFFBQVUsRUFBQTtBQUFBLEdBQ2Q7QUFBQSxFQUNBLEtBQU8sRUFBQTtBQUFBLElBQ0gsUUFBVSxFQUFBO0FBQUE7QUFFbEIsQ0FBQSIsImZpbGUiOiJpbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vQHRzLWNoZWNrXHJcblxyXG4vKiogQHR5cGVkZWYge1JlY29yZDxzdHJpbmcsIG51bWJlcnxbY29udmVydFRvQmFzZVVuaXQ6ICh1bml0czogbnVtYmVyKSA9PiBudW1iZXIsIGNvbnZlcnRGcm9tQmFzZVVuaXQ6IChiYXNlVW5pdHM6IG51bWJlcikgPT4geyBkZWNpbWFsOiBudW1iZXIsIHJlbWFpbmRlcjogbnVtYmVyLCBmcmFjdGlvbjogbnVtYmVyIH1dPn0gQ29udmVydGVyICovXHJcblxyXG4vKipcclxuICogQHRlbXBsYXRlIHtSZWNvcmQ8c3RyaW5nLCBudW1iZXJ8W2NvbnZlcnRUb0Jhc2VVbml0OiAodW5pdHM6IG51bWJlcikgPT4gbnVtYmVyLCBjb252ZXJ0RnJvbUJhc2VVbml0OiAoYmFzZVVuaXRzOiBudW1iZXIpID0+IHsgZGVjaW1hbDogbnVtYmVyLCByZW1haW5kZXI6IG51bWJlciwgZnJhY3Rpb246IG51bWJlciB9XT59IFRcclxuICovXHJcbmV4cG9ydCBjbGFzcyBVbml0U3BhbiB7XHJcbiAgICAvKiogXHJcbiAgICAgKiBBbiBvYmplY3Qgd2l0aCB2YWx1ZXMgb2YgbnVtYmVycyBvciBmdW5jdGlvbnMuIEF0IGxlYXN0IG9uZSBwcm9wZXJ0eSBzaG91bGQgbWFwIHRvIHRoZSB2YWx1ZSBvZiBgMWAgYW5kIHRoYXQgcHJvcGVydHkgc2hvdWxkXHJcbiAgICAgKiBiZSB0aGUgYmFzZSB1bml0IG9mIG1lYXN1cmVtZW50IGluIHRoaXMgY2xhc3MgKGkuby53LiwgYF9fYmFzZVVuaXRWYWx1ZWAgc2hvdWxkIHN0b3JlIHRoaXMgdW5pdCBvZiBtZWFzdXJlbWVudC4pICBcclxuICAgICAqIEB0eXBlIHtUfSBcclxuICAgICAqL1xyXG4gICAgI2NvbnZlcnRlcjtcclxuICAgIC8qKlxyXG4gICAgICogQW4gb2JqZWN0IHdpdGggdGhlIHNhbWUga2V5cyBhcyB0aGUgYGNvbnZlcnRlcmAgb2JqZWN0LCBidXQgd2l0aCB2YWx1ZXMgYmVpbmcgb2JqZWN0cyBob2xkaW5nXHJcbiAgICAgKiBjb25maWd1cmF0aW9ucyBmb3IgaG93IHRoZSBmb3JtYXR0ZWQgc3RyaW5ncyBzaG91bGQgYmUgaGFuZGxlZC5cclxuICAgICAqIEB0eXBlIHt7W0sgaW4ga2V5b2YgVF06IHsgcGFkU3RhcnQ6IG51bWJlciB9fX1cclxuICAgICAqL1xyXG4gICAgI2Zvcm1hdHRlcjtcclxuICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xyXG4gICAgI3ByZWNpc2lvbjtcclxuICAgIC8qKiBcclxuICAgICAqIFN0b3JlZCB2YWx1ZSBvZiB1bml0cywgdGhpcyBzaG91bGQgYWx3YXlzIGJlIGluIG9uZSB0eXBlIG9mIHVuaXQuICBcclxuICAgICAqIFxyXG4gICAgICogRm9yIGV4YW1wbGUsIGluIHRoZSBgVGVtcFNwYW5gIGNsYXNzLCB0aGlzIHZhbHVlIHdpbGwgYWx3YXlzIGJlIG1lYXN1cmVkIGluIHVuaXRzIG9mIGBLZWx2aW5gLlxyXG4gICAgICogQHByb3RlY3RlZCBcclxuICAgICAqIEB0eXBlIHtudW1iZXJ9IFxyXG4gICAgICovXHJcbiAgICBfX2Jhc2VVbml0VmFsdWU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcHJvdGVjdGVkXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcXVhbnRpdHlcclxuICAgICAqIEBwYXJhbSB7VH0gY29udmVydGVyIFxyXG4gICAgICogQHBhcmFtIHt7W0sgaW4ga2V5b2YgVF06IHsgcGFkU3RhcnQ6IG51bWJlciB9fX0gZm9ybWF0dGVyXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcHJlY2lzaW9uXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKHF1YW50aXR5LCBjb252ZXJ0ZXIsIGZvcm1hdHRlciwgcHJlY2lzaW9uPTUpIHtcclxuICAgICAgICB0aGlzLiNjb252ZXJ0ZXIgPSBjb252ZXJ0ZXI7XHJcbiAgICAgICAgdGhpcy4jZm9ybWF0dGVyID0gZm9ybWF0dGVyO1xyXG4gICAgICAgIHRoaXMuI3ByZWNpc2lvbiA9IDEwICoqIHByZWNpc2lvbjtcclxuICAgICAgICB0aGlzLl9fYmFzZVVuaXRWYWx1ZSA9IHF1YW50aXR5O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHBhcmFtIHsob2JqOiB7W0sgaW4ga2V5b2YgVF06IChxdWFudGl0eTogbnVtYmVyKSA9PiB2b2lkfSkgPT4gdm9pZH0gY2FsbGJhY2tcclxuICAgICAqIEByZXR1cm5zIHt0aGlzfVxyXG4gICAgICovXHJcbiAgICBhZGQoY2FsbGJhY2spIHtcclxuICAgICAgICBjb25zdCBjbG9uZSA9IHRoaXMuI2Nsb25lKCk7XHJcbiAgICAgICAgY29uc3QgdCA9IG5ldyBQcm94eSgvKiogQHR5cGUge2FueX0gKi8oey4uLmNsb25lLiNjb252ZXJ0ZXJ9KSwge1xyXG4gICAgICAgICAgICBnZXQ6ICh0LHAscikgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYodHlwZW9mIHAgIT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5IFwiJHtTdHJpbmcocCl9XCIgaXMgbm90IG9mIHR5cGUgc3RyaW5nLmApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIChxdWFudGl0eSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnZlcnRlciA9IGNsb25lLiNjb252ZXJ0ZXJbcF07XHJcbiAgICAgICAgICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShjb252ZXJ0ZXIpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFtjb252ZXJ0VG9CYXNlVW5pdHMsIGNvbnZlcnRGcm9tQmFzZVVuaXRzXSA9IGNvbnZlcnRlcjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmUuX19iYXNlVW5pdFZhbHVlID0gY29udmVydFRvQmFzZVVuaXRzKGNvbnZlcnRGcm9tQmFzZVVuaXRzKGNsb25lLl9fYmFzZVVuaXRWYWx1ZSkgKyBxdWFudGl0eSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICBpZih0eXBlb2YgY29udmVydGVyID09PSBcIm51bWJlclwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lLl9fYmFzZVVuaXRWYWx1ZSArPSBxdWFudGl0eSAvIGNvbnZlcnRlcjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICBjYWxsYmFjayh0KTtcclxuICAgICAgICByZXR1cm4gLyoqIEB0eXBlIHthbnl9ICovIChjbG9uZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0geyhvYmo6IHtbSyBpbiBrZXlvZiBUXTogKHF1YW50aXR5OiBudW1iZXIpID0+IHZvaWR9KSA9PiB2b2lkfSBjYWxsYmFja1xyXG4gICAgICogQHJldHVybnMge3RoaXN9XHJcbiAgICAgKi9cclxuICAgIHN1YihjYWxsYmFjaykge1xyXG4gICAgICAgIGNvbnN0IGNsb25lID0gdGhpcy4jY2xvbmUoKTtcclxuICAgICAgICBjb25zdCB0ID0gbmV3IFByb3h5KC8qKiBAdHlwZSB7YW55fSAqLyh7Li4uY2xvbmUuI2NvbnZlcnRlcn0pLCB7XHJcbiAgICAgICAgICAgIGdldDogKHQscCxyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZih0eXBlb2YgcCAhPT0gXCJzdHJpbmdcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgXCIke1N0cmluZyhwKX1cIiBpcyBub3Qgb2YgdHlwZSBzdHJpbmcuYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gKHF1YW50aXR5KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udmVydGVyID0gY2xvbmUuI2NvbnZlcnRlcltwXTtcclxuICAgICAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KGNvbnZlcnRlcikpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW2NvbnZlcnRUb0Jhc2VVbml0cywgY29udmVydEZyb21CYXNlVW5pdHNdID0gY29udmVydGVyO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhwLCBjbG9uZS5fX2Jhc2VVbml0VmFsdWUsIGNvbnZlcnRUb0Jhc2VVbml0cyhxdWFudGl0eSkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjbG9uZS5fX2Jhc2VVbml0VmFsdWUgPSBjb252ZXJ0VG9CYXNlVW5pdHMoY29udmVydEZyb21CYXNlVW5pdHMoY2xvbmUuX19iYXNlVW5pdFZhbHVlKSAtIHF1YW50aXR5KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBjb252ZXJ0ZXIgPT09IFwibnVtYmVyXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmUuX19iYXNlVW5pdFZhbHVlIC09IHF1YW50aXR5IC8gY29udmVydGVyO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGNhbGxiYWNrKHQpO1xyXG4gICAgICAgIHJldHVybiAvKiogQHR5cGUge2FueX0gKi8gKGNsb25lKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBvdmVybG9hZCBPdmVybG9hZCAxXHJcbiAgICAgKiBAcGFyYW0geyhtb2RlbDogUHJvcGVydHlSZXRyaWV2ZXI8VD4pID0+IGtleW9mIFR9IGNhbGxiYWNrXHJcbiAgICAgKiBDYWxsYmFjayB1c2VkIHRvIGdldCB0aGUgdHlwZSBvZiBjb252ZXJzaW9uIChvciBvdGhlcndpc2UsIHRoZSBrZXkgb2YgY29udmVyc2lvbikgdG8gdXNlIHdoZW4gY29udmVydGluZy5cclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XHJcbiAgICAgKiBUaGUgY29udmVydGVkIG51bWJlciBmcm9tIHRoZSB1bml0IHF1YW50aXR5IGhlbGQgYnkgdGhpcyBVbml0U3BhbiBjbGFzcyBvYmplY3QuXHJcbiAgICAgKiBcclxuICAgICAqIEBvdmVybG9hZFxyXG4gICAgICogQHBhcmFtIHsobW9kZWw6IFByb3BlcnR5UmV0cmlldmVyPFQ+KSA9PiBzdHJpbmd9IGNhbGxiYWNrX