UNPKG

@nova-ui/bits

Version:

SolarWinds Nova Framework

219 lines 30.5 kB
// © 2022 SolarWinds Worldwide, LLC. All rights reserved. // // 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. import { Injectable } from "@angular/core"; import { LoggerService } from "./log-service"; import { UnitBase, unitConversionConstants, } from "../constants/unit-conversion.constants"; import * as i0 from "@angular/core"; import * as i1 from "./log-service"; /** * <example-url>./../examples/index.html#/common/unit-conversion-service</example-url> * * Service for converting a raw value to a larger unit approximation of the value--for example, 1024 B to 1 MB, 12345 Hz to 12.35 kHz, etc. */ export class UnitConversionService { constructor(logger) { this.logger = logger; } /** * Converts a raw value to a larger unit approximation of the value. For example, 1024 B to 1 KB, 12345 Hz to 12.35 kHz, etc. * * @param value The value to convert * @param base The base to use for the exponential expression when calculating the conversion result * * @returns {{ [Key in keyof Pick<IUnitConversionResult, "value" | "order">]: number }} The value and order of conversion */ convertLinear(value, base) { let resultValue; let resultOrder; if (value === 0) { return { value: 0, order: 0, }; } resultOrder = Math.floor(Math.log(Math.abs(value)) / Math.log(base)); resultValue = value / Math.pow(base, Math.floor(resultOrder)); if (Math.abs(value) > 0 && Math.abs(value) < 1) { return { value: value, order: 0, }; } // fix the precision edge case const valueCeiled = Math.ceil(resultValue); if (valueCeiled % base === 0) { resultValue = valueCeiled / base; resultOrder += 1; } return { value: resultValue, order: resultOrder, }; } /** * Converts a raw value to a larger unit approximation of the value. For example, 1100ms to 1.1s, 66000ms to 1.1m, etc. * * @param value The value to convert * @param factors Array of factors to use for calculating smallest possible not zero result * * @returns {{ [Key in keyof Pick<IUnitConversionResult, "value" | "order">]: number }} The value and order of conversion */ convertNonLinear(value, factors) { const sortedFactors = factors.sort((a, b) => a > b ? -1 : a < b ? 1 : 0); const highestFactorIndex = sortedFactors.findIndex((factor) => value / factor >= 1); const highestFactor = factors[highestFactorIndex]; if (Math.abs(value) > 0 && Math.abs(value) < 1) { return { value: value, order: 0, }; } return { value: value / highestFactor, order: highestFactorIndex === -1 ? 0 : factors.length - highestFactorIndex - 1, }; } /** * Converts a raw value to a larger unit approximation of the value. For example, 1024 B to 1 KB, 12345 Hz to 12.35 kHz, 66000ms to 1.1m, etc. * * @param value The value to convert * @param base The base or array of factors to use for calculating the conversion result * @param scale The number of significant digits to the right of the decimal to include in the resulting converted value * * @returns {IUnitConversionResult} The conversion result */ convert(value, base = UnitBase.Standard, scale = 1) { const result = Array.isArray(base) ? this.convertNonLinear(value, base) : this.convertLinear(value, base); let strValue; if (value !== 0) { strValue = parseFloat(result.value.toFixed(scale)).toString(); } else { result.order = 0; strValue = value.toString(); } return { value: strValue, order: result.order, scientificNotation: value?.toExponential(scale), scale, }; } /** * Gets the display string of a conversion result * * @param conversion The result of an invocation of this service's convert method * @param unit The unit used in the conversion * @param plusSign Whether to prepend the display string with a '+' * @param nanDisplay The string to display in case the conversion result is NaN or Infinity * * @returns {string} The display string of the conversion result */ getFullDisplay(conversion, unit, plusSign = false, nanDisplay = "---") { const isValidNumber = this.isValidNumber(conversion.value); const spacing = unit !== "generic" && isValidNumber ? " " : ""; let unitDisplay = isValidNumber ? this.getUnitDisplay(conversion, unit) : ""; // The generic unit is not currently i18n friendly const localizeValue = unit !== "generic"; let displayValue; if (!unitDisplay && isValidNumber && conversion.order) { unitDisplay = this.getUnitDisplayBaseValue(unit); displayValue = this.getScientificDisplay(conversion, plusSign, nanDisplay); } else { displayValue = this.getValueDisplay(conversion, plusSign, nanDisplay, localizeValue); } return `${displayValue}${spacing}${unitDisplay}`; } /** * Gets the converted value display string * * @param conversion The result of an invocation of this service's convert method * @param plusSign Whether to prepend the display string with a '+' * @param nanDisplay The string to display in case the conversion result is NaN or Infinity * @param localize Whether to localize the value for display. Note: It's not recommended to localize values for * the "generic" unit, e.g. "1.1K" for 1100, as the "generic" unit is currently not i18n friendly * * @returns {string} The converted value display string */ getValueDisplay(conversion, plusSign = false, nanDisplay = "---", localize = true) { if (!this.isValidNumber(conversion.value)) { return nanDisplay; } const outputValue = localize ? parseFloat(conversion.value).toLocaleString(undefined, { maximumFractionDigits: conversion.scale, }) : conversion.value; const prefix = plusSign && parseInt(conversion.value, 10) > 0 ? "+" : ""; return `${prefix}${outputValue}`; } /** * Gets the converted unit display string * * @param conversion The result of an invocation of this service's convert method * @param unit The basic unit used in the conversion * * @returns {string} The converted unit display string */ getUnitDisplay(conversion, unit) { return unitConversionConstants[unit][conversion.order]; } /** * Gets the base value of the converted unit * * @param unit The basic unit used in the conversion * * @returns {string} The abbreviation for the smallest unit of the provided UnitOption */ getUnitDisplayBaseValue(unit) { return unitConversionConstants[unit][0]; } /** * Gets the converted value display string in scientific notation * * @param conversion The result of an invocation of this service's convert method * @param plusSign Whether to prepend the display string with a '+' * @param nanDisplay The string to display in case the conversion result is NaN or Infinity * * @returns {string} The converted value display string in scientific notation */ getScientificDisplay(conversion, plusSign = false, nanDisplay = "---") { if (!this.isValidNumber(conversion.value)) { return nanDisplay; } const prefix = plusSign && parseInt(conversion.value, 10) > 0 ? "+" : ""; return `${prefix}${conversion.scientificNotation}`; } isValidNumber(value) { return !isNaN(parseFloat(value)) && isFinite(parseInt(value, 10)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UnitConversionService, deps: [{ token: i1.LoggerService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UnitConversionService, providedIn: "root" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UnitConversionService, decorators: [{ type: Injectable, args: [{ providedIn: "root" }] }], ctorParameters: () => [{ type: i1.LoggerService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5pdC1jb252ZXJzaW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvdW5pdC1jb252ZXJzaW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseURBQXlEO0FBQ3pELEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLDREQUE0RDtBQUM1RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsaUJBQWlCO0FBRWpCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFM0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU5QyxPQUFPLEVBQ0gsUUFBUSxFQUNSLHVCQUF1QixHQUUxQixNQUFNLHdDQUF3QyxDQUFDOzs7QUFFaEQ7Ozs7R0FJRztBQUVILE1BQU0sT0FBTyxxQkFBcUI7SUFDOUIsWUFBb0IsTUFBcUI7UUFBckIsV0FBTSxHQUFOLE1BQU0sQ0FBZTtJQUFHLENBQUM7SUFFN0M7Ozs7Ozs7T0FPRztJQUNLLGFBQWEsQ0FDakIsS0FBYSxFQUNiLElBQVk7UUFFWixJQUFJLFdBQW1CLENBQUM7UUFDeEIsSUFBSSxXQUFtQixDQUFDO1FBRXhCLElBQUksS0FBSyxLQUFLLENBQUMsRUFBRTtZQUNiLE9BQU87Z0JBQ0gsS0FBSyxFQUFFLENBQUM7Z0JBQ1IsS0FBSyxFQUFFLENBQUM7YUFDWCxDQUFDO1NBQ0w7UUFFRCxXQUFXLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FDcEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdB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QUFDLEVBQUU7WUFDdkMsT0FBTyxVQUFVLENBQUM7U0FDckI7UUFDRCxNQUFNLE1BQU0sR0FDUixRQUFRLElBQUksUUFBUSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUU5RCxPQUFPLEdBQUcsTUFBTSxHQUFHLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQ3ZELENBQUM7SUFFTyxhQUFhLENBQUMsS0FBVTtRQUM1QixPQUFPLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEUsQ0FBQzsrR0FqUFEscUJBQXFCO21IQUFyQixxQkFBcUIsY0FEUixNQUFNOzs0RkFDbkIscUJBQXFCO2tCQURqQyxVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbIi8vIMKpIDIwMjIgU29sYXJXaW5kcyBXb3JsZHdpZGUsIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyAgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG9cbi8vICBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vclxuLy8gIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vICBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vICBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vICBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyAgVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuaW1wb3J0IHsgTG9nZ2VyU2VydmljZSB9IGZyb20gXCIuL2xvZy1zZXJ2aWNlXCI7XG5pbXBvcnQgeyBJVW5pdENvbnZlcnNpb25SZXN1bHQgfSBmcm9tIFwiLi9wdWJsaWMtYXBpXCI7XG5pbXBvcnQge1xuICAgIFVuaXRCYXNlLFxuICAgIHVuaXRDb252ZXJzaW9uQ29uc3RhbnRzLFxuICAgIFVuaXRPcHRpb24sXG59IGZyb20gXCIuLi9jb25zdGFudHMvdW5pdC1jb252ZXJzaW9uLmNvbnN0YW50c1wiO1xuXG4vKipcbiAqIDxleGFtcGxlLXVybD4uLy4uL2V4YW1wbGVzL2luZGV4Lmh0bWwjL2NvbW1vbi91bml0LWNvbnZlcnNpb24tc2VydmljZTwvZXhhbXBsZS11cmw+XG4gKlxuICogU2VydmljZSBmb3IgY29udmVydGluZyBhIHJhdyB2YWx1ZSB0byBhIGxhcmdlciB1bml0IGFwcHJveGltYXRpb24gb2YgdGhlIHZhbHVlLS1mb3IgZXhhbXBsZSwgMTAyNCBCIHRvIDEgTUIsIDEyMzQ1IEh6IHRvIDEyLjM1IGtIeiwgZXRjLlxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46IFwicm9vdFwiIH0pXG5leHBvcnQgY2xhc3MgVW5pdENvbnZlcnNpb25TZXJ2aWNlIHtcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGxvZ2dlcjogTG9nZ2VyU2VydmljZSkge31cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGEgcmF3IHZhbHVlIHRvIGEgbGFyZ2VyIHVuaXQgYXBwcm94aW1hdGlvbiBvZiB0aGUgdmFsdWUuIEZvciBleGFtcGxlLCAxMDI0IEIgdG8gMSBLQiwgMTIzNDUgSHogdG8gMTIuMzUga0h6LCBldGMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnRcbiAgICAgKiBAcGFyYW0gYmFzZSBUaGUgYmFzZSB0byB1c2UgZm9yIHRoZSBleHBvbmVudGlhbCBleHByZXNzaW9uIHdoZW4gY2FsY3VsYXRpbmcgdGhlIGNvbnZlcnNpb24gcmVzdWx0XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7eyBbS2V5IGluIGtleW9mIFBpY2s8SVVuaXRDb252ZXJzaW9uUmVzdWx0LCBcInZhbHVlXCIgfCBcIm9yZGVyXCI+XTogbnVtYmVyIH19IFRoZSB2YWx1ZSBhbmQgb3JkZXIgb2YgY29udmVyc2lvblxuICAgICAqL1xuICAgIHByaXZhdGUgY29udmVydExpbmVhcihcbiAgICAgICAgdmFsdWU6IG51bWJlcixcbiAgICAgICAgYmFzZTogbnVtYmVyXG4gICAgKTogeyBbS2V5IGluIGtleW9mIFBpY2s8SVVuaXRDb252ZXJzaW9uUmVzdWx0LCBcInZhbHVlXCIgfCBcIm9yZGVyXCI+XTogbnVtYmVyIH0ge1xuICAgICAgICBsZXQgcmVzdWx0VmFsdWU6IG51bWJlcjtcbiAgICAgICAgbGV0IHJlc3VsdE9yZGVyOiBudW1iZXI7XG5cbiAgICAgICAgaWYgKHZhbHVlID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHZhbHVlOiAwLFxuICAgICAgICAgICAgICAgIG9yZGVyOiAwLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3VsdE9yZGVyID0gTWF0aC5mbG9vcihcbiAgICAgICAgICAgIE1hdGgubG9nKE1hdGguYWJzKHZhbHVlKSkgLyBNYXRoLmxvZyhiYXNlKVxuICAgICAgICApO1xuICAgICAgICByZXN1bHRWYWx1ZSA9IHZhbHVlIC8gTWF0aC5wb3coYmFzZSwgTWF0aC5mbG9vcihyZXN1bHRPcmRlcikpO1xuXG4gICAgICAgIGlmIChNYXRoLmFicyh2YWx1ZSkgPiAwICYmIE1hdGguYWJzKHZhbHVlKSA8IDEpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICAgICAgICAgIG9yZGVyOiAwLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGZpeCB0aGUgcHJlY2lzaW9uIGVkZ2UgY2FzZVxuICAgICAgICBjb25zdCB2YWx1ZUNlaWxlZCA9IE1hdGguY2VpbChyZXN1bHRWYWx1ZSk7XG4gICAgICAgIGlmICh2YWx1ZUNlaWxlZCAlIGJhc2UgPT09IDApIHtcbiAgICAgICAgICAgIHJlc3VsdFZhbHVlID0gdmFsdWVDZWlsZWQgLyBiYXNlO1xuICAgICAgICAgICAgcmVzdWx0T3JkZXIgKz0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2YWx1ZTogcmVzdWx0VmFsdWUsXG4gICAgICAgICAgICBvcmRlcjogcmVzdWx0T3JkZXIsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYSByYXcgdmFsdWUgdG8gYSBsYXJnZXIgdW5pdCBhcHByb3hpbWF0aW9uIG9mIHRoZSB2YWx1ZS4gRm9yIGV4YW1wbGUsIDExMDBtcyB0byAxLjFzLCA2NjAwMG1zIHRvIDEuMW0sIGV0Yy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydFxuICAgICAqIEBwYXJhbSBmYWN0b3JzIEFycmF5IG9mIGZhY3RvcnMgdG8gdXNlIGZvciBjYWxjdWxhdGluZyBzbWFsbGVzdCBwb3NzaWJsZSBub3QgemVybyByZXN1bHRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHt7IFtLZXkgaW4ga2V5b2YgUGljazxJVW5pdENvbnZlcnNpb25SZXN1bHQsIFwidmFsdWVcIiB8IFwib3JkZXJcIj5dOiBudW1iZXIgfX0gVGhlIHZhbHVlIGFuZCBvcmRlciBvZiBjb252ZXJzaW9uXG4gICAgICovXG4gICAgcHJpdmF0ZSBjb252ZXJ0Tm9uTGluZWFyKFxuICAgICAgICB2YWx1ZTogbnVtYmVyLFxuICAgICAgICBmYWN0b3JzOiBudW1iZXJbXVxuICAgICk6IHsgW0tleSBpbiBrZXlvZiBQaWNrPElVbml0Q29udmVyc2lvblJlc3VsdCwgXCJ2YWx1ZVwiIHwgXCJvcmRlclwiPl06IG51bWJlciB9IHtcbiAgICAgICAgY29uc3Qgc29ydGVkRmFjdG9ycyA9IGZhY3RvcnMuc29ydCgoYSwgYikgPT4gYSA+IGIgPyAtMSA6IGEgPCBiID8gMSA6IDApO1xuICAgICAgICBjb25zdCBoaWdoZXN0RmFjdG9ySW5kZXggPSBzb3J0ZWRGYWN0b3JzLmZpbmRJbmRleCgoZmFjdG9yKSA9PiB2YWx1ZSAvIGZhY3RvciA+PSAxKTtcbiAgICAgICAgY29uc3QgaGlnaGVzdEZhY3RvciA9IGZhY3RvcnNbaGlnaGVzdEZhY3RvckluZGV4XTtcblxuICAgICAgICBpZiAoTWF0aC5hYnModmFsdWUpID4gMCAmJiBNYXRoLmFicyh2YWx1ZSkgPCAxKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICBvcmRlcjogMCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdmFsdWU6IHZhbHVlIC8gaGlnaGVzdEZhY3RvcixcbiAgICAgICAgICAgIG9yZGVyOiBoaWdoZXN0RmFjdG9ySW5kZXggPT09IC0xID8gMCA6IGZhY3RvcnMubGVuZ3RoIC0gaGlnaGVzdEZhY3RvckluZGV4IC0gMSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBhIHJhdyB2YWx1ZSB0byBhIGxhcmdlciB1bml0IGFwcHJveGltYXRpb24gb2YgdGhlIHZhbHVlLiBGb3IgZXhhbXBsZSwgMTAyNCBCIHRvIDEgS0IsIDEyMzQ1IEh6IHRvIDEyLjM1IGtIeiwgNjYwMDBtcyB0byAxLjFtLCBldGMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnRcbiAgICAgKiBAcGFyYW0gYmFzZSBUaGUgYmFzZSBvciBhcnJheSBvZiBmYWN0b3JzIHRvIHVzZSBmb3IgY2FsY3VsYXRpbmcgdGhlIGNvbnZlcnNpb24gcmVzdWx0XG4gICAgICogQHBhcmFtIHNjYWxlIFRoZSBudW1iZXIgb2Ygc2lnbmlmaWNhbnQgZGlnaXRzIHRvIHRoZSByaWdodCBvZiB0aGUgZGVjaW1hbCB0byBpbmNsdWRlIGluIHRoZSByZXN1bHRpbmcgY29udmVydGVkIHZhbHVlXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7SVVuaXRDb252ZXJzaW9uUmVzdWx0fSBUaGUgY29udmVyc2lvbiByZXN1bHRcbiAgICAgKi9cbiAgICBjb252ZXJ0KFxuICAgICAgICB2YWx1ZTogbnVtYmVyLFxuICAgICAgICBiYXNlOiBudW1iZXIgfCBudW1iZXJbXSA9IFVuaXRCYXNlLlN0YW5kYXJkLFxuICAgICAgICBzY2FsZTogbnVtYmVyID0gMVxuICAgICk6IElVbml0Q29udmVyc2lvblJlc3VsdCB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IEFycmF5LmlzQXJyYXkoYmFzZSkgP1xuICAgICAgICAgICAgdGhpcy5jb252ZXJ0Tm9uTGluZWFyKHZhbHVlLCBiYXNlKSA6XG4gICAgICAgICAgICB0aGlzLmNvbnZlcnRMaW5lYXIodmFsdWUsIGJhc2UpO1xuXG4gICAgICAgIGxldCBzdHJWYWx1ZTogc3RyaW5nO1xuXG4gICAgICAgIGlmICh2YWx1ZSAhPT0gMCkge1xuICAgICAgICAgICAgc3RyVmFsdWUgPSBwYXJzZUZsb2F0KHJlc3VsdC52YWx1ZS50b0ZpeGVkKHNjYWxlKSkudG9TdHJpbmcoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdC5vcmRlciA9IDA7XG4gICAgICAgICAgICBzdHJWYWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdmFsdWU6IHN0clZhbHVlLFxuICAgICAgICAgICAgb3JkZXI6IHJlc3VsdC5vcmRlcixcbiAgICAgICAgICAgIHNjaWVudGlmaWNOb3RhdGlvbjogdmFsdWU/LnRvRXhwb25lbnRpYWwoc2NhbGUpLFxuICAgICAgICAgICAgc2NhbGUsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZGlzcGxheSBzdHJpbmcgb2YgYSBjb252ZXJzaW9uIHJlc3VsdFxuICAgICAqXG4gICAgICogQHBhcmFtIGNvbnZlcnNpb24gVGhlIHJlc3VsdCBvZiBhbiBpbnZvY2F0aW9uIG9mIHRoaXMgc2VydmljZSdzIGNvbnZlcnQgbWV0aG9kXG4gICAgICogQHBhcmFtIHVuaXQgVGhlIHVuaXQgdXNlZCBpbiB0aGUgY29udmVyc2lvblxuICAgICAqIEBwYXJhbSBwbHVzU2lnbiBXaGV0aGVyIHRvIHByZXBlbmQgdGhlIGRpc3BsYXkgc3RyaW5nIHdpdGggYSAnKydcbiAgICAgKiBAcGFyYW0gbmFuRGlzcGxheSBUaGUgc3RyaW5nIHRvIGRpc3BsYXkgaW4gY2FzZSB0aGUgY29udmVyc2lvbiByZXN1bHQgaXMgTmFOIG9yIEluZmluaXR5XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZGlzcGxheSBzdHJpbmcgb2YgdGhlIGNvbnZlcnNpb24gcmVzdWx0XG4gICAgICovXG4gICAgcHVibGljIGdldEZ1bGxEaXNwbGF5KFxuICAgICAgICBjb252ZXJzaW9uOiBJVW5pdENvbnZlcnNpb25SZXN1bHQsXG4gICAgICAgIHVuaXQ6IFVuaXRPcHRpb24sXG4gICAgICAgIHBsdXNTaWduID0gZmFsc2UsXG4gICAgICAgIG5hbkRpc3BsYXkgPSBcIi0tLVwiXG4gICAgKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgaXNWYWxpZE51bWJlciA9IHRoaXMuaXNWYWxpZE51bWJlcihjb252ZXJzaW9uLnZhbHVlKTtcbiAgICAgICAgY29uc3Qgc3BhY2luZyA9IHVuaXQgIT09IFwiZ2VuZXJpY1wiICYmIGlzVmFsaWROdW1iZXIgPyBcIiBcIiA6IFwiXCI7XG4gICAgICAgIGxldCB1bml0RGlzcGxheSA9IGlzVmFsaWROdW1iZXJcbiAgICAgICAgICAgID8gdGhpcy5nZXRVbml0RGlzcGxheShjb252ZXJzaW9uLCB1bml0KVxuICAgICAgICAgICAgOiBcIlwiO1xuXG4gICAgICAgIC8vIFRoZSBnZW5lcmljIHVuaXQgaXMgbm90IGN1cnJlbnRseSBpMThuIGZyaWVuZGx5XG4gICAgICAgIGNvbnN0IGxvY2FsaXplVmFsdWUgPSB1bml0ICE9PSBcImdlbmVyaWNcIjtcblxuICAgICAgICBsZXQgZGlzcGxheVZhbHVlOiBzdHJpbmc7XG5cbiAgICAgICAgaWYgKCF1bml0RGlzcGxheSAmJiBpc1ZhbGlkTnVtYmVyICYmIGNvbnZlcnNpb24ub3JkZXIpIHtcbiAgICAgICAgICAgIHVuaXREaXNwbGF5ID0gdGhpcy5nZXRVbml0RGlzcGxheUJhc2VWYWx1ZSh1bml0KTtcbiAgICAgICAgICAgIGRpc3BsYXlWYWx1ZSA9IHRoaXMuZ2V0U2NpZW50aWZpY0Rpc3BsYXkoXG4gICAgICAgICAgICAgICAgY29udmVyc2lvbixcbiAgICAgICAgICAgICAgICBwbHVzU2lnbixcbiAgICAgICAgICAgICAgICBuYW5EaXNwbGF5XG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGlzcGxheVZhbHVlID0gdGhpcy5nZXRWYWx1ZURpc3BsYXkoXG4gICAgICAgICAgICAgICAgY29udmVyc2lvbixcbiAgICAgICAgICAgICAgICBwbHVzU2lnbixcbiAgICAgICAgICAgICAgICBuYW5EaXNwbGF5LFxuICAgICAgICAgICAgICAgIGxvY2FsaXplVmFsdWVcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGAke2Rpc3BsYXlWYWx1ZX0ke3NwYWNpbmd9JHt1bml0RGlzcGxheX1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGNvbnZlcnRlZCB2YWx1ZSBkaXNwbGF5IHN0cmluZ1xuICAgICAqXG4gICAgICogQHBhcmFtIGNvbnZlcnNpb24gVGhlIHJlc3VsdCBvZiBhbiBpbnZvY2F0aW9uIG9mIHRoaXMgc2VydmljZSdzIGNvbnZlcnQgbWV0aG9kXG4gICAgICogQHBhcmFtIHBsdXNTaWduIFdoZXRoZXIgdG8gcHJlcGVuZCB0aGUgZGlzcGxheSBzdHJpbmcgd2l0aCBhICcrJ1xuICAgICAqIEBwYXJhbSBuYW5EaXNwbGF5IFRoZSBzdHJpbmcgdG8gZGlzcGxheSBpbiBjYXNlIHRoZSBjb252ZXJzaW9uIHJlc3VsdCBpcyBOYU4gb3IgSW5maW5pdHlcbiAgICAgKiBAcGFyYW0gbG9jYWxpemUgV2hldGhlciB0byBsb2NhbGl6ZSB0aGUgdmFsdWUgZm9yIGRpc3BsYXkuIE5vdGU6IEl0J3Mgbm90IHJlY29tbWVuZGVkIHRvIGxvY2FsaXplIHZhbHVlcyBmb3JcbiAgICAgKiAgICAgICAgICAgICAgICAgdGhlIFwiZ2VuZXJpY1wiIHVuaXQsIGUuZy4gXCIxLjFLXCIgZm9yIDExMDAsIGFzIHRoZSBcImdlbmVyaWNcIiB1bml0IGlzIGN1cnJlbnRseSBub3QgaTE4biBmcmllbmRseVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGNvbnZlcnRlZCB2YWx1ZSBkaXNwbGF5IHN0cmluZ1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXRWYWx1ZURpc3BsYXkoXG4gICAgICAgIGNvbnZlcnNpb246IElVbml0Q29udmVyc2lvblJlc3VsdCxcbiAgICAgICAgcGx1c1NpZ24gPSBmYWxzZSxcbiAgICAgICAgbmFuRGlzcGxheSA9IFwiLS0tXCIsXG4gICAgICAgIGxvY2FsaXplID0gdHJ1ZVxuICAgICk6IHN0cmluZyB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkTnVtYmVyKGNvbnZlcnNpb24udmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gbmFuRGlzcGxheTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG91dHB1dFZhbHVlID0gbG9jYWxpemVcbiAgICAgICAgICAgID8gcGFyc2VGbG9hdChjb252ZXJzaW9uLnZhbHVlKS50b0xvY2FsZVN0cmluZyh1bmRlZmluZWQsIHtcbiAgICAgICAgICAgICAgICAgIG1heGltdW1GcmFjdGlvbkRpZ2l0czogY29udmVyc2lvbi5zY2FsZSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIDogY29udmVyc2lvbi52YWx1ZTtcbiAgICAgICAgY29uc3QgcHJlZml4ID1cbiAgICAgICAgICAgIHBsdXNTaWduICYmIHBhcnNlSW50KGNvbnZlcnNpb24udmFsdWUsIDEwKSA+IDAgPyBcIitcIiA6IFwiXCI7XG4gICAgICAgIHJldHVybiBgJHtwcmVmaXh9JHtvdXRwdXRWYWx1ZX1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGNvbnZlcnRlZCB1bml0IGRpc3BsYXkgc3RyaW5nXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY29udmVyc2lvbiBUaGUgcmVzdWx0IG9mIGFuIGludm9jYXRpb24gb2YgdGhpcyBzZXJ2aWNlJ3MgY29udmVydCBtZXRob2RcbiAgICAgKiBAcGFyYW0gdW5pdCBUaGUgYmFzaWMgdW5pdCB1c2VkIGluIHRoZSBjb252ZXJzaW9uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgY29udmVydGVkIHVuaXQgZGlzcGxheSBzdHJpbmdcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0VW5pdERpc3BsYXkoXG4gICAgICAgIGNvbnZlcnNpb246IElVbml0Q29udmVyc2lvblJlc3VsdCxcbiAgICAgICAgdW5pdDogVW5pdE9wdGlvblxuICAgICk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB1bml0Q29udmVyc2lvbkNvbnN0YW50c1t1bml0XVtjb252ZXJzaW9uLm9yZGVyXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBiYXNlIHZhbHVlIG9mIHRoZSBjb252ZXJ0ZWQgdW5pdFxuICAgICAqXG4gICAgICogQHBhcmFtIHVuaXQgVGhlIGJhc2ljIHVuaXQgdXNlZCBpbiB0aGUgY29udmVyc2lvblxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGFiYnJldmlhdGlvbiBmb3IgdGhlIHNtYWxsZXN0IHVuaXQgb2YgdGhlIHByb3ZpZGVkIFVuaXRPcHRpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0VW5pdERpc3BsYXlCYXNlVmFsdWUodW5pdDogVW5pdE9wdGlvbik6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB1bml0Q29udmVyc2lvbkNvbnN0YW50c1t1bml0XVswXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBjb252ZXJ0ZWQgdmFsdWUgZGlzcGxheSBzdHJpbmcgaW4gc2NpZW50aWZpYyBub3RhdGlvblxuICAgICAqXG4gICAgICogQHBhcmFtIGNvbnZlcnNpb24gVGhlIHJlc3VsdCBvZiBhbiBpbnZvY2F0aW9uIG9mIHRoaXMgc2VydmljZSdzIGNvbnZlcnQgbWV0aG9kXG4gICAgICogQHBhcmFtIHBsdXNTaWduIFdoZXRoZXIgdG8gcHJlcGVuZCB0aGUgZGlzcGxheSBzdHJpbmcgd2l0aCBhICcrJ1xuICAgICAqIEBwYXJhbSBuYW5EaXNwbGF5IFRoZSBzdHJpbmcgdG8gZGlzcGxheSBpbiBjYXNlIHRoZSBjb252ZXJzaW9uIHJlc3VsdCBpcyBOYU4gb3IgSW5maW5pdHlcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjb252ZXJ0ZWQgdmFsdWUgZGlzcGxheSBzdHJpbmcgaW4gc2NpZW50aWZpYyBub3RhdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTY2llbnRpZmljRGlzcGxheShcbiAgICAgICAgY29udmVyc2lvbjogSVVuaXRDb252ZXJzaW9uUmVzdWx0LFxuICAgICAgICBwbHVzU2lnbiA9IGZhbHNlLFxuICAgICAgICBuYW5EaXNwbGF5ID0gXCItLS1cIlxuICAgICk6IHN0cmluZyB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkTnVtYmVyKGNvbnZlcnNpb24udmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gbmFuRGlzcGxheTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwcmVmaXggPVxuICAgICAgICAgICAgcGx1c1NpZ24gJiYgcGFyc2VJbnQoY29udmVyc2lvbi52YWx1ZSwgMTApID4gMCA/IFwiK1wiIDogXCJcIjtcblxuICAgICAgICByZXR1cm4gYCR7cHJlZml4fSR7Y29udmVyc2lvbi5zY2llbnRpZmljTm90YXRpb259YDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGlzVmFsaWROdW1iZXIodmFsdWU6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gIWlzTmFOKHBhcnNlRmxvYXQodmFsdWUpKSAmJiBpc0Zpbml0ZShwYXJzZUludCh2YWx1ZSwgMTApKTtcbiAgICB9XG59XG4iXX0=