@nova-ui/bits
Version:
SolarWinds Nova Framework
330 lines (328 loc) • 43.5 kB
JavaScript
// © 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 { DOCUMENT, isPlatformBrowser } from "@angular/common";
import { Inject, Injectable, PLATFORM_ID } from "@angular/core";
import forOwn from "lodash/forOwn";
import includes from "lodash/includes";
import isBoolean from "lodash/isBoolean";
import isDate from "lodash/isDate";
import isFunction from "lodash/isFunction";
import isNil from "lodash/isNil";
import isNumber from "lodash/isNumber";
import isObject from "lodash/isObject";
import isString from "lodash/isString";
import * as i0 from "@angular/core";
/** @ignore */
var ByteCount;
(function (ByteCount) {
ByteCount[ByteCount["String"] = 2] = "String";
ByteCount[ByteCount["Boolean"] = 4] = "Boolean";
ByteCount[ByteCount["Number"] = 8] = "Number";
})(ByteCount || (ByteCount = {}));
/** @ignore */
export var BrowserName;
(function (BrowserName) {
BrowserName["Chrome"] = "Chrome";
BrowserName["Edge"] = "Edge";
BrowserName["Firefox"] = "Firefox";
BrowserName["Opera"] = "Opera";
BrowserName["Safari"] = "Safari";
})(BrowserName || (BrowserName = {}));
/**
* Service providing common utilities
*/
/**
* @dynamic
* @ignore
*/
export class UtilService {
static getSvgFromString(s) {
const div = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
div.innerHTML = `<svg xmlns='http://www.w3.org/2000/svg'>${s}</svg>`;
const frag = document.createDocumentFragment();
while (div.firstChild?.firstChild) {
frag.appendChild(div.firstChild.firstChild);
}
return frag;
}
static getEventPath(event) {
if (isFunction(event.composedPath)) {
return event.composedPath();
}
let element = event.target;
// Hack for EDGE
if (!element.path) {
element = event.currentTarget;
}
const path = [];
while (element) {
path.push(element);
if (element.tagName === "HTML") {
path.push(document);
path.push(window);
return path;
}
element = element.parentElement;
}
return [];
}
isBrowser() {
return isPlatformBrowser(this.platformId);
}
/**
* Object for getting information about the browser
*/
get browser() {
if (this.isBrowser()) {
return {
name: () => this.browserName,
version: () => this.getBrowserVersion(),
isChrome: () => this.browserName === BrowserName.Chrome,
isEdge: () => this.browserName === BrowserName.Edge,
isFirefox: () => this.browserName === BrowserName.Firefox,
isOpera: () => this.browserName === BrowserName.Opera,
isSafari: () => this.browserName === BrowserName.Safari,
mobileDevice: {
isAndroid: () => this.document.defaultView?.navigator.userAgent.match(/Android/i) !== null,
isBlackberry: () => this.document.defaultView?.navigator.userAgent.match(/BlackBerry|BB10/i) !== null,
isIOS: () => this.document.defaultView?.navigator.userAgent.match(/iPhone|iPad|iPod/i) !== null,
isOpera: () => this.document.defaultView?.navigator.userAgent.match(/Opera Mini/i) !== null,
isAny: () => !!(this.browser?.mobileDevice.isIOS() ||
this.browser?.mobileDevice.isAndroid() ||
this.browser?.mobileDevice.isBlackberry() ||
this.browser?.mobileDevice.isOpera()),
},
};
}
}
constructor(document, platformId) {
this.document = document;
this.platformId = platformId;
this.nextUniqueId = ["0", "0", "0"];
/**
* Returns the approximate memory footprint (byte count) of the object specified
*/
this.sizeof = (object) => {
const visitedObjects = [];
return this.calculateSizeof(object, visitedObjects);
};
this.calculateSizeof = (object, visitedObjects) => {
if (isString(object)) {
return object.length * ByteCount.String;
}
else if (isBoolean(object)) {
return ByteCount.Boolean;
}
else if (isNumber(object)) {
return ByteCount.Number;
}
else if (isObject(object)) {
visitedObjects.push(object);
let bytes = 0;
forOwn(object, (value, key) => {
bytes += this.calculateSizeof(key, visitedObjects);
// short-circuit circular refs
if (!includes(visitedObjects, value)) {
bytes += this.calculateSizeof(value, visitedObjects);
}
});
return bytes;
}
else {
return 0;
}
};
this.browserName = this.getBrowser();
}
/**
* Formats the target string in the same way as .NET's String.format
* @param target the target string
* @param params one or more numbers, booleans, or strings to insert
* into the target string at the specified location(s)
* @returns the formatted string
*/
formatString(target, ...params) {
const toString = (obj, format) => {
const ctor = ((o) => {
if (typeof o === "number") {
return Number;
}
else if (typeof o === "boolean") {
return Boolean;
}
else if (typeof o === "string") {
return String;
}
else {
return o.constructor;
}
})(obj);
const proto = ctor.prototype;
const formatter = typeof obj !== "string"
? proto
? proto.format || proto.toString
: obj.format || obj.toString
: obj.toString;
if (formatter) {
if (typeof format === "undefined" || format === "") {
return formatter.call(obj);
}
else {
return formatter.call(obj, format);
}
}
else {
return "";
}
};
target = target.replace(/\{\{|\}\}|\{([^}: ]+?)(?::([^}]*?))?\}/g, (match, num, format) => {
if (match === "{{") {
return "{";
}
if (match === "}}") {
return "}";
}
if (typeof params[num] !== "undefined" &&
params[num] !== null) {
return toString(params[num], format);
}
else {
return "";
}
});
return target;
}
getBrowser() {
if (isPlatformBrowser(this.platformId)) {
const ua = this.document.defaultView?.navigator.userAgent;
if (isNil(ua)) {
throw new Error("UserAgent is not available");
}
let tem;
let M = ua.match(/(edge|opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (M[1] === "Chrome") {
tem = ua.match(/\bOPR\/(\d+)/);
if (tem != null) {
return BrowserName.Opera;
}
tem = ua.match(/\bEdge\/(\d+)/);
if (tem != null) {
return BrowserName.Edge;
}
}
M = ((M[2]
? [M[1], M[2]]
: [
this.document.defaultView?.navigator.appName,
this.document.defaultView?.navigator.appVersion,
"-?",
]));
if ((tem = ua.match(/version\/(\d+)/i)) != null) {
M.splice(1, 1, tem[1]);
}
return M[0];
}
}
getBrowserVersion() {
if (isPlatformBrowser(this.platformId)) {
const ua = this.document.defaultView?.navigator.userAgent;
if (isNil(ua)) {
throw new Error("UserAgent is not available");
}
let tem, M = ua.match(/(edge|opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return tem[1] || "";
}
if (M[1] === "Chrome") {
tem = ua.match(/\bOPR\/(\d+)/);
if (tem != null) {
return tem[1];
}
tem = ua.match(/\bEdge\/(\d+)/);
if (tem != null) {
return tem[1];
}
}
M = ((M[2]
? [M[1], M[2]]
: [
this.document.defaultView?.navigator.appName,
this.document.defaultView?.navigator.appVersion,
"-?",
]));
if ((tem = ua.match(/version\/(\d+)/i)) != null) {
M.splice(1, 1, tem[1]);
}
return M[1];
}
}
/**
* nextUid, from angular.js.
* A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
* characters such as "012ABC". The reason why we are not using simply a number counter is that
* the number string gets longer over time, and it can also overflow, where as the nextId
* will grow much slower, it is a string, and it will never overflow.
*
*/
nextUid() {
let index = this.nextUniqueId.length;
let digit;
while (index) {
index--;
digit = this.nextUniqueId[index].charCodeAt(0);
if (digit === 57 /* "9" */) {
this.nextUniqueId[index] = "A";
return this.nextUniqueId.join("");
}
if (digit === 90 /* "Z" */) {
this.nextUniqueId[index] = "0";
}
else {
this.nextUniqueId[index] = String.fromCharCode(digit + 1);
return this.nextUniqueId.join("");
}
}
this.nextUniqueId.unshift("0");
return this.nextUniqueId.join("");
}
dateEquals(date1, date2) {
if (isNil(date1) && isNil(date2)) {
return date1 === date2;
}
if (!isDate(date1) || !isDate(date2)) {
return false;
}
return date1?.valueOf() === date2?.valueOf();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilService, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilService, providedIn: "root" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilService, decorators: [{
type: Injectable,
args: [{ providedIn: "root" }]
}], ctorParameters: () => [{ type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3V0aWwuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUFFLFFBQVEsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzlELE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRSxPQUFPLE1BQU0sTUFBTSxlQUFlLENBQUM7QUFDbkMsT0FBTyxRQUFRLE1BQU0saUJBQWlCLENBQUM7QUFDdkMsT0FBTyxTQUFTLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxNQUFNLE1BQU0sZUFBZSxDQUFDO0FBQ25DLE9BQU8sVUFBVSxNQUFNLG1CQUFtQixDQUFDO0FBQzNDLE9BQU8sS0FBSyxNQUFNLGNBQWMsQ0FBQztBQUNqQyxPQUFPLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQztBQUN2QyxPQUFPLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQztBQUN2QyxPQUFPLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQzs7QUFFdkMsY0FBYztBQUNkLElBQUssU0FJSjtBQUpELFdBQUssU0FBUztJQUNWLDZDQUFVLENBQUE7SUFDViwrQ0FBVyxDQUFBO0lBQ1gsNkNBQVUsQ0FBQTtBQUNkLENBQUMsRUFKSSxTQUFTLEtBQVQsU0FBUyxRQUliO0FB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Q0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDbEMsT0FBTyxLQUFLLENBQUM7U0FDaEI7UUFFRCxPQUFPLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUM7SUFDakQsQ0FBQzsrR0E1VFEsV0FBVyxrQkEwRlIsUUFBUSxhQUNSLFdBQVc7bUhBM0ZkLFdBQVcsY0FERSxNQUFNOzs0RkFDbkIsV0FBVztrQkFEdkIsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7OzBCQTJGekIsTUFBTTsyQkFBQyxRQUFROzswQkFDZixNQUFNOzJCQUFDLFdBQVciLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHsgRE9DVU1FTlQsIGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBQTEFURk9STV9JRCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgZm9yT3duIGZyb20gXCJsb2Rhc2gvZm9yT3duXCI7XG5pbXBvcnQgaW5jbHVkZXMgZnJvbSBcImxvZGFzaC9pbmNsdWRlc1wiO1xuaW1wb3J0IGlzQm9vbGVhbiBmcm9tIFwibG9kYXNoL2lzQm9vbGVhblwiO1xuaW1wb3J0IGlzRGF0ZSBmcm9tIFwibG9kYXNoL2lzRGF0ZVwiO1xuaW1wb3J0IGlzRnVuY3Rpb24gZnJvbSBcImxvZGFzaC9pc0Z1bmN0aW9uXCI7XG5pbXBvcnQgaXNOaWwgZnJvbSBcImxvZGFzaC9pc05pbFwiO1xuaW1wb3J0IGlzTnVtYmVyIGZyb20gXCJsb2Rhc2gvaXNOdW1iZXJcIjtcbmltcG9ydCBpc09iamVjdCBmcm9tIFwibG9kYXNoL2lzT2JqZWN0XCI7XG5pbXBvcnQgaXNTdHJpbmcgZnJvbSBcImxvZGFzaC9pc1N0cmluZ1wiO1xuXG4vKiogQGlnbm9yZSAqL1xuZW51bSBCeXRlQ291bnQge1xuICAgIFN0cmluZyA9IDIsXG4gICAgQm9vbGVhbiA9IDQsXG4gICAgTnVtYmVyID0gOCxcbn1cblxuLyoqIEBpZ25vcmUgKi9cbmV4cG9ydCBlbnVtIEJyb3dzZXJOYW1lIHtcbiAgICBDaHJvbWUgPSBcIkNocm9tZVwiLFxuICAgIEVkZ2UgPSBcIkVkZ2VcIixcbiAgICBGaXJlZm94ID0gXCJGaXJlZm94XCIsXG4gICAgT3BlcmEgPSBcIk9wZXJhXCIsXG4gICAgU2FmYXJpID0gXCJTYWZhcmlcIixcbn1cblxuLyoqIEBpZ25vcmUgKi9cbmV4cG9ydCBpbnRlcmZhY2UgQnJvd3NlckluZm8ge1xuICAgIG5hbWUoKTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIHZlcnNpb24oKTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIGlzQ2hyb21lKCk6IGJvb2xlYW47XG4gICAgaXNFZGdlKCk6IGJvb2xlYW47XG4gICAgaXNGaXJlZm94KCk6IGJvb2xlYW47XG4gICAgaXNPcGVyYSgpOiBib29sZWFuO1xuICAgIGlzU2FmYXJpKCk6IGJvb2xlYW47XG4gICAgbW9iaWxlRGV2aWNlOiB7XG4gICAgICAgIGlzQW5kcm9pZCgpOiBib29sZWFuO1xuICAgICAgICBpc0JsYWNrYmVycnkoKTogYm9vbGVhbjtcbiAgICAgICAgaXNJT1MoKTogYm9vbGVhbjtcbiAgICAgICAgaXNPcGVyYSgpOiBib29sZWFuO1xuICAgICAgICBpc0FueSgpOiBib29sZWFuO1xuICAgIH07XG59XG5cbi8qKlxuICogU2VydmljZSBwcm92aWRpbmcgY29tbW9uIHV0aWxpdGllc1xuICovXG5cbi8qKlxuICogQGR5bmFtaWNcbiAqIEBpZ25vcmVcbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiBcInJvb3RcIiB9KVxuZXhwb3J0IGNsYXNzIFV0aWxTZXJ2aWNlIHtcbiAgICBwdWJsaWMgc3RhdGljIGdldFN2Z0Zyb21TdHJpbmcoczogc3RyaW5nKTogRG9jdW1lbnRGcmFnbWVudCB7XG4gICAgICAgIGNvbnN0IGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcbiAgICAgICAgICAgIFwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbFwiLFxuICAgICAgICAgICAgXCJkaXZcIlxuICAgICAgICApO1xuICAgICAgICBkaXYuaW5uZXJIVE1MID0gYDxzdmcgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz4ke3N9PC9zdmc+YDtcbiAgICAgICAgY29uc3QgZnJhZyA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcbiAgICAgICAgd2hpbGUgKGRpdi5maXJzdENoaWxkPy5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICBmcmFnLmFwcGVuZENoaWxkKGRpdi5maXJzdENoaWxkLmZpcnN0Q2hpbGQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmcmFnO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0RXZlbnRQYXRoKGV2ZW50OiBNb3VzZUV2ZW50KTogRXZlbnRUYXJnZXRbXSB7XG4gICAgICAgIGlmIChpc0Z1bmN0aW9uKGV2ZW50LmNvbXBvc2VkUGF0aCkpIHtcbiAgICAgICAgICAgIHJldHVybiBldmVudC5jb21wb3NlZFBhdGgoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBlbGVtZW50OiBIVE1MRWxlbWVudCB8IG51bGwgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG5cbiAgICAgICAgLy8gSGFjayBmb3IgRURHRVxuICAgICAgICBpZiAoIShlbGVtZW50IGFzIGFueSkucGF0aCkge1xuICAgICAgICAgICAgZWxlbWVudCA9IGV2ZW50LmN1cnJlbnRUYXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXRoID0gW107XG4gICAgICAgIHdoaWxlIChlbGVtZW50KSB7XG4gICAgICAgICAgICBwYXRoLnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lID09PSBcIkhUTUxcIikge1xuICAgICAgICAgICAgICAgIHBhdGgucHVzaChkb2N1bWVudCk7XG4gICAgICAgICAgICAgICAgcGF0aC5wdXNoKHdpbmRvdyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbGVtZW50ID0gZWxlbWVudC5wYXJlbnRFbGVtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHByaXZhdGUgbmV4dFVuaXF1ZUlkID0gW1wiMFwiLCBcIjBcIiwgXCIwXCJdO1xuICAgIHByaXZhdGUgYnJvd3Nlck5hbWU/OiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgaXNCcm93c2VyKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybUlkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPYmplY3QgZm9yIGdldHRpbmcgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGJyb3dzZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGJyb3dzZXIoKTogQnJvd3NlckluZm8gfCB1bmRlZmluZWQge1xuICAgICAgICBpZiAodGhpcy5pc0Jyb3dzZXIoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBuYW1lOiAoKSA9PiB0aGlzLmJyb3dzZXJOYW1lLFxuICAgICAgICAgICAgICAgIHZlcnNpb246ICgpID0+IHRoaXMuZ2V0QnJvd3NlclZlcnNpb24oKSxcbiAgICAgICAgICAgICAgICBpc0Nocm9tZTogKCkgPT4gdGhpcy5icm93c2VyTmFtZSA9PT0gQnJvd3Nlck5hbWUuQ2hyb21lLFxuICAgICAgICAgICAgICAgIGlzRWRnZTogKCkgPT4gdGhpcy5icm93c2VyTmFtZSA9PT0gQnJvd3Nlck5hbWUuRWRnZSxcbiAgICAgICAgICAgICAgICBpc0ZpcmVmb3g6ICgpID0+IHRoaXMuYnJvd3Nlck5hbWUgPT09IEJyb3dzZXJOYW1lLkZpcmVmb3gsXG4gICAgICAgICAgICAgICAgaXNPcGVyYTogKCkgPT4gdGhpcy5icm93c2VyTmFtZSA9PT0gQnJvd3Nlck5hbWUuT3BlcmEsXG4gICAgICAgICAgICAgICAgaXNTYWZhcmk6ICgpID0+IHRoaXMuYnJvd3Nlck5hbWUgPT09IEJyb3dzZXJOYW1lLlNhZmFyaSxcbiAgICAgICAgICAgICAgICBtb2JpbGVEZXZpY2U6IHtcbiAgICAgICAgICAgICAgICAgICAgaXNBbmRyb2lkOiAoKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kb2N1bWVudC5kZWZhdWx0Vmlldz8ubmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvQW5kcm9pZC9pXG4gICAgICAgICAgICAgICAgICAgICAgICApICE9PSBudWxsLFxuICAgICAgICAgICAgICAgICAgICBpc0JsYWNrYmVycnk6ICgpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3Py5uYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC9CbGFja0JlcnJ5fEJCMTAvaVxuICAgICAgICAgICAgICAgICAgICAgICAgKSAhPT0gbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgaXNJT1M6ICgpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3Py5uYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC9pUGhvbmV8aVBhZHxpUG9kL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICkgIT09IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIGlzT3BlcmE6ICgpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3Py5uYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC9PcGVyYSBNaW5pL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICkgIT09IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIGlzQW55OiAoKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgISEoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5icm93c2VyPy5tb2JpbGVEZXZpY2UuaXNJT1MoKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnJvd3Nlcj8ubW9iaWxlRGV2aWNlLmlzQW5kcm9pZCgpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5icm93c2VyPy5tb2JpbGVEZXZpY2UuaXNCbGFja2JlcnJ5KCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJyb3dzZXI/Lm1vYmlsZURldmljZS5pc09wZXJhKClcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQsXG4gICAgICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgcGxhdGZvcm1JZDogb2JqZWN0XG4gICAgKSB7XG4gICAgICAgIHRoaXMuYnJvd3Nlck5hbWUgPSB0aGlzLmdldEJyb3dzZXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXRzIHRoZSB0YXJnZXQgc3RyaW5nIGluIHRoZSBzYW1lIHdheSBhcyAuTkVUJ3MgU3RyaW5nLmZvcm1hdFxuICAgICAqIEBwYXJhbSAgdGFyZ2V0IHRoZSB0YXJnZXQgc3RyaW5nXG4gICAgICogQHBhcmFtICBwYXJhbXMgb25lIG9yIG1vcmUgbnVtYmVycywgYm9vbGVhbnMsIG9yIHN0cmluZ3MgdG8gaW5zZXJ0XG4gICAgICogICAgIGludG8gdGhlIHRhcmdldCBzdHJpbmcgYXQgdGhlIHNwZWNpZmllZCBsb2NhdGlvbihzKVxuICAgICAqIEByZXR1cm5zIHRoZSBmb3JtYXR0ZWQgc3RyaW5nXG4gICAgICovXG4gICAgcHVibGljIGZvcm1hdFN0cmluZyh0YXJnZXQ6IHN0cmluZywgLi4ucGFyYW1zOiBBcnJheTxhbnk+KTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgdG9TdHJpbmcgPSAob2JqOiBhbnksIGZvcm1hdDogYW55KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjdG9yID0gKChvOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG8gPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE51bWJlcjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBvID09PSBcImJvb2xlYW5cIikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gQm9vbGVhbjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG8uY29uc3RydWN0b3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkob2JqKTtcbiAgICAgICAgICAgIGNvbnN0IHByb3RvID0gY3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICBjb25zdCBmb3JtYXR0ZXIgPVxuICAgICAgICAgICAgICAgIHR5cGVvZiBvYmogIT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgICAgICAgPyBwcm90b1xuICAgICAgICAgICAgICAgICAgICAgICAgPyBwcm90by5mb3JtYXQgfHwgcHJvdG8udG9TdHJpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogb2JqLmZvcm1hdCB8fCBvYmoudG9TdHJpbmdcbiAgICAgICAgICAgICAgICAgICAgOiBvYmoudG9TdHJpbmc7XG4gICAgICAgICAgICBpZiAoZm9ybWF0dGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXQgPT09IFwidW5kZWZpbmVkXCIgfHwgZm9ybWF0ID09PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmb3JtYXR0ZXIuY2FsbChvYmopO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmb3JtYXR0ZXIuY2FsbChvYmosIGZvcm1hdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0YXJnZXQgPSB0YXJnZXQucmVwbGFjZShcbiAgICAgICAgICAgIC9cXHtcXHt8XFx9XFx9fFxceyhbXn06IF0rPykoPzo6KFtefV0qPykpP1xcfS9nLFxuICAgICAgICAgICAgKG1hdGNoLCBudW0sIGZvcm1hdCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChtYXRjaCA9PT0gXCJ7e1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIntcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoID09PSBcIn19XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwifVwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIHR5cGVvZiBwYXJhbXNbbnVtXSAhPT0gXCJ1bmRlZmluZWRcIiAmJlxuICAgICAgICAgICAgICAgICAgICBwYXJhbXNbbnVtXSAhPT0gbnVsbFxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcocGFyYW1zW251bV0sIGZvcm1hdCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRCcm93c2VyKCkge1xuICAgICAgICBpZiAoaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybUlkKSkge1xuICAgICAgICAgICAgY29uc3QgdWEgPSB0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3Py5uYXZpZ2F0b3IudXNlckFnZW50O1xuXG4gICAgICAgICAgICBpZiAoaXNOaWwodWEpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVXNlckFnZW50IGlzIG5vdCBhdmFpbGFibGVcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCB0ZW07XG4gICAgICAgICAgICBsZXQgTTogUmVnRXhwTWF0Y2hBcnJheSB8IFtdID1cbiAgICAgICAgICAgICAgICB1YS5tYXRjaChcbiAgICAgICAgICAgICAgICAgICAgLyhlZGdlfG9wZXJhfGNocm9tZXxzYWZhcml8ZmlyZWZveHxtc2llfHRyaWRlbnQoPz1cXC8pKVxcLz9cXHMqKFxcZCspL2lcbiAgICAgICAgICAgICAgICApIHx8IFtdO1xuICAgICAgICAgICAgaWYgKE1bMV0gPT09IFwiQ2hyb21lXCIpIHtcbiAgICAgICAgICAgICAgICB0ZW0gPSB1YS5tYXRjaCgvXFxiT1BSXFwvKFxcZCspLyk7XG4gICAgICAgICAgICAgICAgaWYgKHRlbSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBCcm93c2VyTmFtZS5PcGVyYTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGVtID0gdWEubWF0Y2goL1xcYkVkZ2VcXC8oXFxkKykvKTtcbiAgICAgICAgICAgICAgICBpZiAodGVtICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEJyb3dzZXJOYW1lLkVkZ2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgTSA9IDxSZWdFeHBNYXRjaEFycmF5PihcbiAgICAgICAgICAgICAgICAoTVsyXVxuICAgICAgICAgICAgICAgICAgICA/IFtNWzFdLCBNWzJdXVxuICAgICAgICAgICAgICAgICAgICA6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kb2N1bWVudC5kZWZhdWx0Vmlldz8ubmF2aWdhdG9yLmFwcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZG9jdW1lbnQuZGVmYXVsdFZpZXc/Lm5hdmlnYXRvci5hcHBWZXJzaW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBcIi0/XCIsXG4gICAgICAgICAgICAgICAgICAgICAgXSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoKHRlbSA9IHVhLm1hdGNoKC92ZXJzaW9uXFwvKFxcZCspL2kpKSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgTS5zcGxpY2UoMSwgMSwgdGVtWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBNWzBdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRCcm93c2VyVmVyc2lvbigpIHtcbiAgICAgICAgaWYgKGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm1JZCkpIHtcbiAgICAgICAgICAgIGNvbnN0IHVhID0gdGhpcy5kb2N1bWVudC5kZWZhdWx0Vmlldz8ubmF2aWdhdG9yLnVzZXJBZ2VudDtcblxuICAgICAgICAgICAgaWYgKGlzTmlsKHVhKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVzZXJBZ2VudCBpcyBub3QgYXZhaWxhYmxlXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgdGVtLFxuICAgICAgICAgICAgICAgIE0gPVxuICAgICAgICAgICAgICAgICAgICB1YS5tYXRjaChcbiAgICAgICAgICAgICAgICAgICAgICAgIC8oZWRnZXxvcGVyYXxjaHJvbWV8c2FmYXJpfGZpcmVmb3h8bXNpZXx0cmlkZW50KD89XFwvKSlcXC8/XFxzKihcXGQrKS9pXG4gICAgICAgICAgICAgICAgICAgICkgfHwgW107XG4gICAgICAgICAgICBpZiAoL3RyaWRlbnQvaS50ZXN0KE1bMV0pKSB7XG4gICAgICAgICAgICAgICAgdGVtID0gL1xcYnJ2WyA6XSsoXFxkKykvZy5leGVjKHVhKSB8fCBbXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGVtWzFdIHx8IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoTVsxXSA9PT0gXCJDaHJvbWVcIikge1xuICAgICAgICAgICAgICAgIHRlbSA9IHVhLm1hdGNoKC9cXGJPUFJcXC8oXFxkKykvKTtcbiAgICAgICAgICAgICAgICBpZiAodGVtICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRlbVsxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGVtID0gdWEubWF0Y2goL1xcYkVkZ2VcXC8oXFxkKykvKTtcbiAgICAgICAgICAgICAgICBpZiAodGVtICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRlbVsxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBNID0gPFJlZ0V4cE1hdGNoQXJyYXk+KFxuICAgICAgICAgICAgICAgIChNWzJdXG4gICAgICAgICAgICAgICAgICAgID8gW01bMV0sIE1bMl1dXG4gICAgICAgICAgICAgICAgICAgIDogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3Py5uYXZpZ2F0b3IuYXBwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kb2N1bWVudC5kZWZhdWx0Vmlldz8ubmF2aWdhdG9yLmFwcFZlcnNpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFwiLT9cIixcbiAgICAgICAgICAgICAgICAgICAgICBdKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmICgodGVtID0gdWEubWF0Y2goL3ZlcnNpb25cXC8oXFxkKykvaSkpICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBNLnNwbGljZSgxLCAxLCB0ZW1bMV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIE1bMV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBuZXh0VWlkLCBmcm9tIGFuZ3VsYXIuanMuXG4gICAgICogQSBjb25zaXN0ZW50IHdheSBvZiBjcmVhdGluZyB1bmlxdWUgSURzIGluIGFuZ3VsYXIuIFRoZSBJRCBpcyBhIHNlcXVlbmNlIG9mIGFscGhhIG51bWVyaWNcbiAgICAgKiBjaGFyYWN0ZXJzIHN1Y2ggYXMgXCIwMTJBQkNcIi4gVGhlIHJlYXNvbiB3aHkgd2UgYXJlIG5vdCB1c2luZyBzaW1wbHkgYSBudW1iZXIgY291bnRlciBpcyB0aGF0XG4gICAgICogdGhlIG51bWJlciBzdHJpbmcgZ2V0cyBsb25nZXIgb3ZlciB0aW1lLCBhbmQgaXQgY2FuIGFsc28gb3ZlcmZsb3csIHdoZXJlIGFzIHRoZSBuZXh0SWRcbiAgICAgKiB3aWxsIGdyb3cgbXVjaCBzbG93ZXIsIGl0IGlzIGEgc3RyaW5nLCBhbmQgaXQgd2lsbCBuZXZlciBvdmVyZmxvdy5cbiAgICAgKlxuXG4gICAgICovXG4gICAgcHVibGljIG5leHRVaWQoKTogc3RyaW5nIHtcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5uZXh0VW5pcXVlSWQubGVuZ3RoO1xuICAgICAgICBsZXQgZGlnaXQ6IG51bWJlcjtcblxuICAgICAgICB3aGlsZSAoaW5kZXgpIHtcbiAgICAgICAgICAgIGluZGV4LS07XG4gICAgICAgICAgICBkaWdpdCA9IHRoaXMubmV4dFVuaXF1ZUlkW2luZGV4XS5jaGFyQ29kZUF0KDApO1xuXG4gICAgICAgICAgICBpZiAoZGlnaXQgPT09IDU3IC8qIFwiOVwiICovKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uZXh0VW5pcXVlSWRbaW5kZXhdID0gXCJBXCI7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubmV4dFVuaXF1ZUlkLmpvaW4oXCJcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGlnaXQgPT09IDkwIC8qIFwiWlwiICovKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uZXh0VW5pcXVlSWRbaW5kZXhdID0gXCIwXCI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubmV4dFVuaXF1ZUlkW2luZGV4XSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoZGlnaXQgKyAxKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5uZXh0VW5pcXVlSWQuam9pbihcIlwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubmV4dFVuaXF1ZUlkLnVuc2hpZnQoXCIwXCIpO1xuICAgICAgICByZXR1cm4gdGhpcy5uZXh0VW5pcXVlSWQuam9pbihcIlwiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBhcHByb3hpbWF0ZSBtZW1vcnkgZm9vdHByaW50IChieXRlIGNvdW50KSBvZiB0aGUgb2JqZWN0IHNwZWNpZmllZFxuXG4gICAgICovXG4gICAgcHVibGljIHNpemVvZiA9IChvYmplY3Q6IGFueSk6IG51bWJlciA9PiB7XG4gICAgICAgIGNvbnN0IHZpc2l0ZWRPYmplY3RzOiBhbnlbXSA9IFtdO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxjdWxhdGVTaXplb2Yob2JqZWN0LCB2aXNpdGVkT2JqZWN0cyk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgY2FsY3VsYXRlU2l6ZW9mID0gKG9iamVjdDogYW55LCB2aXNpdGVkT2JqZWN0czogYW55W10pOiBudW1iZXIgPT4ge1xuICAgICAgICBpZiAoaXNTdHJpbmcob2JqZWN0KSkge1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdC5sZW5ndGggKiBCeXRlQ291bnQuU3RyaW5nO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQm9vbGVhbihvYmplY3QpKSB7XG4gICAgICAgICAgICByZXR1cm4gQnl0ZUNvdW50LkJvb2xlYW47XG4gICAgICAgIH0gZWxzZSBpZiAoaXNOdW1iZXIob2JqZWN0KSkge1xuICAgICAgICAgICAgcmV0dXJuIEJ5dGVDb3VudC5OdW1iZXI7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICAgICAgdmlzaXRlZE9iamVjdHMucHVzaChvYmplY3QpO1xuICAgICAgICAgICAgbGV0IGJ5dGVzID0gMDtcblxuICAgICAgICAgICAgZm9yT3duKG9iamVjdCwgKHZhbHVlOiBhbnksIGtleTogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgYnl0ZXMgKz0gdGhpcy5jYWxjdWxhdGVTaXplb2Yoa2V5LCB2aXNpdGVkT2JqZWN0cyk7XG4gICAgICAgICAgICAgICAgLy8gc2hvcnQtY2lyY3VpdCBjaXJjdWxhciByZWZzXG4gICAgICAgICAgICAgICAgaWYgKCFpbmNsdWRlcyh2aXNpdGVkT2JqZWN0cywgdmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJ5dGVzICs9IHRoaXMuY2FsY3VsYXRlU2l6ZW9mKHZhbHVlLCB2aXNpdGVkT2JqZWN0cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHJldHVybiBieXRlcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHB1YmxpYyBkYXRlRXF1YWxzKGRhdGUxPzogRGF0ZSwgZGF0ZTI/OiBEYXRlKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChpc05pbChkYXRlMSkgJiYgaXNOaWwoZGF0ZTIpKSB7XG4gICAgICAgICAgICByZXR1cm4gZGF0ZTEgPT09IGRhdGUyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpc0RhdGUoZGF0ZTEpIHx8ICFpc0RhdGUoZGF0ZTIpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZGF0ZTE/LnZhbHVlT2YoKSA9PT0gZGF0ZTI/LnZhbHVlT2YoKTtcbiAgICB9XG59XG4iXX0=