/*! * ONNX Runtime Web v1.26.0 * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ "use strict"; var ort = (() => { var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw Error('Dynamic require of "' + x + '" is not supported'); }); var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // common/dist/esm/backend-impl.js var backends, backendsSortedByPriority, registerBackend, tryResolveAndInitializeBackend, resolveBackendAndExecutionProviders; var init_backend_impl = __esm({ "common/dist/esm/backend-impl.js"() { "use strict"; backends = /* @__PURE__ */ new Map(); backendsSortedByPriority = []; registerBackend = (name, backend, priority) => { if (backend && typeof backend.init === "function" && typeof backend.createInferenceSessionHandler === "function") { const currentBackend = backends.get(name); if (currentBackend === void 0) { backends.set(name, { backend, priority }); } else if (currentBackend.priority > priority) { return; } else if (currentBackend.priority === priority) { if (currentBackend.backend !== backend) { throw new Error(`cannot register backend "${name}" using priority ${priority}`); } } if (priority >= 0) { const i = backendsSortedByPriority.indexOf(name); if (i !== -1) { backendsSortedByPriority.splice(i, 1); } for (let i2 = 0; i2 < backendsSortedByPriority.length; i2++) { if (backends.get(backendsSortedByPriority[i2]).priority <= priority) { backendsSortedByPriority.splice(i2, 0, name); return; } } backendsSortedByPriority.push(name); } return; } throw new TypeError("not a valid backend"); }; tryResolveAndInitializeBackend = async (backendName) => { const backendInfo = backends.get(backendName); if (!backendInfo) { return "backend not found."; } if (backendInfo.initialized) { return backendInfo.backend; } else if (backendInfo.aborted) { return backendInfo.error; } else { const isInitializing = !!backendInfo.initPromise; try { if (!isInitializing) { backendInfo.initPromise = backendInfo.backend.init(backendName); } await backendInfo.initPromise; backendInfo.initialized = true; return backendInfo.backend; } catch (e) { if (!isInitializing) { backendInfo.error = `${e}`; backendInfo.aborted = true; } return backendInfo.error; } finally { delete backendInfo.initPromise; } } }; resolveBackendAndExecutionProviders = async (options) => { const eps = options.executionProviders || []; const backendHints = eps.map((i) => typeof i === "string" ? i : i.name); const backendNames = backendHints.length === 0 ? backendsSortedByPriority : backendHints; let backend; const errors = []; const availableBackendNames = /* @__PURE__ */ new Set(); for (const backendName of backendNames) { const resolveResult = await tryResolveAndInitializeBackend(backendName); if (typeof resolveResult === "string") { errors.push({ name: backendName, err: resolveResult }); } else { if (!backend) { backend = resolveResult; } if (backend === resolveResult) { availableBackendNames.add(backendName); } } } if (!backend) { throw new Error(`no available backend found. ERR: ${errors.map((e) => `[${e.name}] ${e.err}`).join(", ")}`); } for (const { name, err } of errors) { if (backendHints.includes(name)) { console.warn(`removing requested execution provider "${name}" from session options because it is not available: ${err}`); } } const filteredEps = eps.filter((i) => availableBackendNames.has(typeof i === "string" ? i : i.name)); return [ backend, new Proxy(options, { get: (target, prop) => { if (prop === "executionProviders") { return filteredEps; } return Reflect.get(target, prop); } }) ]; }; } }); // common/dist/esm/backend.js var init_backend = __esm({ "common/dist/esm/backend.js"() { "use strict"; init_backend_impl(); } }); // common/dist/esm/version.js var version; var init_version = __esm({ "common/dist/esm/version.js"() { "use strict"; version = "1.26.0"; } }); // common/dist/esm/env-impl.js var logLevelValue, env; var init_env_impl = __esm({ "common/dist/esm/env-impl.js"() { "use strict"; init_version(); logLevelValue = "warning"; env = { wasm: {}, webgl: {}, webgpu: {}, versions: { common: version }, set logLevel(value) { if (value === void 0) { return; } if (typeof value !== "string" || ["verbose", "info", "warning", "error", "fatal"].indexOf(value) === -1) { throw new Error(`Unsupported logging level: ${value}`); } logLevelValue = value; }, get logLevel() { return logLevelValue; } }; Object.defineProperty(env, "logLevel", { enumerable: true }); } }); // common/dist/esm/env.js var env2; var init_env = __esm({ "common/dist/esm/env.js"() { "use strict"; init_env_impl(); env2 = env; } }); // common/dist/esm/tensor-conversion-impl.js var tensorToDataURL, tensorToImageData; var init_tensor_conversion_impl = __esm({ "common/dist/esm/tensor-conversion-impl.js"() { "use strict"; tensorToDataURL = (tensor, options) => { const canvas = typeof document !== "undefined" ? document.createElement("canvas") : new OffscreenCanvas(1, 1); canvas.width = tensor.dims[3]; canvas.height = tensor.dims[2]; const pixels2DContext = canvas.getContext("2d"); if (pixels2DContext != null) { let width; let height; if (options?.tensorLayout !== void 0 && options.tensorLayout === "NHWC") { width = tensor.dims[2]; height = tensor.dims[3]; } else { width = tensor.dims[3]; height = tensor.dims[2]; } const inputformat = options?.format !== void 0 ? options.format : "RGB"; const norm = options?.norm; let normMean; let normBias; if (norm === void 0 || norm.mean === void 0) { normMean = [255, 255, 255, 255]; } else { if (typeof norm.mean === "number") { normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; } else { normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 0]; if (norm.mean[3] !== void 0) { normMean[3] = norm.mean[3]; } } } if (norm === void 0 || norm.bias === void 0) { normBias = [0, 0, 0, 0]; } else { if (typeof norm.bias === "number") { normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; } else { normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0]; if (norm.bias[3] !== void 0) { normBias[3] = norm.bias[3]; } } } const stride = height * width; let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; if (inputformat === "RGBA") { rTensorPointer = 0; gTensorPointer = stride; bTensorPointer = stride * 2; aTensorPointer = stride * 3; } else if (inputformat === "RGB") { rTensorPointer = 0; gTensorPointer = stride; bTensorPointer = stride * 2; } else if (inputformat === "RBG") { rTensorPointer = 0; bTensorPointer = stride; gTensorPointer = stride * 2; } for (let i = 0; i < height; i++) { for (let j = 0; j < width; j++) { const R = (tensor.data[rTensorPointer++] - normBias[0]) * normMean[0]; const G = (tensor.data[gTensorPointer++] - normBias[1]) * normMean[1]; const B = (tensor.data[bTensorPointer++] - normBias[2]) * normMean[2]; const A = aTensorPointer === -1 ? 255 : (tensor.data[aTensorPointer++] - normBias[3]) * normMean[3]; pixels2DContext.fillStyle = "rgba(" + R + "," + G + "," + B + "," + A + ")"; pixels2DContext.fillRect(j, i, 1, 1); } } if ("toDataURL" in canvas) { return canvas.toDataURL(); } else { throw new Error("toDataURL is not supported"); } } else { throw new Error("Can not access image data"); } }; tensorToImageData = (tensor, options) => { const pixels2DContext = typeof document !== "undefined" ? document.createElement("canvas").getContext("2d") : new OffscreenCanvas(1, 1).getContext("2d"); let image; if (pixels2DContext != null) { let width; let height; let channels; if (options?.tensorLayout !== void 0 && options.tensorLayout === "NHWC") { width = tensor.dims[2]; height = tensor.dims[1]; channels = tensor.dims[3]; } else { width = tensor.dims[3]; height = tensor.dims[2]; channels = tensor.dims[1]; } const inputformat = options !== void 0 ? options.format !== void 0 ? options.format : "RGB" : "RGB"; const norm = options?.norm; let normMean; let normBias; if (norm === void 0 || norm.mean === void 0) { normMean = [255, 255, 255, 255]; } else { if (typeof norm.mean === "number") { normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; } else { normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 255]; if (norm.mean[3] !== void 0) { normMean[3] = norm.mean[3]; } } } if (norm === void 0 || norm.bias === void 0) { normBias = [0, 0, 0, 0]; } else { if (typeof norm.bias === "number") { normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; } else { normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0]; if (norm.bias[3] !== void 0) { normBias[3] = norm.bias[3]; } } } const stride = height * width; if (options !== void 0) { if (options.format !== void 0 && channels === 4 && options.format !== "RGBA" || channels === 3 && options.format !== "RGB" && options.format !== "BGR") { throw new Error("Tensor format doesn't match input tensor dims"); } } const step = 4; let rImagePointer = 0, gImagePointer = 1, bImagePointer = 2, aImagePointer = 3; let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; if (inputformat === "RGBA") { rTensorPointer = 0; gTensorPointer = stride; bTensorPointer = stride * 2; aTensorPointer = stride * 3; } else if (inputformat === "RGB") { rTensorPointer = 0; gTensorPointer = stride; bTensorPointer = stride * 2; } else if (inputformat === "RBG") { rTensorPointer = 0; bTensorPointer = stride; gTensorPointer = stride * 2; } image = pixels2DContext.createImageData(width, height); for (let i = 0; i < height * width; rImagePointer += step, gImagePointer += step, bImagePointer += step, aImagePointer += step, i++) { image.data[rImagePointer] = (tensor.data[rTensorPointer++] - normBias[0]) * normMean[0]; image.data[gImagePointer] = (tensor.data[gTensorPointer++] - normBias[1]) * normMean[1]; image.data[bImagePointer] = (tensor.data[bTensorPointer++] - normBias[2]) * normMean[2]; image.data[aImagePointer] = aTensorPointer === -1 ? 255 : (tensor.data[aTensorPointer++] - normBias[3]) * normMean[3]; } } else { throw new Error("Can not access image data"); } return image; }; } }); // common/dist/esm/tensor-factory-impl.js var bufferToTensor, tensorFromImage, tensorFromTexture, tensorFromGpuBuffer, tensorFromMLTensor, tensorFromPinnedBuffer; var init_tensor_factory_impl = __esm({ "common/dist/esm/tensor-factory-impl.js"() { "use strict"; init_tensor_impl(); bufferToTensor = (buffer, options) => { if (buffer === void 0) { throw new Error("Image buffer must be defined"); } if (options.height === void 0 || options.width === void 0) { throw new Error("Image height and width must be defined"); } if (options.tensorLayout === "NHWC") { throw new Error("NHWC Tensor layout is not supported yet"); } const { height, width } = options; const norm = options.norm ?? { mean: 255, bias: 0 }; let normMean; let normBias; if (typeof norm.mean === "number") { normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; } else { normMean = [norm.mean[0], norm.mean[1], norm.mean[2], norm.mean[3] ?? 255]; } if (typeof norm.bias === "number") { normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; } else { normBias = [norm.bias[0], norm.bias[1], norm.bias[2], norm.bias[3] ?? 0]; } const inputformat = options.format !== void 0 ? options.format : "RGBA"; const outputformat = options.tensorFormat !== void 0 ? options.tensorFormat !== void 0 ? options.tensorFormat : "RGB" : "RGB"; const stride = height * width; const float32Data = outputformat === "RGBA" ? new Float32Array(stride * 4) : new Float32Array(stride * 3); let step = 4, rImagePointer = 0, gImagePointer = 1, bImagePointer = 2, aImagePointer = 3; let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; if (inputformat === "RGB") { step = 3; rImagePointer = 0; gImagePointer = 1; bImagePointer = 2; aImagePointer = -1; } if (outputformat === "RGBA") { aTensorPointer = stride * 3; } else if (outputformat === "RBG") { rTensorPointer = 0; bTensorPointer = stride; gTensorPointer = stride * 2; } else if (outputformat === "BGR") { bTensorPointer = 0; gTensorPointer = stride; rTensorPointer = stride * 2; } for (let i = 0; i < stride; i++, rImagePointer += step, bImagePointer += step, gImagePointer += step, aImagePointer += step) { float32Data[rTensorPointer++] = (buffer[rImagePointer] + normBias[0]) / normMean[0]; float32Data[gTensorPointer++] = (buffer[gImagePointer] + normBias[1]) / normMean[1]; float32Data[bTensorPointer++] = (buffer[bImagePointer] + normBias[2]) / normMean[2]; if (aTensorPointer !== -1 && aImagePointer !== -1) { float32Data[aTensorPointer++] = (buffer[aImagePointer] + normBias[3]) / normMean[3]; } } const outputTensor = outputformat === "RGBA" ? new Tensor("float32", float32Data, [1, 4, height, width]) : new Tensor("float32", float32Data, [1, 3, height, width]); return outputTensor; }; tensorFromImage = async (image, options) => { const isHTMLImageEle = typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement; const isImageDataEle = typeof ImageData !== "undefined" && image instanceof ImageData; const isImageBitmap = typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap; const isString = typeof image === "string"; let data; let bufferToTensorOptions = options ?? {}; const createCanvas = () => { if (typeof document !== "undefined") { return document.createElement("canvas"); } else if (typeof OffscreenCanvas !== "undefined") { return new OffscreenCanvas(1, 1); } else { throw new Error("Canvas is not supported"); } }; const createCanvasContext = (canvas) => { if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) { return canvas.getContext("2d"); } else if (canvas instanceof OffscreenCanvas) { return canvas.getContext("2d"); } else { return null; } }; if (isHTMLImageEle) { const canvas = createCanvas(); canvas.width = image.width; canvas.height = image.height; const pixels2DContext = createCanvasContext(canvas); if (pixels2DContext != null) { let height = image.height; let width = image.width; if (options !== void 0 && options.resizedHeight !== void 0 && options.resizedWidth !== void 0) { height = options.resizedHeight; width = options.resizedWidth; } if (options !== void 0) { bufferToTensorOptions = options; if (options.tensorFormat !== void 0) { throw new Error("Image input config format must be RGBA for HTMLImageElement"); } else { bufferToTensorOptions.tensorFormat = "RGBA"; } bufferToTensorOptions.height = height; bufferToTensorOptions.width = width; } else { bufferToTensorOptions.tensorFormat = "RGBA"; bufferToTensorOptions.height = height; bufferToTensorOptions.width = width; } pixels2DContext.drawImage(image, 0, 0); data = pixels2DContext.getImageData(0, 0, width, height).data; } else { throw new Error("Can not access image data"); } } else if (isImageDataEle) { let height; let width; if (options !== void 0 && options.resizedWidth !== void 0 && options.resizedHeight !== void 0) { height = options.resizedHeight; width = options.resizedWidth; } else { height = image.height; width = image.width; } if (options !== void 0) { bufferToTensorOptions = options; } bufferToTensorOptions.format = "RGBA"; bufferToTensorOptions.height = height; bufferToTensorOptions.width = width; if (options !== void 0) { const tempCanvas = createCanvas(); tempCanvas.width = width; tempCanvas.height = height; const pixels2DContext = createCanvasContext(tempCanvas); if (pixels2DContext != null) { pixels2DContext.putImageData(image, 0, 0); data = pixels2DContext.getImageData(0, 0, width, height).data; } else { throw new Error("Can not access image data"); } } else { data = image.data; } } else if (isImageBitmap) { if (options === void 0) { throw new Error("Please provide image config with format for Imagebitmap"); } const canvas = createCanvas(); canvas.width = image.width; canvas.height = image.height; const pixels2DContext = createCanvasContext(canvas); if (pixels2DContext != null) { const height = image.height; const width = image.width; pixels2DContext.drawImage(image, 0, 0, width, height); data = pixels2DContext.getImageData(0, 0, width, height).data; bufferToTensorOptions.height = height; bufferToTensorOptions.width = width; return bufferToTensor(data, bufferToTensorOptions); } else { throw new Error("Can not access image data"); } } else if (isString) { return new Promise((resolve, reject) => { const canvas = createCanvas(); const context = createCanvasContext(canvas); if (!image || !context) { return reject(); } const newImage = new Image(); newImage.crossOrigin = "Anonymous"; newImage.src = image; newImage.onload = () => { canvas.width = newImage.width; canvas.height = newImage.height; context.drawImage(newImage, 0, 0, canvas.width, canvas.height); const img = context.getImageData(0, 0, canvas.width, canvas.height); bufferToTensorOptions.height = canvas.height; bufferToTensorOptions.width = canvas.width; resolve(bufferToTensor(img.data, bufferToTensorOptions)); }; }); } else { throw new Error("Input data provided is not supported - aborted tensor creation"); } if (data !== void 0) { return bufferToTensor(data, bufferToTensorOptions); } else { throw new Error("Input data provided is not supported - aborted tensor creation"); } }; tensorFromTexture = (texture, options) => { const { width, height, download, dispose } = options; const dims = [1, height, width, 4]; return new Tensor({ location: "texture", type: "float32", texture, dims, download, dispose }); }; tensorFromGpuBuffer = (gpuBuffer, options) => { const { dataType, dims, download, dispose } = options; return new Tensor({ location: "gpu-buffer", type: dataType ?? "float32", gpuBuffer, dims, download, dispose }); }; tensorFromMLTensor = (mlTensor, options) => { const { dataType, dims, download, dispose } = options; return new Tensor({ location: "ml-tensor", type: dataType ?? "float32", mlTensor, dims, download, dispose }); }; tensorFromPinnedBuffer = (type, buffer, dims) => new Tensor({ location: "cpu-pinned", type, data: buffer, dims: dims ?? [buffer.length] }); } }); // common/dist/esm/tensor-impl-type-mapping.js var NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP, NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP, isTypedArrayChecked, checkTypedArray; var init_tensor_impl_type_mapping = __esm({ "common/dist/esm/tensor-impl-type-mapping.js"() { "use strict"; NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = /* @__PURE__ */ new Map([ ["float32", Float32Array], ["uint8", Uint8Array], ["int8", Int8Array], ["uint16", Uint16Array], ["int16", Int16Array], ["int32", Int32Array], ["bool", Uint8Array], ["float64", Float64Array], ["uint32", Uint32Array], ["int4", Uint8Array], ["uint4", Uint8Array] ]); NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP = /* @__PURE__ */ new Map([ [Float32Array, "float32"], [Uint8Array, "uint8"], [Int8Array, "int8"], [Uint16Array, "uint16"], [Int16Array, "int16"], [Int32Array, "int32"], [Float64Array, "float64"], [Uint32Array, "uint32"] ]); isTypedArrayChecked = false; checkTypedArray = () => { if (!isTypedArrayChecked) { isTypedArrayChecked = true; const isBigInt64ArrayAvailable = typeof BigInt64Array !== "undefined" && BigInt64Array.from; const isBigUint64ArrayAvailable = typeof BigUint64Array !== "undefined" && BigUint64Array.from; const Float16Array2 = globalThis.Float16Array; const isFloat16ArrayAvailable = typeof Float16Array2 !== "undefined" && Float16Array2.from; if (isBigInt64ArrayAvailable) { NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set("int64", BigInt64Array); NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigInt64Array, "int64"); } if (isBigUint64ArrayAvailable) { NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set("uint64", BigUint64Array); NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigUint64Array, "uint64"); } if (isFloat16ArrayAvailable) { NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set("float16", Float16Array2); NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(Float16Array2, "float16"); } else { NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set("float16", Uint16Array); } } }; } }); // common/dist/esm/tensor-utils-impl.js var calculateSize, tensorReshape; var init_tensor_utils_impl = __esm({ "common/dist/esm/tensor-utils-impl.js"() { "use strict"; init_tensor_impl(); calculateSize = (dims) => { let size = 1; for (let i = 0; i < dims.length; i++) { const dim = dims[i]; if (typeof dim !== "number" || !Number.isSafeInteger(dim)) { throw new TypeError(`dims[${i}] must be an integer, got: ${dim}`); } if (dim < 0) { throw new RangeError(`dims[${i}] must be a non-negative integer, got: ${dim}`); } size *= dim; } return size; }; tensorReshape = (tensor, dims) => { switch (tensor.location) { case "cpu": return new Tensor(tensor.type, tensor.data, dims); case "cpu-pinned": return new Tensor({ location: "cpu-pinned", data: tensor.data, type: tensor.type, dims }); case "texture": return new Tensor({ location: "texture", texture: tensor.texture, type: tensor.type, dims }); case "gpu-buffer": return new Tensor({ location: "gpu-buffer", gpuBuffer: tensor.gpuBuffer, type: tensor.type, dims }); case "ml-tensor": return new Tensor({ location: "ml-tensor", mlTensor: tensor.mlTensor, type: tensor.type, dims }); default: throw new Error(`tensorReshape: tensor location ${tensor.location} is not supported`); } }; } }); // common/dist/esm/tensor-impl.js var Tensor; var init_tensor_impl = __esm({ "common/dist/esm/tensor-impl.js"() { "use strict"; init_tensor_conversion_impl(); init_tensor_factory_impl(); init_tensor_impl_type_mapping(); init_tensor_utils_impl(); Tensor = class { /** * implementation. */ constructor(arg0, arg1, arg2) { checkTypedArray(); let type; let dims; if (typeof arg0 === "object" && "location" in arg0) { this.dataLocation = arg0.location; type = arg0.type; dims = arg0.dims; switch (arg0.location) { case "cpu-pinned": { const expectedTypedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(type); if (!expectedTypedArrayConstructor) { throw new TypeError(`unsupported type "${type}" to create tensor from pinned buffer`); } if (!(arg0.data instanceof expectedTypedArrayConstructor)) { throw new TypeError(`buffer should be of type ${expectedTypedArrayConstructor.name}`); } this.cpuData = arg0.data; break; } case "texture": { if (type !== "float32") { throw new TypeError(`unsupported type "${type}" to create tensor from texture`); } this.gpuTextureData = arg0.texture; this.downloader = arg0.download; this.disposer = arg0.dispose; break; } case "gpu-buffer": { if (type !== "float32" && type !== "float16" && type !== "int32" && type !== "int64" && type !== "uint32" && type !== "uint8" && type !== "bool" && type !== "uint4" && type !== "int4") { throw new TypeError(`unsupported type "${type}" to create tensor from gpu buffer`); } this.gpuBufferData = arg0.gpuBuffer; this.downloader = arg0.download; this.disposer = arg0.dispose; break; } case "ml-tensor": { if (type !== "float32" && type !== "float16" && type !== "int32" && type !== "int64" && type !== "uint32" && type !== "uint64" && type !== "int8" && type !== "uint8" && type !== "bool" && type !== "uint4" && type !== "int4") { throw new TypeError(`unsupported type "${type}" to create tensor from MLTensor`); } this.mlTensorData = arg0.mlTensor; this.downloader = arg0.download; this.disposer = arg0.dispose; break; } default: throw new Error(`Tensor constructor: unsupported location '${this.dataLocation}'`); } } else { let data; let maybeDims; if (typeof arg0 === "string") { type = arg0; maybeDims = arg2; if (arg0 === "string") { if (!Array.isArray(arg1)) { throw new TypeError("A string tensor's data must be a string array."); } data = arg1; } else { const typedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(arg0); if (typedArrayConstructor === void 0) { throw new TypeError(`Unsupported tensor type: ${arg0}.`); } if (Array.isArray(arg1)) { if (arg0 === "float16" && typedArrayConstructor === Uint16Array || arg0 === "uint4" || arg0 === "int4") { throw new TypeError(`Creating a ${arg0} tensor from number array is not supported. Please use ${typedArrayConstructor.name} as data.`); } else if (arg0 === "uint64" || arg0 === "int64") { data = typedArrayConstructor.from(arg1, BigInt); } else { data = typedArrayConstructor.from(arg1); } } else if (arg1 instanceof typedArrayConstructor) { data = arg1; } else if (arg1 instanceof Uint8ClampedArray) { if (arg0 === "uint8") { data = Uint8Array.from(arg1); } else { throw new TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`); } } else if (arg0 === "float16" && arg1 instanceof Uint16Array && typedArrayConstructor !== Uint16Array) { data = new globalThis.Float16Array(arg1.buffer, arg1.byteOffset, arg1.length); } else { throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`); } } } else { maybeDims = arg1; if (Array.isArray(arg0)) { if (arg0.length === 0) { throw new TypeError("Tensor type cannot be inferred from an empty array."); } const firstElementType = typeof arg0[0]; if (firstElementType === "string") { type = "string"; data = arg0; } else if (firstElementType === "boolean") { type = "bool"; data = Uint8Array.from(arg0); } else { throw new TypeError(`Invalid element type of data array: ${firstElementType}.`); } } else if (arg0 instanceof Uint8ClampedArray) { type = "uint8"; data = Uint8Array.from(arg0); } else { const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get(arg0.constructor); if (mappedType === void 0) { throw new TypeError(`Unsupported type for tensor data: ${arg0.constructor}.`); } type = mappedType; data = arg0; } } if (maybeDims === void 0) { maybeDims = [data.length]; } else if (!Array.isArray(maybeDims)) { throw new TypeError("A tensor's dims must be a number array"); } dims = maybeDims; this.cpuData = data; this.dataLocation = "cpu"; } const size = calculateSize(dims); if (this.cpuData && size !== this.cpuData.length) { if ((type === "uint4" || type === "int4") && Math.ceil(size / 2) === this.cpuData.length) { } else { throw new Error(`Tensor's size(${size}) does not match data length(${this.cpuData.length}).`); } } this.type = type; this.dims = dims; this.size = size; } // #endregion // #region factory static async fromImage(image, options) { return tensorFromImage(image, options); } static fromTexture(texture, options) { return tensorFromTexture(texture, options); } static fromGpuBuffer(gpuBuffer, options) { return tensorFromGpuBuffer(gpuBuffer, options); } static fromMLTensor(mlTensor, options) { return tensorFromMLTensor(mlTensor, options); } static fromPinnedBuffer(type, buffer, dims) { return tensorFromPinnedBuffer(type, buffer, dims); } // #endregion // #region conversions toDataURL(options) { return tensorToDataURL(this, options); } toImageData(options) { return tensorToImageData(this, options); } // #endregion // #region properties get data() { this.ensureValid(); if (!this.cpuData) { throw new Error("The data is not on CPU. Use `getData()` to download GPU data to CPU, or use `texture` or `gpuBuffer` property to access the GPU data directly."); } return this.cpuData; } get location() { return this.dataLocation; } get texture() { this.ensureValid(); if (!this.gpuTextureData) { throw new Error("The data is not stored as a WebGL texture."); } return this.gpuTextureData; } get gpuBuffer() { this.ensureValid(); if (!this.gpuBufferData) { throw new Error("The data is not stored as a WebGPU buffer."); } return this.gpuBufferData; } get mlTensor() { this.ensureValid(); if (!this.mlTensorData) { throw new Error("The data is not stored as a WebNN MLTensor."); } return this.mlTensorData; } // #endregion // #region methods async getData(releaseData) { this.ensureValid(); switch (this.dataLocation) { case "cpu": case "cpu-pinned": return this.data; case "texture": case "gpu-buffer": case "ml-tensor": { if (!this.downloader) { throw new Error("The current tensor is not created with a specified data downloader."); } if (this.isDownloading) { throw new Error("The current tensor is being downloaded."); } try { this.isDownloading = true; const data = await this.downloader(); this.downloader = void 0; this.dataLocation = "cpu"; this.cpuData = data; if (releaseData && this.disposer) { this.disposer(); this.disposer = void 0; } return data; } finally { this.isDownloading = false; } } default: throw new Error(`cannot get data from location: ${this.dataLocation}`); } } dispose() { if (this.isDownloading) { throw new Error("The current tensor is being downloaded."); } if (this.disposer) { this.disposer(); this.disposer = void 0; } this.cpuData = void 0; this.gpuTextureData = void 0; this.gpuBufferData = void 0; this.mlTensorData = void 0; this.downloader = void 0; this.isDownloading = void 0; this.dataLocation = "none"; } // #endregion // #region tensor utilities ensureValid() { if (this.dataLocation === "none") { throw new Error("The tensor is disposed."); } } reshape(dims) { this.ensureValid(); if (this.downloader || this.disposer) { throw new Error("Cannot reshape a tensor that owns GPU resource."); } return tensorReshape(this, dims); } }; } }); // common/dist/esm/tensor.js var Tensor2; var init_tensor = __esm({ "common/dist/esm/tensor.js"() { "use strict"; init_tensor_impl(); Tensor2 = Tensor; } }); // common/dist/esm/trace.js var TRACE, TRACE_FUNC, TRACE_FUNC_BEGIN, TRACE_FUNC_END, TRACE_EVENT_BEGIN, TRACE_EVENT_END; var init_trace = __esm({ "common/dist/esm/trace.js"() { "use strict"; init_env_impl(); TRACE = (deviceType, label) => { if (typeof env.trace === "undefined" ? !env.wasm.trace : !env.trace) { return; } console.timeStamp(`${deviceType}::ORT::${label}`); }; TRACE_FUNC = (msg, extraMsg) => { const stack = new Error().stack?.split(/\r\n|\r|\n/g) || []; let hasTraceFunc = false; for (let i = 0; i < stack.length; i++) { if (hasTraceFunc && !stack[i].includes("TRACE_FUNC")) { let label = `FUNC_${msg}::${stack[i].trim().split(" ")[1]}`; if (extraMsg) { label += `::${extraMsg}`; } TRACE("CPU", label); return; } if (stack[i].includes("TRACE_FUNC")) { hasTraceFunc = true; } } }; TRACE_FUNC_BEGIN = (extraMsg) => { if (typeof env.trace === "undefined" ? !env.wasm.trace : !env.trace) { return; } TRACE_FUNC("BEGIN", extraMsg); }; TRACE_FUNC_END = (extraMsg) => { if (typeof env.trace === "undefined" ? !env.wasm.trace : !env.trace) { return; } TRACE_FUNC("END", extraMsg); }; TRACE_EVENT_BEGIN = (extraMsg) => { if (typeof env.trace === "undefined" ? !env.wasm.trace : !env.trace) { return; } console.time(`ORT::${extraMsg}`); }; TRACE_EVENT_END = (extraMsg) => { if (typeof env.trace === "undefined" ? !env.wasm.trace : !env.trace) { return; } console.timeEnd(`ORT::${extraMsg}`); }; } }); // common/dist/esm/inference-session-impl.js var InferenceSession; var init_inference_session_impl = __esm({ "common/dist/esm/inference-session-impl.js"() { "use strict"; init_backend_impl(); init_tensor(); init_trace(); InferenceSession = class _InferenceSession { constructor(handler) { this.handler = handler; } async run(feeds, arg1, arg2) { TRACE_FUNC_BEGIN(); TRACE_EVENT_BEGIN("InferenceSession.run"); const fetches = {}; let options = {}; if (typeof feeds !== "object" || feeds === null || feeds instanceof Tensor2 || Array.isArray(feeds)) { throw new TypeError("'feeds' must be an object that use input names as keys and OnnxValue as corresponding values."); } let isFetchesEmpty = true; if (typeof arg1 === "object") { if (arg1 === null) { throw new TypeError("Unexpected argument[1]: cannot be null."); } if (arg1 instanceof Tensor2) { throw new TypeError("'fetches' cannot be a Tensor"); } if (Array.isArray(arg1)) { if (arg1.length === 0) { throw new TypeError("'fetches' cannot be an empty array."); } isFetchesEmpty = false; for (const name of arg1) { if (typeof name !== "string") { throw new TypeError("'fetches' must be a string array or an object."); } if (this.outputNames.indexOf(name) === -1) { throw new RangeError(`'fetches' contains invalid output name: ${name}.`); } fetches[name] = null; } if (typeof arg2 === "object" && arg2 !== null) { options = arg2; } else if (typeof arg2 !== "undefined") { throw new TypeError("'options' must be an object."); } } else { let isFetches = false; const arg1Keys = Object.getOwnPropertyNames(arg1); for (const name of this.outputNames) { if (arg1Keys.indexOf(name) !== -1) { const v = arg1[name]; if (v === null || v instanceof Tensor2) { isFetches = true; isFetchesEmpty = false; fetches[name] = v; } } } if (isFetches) { if (typeof arg2 === "object" && arg2 !== null) { options = arg2; } else if (typeof arg2 !== "undefined") { throw new TypeError("'options' must be an object."); } } else { options = arg1; } } } else if (typeof arg1 !== "undefined") { throw new TypeError("Unexpected argument[1]: must be 'fetches' or 'options'."); } for (const name of this.inputNames) { if (typeof feeds[name] === "undefined") { throw new Error(`input '${name}' is missing in 'feeds'.`); } } if (isFetchesEmpty) { for (const name of this.outputNames) { fetches[name] = null; } } const results = await this.handler.run(feeds, fetches, options); const returnValue = {}; for (const key in results) { if (Object.hasOwnProperty.call(results, key)) { const result = results[key]; if (result instanceof Tensor2) { returnValue[key] = result; } else { returnValue[key] = new Tensor2(result.type, result.data, result.dims); } } } TRACE_EVENT_END("InferenceSession.run"); TRACE_FUNC_END(); return returnValue; } async release() { return this.handler.dispose(); } static async create(arg0, arg1, arg2, arg3) { TRACE_FUNC_BEGIN(); TRACE_EVENT_BEGIN("InferenceSession.create"); let filePathOrUint8Array; let options = {}; if (typeof arg0 === "string") { filePathOrUint8Array = arg0; if (typeof arg1 === "object" && arg1 !== null) { options = arg1; } else if (typeof arg1 !== "undefined") { throw new TypeError("'options' must be an object."); } } else if (arg0 instanceof Uint8Array) { filePathOrUint8Array = arg0; if (typeof arg1 === "object" && arg1 !== null) { options = arg1; } else if (typeof arg1 !== "undefined") { throw new TypeError("'options' must be an object."); } } else if (arg0 instanceof ArrayBuffer || typeof SharedArrayBuffer !== "undefined" && arg0 instanceof SharedArrayBuffer) { const buffer = arg0; let byteOffset = 0; let byteLength = arg0.byteLength; if (typeof arg1 === "object" && arg1 !== null) { options = arg1; } else if (typeof arg1 === "number") { byteOffset = arg1; if (!Number.isSafeInteger(byteOffset)) { throw new RangeError("'byteOffset' must be an integer."); } if (byteOffset < 0 || byteOffset >= buffer.byteLength) { throw new RangeError(`'byteOffset' is out of range [0, ${buffer.byteLength}).`); } byteLength = arg0.byteLength - byteOffset; if (typeof arg2 === "number") { byteLength = arg2; if (!Number.isSafeInteger(byteLength)) { throw new RangeError("'byteLength' must be an integer."); } if (byteLength <= 0 || byteOffset + byteLength > buffer.byteLength) { throw new RangeError(`'byteLength' is out of range (0, ${buffer.byteLength - byteOffset}].`); } if (typeof arg3 === "object" && arg3 !== null) { options = arg3; } else if (typeof arg3 !== "undefined") { throw new TypeError("'options' must be an object."); } } else if (typeof arg2 !== "undefined") { throw new TypeError("'byteLength' must be a number."); } } else if (typeof arg1 !== "undefined") { throw new TypeError("'options' must be an object."); } filePathOrUint8Array = new Uint8Array(buffer, byteOffset, byteLength); } else { throw new TypeError("Unexpected argument[0]: must be 'path' or 'buffer'."); } const [backend, optionsWithValidatedEPs] = await resolveBackendAndExecutionProviders(options); const handler = await backend.createInferenceSessionHandler(filePathOrUint8Array, optionsWithValidatedEPs); TRACE_EVENT_END("InferenceSession.create"); TRACE_FUNC_END(); return new _InferenceSession(handler); } startProfiling() { this.handler.startProfiling(); } endProfiling() { this.handler.endProfiling(); } get inputNames() { return this.handler.inputNames; } get outputNames() { return this.handler.outputNames; } get inputMetadata() { return this.handler.inputMetadata; } get outputMetadata() { return this.handler.outputMetadata; } }; } }); // common/dist/esm/inference-session.js var InferenceSession2; var init_inference_session = __esm({ "common/dist/esm/inference-session.js"() { "use strict"; init_inference_session_impl(); InferenceSession2 = InferenceSession; } }); // common/dist/esm/tensor-conversion.js var init_tensor_conversion = __esm({ "common/dist/esm/tensor-conversion.js"() { "use strict"; } }); // common/dist/esm/tensor-factory.js var init_tensor_factory = __esm({ "common/dist/esm/tensor-factory.js"() { "use strict"; } }); // common/dist/esm/onnx-model.js var init_onnx_model = __esm({ "common/dist/esm/onnx-model.js"() { "use strict"; } }); // common/dist/esm/onnx-value.js var init_onnx_value = __esm({ "common/dist/esm/onnx-value.js"() { "use strict"; } }); // common/dist/esm/index.js var esm_exports = {}; __export(esm_exports, { InferenceSession: () => InferenceSession2, TRACE: () => TRACE, TRACE_EVENT_BEGIN: () => TRACE_EVENT_BEGIN, TRACE_EVENT_END: () => TRACE_EVENT_END, TRACE_FUNC_BEGIN: () => TRACE_FUNC_BEGIN, TRACE_FUNC_END: () => TRACE_FUNC_END, Tensor: () => Tensor2, env: () => env2, registerBackend: () => registerBackend }); var init_esm = __esm({ "common/dist/esm/index.js"() { "use strict"; init_backend(); init_env(); init_inference_session(); init_tensor(); init_tensor_conversion(); init_tensor_factory(); init_trace(); init_onnx_model(); init_onnx_value(); } }); // web/lib/wasm/wasm-utils-env.ts var isNode; var init_wasm_utils_env = __esm({ "web/lib/wasm/wasm-utils-env.ts"() { "use strict"; isNode = false; } }); // web/lib/wasm/proxy-worker/main.ts var main_exports = {}; __export(main_exports, { default: () => main_default }); var WORKER_NAME, isProxyWorker, main_default; var init_main = __esm({ "web/lib/wasm/proxy-worker/main.ts"() { "use strict"; init_wasm_core_impl(); init_wasm_factory(); init_wasm_utils_import(); WORKER_NAME = "ort-wasm-proxy-worker"; isProxyWorker = globalThis.self?.name === WORKER_NAME; if (isProxyWorker) { self.onmessage = (ev) => { const { type, in: message } = ev.data; try { switch (type) { case "init-wasm": initializeWebAssembly(message.wasm).then( () => { initRuntime(message).then( () => { postMessage({ type }); }, (err) => { postMessage({ type, err }); } ); }, (err) => { postMessage({ type, err }); } ); break; case "init-ep": { const { epName, env: env3 } = message; initEp(env3, epName).then( () => { postMessage({ type }); }, (err) => { postMessage({ type, err }); } ); break; } case "copy-from": { const { buffer } = message; const bufferData = copyFromExternalBuffer(buffer); postMessage({ type, out: bufferData }); break; } case "create": { const { model, options } = message; createSession(model, options).then( (sessionMetadata) => { postMessage({ type, out: sessionMetadata }); }, (err) => { postMessage({ type, err }); } ); break; } case "release": releaseSession(message); postMessage({ type }); break; case "run": { const { sessionId, inputIndices, inputs, outputIndices, options } = message; run(sessionId, inputIndices, inputs, outputIndices, new Array(outputIndices.length).fill(null), options).then( (outputs) => { if (outputs.some((o) => o[3] !== "cpu")) { postMessage({ type, err: "Proxy does not support non-cpu tensor location." }); } else { postMessage( { type, out: outputs }, extractTransferableBuffers([...inputs, ...outputs]) ); } }, (err) => { postMessage({ type, err }); } ); break; } case "end-profiling": endProfiling(message); postMessage({ type }); break; default: } } catch (err) { postMessage({ type, err }); } }; } main_default = isProxyWorker ? null : (urlOverride) => new Worker(urlOverride ?? scriptSrc, { type: false ? "module" : "classic", name: WORKER_NAME }); } }); // web/lib/wasm/wasm-utils-import.ts var origin, getScriptSrc, scriptSrc, inferWasmPathPrefixFromScriptSrc, isSameOrigin, normalizeUrl, fallbackUrl, preload, dynamicImportDefault, createProxyWorker, importProxyWorker, embeddedWasmModule, importWasmModule; var init_wasm_utils_import = __esm({ "web/lib/wasm/wasm-utils-import.ts"() { "use strict"; init_wasm_utils_env(); origin = isNode || typeof location === "undefined" ? void 0 : location.origin; getScriptSrc = () => { if (isNode) { return void 0; } if (false) { if (isEsmImportMetaUrlHardcodedAsFileUri) { const URL2 = URL; return new URL(new URL2("ort.js", void 0).href, origin).href; } return void 0; } return typeof document !== "undefined" ? document.currentScript?.src : ( // use `self.location.href` if available typeof self !== "undefined" ? self.location?.href : void 0 ); }; scriptSrc = getScriptSrc(); inferWasmPathPrefixFromScriptSrc = () => { if (scriptSrc && !scriptSrc.startsWith("blob:")) { return scriptSrc.substring(0, scriptSrc.lastIndexOf("/") + 1); } return void 0; }; isSameOrigin = (filename, prefixOverride) => { try { const baseUrl = prefixOverride ?? scriptSrc; const url = baseUrl ? new URL(filename, baseUrl) : new URL(filename); return url.origin === origin; } catch { return false; } }; normalizeUrl = (filename, prefixOverride) => { const baseUrl = prefixOverride ?? scriptSrc; try { const url = baseUrl ? new URL(filename, baseUrl) : new URL(filename); return url.href; } catch { return void 0; } }; fallbackUrl = (filename, prefixOverride) => `${prefixOverride ?? "./"}${filename}`; preload = async (absoluteUrl) => { const response = await fetch(absoluteUrl, { credentials: "same-origin" }); const blob = await response.blob(); return URL.createObjectURL(blob); }; dynamicImportDefault = async (url) => (await import( /* webpackIgnore: true */ /* @vite-ignore */ url )).default; createProxyWorker = // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires false ? void 0 : (init_main(), __toCommonJS(main_exports)).default; importProxyWorker = async () => { if (!scriptSrc) { throw new Error("Failed to load proxy worker: cannot determine the script source URL."); } if (isSameOrigin(scriptSrc)) { return [void 0, createProxyWorker()]; } const url = await preload(scriptSrc); return [url, createProxyWorker(url)]; }; embeddedWasmModule = false ? ( // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires (true ? null : false ? null : false ? null : null).default ) : void 0; importWasmModule = async (urlOverride, prefixOverride, isMultiThreaded, isWasmOverridden) => { let useEmbeddedModule = embeddedWasmModule && !(urlOverride || prefixOverride); if (useEmbeddedModule) { if (!scriptSrc) { if (isWasmOverridden && !isMultiThreaded) { useEmbeddedModule = true; } else { throw new Error("cannot determine the script source URL."); } } else { useEmbeddedModule = isSameOrigin(scriptSrc) || isWasmOverridden && !isMultiThreaded; } } if (useEmbeddedModule) { return [void 0, embeddedWasmModule]; } else { const wasmModuleFilename = true ? "ort-wasm-simd-threaded.jsep.mjs" : false ? "ort-wasm-simd-threaded.jspi.mjs" : false ? "ort-wasm-simd-threaded.asyncify.mjs" : "ort-wasm-simd-threaded.mjs"; const wasmModuleUrl = urlOverride ?? normalizeUrl(wasmModuleFilename, prefixOverride); const needPreload = !isNode && isMultiThreaded && wasmModuleUrl && !isSameOrigin(wasmModuleUrl, prefixOverride); const url = needPreload ? await preload(wasmModuleUrl) : wasmModuleUrl ?? fallbackUrl(wasmModuleFilename, prefixOverride); return [needPreload ? url : void 0, await dynamicImportDefault(url)]; } }; } }); // web/lib/wasm/wasm-factory.ts var wasm, initialized, initializing, aborted, isMultiThreadSupported, isSimdSupported, isRelaxedSimdSupported, initializeWebAssembly, getInstance; var init_wasm_factory = __esm({ "web/lib/wasm/wasm-factory.ts"() { "use strict"; init_wasm_utils_import(); initialized = false; initializing = false; aborted = false; isMultiThreadSupported = () => { if (typeof SharedArrayBuffer === "undefined") { return false; } try { if (typeof MessageChannel !== "undefined") { new MessageChannel().port1.postMessage(new SharedArrayBuffer(1)); } return WebAssembly.validate( new Uint8Array([ 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5, 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16, 2, 0, 26, 11 ]) ); } catch { return false; } }; isSimdSupported = () => { try { return WebAssembly.validate( new Uint8Array([ 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 30, 1, 28, 0, 65, 0, 253, 15, 253, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 186, 1, 26, 11 ]) ); } catch { return false; } }; isRelaxedSimdSupported = () => { try { return WebAssembly.validate( new Uint8Array([ 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 10, 19, 1, 17, 0, 65, 1, 253, 15, 65, 2, 253, 15, 65, 3, 253, 15, 253, 147, 2, 11 ]) ); } catch { return false; } }; initializeWebAssembly = async (flags) => { if (initialized) { return Promise.resolve(); } if (initializing) { throw new Error("multiple calls to 'initializeWebAssembly()' detected."); } if (aborted) { throw new Error("previous call to 'initializeWebAssembly()' failed."); } initializing = true; const timeout = flags.initTimeout; let numThreads = flags.numThreads; if (flags.simd === false) { } else if (flags.simd === "relaxed") { if (!isRelaxedSimdSupported()) { throw new Error("Relaxed WebAssembly SIMD is not supported in the current environment."); } } else if (!isSimdSupported()) { throw new Error("WebAssembly SIMD is not supported in the current environment."); } if (false) { if (!("Suspending" in WebAssembly)) { throw new Error("WebAssembly JSPI is not supported in the current environment."); } } const multiThreadSupported = isMultiThreadSupported(); if (numThreads > 1 && !multiThreadSupported) { if (typeof self !== "undefined" && !self.crossOriginIsolated) { console.warn( "env.wasm.numThreads is set to " + numThreads + ", but this will not work unless you enable crossOriginIsolated mode. See https://web.dev/cross-origin-isolation-guide/ for more info." ); } console.warn( "WebAssembly multi-threading is not supported in the current environment. Falling back to single-threading." ); flags.numThreads = numThreads = 1; } const wasmPaths = flags.wasmPaths; const wasmPrefixOverride = typeof wasmPaths === "string" ? wasmPaths : void 0; const mjsPathOverrideFlag = wasmPaths?.mjs; const mjsPathOverride = mjsPathOverrideFlag?.href ?? mjsPathOverrideFlag; const wasmPathOverrideFlag = wasmPaths?.wasm; const wasmPathOverride = wasmPathOverrideFlag?.href ?? wasmPathOverrideFlag; const wasmBinaryOverride = flags.wasmBinary; const [objectUrl, ortWasmFactory] = await importWasmModule( mjsPathOverride, wasmPrefixOverride, numThreads > 1, !!wasmBinaryOverride || !!wasmPathOverride ); let isTimeout = false; const tasks = []; if (timeout > 0) { tasks.push( new Promise((resolve) => { setTimeout(() => { isTimeout = true; resolve(); }, timeout); }) ); } tasks.push( new Promise((resolve, reject) => { const config = { /** * The number of threads. WebAssembly will create (Module.numThreads - 1) workers. If it is 1, no worker will be * created. */ numThreads }; if (wasmBinaryOverride) { config.wasmBinary = wasmBinaryOverride; config.locateFile = (fileName) => fileName; } else if (wasmPathOverride || wasmPrefixOverride) { config.locateFile = (fileName) => wasmPathOverride ?? wasmPrefixOverride + fileName; } else if (mjsPathOverride && mjsPathOverride.indexOf("blob:") !== 0) { config.locateFile = (fileName) => new URL(fileName, mjsPathOverride).href; } else if (objectUrl) { const inferredWasmPathPrefix = inferWasmPathPrefixFromScriptSrc(); if (inferredWasmPathPrefix) { config.locateFile = (fileName) => inferredWasmPathPrefix + fileName; } } ortWasmFactory(config).then( // wasm module initialized successfully (module) => { initializing = false; initialized = true; wasm = module; resolve(); if (objectUrl) { URL.revokeObjectURL(objectUrl); } }, // wasm module failed to initialize (what) => { initializing = false; aborted = true; reject(what); } ); }) ); await Promise.race(tasks); if (isTimeout) { throw new Error(`WebAssembly backend initializing failed due to timeout: ${timeout}ms`); } }; getInstance = () => { if (initialized && wasm) { return wasm; } throw new Error("WebAssembly is not initialized yet."); }; } }); // web/lib/wasm/wasm-utils.ts var allocWasmString, iterateExtraOptions, checkLastError; var init_wasm_utils = __esm({ "web/lib/wasm/wasm-utils.ts"() { "use strict"; init_wasm_factory(); allocWasmString = (data, allocs) => { const wasm2 = getInstance(); const dataLength = wasm2.lengthBytesUTF8(data) + 1; const dataOffset = wasm2._malloc(dataLength); wasm2.stringToUTF8(data, dataOffset, dataLength); allocs.push(dataOffset); return dataOffset; }; iterateExtraOptions = (options, prefix, seen, handler) => { if (typeof options == "object" && options !== null) { if (seen.has(options)) { throw new Error("Circular reference in options"); } else { seen.add(options); } } Object.entries(options).forEach(([key, value]) => { const name = prefix ? prefix + key : key; if (typeof value === "object") { iterateExtraOptions(value, name + ".", seen, handler); } else if (typeof value === "string" || typeof value === "number") { handler(name, value.toString()); } else if (typeof value === "boolean") { handler(name, value ? "1" : "0"); } else { throw new Error(`Can't handle extra config type: ${typeof value}`); } }); }; checkLastError = (message) => { const wasm2 = getInstance(); const stack = wasm2.stackSave(); try { const ptrSize = wasm2.PTR_SIZE; const paramsOffset = wasm2.stackAlloc(2 * ptrSize); wasm2._OrtGetLastError(paramsOffset, paramsOffset + ptrSize); const errorCode = Number(wasm2.getValue(paramsOffset, ptrSize === 4 ? "i32" : "i64")); const errorMessagePointer = wasm2.getValue(paramsOffset + ptrSize, "*"); const errorMessage = errorMessagePointer ? wasm2.UTF8ToString(errorMessagePointer) : ""; throw new Error(`${message} ERROR_CODE: ${errorCode}, ERROR_MESSAGE: ${errorMessage}`); } finally { wasm2.stackRestore(stack); } }; } }); // web/lib/wasm/run-options.ts var setRunOptions; var init_run_options = __esm({ "web/lib/wasm/run-options.ts"() { "use strict"; init_wasm_factory(); init_wasm_utils(); setRunOptions = (options) => { const wasm2 = getInstance(); let runOptionsHandle = 0; const allocs = []; const runOptions = options || {}; try { if (options?.logSeverityLevel === void 0) { runOptions.logSeverityLevel = 2; } else if (typeof options.logSeverityLevel !== "number" || !Number.isInteger(options.logSeverityLevel) || options.logSeverityLevel < 0 || options.logSeverityLevel > 4) { throw new Error(`log severity level is not valid: ${options.logSeverityLevel}`); } if (options?.logVerbosityLevel === void 0) { runOptions.logVerbosityLevel = 0; } else if (typeof options.logVerbosityLevel !== "number" || !Number.isInteger(options.logVerbosityLevel)) { throw new Error(`log verbosity level is not valid: ${options.logVerbosityLevel}`); } if (options?.terminate === void 0) { runOptions.terminate = false; } let tagDataOffset = 0; if (options?.tag !== void 0) { tagDataOffset = allocWasmString(options.tag, allocs); } runOptionsHandle = wasm2._OrtCreateRunOptions( runOptions.logSeverityLevel, runOptions.logVerbosityLevel, !!runOptions.terminate, tagDataOffset ); if (runOptionsHandle === 0) { checkLastError("Can't create run options."); } if (options?.extra !== void 0) { iterateExtraOptions(options.extra, "", /* @__PURE__ */ new WeakSet(), (key, value) => { const keyDataOffset = allocWasmString(key, allocs); const valueDataOffset = allocWasmString(value, allocs); if (wasm2._OrtAddRunConfigEntry(runOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { checkLastError(`Can't set a run config entry: ${key} - ${value}.`); } }); } return [runOptionsHandle, allocs]; } catch (e) { if (runOptionsHandle !== 0) { wasm2._OrtReleaseRunOptions(runOptionsHandle); } allocs.forEach((alloc) => wasm2._free(alloc)); throw e; } }; } }); // web/lib/wasm/session-options.ts var getGraphOptimzationLevel, getExecutionMode, appendDefaultOptions, appendSessionConfig, setExecutionProviders, setSessionOptions; var init_session_options = __esm({ "web/lib/wasm/session-options.ts"() { "use strict"; init_wasm_factory(); init_wasm_utils(); getGraphOptimzationLevel = (graphOptimizationLevel) => { switch (graphOptimizationLevel) { case "disabled": return 0; case "basic": return 1; case "extended": return 2; case "layout": return 3; case "all": return 99; default: throw new Error(`unsupported graph optimization level: ${graphOptimizationLevel}`); } }; getExecutionMode = (executionMode) => { switch (executionMode) { case "sequential": return 0; case "parallel": return 1; default: throw new Error(`unsupported execution mode: ${executionMode}`); } }; appendDefaultOptions = (options) => { if (!options.extra) { options.extra = {}; } if (!options.extra.session) { options.extra.session = {}; } const session = options.extra.session; if (!session.use_ort_model_bytes_directly) { session.use_ort_model_bytes_directly = "1"; } if (options.executionProviders && options.executionProviders.some((ep) => (typeof ep === "string" ? ep : ep.name) === "webgpu")) { options.enableMemPattern = false; } }; appendSessionConfig = (sessionOptionsHandle, key, value, allocs) => { const keyDataOffset = allocWasmString(key, allocs); const valueDataOffset = allocWasmString(value, allocs); if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { checkLastError(`Can't set a session config entry: ${key} - ${value}.`); } }; setExecutionProviders = async (sessionOptionsHandle, sessionOptions, allocs) => { const executionProviders = sessionOptions.executionProviders; for (const ep of executionProviders) { let epName = typeof ep === "string" ? ep : ep.name; const epOptions = []; switch (epName) { case "webnn": epName = "WEBNN"; appendSessionConfig(sessionOptionsHandle, "session.disable_quant_qdq", "1", allocs); appendSessionConfig(sessionOptionsHandle, "session.disable_qdq_constant_folding", "1", allocs); if (typeof ep !== "string") { const webnnOptions = ep; const deviceType = webnnOptions?.deviceType; if (deviceType) { appendSessionConfig(sessionOptionsHandle, "deviceType", deviceType, allocs); } } break; case "webgpu": if (false) { epName = "WebGPU"; let customDevice; if (typeof ep !== "string") { const webgpuOptions = ep; if (webgpuOptions.device) { if (typeof GPUDevice !== "undefined" && webgpuOptions.device instanceof GPUDevice) { customDevice = webgpuOptions.device; } else { throw new Error("Invalid GPU device set in WebGPU EP options."); } } const { enableGraphCapture } = sessionOptions; if (typeof enableGraphCapture === "boolean" && enableGraphCapture) { appendEpOption(epOptions, "enableGraphCapture", "1", allocs); } if (typeof webgpuOptions.preferredLayout === "string") { appendEpOption(epOptions, "preferredLayout", webgpuOptions.preferredLayout, allocs); } if (webgpuOptions.forceCpuNodeNames) { const names = Array.isArray(webgpuOptions.forceCpuNodeNames) ? webgpuOptions.forceCpuNodeNames : [webgpuOptions.forceCpuNodeNames]; appendEpOption(epOptions, "forceCpuNodeNames", names.join("\n"), allocs); } if (webgpuOptions.validationMode) { appendEpOption(epOptions, "validationMode", webgpuOptions.validationMode, allocs); } } const info = getInstance().webgpuRegisterDevice(customDevice); if (info) { const [deviceId, instanceHandle, deviceHandle] = info; appendEpOption(epOptions, "deviceId", deviceId.toString(), allocs); appendEpOption(epOptions, "webgpuInstance", instanceHandle.toString(), allocs); appendEpOption(epOptions, "webgpuDevice", deviceHandle.toString(), allocs); } } else { epName = "JS"; if (typeof ep !== "string") { const webgpuOptions = ep; if (webgpuOptions?.preferredLayout) { if (webgpuOptions.preferredLayout !== "NCHW" && webgpuOptions.preferredLayout !== "NHWC") { throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${webgpuOptions.preferredLayout}`); } appendSessionConfig(sessionOptionsHandle, "preferredLayout", webgpuOptions.preferredLayout, allocs); } } } break; case "wasm": case "cpu": continue; default: throw new Error(`not supported execution provider: ${epName}`); } const epNameDataOffset = allocWasmString(epName, allocs); const epOptionsCount = epOptions.length; let keysOffset = 0; let valuesOffset = 0; if (epOptionsCount > 0) { keysOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE); allocs.push(keysOffset); valuesOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE); allocs.push(valuesOffset); for (let i = 0; i < epOptionsCount; i++) { getInstance().setValue(keysOffset + i * getInstance().PTR_SIZE, epOptions[i][0], "*"); getInstance().setValue(valuesOffset + i * getInstance().PTR_SIZE, epOptions[i][1], "*"); } } if (await getInstance()._OrtAppendExecutionProvider( sessionOptionsHandle, epNameDataOffset, keysOffset, valuesOffset, epOptionsCount ) !== 0) { checkLastError(`Can't append execution provider: ${epName}.`); } } }; setSessionOptions = async (options) => { const wasm2 = getInstance(); let sessionOptionsHandle = 0; const allocs = []; const sessionOptions = options || {}; appendDefaultOptions(sessionOptions); try { const graphOptimizationLevel = getGraphOptimzationLevel(sessionOptions.graphOptimizationLevel ?? "all"); const executionMode = getExecutionMode(sessionOptions.executionMode ?? "sequential"); const logIdDataOffset = typeof sessionOptions.logId === "string" ? allocWasmString(sessionOptions.logId, allocs) : 0; const logSeverityLevel = sessionOptions.logSeverityLevel ?? 2; if (!Number.isInteger(logSeverityLevel) || logSeverityLevel < 0 || logSeverityLevel > 4) { throw new Error(`log severity level is not valid: ${logSeverityLevel}`); } const logVerbosityLevel = sessionOptions.logVerbosityLevel ?? 0; if (!Number.isInteger(logVerbosityLevel) || logVerbosityLevel < 0 || logVerbosityLevel > 4) { throw new Error(`log verbosity level is not valid: ${logVerbosityLevel}`); } const optimizedModelFilePathOffset = typeof sessionOptions.optimizedModelFilePath === "string" ? allocWasmString(sessionOptions.optimizedModelFilePath, allocs) : 0; sessionOptionsHandle = wasm2._OrtCreateSessionOptions( graphOptimizationLevel, !!sessionOptions.enableCpuMemArena, !!sessionOptions.enableMemPattern, executionMode, !!sessionOptions.enableProfiling, 0, logIdDataOffset, logSeverityLevel, logVerbosityLevel, optimizedModelFilePathOffset ); if (sessionOptionsHandle === 0) { checkLastError("Can't create session options."); } if (sessionOptions.executionProviders) { await setExecutionProviders(sessionOptionsHandle, sessionOptions, allocs); } if (sessionOptions.enableGraphCapture !== void 0) { if (typeof sessionOptions.enableGraphCapture !== "boolean") { throw new Error(`enableGraphCapture must be a boolean value: ${sessionOptions.enableGraphCapture}`); } appendSessionConfig( sessionOptionsHandle, "enableGraphCapture", sessionOptions.enableGraphCapture.toString(), allocs ); } if (sessionOptions.freeDimensionOverrides) { for (const [name, value] of Object.entries(sessionOptions.freeDimensionOverrides)) { if (typeof name !== "string") { throw new Error(`free dimension override name must be a string: ${name}`); } if (typeof value !== "number" || !Number.isInteger(value) || value < 0) { throw new Error(`free dimension override value must be a non-negative integer: ${value}`); } const nameOffset = allocWasmString(name, allocs); if (wasm2._OrtAddFreeDimensionOverride(sessionOptionsHandle, nameOffset, value) !== 0) { checkLastError(`Can't set a free dimension override: ${name} - ${value}.`); } } } if (sessionOptions.extra !== void 0) { iterateExtraOptions(sessionOptions.extra, "", /* @__PURE__ */ new WeakSet(), (key, value) => { appendSessionConfig(sessionOptionsHandle, key, value, allocs); }); } return [sessionOptionsHandle, allocs]; } catch (e) { if (sessionOptionsHandle !== 0) { if (wasm2._OrtReleaseSessionOptions(sessionOptionsHandle) !== 0) { checkLastError("Can't release session options."); } } allocs.forEach((alloc) => wasm2._free(alloc)); throw e; } }; } }); // web/lib/wasm/wasm-common.ts var tensorDataTypeStringToEnum, tensorDataTypeEnumToString, calculateTensorSizeInBytes, tensorTypeToTypedArrayConstructor, logLevelStringToEnum, isGpuBufferSupportedType, isMLTensorSupportedType, dataLocationStringToEnum; var init_wasm_common = __esm({ "web/lib/wasm/wasm-common.ts"() { "use strict"; tensorDataTypeStringToEnum = (type) => { switch (type) { case "int8": return 3 /* int8 */; case "uint8": return 2 /* uint8 */; case "bool": return 9 /* bool */; case "int16": return 5 /* int16 */; case "uint16": return 4 /* uint16 */; case "int32": return 6 /* int32 */; case "uint32": return 12 /* uint32 */; case "float16": return 10 /* float16 */; case "float32": return 1 /* float */; case "float64": return 11 /* double */; case "string": return 8 /* string */; case "int64": return 7 /* int64 */; case "uint64": return 13 /* uint64 */; case "int4": return 22 /* int4 */; case "uint4": return 21 /* uint4 */; default: throw new Error(`unsupported data type: ${type}`); } }; tensorDataTypeEnumToString = (typeProto) => { switch (typeProto) { case 3 /* int8 */: return "int8"; case 2 /* uint8 */: return "uint8"; case 9 /* bool */: return "bool"; case 5 /* int16 */: return "int16"; case 4 /* uint16 */: return "uint16"; case 6 /* int32 */: return "int32"; case 12 /* uint32 */: return "uint32"; case 10 /* float16 */: return "float16"; case 1 /* float */: return "float32"; case 11 /* double */: return "float64"; case 8 /* string */: return "string"; case 7 /* int64 */: return "int64"; case 13 /* uint64 */: return "uint64"; case 22 /* int4 */: return "int4"; case 21 /* uint4 */: return "uint4"; default: throw new Error(`unsupported data type: ${typeProto}`); } }; calculateTensorSizeInBytes = (dateType, dimsOrSize) => { const elementSize = [ -1, // undefined = 0 4, // float = 1 1, // uint8 = 2 1, // int8 = 3 2, // uint16 = 4 2, // int16 = 5 4, // int32 = 6 8, // int64 = 7 -1, // string = 8 1, // bool = 9 2, // float16 = 10 8, // double = 11 4, // uint32 = 12 8, // uint64 = 13 -1, // complex64 = 14 -1, // complex128 = 15 -1, // bfloat16 = 16 -1, // FLOAT8E4M3FN = 17 -1, // FLOAT8E4M3FNUZ = 18 -1, // FLOAT8E5M2 = 19 -1, // FLOAT8E5M2FNUZ = 20 0.5, // uint4 = 21 0.5 // int4 = 22 ][dateType]; const size = typeof dimsOrSize === "number" ? dimsOrSize : dimsOrSize.reduce((a, b) => a * b, 1); return elementSize > 0 ? Math.ceil(size * elementSize) : void 0; }; tensorTypeToTypedArrayConstructor = (type) => { switch (type) { case "float16": return typeof Float16Array !== "undefined" && Float16Array.from ? Float16Array : Uint16Array; case "float32": return Float32Array; case "uint8": return Uint8Array; case "int8": return Int8Array; case "uint16": return Uint16Array; case "int16": return Int16Array; case "int32": return Int32Array; case "bool": return Uint8Array; case "float64": return Float64Array; case "uint32": return Uint32Array; case "int64": return BigInt64Array; case "uint64": return BigUint64Array; default: throw new Error(`unsupported type: ${type}`); } }; logLevelStringToEnum = (logLevel) => { switch (logLevel) { case "verbose": return 0; case "info": return 1; case "warning": return 2; case "error": return 3; case "fatal": return 4; default: throw new Error(`unsupported logging level: ${logLevel}`); } }; isGpuBufferSupportedType = (type) => type === "float32" || type === "float16" || type === "int32" || type === "int64" || type === "uint32" || type === "uint8" || type === "bool" || type === "uint4" || type === "int4"; isMLTensorSupportedType = (type) => type === "float32" || type === "float16" || type === "int32" || type === "int64" || type === "uint32" || type === "uint64" || type === "int8" || type === "uint8" || type === "bool" || type === "uint4" || type === "int4"; dataLocationStringToEnum = (location2) => { switch (location2) { case "none": return 0; case "cpu": return 1; case "cpu-pinned": return 2; case "texture": return 3; case "gpu-buffer": return 4; case "ml-tensor": return 5; default: throw new Error(`unsupported data location: ${location2}`); } }; } }); // web/lib/wasm/wasm-utils-load-file.ts var loadFile; var init_wasm_utils_load_file = __esm({ "web/lib/wasm/wasm-utils-load-file.ts"() { "use strict"; init_wasm_utils_env(); loadFile = async (file) => { if (typeof file === "string") { if (isNode) { try { const { readFile } = __require("node:fs/promises"); return new Uint8Array(await readFile(file)); } catch (e) { if (e.code === "ERR_FS_FILE_TOO_LARGE") { const { createReadStream } = __require("node:fs"); const stream = createReadStream(file); const chunks = []; for await (const chunk of stream) { chunks.push(chunk); } return new Uint8Array(Buffer.concat(chunks)); } throw e; } } else { const response = await fetch(file); if (!response.ok) { throw new Error(`failed to load external data file: ${file}`); } const contentLengthHeader = response.headers.get("Content-Length"); const fileSize = contentLengthHeader ? parseInt(contentLengthHeader, 10) : 0; if (fileSize < 1073741824) { return new Uint8Array(await response.arrayBuffer()); } else { if (!response.body) { throw new Error(`failed to load external data file: ${file}, no response body.`); } const reader = response.body.getReader(); let buffer; try { buffer = new ArrayBuffer(fileSize); } catch (e) { if (e instanceof RangeError) { const pages = Math.ceil(fileSize / 65536); buffer = new WebAssembly.Memory({ initial: pages, maximum: pages }).buffer; } else { throw e; } } let offset = 0; while (true) { const { done, value } = await reader.read(); if (done) { break; } const chunkSize = value.byteLength; const chunk = new Uint8Array(buffer, offset, chunkSize); chunk.set(value); offset += chunkSize; } return new Uint8Array(buffer, 0, fileSize); } } } else if (file instanceof Blob) { return new Uint8Array(await file.arrayBuffer()); } else if (file instanceof Uint8Array) { return file; } else { return new Uint8Array(file); } }; } }); // web/lib/wasm/jsep/log.ts var logLevelPrefix, doLog, configLogLevel, debug, configureLogger, LOG, LOG_DEBUG; var init_log = __esm({ "web/lib/wasm/jsep/log.ts"() { "use strict"; init_wasm_common(); logLevelPrefix = ["V", "I", "W", "E", "F"]; doLog = (level, message) => { console.log(`[${logLevelPrefix[level]},${(/* @__PURE__ */ new Date()).toISOString()}]${message}`); }; configureLogger = ($configLogLevel, $debug) => { configLogLevel = $configLogLevel; debug = $debug; }; LOG = (logLevel, msg) => { const messageLevel = logLevelStringToEnum(logLevel); const configLevel = logLevelStringToEnum(configLogLevel); if (messageLevel >= configLevel) { doLog(messageLevel, typeof msg === "function" ? msg() : msg); } }; LOG_DEBUG = (...args) => { if (debug) { LOG(...args); } }; } }); // web/lib/wasm/jsep/util.ts var MatMulUtil, BroadcastUtil, ShapeUtil, PoolConvUtil, GemmUtil, MIN_CLIP, MAX_CLIP; var init_util = __esm({ "web/lib/wasm/jsep/util.ts"() { "use strict"; MatMulUtil = class { /** * Calculate the expected shape when matrix multiplication * @param a The shape of tensor A. Should be a tuple of 2 positive integers * @param b The shape of tensor B. Should be a tuple of 2 positive integers * @returns The expected shape of the result, or undefined if N/A */ static calcMatMulShape(a, b) { return a[1] !== b[0] ? void 0 : [a[0], b[1]]; } }; BroadcastUtil = class { /** * Calculate the expected shape when broadcasting 2 tensors * @param a The shape of tensor A. Should be an array of positive integers * @param b The shape of tensor B. Should be an array of positive integers * @param isMatMul Whether the operation is MatMul * @returns The expected shape of the result, or undefined if N/A */ static calcShape(adims, bdims, isMatMul = false) { const arank = adims.length; const brank = bdims.length; if (arank === 0) { return bdims; } if (brank === 0) { return adims; } const crank = Math.max(adims.length, bdims.length); const cdims = new Array(crank); if (isMatMul) { if (arank < 2 || brank < 2) { return void 0; } const cShapeMatMul = MatMulUtil.calcMatMulShape( [adims[arank - 2], adims[arank - 1]], [bdims[brank - 2], bdims[brank - 1]] ); if (cShapeMatMul === void 0) { return void 0; } [cdims[crank - 2], cdims[crank - 1]] = cShapeMatMul; } for (let i = isMatMul ? 3 : 1; i <= crank; i++) { const aLen = arank - i < 0 ? 1 : adims[arank - i]; const bLen = brank - i < 0 ? 1 : bdims[brank - i]; if (aLen !== bLen && aLen > 1 && bLen > 1) { return void 0; } const max = Math.max(aLen, bLen); if (aLen && bLen) { cdims[crank - i] = Math.max(aLen, bLen); } else { if (max > 1) { return void 0; } cdims[crank - i] = 0; } } return cdims; } /** * Determine if a shape is unidirectional broadcastable to another shape * @param shape The input shape * @param finalShape The desired shape after broadcasting */ static isValidBroadcast(shape, finalShape) { const inputRank = shape.length; const finalRank = finalShape.length; if (inputRank > finalRank) { return false; } for (let i = 1; i <= inputRank; i++) { if (shape[inputRank - i] !== 1 && shape[inputRank - i] !== finalShape[finalRank - i]) { return false; } } return true; } }; ShapeUtil = class _ShapeUtil { /** * calculate the size (number of elements) */ static size(dims) { return _ShapeUtil.getSizeFromDimensionRange(dims, 0, dims.length); } /** * convert dims corresponding to type change to pack. ex. uint8 data to uint32 */ static convertShape(dims, size = 4) { const rank = dims.length; if (rank === 0) { return []; } const newDims = new Array(rank); let i = rank - 1; while (i >= 0) { if (dims[i] % size === 0) { newDims[i] = dims[i] / size; break; } if (size % dims[i] !== 0) { throw new Error("cannot convert shape"); } newDims[i] = 1; size /= dims[i]; i--; } for (i--; i >= 0; i--) { newDims[i] = dims[i]; } return newDims; } /** * calculate the size (number of elements) from the given axis (inclusive) */ static sizeFromDimension(dims, axis) { if (axis < 0 || axis > dims.length) { throw new Error(`invalid dimension of ${axis} for sizeFromDimension as Tensor has ${dims.length} dimensions.`); } return _ShapeUtil.getSizeFromDimensionRange(dims, axis, dims.length); } /** * calculate the size (number of elements) to the given axis (exclusive) */ static sizeToDimension(dims, axis) { if (axis < 0 || axis > dims.length) { throw new Error(`invalid dimension of ${axis} for sizeToDimension as Tensor has ${dims.length} dimensions.`); } return _ShapeUtil.getSizeFromDimensionRange(dims, 0, axis); } /** * calculate the size (number of elements) from and to the given axis [start, end) */ static getSizeFromDimensionRange(dims, start, end) { let size = 1; for (let i = start; i < end; i++) { if (dims[i] < 0) { throw new Error( "cannot get valid size from specified dimension range. Most likely the range contains negative values in them." ); } size *= Number(dims[i]); } return size; } static computeStrides(dims) { const rank = dims.length; if (rank === 0) { return []; } else if (rank === 1) { return [1]; } const strides = new Array(rank); strides[rank - 1] = 1; strides[rank - 2] = dims[rank - 1]; for (let i = rank - 3; i >= 0; --i) { strides[i] = strides[i + 1] * dims[i + 1]; } return strides; } /** * normalize axis of range [-r, r) into [0, r). */ static normalizeAxis(axis, tensorRank) { if (axis < -tensorRank && axis >= tensorRank) { throw new Error("unsupported axis for this operation."); } return axis < 0 ? axis + tensorRank : axis; } static normalizeAxes(axes, tensorRank) { return axes.map((x) => this.normalizeAxis(x, tensorRank ?? axes.length)); } /** * Sorts a given array based on the indices in the Perm array * Used in Transpose * @param a Array to be sorted such as dims or strides * @param perm Perm given; if null a will be reversed */ static sortBasedOnPerm(a, perm) { if (perm) { return perm.map((v) => a[v]); } else { return a.slice().reverse(); } } /** * Pads a given shape according to the padding values * @param dims shape of the Tensor to be padded * @param pad pad values */ static padShape(dims, pad2) { const rank = dims.length; return dims.map((v, i) => v + pad2[i] + pad2[i + rank]); } /** * Determines if the two shapes are identical * @param shape1 * @param shape2 */ static areEqual(shape1, shape2) { if (shape1.length !== shape2.length) { return false; } return shape1.every((v, i) => v === shape2[i]); } }; PoolConvUtil = class _PoolConvUtil { /** * Adjust the kernel, strides, pads to correct rank. Set to default value if not present * @param isGlobalOperator If true, perform global pooling. * @param inputDims The input tensor dimension. * @param kernelShape The size of the kernel along each axis. * @param strides Stride along each axis. * @param dilations Dilation along each axis. * @param pads Padding for the beginning and ending along each axis. */ static adjustPoolAttributes(isGlobalOperator, inputDims, kernelShape, strides, dilations, pads) { if (!isGlobalOperator && kernelShape.length !== inputDims.length - 2) { throw new Error("length of specified kernel shapes should be 2 less than length of input dimensions"); } if (isGlobalOperator) { for (let dim = 0; dim < inputDims.length - 2; dim++) { if (dim >= kernelShape.length) { kernelShape.push(inputDims[dim + 2]); } else { kernelShape[dim] = inputDims[dim + 2]; } } } for (let dim = 0; dim < kernelShape.length; dim++) { if (dim < strides.length) { if (strides[dim] < 0) { throw new Error("strides should be greater than or equal to 1"); } } else { strides.push(1); } } for (let dim = 0; dim < kernelShape.length; dim++) { if (dim < dilations.length) { if (dilations[dim] < 0) { throw new Error("dilations should be greater than or equal to 1"); } } else { dilations.push(1); } } for (let dim = 0; dim < kernelShape.length * 2; dim++) { if (dim < pads.length) { if (pads[dim] < 0) { throw new Error("pad should be greater than or equal to 1"); } } else { pads.push(0); } } for (let dim = 0; dim < kernelShape.length; dim++) { if (kernelShape[dim] <= 0) { throw new Error("kernel shapes need to be greater than 0"); } if (pads[dim] >= kernelShape[dim] || pads[dim + kernelShape.length] >= kernelShape[dim]) { throw new Error("pads should be smaller than kernel"); } } } // adjust pad values based on 'autoPad' attribute static adjustPadsBasedOnAutoPad(inputDims, strides, dilations, kernelShape, pads, isChannelLast, autoPad) { if (!autoPad) { return; } if (pads.length !== 2 * (inputDims.length - 2)) { throw new Error("length of pads should be twice the length of data dimensions"); } if (strides.length !== inputDims.length - 2) { throw new Error("length of strides should be the length of data dimensions"); } if (kernelShape.length !== inputDims.length - 2) { throw new Error("length of kernel shapes should be the length of data dimensions"); } for (let dim = 0; dim < inputDims.length - 2; dim++) { _PoolConvUtil.adjustPadAndReturnShape( inputDims[dim + (isChannelLast ? 1 : 2)], strides[dim], dilations[dim], kernelShape[dim], pads, dim, dim + inputDims.length - 2, autoPad ); } } /** * Calculate the output shape for Pool ops based on input attributes. (Should be used only for Pool ops) * @param isGlobalOperator If true, perform global pooling. * @param inputDims The input tensor dimension. (inputs[0].dims) * @param strides Stride along each axis. * @param dilations Dilation along each axis. * @param kernelShape The size of the kernel along each axis. * @param pads Padding for the beginning and ending along each axis. * @param autoPad DEPRECATED attribute supported for legacy models. Specifies how to implicitly calculate pads in each * dimension. Can take values NOTSET, SAME_UPPER, SAME_LOWER, or VALID. */ static computePoolOutputShape(isGlobalOperator, inputDims, strides, dilations, kernelShape, pads, autoPad) { if (inputDims.length <= 0) { throw new Error("input shape must be of size greater than 0"); } const outputDims = [inputDims[0], inputDims[1]]; _PoolConvUtil.computeShapeHelper( isGlobalOperator, inputDims, outputDims, strides, dilations, kernelShape, pads, autoPad ); return outputDims; } /** * Calculate the output shape for Conv op based on input attributes. (Should be used only for Conv op) * @param inputDims The input tensor dimension. (inputs[0].dims) * @param filterDims The filter tensor dimension. (inputs[1].dims) * @param strides Stride along each axis. * @param kernelShape The size of the kernel along each axis. * @param pads Padding for the beginning and ending along each axis. * @param autoPad DEPRECATED attribute supported for legacy models. Specifies how to implicitly calculate pads in each * dimension. Can take values NOTSET, SAME_UPPER, SAME_LOWER, or VALID. */ static computeConvOutputShape(inputDims, filterDims, strides, dilations, kernelShape, pads, autoPad) { if (inputDims.length <= 0 || filterDims.length <= 0) { throw new Error("invalid input tensor dims or invalid filter tensor dims"); } const outputDims = [inputDims[0], filterDims[0]]; _PoolConvUtil.computeShapeHelper(false, inputDims, outputDims, strides, dilations, kernelShape, pads, autoPad); return outputDims; } // will compute output shapes for data dimensions ONLY (i.e.) no batch size and channels // called by computePoolOutputShape() and computeConvOutputShape() // adjust pads based on 'autoPad' attribute prior to shape computation static computeShapeHelper(isGlobalOperator, inputDims, outputDims, strides, dilations, kernelShape, pads, autoPad) { if (isGlobalOperator) { for (let dim = 0; dim < inputDims.length - 2; dim++) { outputDims.push(1); } } else { for (let dim = 0; dim < inputDims.length - 2; dim++) { outputDims.push( _PoolConvUtil.adjustPadAndReturnShape( inputDims[dim + 2], strides[dim], dilations[dim], kernelShape[dim], pads, dim, dim + inputDims.length - 2, autoPad ) ); } } } // helper for computeShapeHelper() and adjustPadsBasedOnAutoPad() // adjusts pad value for given 'autoPad' string and computes output shape along a particular dimension static adjustPadAndReturnShape(inSize, stride, dilation, kernel, pads, padHeadIndex, padTailIndex, autoPad) { const dkernel = dilation * (kernel - 1) + 1; if (autoPad && autoPad !== "NOTSET") { switch (autoPad) { case "VALID": pads[padHeadIndex] = 0; pads[padTailIndex] = 0; return Math.floor((inSize - dkernel) / stride + 1); case "SAME_LOWER": case "SAME_UPPER": if (dilation !== 1) { throw new Error("Dilation not supported for SAME_UPPER or SAME_LOWER"); } else { const legacyTargetSize = (inSize + stride - 1) / stride; const padNeeded = (legacyTargetSize - 1) * stride + kernel - inSize; pads[padHeadIndex] = autoPad === "SAME_LOWER" ? Math.floor((padNeeded + 1) / 2) : Math.floor(padNeeded / 2); pads[padTailIndex] = padNeeded - pads[padHeadIndex]; return Math.floor((inSize + padNeeded - kernel) / stride + 1); } default: throw new Error("Unsupported AutoPad type"); } } else { return Math.floor((inSize + pads[padHeadIndex] + pads[padTailIndex] - dkernel) / stride + 1); } } }; GemmUtil = class { // will make sure input shapes are compatible for this op // and return back the shape of the output in the form of a tuple // will throw exception if the input shapes are not compatible static getShapeOfGemmResult(leftShape, transLeft, rightShape, transRight, biasShape) { if (leftShape.length !== 2 || rightShape.length !== 2) { throw new Error("shape need to be of size 2"); } let M; let K; let N; if (transLeft) { M = leftShape[1]; K = leftShape[0]; } else { M = leftShape[0]; K = leftShape[1]; } let kDim = -1; if (transRight) { N = rightShape[0]; kDim = 1; } else { N = rightShape[1]; kDim = 0; } if (rightShape[kDim] !== K) { throw new Error("dimension mismatch"); } if (M <= 0 || N <= 0 || K <= 0) { throw new Error("invalid shape specified"); } if (biasShape && !BroadcastUtil.isValidBroadcast(biasShape, [M, N])) { throw new Error("gemm: invalid bias shape for broadcast"); } return [M, N, K]; } }; MIN_CLIP = -34028234663852886e22; MAX_CLIP = 34028234663852886e22; } }); // web/lib/wasm/jsep/tensor-view.ts var createView; var init_tensor_view = __esm({ "web/lib/wasm/jsep/tensor-view.ts"() { "use strict"; init_wasm_common(); createView = (dataBuffer, type) => new (tensorTypeToTypedArrayConstructor(type))(dataBuffer); } }); // web/lib/wasm/jsep/webnn/tensor-manager.ts var webnnDataTypeToSize, convertDataToInt32, convertInt32ToData, tensorGuid, createNewTensorId, webnnDataTypeToFallback, calculateByteLength, TensorWrapper, TensorIdTracker, TensorManagerImpl, createTensorManager; var init_tensor_manager = __esm({ "web/lib/wasm/jsep/webnn/tensor-manager.ts"() { "use strict"; init_wasm_common(); init_log(); webnnDataTypeToSize = /* @__PURE__ */ new Map([ ["float32", 32], ["float16", 16], ["int32", 32], ["uint32", 32], ["int64", 64], ["uint64", 64], ["int8", 8], ["uint8", 8], ["int4", 4], ["uint4", 4] ]); convertDataToInt32 = (data, dataType) => { if (dataType === "int32") { return data; } const dataTypeSize = webnnDataTypeToSize.get(dataType); if (!dataTypeSize) { throw new Error(`WebNN backend does not support data type: ${dataType}`); } const bytesPerElement = dataTypeSize / 8; if (data.byteLength % bytesPerElement !== 0) { throw new Error(`Invalid Uint8Array length - must be a multiple of ${bytesPerElement}.`); } const numElements = data.byteLength / bytesPerElement; const originalArray = new (tensorTypeToTypedArrayConstructor(dataType))(data.buffer, data.byteOffset, numElements); switch (dataType) { case "int64": case "uint64": { const int32Array = new Int32Array(numElements); for (let i = 0; i < numElements; i++) { const value = originalArray[i]; if (value > 2147483647n || value < -2147483648n) { throw new Error(`Can not convert int64 data to int32 - value out of range.`); } int32Array[i] = Number(value); } return new Uint8Array(int32Array.buffer); } case "int8": case "uint8": case "uint32": { if (dataType === "uint32") { if (originalArray.some((value) => value > 2147483647)) { throw new Error(`Can not convert uint32 data to int32 - value out of range.`); } } const int32Array = Int32Array.from(originalArray, Number); return new Uint8Array(int32Array.buffer); } default: throw new Error(`Unsupported data conversion from ${dataType} to 'int32'`); } }; convertInt32ToData = (data, dataType) => { if (dataType === "int32") { return data; } if (data.byteLength % 4 !== 0) { throw new Error("Invalid Uint8Array length - must be a multiple of 4 (int32)."); } const numElements = data.byteLength / 4; const int32Array = new Int32Array(data.buffer, data.byteOffset, numElements); switch (dataType) { case "int64": { const bigInt64Array = BigInt64Array.from(int32Array, BigInt); return new Uint8Array(bigInt64Array.buffer); } case "uint64": { if (int32Array.some((value) => value < 0)) { throw new Error("Can not convert int32 data to uin64 - negative value found."); } const bigUint64Array = BigUint64Array.from(int32Array, BigInt); return new Uint8Array(bigUint64Array.buffer); } case "int8": { if (int32Array.some((value) => value < -128 || value > 127)) { throw new Error("Can not convert int32 data to int8 - value out of range."); } const int8Array = Int8Array.from(int32Array, Number); return new Uint8Array(int8Array.buffer); } case "uint8": { if (int32Array.some((value) => value < 0 || value > 255)) { throw new Error("Can not convert int32 data to uint8 - value out of range."); } return Uint8Array.from(int32Array, Number); } case "uint32": { if (int32Array.some((value) => value < 0)) { throw new Error("Can not convert int32 data to uint32 - negative value found."); } const uint32Array = Uint32Array.from(int32Array, Number); return new Uint8Array(uint32Array.buffer); } default: throw new Error(`Unsupported data conversion from 'int32' to ${dataType}`); } }; tensorGuid = 1; createNewTensorId = () => tensorGuid++; webnnDataTypeToFallback = /* @__PURE__ */ new Map([ ["int8", "int32"], ["uint8", "int32"], ["uint32", "int32"], ["int64", "int32"] ]); calculateByteLength = (dataType, shape) => { const dataTypeSize = webnnDataTypeToSize.get(dataType); if (!dataTypeSize) { throw new Error(`WebNN backend does not support data type: ${dataType}`); } return shape.length > 0 ? Math.ceil(shape.reduce((a, b) => a * b) * dataTypeSize / 8) : 0; }; TensorWrapper = class { constructor(descriptor) { // This flag is used to indicate whether the data has been converted to fallback data type. this.isDataConverted = false; const { sessionId, context, tensor, dataType, shape, fallbackDataType } = descriptor; this.sessionId = sessionId; this.mlContext = context; this.mlTensor = tensor; this.dataType = dataType; this.tensorShape = shape; this.fallbackDataType = fallbackDataType; } get tensor() { return this.mlTensor; } get type() { return this.dataType; } get fallbackType() { return this.fallbackDataType; } get shape() { return this.tensorShape; } get byteLength() { return calculateByteLength(this.dataType, this.tensorShape); } destroy() { LOG_DEBUG("verbose", () => "[WebNN] TensorWrapper.destroy"); this.mlTensor.destroy(); } write(data) { this.mlContext.writeTensor(this.mlTensor, data); } async read(dstBuffer) { if (this.fallbackDataType) { const data = await this.mlContext.readTensor(this.mlTensor); const originalData = convertInt32ToData(new Uint8Array(data), this.dataType); if (dstBuffer) { const targetBuffer = dstBuffer instanceof ArrayBuffer ? new Uint8Array(dstBuffer) : new Uint8Array(dstBuffer.buffer, dstBuffer.byteOffset, dstBuffer.byteLength); targetBuffer.set(originalData); return void 0; } else { return originalData.buffer; } } else { return dstBuffer ? this.mlContext.readTensor(this.mlTensor, dstBuffer) : this.mlContext.readTensor(this.mlTensor); } } canReuseTensor(context, dataType, shape) { return this.mlContext === context && this.dataType === dataType && this.tensorShape.length === shape.length && this.tensorShape.every((v, i) => v === shape[i]); } setIsDataConverted(isConverted) { this.isDataConverted = isConverted; } }; TensorIdTracker = class { constructor(tensorManager, wrapper) { this.tensorManager = tensorManager; this.wrapper = wrapper; } get tensorWrapper() { return this.wrapper; } releaseTensor() { if (this.tensorWrapper) { this.tensorManager.releaseTensor(this.tensorWrapper); this.wrapper = void 0; } } async ensureTensor(sessionId, dataType, shape, copyOld) { const context = this.tensorManager.getMLContext(sessionId); const opLimits = this.tensorManager.getMLOpSupportLimits(sessionId); let fallbackDataType; if (!opLimits?.input.dataTypes.includes(dataType)) { fallbackDataType = webnnDataTypeToFallback.get(dataType); if (!fallbackDataType || opLimits?.input.dataTypes.includes(fallbackDataType)) { throw new Error(`WebNN backend does not support data type: ${dataType}`); } LOG_DEBUG( "verbose", () => `[WebNN] TensorIdTracker.ensureTensor: fallback dataType from ${dataType} to ${fallbackDataType}` ); } if (this.wrapper) { if (this.wrapper.canReuseTensor(context, dataType, shape)) { return this.wrapper.tensor; } else { if (copyOld) { if (this.wrapper.byteLength !== calculateByteLength(dataType, shape)) { throw new Error("Unable to copy data to tensor with different size."); } this.activeUpload = new Uint8Array(await this.wrapper.read()); } this.tensorManager.releaseTensor(this.wrapper); } } const usage = typeof MLTensorUsage == "undefined" ? void 0 : MLTensorUsage.READ | MLTensorUsage.WRITE; this.wrapper = await this.tensorManager.getCachedTensor( sessionId, dataType, shape, usage, true, true, fallbackDataType ); if (copyOld && this.activeUpload) { this.wrapper.write(this.activeUpload); this.activeUpload = void 0; } return this.wrapper.tensor; } upload(data) { let newData = data; if (this.wrapper) { if (this.wrapper.fallbackType) { if (this.wrapper.fallbackType === "int32") { newData = convertDataToInt32(data, this.wrapper.type); this.wrapper.setIsDataConverted(true); } else { throw new Error(`Unsupported fallback data type: ${this.wrapper.fallbackType}`); } } if (data.byteLength === this.wrapper.byteLength) { this.wrapper.write(newData); return; } else { LOG_DEBUG("verbose", () => "Data size does not match tensor size. Releasing tensor."); this.releaseTensor(); } } if (this.activeUpload) { this.activeUpload.set(newData); } else { this.activeUpload = new Uint8Array(newData); } } async download(dstBuffer) { if (this.activeUpload) { const dstData = this.wrapper?.isDataConverted ? convertInt32ToData(this.activeUpload, this.wrapper?.type) : this.activeUpload; if (dstBuffer) { if (dstBuffer instanceof ArrayBuffer) { new Uint8Array(dstBuffer).set(dstData); } else { new Uint8Array(dstBuffer.buffer, dstBuffer.byteOffset, dstBuffer.byteLength).set(dstData); } return; } else { return dstData.buffer; } } if (!this.wrapper) { throw new Error("Tensor has not been created."); } if (!dstBuffer) { return this.wrapper.read(); } return this.wrapper.read(dstBuffer); } }; TensorManagerImpl = class { constructor(backend) { this.backend = backend; this.tensorTrackersById = /* @__PURE__ */ new Map(); this.freeTensors = []; this.externalTensors = /* @__PURE__ */ new Set(); } getMLContext(sessionId) { const context = this.backend.getMLContext(sessionId); if (!context) { throw new Error("MLContext not found for session."); } return context; } getMLOpSupportLimits(sessionId) { return this.backend.getMLOpSupportLimits(sessionId); } reserveTensorId() { const tensorId = createNewTensorId(); this.tensorTrackersById.set(tensorId, new TensorIdTracker(this)); return tensorId; } releaseTensorId(tensorId) { const tensorTracker = this.tensorTrackersById.get(tensorId); if (!tensorTracker) { return; } this.tensorTrackersById.delete(tensorId); if (tensorTracker.tensorWrapper) { this.releaseTensor(tensorTracker.tensorWrapper); } } async ensureTensor(sessionId, tensorId, dataType, shape, copyOld) { LOG_DEBUG( "verbose", () => `[WebNN] TensorManager.ensureTensor {tensorId: ${tensorId}, dataType: ${dataType}, shape: ${shape}, copyOld: ${copyOld}}` ); const tensor = this.tensorTrackersById.get(tensorId); if (!tensor) { throw new Error("Tensor not found."); } return tensor.ensureTensor(sessionId, dataType, shape, copyOld); } upload(tensorId, data) { const tensor = this.tensorTrackersById.get(tensorId); if (!tensor) { throw new Error("Tensor not found."); } tensor.upload(data); } async download(tensorId, dstBuffer) { LOG_DEBUG( "verbose", () => `[WebNN] TensorManager.download {tensorId: ${tensorId}, dstBuffer: ${dstBuffer?.byteLength}}` ); const tensorTracker = this.tensorTrackersById.get(tensorId); if (!tensorTracker) { throw new Error("Tensor not found."); } return tensorTracker.download(dstBuffer); } releaseTensorsForSession(sessionId) { for (const tensor of this.freeTensors) { if (tensor.sessionId === sessionId) { tensor.destroy(); } } this.freeTensors = this.freeTensors.filter((tensor) => tensor.sessionId !== sessionId); } registerTensor(sessionId, mlTensor, dataType, shape) { const context = this.getMLContext(sessionId); const tensorId = createNewTensorId(); const wrapper = new TensorWrapper({ sessionId, context, tensor: mlTensor, dataType, shape }); this.tensorTrackersById.set(tensorId, new TensorIdTracker(this, wrapper)); this.externalTensors.add(wrapper); return tensorId; } /** * Get or create an MLTensor with the given data type and shape. */ async getCachedTensor(sessionId, dataType, shape, usage, writable, readable, fallbackDataType) { const context = this.getMLContext(sessionId); for (const [index, tensor2] of this.freeTensors.entries()) { if (tensor2.canReuseTensor(context, dataType, shape)) { LOG_DEBUG( "verbose", () => `[WebNN] Reusing tensor {dataType: ${dataType}, ${fallbackDataType ? `fallbackDataType: ${fallbackDataType},` : ""} shape: ${shape}` ); const wrapper = this.freeTensors.splice(index, 1)[0]; wrapper.sessionId = sessionId; return wrapper; } } LOG_DEBUG( "verbose", () => `[WebNN] MLContext.createTensor {dataType: ${dataType}, ${fallbackDataType ? `fallbackDataType: ${fallbackDataType},` : ""} shape: ${shape}}` ); const tensor = await context.createTensor({ dataType: fallbackDataType ?? dataType, // If fallback data type is provided, use it. shape, dimensions: shape, usage, writable, readable }); return new TensorWrapper({ sessionId, context, tensor, dataType, shape, fallbackDataType }); } /** * Release tensor for reuse unless external. */ releaseTensor(tensorWrapper) { if (this.externalTensors.has(tensorWrapper)) { this.externalTensors.delete(tensorWrapper); } this.freeTensors.push(tensorWrapper); } }; createTensorManager = (...args) => new TensorManagerImpl(...args); } }); // web/lib/wasm/jsep/backend-webnn.ts var onnxDataTypeToWebnnDataType, compareMLContextOptions, WebNNBackend; var init_backend_webnn = __esm({ "web/lib/wasm/jsep/backend-webnn.ts"() { "use strict"; init_wasm_common(); init_wasm_factory(); init_tensor_view(); init_tensor_manager(); init_log(); onnxDataTypeToWebnnDataType = /* @__PURE__ */ new Map([ [1 /* float */, "float32"], [10 /* float16 */, "float16"], [6 /* int32 */, "int32"], [12 /* uint32 */, "uint32"], [7 /* int64 */, "int64"], [13 /* uint64 */, "uint64"], [22 /* int4 */, "int4"], [21 /* uint4 */, "uint4"], [3 /* int8 */, "int8"], [2 /* uint8 */, "uint8"], [9 /* bool */, "uint8"] ]); compareMLContextOptions = (a, b) => { if (a === b) { return true; } if (a === void 0 || b === void 0) { return false; } const aKeys = Object.keys(a).sort(); const bKeys = Object.keys(b).sort(); return aKeys.length === bKeys.length && aKeys.every((key, index) => key === bKeys[index] && a[key] === b[key]); }; WebNNBackend = class { constructor(env3) { /** * Tensor managers for each session. */ this.tensorManager = createTensorManager(this); /** * Maps from session id to MLContexts. */ this.mlContextBySessionId = /* @__PURE__ */ new Map(); /** * Maps from MLContext to session ids. */ this.sessionIdsByMLContext = /* @__PURE__ */ new Map(); /** * Cache of MLContexts. */ this.mlContextCache = []; /** * Maps from session id to list of graph inputs. */ this.sessionGraphInputs = /* @__PURE__ */ new Map(); /** * Maps from session id to list of graph outputs. */ this.sessionGraphOutputs = /* @__PURE__ */ new Map(); /** * Temporary graph inputs for the current session. * These inputs will be registered when the session is created. */ this.temporaryGraphInputs = []; /** * Temporary graph outputs for the current session. * These outputs will be registered when the session is created. */ this.temporaryGraphOutputs = []; /** * Temporary tensors for the current session. */ this.temporarySessionTensorIds = /* @__PURE__ */ new Map(); /** * Maps from session id to MLOpSupportLimits. */ this.mlOpSupportLimitsBySessionId = /* @__PURE__ */ new Map(); configureLogger(env3.logLevel, !!env3.debug); } get currentSessionId() { if (this.activeSessionId === void 0) { throw new Error("No active session"); } return this.activeSessionId; } onRunStart(sessionId) { LOG_DEBUG("verbose", () => `[WebNN] onRunStart {sessionId: ${sessionId}}`); this.activeSessionId = sessionId; } onRunEnd(sessionId) { LOG_DEBUG("verbose", () => `[WebNN] onRunEnd {sessionId: ${sessionId}}`); const tensorIds = this.temporarySessionTensorIds.get(sessionId); if (!tensorIds) { return; } for (const tensorId of tensorIds) { LOG_DEBUG("verbose", () => `[WebNN] releasing temporary tensor {tensorId: ${tensorId}}`); this.tensorManager.releaseTensorId(tensorId); } this.temporarySessionTensorIds.delete(sessionId); this.activeSessionId = void 0; } async createMLContext(optionsOrDevice) { if (optionsOrDevice instanceof GPUDevice) { const mlContextIndex2 = this.mlContextCache.findIndex((entry) => entry.gpuDevice === optionsOrDevice); if (mlContextIndex2 !== -1) { return this.mlContextCache[mlContextIndex2].mlContext; } else { const mlContext = await navigator.ml.createContext(optionsOrDevice); this.mlContextCache.push({ gpuDevice: optionsOrDevice, mlContext }); return mlContext; } } else if (optionsOrDevice === void 0) { const mlContextIndex2 = this.mlContextCache.findIndex( (entry) => entry.options === void 0 && entry.gpuDevice === void 0 ); if (mlContextIndex2 !== -1) { return this.mlContextCache[mlContextIndex2].mlContext; } else { const mlContext = await navigator.ml.createContext(); this.mlContextCache.push({ mlContext }); return mlContext; } } const mlContextIndex = this.mlContextCache.findIndex( (entry) => compareMLContextOptions(entry.options, optionsOrDevice) ); if (mlContextIndex !== -1) { return this.mlContextCache[mlContextIndex].mlContext; } else { const mlContext = await navigator.ml.createContext(optionsOrDevice); this.mlContextCache.push({ options: optionsOrDevice, mlContext }); return mlContext; } } registerMLContext(sessionId, mlContext) { this.mlContextBySessionId.set(sessionId, mlContext); let sessionIds = this.sessionIdsByMLContext.get(mlContext); if (!sessionIds) { sessionIds = /* @__PURE__ */ new Set(); this.sessionIdsByMLContext.set(mlContext, sessionIds); } sessionIds.add(sessionId); if (!this.mlOpSupportLimitsBySessionId.has(sessionId)) { this.mlOpSupportLimitsBySessionId.set(sessionId, mlContext.opSupportLimits()); } if (this.temporaryGraphInputs.length > 0) { this.sessionGraphInputs.set(sessionId, this.temporaryGraphInputs); this.temporaryGraphInputs = []; } if (this.temporaryGraphOutputs.length > 0) { this.sessionGraphOutputs.set(sessionId, this.temporaryGraphOutputs); this.temporaryGraphOutputs = []; } } onReleaseSession(sessionId) { this.sessionGraphInputs.delete(sessionId); this.sessionGraphOutputs.delete(sessionId); const mlContext = this.mlContextBySessionId.get(sessionId); if (!mlContext) { return; } this.tensorManager.releaseTensorsForSession(sessionId); this.mlContextBySessionId.delete(sessionId); this.mlOpSupportLimitsBySessionId.delete(sessionId); const sessionIds = this.sessionIdsByMLContext.get(mlContext); sessionIds.delete(sessionId); if (sessionIds.size === 0) { this.sessionIdsByMLContext.delete(mlContext); const mlContextIndex = this.mlContextCache.findIndex((entry) => entry.mlContext === mlContext); if (mlContextIndex !== -1) { this.mlContextCache.splice(mlContextIndex, 1); } } } getMLContext(sessionId) { return this.mlContextBySessionId.get(sessionId); } getMLOpSupportLimits(sessionId) { return this.mlOpSupportLimitsBySessionId.get(sessionId); } reserveTensorId() { return this.tensorManager.reserveTensorId(); } releaseTensorId(tensorId) { LOG_DEBUG("verbose", () => `[WebNN] releaseTensorId {tensorId: ${tensorId}}`); this.tensorManager.releaseTensorId(tensorId); } async ensureTensor(sessionId, tensorId, onnxDataType, dimensions, copyOld) { const webnnDataType = onnxDataTypeToWebnnDataType.get(onnxDataType); if (!webnnDataType) { throw new Error(`Unsupported ONNX data type: ${onnxDataType}`); } return this.tensorManager.ensureTensor( sessionId ?? this.currentSessionId, tensorId, webnnDataType, dimensions, copyOld ); } async createTemporaryTensor(sessionId, onnxDataType, shape) { LOG_DEBUG("verbose", () => `[WebNN] createTemporaryTensor {onnxDataType: ${onnxDataType}, shape: ${shape}}`); const dataType = onnxDataTypeToWebnnDataType.get(onnxDataType); if (!dataType) { throw new Error(`Unsupported ONNX data type: ${onnxDataType}`); } const tensorId = this.tensorManager.reserveTensorId(); await this.tensorManager.ensureTensor(sessionId, tensorId, dataType, shape, false); const tensorIds = this.temporarySessionTensorIds.get(sessionId); if (!tensorIds) { this.temporarySessionTensorIds.set(sessionId, [tensorId]); } else { tensorIds.push(tensorId); } return tensorId; } uploadTensor(tensorId, data) { const wasm2 = getInstance(); if (!wasm2.shouldTransferToMLTensor) { throw new Error("Trying to upload to a MLTensor while shouldTransferToMLTensor is false"); } LOG_DEBUG("verbose", () => `[WebNN] uploadTensor {tensorId: ${tensorId}, data: ${data.byteLength}}`); this.tensorManager.upload(tensorId, data); } async downloadTensor(tensorId, dstBuffer) { return this.tensorManager.download(tensorId, dstBuffer); } createMLTensorDownloader(tensorId, type) { return async () => { const data = await this.tensorManager.download(tensorId); return createView(data, type); }; } registerMLTensor(sessionId, tensor, onnxDataType, dimensions) { const webnnDataType = onnxDataTypeToWebnnDataType.get(onnxDataType); if (!webnnDataType) { throw new Error(`Unsupported ONNX data type: ${onnxDataType}`); } const id = this.tensorManager.registerTensor(sessionId, tensor, webnnDataType, dimensions); LOG_DEBUG( "verbose", () => `[WebNN] registerMLTensor {tensor: ${tensor}, dataType: ${webnnDataType}, dimensions: ${dimensions}} -> {tensorId: ${id}}` ); return id; } // Register a WebNN Constant operand from external data. registerMLConstant(externalFilePath, dataOffset, dataLength, builder, desc, mountedFiles, shouldConvertInt64ToInt32 = false) { if (!mountedFiles) { throw new Error("External mounted files are not available."); } let filePath = externalFilePath; if (externalFilePath.startsWith("./")) { filePath = externalFilePath.substring(2); } const fileData = mountedFiles.get(filePath); if (!fileData) { throw new Error(`File with name ${filePath} not found in preloaded files.`); } if (dataOffset + dataLength > fileData.byteLength) { throw new Error("Out of bounds: data offset and length exceed the external file data size."); } const buffer = fileData.slice(dataOffset, dataOffset + dataLength).buffer; let bufferView; switch (desc.dataType) { case "float32": bufferView = new Float32Array(buffer); break; case "float16": bufferView = typeof Float16Array !== "undefined" && Float16Array.from ? new Float16Array(buffer) : new Uint16Array(buffer); break; case "int32": bufferView = new Int32Array(buffer); break; case "uint32": bufferView = new Uint32Array(buffer); break; case "int64": if (shouldConvertInt64ToInt32) { const int32Buffer = convertDataToInt32(new Uint8Array(buffer), "int64"); bufferView = new Int32Array(int32Buffer.buffer); desc.dataType = "int32"; } else { bufferView = new BigInt64Array(buffer); } break; case "uint64": bufferView = new BigUint64Array(buffer); break; case "int8": bufferView = new Int8Array(buffer); break; case "int4": case "uint4": case "uint8": bufferView = new Uint8Array(buffer); break; default: throw new Error(`Unsupported data type: ${desc.dataType} in creating WebNN Constant from external data.`); } LOG_DEBUG( "verbose", () => `[WebNN] registerMLConstant {dataType: ${desc.dataType}, shape: ${desc.shape}}} ${shouldConvertInt64ToInt32 ? "(Note: it was int64 data type and registered to int32 as workaround)" : ""}` ); return builder.constant(desc, bufferView); } registerGraphInput(inputName) { this.temporaryGraphInputs.push(inputName); } registerGraphOutput(outputName) { this.temporaryGraphOutputs.push(outputName); } isGraphInput(sessionId, inputName) { const inputNames = this.sessionGraphInputs.get(sessionId); if (!inputNames) { return false; } return inputNames.includes(inputName); } isGraphOutput(sessionId, outputName) { const outputNames = this.sessionGraphOutputs.get(sessionId); if (!outputNames) { return false; } return outputNames.includes(outputName); } isGraphInputOutputTypeSupported(sessionId, type, isInput = true) { const dataType = onnxDataTypeToWebnnDataType.get(tensorDataTypeStringToEnum(type)); const opLimits = this.mlOpSupportLimitsBySessionId.get(sessionId); if (typeof dataType === "undefined") { return false; } if (isInput) { return !!opLimits?.input.dataTypes.includes(dataType); } else { return !!opLimits?.output.dataTypes.includes(dataType); } } flush() { } }; } }); // web/lib/wasm/jsep/webgpu/types.ts var init_types = __esm({ "web/lib/wasm/jsep/webgpu/types.ts"() { "use strict"; } }); // web/lib/wasm/jsep/webgpu/gpu-data-manager.ts var bucketFreelist, bucketArr, calcNormalizedBufferSize, calcBucketBufferSize, guid, createNewGpuDataId, downloadGpuData, GpuDataManagerImpl, createGpuDataManager; var init_gpu_data_manager = __esm({ "web/lib/wasm/jsep/webgpu/gpu-data-manager.ts"() { "use strict"; init_log(); init_types(); bucketFreelist = /* @__PURE__ */ new Map([ [64, 250], [128, 200], [256, 200], [512, 200], [2048, 230], [4096, 200], [8192, 50], [16384, 50], [32768, 50], [65536, 50], [131072, 50], [262144, 50], [524288, 50], [1048576, 50], [2097152, 30], [4194304, 20], [8388608, 10], [12582912, 10], [16777216, 10], [26214400, 15], [33554432, 22], [44236800, 2], [58982400, 6], // we don't want to cache the bucket sizes below but not caching them // results in some major performance hits for models like sd-turbo. [67108864, 6], [134217728, 6], [167772160, 6] ]); bucketArr = []; calcNormalizedBufferSize = (size) => Math.ceil(Number(size) / 16) * 16; calcBucketBufferSize = (size) => { for (let idx = 0; idx < bucketArr.length; idx++) { const sizeForBucket = bucketArr[idx]; if (size <= sizeForBucket) { return sizeForBucket; } } return Math.ceil(size / 16) * 16; }; guid = 1; createNewGpuDataId = () => guid++; downloadGpuData = async (backend, gpuBuffer, originalSize, getTargetBuffer) => { const bufferSize = calcNormalizedBufferSize(originalSize); const gpuReadBuffer = backend.device.createBuffer( // eslint-disable-next-line no-bitwise { size: bufferSize, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ } ); try { const commandEncoder = backend.getCommandEncoder(); backend.endComputePass(); commandEncoder.copyBufferToBuffer( gpuBuffer, 0, gpuReadBuffer, 0, bufferSize ); backend.flush(); await gpuReadBuffer.mapAsync(GPUMapMode.READ); const arrayBuffer = gpuReadBuffer.getMappedRange(); if (getTargetBuffer) { const targetBuffer = getTargetBuffer(); targetBuffer.set(new Uint8Array(arrayBuffer, 0, originalSize)); return targetBuffer; } else { return new Uint8Array(arrayBuffer.slice(0, originalSize)); } } finally { gpuReadBuffer.destroy(); } }; GpuDataManagerImpl = class { constructor(backend) { this.backend = backend; this.storageCache = /* @__PURE__ */ new Map(); this.freeBuffers = /* @__PURE__ */ new Map(); this.freeUniformBuffers = /* @__PURE__ */ new Map(); this.buffersPending = []; this.capturedPendingBuffers = /* @__PURE__ */ new Map(); for (const [key] of bucketFreelist) { bucketArr.push(key); this.freeBuffers.set(key, []); this.freeUniformBuffers.set(key, []); } this.sessionCount = 0; } upload(id, data) { const srcArrayBuffer = data.buffer; const srcOffset = data.byteOffset; const srcLength = data.byteLength; const size = calcNormalizedBufferSize(srcLength); const gpuDataCache = this.storageCache.get(id); if (!gpuDataCache) { throw new Error("gpu data for uploading does not exist"); } if (Number(gpuDataCache.originalSize) !== srcLength) { throw new Error(`inconsistent data size. gpu data size=${gpuDataCache.originalSize}, data size=${srcLength}`); } const gpuBufferForUploading = this.backend.device.createBuffer( // eslint-disable-next-line no-bitwise { mappedAtCreation: true, size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC } ); const arrayBuffer = gpuBufferForUploading.getMappedRange(); new Uint8Array(arrayBuffer).set(new Uint8Array(srcArrayBuffer, srcOffset, srcLength)); gpuBufferForUploading.unmap(); const commandEncoder = this.backend.device.createCommandEncoder(); commandEncoder.copyBufferToBuffer(gpuBufferForUploading, 0, gpuDataCache.gpuData.buffer, 0, size); this.backend.device.queue.submit([commandEncoder.finish()]); gpuBufferForUploading.destroy(); LOG_DEBUG("verbose", () => `[WebGPU] GpuDataManager.upload(id=${id})`); } memcpy(sourceId, destinationId) { const sourceGpuDataCache = this.storageCache.get(sourceId); if (!sourceGpuDataCache) { throw new Error("source gpu data for memcpy does not exist"); } const destinationGpuDataCache = this.storageCache.get(destinationId); if (!destinationGpuDataCache) { throw new Error("destination gpu data for memcpy does not exist"); } if (sourceGpuDataCache.originalSize !== destinationGpuDataCache.originalSize) { throw new Error("inconsistent source and destination gpu data size"); } const size = calcNormalizedBufferSize(sourceGpuDataCache.originalSize); const commandEncoder = this.backend.getCommandEncoder(); this.backend.endComputePass(); commandEncoder.copyBufferToBuffer( sourceGpuDataCache.gpuData.buffer, 0, destinationGpuDataCache.gpuData.buffer, 0, size ); } registerExternalBuffer(buffer, originalSize, previous) { let id; if (previous) { id = previous[0]; if (buffer === previous[1]) { LOG_DEBUG( "verbose", () => `[WebGPU] GpuDataManager.registerExternalBuffer(size=${originalSize}) => id=${id}, buffer is the same, skip.` ); return id; } else if (this.backend.capturedCommandList.has(this.backend.currentSessionId)) { throw new Error(`Registering a different external buffer under graph capture mode is not supported yet. Please use the previous external buffer!`); } } else { id = createNewGpuDataId(); } this.storageCache.set(id, { gpuData: { id, type: 0 /* default */, buffer }, originalSize }); LOG_DEBUG( "verbose", () => `[WebGPU] GpuDataManager.registerExternalBuffer(size=${originalSize}) => id=${id}, registered.` ); return id; } unregisterExternalBuffer(id) { if (id !== void 0) { this.storageCache.delete(id); LOG_DEBUG("verbose", () => `[WebGPU] GpuDataManager.unregisterExternalBuffer() => id=${id}`); } } // eslint-disable-next-line no-bitwise create(size, usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST) { const bufferSize = calcBucketBufferSize(size); let gpuBuffer; const isStorage = (usage & GPUBufferUsage.STORAGE) === GPUBufferUsage.STORAGE; const isUniform = (usage & GPUBufferUsage.UNIFORM) === GPUBufferUsage.UNIFORM; if (isStorage || isUniform) { const freeBuffers = isStorage ? this.freeBuffers : this.freeUniformBuffers; const buffers = freeBuffers.get(bufferSize); if (!buffers) { gpuBuffer = this.backend.device.createBuffer({ size: bufferSize, usage }); } else { if (buffers.length > 0) { gpuBuffer = buffers.pop(); } else { gpuBuffer = this.backend.device.createBuffer({ size: bufferSize, usage }); } } } else { gpuBuffer = this.backend.device.createBuffer({ size: bufferSize, usage }); } const gpuData = { id: createNewGpuDataId(), type: 0 /* default */, buffer: gpuBuffer }; this.storageCache.set(gpuData.id, { gpuData, originalSize: Number(size) }); LOG_DEBUG("verbose", () => `[WebGPU] GpuDataManager.create(size=${size}) => id=${gpuData.id}`); return gpuData; } get(id) { return this.storageCache.get(id)?.gpuData; } release(idInput) { const id = typeof idInput === "bigint" ? Number(idInput) : idInput; const cachedData = this.storageCache.get(id); if (!cachedData) { if (this.storageCache.size === 0) { return 0; } else { throw new Error("releasing data does not exist"); } } LOG_DEBUG("verbose", () => `[WebGPU] GpuDataManager.release(id=${id}), gpuDataId=${cachedData.gpuData.id}`); this.storageCache.delete(id); this.buffersPending.push(cachedData.gpuData.buffer); return cachedData.originalSize; } async download(id, getTargetBuffer) { const cachedData = this.storageCache.get(Number(id)); if (!cachedData) { throw new Error("data does not exist"); } await downloadGpuData(this.backend, cachedData.gpuData.buffer, cachedData.originalSize, getTargetBuffer); } refreshPendingBuffers() { if (this.buffersPending.length === 0) { return; } if (this.backend.sessionStatus === "default") { for (const buffer of this.buffersPending) { const maxInFreeList = bucketFreelist.get(buffer.size); if ((buffer.usage & GPUBufferUsage.STORAGE) === GPUBufferUsage.STORAGE) { const freelist = this.freeBuffers.get(buffer.size) || []; if (maxInFreeList === void 0 || freelist.length >= maxInFreeList) { buffer.destroy(); } else { freelist.push(buffer); } } else if ((buffer.usage & GPUBufferUsage.UNIFORM) === GPUBufferUsage.UNIFORM) { const freelist = this.freeUniformBuffers.get(buffer.size) || []; if (maxInFreeList === void 0 || freelist.length >= maxInFreeList) { buffer.destroy(); } else { freelist.push(buffer); } } else { buffer.destroy(); } } this.buffersPending = []; } else { let capturedBuffers = this.capturedPendingBuffers.get(this.backend.currentSessionId); if (!capturedBuffers) { capturedBuffers = []; this.capturedPendingBuffers.set(this.backend.currentSessionId, capturedBuffers); } for (const buffer of this.buffersPending) { capturedBuffers.push(buffer); } this.buffersPending = []; } } dispose() { this.freeBuffers.forEach((buffers) => { buffers.forEach((buffer) => { buffer.destroy(); }); }); this.freeUniformBuffers.forEach((buffers) => { buffers.forEach((buffer) => { buffer.destroy(); }); }); this.storageCache.forEach((storage) => { storage.gpuData.buffer.destroy(); }); this.capturedPendingBuffers.forEach((buffers) => { buffers.forEach((buffer) => { buffer.destroy(); }); }); this.storageCache = /* @__PURE__ */ new Map(); this.freeBuffers = /* @__PURE__ */ new Map(); this.freeUniformBuffers = /* @__PURE__ */ new Map(); this.capturedPendingBuffers = /* @__PURE__ */ new Map(); } onCreateSession() { this.sessionCount += 1; } onReleaseSession(sessionId) { const pendingBuffers = this.capturedPendingBuffers.get(sessionId); if (pendingBuffers) { pendingBuffers.forEach((buffer) => { buffer.destroy(); }); this.capturedPendingBuffers.delete(sessionId); } this.sessionCount -= 1; if (this.sessionCount === 0) { LOG_DEBUG("warning", () => "[WebGPU] Clearing webgpu buffer cache"); this.storageCache.forEach((storage) => { storage.gpuData.buffer.destroy(); }); this.storageCache = /* @__PURE__ */ new Map(); } } }; createGpuDataManager = (...args) => new GpuDataManagerImpl(...args); } }); // web/lib/wasm/jsep/webgpu/attribute-with-cache-key.ts var AttributeWithCacheKeyImpl, createAttributeWithCacheKey; var init_attribute_with_cache_key = __esm({ "web/lib/wasm/jsep/webgpu/attribute-with-cache-key.ts"() { "use strict"; AttributeWithCacheKeyImpl = class { constructor(attribute) { Object.assign(this, attribute); } get cacheKey() { if (!this.key) { this.key = Object.getOwnPropertyNames(this).sort().map((name) => `${this[name]}`).join(";"); } return this.key; } }; createAttributeWithCacheKey = (attribute) => new AttributeWithCacheKeyImpl(attribute); } }); // web/lib/wasm/jsep/webgpu/ops/common.ts var WORKGROUP_SIZE, getWgslMappedType, tensorTypeToWsglStorageType, tensorTypeToWsglValueType, createTensorShapeVariables, getMaxComponents, fillVector, castToF32, sumVector, getElementAt, createIndicesHelper, inputVariable, outputVariable, atomicOutputVariable, internalVariable, ShaderHelperImpl, createShaderHelper; var init_common = __esm({ "web/lib/wasm/jsep/webgpu/ops/common.ts"() { "use strict"; init_wasm_common(); init_util(); WORKGROUP_SIZE = 64; getWgslMappedType = (type, components) => { if (components === 3) { throw new Error("vec3 has same alignment as vec4, use vec4 instead"); } switch (Number(type)) { case 10 /* float16 */: return components > 1 ? `vec${components}` : "f16"; case 1 /* float */: return components > 1 ? `vec${components}` : "f32"; case 6 /* int32 */: return components > 1 ? `vec${components}` : "i32"; case 12 /* uint32 */: return components > 1 ? `vec${components}` : "u32"; case 7 /* int64 */: if (components > 1) { throw new Error("currently not supported vecX of uint64 yet"); } return ["vec2", "i32"]; case 13 /* uint64 */: if (components > 1) { throw new Error("currently not supported vecX of uint64 yet"); } return ["vec2", "u32"]; case 9 /* bool */: if (components !== 4) { throw new Error("bool must be vec4"); } return ["u32", "vec4"]; case 22 /* int4 */: return "i32"; case 21 /* uint4 */: return "u32"; default: throw new Error(`Unknown data type: ${type}`); } }; tensorTypeToWsglStorageType = (type, components = 1) => { const mappedType = getWgslMappedType(type, components); return typeof mappedType === "string" ? mappedType : mappedType[0]; }; tensorTypeToWsglValueType = (type, components = 1) => { const mappedType = getWgslMappedType(type, components); return typeof mappedType === "string" ? mappedType : mappedType[1]; }; createTensorShapeVariables = (...dims) => { const programUniforms = []; dims.forEach((dim) => { if (dim.length !== 0) { programUniforms.push( { type: 12 /* uint32 */, data: dim }, { type: 12 /* uint32 */, data: ShapeUtil.computeStrides(dim) } ); } }); return programUniforms; }; getMaxComponents = (size) => { if (size % 4 === 0) { return 4; } else if (size % 2 === 0) { return 2; } return 1; }; fillVector = (dataType = "f32", components, value = "0") => { if (!components || components === 1) { return `${dataType}(${value})`; } return `vec${components}<${dataType}>(${value})`; }; castToF32 = (dataType, components, value) => { if (dataType === "f32") { return value; } if (components === 1) { return `f32(${value})`; } return `vec${components}(${value})`; }; sumVector = (name, components) => { if (components === 4) { return `(${name}.x + ${name}.y + ${name}.z + ${name}.w)`; } else if (components === 2) { return `(${name}.x + ${name}.y)`; } else if (components === 3) { return `(${name}.x + ${name}.y + ${name}.z)`; } return name; }; getElementAt = (name, index, length, type) => { if (name.startsWith("uniforms.") && length > 4) { if (typeof index === "string") { if (type === "f16") { return `${name}[(${index}) / 8][(${index}) % 8 / 4][(${index}) % 8 % 4]`; } else { return `${name}[(${index}) / 4][(${index}) % 4]`; } } else { if (type === "f16") { return `${name}[${Math.floor(index / 8)}][${Math.floor(index % 8 / 4)}][${index % 8 % 4}]`; } else { return `${name}[${Math.floor(index / 4)}][${index % 4}]`; } } } else { return length > 1 ? `${name}[${index}]` : name; } }; createIndicesHelper = (name, tensorType, shapeOrRank, usage, components) => { const useUniform = typeof shapeOrRank === "number"; const rank = useUniform ? shapeOrRank : shapeOrRank.length; const rankIdentity = [...new Array(rank).keys()]; const indicesType = rank < 2 ? "u32" : rank <= 4 ? `vec${rank}` : `array`; const mappedType = getWgslMappedType(tensorType, components); const valueType = typeof mappedType === "string" ? mappedType : mappedType[1]; const storageType = typeof mappedType === "string" ? mappedType : mappedType[0]; const type = { indices: indicesType, value: valueType, storage: storageType, tensor: tensorType }; const normalizeDim = (dim) => typeof dim === "string" ? dim : `${dim}u`; const implementationUsed = { offsetToIndices: false, indicesToOffset: false, broadcastedIndicesToOffset: false, set: false, setByIndices: false, get: false, getByIndices: false }; const uniformPrefix = useUniform ? "uniforms." : ""; const shape = `${uniformPrefix}${name}_shape`; const strides = `${uniformPrefix}${name}_strides`; let o2iSnippet = ""; for (let i = 0; i < rank - 1; i++) { o2iSnippet += ` let dim${i} = current / ${getElementAt(strides, i, rank)}; let rest${i} = current % ${getElementAt(strides, i, rank)}; indices[${i}] = dim${i}; current = rest${i}; `; } o2iSnippet += `indices[${rank - 1}] = current;`; const offsetToIndicesImplementation = rank < 2 ? "" : ` fn o2i_${name}(offset: u32) -> ${type.indices} { var indices: ${type.indices}; var current = offset; ${o2iSnippet} return indices; }`; const offsetToIndices = (varOffset) => { implementationUsed.offsetToIndices = true; return rank < 2 ? varOffset : `o2i_${name}(${varOffset})`; }; const offsets = []; if (rank >= 2) { for (let i = rank - 1; i >= 0; i--) { offsets.push(`${getElementAt(strides, i, rank)} * (indices[${i}])`); } } const indicesToOffsetImplementation = rank < 2 ? "" : ` fn i2o_${name}(indices: ${type.indices}) -> u32 { return ${offsets.join("+")}; }`; const indicesToOffset = (varIndices) => { implementationUsed.indicesToOffset = true; return rank < 2 ? varIndices : `i2o_${name}(${varIndices})`; }; const indices = (...init2) => rank === 0 ? "0u" : `${type.indices}(${init2.map(normalizeDim).join(",")})`; const indicesGet = (varIndices, idx) => { if (rank < 2) { return `${varIndices}`; } else { return `${getElementAt(varIndices, idx, rank)}`; } }; const indicesSet = (varIndices, idx, value) => { if (rank < 2) { return `${varIndices}=${value};`; } else { return `${getElementAt(varIndices, idx, rank)}=${value};`; } }; const broadcastedIndicesToOffsetImplementation = {}; const broadcastedIndicesToOffset = (varIndices, output) => { implementationUsed.broadcastedIndicesToOffset = true; const implKey = `${output.name}broadcastedIndicesTo${name}Offset`; if (implKey in broadcastedIndicesToOffsetImplementation) { return `${implKey}(${varIndices})`; } const offsets2 = []; for (let i = rank - 1; i >= 0; i--) { const idx = output.indicesGet("outputIndices", i + output.rank - rank); offsets2.push(`${indicesGet(strides, i)} * (${idx} % ${indicesGet(shape, i)})`); } broadcastedIndicesToOffsetImplementation[implKey] = `fn ${implKey}(outputIndices: ${output.type.indices}) -> u32 { return ${offsets2.length > 0 ? offsets2.join("+") : "0u"}; }`; return `${implKey}(${varIndices})`; }; const setByOffset = (offset, value) => (() => { if (type.storage === type.value) { return `${name}[${offset}]=${value};`; } else if (type.storage === "vec2" && type.value === "i32") { return `${name}[${offset}]=vec2(u32(${value}), select(0u, 0xFFFFFFFFu, ${value} < 0));`; } else if (type.storage === "vec2" && type.value === "u32") { return `${name}[${offset}]=vec2(u32(${value}), 0u);`; } else if (type.storage === "u32" && type.value === "vec4") { return `${name}[${offset}]=dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(${value}));`; } else { throw new Error(`not supported combination of storage type ${type.storage} and value type ${type.value} yet`); } })(); const getByOffset = (offset) => (() => { if (type.storage === type.value) { return `${name}[${offset}]`; } else if (type.storage === "vec2" && type.value === "i32") { return `i32(${name}[${offset}].x)`; } else if (type.storage === "vec2" && type.value === "u32") { return `u32(${name}[${offset}].x)`; } else if (type.storage === "u32" && type.value === "vec4") { return `vec4(bool(${name}[${offset}] & 0xFFu), bool(${name}[${offset}] & 0xFF00u), bool(${name}[${offset}] & 0xFF0000u), bool(${name}[${offset}] & 0xFF000000u))`; } else { throw new Error(`not supported combination of storage type ${type.storage} and value type ${type.value} yet`); } })(); const getByIndicesImplementation = rank < 2 ? "" : ` fn get_${name}ByIndices(indices: ${type.indices}) -> ${valueType} { return ${getByOffset(`i2o_${name}(indices)`)}; }`; const getImplementation = rank < 2 ? "" : (() => { const functionParams = rankIdentity.map((i) => `d${i}: u32`).join(", "); const dimsParams = rankIdentity.map((i) => `d${i}`).join(", "); return ` fn get_${name}(${functionParams}) -> ${valueType} { return get_${name}ByIndices(${indices(dimsParams)}); }`; })(); const get = (...indices2) => { if (indices2.length !== rank) { throw new Error(`indices length must be ${rank}`); } const normalizedIndices = indices2.map(normalizeDim).join(","); if (rank === 0) { return getByOffset("0u"); } else if (rank === 1) { return getByOffset(normalizedIndices[0]); } else { implementationUsed.get = true; implementationUsed.getByIndices = true; implementationUsed.indicesToOffset = true; return `get_${name}(${normalizedIndices})`; } }; const getByIndices = (varIndices) => { if (rank < 2) { return getByOffset(varIndices); } else { implementationUsed.getByIndices = true; implementationUsed.indicesToOffset = true; return `get_${name}ByIndices(${varIndices})`; } }; const setByIndicesImplementation = rank < 2 ? "" : ` fn set_${name}ByIndices(indices: ${type.indices}, value: ${valueType}) { ${setByOffset(`i2o_${name}(indices)`, "value")} }`; const setImplementation = rank < 2 ? "" : (() => { const functionParams = rankIdentity.map((i) => `d${i}: u32`).join(", "); const dimsParams = rankIdentity.map((i) => `d${i}`).join(", "); return ` fn set_${name}(${functionParams}, value: ${valueType}) { set_${name}ByIndices(${indices(dimsParams)}, value); }`; })(); const set = (...indicesAndValue) => { if (indicesAndValue.length !== rank + 1) { throw new Error(`indices length must be ${rank}`); } const value = indicesAndValue[rank]; if (typeof value !== "string") { throw new Error("value must be string"); } const normalizedIndices = indicesAndValue.slice(0, rank).map(normalizeDim).join(","); if (rank === 0) { return setByOffset("0u", value); } else if (rank === 1) { return setByOffset(normalizedIndices[0], value); } else { implementationUsed.set = true; implementationUsed.setByIndices = true; implementationUsed.indicesToOffset = true; return `set_${name}(${normalizedIndices}, ${value})`; } }; const setByIndices = (varIndices, value) => { if (rank < 2) { return setByOffset(varIndices, value); } else { implementationUsed.setByIndices = true; implementationUsed.indicesToOffset = true; return `set_${name}ByIndices(${varIndices}, ${value});`; } }; const impl = () => { const impls = []; let needShapeStrides = false; if (implementationUsed.offsetToIndices) { impls.push(offsetToIndicesImplementation); needShapeStrides = true; } if (implementationUsed.indicesToOffset) { impls.push(indicesToOffsetImplementation); needShapeStrides = true; } if (implementationUsed.broadcastedIndicesToOffset) { Object.values(broadcastedIndicesToOffsetImplementation).forEach((impl2) => impls.push(impl2)); needShapeStrides = true; } if (implementationUsed.set) { impls.push(setImplementation); needShapeStrides = true; } if (implementationUsed.setByIndices) { impls.push(setByIndicesImplementation); needShapeStrides = true; } if (implementationUsed.get) { impls.push(getImplementation); needShapeStrides = true; } if (implementationUsed.getByIndices) { impls.push(getByIndicesImplementation); needShapeStrides = true; } if (!useUniform && needShapeStrides) { impls.unshift( `const ${shape} = ${type.indices}(${shapeOrRank.join(",")});`, `const ${strides} = ${type.indices}(${ShapeUtil.computeStrides(shapeOrRank).join(",")});` ); } return impls.join("\n"); }; return { impl, type, offsetToIndices, indicesToOffset, broadcastedIndicesToOffset, indices, indicesGet, indicesSet, set, setByOffset, setByIndices, get, getByOffset, getByIndices, // isVec4, usage, name, strides, shape, rank }; }; inputVariable = (name, type, shapeOrRank, components = 1) => createIndicesHelper(name, type, shapeOrRank, "input", components); outputVariable = (name, type, shapeOrRank, components = 1) => createIndicesHelper(name, type, shapeOrRank, "output", components); atomicOutputVariable = (name, type, shapeOrRank) => createIndicesHelper(name, type, shapeOrRank, "atomicOutput", 1); internalVariable = (name, type, shapeOrRank, components = 1) => createIndicesHelper(name, type, shapeOrRank, "internal", components); ShaderHelperImpl = class { constructor(normalizedDispatchGroup, limits) { this.normalizedDispatchGroup = normalizedDispatchGroup; this.limits = limits; this.internalVariables = []; this.variables = []; this.uniforms = []; this.variableIndex = 0; } guardAgainstOutOfBoundsWorkgroupSizes(size) { const sizeInCode = typeof size === "number" ? `${size}u` : size; return `if (global_idx >= ${sizeInCode}) { return; }`; } mainStart(workgroupSize = WORKGROUP_SIZE) { const workgroupSizeX = typeof workgroupSize === "number" ? workgroupSize : workgroupSize[0]; const workgroupSizeY = typeof workgroupSize === "number" ? 1 : workgroupSize[1]; const workgroupSizeZ = typeof workgroupSize === "number" ? 1 : workgroupSize[2]; if (workgroupSizeX > this.limits.maxComputeWorkgroupSizeX || workgroupSizeY > this.limits.maxComputeWorkgroupSizeY || workgroupSizeZ > this.limits.maxComputeWorkgroupSizeZ) { throw new Error( `workgroup size [${workgroupSizeX}, ${workgroupSizeY}, ${workgroupSizeZ}] exceeds the maximum workgroup size [${this.limits.maxComputeWorkgroupSizeX}, ${this.limits.maxComputeWorkgroupSizeY}, ${this.limits.maxComputeWorkgroupSizeZ}].` ); } if (workgroupSizeX * workgroupSizeY * workgroupSizeZ > this.limits.maxComputeInvocationsPerWorkgroup) { throw new Error( `workgroup size [${workgroupSizeX}, ${workgroupSizeY}, ${workgroupSizeZ}] exceeds the maximum workgroup invocations ${this.limits.maxComputeInvocationsPerWorkgroup}.` ); } const is1DimensionDispatch = this.normalizedDispatchGroup[1] === 1 && this.normalizedDispatchGroup[2] === 1; const paramList = is1DimensionDispatch ? `@builtin(global_invocation_id) global_id : vec3, @builtin(workgroup_id) workgroup_id : vec3, @builtin(local_invocation_index) local_idx : u32, @builtin(local_invocation_id) local_id : vec3` : `@builtin(global_invocation_id) global_id : vec3, @builtin(local_invocation_id) local_id : vec3, @builtin(local_invocation_index) local_idx : u32, @builtin(workgroup_id) workgroup_id : vec3, @builtin(num_workgroups) num_workgroups : vec3`; const globalIdxDefinition = is1DimensionDispatch ? `let global_idx = global_id.x; let workgroup_index = workgroup_id.x;` : `let workgroup_index = workgroup_id.z * num_workgroups[0] * num_workgroups[1] + workgroup_id.y * num_workgroups[0] + workgroup_id.x; let global_idx = workgroup_index * ${workgroupSizeX * workgroupSizeY * workgroupSizeZ}u + local_idx;`; return `@compute @workgroup_size(${workgroupSizeX}, ${workgroupSizeY}, ${workgroupSizeZ}) fn main(${paramList}) { ${globalIdxDefinition} `; } appendVariableUniforms(variable) { if (variable.rank !== 0) { if (variable.shape.startsWith("uniforms.")) { this.uniforms.push({ name: variable.shape.replace("uniforms.", ""), type: "u32", length: variable.rank }); } if (variable.strides.startsWith("uniforms.")) { this.uniforms.push({ name: variable.strides.replace("uniforms.", ""), type: "u32", length: variable.rank }); } } } declareVariable(variable, bindingIndex) { if (variable.usage === "internal") { throw new Error("cannot use internal variable with declareVariable(). use registerInternalVariables() instead."); } this.variables.push(variable); this.appendVariableUniforms(variable); const access = variable.usage === "input" ? "read" : "read_write"; const storageType = variable.usage === "atomicOutput" ? `atomic` : variable.type.storage; return `@group(0) @binding(${bindingIndex}) var ${variable.name}: array<${storageType}>;`; } declareVariables(...variables) { return variables.map((v) => this.declareVariable(v, this.variableIndex++)).join("\n"); } registerInternalVariable(variable) { if (variable.usage !== "internal") { throw new Error( "cannot use input or output variable with registerInternalVariable(). use declareVariables() instead." ); } this.internalVariables.push(variable); this.appendVariableUniforms(variable); } registerInternalVariables(...variables) { variables.forEach((v) => this.registerInternalVariable(v)); return this; } registerUniform(name, type, length = 1) { this.uniforms.push({ name, type, length }); return this; } registerUniforms(additionalUniforms) { this.uniforms = this.uniforms.concat(additionalUniforms); return this; } uniformDeclaration() { if (this.uniforms.length === 0) { return ""; } const uniformSnippets = []; for (const { name, type, length } of this.uniforms) { if (length && length > 4) { if (type === "f16") { uniformSnippets.push(`@align(16) ${name}:array, ${Math.ceil(length / 8)}>`); } else { uniformSnippets.push(`${name}:array, ${Math.ceil(length / 4)}>`); } } else { const typeTemp = length == null || length === 1 ? type : `vec${length}<${type}>`; uniformSnippets.push(`${name}:${typeTemp}`); } } return ` struct Uniforms { ${uniformSnippets.join(", ")} }; @group(0) @binding(${this.variableIndex}) var uniforms: Uniforms;`; } /** * Get additional implementation that needs to be added to the shader source. */ get additionalImplementations() { return this.uniformDeclaration() + this.variables.map((i) => i.impl()).join("\n") + this.internalVariables.map((i) => i.impl()).join("\n"); } /** * Get the variable info of the shader program. */ get variablesInfo() { if (this.uniforms.length === 0) { return void 0; } const uniformWgslTypeToDataType = (type) => [12 /* uint32 */, 10 /* float16 */, 1 /* float */, 6 /* int32 */][["u32", "f16", "f32", "i32"].indexOf(type)]; return this.uniforms.map((u) => [uniformWgslTypeToDataType(u.type), u.length ?? 1]); } }; createShaderHelper = (dispatchGroup, limits) => new ShaderHelperImpl(dispatchGroup, limits); } }); // web/lib/wasm/jsep/webgpu/ops/transpose.ts var validateInputs, getAdjustedPerm, getOutputShape, permFunctionBody, squeezeShape, isTransposeReshape, createTransposeProgramInfo, transpose, parseTransposeAttributes; var init_transpose = __esm({ "web/lib/wasm/jsep/webgpu/ops/transpose.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs = (inputs, perm) => { if (!inputs || inputs.length !== 1) { throw new Error("Transpose requires 1 input."); } if (perm.length !== 0 && perm.length !== inputs[0].dims.length) { throw new Error(`perm size ${perm.length} does not match input rank ${inputs[0].dims.length}`); } }; getAdjustedPerm = (inputRank, perm) => perm.length !== 0 ? perm : [...new Array(inputRank).keys()].reverse(); getOutputShape = (inputShape, perm) => ShapeUtil.sortBasedOnPerm(inputShape, getAdjustedPerm(inputShape.length, perm)); permFunctionBody = (perm, rank, input, output) => { let reverseFunc = `fn perm(i: ${output.type.indices}) -> ${input.type.indices} { var a: ${input.type.indices};`; for (let i = 0; i < rank; ++i) { reverseFunc += `a[${perm[i]}]=i[${i}];`; } return reverseFunc += "return a;}"; }; squeezeShape = (shape, adjustedPerm) => { const newShape = []; const newPerm = []; for (let i = 0; i < shape.length; ++i) { if (shape[i] !== 1) { newShape.push(shape[i]); } if (shape[adjustedPerm[i]] !== 1) { newPerm.push(adjustedPerm[i]); } } return { newShape, newPerm }; }; isTransposeReshape = (perm, shape) => { let lastPermutedAxis = 0; for (let i = 0; i < perm.length; ++i) { if (shape[perm[i]] === 1) { continue; } if (perm[i] < lastPermutedAxis) { return false; } lastPermutedAxis = perm[i]; } return true; }; createTransposeProgramInfo = (inputTensor, permAttr) => { const inputDataType = inputTensor.dataType; const inputRank = inputTensor.dims.length; const perm = getAdjustedPerm(inputRank, permAttr); const outputShape = getOutputShape(inputTensor.dims, perm); let newInputShape = inputTensor.dims; let newOutputShape = outputShape; const transposeAsReshape = inputRank < 2 || isTransposeReshape(perm, inputTensor.dims); let getShaderSource; if (transposeAsReshape) { getShaderSource = (shaderHelper) => { const input = inputVariable("input", inputDataType, newInputShape, 4); const output = outputVariable("output", inputDataType, newOutputShape, 4); return ` ${shaderHelper.registerUniform("output_size", "u32").declareVariables(input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} output[global_idx] = input[global_idx]; }`; }; return { name: "TransposeCopy", shaderCache: { inputDependencies: ["type"] }, getRunData: () => { const outputSize = ShapeUtil.size(outputShape); return { outputs: [{ dims: outputShape, dataType: inputTensor.dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 / 4 /* components */ ) }, programUniforms: [{ type: 12 /* uint32 */, data: Math.ceil(outputSize / 4) }] }; }, getShaderSource }; } const { newShape, newPerm } = squeezeShape(inputTensor.dims, perm); const channelsLast = ShapeUtil.areEqual(newPerm, [2, 3, 1]); const channelsFirst = ShapeUtil.areEqual(newPerm, [3, 1, 2]); const useShared = newShape.length === 2 || channelsLast || channelsFirst; if (useShared) { newInputShape = channelsLast ? [newShape[0], newShape[1] * newShape[2]] : channelsFirst ? [newShape[0] * newShape[1], newShape[2]] : newShape; newOutputShape = [newInputShape[1], newInputShape[0]]; const tileSize = 16; getShaderSource = (shaderHelper) => { const input = inputVariable("a", inputDataType, newInputShape.length); const output = outputVariable("output", inputDataType, newOutputShape.length); return ` ${shaderHelper.registerUniform("output_size", "u32").declareVariables(input, output)} var tile : array, ${tileSize}>; ${shaderHelper.mainStart([tileSize, tileSize, 1])} let stride = (uniforms.output_shape[1] - 1) / ${tileSize} + 1; let workgroup_id_x = workgroup_index % stride; let workgroup_id_y = workgroup_index / stride; let input_col = workgroup_id_y * ${tileSize}u + local_id.x; let input_row = workgroup_id_x * ${tileSize}u + local_id.y; if (input_row < uniforms.a_shape[0] && input_col < uniforms.a_shape[1]) { tile[local_id.y][local_id.x] = ${input.getByIndices(`${input.type.indices}(input_row, input_col)`)}; } workgroupBarrier(); let output_col = workgroup_id_x * ${tileSize}u + local_id.x; let output_row = workgroup_id_y * ${tileSize}u + local_id.y; if (output_row < uniforms.output_shape[0] && output_col < uniforms.output_shape[1]) { ${output.setByIndices(`${output.type.indices}(output_row, output_col)`, "tile[local_id.x][local_id.y]")} } }`; }; return { name: "TransposeShared", shaderCache: { inputDependencies: ["type"] }, getRunData: () => { const outputSize = ShapeUtil.size(outputShape); return { outputs: [{ dims: outputShape, dataType: inputTensor.dataType }], dispatchGroup: { x: Math.ceil(newOutputShape[1] / tileSize), y: Math.ceil(newOutputShape[0] / tileSize) }, programUniforms: [ { type: 12 /* uint32 */, data: outputSize }, ...createTensorShapeVariables(newInputShape, newOutputShape) ] }; }, getShaderSource }; } getShaderSource = (shaderHelper) => { const input = inputVariable("a", inputDataType, newInputShape.length); const output = outputVariable("output", inputDataType, newOutputShape.length); return ` ${shaderHelper.registerUniform("output_size", "u32").declareVariables(input, output)} ${permFunctionBody(perm, inputRank, input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let indices = ${output.offsetToIndices("global_idx")}; let aIndices = perm(indices); ${output.setByOffset("global_idx", input.getByIndices("aIndices"))} }`; }; return { name: "Transpose", shaderCache: { hint: `${permAttr}`, inputDependencies: ["rank"] }, getRunData: () => { const outputSize = ShapeUtil.size(outputShape); return { outputs: [{ dims: outputShape, dataType: inputTensor.dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms: [ { type: 12 /* uint32 */, data: outputSize }, ...createTensorShapeVariables(newInputShape, newOutputShape) ] }; }, getShaderSource }; }; transpose = (context, attributes) => { validateInputs(context.inputs, attributes.perm); context.compute(createTransposeProgramInfo(context.inputs[0], attributes.perm)); }; parseTransposeAttributes = (attributes) => createAttributeWithCacheKey({ perm: attributes.perm }); } }); // web/lib/wasm/jsep/webgpu/ops/reduce-shared.ts var reduceOps, reduceSharedOps, reduceInitValues, reduceOutputValues, getInnerMostAxes, computeOutAndReduceShapes, expandShapeToKeepDim, areAxesInnerMostDims, getAxesPermutation, createReduceSharedProgramInfo, reduceCommon, reduceMeanShared, reduceL1Shared, reduceL2Shared, reduceLogSumExpShared, reduceMaxShared, reduceMinShared, reduceProdShared, reduceSumShared, reduceSumSquareShared, reduceLogSumShared; var init_reduce_shared = __esm({ "web/lib/wasm/jsep/webgpu/ops/reduce-shared.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); init_reduce(); init_transpose(); reduceOps = { max: "select(bestValue, candidate, candidate > bestValue)", min: "select(bestValue, candidate, candidate < bestValue)", mean: "bestValue + candidate", sum: "bestValue + candidate", prod: "bestValue * candidate", sumSquare: "bestValue + candidate * candidate", logSumExp: "bestValue + exp(candidate)", l1: "bestValue + abs(candidate)", l2: "bestValue + candidate * candidate", logSum: "bestValue + candidate" }; reduceSharedOps = { max: "select(bestValue, candidate, candidate > bestValue)", min: "select(bestValue, candidate, candidate < bestValue)", mean: "bestValue + candidate", sum: "bestValue + candidate", prod: "bestValue * candidate", sumSquare: "bestValue + candidate", logSumExp: "bestValue + candidate", l1: "bestValue + candidate", l2: "bestValue + candidate", logSum: "bestValue + candidate" }; reduceInitValues = { max: "_A[offset]", min: "_A[offset]", mean: "0", sum: "0", prod: "1", sumSquare: "0", logSumExp: "0", l1: "0", l2: "0", logSum: "0" }; reduceOutputValues = { max: "bestValue", min: "bestValue", sum: "bestValue", prod: "bestValue", sumSquare: "bestValue", logSumExp: "log(bestValue)", l1: "bestValue", l2: "sqrt(bestValue)", logSum: "log(bestValue)" }; getInnerMostAxes = (numInnerAxes, rank) => { const res = []; for (let i = rank - numInnerAxes; i < rank; ++i) { res.push(i); } return res; }; computeOutAndReduceShapes = (shape, axes) => { const outputShape = []; const rank = shape.length; for (let dim = 0; dim < rank; dim++) { if (axes.indexOf(dim) === -1) { outputShape.push(shape[dim]); } } const reduceShape = axes.map((dim) => shape[dim]); return [outputShape, reduceShape]; }; expandShapeToKeepDim = (shape, axes) => { const rank = shape.length + axes.length; const expandShape = []; let shapeIdx = 0; for (let dim = 0; dim < rank; dim++) { if (axes.indexOf(dim) === -1) { expandShape.push(shape[shapeIdx++]); } else { expandShape.push(1); } } return expandShape; }; areAxesInnerMostDims = (axes, rank) => { for (let i = 0; i < axes.length; ++i) { if (axes[axes.length - i - 1] !== rank - 1 - i) { return false; } } return true; }; getAxesPermutation = (axes, rank) => { const res = []; if (!areAxesInnerMostDims(axes, rank)) { for (let i = 0; i < rank; ++i) { if (axes.indexOf(i) === -1) { res.push(i); } } axes.forEach((axis) => res.push(axis)); } return res; }; createReduceSharedProgramInfo = (name, cacheKey, inputs, reduceType, outputDataType, outputShape, reduceShape) => { const inputShape = inputs[0].dims; const outputSize = ShapeUtil.size(outputShape); const reduceSize = ShapeUtil.size(reduceShape); const input = inputVariable("_A", inputs[0].dataType, inputShape); const output = outputVariable("output", outputDataType, outputShape); let workgroupSize = 64; if (outputSize === 1) { workgroupSize = 256; } const sharedMemorySnippet = ` var aBestValues : array; `; const getShaderSource = (shaderHelper) => ` ${shaderHelper.registerUniform("reduceSize", "u32").declareVariables(input, output)} ${sharedMemorySnippet} fn DIV_CEIL(a : u32, b : u32) -> u32 { return ((a - 1u) / b + 1u); } ${shaderHelper.mainStart(workgroupSize)} let outputIndex = global_idx / ${workgroupSize}; let offset = outputIndex * uniforms.reduceSize; var bestValue = f32(${reduceInitValues[reduceType]}); let Length = uniforms.reduceSize; for (var k = local_idx; k < Length; k = k + ${workgroupSize}) { let candidate = f32(${input.getByOffset("offset + k")}); bestValue = ${reduceOps[reduceType]}; } aBestValues[local_idx] = bestValue; workgroupBarrier(); var reduceSize = min(Length, ${workgroupSize}u); for (var currentSize = reduceSize / 2u; reduceSize > 1u; currentSize = reduceSize / 2u) { let interval = DIV_CEIL(reduceSize, 2u); if (local_idx < currentSize) { let candidate = aBestValues[local_idx + interval]; bestValue = ${reduceSharedOps[reduceType]}; aBestValues[local_idx] = bestValue; } reduceSize = interval; workgroupBarrier(); } if (local_idx == 0u) { ${output.setByOffset( "outputIndex", `${reduceType === "mean" ? `${output.type.storage}(bestValue / f32(uniforms.reduceSize))` : `${output.type.storage}(${reduceOutputValues[reduceType]})`}` )}; } }`; return { name, // Note that in JSEP, WG size is not included in cache by default, but WebGPU EP it is. shaderCache: { hint: `${cacheKey};${workgroupSize}`, inputDependencies: ["type"] }, getShaderSource, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: outputDataType }], dispatchGroup: { x: outputSize }, programUniforms: [{ type: 12 /* uint32 */, data: reduceSize }] }) }; }; reduceCommon = (context, name, attributes, reduceType) => { const updatedAttributes = context.inputs.length === 1 ? attributes : createReduceAttributesFromInputs(context.inputs, attributes); let updatedAxes = updatedAttributes.axes; if (updatedAxes.length === 0 && !updatedAttributes.noopWithEmptyAxes) { updatedAxes = context.inputs[0].dims.map((_dim, i) => i); } const normalizeAxes = ShapeUtil.normalizeAxes(updatedAxes, context.inputs[0].dims.length); let axes = normalizeAxes; let input = context.inputs[0]; const permutedAxes = getAxesPermutation(axes, context.inputs[0].dims.length); if (permutedAxes.length > 0) { input = context.compute(createTransposeProgramInfo(context.inputs[0], permutedAxes), { inputs: [0], outputs: [-1] })[0]; axes = getInnerMostAxes(axes.length, input.dims.length); } const [outputShape, reduceShape] = computeOutAndReduceShapes(input.dims, axes); let finalOutputShape = outputShape; if (updatedAttributes.keepDims) { finalOutputShape = expandShapeToKeepDim(outputShape, normalizeAxes); } context.compute( createReduceSharedProgramInfo( name, updatedAttributes.cacheKey, [input], reduceType, context.inputs[0].dataType, finalOutputShape, reduceShape ), { inputs: [input] } ); }; reduceMeanShared = (context, attributes) => { reduceCommon(context, "ReduceMeanShared", attributes, "mean"); }; reduceL1Shared = (context, attributes) => { reduceCommon(context, "ReduceL1Shared", attributes, "l1"); }; reduceL2Shared = (context, attributes) => { reduceCommon(context, "ReduceL2Shared", attributes, "l2"); }; reduceLogSumExpShared = (context, attributes) => { reduceCommon(context, "ReduceLogSumExpShared", attributes, "logSumExp"); }; reduceMaxShared = (context, attributes) => { reduceCommon(context, "ReduceMaxShared", attributes, "max"); }; reduceMinShared = (context, attributes) => { reduceCommon(context, "ReduceMinShared", attributes, "min"); }; reduceProdShared = (context, attributes) => { reduceCommon(context, "ReduceProdShared", attributes, "prod"); }; reduceSumShared = (context, attributes) => { reduceCommon(context, "ReduceSumShared", attributes, "sum"); }; reduceSumSquareShared = (context, attributes) => { reduceCommon(context, "ReduceSumSquareShared", attributes, "sumSquare"); }; reduceLogSumShared = (context, attributes) => { reduceCommon(context, "ReduceLogSumShared", attributes, "logSum"); }; } }); // web/lib/wasm/jsep/webgpu/ops/reduce.ts var validateInputs2, noOp, createReduceProgramInfo, createReduceAttributesFromInputs, runReduceProgram, reduceLogSumNaive, reduceL1Naive, reduceL2Naive, reduceLogSumExpNaive, reduceMaxNaive, reduceMeanNaive, reduceMinNaive, reduceProdNaive, reduceSumNaive, reduceSumSquareNaive, useNaiveReduceMethod, reduceMean, reduceL1, reduceL2, reduceLogSumExp, reduceMax, reduceMin, reduceProd, reduceSum, reduceSumSquare, reduceLogSum; var init_reduce = __esm({ "web/lib/wasm/jsep/webgpu/ops/reduce.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); init_reduce_shared(); validateInputs2 = (inputs) => { if (!inputs || inputs.length === 0 || inputs.length > 2) { throw new Error("Reduce op requires 1 or 2 inputs."); } if (inputs.length === 2 && inputs[1].dims.length !== 1) { throw new Error("Invalid axes input dims."); } }; noOp = (input) => ["", "", `var value = ${input.getByIndices("input_indices")};`, ""]; createReduceProgramInfo = (name, shaderCache, inputs, reduceOp, axesInput, outputDataType, keepDims = false, noopWithEmptyAxes = false) => { const outputShape = []; const inputShape = inputs[0].dims; const inputRank = inputShape.length; const axes = ShapeUtil.normalizeAxes(axesInput, inputRank); const reduceOnAllAxes = !noopWithEmptyAxes && axes.length === 0; inputShape.forEach((d, i) => { if (reduceOnAllAxes || axes.indexOf(i) >= 0) { if (keepDims) { outputShape.push(1); } } else { outputShape.push(d); } }); const outputRank = outputShape.length; const outputSize = ShapeUtil.size(outputShape); const getShaderSource = (shaderHelper) => { const idxCopy = []; const input = inputVariable("_A", inputs[0].dataType, inputRank); const output = outputVariable("output", outputDataType, outputRank); const ops = reduceOp(input, output, axes); let reduceOps2 = ops[2]; for (let k = 0, l = 0; k < inputRank; k++) { if (reduceOnAllAxes || axes.indexOf(k) >= 0) { if (keepDims) { l++; } reduceOps2 = `for(var j${k}: u32 = 0; j${k} < ${inputShape[k]}; j${k}++) { ${ops[2].includes("last_index") ? `let last_index = j${k};` : ""} ${input.indicesSet("input_indices", k, `j${k}`)} ${reduceOps2} }`; } else { idxCopy.push(`${input.indicesSet("input_indices", k, output.indicesGet("output_indices", l))};`); l++; } } return ` ${shaderHelper.registerUniform("output_size", "u32").declareVariables(input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} var input_indices: ${input.type.indices}; let output_indices = ${output.offsetToIndices("global_idx")}; ${idxCopy.join("\n")} ${ops[0]} // init ops for reduce max/min ${ops[1]} ${reduceOps2} ${ops[3]} ${ops.length === 4 ? output.setByOffset("global_idx", "value") : ops.slice(4).join("\n")} }`; }; return { name, shaderCache, getShaderSource, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: outputDataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms: [ { type: 12 /* uint32 */, data: outputSize }, ...createTensorShapeVariables(inputShape, outputShape) ] }) }; }; createReduceAttributesFromInputs = (inputs, attributes) => { const axes = []; if (inputs[1].dims[0] > 0) { inputs[1].getBigInt64Array().forEach((v) => axes.push(Number(v))); } return createAttributeWithCacheKey({ axes, keepDims: attributes.keepDims, noopWithEmptyAxes: attributes.noopWithEmptyAxes }); }; runReduceProgram = (context, name, attributes, reduceOp) => { const inputs = context.inputs; const updatedAttributes = inputs.length === 1 ? attributes : createReduceAttributesFromInputs(inputs, attributes); context.compute( createReduceProgramInfo( name, { hint: updatedAttributes.cacheKey, inputDependencies: ["rank"] }, [inputs[0]], updatedAttributes.noopWithEmptyAxes && updatedAttributes.axes.length === 0 ? noOp : reduceOp, updatedAttributes.axes, inputs[0].dataType, updatedAttributes.keepDims, updatedAttributes.noopWithEmptyAxes ), { inputs: [0] } ); }; reduceLogSumNaive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, output) => [ `var value = ${output.type.storage}(0);`, "", `value += ${input.getByIndices("input_indices")};`, "value = log(value);" ]; runReduceProgram(context, "ReduceLogSum", attributes, reduceOp); }; reduceL1Naive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, output) => [ `var value = ${output.type.storage}(0);`, "", `value += abs(${input.getByIndices("input_indices")});`, "" ]; runReduceProgram(context, "ReduceL1", attributes, reduceOp); }; reduceL2Naive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, output) => [ `var t = ${output.type.value}(0); var value = ${output.type.value}(0);`, "", `t = ${input.getByIndices("input_indices")}; value += (t * t);`, "value = sqrt(value);" ]; runReduceProgram(context, "ReduceL2", attributes, reduceOp); }; reduceLogSumExpNaive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, output) => [ `var value = ${output.type.storage}(0);`, "", `value += exp(${input.getByIndices("input_indices")});`, "value = log(value);" ]; runReduceProgram(context, "ReduceLogSumExp", attributes, reduceOp); }; reduceMaxNaive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, _output, axes) => { const idxZero = []; for (let k = 0; k < input.rank; k++) { if (axes.indexOf(k) >= 0 || axes.length === 0) { idxZero.push(input.indicesSet("input_indices", k, 0)); } } return [ `${idxZero.join("\n")}`, `var value = ${input.getByIndices("input_indices")};`, `value = max(value, ${input.getByIndices("input_indices")});`, "" ]; }; runReduceProgram(context, "ReduceMax", attributes, reduceOp); }; reduceMeanNaive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, output, axes) => { let size = 1; for (let k = 0; k < input.rank; k++) { if (axes.indexOf(k) >= 0 || axes.length === 0) { size *= context.inputs[0].dims[k]; } } return [ "var sum = f32(0);", "", `sum += f32(${input.getByIndices("input_indices")});`, `let value = ${output.type.value}(sum / ${size});` ]; }; runReduceProgram(context, "ReduceMean", attributes, reduceOp); }; reduceMinNaive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, _output, axes) => { const idxZero = []; for (let k = 0; k < input.rank; k++) { if (axes.indexOf(k) >= 0 || axes.length === 0) { idxZero.push(`input_indices[${k}] = 0;`); } } return [ `${idxZero.join("\n")}`, `var value = ${input.getByIndices("input_indices")};`, `value = min(value, ${input.getByIndices("input_indices")});`, "" ]; }; runReduceProgram(context, "ReduceMin", attributes, reduceOp); }; reduceProdNaive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, output) => [ `var value = ${output.type.storage}(1);`, "", `value *= ${input.getByIndices("input_indices")};`, "" ]; runReduceProgram(context, "ReduceProd", attributes, reduceOp); }; reduceSumNaive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, output) => [ `var value = ${output.type.storage}(0);`, "", `value += ${input.getByIndices("input_indices")};`, "" ]; runReduceProgram(context, "ReduceSum", attributes, reduceOp); }; reduceSumSquareNaive = (context, attributes) => { validateInputs2(context.inputs); const reduceOp = (input, output) => [ `var t = ${output.type.value}(0); var value = ${output.type.value}(0);`, "", `t = ${input.getByIndices("input_indices")}; value += t * t;`, "" ]; runReduceProgram(context, "ReduceSumSquare", attributes, reduceOp); }; useNaiveReduceMethod = (shape, axes, noopWithEmptyAxes) => { if (axes.length === 0) { return noopWithEmptyAxes; } let outputSize = 1; let reduceSize = 1; for (let dim = 0; dim < axes.length; dim++) { if (axes.indexOf(dim) === -1) { outputSize *= shape[dim]; } else { reduceSize *= shape[dim]; } } return reduceSize < 32 && outputSize > 1024; }; reduceMean = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceMeanNaive(context, attributes); } else { reduceMeanShared(context, attributes); } }; reduceL1 = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceL1Naive(context, attributes); } else { reduceL1Shared(context, attributes); } }; reduceL2 = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceL2Naive(context, attributes); } else { reduceL2Shared(context, attributes); } }; reduceLogSumExp = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceLogSumExpNaive(context, attributes); } else { reduceLogSumExpShared(context, attributes); } }; reduceMax = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceMaxNaive(context, attributes); } else { reduceMaxShared(context, attributes); } }; reduceMin = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceMinNaive(context, attributes); } else { reduceMinShared(context, attributes); } }; reduceProd = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceProdNaive(context, attributes); } else { reduceProdShared(context, attributes); } }; reduceSum = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceSumNaive(context, attributes); } else { reduceSumShared(context, attributes); } }; reduceSumSquare = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceSumSquareNaive(context, attributes); } else { reduceSumSquareShared(context, attributes); } }; reduceLogSum = (context, attributes) => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { reduceLogSumNaive(context, attributes); } else { reduceLogSumShared(context, attributes); } }; } }); // web/lib/wasm/jsep/webgpu/ops/argminmax.ts var validateInputs3, argMin, argMax, parseArgMinMaxAttributes; var init_argminmax = __esm({ "web/lib/wasm/jsep/webgpu/ops/argminmax.ts"() { "use strict"; init_wasm_common(); init_attribute_with_cache_key(); init_reduce(); validateInputs3 = (inputs) => { if (!inputs || inputs.length === 0 || inputs.length > 2) { throw new Error("ArgMinMaxOp op requires 1 or 2 inputs."); } if (inputs[0].dataType !== 1 /* float */) { throw new Error("Invalid input type."); } }; argMin = (context, attributes) => { validateInputs3(context.inputs); const argMinMaxOp = (input, output, axes) => { const idxZero = []; for (let k = 0; k < input.rank; k++) { if (axes.indexOf(k) >= 0 || axes.length === 0) { idxZero.push(`input_indices[${k}] = 0;`); } } return [ `${idxZero.join("\n")}`, `var value = ${input.getByIndices("input_indices")}; var best_index : i32 = 0;`, `if (${input.getByIndices("input_indices")} ${attributes.selectLastIndex > 0 ? "<=" : "<"} value) { value = ${input.getByIndices("input_indices")}; best_index = i32(last_index); }`, "", output.setByOffset("global_idx", "best_index") ]; }; context.compute( createReduceProgramInfo( "ArgMin", { hint: attributes.cacheKey, inputDependencies: ["rank"] }, [context.inputs[0]], argMinMaxOp, [attributes.axis], 7 /* int64 */, attributes.keepDims ), { inputs: [0] } ); }; argMax = (context, attributes) => { validateInputs3(context.inputs); const argMinMaxOp = (input, output, axes) => { const idxZero = []; for (let k = 0; k < input.rank; k++) { if (axes.indexOf(k) >= 0 || axes.length === 0) { idxZero.push(`input_indices[${k}] = 0;`); } } return [ `${idxZero.join("\n")}`, `var value = ${input.getByIndices("input_indices")}; var best_index : i32 = 0;`, `if (${input.getByIndices("input_indices")} ${attributes.selectLastIndex > 0 ? ">=" : ">"} value) { value = ${input.getByIndices("input_indices")}; best_index = i32(last_index); }`, "", output.setByOffset("global_idx", "best_index") ]; }; context.compute( createReduceProgramInfo( "argMax", { hint: attributes.cacheKey, inputDependencies: ["rank"] }, [context.inputs[0]], argMinMaxOp, [attributes.axis], 7 /* int64 */, attributes.keepDims ), { inputs: [0] } ); }; parseArgMinMaxAttributes = (attributes) => createAttributeWithCacheKey(attributes); } }); // web/lib/wasm/jsep/webgpu/ops/attention.ts var validateAttentionInputs, initVarStub, createInPlaceSoftmaxProgramInfo, createAttentionProbsProgramInfo, createVxAttentionScoreProgramInfo, applyAttention, prepare, attention; var init_attention = __esm({ "web/lib/wasm/jsep/webgpu/ops/attention.ts"() { "use strict"; init_wasm_common(); init_util(); init_types(); init_common(); validateAttentionInputs = (inputs, attributes) => { const input = inputs[0]; const weights = inputs[1]; const bias = inputs[2]; const maskIndex = inputs[3]; const past = inputs[4]; const attentionBias = inputs[5]; if (past && attentionBias) { throw new Error("Attention cannot have both past and attention_bias"); } if (input.dims.length !== 3) { throw new Error('Input "input" must have 3 dimensions'); } const batchSize = input.dims[0]; const sequenceLength = input.dims[1]; const inputHiddenSize = input.dims[2]; if (bias.dims.length !== 1) { throw new Error('Input "bias" is expected to have 1 dimensions'); } if (weights.dims.length !== 2) { throw new Error('Input "weights" is expected to have 2 dimensions'); } if (weights.dims[0] !== inputHiddenSize) { throw new Error("Input 1 dimension 0 should have same length as dimension 2 of input 0"); } if (bias.dims[0] !== weights.dims[1]) { throw new Error('Input "bias" dimension 0 should have same length as dimension 1 of input "weights"'); } let qHiddenSize = bias.dims[0] / 3; let kHiddenSize = qHiddenSize; let vHiddenSize = kHiddenSize; if (attributes.qkvHiddenSizes.length > 0) { if (attributes.qkvHiddenSizes.length !== 3) { throw new Error("qkv_hidden_sizes attribute should have 3 elements"); } for (const sz of attributes.qkvHiddenSizes) { if (sz % attributes.numHeads !== 0) { throw new Error("qkv_hidden_sizes should be divisible by num_heads"); } } qHiddenSize = attributes.qkvHiddenSizes[0]; kHiddenSize = attributes.qkvHiddenSizes[1]; vHiddenSize = attributes.qkvHiddenSizes[2]; } const kvSequenceLength = sequenceLength; if (qHiddenSize !== kHiddenSize) { throw new Error("qkv_hidden_sizes first element should be same as the second"); } if (bias.dims[0] !== qHiddenSize + kHiddenSize + vHiddenSize) { throw new Error('Input "bias" dimension 0 should have same length as sum of Q/K/V hidden sizes'); } let pastSequenceLength = 0; if (past) { if (kHiddenSize !== vHiddenSize) { throw new Error('Input "past" expect k_hidden_size == v_hidden_size'); } if (past.dims.length !== 5) { throw new Error('Input "past" must have 5 dimensions'); } if (past.dims[0] !== 2) { throw new Error('Input "past" first dimension must be 2'); } if (past.dims[1] !== batchSize) { throw new Error('Input "past" second dimension must be batch_size'); } if (past.dims[2] !== attributes.numHeads) { throw new Error('Input "past" third dimension must be num_heads'); } if (past.dims[4] !== kHiddenSize / attributes.numHeads) { throw new Error('Input "past" fifth dimension must be k_hidden_size / num_heads'); } if (!attributes.pastPresentShareBuffer) { pastSequenceLength = past.dims[3]; } } const totalSequenceLength = kvSequenceLength + pastSequenceLength; const maxSequenceLength = -1; const maskType = 0 /* none */; if (maskIndex) { throw new Error("Mask not supported"); } if (past) { throw new Error("past is not supported"); } if (attentionBias) { if (attentionBias.dims.length !== 4) { throw new Error('Input "attention_bias" must have 4 dimensions'); } if (attentionBias.dims[0] !== batchSize || attentionBias.dims[1] !== attributes.numHeads || attentionBias.dims[2] !== sequenceLength || attentionBias.dims[3] !== totalSequenceLength) { throw new Error('Expect "attention_bias" shape (batch_size, num_heads, sequence_length, total_sequence_length)'); } } return { batchSize, sequenceLength, pastSequenceLength, kvSequenceLength, totalSequenceLength, maxSequenceLength, inputHiddenSize, hiddenSize: qHiddenSize, vHiddenSize, headSize: Math.floor(qHiddenSize / attributes.numHeads), vHeadSize: Math.floor(vHiddenSize / attributes.numHeads), numHeads: attributes.numHeads, isUnidirectional: false, pastPresentShareBuffer: false, maskFilterValue: attributes.maskFilterValue, maskType, scale: attributes.scale, broadcastResPosBias: false, passPastInKv: false, qkvFormat: 1 /* qkvBNSH */ }; }; initVarStub = (seqLensInput, totalSequenceLengthInput, initPastSequenceLength) => { if (totalSequenceLengthInput && seqLensInput) { return ` let total_sequence_length_input = u32(${totalSequenceLengthInput.getByOffset("0")}); let present_sequence_length = max(total_sequence_length_input, uniforms.past_sequence_length); let is_subsequent_prompt: bool = sequence_length > 1 && sequence_length != total_sequence_length_input; let is_first_prompt: bool = is_subsequent_prompt == false && sequence_length == total_sequence_length_input; total_sequence_length = u32(${seqLensInput?.getByOffset("batchIdx")}) + 1; var past_sequence_length: u32 = 0; if (is_first_prompt == false) { past_sequence_length = total_sequence_length - sequence_length; } `; } else { return ` ${initPastSequenceLength ? "let past_sequence_length = uniforms.past_sequence_length" : ""}; let present_sequence_length = total_sequence_length; `; } }; createInPlaceSoftmaxProgramInfo = (input, batchSize, numHeads, pastSequenceLength, sequenceLength, totalSequenceLength, seqLens, totalSequenceLengthInput) => { const components = getMaxComponents(seqLens ? 1 : totalSequenceLength); let WG = 64; const totalSequenceLengthComp = totalSequenceLength / components; if (totalSequenceLengthComp < WG) { WG = 32; } const elementsPerThread = Math.ceil(totalSequenceLength / components / WG); const programUniforms = [ { type: 12 /* uint32 */, data: batchSize }, { type: 12 /* uint32 */, data: numHeads }, { type: 12 /* uint32 */, data: pastSequenceLength }, { type: 12 /* uint32 */, data: sequenceLength }, { type: 12 /* uint32 */, data: totalSequenceLengthComp }, { type: 12 /* uint32 */, data: elementsPerThread } ]; const dataType = tensorTypeToWsglStorageType(input.dataType, components); const f32Type = tensorTypeToWsglValueType(1 /* float */, components); const inputDependencies = ["type"]; if (seqLens) { inputDependencies.push("type"); } if (totalSequenceLengthInput) { inputDependencies.push("type"); } const getShaderSource = (shaderHelper) => { const inputHelper = outputVariable("x", input.dataType, input.dims, components); const inputHelpers = [inputHelper]; const seqLensInputHelper = seqLens ? inputVariable("seq_lens", seqLens.dataType, seqLens.dims) : void 0; if (seqLensInputHelper) { inputHelpers.push(seqLensInputHelper); } const totalSequenceLengthInputHelper = totalSequenceLengthInput ? inputVariable("total_sequence_length_input", totalSequenceLengthInput.dataType, totalSequenceLengthInput.dims) : void 0; if (totalSequenceLengthInputHelper) { inputHelpers.push(totalSequenceLengthInputHelper); } const elemValueType = tensorTypeToWsglValueType(input.dataType); const uniforms = [ { name: "batch_size", type: "u32" }, { name: "num_heads", type: "u32" }, { name: "past_sequence_length", type: "u32" }, { name: "sequence_length", type: "u32" }, { name: "total_sequence_length", type: "u32" }, { name: "elements_per_thread", type: "u32" } ]; return ` var thread_max: array; var thread_sum: array; ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputHelpers)} ${shaderHelper.mainStart([WG, 1, 1])} let batchIdx = workgroup_id.z / uniforms.num_heads; let headIdx = workgroup_id.z % uniforms.num_heads; let sequence_length = uniforms.sequence_length; var total_sequence_length = uniforms.total_sequence_length; ${initVarStub(seqLensInputHelper, totalSequenceLengthInputHelper, false)} let local_offset = local_idx * uniforms.elements_per_thread; let offset = (global_idx / ${WG}) * uniforms.total_sequence_length + local_offset; let seq_causal_length = ${seqLens ? "u32(past_sequence_length + workgroup_id.y + 1)" : "total_sequence_length"}; var thread_max_vector = ${f32Type}(-3.4028234663852886e+38f); for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < seq_causal_length; i++) { thread_max_vector = max(${f32Type}(x[offset + i]), thread_max_vector); } thread_max[local_idx] = ${(() => { switch (components) { case 1: return "thread_max_vector"; case 2: return "max(thread_max_vector.x, thread_max_vector.y)"; case 4: return "max(max(thread_max_vector.x, thread_max_vector.y), max(thread_max_vector.z, thread_max_vector.w))"; default: throw new Error(`Unsupported components: ${components}`); } })()}; workgroupBarrier(); var max_value = f32(-3.4028234663852886e+38f); for (var i = 0u; i < ${WG}; i++) { max_value = max(thread_max[i], max_value); } var sum_vector = ${f32Type}(0); for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < seq_causal_length; i++) { sum_vector += exp(${f32Type}(x[offset + i]) - max_value); } thread_sum[local_idx] = ${(() => { switch (components) { case 1: return "sum_vector"; case 2: return "sum_vector.x + sum_vector.y"; case 4: return "sum_vector.x + sum_vector.y + sum_vector.z + sum_vector.w"; default: throw new Error(`Unsupported components: ${components}`); } })()}; workgroupBarrier(); var sum: f32 = 0; for (var i = 0u; i < ${WG}; i++) { sum += thread_sum[i]; } if (sum == 0) { for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < seq_causal_length; i++) { x[offset + i] = ${inputHelper.type.value}(${elemValueType}(1.0) / ${elemValueType}(seq_causal_length)); } } else { for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < seq_causal_length; i++) { var f32input = ${f32Type}(x[offset + i]); x[offset + i] = ${inputHelper.type.value}(exp(f32input - max_value) / sum); } } ${seqLens ? ` for (var total_seq_id: u32 = seq_causal_length; total_seq_id + local_offset < uniforms.total_sequence_length; total_seq_id++) { x[offset + total_seq_id] = ${inputHelper.type.value}(${elemValueType}(0)); }` : ""}; }`; }; return { name: "AttentionProbsSoftmax", shaderCache: { hint: `${WG};${dataType};${components}`, inputDependencies }, getShaderSource, getRunData: () => ({ outputs: [], dispatchGroup: { x: 1, y: sequenceLength, z: batchSize * numHeads }, programUniforms }) }; }; createAttentionProbsProgramInfo = (outputCount, q, key, pastKey, attentionBias, parameters, pastSequenceLength, seqLens, totalSequenceLengthInput) => { const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength; const probsShape = [parameters.batchSize, parameters.numHeads, parameters.sequenceLength, totalSequenceLength]; const presentKey = outputCount > 1 && pastKey; const kvNumHeads = parameters.kvNumHeads ? parameters.kvNumHeads : parameters.numHeads; const presentKeyShape = presentKey ? [parameters.batchSize, kvNumHeads, totalSequenceLength, parameters.headSize] : void 0; const nReps = parameters.nReps ? parameters.nReps : 1; const alpha = parameters.scale === 0 ? 1 / Math.sqrt(parameters.headSize) : parameters.scale; const components = getMaxComponents(parameters.headSize); const vectorizedHeadSize = parameters.headSize / components; const TILE_SIZE = 12; const dispatch = { x: Math.ceil(totalSequenceLength / TILE_SIZE), y: Math.ceil(parameters.sequenceLength / TILE_SIZE), z: parameters.batchSize * parameters.numHeads }; const programUniforms = [ { type: 12 /* uint32 */, data: parameters.sequenceLength }, { type: 12 /* uint32 */, data: vectorizedHeadSize }, { type: 12 /* uint32 */, data: totalSequenceLength }, { type: 12 /* uint32 */, data: parameters.numHeads }, { type: 12 /* uint32 */, data: parameters.headSize }, { type: 1 /* float */, data: alpha }, { type: 12 /* uint32 */, data: pastSequenceLength }, { type: 12 /* uint32 */, data: parameters.kvSequenceLength }, { type: 12 /* uint32 */, data: nReps } ]; const feedPastKey = presentKey && pastKey && ShapeUtil.size(pastKey.dims) > 0; const inputDependencies = ["type", "type"]; if (feedPastKey) { inputDependencies.push("type"); } if (attentionBias) { inputDependencies.push("type"); } if (seqLens) { inputDependencies.push("type"); } if (totalSequenceLengthInput) { inputDependencies.push("type"); } const outputs = [{ dims: probsShape, dataType: q.dataType, gpuDataType: 0 /* default */ }]; if (presentKey) { outputs.push({ dims: presentKeyShape, dataType: q.dataType, gpuDataType: 0 /* default */ }); } const getShaderSource = (shaderHelper) => { const qInput = inputVariable("q", q.dataType, q.dims, components); const kInput = inputVariable("key", key.dataType, key.dims, components); const inputVars = [qInput, kInput]; if (feedPastKey) { const pastKeyInput = inputVariable("past_key", pastKey.dataType, pastKey.dims, components); inputVars.push(pastKeyInput); } if (attentionBias) { inputVars.push(inputVariable("attention_bias", attentionBias.dataType, attentionBias.dims)); } const seqLensInputVariable = seqLens ? inputVariable("seq_lens", seqLens.dataType, seqLens.dims) : void 0; if (seqLensInputVariable) { inputVars.push(seqLensInputVariable); } const totalSequenceLengthInputVariable = totalSequenceLengthInput ? inputVariable("total_sequence_length_input", totalSequenceLengthInput.dataType, totalSequenceLengthInput.dims) : void 0; if (totalSequenceLengthInputVariable) { inputVars.push(totalSequenceLengthInputVariable); } const output = outputVariable("output", q.dataType, probsShape); const outputVars = [output]; if (presentKey) { outputVars.push(outputVariable("present_key", q.dataType, presentKeyShape, components)); } const f32Type = tensorTypeToWsglValueType(1 /* float */, components); const uniforms = [ { name: "M", type: "u32" }, { name: "K", type: "u32" }, { name: "N", type: "u32" }, { name: "num_heads", type: "u32" }, { name: "head_size", type: "u32" }, { name: "alpha", type: "f32" }, { name: "past_sequence_length", type: "u32" }, { name: "kv_sequence_length", type: "u32" }, { name: "n_reps", type: "u32" } ]; return ` const TILE_SIZE = ${TILE_SIZE}u; var tileQ: array<${qInput.type.storage}, ${TILE_SIZE * TILE_SIZE}>; var tileK: array<${qInput.type.storage}, ${TILE_SIZE * TILE_SIZE}>; ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, ...outputVars)} ${shaderHelper.mainStart([TILE_SIZE, TILE_SIZE, 1])} // x holds the N and y holds the M let headIdx = workgroup_id.z % uniforms.num_heads; let kvHeadIdx = ${nReps === 1 ? "headIdx" : "headIdx / uniforms.n_reps"}; let kv_num_heads = ${nReps === 1 ? "uniforms.num_heads" : "uniforms.num_heads / uniforms.n_reps"}; let batchIdx = workgroup_id.z / uniforms.num_heads; let m = workgroup_id.y * TILE_SIZE; let n = workgroup_id.x * TILE_SIZE; let sequence_length = uniforms.M; var total_sequence_length = uniforms.N; ${initVarStub(seqLensInputVariable, totalSequenceLengthInputVariable, true)} let absKvHeadIdx = batchIdx * kv_num_heads + kvHeadIdx; let qOffset = workgroup_id.z * uniforms.M * uniforms.K + m * uniforms.K; ${feedPastKey && presentKey ? "let pastKeyOffset = absKvHeadIdx * uniforms.past_sequence_length * uniforms.K;" : ""}; let kOffset = absKvHeadIdx * uniforms.kv_sequence_length * uniforms.K; ${presentKey ? "let presentKeyOffset = absKvHeadIdx * uniforms.N * uniforms.K;" : ""} var value = ${f32Type}(0); for (var w: u32 = 0u; w < uniforms.K; w += TILE_SIZE) { if (global_id.y < uniforms.M && w + local_id.x < uniforms.K) { tileQ[TILE_SIZE * local_id.y + local_id.x] = q[qOffset + local_id.y * uniforms.K + w + local_id.x]; } if (n + local_id.y < uniforms.N && w + local_id.x < uniforms.K) { var idx = TILE_SIZE * local_id.y + local_id.x; ${(() => { if (feedPastKey && presentKey) { return ` if (n + local_id.y < past_sequence_length) { tileK[idx] = past_key[pastKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x]; } else if (n + local_id.y - past_sequence_length < uniforms.kv_sequence_length) { tileK[idx] = key[kOffset + (n + local_id.y - past_sequence_length) * uniforms.K + w + local_id.x]; }`; } else { return ` if (n + local_id.y < uniforms.kv_sequence_length) { tileK[idx] = key[kOffset + (n + local_id.y) * uniforms.K + w + local_id.x]; }`; } })()} ${presentKey ? `if (n + local_id.y < present_sequence_length) { present_key[presentKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x] = tileK[idx]; }` : ""} } workgroupBarrier(); for (var k: u32 = 0u; k < TILE_SIZE && w+k < uniforms.K; k++) { value += ${f32Type}(tileQ[TILE_SIZE * local_id.y + k] * tileK[TILE_SIZE * local_id.x + k]); } workgroupBarrier(); } if (global_id.y < uniforms.M && global_id.x < total_sequence_length) { let headOffset = workgroup_id.z * uniforms.M * uniforms.N; let outputIdx = headOffset + global_id.y * uniforms.N + global_id.x; var sum: f32 = ${(() => { switch (components) { case 1: return "value"; case 2: return "value.x + value.y"; case 4: return "value.x + value.y + value.z + value.w"; default: throw new Error(`Unsupported components: ${components}`); } })()}; output[outputIdx] = ${output.type.value} (sum * uniforms.alpha) + ${attentionBias ? "attention_bias[outputIdx]" : "0.0"}; } }`; }; return { name: "AttentionProbs", shaderCache: { hint: `${components};${attentionBias !== void 0};${pastKey !== void 0};${outputCount}`, inputDependencies }, getRunData: () => ({ outputs, dispatchGroup: dispatch, programUniforms }), getShaderSource }; }; createVxAttentionScoreProgramInfo = (outputCount, probs, v, pastValue, params, pastSequenceLength, seqLens = void 0, totalSequenceLengthInput = void 0) => { const totalSequenceLength = pastSequenceLength + params.kvSequenceLength; const nReps = params.nReps ? params.nReps : 1; const repeatedVHiddenSize = params.vHiddenSize * nReps; const presentValue = outputCount > 1 && pastValue; const kvNumHeads = params.kvNumHeads ? params.kvNumHeads : params.numHeads; const presentValueShape = presentValue ? [params.batchSize, kvNumHeads, totalSequenceLength, params.headSize] : void 0; const outputShape = [params.batchSize, params.sequenceLength, repeatedVHiddenSize]; const TILE_SIZE = 12; const dispatch = { x: Math.ceil(params.vHeadSize / TILE_SIZE), y: Math.ceil(params.sequenceLength / TILE_SIZE), z: params.batchSize * params.numHeads }; const programUniforms = [ { type: 12 /* uint32 */, data: params.sequenceLength }, { type: 12 /* uint32 */, data: totalSequenceLength }, { type: 12 /* uint32 */, data: params.vHeadSize }, { type: 12 /* uint32 */, data: params.numHeads }, { type: 12 /* uint32 */, data: params.headSize }, { type: 12 /* uint32 */, data: repeatedVHiddenSize }, { type: 12 /* uint32 */, data: pastSequenceLength }, { type: 12 /* uint32 */, data: params.kvSequenceLength }, { type: 12 /* uint32 */, data: nReps } ]; const feedPastValue = presentValue && pastValue && ShapeUtil.size(pastValue.dims) > 0; const inputDependencies = ["type", "type"]; if (feedPastValue) { inputDependencies.push("type"); } if (seqLens) { inputDependencies.push("type"); } if (totalSequenceLengthInput) { inputDependencies.push("type"); } const outputs = [{ dims: outputShape, dataType: probs.dataType, gpuDataType: 0 /* default */ }]; if (presentValue) { outputs.push({ dims: presentValueShape, dataType: probs.dataType, gpuDataType: 0 /* default */ }); } const getShaderSource = (shaderHelper) => { const probsHelper = inputVariable("probs", probs.dataType, probs.dims); const vHelper = inputVariable("v", v.dataType, v.dims); const inputVars = [probsHelper, vHelper]; if (feedPastValue) { inputVars.push(inputVariable("past_value", pastValue.dataType, pastValue.dims)); } const seqLensInputVariable = seqLens ? inputVariable("seq_lens", seqLens.dataType, seqLens.dims) : void 0; if (seqLens) { inputVars.push(seqLensInputVariable); } const totalSequenceLengthInputVariable = totalSequenceLengthInput ? inputVariable("total_sequence_length_input", totalSequenceLengthInput.dataType, totalSequenceLengthInput.dims) : void 0; if (totalSequenceLengthInput) { inputVars.push(totalSequenceLengthInputVariable); } const output = outputVariable("output", probs.dataType, outputShape); const outputVars = [output]; if (presentValue) { outputVars.push(outputVariable("present_value", probs.dataType, presentValueShape)); } const uniforms = [ { name: "M", type: "u32" }, { name: "K", type: "u32" }, { name: "N", type: "u32" }, { name: "num_heads", type: "u32" }, { name: "head_size", type: "u32" }, { name: "v_hidden_size", type: "u32" }, { name: "past_sequence_length", type: "u32" }, { name: "kv_sequence_length", type: "u32" }, { name: "n_reps", type: "u32" } ]; return ` const TILE_SIZE = ${TILE_SIZE}u; var tileQ: array<${probsHelper.type.value}, ${TILE_SIZE * TILE_SIZE}>; var tileV: array<${probsHelper.type.value}, ${TILE_SIZE * TILE_SIZE}>; ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, ...outputVars)} ${shaderHelper.mainStart([TILE_SIZE, TILE_SIZE, 1])} let headIdx = workgroup_id.z % uniforms.num_heads; let batchIdx = workgroup_id.z / uniforms.num_heads; let kvHeadIdx = ${nReps === 1 ? "headIdx" : "headIdx / uniforms.n_reps"}; let kv_num_heads = ${nReps === 1 ? "uniforms.num_heads" : "uniforms.num_heads / uniforms.n_reps"}; let m = global_id.y; let n = global_id.x; let sequence_length = uniforms.M; var total_sequence_length = uniforms.K; ${initVarStub(seqLensInputVariable, totalSequenceLengthInputVariable, true)} let offsetA = workgroup_id.z * uniforms.M * uniforms.K + m * uniforms.K; let absKvHeadIdx = batchIdx * kv_num_heads + kvHeadIdx; // kvHeadIdx is relative to the batch ${feedPastValue && presentValue ? "let pastValueOffset = absKvHeadIdx * uniforms.N * uniforms.past_sequence_length + n;" : ""}; let vOffset = absKvHeadIdx * uniforms.N * uniforms.kv_sequence_length + n; ${presentValue ? "let presentValueOffset = absKvHeadIdx * uniforms.N * uniforms.K + n;" : ""} var value = ${probsHelper.type.storage}(0); for (var w: u32 = 0u; w < uniforms.K; w += TILE_SIZE) { if (m < uniforms.M && w + local_id.x < uniforms.K) { tileQ[TILE_SIZE * local_id.y + local_id.x] = probs[offsetA + w + local_id.x]; } if (n < uniforms.N && w + local_id.y < uniforms.K) { var idx = TILE_SIZE * local_id.y + local_id.x; ${(() => { if (feedPastValue && presentValue) { return ` if (w + local_id.y < past_sequence_length) { tileV[idx] = past_value[pastValueOffset + (w + local_id.y) * uniforms.N]; } else if (w + local_id.y - past_sequence_length < uniforms.kv_sequence_length) { tileV[idx] = v[vOffset + (w + local_id.y - past_sequence_length) * uniforms.N]; } `; } else { return ` if (w + local_id.y < uniforms.kv_sequence_length) { tileV[idx] = v[vOffset + (w + local_id.y) * uniforms.N]; }`; } })()} ${presentValue ? ` if (w + local_id.y < present_sequence_length) { present_value[presentValueOffset + (w + local_id.y) * uniforms.N] = tileV[idx]; }` : ""} } workgroupBarrier(); for (var k: u32 = 0u; k < TILE_SIZE && w+k < total_sequence_length; k++) { value += tileQ[TILE_SIZE * local_id.y + k] * tileV[TILE_SIZE * k + local_id.x]; } workgroupBarrier(); } // we need to transpose output from BNSH_v to BSND_v if (m < uniforms.M && n < uniforms.N) { let outputIdx = batchIdx * uniforms.M * uniforms.v_hidden_size + m * uniforms.v_hidden_size + headIdx * uniforms.N + n; output[outputIdx] = value; } }`; }; return { name: "AttentionScore", shaderCache: { hint: `${pastValue !== void 0};${outputCount}`, inputDependencies }, getRunData: () => ({ outputs, dispatchGroup: dispatch, programUniforms }), getShaderSource }; }; applyAttention = (context, q, k, v, _maskIndex, _past, pastKey, pastValue, attentionBiasInput, parameters, seqLens = void 0, totalSequenceLengthInput = void 0) => { const outputCount = Math.min(context.outputCount, 1 + (pastKey ? 1 : 0) + (pastValue ? 1 : 0)); const effectivePastKey = outputCount > 1 ? pastKey : void 0; const effectivePastValue = outputCount > 1 ? pastValue : void 0; const pastSequenceLength = outputCount > 1 ? parameters.pastSequenceLength : 0; const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength; const attentionBias = attentionBiasInput && ShapeUtil.size(attentionBiasInput.dims) > 0 ? attentionBiasInput : void 0; const inputsK = [q, k]; if (effectivePastKey && ShapeUtil.size(effectivePastKey.dims) > 0) { inputsK.push(effectivePastKey); } if (attentionBias) { inputsK.push(attentionBias); } if (seqLens) { inputsK.push(seqLens); } if (totalSequenceLengthInput) { inputsK.push(totalSequenceLengthInput); } const probs = context.compute( createAttentionProbsProgramInfo( outputCount, q, k, effectivePastKey, attentionBias, parameters, pastSequenceLength, seqLens, totalSequenceLengthInput ), { inputs: inputsK, outputs: outputCount > 1 ? [-1, 1] : [-1] } )[0]; context.compute( createInPlaceSoftmaxProgramInfo( probs, parameters.batchSize, parameters.numHeads, pastSequenceLength, parameters.sequenceLength, totalSequenceLength, seqLens, totalSequenceLengthInput ), { inputs: seqLens && totalSequenceLengthInput ? [probs, seqLens, totalSequenceLengthInput] : [probs], outputs: [] } ); const inputsV = [probs, v]; if (effectivePastValue && ShapeUtil.size(effectivePastValue.dims) > 0) { inputsV.push(effectivePastValue); } if (seqLens) { inputsV.push(seqLens); } if (totalSequenceLengthInput) { inputsV.push(totalSequenceLengthInput); } context.compute( createVxAttentionScoreProgramInfo( outputCount, probs, v, effectivePastValue, parameters, pastSequenceLength, seqLens, totalSequenceLengthInput ), { inputs: inputsV, outputs: outputCount > 1 ? [0, 2] : [0] } ); }; prepare = (context, parameters) => { const outputShape = [parameters.batchSize, parameters.numHeads, parameters.sequenceLength, parameters.headSize]; const M = parameters.sequenceLength; const K = parameters.inputHiddenSize; const N = parameters.headSize; const TILE_SIZE = 12; const dispatch = { x: Math.ceil(parameters.headSize / TILE_SIZE), y: Math.ceil(parameters.sequenceLength / TILE_SIZE), z: parameters.batchSize * parameters.numHeads }; const inputs = [context.inputs[0], context.inputs[1], context.inputs[2]]; const programUniforms = [ { type: 12 /* uint32 */, data: M }, { type: 12 /* uint32 */, data: K }, { type: 12 /* uint32 */, data: N }, { type: 12 /* uint32 */, data: parameters.numHeads }, { type: 12 /* uint32 */, data: parameters.headSize }, { type: 12 /* uint32 */, data: parameters.hiddenSize }, { type: 12 /* uint32 */, data: parameters.hiddenSize + parameters.hiddenSize + parameters.vHiddenSize } ]; const getShaderSource = (shaderHelper) => { const outputQ = outputVariable("output_q", inputs[0].dataType, outputShape); const outputK = outputVariable("output_k", inputs[0].dataType, outputShape); const outputV = outputVariable("output_v", inputs[0].dataType, outputShape); const input = inputVariable("input", inputs[0].dataType, inputs[0].dims); const weight = inputVariable("weight", inputs[1].dataType, inputs[1].dims); const bias = inputVariable("bias", inputs[2].dataType, inputs[2].dims); const dataType = input.type.storage; const uniforms = [ { name: "M", type: "u32" }, { name: "K", type: "u32" }, { name: "N", type: "u32" }, { name: "num_heads", type: "u32" }, { name: "head_size", type: "u32" }, { name: "hidden_size", type: "u32" }, { name: "ldb", type: "u32" } ]; return ` const TILE_SIZE = ${TILE_SIZE}u; var tileInput: array<${dataType}, ${TILE_SIZE * TILE_SIZE}>; var tileWeightQ: array<${dataType}, ${TILE_SIZE * TILE_SIZE}>; var tileWeightK: array<${dataType}, ${TILE_SIZE * TILE_SIZE}>; var tileWeightV: array<${dataType}, ${TILE_SIZE * TILE_SIZE}>; ${shaderHelper.registerUniforms(uniforms).declareVariables(input, weight, bias, outputQ, outputK, outputV)} ${shaderHelper.mainStart([TILE_SIZE, TILE_SIZE, 1])} let batchIndex = workgroup_id.z / uniforms.num_heads; let headNumber = workgroup_id.z % uniforms.num_heads; let m = global_id.y; let n = global_id.x; let inputOffset = batchIndex * (uniforms.M * uniforms.K) + m * uniforms.K; let biasOffsetQ = headNumber * uniforms.head_size; let biasOffsetK = uniforms.hidden_size + biasOffsetQ; let biasOffsetV = uniforms.hidden_size + biasOffsetK; var valueQ = ${dataType}(0); var valueK = ${dataType}(0); var valueV = ${dataType}(0); for (var w: u32 = 0u; w < uniforms.K; w += TILE_SIZE) { if (m < uniforms.M && w + local_id.x < uniforms.K) { tileInput[TILE_SIZE * local_id.y + local_id.x] = input[inputOffset + w + local_id.x]; } if (n < uniforms.N && w + local_id.y < uniforms.K) { let offset = n + (w + local_id.y) * uniforms.ldb; tileWeightQ[TILE_SIZE * local_id.y + local_id.x] = weight[biasOffsetQ + offset]; tileWeightK[TILE_SIZE * local_id.y + local_id.x] = weight[biasOffsetK + offset]; tileWeightV[TILE_SIZE * local_id.y + local_id.x] = weight[biasOffsetV + offset]; } workgroupBarrier(); for (var k: u32 = 0u; k ({ outputs: [ { dims: outputShape, dataType: context.inputs[0].dataType, gpuDataType: 0 /* default */ }, { dims: outputShape, dataType: context.inputs[0].dataType, gpuDataType: 0 /* default */ }, { dims: outputShape, dataType: context.inputs[0].dataType, gpuDataType: 0 /* default */ } ], dispatchGroup: dispatch, programUniforms }), getShaderSource }, { inputs, outputs: [-1, -1, -1] } ); }; attention = (context, attributes) => { const params = validateAttentionInputs(context.inputs, attributes); const [q, k, v] = prepare(context, params); return applyAttention( context, q, k, v, context.inputs[4], void 0, void 0, void 0, context.inputs[5], params ); }; } }); // web/lib/wasm/jsep/webgpu/ops/batch-norm.ts var validateInputs4, createBatchNormInferenceProgramInfo, parseBatchNormAttributes, batchNorm; var init_batch_norm = __esm({ "web/lib/wasm/jsep/webgpu/ops/batch-norm.ts"() { "use strict"; init_esm(); init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs4 = (inputs, attributes) => { if (!inputs || inputs.length !== 5) { throw new Error("BatchNormalization requires 5 inputs"); } const checkShapeEqual = (actual, expected, message) => { const r = expected.length; if (r !== actual.length) { throw new Error(`${message}: num dimensions != ${r}`); } expected.forEach((v, i) => { if (v !== actual[i]) { throw new Error(`${message}: dim[${i}] do not match`); } }); }; if (inputs[0].dims.length > 1) { const shape = attributes.format === "NHWC" ? attributes.spatial ? inputs[0].dims.slice(-1) : inputs[0].dims.slice(-1).concat(inputs[0].dims.slice(1, inputs[0].dims.length - 1)) : inputs[0].dims.slice(1, attributes.spatial ? 2 : void 0); checkShapeEqual(inputs[1].dims, shape, "Invalid input scale"); checkShapeEqual(inputs[2].dims, shape, "Invalid input B"); checkShapeEqual(inputs[3].dims, shape, "Invalid input mean"); checkShapeEqual(inputs[4].dims, shape, "Invalid input var"); } else { checkShapeEqual(inputs[1].dims, [1], "Invalid input scale"); checkShapeEqual(inputs[2].dims, [1], "Invalid input B"); checkShapeEqual(inputs[3].dims, [1], "Invalid input mean"); checkShapeEqual(inputs[4].dims, [1], "Invalid input var"); } }; createBatchNormInferenceProgramInfo = (inputs, attributes) => { const { epsilon, spatial, format } = attributes; const yShape = inputs[0].dims; const components = spatial ? getMaxComponents(yShape[yShape.length - 1]) : 1; const cComponents = format === "NHWC" && yShape.length > 1 ? components : 1; const outputSize = ShapeUtil.size(yShape) / components; const useShapesUniforms = spatial; const shapeOrRank = useShapesUniforms ? yShape.length : yShape; const x = inputVariable("x", inputs[0].dataType, inputs[0].dims, components); const scale = inputVariable("scale", inputs[1].dataType, inputs[1].dims, cComponents); const bias = inputVariable("bias", inputs[2].dataType, inputs[2].dims, cComponents); const inputMean = inputVariable("inputMean", inputs[3].dataType, inputs[3].dims, cComponents); const inputVar = inputVariable("inputVar", inputs[4].dataType, inputs[4].dims, cComponents); const y = outputVariable("y", inputs[0].dataType, shapeOrRank, components); const calcCOffset = () => { let cOffset = ""; if (spatial) { cOffset = `let cOffset = ${yShape.length === 1 ? "0u" : format === "NHWC" ? `outputIndices[${yShape.length - 1}] / ${components}` : "outputIndices[1]"};`; } else { if (format === "NCHW") { cOffset = ` ${y.indicesSet("outputIndices", "0", "0")} let cOffset = ${y.indicesToOffset("outputIndices")};`; } else { cOffset = `var cIndices = ${scale.type.indices}(0); cIndices[0] = outputIndices[${yShape.length - 1}];`; for (let i = 1; i < scale.rank; i++) { cOffset += `cIndices[${i}] = outputIndices[${i}];`; } cOffset += `let cOffset = ${scale.indicesToOffset("cIndices")};`; } } return cOffset; }; const getInferenceModeShaderSource = (helper) => ` const epsilon = ${epsilon}; ${helper.registerUniform("outputSize", "u32").declareVariables(x, scale, bias, inputMean, inputVar, y)} ${helper.mainStart()} ${helper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} var outputIndices = ${y.offsetToIndices(`global_idx * ${components}`)}; ${calcCOffset()} let scale = ${scale.getByOffset("cOffset")}; let bias = ${bias.getByOffset("cOffset")}; let inputMean = ${inputMean.getByOffset("cOffset")}; let inputVar = ${inputVar.getByOffset("cOffset")}; let x = ${x.getByOffset("global_idx")}; let value = (x - inputMean) * inverseSqrt(inputVar + epsilon) * scale + bias; ${y.setByOffset("global_idx", "value")} }`; return { name: "BatchNormalization", shaderCache: { hint: `${attributes.epsilon}_${attributes.format}_${spatial}_${components}`, inputDependencies: useShapesUniforms ? ["rank", "type", "type", "type", "type"] : void 0 }, getShaderSource: getInferenceModeShaderSource, getRunData: () => ({ outputs: [{ dims: inputs[0].dims, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms: useShapesUniforms ? [{ type: 12 /* uint32 */, data: outputSize }, ...createTensorShapeVariables(yShape)] : [{ type: 12 /* uint32 */, data: outputSize }] }) }; }; parseBatchNormAttributes = (attributes) => createAttributeWithCacheKey(attributes); batchNorm = (context, attributes) => { const { inputs, outputCount } = context; const updatedAttributes = parseBatchNormAttributes({ ...attributes, outputCount }); if (env2.webgpu.validateInputContent) { validateInputs4(inputs, updatedAttributes); } if (attributes.trainingMode) { throw new Error("BatchNormalization trainingMode is not supported yet."); } else { context.compute(createBatchNormInferenceProgramInfo(inputs, updatedAttributes)); } }; } }); // web/lib/wasm/jsep/webgpu/ops/bias-add.ts var validateInputs5, createBiasAddProgramInfo, biasAdd; var init_bias_add = __esm({ "web/lib/wasm/jsep/webgpu/ops/bias-add.ts"() { "use strict"; init_util(); init_common(); validateInputs5 = (inputs) => { if (inputs[0].dims.length !== 3) { throw new Error("input should have 3 dimensions"); } if (![320, 640, 1280].includes(inputs[0].dims[2])) { throw new Error("number of channels should be 320, 640 or 1280"); } if (inputs[1].dims.length !== 1) { throw new Error("bias is expected to have 1 dimensions"); } if (inputs[0].dims[2] !== inputs[1].dims[0]) { throw new Error("last dimension of input and bias are not the same"); } }; createBiasAddProgramInfo = (inputs) => { const outputShape = inputs[0].dims; const channels = inputs[0].dims[2]; const outputSize = ShapeUtil.size(outputShape) / 4; const dataType = inputs[0].dataType; const input = inputVariable("input", dataType, outputShape, 4); const bias = inputVariable("bias", dataType, [channels], 4); const residual = inputVariable("residual", dataType, outputShape, 4); const output = outputVariable("output", dataType, outputShape, 4); const getShaderSource = (shaderHelper) => ` const channels = ${channels}u / 4; ${shaderHelper.declareVariables(input, bias, residual, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(outputSize)} let value = ${input.getByOffset("global_idx")} + ${bias.getByOffset("global_idx % channels")} + ${residual.getByOffset("global_idx")}; ${output.setByOffset("global_idx", "value")} }`; return { name: "BiasAdd", getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) } }), getShaderSource }; }; biasAdd = (context) => { validateInputs5(context.inputs); context.compute(createBiasAddProgramInfo(context.inputs)); }; } }); // web/lib/wasm/jsep/webgpu/ops/unary-op.ts var createElementwiseProgramShader, createElementwiseProgramInfo, abs, acos, acosh, asin, asinh, atan, atanh, parseCastAttributes, cast, generateClipAttributesFromInputs, clip, ceil, cos, cosh, parseAlphaAttributes, elu, erfImpl, erf, exp, floor, gelu, leakyRelu, not, neg, reciprocal, relu, sigmoid, parseHardSigmoidAttributes, hardSigmoid, sin, sinh, sqrt, tan, tanhExpression, tanh, fastGeluImpl, fastGeluExpression, fastGelu, thresholdedRelu, log, quickGeluImpl, quickGeluExpression, quickgelu; var init_unary_op = __esm({ "web/lib/wasm/jsep/webgpu/ops/unary-op.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); createElementwiseProgramShader = (shaderHelper, datasize, inputDataType, outputDataType, funcCall, additionalImplementation, additionalUniformsType) => { const vecSize = Math.ceil(datasize / 4); let expression = ""; if (typeof funcCall === "string") { expression = `${funcCall}(a)`; } else { expression = funcCall("a"); } const input = inputVariable("inputData", inputDataType, [vecSize], 4); const output = outputVariable("outputData", outputDataType, [vecSize], 4); const uniforms = [{ name: "vec_size", type: "u32" }]; if (additionalUniformsType) { uniforms.push(...additionalUniformsType); } return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(input, output)} ${additionalImplementation ?? ""} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.vec_size")} let a = ${input.getByOffset("global_idx")}; ${output.setByOffset("global_idx", expression)} }`; }; createElementwiseProgramInfo = (input, name, funcCall, additionalImplementation, cacheKey, outputDataType = input.dataType, additionalUniforms, additionalUniformsType) => { const programUniforms = [ { type: 12 /* uint32 */, data: Math.ceil(ShapeUtil.size(input.dims) / 4) } ]; if (additionalUniforms) { programUniforms.push(...additionalUniforms); } return { name, shaderCache: { hint: cacheKey, inputDependencies: ["type"] }, getShaderSource: (shaderHelper) => createElementwiseProgramShader( shaderHelper, ShapeUtil.size(input.dims), input.dataType, outputDataType, funcCall, additionalImplementation, additionalUniformsType ), getRunData: (inputTensors) => ({ outputs: [{ dims: input.dims, dataType: outputDataType }], dispatchGroup: { x: Math.ceil( ShapeUtil.size(inputTensors[0].dims) / 64 / 4 /* vec size */ ) }, programUniforms }) }; }; abs = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Abs", "abs")); }; acos = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Acos", "acos")); }; acosh = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Acosh", "acosh")); }; asin = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Asin", "asin")); }; asinh = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Asinh", "asinh")); }; atan = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Atan", "atan")); }; atanh = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Atanh", "atanh")); }; parseCastAttributes = (attributes) => createAttributeWithCacheKey(attributes); cast = (context, attributes) => { let func; switch (attributes.to) { case 10 /* float16 */: func = "vec4"; break; case 1 /* float */: func = "vec4"; break; case 12 /* uint32 */: func = "vec4"; break; case 6 /* int32 */: func = "vec4"; break; case 9 /* bool */: func = "vec4"; break; default: throw new RangeError(`not supported type (specified in attribute 'to' from 'Cast' operator): ${attributes.to}`); } context.compute( createElementwiseProgramInfo(context.inputs[0], "Cast", func, void 0, attributes.cacheKey, attributes.to) ); }; generateClipAttributesFromInputs = (inputs) => { let min; let max; const hasMin = inputs.length >= 2 && inputs[1].data !== 0; const hasMax = inputs.length >= 3 && inputs[2].data !== 0; switch (inputs[0].dataType) { case 1 /* float */: min = hasMin ? inputs[1].getFloat32Array()[0] : -34028234663852886e22; max = hasMax ? inputs[2].getFloat32Array()[0] : 34028234663852886e22; break; case 10 /* float16 */: min = hasMin ? inputs[1].getUint16Array()[0] : 64511; max = hasMax ? inputs[2].getUint16Array()[0] : 31743; break; default: throw new Error("Unsupport data type"); } return createAttributeWithCacheKey({ min, max }); }; clip = (context, clipAttributes) => { const attributes = clipAttributes ? clipAttributes : generateClipAttributesFromInputs(context.inputs); const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], "Clip", (a) => `clamp(${a}, vec4<${dataType}>(uniforms.min), vec4<${dataType}>(uniforms.max))`, void 0, attributes.cacheKey, void 0, [ { type: context.inputs[0].dataType, data: attributes.min }, { type: context.inputs[0].dataType, data: attributes.max } ], [ { name: "min", type: dataType }, { name: "max", type: dataType } ] ), { inputs: [0] } ); }; ceil = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Ceil", "ceil")); }; cos = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Cos", "cos")); }; cosh = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Cosh", "cosh")); }; parseAlphaAttributes = (attributes) => createAttributeWithCacheKey(attributes); elu = (context, attributes) => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], "Elu", (a) => `elu_vf32(${a})`, ` const elu_alpha_ = ${dataType}(${attributes.alpha}); fn elu_f32(a: ${dataType}) -> ${dataType} { return select((exp(a) - 1.0) * elu_alpha_, a, a >= 0.0); } fn elu_vf32(v: vec4<${dataType}>) -> vec4<${dataType}> { return vec4(elu_f32(v.x), elu_f32(v.y), elu_f32(v.z), elu_f32(v.w)); }`, attributes.cacheKey ) ); }; erfImpl = (varType = "f32") => ` const r0: ${varType} = 0.3275911; const r1: ${varType} = 0.254829592; const r2: ${varType} = -0.284496736; const r3: ${varType} = 1.421413741; const r4: ${varType} = -1.453152027; const r5: ${varType} = 1.061405429; fn erf_vf32(v: vec4<${varType}>) -> vec4<${varType}> { let absv = abs(v); let x = 1.0 / (1.0 + r0 * absv); return sign(v) * (1.0 - ((((r5 * x + r4) * x + r3) * x + r2) * x + r1) * x * exp(-absv * absv)); }`; erf = (context) => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute(createElementwiseProgramInfo(context.inputs[0], "Erf", (a) => `erf_vf32(${a})`, erfImpl(dataType))); }; exp = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Exp", "exp")); }; floor = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Floor", "floor")); }; gelu = (context) => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], "Gelu", (a) => `0.5 * ${a} * (1.0 + erf_vf32(${a} * 0.7071067811865475))`, erfImpl(dataType) ) ); }; leakyRelu = (context, attributes) => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], "LeakyRelu", (a) => `select(leaky_relu_alpha_ * ${a}, ${a}, ${a} >= vec4<${dataType}>(0.0))`, `const leaky_relu_alpha_ = ${dataType}(${attributes.alpha});`, attributes.cacheKey ) ); }; not = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Not", (a) => `!${a}`)); }; neg = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Neg", (a) => `-${a}`)); }; reciprocal = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Reciprocal", (a) => `1.0/${a}`)); }; relu = (context) => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], "Relu", (a) => `select(vec4<${dataType}>(0.0), ${a}, ${a} > vec4<${dataType}>(0.0))` ) ); }; sigmoid = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Sigmoid", (a) => `(1.0 / (1.0 + exp(-${a})))`)); }; parseHardSigmoidAttributes = (attributes) => createAttributeWithCacheKey( attributes ); hardSigmoid = (context, attributes) => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], "HardSigmoid", (a) => `max(vec4<${dataType}>(0.0), min(vec4<${dataType}>(1.0), ${attributes.alpha} * ${a} + vec4<${dataType}>(${attributes.beta})))`, void 0, attributes.cacheKey ) ); }; sin = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Sin", "sin")); }; sinh = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Sinh", "sinh")); }; sqrt = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Sqrt", "sqrt")); }; tan = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Tan", "tan")); }; tanhExpression = (a) => `sign(${a}) * (1 - exp(-2 * abs(${a}))) / (1 + exp(-2 * abs(${a})))`; tanh = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Tanh", tanhExpression)); }; fastGeluImpl = (varType = "f32") => ` const fast_gelu_a: ${varType} = 0.5; const fast_gelu_b: ${varType} = 0.7978845608028654; const fast_gelu_c: ${varType} = 0.035677408136300125; fn tanh_v(v: vec4<${varType}>) -> vec4<${varType}> { return ${tanhExpression("v")}; } `; fastGeluExpression = (x) => `(fast_gelu_a + fast_gelu_a * tanh_v(${x} * (fast_gelu_c * ${x} * ${x} + fast_gelu_b))) * ${x}`; fastGelu = (context) => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], "FastGelu", fastGeluExpression, fastGeluImpl(dataType), void 0, context.inputs[0].dataType ) ); }; thresholdedRelu = (context, attributes) => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], "ThresholdedRelu", (a) => `select(vec4<${dataType}>(0.0), ${a}, ${a} > thresholded_relu_alpha_)`, `const thresholded_relu_alpha_ = vec4<${dataType}>(${attributes.alpha});`, attributes.cacheKey ) ); return 0; }; log = (context) => { context.compute(createElementwiseProgramInfo(context.inputs[0], "Log", "log")); }; quickGeluImpl = (varType, alpha) => ` const alpha = vec4<${varType}>(${alpha}); const one = ${varType}(1.0); const zero = ${varType}(0.0); fn quick_gelu_impl(x: vec4<${varType}>) -> vec4<${varType}> { let v = x *alpha; var x1 : vec4<${varType}>; for (var i = 0; i < 4; i = i + 1) { if (v[i] >= zero) { x1[i] = one / (one + exp(-v[i])); } else { x1[i] = one - one / (one + exp(v[i])); } } return x * x1; } `; quickGeluExpression = (x) => `quick_gelu_impl(${x})`; quickgelu = (context, attributes) => { const dType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], "QuickGelu", quickGeluExpression, quickGeluImpl(dType, attributes.alpha), attributes.cacheKey, context.inputs[0].dataType ) ); }; } }); // web/lib/wasm/jsep/webgpu/ops/bias-split-gelu.ts var validateInputs6, createBiasSplitGeluProgramInfo, biasSplitGelu; var init_bias_split_gelu = __esm({ "web/lib/wasm/jsep/webgpu/ops/bias-split-gelu.ts"() { "use strict"; init_util(); init_common(); init_unary_op(); validateInputs6 = (inputs) => { if (inputs[0].dims.length !== 3) { throw new Error("input should have 3 dimensions"); } if (![2560, 5120, 10240].includes(inputs[0].dims[2])) { throw new Error("hidden state should be 2560, 5120 or 10240"); } if (inputs[1].dims.length !== 1) { throw new Error("bias is expected to have 1 dimensions"); } if (inputs[0].dims[2] !== inputs[1].dims[0]) { throw new Error("last dimension of input and bias are not the same"); } }; createBiasSplitGeluProgramInfo = (inputs) => { const outputShape = inputs[0].dims.slice(); outputShape[2] = outputShape[2] / 2; const input = inputVariable("input", inputs[0].dataType, inputs[0].dims, 4); const bias = inputVariable("bias", inputs[0].dataType, [inputs[0].dims[2]], 4); const output = outputVariable("output", inputs[0].dataType, outputShape, 4); const outputSize = ShapeUtil.size(outputShape) / 4; const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); const getShaderSource = (shaderHelper) => ` const M_SQRT2 = sqrt(2.0); const halfChannels = ${inputs[0].dims[2] / 4 / 2}u; ${shaderHelper.declareVariables(input, bias, output)} ${erfImpl(dataType)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(outputSize)} let biasIdx = global_idx % halfChannels; let batchIndex = global_idx / halfChannels; let inputOffset = biasIdx + batchIndex * halfChannels * 2; let valueLeft = input[inputOffset] + bias[biasIdx]; let valueRight = input[inputOffset + halfChannels] + bias[biasIdx + halfChannels]; let geluRight = valueRight * 0.5 * (erf_vf32(valueRight / M_SQRT2) + 1); ${output.setByOffset("global_idx", "valueLeft * geluRight")} }`; return { name: "BiasSplitGelu", getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) } }), getShaderSource }; }; biasSplitGelu = (context) => { validateInputs6(context.inputs); context.compute(createBiasSplitGeluProgramInfo(context.inputs)); }; } }); // web/lib/wasm/jsep/webgpu/ops/binary-op.ts var createBinaryOpProgramShader, createBinaryOpProgramInfo, runBinaryOp, add, div, equal, mul, pow, sub, greater, less, greaterOrEqual, lessOrEqual; var init_binary_op = __esm({ "web/lib/wasm/jsep/webgpu/ops/binary-op.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); createBinaryOpProgramShader = (shaderHelper, dimsA, dimsB, dimsOutput, vectorize, doBroadcast, sharedDimensionDivisibleBy4, funcCall, typeA, typeB, typeOutput, additionalImplementation) => { let expressionScalar; let expressionVector; if (typeof funcCall === "string") { expressionScalar = expressionVector = (a2, b2) => `${funcCall}((${a2}),(${b2}))`; } else if (typeof funcCall === "function") { expressionScalar = expressionVector = funcCall; } else { expressionScalar = funcCall.scalar; expressionVector = funcCall.vector; } const output = outputVariable("outputData", typeOutput, dimsOutput.length, 4); const a = inputVariable("aData", typeA, dimsA.length, 4); const b = inputVariable("bData", typeB, dimsB.length, 4); let assignment; if (vectorize) { if (doBroadcast) { const isAOneElement = ShapeUtil.size(dimsA) === 1; const isBOneElement = ShapeUtil.size(dimsB) === 1; const aLastDimDivisibleBy4 = dimsA.length > 0 && dimsA[dimsA.length - 1] % 4 === 0; const bLastDimDivisibleBy4 = dimsB.length > 0 && dimsB[dimsB.length - 1] % 4 === 0; if (isAOneElement || isBOneElement) { assignment = output.setByOffset( "global_idx", expressionVector( isAOneElement ? `${a.type.value}(${a.getByOffset("0")}.x)` : a.getByOffset("global_idx"), isBOneElement ? `${b.type.value}(${b.getByOffset("0")}.x)` : b.getByOffset("global_idx") ) ); } else { assignment = ` let outputIndices = ${output.offsetToIndices("global_idx * 4u")}; let offsetA = ${a.broadcastedIndicesToOffset("outputIndices", output)}; let offsetB = ${b.broadcastedIndicesToOffset("outputIndices", output)}; ${output.setByOffset( "global_idx", expressionVector( sharedDimensionDivisibleBy4 || aLastDimDivisibleBy4 ? a.getByOffset("offsetA / 4u") : `${a.type.value}(${a.getByOffset("offsetA / 4u")}[offsetA % 4u])`, sharedDimensionDivisibleBy4 || bLastDimDivisibleBy4 ? b.getByOffset("offsetB / 4u") : `${b.type.value}(${b.getByOffset("offsetB / 4u")}[offsetB % 4u])` ) )} `; } } else { assignment = output.setByOffset( "global_idx", expressionVector(a.getByOffset("global_idx"), b.getByOffset("global_idx")) ); } } else { if (!doBroadcast) { throw new Error("no necessary to use scalar implementation for element-wise binary op implementation."); } const singleAssignment = (resStr, x, typeCast = "") => { const expressionA = `aData[indexA${x}][componentA${x}]`; const expressionB = `bData[indexB${x}][componentB${x}]`; return ` let outputIndices${x} = ${output.offsetToIndices(`global_idx * 4u + ${x}u`)}; let offsetA${x} = ${a.broadcastedIndicesToOffset(`outputIndices${x}`, output)}; let offsetB${x} = ${b.broadcastedIndicesToOffset(`outputIndices${x}`, output)}; let indexA${x} = offsetA${x} / 4u; let indexB${x} = offsetB${x} / 4u; let componentA${x} = offsetA${x} % 4u; let componentB${x} = offsetB${x} % 4u; ${resStr}[${x}] = ${typeCast}(${expressionScalar(expressionA, expressionB)}); `; }; if (typeOutput === 9 /* bool */) { assignment = ` var data = vec4(0); ${singleAssignment("data", 0, "u32")} ${singleAssignment("data", 1, "u32")} ${singleAssignment("data", 2, "u32")} ${singleAssignment("data", 3, "u32")} outputData[global_idx] = dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(data));`; } else { assignment = ` ${singleAssignment("outputData[global_idx]", 0)} ${singleAssignment("outputData[global_idx]", 1)} ${singleAssignment("outputData[global_idx]", 2)} ${singleAssignment("outputData[global_idx]", 3)} `; } } return ` ${shaderHelper.registerUniform("vec_size", "u32").declareVariables(a, b, output)} ${additionalImplementation ?? ""} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.vec_size")} ${assignment} }`; }; createBinaryOpProgramInfo = (name, cacheKey, a, b, funcCall, additionalImplementation, outputDataType = a.dataType) => { const aDims = a.dims.map(Number); const bDims = b.dims.map(Number); const isBroadcast = !ShapeUtil.areEqual(aDims, bDims); let outputShape = aDims; let outputSize = ShapeUtil.size(aDims); let vectorize = false; let sharedDimensionDivisibleBy4 = false; const cacheKeyAux = [isBroadcast]; if (isBroadcast) { const calculatedShape = BroadcastUtil.calcShape(aDims, bDims, false); if (!calculatedShape) { throw new Error("Can't perform binary op on the given tensors"); } outputShape = calculatedShape.slice(); outputSize = ShapeUtil.size(outputShape); const isAOneElement = ShapeUtil.size(aDims) === 1; const isBOneElement = ShapeUtil.size(bDims) === 1; const aLastDimDivisibleBy4 = aDims.length > 0 && aDims[aDims.length - 1] % 4 === 0; const bLastDimDivisibleBy4 = bDims.length > 0 && bDims[bDims.length - 1] % 4 === 0; cacheKeyAux.push(isAOneElement); cacheKeyAux.push(isBOneElement); cacheKeyAux.push(aLastDimDivisibleBy4); cacheKeyAux.push(bLastDimDivisibleBy4); let sharedDimension = 1; for (let i = 1; i < outputShape.length; i++) { const dimA = aDims[aDims.length - i]; const dimB = bDims[bDims.length - i]; if (dimA === dimB) { sharedDimension *= dimA; } else { break; } } if (sharedDimension % 4 === 0) { sharedDimensionDivisibleBy4 = true; vectorize = true; } else if (isAOneElement || isBOneElement || aLastDimDivisibleBy4 || bLastDimDivisibleBy4) { vectorize = true; } } else { vectorize = true; } cacheKeyAux.push(vectorize); return { name, shaderCache: { hint: cacheKey + cacheKeyAux.map((x) => x.toString()).join("_"), inputDependencies: ["rank", "rank"] }, getShaderSource: (shaderHelper) => createBinaryOpProgramShader( shaderHelper, aDims, bDims, outputShape, vectorize, isBroadcast, sharedDimensionDivisibleBy4, funcCall, a.dataType, b.dataType, outputDataType, additionalImplementation ), getRunData: () => ({ outputs: [{ dims: outputShape, dataType: outputDataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 / 4 /* component size */ ) }, programUniforms: [ { type: 12 /* uint32 */, data: Math.ceil(ShapeUtil.size(outputShape) / 4) }, ...createTensorShapeVariables(aDims, bDims, outputShape) ] }) }; }; runBinaryOp = (context, name, funcCall, additionalImplementation, cacheKey, outputDataType) => { context.compute( createBinaryOpProgramInfo( name, cacheKey ?? "", context.inputs[0], context.inputs[1], funcCall, additionalImplementation, outputDataType ) ); }; add = (context) => { runBinaryOp(context, "Add", (a, b) => `${a}+${b}`); }; div = (context) => { runBinaryOp(context, "Div", (a, b) => `${a}/${b}`); }; equal = (context) => { runBinaryOp( context, "Equal", { scalar: (a, b) => `u32(${a}==${b})`, vector: (a, b) => `vec4(${a}==${b})` }, void 0, void 0, 9 /* bool */ ); }; mul = (context) => { runBinaryOp(context, "Mul", (a, b) => `${a}*${b}`); }; pow = (context) => { const type = inputVariable("input", context.inputs[0].dataType, context.inputs[0].dims).type.value; const roundStr = type === "i32" ? "round" : ""; runBinaryOp( context, "Pow", { scalar: (a, b) => `pow_custom(${a},${b})`, vector: (a, b) => `pow_vector_custom(${a},${b})` }, ` fn pow_custom(a : ${type}, b : ${type}) -> ${type} { if (b == ${type}(0.0)) { return ${type}(1.0); } else if (a < ${type}(0.0) && f32(b) != floor(f32(b))) { return ${type}(pow(f32(a), f32(b))); // NaN } return select(sign(a), ${type}(1.0), round(f32(abs(b) % ${type}(2.0))) != 1.0) * ${type}(${roundStr}(pow(f32(abs(a)), f32(b)))); } fn pow_vector_custom(a : vec4<${type}>, b : vec4<${type}>) -> vec4<${type}> { // TODO: implement vectorized pow return vec4<${type}>(pow_custom(a.x, b.x), pow_custom(a.y, b.y), pow_custom(a.z, b.z), pow_custom(a.w, b.w)); } ` ); }; sub = (context) => { runBinaryOp(context, "Sub", (a, b) => `${a}-${b}`); }; greater = (context) => { runBinaryOp( context, "Greater", { scalar: (a, b) => `u32(${a}>${b})`, vector: (a, b) => `vec4(${a}>${b})` }, void 0, void 0, 9 /* bool */ ); }; less = (context) => { runBinaryOp( context, "Less", { scalar: (a, b) => `u32(${a}<${b})`, vector: (a, b) => `vec4(${a}<${b})` }, void 0, void 0, 9 /* bool */ ); }; greaterOrEqual = (context) => { runBinaryOp( context, "GreaterOrEqual", { scalar: (a, b) => `u32(${a}>=${b})`, vector: (a, b) => `vec4(${a}>=${b})` }, void 0, void 0, 9 /* bool */ ); }; lessOrEqual = (context) => { runBinaryOp( context, "LessOrEqual", { scalar: (a, b) => `u32(${a}<=${b})`, vector: (a, b) => `vec4(${a}<=${b})` }, void 0, void 0, 9 /* bool */ ); }; } }); // web/lib/wasm/jsep/webgpu/ops/concat.ts var validateInputs7, calculateInputIndexImpl, assignOutputData, createConcatProgramInfo, concat, parseConcatAttributes; var init_concat = __esm({ "web/lib/wasm/jsep/webgpu/ops/concat.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs7 = (inputs, axis) => { if (!inputs || inputs.length < 1) { throw new Error("too few inputs"); } const referenceIndex = 0; const referenceInput = inputs[referenceIndex]; const inputType = referenceInput.dataType; const inputRank = referenceInput.dims.length; inputs.forEach((input, i) => { if (i === referenceIndex) { return; } if (input.dataType !== inputType) { throw new Error("input tensors should be one type"); } if (input.dims.length !== inputRank) { throw new Error("input tensors should have the same shape"); } input.dims.forEach((dim, i2) => { if (i2 !== axis && dim !== referenceInput.dims[i2]) { throw new Error("non concat dimensions must match"); } }); }); }; calculateInputIndexImpl = (numberOfTensors, sizeInConcatAxisStr) => ` fn calculateInputIndex(index: u32) -> u32 { let sizeInConcatAxis = array(${sizeInConcatAxisStr}); for (var i: u32 = 0u; i < ${numberOfTensors}; i += 1u ) { if (index < sizeInConcatAxis[i]) { return i; } } return ${numberOfTensors}u; }`; assignOutputData = (inputs, output) => { const numberOfTensors = inputs.length; const codeLines = []; for (let i = 0; i < numberOfTensors; ++i) { const returnSnippet = output.setByOffset("global_idx", inputs[i].getByIndices("indices")); if (numberOfTensors === 1) { codeLines.push(returnSnippet); } else if (i === 0) { codeLines.push(`if (inputIndex == ${i}u) { ${returnSnippet} }`); } else if (i === numberOfTensors - 1) { codeLines.push(`else { ${returnSnippet} }`); } else { codeLines.push(`else if (inputIndex == ${i}) { ${returnSnippet} }`); } } return codeLines.join("\n"); }; createConcatProgramInfo = (inputs, adjustedAxis, outputShape, dataType) => { const outputSize = ShapeUtil.size(outputShape); const sizeInConcatAxis = new Array(inputs.length); const inputVars = new Array(inputs.length); let previousSum = 0; const inputDependencies = []; const inputRanks = []; const programUniforms = [{ type: 12 /* uint32 */, data: outputSize }]; for (let i = 0; i < inputs.length; ++i) { previousSum += inputs[i].dims[adjustedAxis]; sizeInConcatAxis[i] = previousSum; inputRanks.push(inputs[i].dims.length); inputVars[i] = inputVariable(`input${i}`, dataType, inputRanks[i]); inputDependencies.push("rank"); programUniforms.push({ type: 12 /* uint32 */, data: sizeInConcatAxis[i] }); } for (let i = 0; i < inputs.length; ++i) { programUniforms.push(...createTensorShapeVariables(inputs[i].dims)); } programUniforms.push(...createTensorShapeVariables(outputShape)); const output = outputVariable("output", dataType, outputShape.length); const indicesAxis = output.indicesGet("indices", adjustedAxis); const sizeInConcatAxisStr = Array.from(Array(sizeInConcatAxis.length).keys()).map((i) => `uniforms.sizeInConcatAxis${i}`).join(","); const getShaderSource = (shaderHelper) => ` ${(() => { shaderHelper.registerUniform("outputSize", "u32"); for (let i = 0; i < inputs.length; i++) { shaderHelper.registerUniform(`sizeInConcatAxis${i}`, "u32"); } return shaderHelper.declareVariables(...inputVars, output); })()} ${calculateInputIndexImpl(sizeInConcatAxis.length, sizeInConcatAxisStr)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} var indices = ${output.offsetToIndices("global_idx")}; let inputIndex = calculateInputIndex(${indicesAxis}); if (inputIndex != 0u) { let sizeInConcatAxis = array(${sizeInConcatAxisStr}); ${indicesAxis} -= sizeInConcatAxis[inputIndex - 1u]; } ${assignOutputData(inputVars, output)} }`; return { name: "Concat", shaderCache: { hint: `${adjustedAxis}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; concat = (context, attributes) => { const inputs = context.inputs; const inputShape = inputs[0].dims; const adjustedAxis = ShapeUtil.normalizeAxis(attributes.axis, inputShape.length); validateInputs7(inputs, adjustedAxis); const outputShape = inputShape.slice(); outputShape[adjustedAxis] = inputs.reduce( (sum, input) => sum + (input.dims.length > adjustedAxis ? input.dims[adjustedAxis] : 0), 0 ); const nonEmptyInputs = inputs.filter((input) => ShapeUtil.size(input.dims) > 0); context.compute(createConcatProgramInfo(nonEmptyInputs, adjustedAxis, outputShape, inputs[0].dataType), { inputs: nonEmptyInputs }); }; parseConcatAttributes = (attributes) => createAttributeWithCacheKey({ axis: attributes.axis }); } }); // web/lib/wasm/jsep/webgpu/ops/fuse-utils.ts var getActivationSnippet, appendActivationUniformsData, appendActivationUniforms, parseInternalActivationAttributes; var init_fuse_utils = __esm({ "web/lib/wasm/jsep/webgpu/ops/fuse-utils.ts"() { "use strict"; init_wasm_common(); init_util(); getActivationSnippet = (attributes, valueType, baseType = "f32") => { switch (attributes.activation) { case "Relu": return `value = max(value, ${valueType}(0.0));`; case "Sigmoid": return `value = (${valueType}(1.0) / (${valueType}(1.0) + exp(-value)));`; case "Clip": return `value = clamp(value, ${valueType}(${baseType}(uniforms.clip_min)), ${valueType}(${baseType}(uniforms.clip_max)));`; case "HardSigmoid": return `value = max(${valueType}(0.0), min(${valueType}(1.0), ${baseType}(uniforms.alpha) * value + ${baseType}(uniforms.beta)));`; case "LeakyRelu": return `value = select(${baseType}(uniforms.alpha) * value, value, value >= ${valueType}(0.0));`; case "Tanh": return `let e2x = exp(-2.0 * abs(value)); value = sign(value) * (1.0 - e2x) / (1.0 + e2x); `; case "": return ""; // TODO: adding other activations that can be fused. default: throw new Error(`Unsupported activation ${attributes.activation}`); } }; appendActivationUniformsData = (attributes, programUniform) => { if (attributes.activation === "Clip") { programUniform.push( { type: 1 /* float */, data: attributes.clipMax }, { type: 1 /* float */, data: attributes.clipMin } ); } else if (attributes.activation === "HardSigmoid") { programUniform.push( { type: 1 /* float */, data: attributes.alpha }, { type: 1 /* float */, data: attributes.beta } ); } else if (attributes.activation === "LeakyRelu") { programUniform.push({ type: 1 /* float */, data: attributes.alpha }); } }; appendActivationUniforms = (attributes, uniforms) => { if (attributes.activation === "Clip") { uniforms.push({ name: "clip_max", type: "f32" }, { name: "clip_min", type: "f32" }); } else if (attributes.activation === "HardSigmoid") { uniforms.push({ name: "alpha", type: "f32" }, { name: "beta", type: "f32" }); } else if (attributes.activation === "LeakyRelu") { uniforms.push({ name: "alpha", type: "f32" }); } }; parseInternalActivationAttributes = (attributes) => { const activation = attributes?.activation || ""; if (activation === "HardSigmoid") { const [alpha, beta] = attributes?.activation_params || [0.2, 0.5]; return { activation, alpha, beta }; } else if (activation === "Clip") { const [clipMin, clipMax] = attributes?.activation_params || [MIN_CLIP, MAX_CLIP]; return { activation, clipMax, clipMin }; } else if (activation === "LeakyRelu") { const [alpha] = attributes?.activation_params || [0.01]; return { activation, alpha }; } return { activation }; }; } }); // web/lib/wasm/jsep/webgpu/ops/3rd-party/activation_util.ts var typeSnippet, biasSnippet; var init_activation_util = __esm({ "web/lib/wasm/jsep/webgpu/ops/3rd-party/activation_util.ts"() { "use strict"; typeSnippet = (component, dataType) => { switch (component) { case 1: return dataType; case 2: return `vec2<${dataType}>`; case 3: return `vec3<${dataType}>`; case 4: return `vec4<${dataType}>`; default: throw new Error(`${component}-component is not supported.`); } }; biasSnippet = (hasBias) => ` ${hasBias ? "value = value + getBiasByOutputCoords(coords);" : ""} `; } }); // web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_util.ts var utilFunctions; var init_conv_util = __esm({ "web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_util.ts"() { "use strict"; utilFunctions = (strideStr) => ` fn getIndexFromCoords4D(coords : vec4, shape : vec4) -> i32 { return dot(coords, vec4( shape.y * shape.z * shape.w, shape.z * shape.w, shape.w, 1)); } fn getOutputIndexFromCoords(coords : vec4) -> i32 { return dot(coords, vec4( i32(${strideStr}.x), i32(${strideStr}.y), i32(${strideStr}.z), 1)); } `; } }); // web/lib/wasm/jsep/webgpu/ops/matmul-shaders.ts var convertOutputBatchIndicesToInputBatchIndices, createNaiveMatmulProgramInfo; var init_matmul_shaders = __esm({ "web/lib/wasm/jsep/webgpu/ops/matmul-shaders.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); init_fuse_utils(); convertOutputBatchIndicesToInputBatchIndices = (targetIndicesName, inputVariable2, inputBatchRank, outputBatchRank, batchIndicesName) => { const extendingInputRank = outputBatchRank - inputBatchRank; return ` ${Array.from({ length: inputBatchRank }).map( (_, i) => ` if (${getElementAt(inputVariable2.shape, i, inputVariable2.rank)} != 1) { ${inputVariable2.indicesSet(targetIndicesName, i, getElementAt(batchIndicesName, i + extendingInputRank, outputBatchRank))} } else { ${inputVariable2.indicesSet(targetIndicesName, i, 0)} }` ).join("")} `; }; createNaiveMatmulProgramInfo = (inputs, activationAttributes, outputShape, reshapedOutputShape, isChannelsLast = false, squeezeOutputShapeFunction) => { const aShape = inputs[0].dims; const bShape = inputs[1].dims; const M = aShape[aShape.length - 2]; const N = bShape[bShape.length - 1]; const K = aShape[aShape.length - 1]; const components = getMaxComponents(N); const aComponents = getMaxComponents(K); const outputNumber = getMaxComponents(M); const outputSize = ShapeUtil.size(outputShape) / components / outputNumber; const hasBias = inputs.length > 2; const outerDims = reshapedOutputShape ? reshapedOutputShape.slice(0, -2) : outputShape.slice(0, -2); const batchSize = ShapeUtil.size(outerDims); const outputShapeInShader = [batchSize, M, N]; const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: M }, { type: 12 /* uint32 */, data: N }, { type: 12 /* uint32 */, data: K } ]; appendActivationUniformsData(activationAttributes, programUniforms); programUniforms.push(...createTensorShapeVariables(outerDims, aShape, bShape)); if (hasBias) { programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); } programUniforms.push(...createTensorShapeVariables(outputShapeInShader)); const getShaderSource = (shaderHelper) => { const batchDims = internalVariable("batch_dims", inputs[0].dataType, outerDims.length); const a = inputVariable("a", inputs[0].dataType, aShape.length, aComponents); const b = inputVariable("b", inputs[1].dataType, bShape.length, components); const output = outputVariable("output", inputs[0].dataType, outputShapeInShader.length, components); const baseType = tensorTypeToWsglStorageType(output.type.tensor); const applyActivation = getActivationSnippet(activationAttributes, output.type.value, baseType); const inputVariables = [a, b]; let processBias = ""; if (hasBias) { const biasComponents = isChannelsLast ? components : 1; inputVariables.push(inputVariable("bias", inputs[2].dataType, inputs[2].dims.length, biasComponents)); processBias = `${isChannelsLast ? `value += bias[col / ${biasComponents}];` : `value += ${output.type.value}(bias[row + i]);`}`; } const uniforms = [ { name: "output_size", type: "u32" }, { name: "M", type: "u32" }, { name: "N", type: "u32" }, { name: "K", type: "u32" } ]; appendActivationUniforms(activationAttributes, uniforms); const calcResult = () => { let calcStr = `var a_data: ${a.type.value};`; for (let i = 0; i < aComponents; i++) { calcStr += ` let b_data${i} = b[(b_offset + (k + ${i}) * uniforms.N + col) / ${components}];`; } for (let i = 0; i < outputNumber; i++) { calcStr += `a_data = a[(a_offset + (row + ${i}) * uniforms.K + k) / ${aComponents}];`; for (let j = 0; j < aComponents; j++) { calcStr += ` values[${i}] = fma(${b.type.value}(a_data${aComponents === 1 ? "" : `[${j}]`}), b_data${j}, values[${i}]); `; } } return calcStr; }; return ` ${shaderHelper.registerUniforms(uniforms).registerInternalVariables(batchDims).declareVariables(...inputVariables, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let col = (global_idx % (uniforms.N / ${components})) * ${components}; var index1 = global_idx / (uniforms.N / ${components}); let stride1 = uniforms.M / ${outputNumber}; let row = (index1 % stride1) * ${outputNumber}; let batch = index1 / stride1; ${outputShape.length === 2 ? "" : `let batch_indices = ${batchDims.offsetToIndices("batch")};`} var a_indices: ${a.type.indices}; ${convertOutputBatchIndicesToInputBatchIndices("a_indices", a, a.rank - 2, batchDims.rank, "batch_indices")} ${a.indicesSet("a_indices", a.rank - 2, 0)} ${a.indicesSet("a_indices", a.rank - 1, 0)} let a_offset = ${a.indicesToOffset("a_indices")}; var b_indices: ${b.type.indices}; ${convertOutputBatchIndicesToInputBatchIndices("b_indices", b, b.rank - 2, batchDims.rank, "batch_indices")} ${b.indicesSet("b_indices", b.rank - 2, 0)} ${b.indicesSet("b_indices", b.rank - 1, 0)} let b_offset = ${b.indicesToOffset("b_indices")}; var values: array<${output.type.value}, ${outputNumber}>; for (var k: u32 = 0u; k < uniforms.K; k = k + ${aComponents}) { ${calcResult()} } for (var i = 0u; i < ${outputNumber}u; i++) { var value = values[i]; ${processBias} ${applyActivation} let cur_indices = ${output.type.indices}(batch, row + i, col); let offset = ${output.indicesToOffset("cur_indices")}; ${output.setByOffset(`offset / ${components}`, "value")}; } } `; }; return { name: "MatMulNaive", shaderCache: { hint: `${activationAttributes.activation};${components};${aComponents};${outputNumber};${isChannelsLast}`, inputDependencies: hasBias ? ["rank", "rank", "rank"] : ["rank", "rank"] }, getRunData: () => ({ outputs: [ { dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, dataType: inputs[0].dataType } ], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; } }); // web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts var writeDataToSubAVec4Snippet, calculateResultSnippet, makeMatMulPackedVec4Source, writeDataToSubASnippet, readDataFromSubASnippet, makeMatMulPackedSource, matMulReadWriteFnSource, createMatmulProgramInfo; var init_matmul_packed_webgpu = __esm({ "web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); init_fuse_utils(); init_matmul_shaders(); init_activation_util(); writeDataToSubAVec4Snippet = (transpose2, batchDims) => { if (transpose2) { return ` mm_Asub[inputRow][inputCol] = mm_readA(batch, kStart + inputRow, globalRowStart / innerElementSize + inputCol${batchDims ? ", batchIndices" : ""}); `; } else { return ` mm_Asub[inputRow][inputCol] = mm_readA(batch, globalRow + innerRow, kStart / innerElementSize + inputCol${batchDims ? ", batchIndices" : ""}); `; } }; calculateResultSnippet = (transposeA, innerElementSize) => { if (transposeA) { return ` let ACached0 = mm_Asub[k * innerElementSize][localRow]; let ACached1 = mm_Asub[k * innerElementSize + 1][localRow]; let ACached2 = mm_Asub[k * innerElementSize + 2][localRow]; ${innerElementSize === 3 ? "" : "let ACached3 = mm_Asub[k * innerElementSize + 3][localRow];"} for (var i = 0; i < rowPerThread; i = i + 1) { acc[i] = BCached0 * ACached0[i] + acc[i]; acc[i] = BCached1 * ACached1[i] + acc[i]; acc[i] = BCached2 * ACached2[i] + acc[i]; ${innerElementSize === 3 ? "" : "acc[i] = BCached3 * ACached3[i] + acc[i];"} }`; } else { return ` for (var i = 0; i < rowPerThread; i = i + 1) { let ACached = mm_Asub[tileRow + i][k]; acc[i] = BCached0 * ACached.x + acc[i]; acc[i] = BCached1 * ACached.y + acc[i]; acc[i] = BCached2 * ACached.z + acc[i]; ${innerElementSize === 3 ? "" : "acc[i] = BCached3 * ACached.w + acc[i];"} }`; } }; makeMatMulPackedVec4Source = (workPerThread, workgroupSize, type = "f32", batchDims, transposeA = false, tileInner = 32, splitK = false, splitedDimInner = 32) => { const tileAOuter = workgroupSize[1] * workPerThread[1]; const tileBOuter = workgroupSize[0] * workPerThread[0]; const tileAWidth = transposeA ? tileAOuter : tileInner; const tileAHight = transposeA ? tileInner : tileAOuter; const innerElementSize = tileAWidth / workgroupSize[0]; const rowPerThreadB = tileInner / workgroupSize[1]; if (!((transposeA && innerElementSize === 4 && workPerThread[1] === 4 || !transposeA && (innerElementSize === 3 || innerElementSize === 4)) && tileAWidth % workgroupSize[0] === 0 && tileInner % workgroupSize[1] === 0 && workPerThread[0] === 4)) { throw new Error(`If transposeA ${transposeA} is true, innerElementSize ${innerElementSize} and workPerThread[1] ${workPerThread[1]} must be 4. Otherwise, innerElementSize ${innerElementSize} must be 3 or 4. tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${workgroupSize[0]}. tileInner ${tileInner} must be divisible by workgroupSize[1] ${workgroupSize[1]}. colPerThread ${workPerThread[0]} must be 4.`); } return ` var mm_Asub: array, ${tileAWidth / innerElementSize}>, ${tileAHight}>; var mm_Bsub: array, ${tileBOuter / workPerThread[0]}>, ${tileInner}>; const rowPerThread = ${workPerThread[1]}; const colPerThread = ${workPerThread[0]}; const innerElementSize = ${innerElementSize}; const tileInner = ${tileInner}; @compute @workgroup_size(${workgroupSize[0]}, ${workgroupSize[1]}, ${workgroupSize[2]}) fn main(@builtin(local_invocation_id) localId : vec3, @builtin(global_invocation_id) globalId : vec3, @builtin(workgroup_id) workgroupId : vec3) { let localRow = i32(localId.y); let tileRow = localRow * rowPerThread; let tileCol = i32(localId.x); let globalRow =i32(globalId.y) * rowPerThread; let globalCol = i32(globalId.x); let batch = ${splitK ? "0" : "i32(globalId.z)"}; ${batchDims ? `let batchIndices = ${batchDims.offsetToIndices("u32(batch)")};` : ""} let globalRowStart = i32(workgroupId.y) * ${tileAOuter}; let num_tiles = ${splitK ? `${Math.ceil(splitedDimInner / tileInner)}` : "(uniforms.dim_inner - 1) / tileInner + 1"}; var kStart = ${splitK ? `i32(globalId.z) * ${splitedDimInner}` : "0"}; var acc: array, rowPerThread>; // Loop over shared dimension. let tileRowB = localRow * ${rowPerThreadB}; for (var t = 0; t < num_tiles; t = t + 1) { // Load one tile of A into local memory. for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { let inputRow = tileRow + innerRow; let inputCol = tileCol; ${writeDataToSubAVec4Snippet(transposeA, batchDims)} } // Load one tile of B into local memory. for (var innerRow = 0; innerRow < ${rowPerThreadB}; innerRow = innerRow + 1) { let inputRow = tileRowB + innerRow; let inputCol = tileCol; mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol${batchDims ? ", batchIndices" : ""}); } kStart = kStart + tileInner; workgroupBarrier(); // Compute acc values for a single thread. for (var k = 0; k < tileInner / innerElementSize; k = k + 1) { let BCached0 = mm_Bsub[k * innerElementSize][tileCol]; let BCached1 = mm_Bsub[k * innerElementSize + 1][tileCol]; let BCached2 = mm_Bsub[k * innerElementSize + 2][tileCol]; ${innerElementSize === 3 ? "" : "let BCached3 = mm_Bsub[k * innerElementSize + 3][tileCol];"} ${calculateResultSnippet(transposeA, innerElementSize)} } workgroupBarrier(); } for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { mm_write(batch, globalRow + innerRow, globalCol, acc[innerRow]); } }`; }; writeDataToSubASnippet = (transpose2, batchDims) => { if (transpose2) { return ` mm_Asub[inputRow][inputCol] = mm_readA(batch, kStart + inputRow, globalRowStart + inputCol${batchDims ? ", batchIndices" : ""}); `; } else { return ` mm_Asub[inputRow][inputCol] = mm_readA(batch, globalRowStart + inputRow, kStart + inputCol${batchDims ? ", batchIndices" : ""}); `; } }; readDataFromSubASnippet = (transposeA) => transposeA ? "let ACached = mm_Asub[k][tileRow + innerRow];" : "let ACached = mm_Asub[tileRow + innerRow][k];"; makeMatMulPackedSource = (workPerThread, workgroupSize, type = "f32", batchDims, transposeA = false, tileInner = 32, splitK = false, splitedDimInner = 32, sequentialAccessByThreads = false) => { const tileAOuter = workPerThread[1] * workgroupSize[1]; const tileBOuter = workPerThread[0] * workgroupSize[0]; const tileAWidth = transposeA ? tileAOuter : tileInner; const tileAHight = transposeA ? tileInner : tileAOuter; if (!(tileAHight % workgroupSize[1] === 0 && tileAWidth % workgroupSize[0] === 0 && tileInner % workgroupSize[1] === 0)) { throw new Error( `tileAHight ${tileAHight} must be divisible by workgroupSize[1]${workgroupSize[1]}, tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${workgroupSize[0]}, tileInner ${tileInner} must be divisible by workgroupSize[1]${workgroupSize[1]}` ); } const rowPerThreadA = tileAHight / workgroupSize[1]; const colPerThreadA = tileAWidth / workgroupSize[0]; const rowPerThreadB = tileInner / workgroupSize[1]; const matmulSnippet = sequentialAccessByThreads ? ` let localRow = i32(localId.y); let localCol = i32(localId.x); let globalRowStart = i32(workgroupId.y) * ${tileAOuter}; let globalColStart = i32(workgroupId.x) * ${tileBOuter}; // Loop over shared dimension. for (var t = 0; t < num_tiles; t = t + 1) { // Load one tile of A into local memory. for (var inputRow = localRow; inputRow < ${tileAHight}; inputRow = inputRow + ${workgroupSize[1]}) { for (var inputCol = localCol; inputCol < ${tileAWidth}; inputCol = inputCol + ${workgroupSize[0]}) { ${writeDataToSubASnippet(transposeA, batchDims)} } } // Load one tile of B into local memory. for (var inputRow = localRow; inputRow < ${tileInner}; inputRow = inputRow + ${workgroupSize[1]}) { for (var inputCol = localCol; inputCol < ${tileBOuter}; inputCol = inputCol + ${workgroupSize[0]}) { mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalColStart + inputCol${batchDims ? ", batchIndices" : ""}); } } kStart = kStart + tileInner; workgroupBarrier(); // Compute acc values for a single thread. var BCached : array<${type}, colPerThread>; for (var k = 0; k < tileInner; k = k + 1) { for (var inner = 0; inner < colPerThread; inner = inner + 1) { BCached[inner] = mm_Bsub[k][localCol + inner * ${workgroupSize[0]}]; } for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { let ACached = ${transposeA ? `mm_Asub[k][localRow + innerRow * ${workgroupSize[1]}];` : `mm_Asub[localRow + innerRow * ${workgroupSize[1]}][k];`} for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { acc[innerRow][innerCol] = acc[innerRow][innerCol] + ACached * BCached[innerCol]; } } } workgroupBarrier(); } for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { let gRow = globalRowStart + localRow + innerRow * ${workgroupSize[1]}; for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { let gCol = globalColStart + localCol + innerCol * ${workgroupSize[0]}; mm_write(batch, gRow, gCol, acc[innerRow][innerCol]); } } ` : ` let tileRow = i32(localId.y) * rowPerThread; let tileCol = i32(localId.x) * colPerThread; let globalRow = i32(globalId.y) * rowPerThread; let globalCol = i32(globalId.x) * colPerThread; let globalRowStart = i32(workgroupId.y) * ${tileAOuter}; let tileRowA = i32(localId.y) * ${rowPerThreadA}; let tileColA = i32(localId.x) * ${colPerThreadA}; let tileRowB = i32(localId.y) * ${rowPerThreadB}; // Loop over shared dimension. for (var t = 0; t < num_tiles; t = t + 1) { // Load one tile of A into local memory. for (var innerRow = 0; innerRow < ${rowPerThreadA}; innerRow = innerRow + 1) { for (var innerCol = 0; innerCol < ${colPerThreadA}; innerCol = innerCol + 1) { let inputRow = tileRowA + innerRow; let inputCol = tileColA + innerCol; ${writeDataToSubASnippet(transposeA, batchDims)} } } // Load one tile of B into local memory. for (var innerRow = 0; innerRow < ${rowPerThreadB}; innerRow = innerRow + 1) { for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { let inputRow = tileRowB + innerRow; let inputCol = tileCol + innerCol; mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol + innerCol${batchDims ? ", batchIndices" : ""}); } } kStart = kStart + tileInner; workgroupBarrier(); // Compute acc values for a single thread. var BCached : array<${type}, colPerThread>; for (var k = 0; k < tileInner; k = k + 1) { for (var inner = 0; inner < colPerThread; inner = inner + 1) { BCached[inner] = mm_Bsub[k][tileCol + inner]; } for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { ${readDataFromSubASnippet(transposeA)} for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { acc[innerRow][innerCol] = acc[innerRow][innerCol] + ACached * BCached[innerCol]; } } } workgroupBarrier(); } for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { mm_write(batch, globalRow + innerRow, globalCol + innerCol, acc[innerRow][innerCol]); } } `; return ` var mm_Asub : array, ${tileAHight}>; var mm_Bsub : array, ${tileInner}>; const rowPerThread = ${workPerThread[1]}; const colPerThread = ${workPerThread[0]}; const tileInner = ${tileInner}; @compute @workgroup_size(${workgroupSize[0]}, ${workgroupSize[1]}, ${workgroupSize[2]}) fn main(@builtin(local_invocation_id) localId : vec3, @builtin(global_invocation_id) globalId : vec3, @builtin(workgroup_id) workgroupId : vec3) { let batch = ${splitK ? "0" : "i32(globalId.z)"}; ${batchDims ? `let batchIndices = ${batchDims.offsetToIndices("u32(batch)")};` : ""} let num_tiles = ${splitK ? `${Math.ceil(splitedDimInner / tileInner)}` : "(uniforms.dim_inner - 1) / tileInner + 1"}; var kStart = ${splitK ? `i32(globalId.z) * ${splitedDimInner}` : "0"}; var acc : array, rowPerThread>; ${matmulSnippet} } `; }; matMulReadWriteFnSource = (component, hasBias, applyActivation, variables, isChannelsLast = false) => { const [batchVariable, aVariable, bVariable, outputVariable2] = variables; const dataType = tensorTypeToWsglStorageType(variables[0].type.tensor); const source = ` fn mm_readA(batch: i32, row: i32, colIn: i32, batchIndices: ${batchVariable.type.indices}) -> ${typeSnippet( component, dataType )} { var value = ${typeSnippet(component, dataType)}(0.0); let col = colIn * ${component}; if(row < uniforms.dim_a_outer && col < uniforms.dim_inner) { var aIndices: ${aVariable.type.indices}; ${convertOutputBatchIndicesToInputBatchIndices( "aIndices", aVariable, aVariable.rank - 2, batchVariable.rank, "batchIndices" )} ${aVariable.indicesSet("aIndices", aVariable.rank - 2, "u32(row)")} ${aVariable.indicesSet("aIndices", aVariable.rank - 1, "u32(colIn)")} value = ${aVariable.getByIndices("aIndices")}; } return value; } fn mm_readB(batch: i32, row: i32, colIn: i32, batchIndices: ${batchVariable.type.indices}) -> ${typeSnippet( component, dataType )} { var value = ${typeSnippet(component, dataType)}(0.0); let col = colIn * ${component}; if(row < uniforms.dim_inner && col < uniforms.dim_b_outer) { var bIndices: ${bVariable.type.indices}; ${convertOutputBatchIndicesToInputBatchIndices( "bIndices", bVariable, bVariable.rank - 2, batchVariable.rank, "batchIndices" )} ${bVariable.indicesSet("bIndices", bVariable.rank - 2, "u32(row)")} ${bVariable.indicesSet("bIndices", bVariable.rank - 1, "u32(colIn)")} value = ${bVariable.getByIndices("bIndices")}; } return value; } fn mm_write(batch: i32, row: i32, colIn: i32, valueIn: ${typeSnippet(component, dataType)}) { let col = colIn * ${component}; if (row < uniforms.dim_a_outer && col < uniforms.dim_b_outer) { var value = valueIn; let coords = vec3(batch, row, colIn); ${hasBias ? `value = value + ${isChannelsLast ? "bias[colIn]" : `${typeSnippet(component, dataType)}(bias[row])`};` : ""} ${applyActivation} ${outputVariable2.setByIndices("vec3(coords)", "value")} } } `; return source; }; createMatmulProgramInfo = (inputs, activationAttributes, outputShape, reshapedOutputShape, isChannelsLast = false, squeezeOutputShapeFunction) => { const aShape = inputs[0].dims; const bShape = inputs[1].dims; const outerDimsA = aShape.slice(0, -2); const outerDimsB = bShape.slice(0, -2); const outerDims = reshapedOutputShape ? reshapedOutputShape.slice(0, -2) : outputShape.slice(0, -2); const batchSize = ShapeUtil.size(outerDims); const dimAOuter = aShape[aShape.length - 2]; const dimInner = aShape[aShape.length - 1]; const dimBOuter = bShape[bShape.length - 1]; const isVec4 = dimInner % 4 === 0 && dimBOuter % 4 === 0; const elementsPerThread = dimAOuter <= 8 ? [4, 1, 1] : [4, 4, 1]; const workgroupSize = [8, 8, 1]; const dispatch = [ Math.ceil(dimBOuter / workgroupSize[0] / elementsPerThread[0]), Math.ceil(dimAOuter / workgroupSize[1] / elementsPerThread[1]), Math.ceil(batchSize / workgroupSize[2] / elementsPerThread[2]) ]; const components = isVec4 ? 4 : 1; const aShapeTemp = [...outerDimsA, dimAOuter, dimInner / components]; const aRank = aShapeTemp.length; const bShapeTemp = [...outerDimsB, dimInner, dimBOuter / components]; const bRank = bShapeTemp.length; const outputShapeTemp = [batchSize, dimAOuter, dimBOuter / components]; const programUniforms = [ { type: 6 /* int32 */, data: dimAOuter }, { type: 6 /* int32 */, data: dimBOuter }, { type: 6 /* int32 */, data: dimInner } ]; appendActivationUniformsData(activationAttributes, programUniforms); programUniforms.push(...createTensorShapeVariables(outerDims, aShapeTemp, bShapeTemp)); const inputDependencies = ["rank", "rank"]; const hasBias = inputs.length > 2; if (hasBias) { programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); inputDependencies.push("rank"); } programUniforms.push(...createTensorShapeVariables(outputShapeTemp)); const getShaderSource = (shaderHelper) => { const batchRank = outerDims.length; const batchDims = internalVariable("batchDims", inputs[0].dataType, batchRank, 1); const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); const A = inputVariable("a", inputs[0].dataType, aRank, components); const B = inputVariable("b", inputs[1].dataType, bRank, components); const output = outputVariable("result", inputs[0].dataType, outputShapeTemp.length, components); const inputVariables = [A, B]; if (hasBias) { const biasComponents = isChannelsLast ? components : 1; inputVariables.push(inputVariable("bias", inputs[2].dataType, inputs[2].dims.length, biasComponents)); } const uniforms = [ { name: "dim_a_outer", type: "i32" }, { name: "dim_b_outer", type: "i32" }, { name: "dim_inner", type: "i32" } ]; appendActivationUniforms(activationAttributes, uniforms); const baseType = tensorTypeToWsglStorageType(output.type.tensor); const applyActivation = getActivationSnippet(activationAttributes, output.type.value, baseType); const declareFunctions = matMulReadWriteFnSource( components, hasBias, applyActivation, [batchDims, A, B, output], isChannelsLast ); return ` ${shaderHelper.registerUniforms(uniforms).registerInternalVariables(batchDims).declareVariables(...inputVariables, output)} ${declareFunctions} ${isVec4 ? makeMatMulPackedVec4Source(elementsPerThread, workgroupSize, dataType, batchDims) : makeMatMulPackedSource(elementsPerThread, workgroupSize, dataType, batchDims)} `; }; return { name: "MatMul", shaderCache: { hint: `${elementsPerThread};${activationAttributes.activation};${isVec4};${isChannelsLast}`, inputDependencies }, getRunData: () => ({ outputs: [ { dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, dataType: inputs[0].dataType } ], dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, programUniforms }), getShaderSource }; }; } }); // web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts var conv2dCommonSnippet, createConv2DMatMulProgramInfo; var init_conv2d_mm_webgpu = __esm({ "web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts"() { "use strict"; init_wasm_common(); init_log(); init_common(); init_fuse_utils(); init_activation_util(); init_conv_util(); init_matmul_packed_webgpu(); conv2dCommonSnippet = (isChannelsLast, fitAOuter, fitBOuter, fitInner, addBias = false, attributes, innerElementSizeX = 4, innerElementSizeW = 4, innerElementSize = 4, dataType = "f32") => { const getXSnippet = (innerElementSize2) => { switch (innerElementSize2) { case 1: return "resData = x[xIndex];"; case 3: return `resData = vec3<${dataType}>(x[xIndex], x[xIndex + 1], x[xIndex + 2]);`; case 4: return "resData = x[xIndex / 4];"; default: throw new Error(`innerElementSize ${innerElementSize2} is not supported.`); } }; const getWSnippet = (innerElementSize2) => { switch (innerElementSize2) { case 1: return "return w[row * i32(uniforms.w_shape[3]) + colIn];"; case 4: return "return w[row * i32(uniforms.w_shape[3]) / 4 + colIn];"; default: throw new Error(`innerElementSize ${innerElementSize2} is not supported.`); } }; const coordASnippet = isChannelsLast ? ` let coord = vec4(batch, xRow, xCol, xCh); ` : ` let coord = vec4(batch, xCh, xRow, xCol); `; const coordResSnippet = isChannelsLast ? ` let coords = vec4( batch, row / outWidth, row % outWidth, col); ` : ` let coords = vec4( batch, row, col / outWidth, col % outWidth); `; const xHeight = isChannelsLast ? "i32(uniforms.x_shape[1])" : "i32(uniforms.x_shape[2])"; const xWidth = isChannelsLast ? "i32(uniforms.x_shape[2])" : "i32(uniforms.x_shape[3])"; const row = isChannelsLast ? "row" : "col"; const col = isChannelsLast ? "col" : "row"; const readXSnippet = ` let inChannels = i32(uniforms.w_shape[2]); let outWidth = ${isChannelsLast ? "i32(uniforms.result_shape[2])" : "i32(uniforms.result_shape[3])"}; let outRow = ${row} / outWidth; let outCol = ${row} % outWidth; let WRow = ${col} / (i32(uniforms.w_shape[1]) * inChannels); let WCol = ${col} / inChannels % i32(uniforms.w_shape[1]); let xRow = outRow * uniforms.stride[0] + uniforms.dilation[0] * WRow - uniforms.pad[0]; let xCol = outCol * uniforms.stride[1] + uniforms.dilation[1] * WCol - uniforms.pad[1]; let xCh = ${col} % inChannels; var resData = ${typeSnippet(innerElementSizeX, dataType)}(0.0); // The bounds checking is always needed since we use it to pad zero for // the 'same' padding type. if (xRow >= 0 && xRow < ${xHeight} && xCol >= 0 && xCol < ${xWidth}) { ${coordASnippet} let xIndex = getIndexFromCoords4D(coord, vec4(uniforms.x_shape)); ${getXSnippet(innerElementSizeX)} } return resData;`; const sampleX = isChannelsLast ? fitAOuter && fitInner ? ` let col = colIn * ${innerElementSizeX}; ${readXSnippet}` : ` let col = colIn * ${innerElementSizeX}; if (row < uniforms.dim_a_outer && col < uniforms.dim_inner) { ${readXSnippet} } return ${typeSnippet(innerElementSizeX, dataType)}(0.0);` : fitInner && fitBOuter ? ` let col = colIn * ${innerElementSizeX}; ${readXSnippet}` : ` let col = colIn * ${innerElementSizeX}; if (row < uniforms.dim_inner && col < uniforms.dim_b_outer) { ${readXSnippet} } return ${typeSnippet(innerElementSizeX, dataType)}(0.0);`; const sampleW = isChannelsLast ? fitInner && fitBOuter ? getWSnippet(innerElementSizeW) : ` let col = colIn * ${innerElementSizeW}; if (row < uniforms.dim_inner && col < uniforms.dim_b_outer) { ${getWSnippet(innerElementSizeW)} } return ${typeSnippet(innerElementSizeW, dataType)}(0.0);` : ` let col = colIn * ${innerElementSizeW}; if (row < uniforms.dim_inner && col < uniforms.dim_a_outer) { ${getWSnippet(innerElementSizeW)} } return ${typeSnippet(innerElementSizeW, dataType)}(0.0);`; const resType = typeSnippet(innerElementSize, dataType); const aType = isChannelsLast ? typeSnippet(innerElementSizeX, dataType) : typeSnippet(innerElementSizeW, dataType); const bType = isChannelsLast ? typeSnippet(innerElementSizeW, dataType) : typeSnippet(innerElementSizeX, dataType); const applyActivation = getActivationSnippet(attributes, resType, dataType); const userCode = ` fn mm_readA(batch: i32, row : i32, colIn : i32) -> ${aType} { ${isChannelsLast ? sampleX : sampleW} } fn mm_readB(batch: i32, row : i32, colIn : i32) -> ${bType} { ${isChannelsLast ? sampleW : sampleX} } fn mm_write(batch: i32, row : i32, colIn : i32, valueIn : ${resType}) { let col = colIn * ${innerElementSize}; if (row < uniforms.dim_a_outer && col < uniforms.dim_b_outer) { var value = valueIn; let outWidth = ${isChannelsLast ? "i32(uniforms.result_shape[2])" : "i32(uniforms.result_shape[3])"}; ${coordResSnippet} ${biasSnippet(addBias)} ${applyActivation} setOutputAtCoords(coords[0], coords[1], coords[2], coords[3], value); } }`; return userCode; }; createConv2DMatMulProgramInfo = (inputs, attributes, outputShape, dimAOuter, dimBOuter, dimInner, hasBias, sequentialAccessByThreads, squeezeOutputShapeFunction) => { const isChannelsLast = attributes.format === "NHWC"; const inChannels = isChannelsLast ? inputs[0].dims[3] : inputs[0].dims[1]; const batchSize = outputShape[0]; const outWidth = isChannelsLast ? outputShape[2] : outputShape[3]; const outHeight = isChannelsLast ? outputShape[1] : outputShape[2]; const outChannels = isChannelsLast ? outputShape[3] : outputShape[1]; const isVec4 = isChannelsLast && (inChannels % 4 === 0 || inChannels % 3 === 0) && outChannels % 4 === 0; const dispatchX = isChannelsLast ? outChannels : outWidth * outHeight; const dispatchY = isChannelsLast ? outWidth * outHeight : outChannels; const workGroupSize = [8, 8, 1]; const elementsPerThread = dimAOuter <= 8 ? [4, 1, 1] : [4, 4, 1]; const dispatch = [ Math.ceil(dispatchX / workGroupSize[0] / elementsPerThread[0]), Math.ceil(dispatchY / workGroupSize[1] / elementsPerThread[1]), Math.ceil(batchSize / workGroupSize[2] / elementsPerThread[2]) ]; LOG_DEBUG("verbose", () => `[conv2d_mm_webgpu] dispatch = ${dispatch}`); const innerElementSize = isVec4 ? isChannelsLast && inChannels % 4 !== 0 ? 3 : 4 : 1; const tileAOuter = workGroupSize[1] * elementsPerThread[1]; const tileBOuter = workGroupSize[0] * elementsPerThread[0]; const tileInner = Math.max(workGroupSize[0] * innerElementSize, workGroupSize[1]); const fitAOuter = dimAOuter % tileAOuter === 0; const fitBOuter = dimBOuter % tileBOuter === 0; const fitInner = dimInner % tileInner === 0; const elementsSize = isVec4 ? [innerElementSize, 4, 4] : [1, 1, 1]; const programUniforms = [ { type: 6 /* int32 */, data: dimAOuter }, { type: 6 /* int32 */, data: dimBOuter }, { type: 6 /* int32 */, data: dimInner }, { type: 6 /* int32 */, data: [attributes.pads[0], attributes.pads[1]] }, { type: 6 /* int32 */, data: attributes.strides }, { type: 6 /* int32 */, data: attributes.dilations } ]; appendActivationUniformsData(attributes, programUniforms); programUniforms.push(...createTensorShapeVariables(inputs[0].dims, inputs[1].dims)); const inputDependencies = ["rank", "rank"]; if (hasBias) { programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); inputDependencies.push("rank"); } programUniforms.push(...createTensorShapeVariables(outputShape)); const getShaderSource = (shaderHelper) => { const uniforms = [ { name: "dim_a_outer", type: "i32" }, { name: "dim_b_outer", type: "i32" }, { name: "dim_inner", type: "i32" }, { name: "pad", type: "i32", length: 2 }, { name: "stride", type: "i32", length: 2 }, { name: "dilation", type: "i32", length: 2 } ]; appendActivationUniforms(attributes, uniforms); const components = isVec4 ? 4 : 1; const t = tensorTypeToWsglStorageType(inputs[0].dataType); let declareFunctions = ` fn setOutputAtIndex(flatIndex : i32, value : ${isVec4 ? `vec4<${t}>` : t}) { result[flatIndex] = ${isVec4 ? `vec4<${t}>` : t}(value); } fn setOutputAtCoords(d0 : i32, d1 : i32, d2 : i32, d3 : i32, value : ${isVec4 ? `vec4<${t}>` : t}) { let flatIndex = getOutputIndexFromCoords(vec4(d0, d1, d2, d3)); setOutputAtIndex(flatIndex ${isVec4 ? "/ 4" : ""}, value); }`; const x = inputVariable( "x", inputs[0].dataType, inputs[0].dims.length, innerElementSize === 3 ? 1 : innerElementSize ); const w = inputVariable("w", inputs[1].dataType, inputs[1].dims.length, components); const inputVariables = [x, w]; const output = outputVariable("result", inputs[0].dataType, outputShape.length, components); if (hasBias) { const bias = inputVariable("bias", inputs[2].dataType, inputs[2].dims.length, components); inputVariables.push(bias); declareFunctions += ` fn getBiasByOutputCoords(coords : vec4) -> ${isVec4 ? `vec4<${t}>` : t} { return bias[coords.${isChannelsLast ? "w" : "y"}${isVec4 ? "/ 4" : ""}]; }`; } return ` ${utilFunctions("uniforms.result_strides")} //struct Uniforms { xShape : vec4, wShape : vec4, outShape : vec4, // outShapeStrides: vec3, filterDims : vec2, pad : vec2, stride : vec2, // dilation : vec2, dimAOuter : i32, dimBOuter : i32, dimInner : i32 }; ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} ${declareFunctions} ${conv2dCommonSnippet( isChannelsLast, fitAOuter, fitBOuter, fitInner, hasBias, attributes, elementsSize[0], elementsSize[1], elementsSize[2], t )} ${isVec4 ? makeMatMulPackedVec4Source(elementsPerThread, workGroupSize, t, void 0, !isChannelsLast, tileInner) : makeMatMulPackedSource( elementsPerThread, workGroupSize, t, void 0, !isChannelsLast, tileInner, false, void 0, sequentialAccessByThreads )}`; }; return { name: "Conv2DMatMul", shaderCache: { hint: `${attributes.cacheKey};${innerElementSize};${isVec4};${fitAOuter};${fitBOuter};${fitInner};${tileAOuter};${tileBOuter};${tileInner}`, inputDependencies }, getRunData: () => ({ outputs: [ { dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, dataType: inputs[0].dataType } ], dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, programUniforms }), getShaderSource }; }; } }); // web/lib/wasm/jsep/webgpu/ops/3rd-party/conv3d_naive_webgpu.ts var arrayProduct, parse3TupleParam, getEffectiveFilterSize, computeDefaultPad, computeOutputShape4D, get3DPadAndOutInfo, computeConv3DInfo, createConv3DNaiveProgramInfo; var init_conv3d_naive_webgpu = __esm({ "web/lib/wasm/jsep/webgpu/ops/3rd-party/conv3d_naive_webgpu.ts"() { "use strict"; init_wasm_common(); init_log(); init_util(); init_common(); init_fuse_utils(); init_activation_util(); arrayProduct = (arr) => { let product = 1; for (let i = 0; i < arr.length; i++) { product *= arr[i]; } return product; }; parse3TupleParam = (param) => typeof param === "number" ? [param, param, param] : param; getEffectiveFilterSize = (filterSize, dilation) => { if (dilation <= 1) { return filterSize; } return filterSize + (filterSize - 1) * (dilation - 1); }; computeDefaultPad = (inputShape, fieldSize, stride, dilation = 1) => { const effectiveFieldSize = getEffectiveFilterSize(fieldSize, dilation); return Math.floor((inputShape[0] * (stride - 1) - stride + effectiveFieldSize) / 2); }; computeOutputShape4D = (inShape, filterShape, outChannels, strides, zeroPad) => { if (zeroPad == null) { zeroPad = computeDefaultPad(inShape, filterShape[0], strides[0]); } const outShape = [0, 0, 0, outChannels]; for (let index = 0; index < 3; index++) { if (inShape[index] + 2 * zeroPad >= filterShape[index]) { outShape[index] = Math.trunc((inShape[index] - filterShape[index] + 2 * zeroPad) / strides[index] + 1); } } return outShape; }; get3DPadAndOutInfo = (pad2, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, filterDepth, filterHeight, filterWidth) => { let padInfo; let outDepth; let outHeight; let outWidth; if (pad2 === "VALID") { pad2 = 0; } if (typeof pad2 === "number") { padInfo = { top: pad2, bottom: pad2, left: pad2, right: pad2, front: pad2, back: pad2 }; const outShape = computeOutputShape4D( [inDepth, inHeight, inWidth, 1], [filterDepth, filterHeight, filterWidth], 1, [strideDepth, strideHeight, strideWidth], pad2 ); outDepth = outShape[0]; outHeight = outShape[1]; outWidth = outShape[2]; } else if (Array.isArray(pad2)) { if (!pad2.every((val, _, arr) => val === arr[0])) { throw Error(`Unsupported padding parameter: ${pad2}`); } padInfo = { top: pad2[0], bottom: pad2[1], left: pad2[2], right: pad2[3], front: pad2[4], back: pad2[5] }; const outShape = computeOutputShape4D( [inDepth, inHeight, inWidth, 1], [filterDepth, filterHeight, filterWidth], 1, [strideDepth, strideHeight, strideWidth], pad2[0] ); outDepth = outShape[0]; outHeight = outShape[1]; outWidth = outShape[2]; } else if (pad2 === "SAME_UPPER") { outDepth = Math.ceil(inDepth / strideDepth); outHeight = Math.ceil(inHeight / strideHeight); outWidth = Math.ceil(inWidth / strideWidth); const padAlongDepth = (outDepth - 1) * strideDepth + filterDepth - inDepth; const padAlongHeight = (outHeight - 1) * strideHeight + filterHeight - inHeight; const padAlongWidth = (outWidth - 1) * strideWidth + filterWidth - inWidth; const front = Math.floor(padAlongDepth / 2); const back = padAlongDepth - front; const top = Math.floor(padAlongHeight / 2); const bottom = padAlongHeight - top; const left = Math.floor(padAlongWidth / 2); const right = padAlongWidth - left; padInfo = { top, bottom, left, right, front, back }; } else { throw Error(`Unknown padding parameter: ${pad2}`); } return { padInfo, outDepth, outHeight, outWidth }; }; computeConv3DInfo = (inShape, filterShape, strides, dilations, pad2, depthwise = false, dataFormat = "channelsLast") => { let batchSize, inDepth, inHeight, inWidth, inChannels; if (dataFormat === "channelsLast") { [batchSize, inDepth, inHeight, inWidth, inChannels] = inShape; } else if (dataFormat === "channelsFirst") { [batchSize, inChannels, inDepth, inHeight, inWidth] = inShape; } else { throw new Error(`Unknown dataFormat ${dataFormat}`); } const [filterChannels, , filterDepth, filterHeight, filterWidth] = filterShape; const [strideDepth, strideHeight, strideWidth] = parse3TupleParam(strides); const [dilationDepth, dilationHeight, dilationWidth] = parse3TupleParam(dilations); const effectiveFilterDepth = getEffectiveFilterSize(filterDepth, dilationDepth); const effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); const effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); const { padInfo, outDepth, outHeight, outWidth } = get3DPadAndOutInfo( pad2, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, effectiveFilterDepth, effectiveFilterHeight, effectiveFilterWidth ); const outChannels = depthwise ? filterChannels * inChannels : filterChannels; let outShape = [0, 0, 0, 0, 0]; if (dataFormat === "channelsFirst") { outShape = [batchSize, outChannels, outDepth, outHeight, outWidth]; } else if (dataFormat === "channelsLast") { outShape = [batchSize, outDepth, outHeight, outWidth, outChannels]; } return { batchSize, dataFormat, inDepth, inHeight, inWidth, inChannels, outDepth, outHeight, outWidth, outChannels, padInfo, strideDepth, strideHeight, strideWidth, filterDepth, filterHeight, filterWidth, effectiveFilterDepth, effectiveFilterHeight, effectiveFilterWidth, dilationDepth, dilationHeight, dilationWidth, inShape, outShape, filterShape }; }; createConv3DNaiveProgramInfo = (inputs, attributes, outputShape, filterDims, pads, dataFormat) => { const isChannelLast = dataFormat === "channelsLast"; const inChannels = isChannelLast ? inputs[0].dims[3] : inputs[0].dims[1]; const isVec4 = false; const workGroupSize = [64, 1, 1]; const dispatchLayout = { x: outputShape.map((_, i) => i) }; const dispatch = [Math.ceil(arrayProduct(dispatchLayout.x.map((d) => outputShape[d])) / workGroupSize[0]), 1, 1]; LOG_DEBUG("verbose", () => `[conv3d_naive_webgpu] dispatch = ${dispatch}`); const innerElementSize = isVec4 ? isChannelLast && inChannels % 4 !== 0 ? 3 : 4 : 1; const outputSize = ShapeUtil.size(outputShape); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: filterDims }, { type: 12 /* uint32 */, data: pads }, { type: 12 /* uint32 */, data: attributes.strides }, { type: 12 /* uint32 */, data: attributes.dilations } ]; appendActivationUniformsData(attributes, programUniforms); programUniforms.push(...createTensorShapeVariables(inputs[0].dims, inputs[1].dims)); const inputDependencies = ["rank", "rank"]; const hasBias = inputs.length === 3; if (hasBias) { programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); inputDependencies.push("rank"); } programUniforms.push(...createTensorShapeVariables(outputShape)); const getShaderSource = (shaderHelper) => { const uniforms = [ { name: "output_size", type: "u32" }, { name: "filter_dims", type: "u32", length: filterDims.length }, { name: "pads", type: "u32", length: pads.length }, { name: "strides", type: "u32", length: attributes.strides.length }, { name: "dilations", type: "u32", length: attributes.dilations.length } ]; appendActivationUniforms(attributes, uniforms); const components = isVec4 ? 4 : 1; const t = tensorTypeToWsglStorageType(inputs[0].dataType); const x = inputVariable( "x", inputs[0].dataType, inputs[0].dims.length, innerElementSize === 3 ? 1 : innerElementSize ); const w = inputVariable("W", inputs[1].dataType, inputs[1].dims.length, components); const inputVariables = [x, w]; const output = outputVariable("result", inputs[0].dataType, outputShape.length, components); let declareFunctions = ""; if (hasBias) { const bias = inputVariable("bias", inputs[2].dataType, inputs[2].dims.length, components); inputVariables.push(bias); declareFunctions += ` fn getBiasByOutputCoords(coords : array) -> ${isVec4 ? `vec4<${t}>` : t} { return bias[${isChannelLast ? getElementAt("coords", 4, 5) : getElementAt("coords", 1, 5)}${isVec4 ? "/ 4" : ""}]; }`; } const resType = typeSnippet(innerElementSize, t); const applyActivation = getActivationSnippet(attributes, resType, t); return ` ${declareFunctions} fn getX(d0 : u32, d1 : u32, d2 : u32, d3 : u32, d4 : u32) -> f32 { let aIndices = array(d0, d1, d2, d3, d4); return ${x.getByIndices("aIndices")}; } fn getW(d0 : u32, d1 : u32, d2 : u32, d3 : u32, d4 : u32) -> f32 { let aIndices = array(d0, d1, d2, d3, d4); return ${w.getByIndices("aIndices")}; } ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let coords = ${output.offsetToIndices("global_idx")}; let batch = ${getElementAt("coords", 0, x.rank)}; let d2 = ${isChannelLast ? getElementAt("coords", x.rank - 1, x.rank) : getElementAt("coords", 1, x.rank)}; let xFRCCorner = vec3(${isChannelLast ? getElementAt("coords", 1, x.rank) : getElementAt("coords", 2, x.rank)}, ${isChannelLast ? getElementAt("coords", 2, x.rank) : getElementAt("coords", 3, x.rank)}, ${isChannelLast ? getElementAt("coords", 3, x.rank) : getElementAt("coords", 4, x.rank)}) * uniforms.strides - uniforms.pads; let xFCorner = xFRCCorner.x; let xRCorner = xFRCCorner.y; let xCCorner = xFRCCorner.z; let xShapeY = ${isChannelLast ? getElementAt("uniforms.x_shape", 1, x.rank) : getElementAt("uniforms.x_shape", 2, x.rank)}; let xShapeZ = ${isChannelLast ? getElementAt("uniforms.x_shape", 2, x.rank) : getElementAt("uniforms.x_shape", 3, x.rank)}; let xShapeW = ${isChannelLast ? getElementAt("uniforms.x_shape", 3, x.rank) : getElementAt("uniforms.x_shape", 4, x.rank)}; let xShapeU = ${isChannelLast ? getElementAt("uniforms.x_shape", 4, x.rank) : getElementAt("uniforms.x_shape", 1, x.rank)}; let inputDepthNearestVec4 = (xShapeU / 4) * 4; let inputDepthVec4Remainder = xShapeU % 4; var value = 0.0; for (var wF = 0u; wF < uniforms.filter_dims[0]; wF++) { let xF = xFCorner + wF * uniforms.dilations[0]; if (xF < 0 || xF >= xShapeY) { continue; } for (var wR = 0u; wR < uniforms.filter_dims[1]; wR++) { let xR = xRCorner + wR * uniforms.dilations[1]; if (xR < 0 || xR >= xShapeZ) { continue; } for (var wC = 0u; wC < uniforms.filter_dims[2]; wC++) { let xC = xCCorner + wC * uniforms.dilations[2]; if (xC < 0 || xC >= xShapeW) { continue; } for (var d1 = 0u; d1 < inputDepthNearestVec4; d1 += 4) { ${isChannelLast ? `let xValues = vec4( getX(batch, xF, xR, xC, d1), getX(batch, xF, xR, xC, d1 + 1), getX(batch, xF, xR, xC, d1 + 2), getX(batch, xF, xR, xC, d1 + 3)); ` : `let xValues = vec4( getX(batch, d1, xF, xR, xC), getX(batch, d1 + 1, xF, xR, xC), getX(batch, d1 + 2, xF, xR, xC), getX(batch, d1 + 3, xF, xR, xC)); `} let wValues = vec4( getW(d2, d1, wF, wR, wC), getW(d2, d1 + 1, wF, wR, wC), getW(d2, d1 + 2, wF, wR, wC), getW(d2, d1 + 3, wF, wR, wC)); value += dot(xValues, wValues); } if (inputDepthVec4Remainder == 1) { ${isChannelLast ? `value += getX(batch, xF, xR, xC, inputDepthNearestVec4) * getW(d2, inputDepthNearestVec4, wF, wR, wC);` : `value += getX(batch, inputDepthNearestVec4, xF, xR, xC) * getW(d2, inputDepthNearestVec4, wF, wR, wC);`} } else if (inputDepthVec4Remainder == 2) { ${isChannelLast ? `let xValues = vec2( getX(batch, xF, xR, xC, inputDepthNearestVec4), getX(batch, xF, xR, xC, inputDepthNearestVec4 + 1)); ` : `let xValues = vec2( getX(batch, inputDepthNearestVec4, xF, xR, xC), getX(batch, inputDepthNearestVec4 + 1, xF, xR, xC)); `} let wValues = vec2( getW(d2, inputDepthNearestVec4, wF, wR, wC), getW(d2, inputDepthNearestVec4 + 1, wF, wR, wC)); value += dot(xValues, wValues); } else if (inputDepthVec4Remainder == 3) { ${isChannelLast ? `let xValues = vec3( getX(batch, xF, xR, xC, inputDepthNearestVec4), getX(batch, xF, xR, xC, inputDepthNearestVec4 + 1), getX(batch, xF, xR, xC, inputDepthNearestVec4 + 2)); ` : `let xValues = vec3( getX(batch, inputDepthNearestVec4, xF, xR, xC), getX(batch, inputDepthNearestVec4 + 1, xF, xR, xC), getX(batch, inputDepthNearestVec4 + 2, xF, xR, xC)); `} let wValues = vec3( getW(d2, inputDepthNearestVec4, wF, wR, wC), getW(d2, inputDepthNearestVec4 + 1, wF, wR, wC), getW(d2, inputDepthNearestVec4 + 2, wF, wR, wC)); value += dot(xValues, wValues); } } } } ${hasBias ? "value = value + getBiasByOutputCoords(coords)" : ""}; ${applyActivation} result[global_idx] = f32(value); }`; }; return { name: "Conv3DNaive", shaderCache: { hint: `${attributes.cacheKey};${isChannelLast};${innerElementSize};${hasBias}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, programUniforms }), getShaderSource }; }; } }); // web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts var createGroupedConvProgramInfo, createGroupedConvVectorizeProgramInfo; var init_conv_grouped = __esm({ "web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); init_fuse_utils(); createGroupedConvProgramInfo = (inputs, attributes, outputShape, squeezeOutputShapeFunction) => { const hasBias = inputs.length > 2; const processBias = hasBias ? "value += b[output_channel];" : ""; const xShape = inputs[0].dims; const wShape = inputs[1].dims; const isChannelLast = attributes.format === "NHWC"; const outputChannels = isChannelLast ? outputShape[3] : outputShape[1]; const outputChannelsPerGroup = outputChannels / attributes.group; const components = isChannelLast && outputChannelsPerGroup >= 4 ? getMaxComponents(outputChannels) : 1; const outputSize = ShapeUtil.size(outputShape) / components; const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: attributes.dilations }, { type: 12 /* uint32 */, data: [attributes.strides[0], attributes.strides[1]] }, { type: 12 /* uint32 */, data: [attributes.pads[0], attributes.pads[1]] }, { type: 12 /* uint32 */, data: outputChannelsPerGroup } ]; appendActivationUniformsData(attributes, programUniforms); programUniforms.push( ...createTensorShapeVariables(xShape, [wShape[0], wShape[1], wShape[2], wShape[3] / components]) ); const inputDependencies = hasBias ? ["rank", "rank", "rank"] : ["rank", "rank"]; programUniforms.push( ...createTensorShapeVariables([outputShape[0], outputShape[1], outputShape[2], outputShape[3] / components]) ); const getShaderSource = (shaderHelper) => { const output = outputVariable("output", inputs[0].dataType, outputShape.length, components); const baseType = tensorTypeToWsglStorageType(output.type.tensor); const applyActivation = getActivationSnippet(attributes, output.type.value, baseType); const x = inputVariable("x", inputs[0].dataType, xShape.length); const w = inputVariable("w", inputs[1].dataType, wShape.length, components); const inputVars = [x, w]; if (hasBias) { inputVars.push(inputVariable("b", inputs[2].dataType, inputs[2].dims, components)); } const uniforms = [ { name: "output_size", type: "u32" }, { name: "dilations", type: "u32", length: attributes.dilations.length }, { name: "strides", type: "u32", length: 2 }, { name: "pads", type: "u32", length: 2 }, { name: "output_channels_per_group", type: "u32" } ]; appendActivationUniforms(attributes, uniforms); const calculateResult = isChannelLast ? ` for (var wHeight: u32 = 0u; wHeight < uniforms.w_shape[0]; wHeight++) { let xHeight = xRCCorner.x + wHeight * uniforms.dilations[0]; if (xHeight < 0u || xHeight >= uniforms.x_shape[1]) { continue; } for (var wWidth: u32 = 0u; wWidth < uniforms.w_shape[1]; wWidth++) { let xWidth = xRCCorner.y + wWidth * uniforms.dilations[1]; if (xWidth < 0u || xWidth >= uniforms.x_shape[2]) { continue; } for (var wInChannel: u32 = 0u; wInChannel < uniforms.w_shape[2]; wInChannel++) { let input_channel = in_channel_offset + wInChannel; let xVal = ${x.get("batch", "xHeight", "xWidth", "input_channel")}; let wVal = ${w.get("wHeight", "wWidth", "wInChannel", "output_channel")}; value += xVal * wVal; } } } ` : ` for (var wInChannel: u32 = 0u; wInChannel < uniforms.w_shape[1]; wInChannel++) { let input_channel = in_channel_offset + wInChannel; for (var wHeight: u32 = 0u; wHeight < uniforms.w_shape[2]; wHeight++) { let xHeight = xRCCorner.x + wHeight * uniforms.dilations[0]; if (xHeight < 0u || xHeight >= uniforms.x_shape[2]) { continue; } for (var wWidth: u32 = 0u; wWidth < uniforms.w_shape[3]; wWidth++) { let xWidth = xRCCorner.y + wWidth * uniforms.dilations[1]; if (xWidth < 0u || xWidth >= uniforms.x_shape[3]) { continue; } let xVal = ${x.get("batch", "input_channel", "xHeight", "xWidth")}; let wVal = ${w.get("output_channel", "wInChannel", "wHeight", "wWidth")}; value += xVal * wVal; } } } `; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let outputIndices = ${output.offsetToIndices("global_idx")}; let batch: u32 = outputIndices[0]; let output_channel: u32 = outputIndices[${isChannelLast ? 3 : 1}]; let xRCCorner: vec2 = vec2(outputIndices[${isChannelLast ? 1 : 2}], outputIndices[${isChannelLast ? 2 : 3}]) * uniforms.strides - uniforms.pads; let group_id: u32 = output_channel * ${components} / uniforms.output_channels_per_group; var in_channel_offset = group_id * uniforms.w_shape[${isChannelLast ? 2 : 1}]; var value: ${output.type.value} = ${output.type.value}(0); ${calculateResult} ${processBias} ${applyActivation} ${output.setByOffset("global_idx", "value")} }`; }; return { name: "GroupedConv", shaderCache: { hint: `${attributes.cacheKey}_${components}`, inputDependencies }, getRunData: () => ({ outputs: [ { dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, dataType: inputs[0].dataType } ], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; createGroupedConvVectorizeProgramInfo = (inputs, attributes, outputShape, squeezeOutputShapeFunction) => { const hasBias = inputs.length > 2; const components = getMaxComponents(outputShape[3]); const outputNumber = getMaxComponents(outputShape[2]); const outputSize = ShapeUtil.size(outputShape) / components / outputNumber; const xShape = [inputs[0].dims[0], inputs[0].dims[1], inputs[0].dims[2], inputs[0].dims[3] / components]; const wShape = [inputs[1].dims[0], inputs[1].dims[1], inputs[1].dims[2], inputs[1].dims[3] / components]; const outputShapeInShader = [outputShape[0], outputShape[1], outputShape[2], outputShape[3] / components]; const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 6 /* int32 */, data: [attributes.strides[0], attributes.strides[1]] }, { type: 6 /* int32 */, data: [attributes.pads[0], attributes.pads[1]] } ]; appendActivationUniformsData(attributes, programUniforms); programUniforms.push(...createTensorShapeVariables(xShape, wShape, outputShapeInShader)); const xNumber = (outputNumber - 1) * attributes.strides[1] + wShape[1]; const getShaderSource = (shaderHelper) => { const output = outputVariable("output", inputs[0].dataType, outputShapeInShader.length, components); const baseType = tensorTypeToWsglStorageType(output.type.tensor); const applyActivation = getActivationSnippet(attributes, output.type.value, baseType); const x = inputVariable("x", inputs[0].dataType, xShape.length, components); const w = inputVariable("w", inputs[1].dataType, wShape.length, components); const inputVars = [x, w]; if (hasBias) { inputVars.push(inputVariable("b", inputs[2].dataType, inputs[2].dims, components)); } const processBias = hasBias ? "value += b[output_channel];" : ""; const uniforms = [ { name: "output_size", type: "u32" }, { name: "strides", type: "i32", length: 2 }, { name: "pads", type: "i32", length: 2 } ]; appendActivationUniforms(attributes, uniforms); return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let width0 = uniforms.output_shape[3]; let output_channel = global_idx % width0; var index1 = global_idx / width0; let width1 = uniforms.output_shape[2] / ${outputNumber}u; let col = (index1 % width1) * ${outputNumber}u; index1 = index1 / width1; let row = index1 % uniforms.output_shape[1]; let batch = index1 / uniforms.output_shape[1]; let x_corner = vec2(i32(row), i32(col)) * uniforms.strides - uniforms.pads; var x_vals: array<${x.type.value}, ${xNumber}>; var values: array<${output.type.value}, ${outputNumber}>; let input_channel = output_channel; // Use constant instead of uniform can give better performance for w's height/width. for (var w_height: u32 = 0u; w_height < ${wShape[0]}; w_height++) { let x_height = x_corner.x + i32(w_height); if (x_height >= 0 && u32(x_height) < uniforms.x_shape[1]) { for (var i = 0; i < ${xNumber}; i++) { let x_width = x_corner.y + i; if (x_width >= 0 && u32(x_width) < uniforms.x_shape[2]) { x_vals[i] = ${x.get("batch", "u32(x_height)", "u32(x_width)", "input_channel")}; } else { x_vals[i] = ${x.type.value}(0); } } for (var w_width: u32 = 0u; w_width < ${wShape[1]}; w_width++) { let w_val = ${w.get("w_height", "w_width", "0", "output_channel")}; for (var i = 0u; i < ${outputNumber}u; i++) { values[i] = fma(x_vals[i * u32(uniforms.strides[1]) + w_width], w_val, values[i]); } } } } for (var i = 0u; i < ${outputNumber}u; i++) { var value = values[i]; ${processBias} ${applyActivation} ${output.set("batch", "row", "col + i", "output_channel", "value")}; } }`; }; return { name: "GroupedConv-Vectorize", shaderCache: { hint: `${attributes.cacheKey};${components};${outputNumber};${xNumber};${wShape[0]};${wShape[1]}`, inputDependencies: hasBias ? ["rank", "rank", "type"] : ["rank", "rank"] }, getRunData: () => ({ outputs: [ { dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, dataType: inputs[0].dataType } ], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; } }); // web/lib/wasm/jsep/webgpu/ops/conv.ts var calculateOutputShape, weightTransposeAttribute, validateInputs8, getAdjustedConvAttributes, parseConvAttributes, conv2d, conv1d, conv3d, conv; var init_conv = __esm({ "web/lib/wasm/jsep/webgpu/ops/conv.ts"() { "use strict"; init_util(); init_conv2d_mm_webgpu(); init_conv3d_naive_webgpu(); init_matmul_packed_webgpu(); init_conv_grouped(); init_fuse_utils(); init_matmul_shaders(); init_transpose(); calculateOutputShape = (inputShape, kernelShape, dilations, adjustPads, strides, isChannelLast) => { const batchSize = inputShape[0]; const inputSpatialShape = inputShape.slice(isChannelLast ? 1 : 2, isChannelLast ? 3 : 4); const spatialRank = inputSpatialShape.length; const outChannels = kernelShape[0]; const kernelSpatialShape = kernelShape.slice(2); const dilatedKernelShape = kernelSpatialShape.map((v, i) => v + (v - 1) * (dilations[i] - 1)); const inputSpatialShapeWithPad = inputSpatialShape.map((v, i) => v + adjustPads[i] + adjustPads[i + spatialRank]); const outputShape = inputSpatialShapeWithPad.map( (v, i) => Math.floor((v - dilatedKernelShape[i] + strides[i]) / strides[i]) ); outputShape.splice(0, 0, batchSize); outputShape.splice(isChannelLast ? 3 : 1, 0, outChannels); return outputShape; }; weightTransposeAttribute = [2, 3, 1, 0]; validateInputs8 = (inputs, attributes) => { if (!inputs || inputs.length !== 2 && inputs.length !== 3) { throw new Error("Conv requires 2 or 3 inputs"); } if (inputs[0].dims.length > 5) { throw new Error("greater than 5D is not supported"); } if (inputs[0].dims.length !== inputs[1].dims.length) { throw new Error("filter does not have same dimension as input"); } const dataChannel = inputs[0].dims[attributes.format === "NHWC" ? inputs[0].dims.length - 1 : 1]; const filterInChannel = inputs[1].dims[1] * attributes.group; if (dataChannel !== filterInChannel) { throw new Error("FILTER_IN_CHANNEL should be equal to DATA_CHANNEL"); } if (inputs.length === 3 && (inputs[2].dims.length !== 1 || inputs[1].dims[0] !== inputs[2].dims[0])) { throw new Error("invalid bias"); } const spatialRank = inputs[0].dims.length - 2; if (attributes.dilations.length !== spatialRank) { throw new Error(`dilations should be ${spatialRank}D`); } if (attributes.strides.length !== spatialRank) { throw new Error(`strides should be ${spatialRank}D`); } if (attributes.pads.length !== spatialRank * 2) { throw new Error(`pads should be ${spatialRank * 2}D`); } if (attributes.kernelShape.length !== 0 && attributes.kernelShape.length !== inputs[1].dims.length - 2) { throw new Error("invalid kernel shape"); } }; getAdjustedConvAttributes = (attributes, inputs) => { const kernelShape = attributes.kernelShape.slice(); if (kernelShape.length < inputs[1].dims.length - 2) { kernelShape.push(...Array(inputs[1].dims.length - 2 - kernelShape.length).fill(0)); } for (let i = 2; i < inputs[1].dims.length; ++i) { if (kernelShape[i - 2] === 0) { kernelShape[i - 2] = inputs[1].dims[i]; } } const pads = attributes.pads.slice(); PoolConvUtil.adjustPadsBasedOnAutoPad( inputs[0].dims, attributes.strides, attributes.dilations, kernelShape, pads, attributes.format === "NHWC", attributes.autoPad ); const newAttributes = Object.assign({}, attributes); Object.assign(newAttributes, { kernelShape, pads }); return newAttributes; }; parseConvAttributes = (attributes) => { const activationAttributes = parseInternalActivationAttributes(attributes); const format = attributes.format; const autoPad = ["NOTSET", "VALID", "SAME_UPPER", "SAME_LOWER"][attributes.auto_pad]; const dilations = attributes.dilations; const group = attributes.group; const kernelShape = attributes.kernel_shape; const pads = attributes.pads; const strides = attributes.strides; const wIsConst = attributes.w_is_const(); return { autoPad, format, dilations, group, kernelShape, pads, strides, wIsConst, ...activationAttributes, cacheKey: `${attributes.format};${activationAttributes.activation};` }; }; conv2d = (context, inputs, attributes, squeezeOutputShapeFunction) => { const isChannelsLast = attributes.format === "NHWC"; const outputShape = calculateOutputShape( inputs[0].dims, inputs[1].dims, attributes.dilations, attributes.pads, attributes.strides, isChannelsLast ); if (attributes.group !== 1) { const convInputs2 = [inputs[0]]; if (isChannelsLast) { const transposedWeight2 = context.kernelCustomData.wT ?? context.compute(createTransposeProgramInfo(inputs[1], weightTransposeAttribute), { inputs: [1], outputs: [attributes.wIsConst ? -2 : -1] })[0]; if (attributes.wIsConst && !context.kernelCustomData.wT) { context.kernelCustomData.wT = transposedWeight2; } convInputs2.push(transposedWeight2); } else { convInputs2.push(inputs[1]); } if (inputs.length === 3) { convInputs2.push(inputs[2]); } const enableGroupedConvVectorize = !context.adapterInfo.isArchitecture("ampere"); if (enableGroupedConvVectorize && isChannelsLast && inputs[1].dims[0] === attributes.group && inputs[1].dims[1] === 1 && attributes.dilations[0] === 1 && attributes.dilations[1] === 1) { context.compute( createGroupedConvVectorizeProgramInfo(convInputs2, attributes, outputShape, squeezeOutputShapeFunction), { inputs: convInputs2 } ); } else { context.compute(createGroupedConvProgramInfo(convInputs2, attributes, outputShape, squeezeOutputShapeFunction), { inputs: convInputs2 }); } return; } const hasBias = inputs.length === 3; const inputHeight = inputs[0].dims[isChannelsLast ? 1 : 2]; const inputWidth = inputs[0].dims[isChannelsLast ? 2 : 3]; const inputChannels = inputs[0].dims[isChannelsLast ? 3 : 1]; const weightHeight = inputs[1].dims[2]; const weightWidth = inputs[1].dims[3]; const outHeight = outputShape[isChannelsLast ? 1 : 2]; const outWidth = outputShape[isChannelsLast ? 2 : 3]; const outChannels = outputShape[isChannelsLast ? 3 : 1]; const sameSize = isChannelsLast && weightHeight === inputHeight && weightWidth === inputWidth && attributes.pads[0] === 0 && attributes.pads[1] === 0; if (sameSize || weightHeight === 1 && weightWidth === 1 && attributes.dilations[0] === 1 && attributes.dilations[1] === 1 && attributes.strides[0] === 1 && attributes.strides[1] === 1 && attributes.pads[0] === 0 && attributes.pads[1] === 0) { const batch = outputShape[0]; let xReshaped, wReshaped, matmulOutputShape; const matmulInputs = []; if (isChannelsLast) { const transposedWeight2 = context.kernelCustomData.wT ?? context.compute(createTransposeProgramInfo(inputs[1], weightTransposeAttribute), { inputs: [1], outputs: [attributes.wIsConst ? -2 : -1] })[0]; if (attributes.wIsConst && !context.kernelCustomData.wT) { context.kernelCustomData.wT = transposedWeight2; } if (sameSize) { const sharedDim = inputHeight * inputWidth * inputChannels; xReshaped = inputs[0].reshape([1, batch, sharedDim]); wReshaped = transposedWeight2.reshape([1, sharedDim, outChannels]); matmulOutputShape = [1, batch, outChannels]; } else { xReshaped = inputs[0].reshape([batch, inputHeight * inputWidth, inputChannels]); wReshaped = transposedWeight2.reshape([1, inputChannels, outChannels]); matmulOutputShape = [batch, outHeight * outWidth, outChannels]; } matmulInputs.push(xReshaped); matmulInputs.push(wReshaped); } else { xReshaped = inputs[0].reshape([batch, inputChannels, inputHeight * inputWidth]); wReshaped = inputs[1].reshape([1, outChannels, inputChannels]); matmulOutputShape = [batch, outChannels, outHeight * outWidth]; matmulInputs.push(wReshaped); matmulInputs.push(xReshaped); } if (hasBias) { matmulInputs.push(inputs[2]); } const N = matmulOutputShape[2]; const K = matmulInputs[0].dims[matmulInputs[0].dims.length - 1]; if (N < 8 && K < 8) { context.compute( createNaiveMatmulProgramInfo( matmulInputs, attributes, outputShape, matmulOutputShape, isChannelsLast, squeezeOutputShapeFunction ), { inputs: matmulInputs } ); } else { context.compute( createMatmulProgramInfo( matmulInputs, attributes, outputShape, matmulOutputShape, isChannelsLast, squeezeOutputShapeFunction ), { inputs: matmulInputs } ); } return; } const sequentialAccessByThreads = ( /* backend.adapterInfo.isIntel() */ true ); const transposedWeight = context.kernelCustomData.wT ?? context.compute(createTransposeProgramInfo(inputs[1], weightTransposeAttribute), { inputs: [1], outputs: [attributes.wIsConst ? -2 : -1] })[0]; if (attributes.wIsConst && !context.kernelCustomData.wT) { context.kernelCustomData.wT = transposedWeight; } const convInputs = [inputs[0], transposedWeight]; if (hasBias) { convInputs.push(inputs[2]); } const dimAOuter = isChannelsLast ? outHeight * outWidth : outChannels; const dimBOuter = isChannelsLast ? outChannels : outHeight * outWidth; const dimInner = weightHeight * weightWidth * inputChannels; context.compute( createConv2DMatMulProgramInfo( convInputs, attributes, outputShape, dimAOuter, dimBOuter, dimInner, hasBias, sequentialAccessByThreads, squeezeOutputShapeFunction ), { inputs: convInputs } ); }; conv1d = (context, attributes) => { const isChannelLast = attributes.format === "NHWC"; const inputs = [ context.inputs[0].reshape( isChannelLast ? ( // [N, W, C] -> [N, H=1, W, C] [context.inputs[0].dims[0], 1, context.inputs[0].dims[1], context.inputs[0].dims[2]] ) : ( // [N, C, W] -> [N, C, H=1, W] [context.inputs[0].dims[0], context.inputs[0].dims[1], 1, context.inputs[0].dims[2]] ) ), //[FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kW] -> [FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kH=1, kW] context.inputs[1].reshape([context.inputs[1].dims[0], context.inputs[1].dims[1], 1, context.inputs[1].dims[2]]) ]; if (context.inputs.length === 3) { inputs.push(context.inputs[2]); } const pads = [0, attributes.pads[0], 0, attributes.pads[1]]; const strides = [1].concat(attributes.strides); const dilations = [1].concat(attributes.dilations); const kernelShape = [1].concat(attributes.kernelShape); const adjustedAttributes = getAdjustedConvAttributes( { ...attributes, pads, strides, dilations, kernelShape }, inputs ); conv2d( context, inputs, adjustedAttributes, (outputShape) => isChannelLast ? [outputShape[0], outputShape[2], outputShape[3]] : [outputShape[0], outputShape[1], outputShape[3]] ); }; conv3d = (context, inputs, attributes) => { const format = attributes.format === "NHWC" ? "channelsLast" : "channelsFirst"; const adjustedAttributes = getAdjustedConvAttributes(attributes, inputs); const pads = attributes.autoPad === "NOTSET" ? attributes.pads : attributes.autoPad; const convInfo = computeConv3DInfo( inputs[0].dims, inputs[1].dims, attributes.strides, attributes.dilations, pads, false, format ); context.compute( createConv3DNaiveProgramInfo( inputs, adjustedAttributes, convInfo.outShape, [convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth], [convInfo.padInfo.front, convInfo.padInfo.top, convInfo.padInfo.left], format ) ); }; conv = (context, attributes) => { validateInputs8(context.inputs, attributes); if (context.inputs[0].dims.length === 3) { conv1d(context, attributes); } else if (context.inputs[0].dims.length === 5) { conv3d(context, context.inputs, attributes); } else { const adjustedAttributes = getAdjustedConvAttributes(attributes, context.inputs); conv2d(context, context.inputs, adjustedAttributes); } }; } }); // web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts var createConvTranspose2DProgramInfo; var init_conv_backprop_webgpu = __esm({ "web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts"() { "use strict"; init_wasm_common(); init_log(); init_util(); init_common(); createConvTranspose2DProgramInfo = (inputs, attributes, squeezeOutputShapeFunction) => { const hasBias = inputs.length > 2; const outputShape = attributes.outputShape; const isChannelsLast = attributes.format === "NHWC"; const group = attributes.group; const wShape = inputs[1].dims; const inputChannelsPerGroup = wShape[2] / group; const outputChannelsPerGroup = wShape[3]; const aComponents = isChannelsLast ? getMaxComponents(inputChannelsPerGroup) : 1; const packInputAs4 = isChannelsLast && outputChannelsPerGroup === 1 && inputChannelsPerGroup >= 4; const inputChannelsPerGroupInt = packInputAs4 ? Math.floor(inputChannelsPerGroup / 4) * 4 : Math.floor(inputChannelsPerGroup / aComponents) * aComponents; const inputChannelsRemainder = inputChannelsPerGroup - inputChannelsPerGroupInt; const components = isChannelsLast ? getMaxComponents(outputChannelsPerGroup) : 1; const bComponents = isChannelsLast ? outputChannelsPerGroup === 1 ? aComponents : components : 1; const outputSize = ShapeUtil.size(outputShape) / components; const dispatch = [Math.ceil(outputSize / 64), 1, 1]; LOG_DEBUG("verbose", () => `[conv2d_backprop_webgpu] dispatch = ${dispatch}`); const inputDependencies = ["rank", "rank"]; const strides = [attributes.strides[0], attributes.strides[1]]; const filterDims = [attributes.kernelShape[isChannelsLast ? 1 : 2], attributes.kernelShape[isChannelsLast ? 2 : 3]]; const dilations = [attributes.dilations[0], attributes.dilations[1]]; const effectiveFilterDims = [ filterDims[0] + (attributes.dilations[0] <= 1 ? 0 : (attributes.kernelShape[isChannelsLast ? 1 : 2] - 1) * (attributes.dilations[0] - 1)), filterDims[1] + (attributes.dilations[1] <= 1 ? 0 : (attributes.kernelShape[isChannelsLast ? 2 : 3] - 1) * (attributes.dilations[1] - 1)) ]; const pads = [ effectiveFilterDims[0] - 1 - Math.floor((attributes.pads[0] + attributes.pads[2]) / 2), effectiveFilterDims[1] - 1 - Math.floor((attributes.pads[1] + attributes.pads[3]) / 2) ]; const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: strides }, { type: 12 /* uint32 */, data: filterDims }, { type: 12 /* uint32 */, data: dilations }, { type: 12 /* uint32 */, data: effectiveFilterDims }, { type: 6 /* int32 */, data: pads }, { type: 12 /* uint32 */, data: inputChannelsPerGroupInt }, { type: 12 /* uint32 */, data: inputChannelsPerGroup }, { type: 12 /* uint32 */, data: outputChannelsPerGroup }, ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims) ]; if (hasBias) { programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); inputDependencies.push("rank"); } programUniforms.push(...createTensorShapeVariables(outputShape)); const getShaderSource = (shaderHelper) => { const uniforms = [ { name: "output_size", type: "u32" }, { name: "strides", type: "u32", length: strides.length }, { name: "filter_dims", type: "u32", length: filterDims.length }, { name: "dilations", type: "u32", length: filterDims.length }, { name: "effective_filter_dims", type: "u32", length: effectiveFilterDims.length }, { name: "pads", type: "i32", length: pads.length }, { name: "input_channels_per_group_int", type: "u32" }, { name: "input_channels_per_group", type: "u32" }, { name: "output_channels_per_group", type: "u32" } ]; const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); const rowDim = isChannelsLast ? 1 : 2; const colDim = isChannelsLast ? 2 : 3; const channelDim = isChannelsLast ? 3 : 1; const w = inputVariable("W", inputs[1].dataType, inputs[1].dims.length, bComponents); const dy = inputVariable("Dy", inputs[0].dataType, inputs[0].dims.length, aComponents); const inputVariables = [dy, w]; if (hasBias) { inputVariables.push(inputVariable("bias", inputs[2].dataType, [outputShape[channelDim]].length, components)); } const output = outputVariable("result", inputs[0].dataType, outputShape.length, components); const calculateResult = () => { let calcStr = ""; if (packInputAs4) { if (aComponents === 4) { calcStr += ` let xValue = ${dy.getByOffset("x_offset")}; let wValue = ${w.getByOffset("w_offset")}; dotProd = dotProd + dot(xValue, wValue); x_offset += 1u; w_offset += 1u;`; } else if (aComponents === 2) { calcStr += ` dotProd = dotProd + dot(vec4<${dataType}>(${dy.getByOffset("x_offset")}, ${dy.getByOffset("x_offset + 1u")}), vec4<${dataType}>(${w.getByOffset("w_offset")}, ${w.getByOffset("w_offset + 1u")})); x_offset += 2u; w_offset += 2u;`; } else if (aComponents === 1) { calcStr += ` dotProd = dotProd + dot(vec4<${dataType}>(${dy.getByOffset("x_offset")}, ${dy.getByOffset("x_offset + 1u")}, ${dy.getByOffset("x_offset + 2u")}, ${dy.getByOffset("x_offset + 3u")}), vec4<${dataType}>(${w.getByOffset("w_offset")}, ${w.getByOffset("w_offset + 1u")}, ${w.getByOffset("w_offset + 2u")}, ${w.getByOffset("w_offset + 3u")})); x_offset += 4u; w_offset += 4u;`; } } else { calcStr += ` let xValue = ${isChannelsLast ? dy.getByOffset( `${dy.indicesToOffset(`${dy.type.indices}(batch, idyR, idyC, inputChannel)`)} / ${aComponents}` ) : dy.get("batch", "inputChannel", "idyR", "idyC")}; `; if (aComponents === 1) { calcStr += ` let w_offset = ${w.indicesToOffset(`${w.type.indices}(u32(wRPerm), u32(wCPerm), inputChannel, wOutChannel)`)}; let wValue = ${w.getByOffset(`w_offset / ${bComponents}`)}; dotProd = dotProd + xValue * wValue;`; } else { for (let c = 0; c < aComponents; c++) { calcStr += ` let wValue${c} = ${w.getByOffset(`${w.indicesToOffset(`${w.type.indices}(u32(wRPerm), u32(wCPerm), inputChannel + ${c}, wOutChannel)`)} / ${bComponents}`)}; dotProd = dotProd + xValue[${c}] * wValue${c};`; } } } return calcStr; }; const calculateRemainder = () => { if (inputChannelsRemainder === 0) { return ""; } if (!packInputAs4) { throw new Error(`packInputAs4 ${packInputAs4} is not true.`); } let calcStr = ""; if (aComponents === 1) { calcStr += "dotProd = dotProd"; for (let i = 0; i < inputChannelsRemainder; i++) { calcStr += ` + ${dy.getByOffset(`x_offset + ${i}`)} * ${w.getByOffset(`w_offset + ${i}`)}`; } calcStr += ";"; } else if (aComponents === 2) { if (inputChannelsRemainder !== 2) { throw new Error(`Invalid inputChannelsRemainder ${inputChannelsRemainder}.`); } calcStr += ` let xValue = ${dy.getByOffset("x_offset")}; let wValue = ${w.getByOffset("w_offset")}; dotProd = dotProd + dot(xValue, wValue);`; } return calcStr; }; const codeSnippet = ` let outputIndices = ${output.offsetToIndices(`global_idx * ${components}`)}; let batch = ${output.indicesGet("outputIndices", 0)}; let d1 = ${output.indicesGet("outputIndices", channelDim)}; let r = ${output.indicesGet("outputIndices", rowDim)}; let c = ${output.indicesGet("outputIndices", colDim)}; let dyCorner = vec2(i32(r), i32(c)) - uniforms.pads; let dyRCorner = dyCorner.x; let dyCCorner = dyCorner.y; let groupId = d1 / uniforms.output_channels_per_group; let wOutChannel = d1 - groupId * uniforms.output_channels_per_group; // Convolve dy(?, ?, d2) with w(:, :, d1, d2) to compute dx(xR, xC, d1). // ? = to be determined. : = across all values in that axis. var dotProd = ${output.type.value}(0.0); var wR: u32 = 0; if (uniforms.dilations.x == 1) { // Minimum wR >= 0 that satisfies (dyRCorner + wR) % (uniforms.strides.x) == 0 wR = u32(((dyRCorner + i32(uniforms.strides.x) - 1) / i32(uniforms.strides.x)) * i32(uniforms.strides.x) - dyRCorner); } for (; wR < uniforms.effective_filter_dims.x; wR = wR + 1) { if (wR % uniforms.dilations.x != 0) { continue; } let dyR = (${dataType}(dyRCorner) + ${dataType}(wR)) / ${dataType}(uniforms.strides[0]); let wRPerm = uniforms.filter_dims.x - 1 - wR / uniforms.dilations.x; if (dyR < 0.0 || dyR >= ${dataType}(uniforms.Dy_shape[${rowDim}]) || fract(dyR) > 0.0 || wRPerm < 0) { continue; } let idyR: u32 = u32(dyR); var wC: u32 = 0; if (uniforms.dilations.y == 1) { // Minimum wC >= 0 that satisfies (dyCCorner + wC) % (uniforms.strides.y) == 0 wC = u32(((dyCCorner + i32(uniforms.strides.y) - 1) / i32(uniforms.strides.y)) * i32(uniforms.strides.y) - dyCCorner); } for (; wC < uniforms.effective_filter_dims.y; wC = wC + 1) { if (wC % uniforms.dilations.y != 0) { continue; } let dyC = (${dataType}(dyCCorner) + ${dataType}(wC)) / ${dataType}(uniforms.strides.y); let wCPerm = uniforms.filter_dims.y - 1 - wC / uniforms.dilations.y; if (dyC < 0.0 || dyC >= ${dataType}(uniforms.Dy_shape[${colDim}]) || fract(dyC) > 0.0 || wCPerm < 0) { continue; } let idyC: u32 = u32(dyC); var inputChannel = groupId * uniforms.input_channels_per_group; ${packInputAs4 ? ` var x_offset = ${dy.indicesToOffset(`${dy.type.indices}(batch, idyR, idyC, inputChannel)`)} / ${aComponents}; var w_offset = ${w.indicesToOffset(`${w.type.indices}(wRPerm, wCPerm, inputChannel, wOutChannel)`)} / ${bComponents}; ` : ""} for (var d2: u32 = 0; d2 < uniforms.input_channels_per_group_int; d2 = d2 + ${packInputAs4 ? 4 : aComponents}) { ${calculateResult()} inputChannel = inputChannel + ${packInputAs4 ? 4 : aComponents}; } ${calculateRemainder()} wC = wC + uniforms.strides.y - 1; } wR = wR + uniforms.strides[0] - 1; } let value = dotProd${hasBias ? ` + bias[d1 / ${components}]` : ""}; ${output.setByOffset("global_idx", "value")}; `; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")}; ${codeSnippet}}`; }; return { name: "ConvTranspose2D", shaderCache: { hint: `${attributes.cacheKey};${aComponents}${bComponents}${components}${packInputAs4}${inputChannelsRemainder}`, inputDependencies }, getRunData: () => ({ dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, outputs: [ { dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, dataType: inputs[0].dataType } ], programUniforms }), getShaderSource }; }; } }); // web/lib/wasm/jsep/webgpu/ops/conv-transpose.ts var computeTotalPad, distributePadding, calculateOutputShapeAndPads, getAdjustedConvTransposeAttributes, parseConvTransposeAttributes, validateInputs9, convTranspose2d, convTranspose1d, convTranspose; var init_conv_transpose = __esm({ "web/lib/wasm/jsep/webgpu/ops/conv-transpose.ts"() { "use strict"; init_conv_backprop_webgpu(); init_fuse_utils(); init_transpose(); computeTotalPad = (inDim, stride, adj, kernel, dilation, outSize) => (inDim - 1) * stride + adj + (kernel - 1) * dilation + 1 - outSize; distributePadding = (totalPad, autoPad, pads, head, tail) => { const smallPad = Math.floor(totalPad / 2); if (autoPad === "SAME_UPPER") { pads[head] = smallPad; pads[tail] = totalPad - smallPad; } else if (autoPad === "SAME_LOWER") { pads[head] = totalPad - smallPad; pads[tail] = smallPad; } }; calculateOutputShapeAndPads = (inputShape, kernelShape, dilations, autoPad, group, pads, strides, isChannelLast, outputPadding, outputShape) => { const spatialRank = inputShape.length - 2; const updateOutputShape = outputShape.length === 0; if (outputPadding.length < spatialRank) { outputPadding.push(...Array(spatialRank - outputPadding.length).fill(0)); } const batchSize = inputShape[0]; const outChannels = kernelShape[isChannelLast ? 3 : 1] * group; for (let i = 0, j = inputShape.length - spatialRank - (isChannelLast ? 1 : 0); i < spatialRank; ++i, ++j) { const inSize = inputShape[j]; const outSize = updateOutputShape ? inSize * strides[i] : outputShape[i]; const totalPad = computeTotalPad(inSize, strides[i], pads[i], kernelShape[j], dilations[i], outSize); distributePadding(totalPad, autoPad, pads, i, i + spatialRank); if (updateOutputShape) { outputShape.push( strides[i] * (inSize - 1) + outputPadding[i] + (kernelShape[j] - 1) * dilations[i] + 1 - pads[i] - pads[i + spatialRank] ); } } outputShape.splice(0, 0, batchSize); outputShape.splice(isChannelLast ? 3 : 1, 0, outChannels); }; getAdjustedConvTransposeAttributes = (attributes, inputs) => { const kernelShape = attributes.kernelShape.slice(); if (attributes.kernelShape.length === 0 || attributes.kernelShape.reduce((a, b) => a * b, 1) === 0) { kernelShape.length = 0; for (let i = 2; i < inputs[1].dims.length; ++i) { kernelShape.push(inputs[1].dims[i]); } } const isChannelsLast = attributes.format === "NHWC"; kernelShape.splice(0, 0, inputs[1].dims[0]); kernelShape.splice(isChannelsLast ? 3 : 1, 0, inputs[1].dims[1]); const pads = attributes.pads.slice(); const outputShape = attributes.outputShape.slice(); const outputPadding = attributes.outputPadding.slice(); const inputShape = inputs[0].dims; let dilations = attributes.dilations.slice(); if (dilations.reduce((a, b) => a + b, 0) === 0) { const spatialRank = inputs[0].dims.length - 2; dilations = new Array(spatialRank).fill(1); } let strides = attributes.strides.slice(); if (strides.reduce((a, b) => a + b, 0) === 0) { const spatialRank = inputs[0].dims.length - 2; strides = new Array(spatialRank).fill(1); } calculateOutputShapeAndPads( inputShape, kernelShape, dilations, attributes.autoPad, attributes.group, pads, strides, isChannelsLast, outputPadding, outputShape ); const newAttributes = Object.assign({}, attributes); Object.assign(newAttributes, { kernelShape, pads, outputPadding, outputShape, dilations, strides }); return newAttributes; }; parseConvTransposeAttributes = (attributes) => { const activationAttributes = parseInternalActivationAttributes(attributes); const format = attributes.format; const autoPad = ["NOTSET", "VALID", "SAME_UPPER", "SAME_LOWER"][typeof attributes.autoPad == "undefined" ? 0 : attributes.autoPad]; const dilations = attributes.dilations; const group = attributes.group ?? 1; const kernelShape = attributes.kernelShape; const pads = attributes.pads; const strides = attributes.strides; const wIsConst = attributes.wIsConst(); const outputPadding = attributes.outputPadding; const outputShape = attributes.outputShape; return { autoPad, format, dilations, group, kernelShape, outputPadding, outputShape, pads, strides, wIsConst, ...activationAttributes, cacheKey: `${attributes.format};${activationAttributes.activation};` }; }; validateInputs9 = (inputs, attributes) => { if (!inputs || inputs.length !== 2 && inputs.length !== 3) { throw new Error("Conv requires 2 or 3 inputs"); } if (inputs[0].dims.length !== 4 && inputs[0].dims.length !== 3) { throw new Error("currently only support 2-dimensional conv"); } if (inputs[0].dims.length !== inputs[1].dims.length) { throw new Error("filter does not have same dimension as input"); } const dataChannel = inputs[0].dims[attributes.format === "NHWC" ? inputs[0].dims.length - 1 : 1]; const filterInChannel = inputs[1].dims[0]; if (dataChannel !== filterInChannel) { throw new Error("FILTER_IN_CHANNEL should be equal to DATA_CHANNEL"); } const featureMaps = inputs[1].dims[1] * attributes.group; if (inputs.length === 3 && (inputs[2].dims.length !== 1 || inputs[2].dims[0] !== featureMaps)) { throw new Error("invalid bias"); } const spatialRank = inputs[0].dims.length - 2; const dilationsSet = attributes.dilations.reduce((a, b) => a + b, 0) > 0; if (dilationsSet && attributes.dilations.length !== spatialRank) { throw new Error(`dilations should be ${spatialRank}D`); } const stridesSet = attributes.strides.reduce((a, b) => a + b, 0) > 0; if (stridesSet && attributes.strides.length !== spatialRank) { throw new Error(`strides should be ${spatialRank}D`); } const padsSet = attributes.pads.reduce((a, b) => a + b, 0) > 0; if (padsSet && attributes.pads.length !== spatialRank * 2) { throw new Error(`pads should be ${spatialRank * 2}D`); } if (attributes.outputPadding.length !== spatialRank && attributes.outputPadding.length !== 0) { throw new Error(`output_padding should be ${spatialRank}D`); } const kernelShapeSet = attributes.kernelShape.reduce((a, b) => a + b, 0) > 0; if (kernelShapeSet && attributes.kernelShape.length !== 0 && attributes.kernelShape.length !== inputs[1].dims.length - 2) { throw new Error("invalid kernel shape"); } if (attributes.outputShape.length !== 0 && attributes.outputShape.length !== inputs[0].dims.length - 2) { throw new Error("invalid output shape"); } }; convTranspose2d = (context, inputs, attributes, squeezeOutputShapeFunction) => { const transposedWeight = context.kernelCustomData.wT ?? context.compute(createTransposeProgramInfo(inputs[1], [2, 3, 0, 1]), { inputs: [1], outputs: [attributes.wIsConst ? -2 : -1] })[0]; if (attributes.wIsConst && !context.kernelCustomData.wT) { context.kernelCustomData.wT = transposedWeight; } const convTransposeInputs = [inputs[0], transposedWeight]; if (inputs.length === 3) { convTransposeInputs.push(inputs[2]); } context.compute(createConvTranspose2DProgramInfo(convTransposeInputs, attributes, squeezeOutputShapeFunction), { inputs: convTransposeInputs }); }; convTranspose1d = (context, attributes) => { const isChannelLast = attributes.format === "NHWC"; const inputs = [ context.inputs[0].reshape( isChannelLast ? ( // [N, W, C] -> [N, H=1, W, C] [context.inputs[0].dims[0], 1, context.inputs[0].dims[1], context.inputs[0].dims[2]] ) : ( // [N, C, W] -> [N, C, H=1, W] [context.inputs[0].dims[0], context.inputs[0].dims[1], 1, context.inputs[0].dims[2]] ) ), //[FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kW] -> [FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kH=1, kW] context.inputs[1].reshape([context.inputs[1].dims[0], context.inputs[1].dims[1], 1, context.inputs[1].dims[2]]) ]; if (context.inputs.length === 3) { inputs.push(context.inputs[2]); } let kernelShape = attributes.kernelShape; if (kernelShape.length === 0 || kernelShape[0] === 0) { kernelShape = [context.inputs[1].dims[2]]; } let dilations = attributes.dilations; if (dilations.length === 0 || dilations[0] === 0) { dilations = [1]; } let strides = attributes.strides; if (strides.length === 0 || strides[0] === 0) { strides = [1]; } let pads = attributes.pads; if (pads.length === 0) { pads = [0, 0]; } pads = [0, pads[0], 0, pads[1]]; strides = [1].concat(strides); dilations = [1].concat(dilations); kernelShape = [1].concat(kernelShape); let outputPadding = attributes.outputPadding; outputPadding = [0].concat(outputPadding); const adjustedAttributes = getAdjustedConvTransposeAttributes( { ...attributes, pads, strides, dilations, kernelShape, outputPadding }, inputs ); convTranspose2d( context, inputs, adjustedAttributes, (outputShape) => isChannelLast ? [outputShape[0], outputShape[2], outputShape[3]] : [outputShape[0], outputShape[1], outputShape[3]] ); }; convTranspose = (context, attributes) => { validateInputs9(context.inputs, attributes); if (context.inputs[0].dims.length === 3) { convTranspose1d(context, attributes); } else { const adjustedAttributes = getAdjustedConvTransposeAttributes(attributes, context.inputs); convTranspose2d(context, context.inputs, adjustedAttributes); } }; } }); // web/lib/wasm/jsep/webgpu/ops/cumsum.ts var createCumsumProgramInfo, cumsum, parseCumSumAttributes; var init_cumsum = __esm({ "web/lib/wasm/jsep/webgpu/ops/cumsum.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); createCumsumProgramInfo = (inputType, inputShape, axisInput, attributes) => { const outputSize = ShapeUtil.size(inputShape); const rank = inputShape.length; const input = inputVariable("input", inputType, rank); const output = outputVariable("output", inputType, rank); const axisValue = axisInput.dataType === 6 /* int32 */ ? axisInput.getInt32Array()[0] : Number(axisInput.getBigInt64Array()[0]); const axis = ShapeUtil.normalizeAxis(axisValue, rank); const getShaderSource = (shaderHelper) => { const index = ` i32(${input.indicesGet("inputIndices", "uniforms.axis")}) `; const max = getElementAt("uniforms.input_shape", "uniforms.axis", rank); const lowerLimit = attributes.reverse ? index + (attributes.exclusive ? " + 1" : "") : "0"; const upperLimit = attributes.reverse ? max : index + (attributes.exclusive ? "" : " + 1"); return ` ${shaderHelper.registerUniform("outputSize", "u32").registerUniform("axis", "u32").declareVariables(input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} var inputIndices = ${output.offsetToIndices("global_idx")}; var sum = ${output.type.value}(0); let first : i32 = ${lowerLimit}; let last : i32 = ${upperLimit}; for (var i : i32 = first; i < last; i++) { ${input.indicesSet("inputIndices", "uniforms.axis", "u32(i)")}; sum = sum + ${input.getByIndices("inputIndices")}; } ${output.setByOffset("global_idx", "sum")}; }`; }; return { name: "CumSum", shaderCache: { hint: attributes.cacheKey, inputDependencies: ["rank"] }, getRunData: () => ({ outputs: [{ dims: inputShape, dataType: inputType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms: [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: axis }, ...createTensorShapeVariables(inputShape, inputShape) ] }), getShaderSource }; }; cumsum = (context, attributes) => { const inputShape = context.inputs[0].dims; const inputType = context.inputs[0].dataType; const axis = context.inputs[1]; context.compute(createCumsumProgramInfo(inputType, inputShape, axis, attributes), { inputs: [0] }); }; parseCumSumAttributes = (attributes) => { const exclusive = attributes.exclusive === 1; const reverse = attributes.reverse === 1; return createAttributeWithCacheKey({ exclusive, reverse }); }; } }); // web/lib/wasm/jsep/webgpu/ops/depth-to-space.ts var validateInputs10, permFunctionBody2, createDepthToSpaceProgramInfo, depthToSpace, parseDepthToSpaceAttributes; var init_depth_to_space = __esm({ "web/lib/wasm/jsep/webgpu/ops/depth-to-space.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs10 = (inputs) => { if (!inputs || inputs.length !== 1) { throw new Error("DepthToSpace requires 1 input."); } if (inputs[0].dims.length !== 4) { throw new Error("DepthToSpace requires 4D input."); } }; permFunctionBody2 = (perm, rank, input, output) => { const reverseFunc = []; reverseFunc.push(`fn perm(i: ${output.type.indices}) -> ${input.type.indices} { var a: ${input.type.indices};`); for (let i = 0; i < rank; ++i) { reverseFunc.push(input.indicesSet("a", perm[i], `i[${i}]`)); } reverseFunc.push("return a;}"); return reverseFunc.join("\n"); }; createDepthToSpaceProgramInfo = (inputTensor, attributes) => { let n, h, w, c; let shape; let perm; const isChannelLast = attributes.format === "NHWC"; const blocksize = attributes.blocksize; const isDCRmode = attributes.mode === "DCR"; if (isChannelLast) { [n, h, w, c] = inputTensor.dims; shape = isDCRmode ? [n, h, w, blocksize, blocksize, c / blocksize ** 2] : [n, h, w, c / blocksize ** 2, blocksize, blocksize]; perm = isDCRmode ? [0, 1, 3, 2, 4, 5] : [0, 1, 4, 2, 5, 3]; } else { [n, h, w, c] = [inputTensor.dims[0], inputTensor.dims[2], inputTensor.dims[3], inputTensor.dims[1]]; shape = isDCRmode ? [n, blocksize, blocksize, c / blocksize ** 2, h, w] : [n, c / blocksize ** 2, blocksize, blocksize, h, w]; perm = isDCRmode ? [0, 3, 4, 1, 5, 2] : [0, 1, 4, 2, 5, 3]; } const reshapedInputTensor = inputTensor.reshape(shape); const reshapedInputRank = reshapedInputTensor.dims.length; const inputDataType = inputTensor.dataType; const reshapedInput = inputVariable("a", inputDataType, reshapedInputRank); const permedOutput = outputVariable("output", inputDataType, reshapedInputRank); const getShaderSource = (shaderHelper) => ` ${shaderHelper.registerUniform("output_size", "u32").declareVariables(reshapedInput, permedOutput)} ${permFunctionBody2(perm, reshapedInputRank, reshapedInput, permedOutput)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let indices = ${permedOutput.offsetToIndices("global_idx")}; let aIndices = perm(indices); ${permedOutput.setByOffset("global_idx", reshapedInput.getByIndices("aIndices"))} }`; return { name: "DepthToSpace", shaderCache: { hint: `${inputTensor.dims};${attributes.blocksize};${attributes.mode}`, inputDependencies: ["rank"] }, getRunData: (inputs) => { const outputShape = isChannelLast ? [n, h * blocksize, w * blocksize, c / blocksize ** 2] : [n, c / blocksize ** 2, h * blocksize, w * blocksize]; const outputSize = ShapeUtil.size(outputShape); const shapeBeforePerm = reshapedInputTensor.dims; const shapeAfterPerm = ShapeUtil.sortBasedOnPerm(shapeBeforePerm, perm); return { outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms: [ { type: 12 /* uint32 */, data: outputSize }, ...createTensorShapeVariables(shapeBeforePerm, shapeAfterPerm) ] }; }, getShaderSource }; }; depthToSpace = (context, attributes) => { validateInputs10(context.inputs); context.compute(createDepthToSpaceProgramInfo(context.inputs[0], attributes)); }; parseDepthToSpaceAttributes = (attributes) => createAttributeWithCacheKey({ blocksize: attributes.blocksize, mode: attributes.mode, format: attributes.format }); } }); // web/lib/wasm/jsep/webgpu/ops/einsum.ts var symbolPattern, termPattern, termPatternOnly, lhsPattern, lhsPatternOnly, EinsumTerm, EinsumEquation, appendMax, createEinsumProgramInfo, einsum, parseEinsumAttributes; var init_einsum = __esm({ "web/lib/wasm/jsep/webgpu/ops/einsum.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); symbolPattern = "[a-zA-Z]|\\.\\.\\."; termPattern = "(" + symbolPattern + ")+"; termPatternOnly = "^" + termPattern + "$"; lhsPattern = "(" + termPattern + ",)*" + termPattern; lhsPatternOnly = "^" + lhsPattern + "$"; EinsumTerm = class { constructor(inputIndex = -1) { this.symbolToIndices = /* @__PURE__ */ new Map(); this.inputIndex = inputIndex; } // Add a symbol to the term addSymbol(symbol, index) { let value = this.symbolToIndices.get(symbol); if (value === void 0) { value = [index]; } else { value.push(index); } this.symbolToIndices.set(symbol, value); } // -1 for output and 0, 1, 2, ... for inputs }; EinsumEquation = class { constructor(inputs, equation) { this.equation = equation; this.hasEllipsis = false; this.symbolToInfo = /* @__PURE__ */ new Map(); this.lhs = new Array(); this.outputDims = []; let [lhs, rhs] = equation.includes("->") ? equation.split("->", 2) : [equation, ""]; if (!lhs.match(RegExp(lhsPatternOnly))) { throw new Error("Invalid LHS term"); } const inputTerms = lhs.split(","); inputTerms.forEach((inputTerm, index) => { const dims = inputs[index].dims.slice(); if (!inputTerm.match(RegExp(termPatternOnly))) { throw new Error("Invalid LHS term"); } const einsumTerm = this.processTerm(inputTerm, true, dims, index); this.lhs.push(einsumTerm); }); if (rhs === "") { rhs += [...this.symbolToInfo.entries()].filter(([sym, info]) => info.count === 1 || sym === "...").map(([sym]) => sym).join(""); } else { if (!rhs.match(RegExp(termPattern))) { throw new Error("Invalid RHS"); } } const rhsSymbols = rhs.match(RegExp(symbolPattern, "g")); rhsSymbols?.forEach((symbol) => { if (symbol === "...") { this.outputDims = this.outputDims.concat(this.ellipsisDims); } else { const info = this.symbolToInfo.get(symbol); if (info === void 0) { throw new Error("Invalid RHS symbol"); } this.outputDims.push(info.dimValue); } }); this.rhs = this.processTerm(rhs, false, this.outputDims); } // End of EinsumEqation constructor // Add a symbol to the equation addSymbol(symbol, dimValue, inputIndex) { let info = this.symbolToInfo.get(symbol); if (info !== void 0) { if (info.dimValue !== dimValue && info.count !== 1) { throw new Error("Dimension mismatch"); } else { info.count++; info.inputIndices.push(inputIndex); } } else { info = { count: 1, dimValue, inputIndices: [inputIndex] }; } this.symbolToInfo.set(symbol, info); } // Process one input/output term processTerm(term, isInput, dims, index = -1) { const rank = dims.length; let ellipsis = false; let ellipsisDims = []; let nextDim = 0; if (!term.match(RegExp(termPatternOnly)) && !isInput && term !== "") { throw new Error("Invalid LHS term"); } const indexSymbols = term.match(RegExp(symbolPattern, "g")); const einsumTerm = new EinsumTerm(index); indexSymbols?.forEach((symbol, i) => { if (symbol === "...") { if (ellipsis) { throw new Error("Only one ellipsis is allowed per input term"); } ellipsis = true; const ellipsisDimLength = rank - indexSymbols.length + 1; if (ellipsisDimLength < 0) { throw new Error("Ellipsis out of bounds"); } ellipsisDims = dims.slice(nextDim, nextDim + ellipsisDimLength); if (this.hasEllipsis) { if (this.ellipsisDims.length !== ellipsisDims.length || this.ellipsisDims.toString() !== ellipsisDims.toString()) { throw new Error("Ellipsis dimensions mismatch"); } } else if (isInput) { this.hasEllipsis = true; this.ellipsisDims = ellipsisDims; } else { throw new Error("Ellipsis must be specified in the LHS"); } for (let j = 0; j < ellipsisDims.length; j++) { const symbol2 = String.fromCharCode("0".charCodeAt(0) + j); einsumTerm.addSymbol(symbol2, i + j); this.addSymbol(symbol2, dims[nextDim++], index); } } else { einsumTerm.addSymbol(symbol, i + (this.hasEllipsis ? this.ellipsisDims.length - 1 : 0)); this.addSymbol(symbol, dims[nextDim++], index); } }); return einsumTerm; } // Output dimensions of the equation }; appendMax = (name) => name + "_max"; createEinsumProgramInfo = (inputShapes, dataType, einsumEquation, outputShape) => { const ranks = inputShapes.map((dims) => dims.length); const inputVars = ranks.map((rank, index) => inputVariable(`input${index}`, dataType, rank)); const outputSize = ShapeUtil.size(outputShape); const output = outputVariable("output", dataType, outputShape.length); const uniformsSymbols = [...einsumEquation.symbolToInfo.keys()].filter( (symbol) => !einsumEquation.rhs.symbolToIndices.has(symbol) ); const getShaderSource = (shaderHelper) => { const idxCopy = []; const initProd = "var prod = 1.0;"; const initSum = "var sum = 0.0;"; const updateSum = "sum += prod;"; const reduceOpsSetIndices = []; const reduceOpsLoopHeaders = []; const reduceOpsLoopFooters = []; const reduceOpCompute = []; const isReduceOpsWithoutLoop = einsumEquation.symbolToInfo.size === einsumEquation.rhs.symbolToIndices.size; einsumEquation.symbolToInfo.forEach((info, symbol) => { if (einsumEquation.rhs.symbolToIndices.has(symbol)) { const outputIndex = einsumEquation.rhs.symbolToIndices.get(symbol)?.[0]; if (outputIndex !== void 0) { einsumEquation.lhs.forEach((term, i) => { if (info.inputIndices.includes(i)) { const indices = term.symbolToIndices.get(symbol); if (indices === void 0) { throw new Error("Invalid symbol error"); } indices.forEach((index) => { idxCopy.push( `${inputVars[i].indicesSet( `input${i}Indices`, index, output.indicesGet("outputIndices", outputIndex) )}` ); }); } }); } } else { einsumEquation.lhs.forEach((term, i) => { if (info.inputIndices.includes(i)) { const indices = term.symbolToIndices.get(symbol); if (indices === void 0) { throw new Error("Invalid symbol error"); } indices.forEach((index) => { reduceOpsSetIndices.push(`${inputVars[i].indicesSet(`input${i}Indices`, index, `${symbol}`)}`); }); reduceOpCompute.push(`prod *= ${inputVars[i].getByIndices(`input${i}Indices`)};`); } }); reduceOpsLoopHeaders.push( `for(var ${symbol}: u32 = 0; ${symbol} < uniforms.${appendMax(symbol)}; ${symbol}++) {` ); reduceOpsLoopFooters.push("}"); } }); const reduceOps2 = isReduceOpsWithoutLoop ? [ ...idxCopy, `let sum = ${inputVars.map((inputVar, i) => inputVar.getByIndices(`input${i}Indices`)).join(" * ")};` ] : [ ...idxCopy, initSum, ...reduceOpsLoopHeaders, ...reduceOpsSetIndices, initProd, ...reduceOpCompute, updateSum, ...reduceOpsLoopFooters ]; return ` ${shaderHelper.registerUniforms(uniformsSymbols.map((symbol) => ({ name: `${appendMax(symbol)}`, type: "u32" }))).registerUniform("outputSize", "u32").declareVariables(...inputVars, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} var outputIndices = ${output.offsetToIndices("global_idx")}; ${inputVars.map((_var, i) => `var input${i}Indices: ${inputVars[i].type.indices};`).join("\n")} ${reduceOps2.join("\n")}; ${output.setByOffset("global_idx", "sum")}; }`; }; return { name: "Einsum", shaderCache: { hint: einsumEquation.equation, inputDependencies: inputShapes.map(() => "rank") }, getRunData: () => { const programUniformsInit = uniformsSymbols.filter((symbol) => einsumEquation.symbolToInfo.has(symbol)).map((symbol) => ({ type: 12 /* uint32 */, data: einsumEquation.symbolToInfo.get(symbol)?.dimValue || 0 })); programUniformsInit.push({ type: 12 /* uint32 */, data: outputSize }); const programUniforms = inputShapes.map((dims, _) => [...createTensorShapeVariables(dims)]).reduce((acc, inputProgramUniforms) => acc.concat(inputProgramUniforms), programUniformsInit); programUniforms.push(...createTensorShapeVariables(outputShape)); return { outputs: [{ dims: outputShape, dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }; }, getShaderSource }; }; einsum = (context, attributes) => { const einsumEquation = new EinsumEquation(context.inputs, attributes.equation); const outputShape = einsumEquation.outputDims; const inputShapes = context.inputs.map((input, _) => input.dims); context.compute(createEinsumProgramInfo(inputShapes, context.inputs[0].dataType, einsumEquation, outputShape)); }; parseEinsumAttributes = (attributes) => { const equation = attributes.equation.replace(/\s+/g, ""); return createAttributeWithCacheKey({ equation }); }; } }); // web/lib/wasm/jsep/webgpu/ops/expand.ts var validateInputs11, getAdjustedShape, calculateOutputShape2, createExpandProgramInfo, expand; var init_expand = __esm({ "web/lib/wasm/jsep/webgpu/ops/expand.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); validateInputs11 = (inputs) => { if (!inputs || inputs.length !== 2) { throw new Error("Expand requires 2 input."); } const inputShape = inputs[0].dims; const shape = Array.from(inputs[1].getBigInt64Array(), Number); let shapeIndex = shape.length < inputShape.length ? 0 : shape.length - inputShape.length; let inputShapeIndex = inputShape.length < shape.length ? 0 : inputShape.length - shape.length; for (; shapeIndex < shape.length && inputShapeIndex < inputShape.length; ++shapeIndex, ++inputShapeIndex) { if (shape[shapeIndex] !== inputShape[inputShapeIndex] && shape[shapeIndex] !== 1 && inputShape[inputShapeIndex] !== 1) { throw new Error("Expand requires shape to be broadcastable to input"); } } }; getAdjustedShape = (shape1, shape2) => { const diff = shape1.length - shape2.length; const shape = []; for (let i = 0; i < diff; ++i) { shape.push(shape1[i]); } for (let i = 0; i < shape2.length; ++i) { shape.push(shape2[i] === 1 ? shape1[i + diff] : shape2[i]); } return shape; }; calculateOutputShape2 = (inputShape, shape) => inputShape.length > shape.length ? getAdjustedShape(inputShape, shape) : getAdjustedShape(shape, inputShape); createExpandProgramInfo = (inputs) => { const inputShape = inputs[0].dims; const shape = Array.from(inputs[1].getBigInt64Array(), Number); const outputShape = calculateOutputShape2(inputShape, shape); const dataType = inputs[0].dataType; const isBoolOrScalar = dataType === 9 /* bool */ || ShapeUtil.size(inputShape) === 1; const iComponents = dataType === 9 /* bool */ ? 4 : inputShape.length > 0 && inputShape[inputShape.length - 1] % 4 === 0 ? 4 : 1; const components = isBoolOrScalar ? 4 : outputShape.length > 0 && outputShape[outputShape.length - 1] % 4 === 0 ? 4 : 1; const outputSize = Math.ceil(ShapeUtil.size(outputShape) / components); const getShaderSource = (shaderHelper) => { const input = inputVariable("input", dataType, inputShape.length, iComponents); const output = outputVariable("output", dataType, outputShape.length, components); let assignment; if (dataType === 9 /* bool */) { const singleAssignment = (resStr, x, typeCast = "") => ` let outputIndices${x} = ${output.offsetToIndices(`outputOffset + ${x}u`)}; let offset${x} = ${input.broadcastedIndicesToOffset(`outputIndices${x}`, output)}; let index${x} = offset${x} / 4u; let component${x} = offset${x} % 4u; ${resStr}[${x}] = ${typeCast}(${input.getByOffset(`index${x}`)}[component${x}]); `; assignment = ` let outputOffset = global_idx * ${components}; var data = vec4(0); ${singleAssignment("data", 0, "u32")} ${singleAssignment("data", 1, "u32")} ${singleAssignment("data", 2, "u32")} ${singleAssignment("data", 3, "u32")} ${output.setByOffset("global_idx", "data")} }`; } else { assignment = ` let outputIndices = ${output.offsetToIndices(`global_idx * ${components}`)}; let inputOffset = ${input.broadcastedIndicesToOffset("outputIndices", output)}; let data = ${output.type.value}(${input.getByOffset(`inputOffset / ${iComponents}`)}); ${output.setByOffset("global_idx", "data")} }`; } return ` ${shaderHelper.registerUniform("vec_size", "u32").declareVariables(input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.vec_size")} ${assignment}`; }; const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, ...createTensorShapeVariables(inputShape, outputShape) ]; return { name: "Expand", shaderCache: { hint: `${outputShape.length};${iComponents}${components}`, inputDependencies: ["rank"] }, getShaderSource, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }) }; }; expand = (context) => { validateInputs11(context.inputs); context.compute(createExpandProgramInfo(context.inputs), { inputs: [0] }); }; } }); // web/lib/wasm/jsep/webgpu/ops/fast-gelu.ts var createFastGeluProgramInfo, fastGelu2; var init_fast_gelu = __esm({ "web/lib/wasm/jsep/webgpu/ops/fast-gelu.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); init_unary_op(); createFastGeluProgramInfo = (inputTensors) => { const dataType = inputTensors[0].dataType; const outputSize = ShapeUtil.size(inputTensors[0].dims); const biasLength = ShapeUtil.size(inputTensors[1].dims); const useVec4 = biasLength % 4 === 0; const getShaderSource = (shaderHelper) => { const x = inputVariable("x", dataType, [1], 4); const bias = inputVariable("bias", dataType, [1], 4); const y = outputVariable("y", dataType, [1], 4); const uniforms = [ { name: "output_vec_size", type: "u32" }, { name: "bias_size", type: "u32" } ]; const singleElementBias = (i) => ` let bias${i}_offset: u32 = (global_idx * 4 + ${i}) % uniforms.bias_size; let bias${i} = ${bias.getByOffset(`bias${i}_offset / 4`)}[bias${i}_offset % 4];`; const biasGetExpression = useVec4 ? ` let bias = ${bias.getByOffset("global_idx % (uniforms.bias_size / 4)")};` : `${singleElementBias(0)}${singleElementBias(1)}${singleElementBias(2)}${singleElementBias(3)} let bias = ${x.type.value}(bias0, bias1, bias2, bias3);`; return `${shaderHelper.registerUniforms(uniforms).declareVariables(x, bias, y)} ${fastGeluImpl(tensorTypeToWsglValueType(dataType))} ${shaderHelper.mainStart(WORKGROUP_SIZE)} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_vec_size")} let x = ${x.getByOffset("global_idx")}; ${biasGetExpression} let x_in = x + bias; ${y.setByOffset("global_idx", fastGeluExpression("x_in"))} }`; }; return { name: "FastGeluWithBias", shaderCache: { hint: `${useVec4}`, inputDependencies: ["type", "type"] }, getShaderSource, getRunData: (inputs) => ({ outputs: [{ dims: inputs[0].dims, dataType: inputs[0].dataType }], programUniforms: [ { type: 12 /* uint32 */, data: Math.ceil(outputSize / 4) }, { type: 12 /* uint32 */, data: biasLength } ], dispatchGroup: { x: Math.ceil(outputSize / WORKGROUP_SIZE / 4) } }) }; }; fastGelu2 = (context) => { if (context.inputs.length < 2 || ShapeUtil.size(context.inputs[1].dims) === 0) { fastGelu(context); } else { context.compute(createFastGeluProgramInfo(context.inputs)); } }; } }); // web/lib/wasm/jsep/webgpu/ops/gather.ts var validateInputs12, createGatherProgramInfo, parseGatherAttributes, gather; var init_gather = __esm({ "web/lib/wasm/jsep/webgpu/ops/gather.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs12 = (inputs) => { if (!inputs || inputs.length !== 2) { throw new Error("Gather requires 2 inputs."); } }; createGatherProgramInfo = (inputs, attributes) => { const inputShape = inputs[0].dims; const indicesShape = inputs[1].dims; const inputRank = inputShape.length; const axis = ShapeUtil.normalizeAxis(attributes.axis, inputRank); const outputShape = inputShape.slice(0); outputShape.splice(axis, 1, ...indicesShape); const axisDimLimit = inputShape[axis]; const components = inputs[0].dataType === 9 /* bool */ ? 4 : 1; const outputSize = Math.ceil(ShapeUtil.size(outputShape) / components); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 6 /* int32 */, data: axisDimLimit }, { type: 12 /* uint32 */, data: axis }, ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims, outputShape) ]; const getShaderSource = (shaderHelper) => { const data = inputVariable("data", inputs[0].dataType, inputs[0].dims.length, components); const indices = inputVariable("inputIndices", inputs[1].dataType, inputs[1].dims.length); const output = outputVariable("output", inputs[0].dataType, outputShape.length, components); const calcDataIndices = (x) => { const indicesRank = indicesShape.length; let calcStr = `var indicesIndices${x} = ${indices.type.indices}(0);`; for (let i = 0; i < indicesRank; i++) { calcStr += `${indicesRank > 1 ? `indicesIndices${x}[${i}]` : `indicesIndices${x}`} = ${outputShape.length > 1 ? `outputIndices${x}[uniforms.axis + ${i}]` : `outputIndices${x}`};`; } calcStr += ` var idx${x} = ${indices.getByIndices(`indicesIndices${x}`)}; if (idx${x} < 0) { idx${x} = idx${x} + uniforms.axisDimLimit; } var dataIndices${x} : ${data.type.indices}; `; for (let i = 0, j = 0; i < inputRank; i++) { if (i === axis) { calcStr += `${inputRank > 1 ? `dataIndices${x}[${i}]` : `dataIndices${x}`} = u32(idx${x});`; j += indicesRank; } else { calcStr += `${inputRank > 1 ? `dataIndices${x}[${i}]` : `dataIndices${x}`} = ${outputShape.length > 1 ? `outputIndices${x}[${j}]` : `outputIndices${x}`};`; j++; } } return calcStr; }; let assignment; if (inputs[0].dataType === 9 /* bool */) { const singleAssignment = (resStr, x, typeCast = "") => ` let outputIndices${x} = ${output.offsetToIndices(`outputOffset + ${x}u`)}; ${calcDataIndices(x)}; let offset${x} = ${data.indicesToOffset(`dataIndices${x}`)}; let index${x} = offset${x} / 4u; let component${x} = offset${x} % 4u; ${resStr}[${x}] = ${typeCast}(${data.getByOffset(`index${x}`)}[component${x}]); `; assignment = ` let outputOffset = global_idx * ${components}; var value = vec4(0); ${singleAssignment("value", 0, "u32")} ${singleAssignment("value", 1, "u32")} ${singleAssignment("value", 2, "u32")} ${singleAssignment("value", 3, "u32")} ${output.setByOffset("global_idx", "value")} `; } else { assignment = ` let outputIndices = ${output.offsetToIndices("global_idx")}; ${calcDataIndices("")}; let value = ${data.getByIndices("dataIndices")}; ${output.setByOffset("global_idx", "value")}; `; } return ` ${shaderHelper.registerUniform("outputSize", "u32").registerUniform("axisDimLimit", "i32").registerUniform("axis", "u32").declareVariables(data, indices, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} ${assignment} }`; }; return { name: "Gather", shaderCache: { hint: attributes.cacheKey, inputDependencies: ["rank", "rank"] }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; parseGatherAttributes = (attributes) => createAttributeWithCacheKey({ axis: attributes.axis }); gather = (context, attributes) => { const inputs = context.inputs; validateInputs12(inputs); context.compute(createGatherProgramInfo(context.inputs, attributes)); }; } }); // web/lib/wasm/jsep/webgpu/ops/gather-nd.ts var computeSliceOffsets, gatherND, parseGatherNDAttributes; var init_gather_nd = __esm({ "web/lib/wasm/jsep/webgpu/ops/gather-nd.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); computeSliceOffsets = (context, indicesData, sizesFromSliceDimsData, batchDims, inputDims, numSlices, numSlicesPerBatch, inputBatchStride, numSliceDims) => { const programUniforms = [ { type: 12 /* uint32 */, data: numSlices }, { type: 12 /* uint32 */, data: batchDims }, { type: 12 /* uint32 */, data: inputDims }, { type: 12 /* uint32 */, data: sizesFromSliceDimsData }, { type: 12 /* uint32 */, data: numSlicesPerBatch }, { type: 12 /* uint32 */, data: inputBatchStride }, { type: 12 /* uint32 */, data: numSliceDims } ]; const outputShape = [numSlices]; programUniforms.push(...createTensorShapeVariables(indicesData.dims, outputShape)); const getShaderSource = (shaderHelper) => { const indices = inputVariable("indices_data", indicesData.dataType, indicesData.dims.length); const output = outputVariable("input_slice_offsets_data", 12 /* uint32 */, 1, 1); const variables = [indices, output]; const uniforms = [ { name: "output_size", type: "u32" }, { name: "batch_dims", type: "u32" }, { name: "input_dims", type: "u32", length: inputDims.length }, { name: "sizes_from_slice_dims_data", type: "u32", length: sizesFromSliceDimsData.length }, { name: "num_slices_per_batch", type: "u32" }, { name: "input_batch_stride", type: "u32" }, { name: "num_slice_dims", type: "u32" } ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...variables)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let batch_idx = global_idx / uniforms.num_slices_per_batch; let base_offset = batch_idx * uniforms.input_batch_stride; let slice_indices_base_offset = global_idx * uniforms.num_slice_dims; var relative_slice_offset = 0; for (var dim_idx = 0u; dim_idx < uniforms.num_slice_dims; dim_idx ++) { var index = i32(indices_data[dim_idx + slice_indices_base_offset].x); let input_dim_idx = uniforms.batch_dims + dim_idx; if (index < 0) { ${inputDims.length === 1 ? "index += i32(uniforms.input_dims);" : "index += i32(uniforms.input_dims[input_dim_idx]);"} } ${sizesFromSliceDimsData.length === 1 ? "relative_slice_offset += index * i32(uniforms.sizes_from_slice_dims_data);" : "relative_slice_offset += index * i32(uniforms.sizes_from_slice_dims_data[dim_idx]);"} } input_slice_offsets_data[global_idx] = base_offset + u32(relative_slice_offset); }`; }; return context.compute( { name: "computeSliceOffsets", shaderCache: { hint: `${inputDims.length}_${sizesFromSliceDimsData.length}`, inputDependencies: ["rank"] }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: context.inputs[1].dataType }], dispatchGroup: { x: Math.ceil(numSlices / 64) }, programUniforms }), getShaderSource }, { inputs: [indicesData], outputs: [-1] } )[0]; }; gatherND = (context, attributes) => { const inputs = context.inputs; const inputShape = inputs[0].dims; const inputType = inputs[0].dataType; const indicesShape = inputs[1].dims; const numSliceDims = indicesShape[indicesShape.length - 1]; const numSlices = ShapeUtil.sizeToDimension(indicesShape, indicesShape.length - 1); const sliceSize = ShapeUtil.sizeFromDimension(inputShape, attributes.batchDims + numSliceDims); const numBatches = ShapeUtil.sizeToDimension(inputShape, attributes.batchDims); const inputBatchStride = ShapeUtil.sizeFromDimension(inputShape, attributes.batchDims); const numSlicesPerBatch = numSlices / numBatches; const sizesFromSliceDims = new Array(numSliceDims); let runningProduct = sliceSize; for (let i = 0; i < numSliceDims; ++i) { sizesFromSliceDims[numSliceDims - 1 - i] = runningProduct; runningProduct *= inputShape[attributes.batchDims + numSliceDims - 1 - i]; } const inputSliceOffsets = computeSliceOffsets( context, inputs[1], sizesFromSliceDims, attributes.batchDims, inputShape, numSlices, numSlicesPerBatch, inputBatchStride, numSliceDims ); const lastIndicesDimension = attributes.batchDims + numSliceDims; if (lastIndicesDimension > inputShape.length) { throw new Error("last dimension of indices must not be larger than rank of input tensor"); } const outputShape = indicesShape.slice(0, -1).concat(inputShape.slice(lastIndicesDimension)); const outputSize = ShapeUtil.size(outputShape); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: sliceSize }, ...createTensorShapeVariables(inputs[0].dims, inputSliceOffsets.dims, outputShape) ]; const getShaderSource = (shaderHelper) => { const input = inputVariable("data", inputs[0].dataType, inputs[0].dims.length); const indices = inputVariable("slice_offsets", 12 /* uint32 */, inputSliceOffsets.dims.length); const output = outputVariable("output", inputs[0].dataType, outputShape.length); return ` ${shaderHelper.registerUniform("output_size", "u32").registerUniform("slice_size", "u32").declareVariables(input, indices, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let slice_offset = slice_offsets[global_idx / uniforms.slice_size]; output[global_idx] = data[u32(slice_offset) + global_idx % uniforms.slice_size]; }`; }; context.compute( { name: "GatherND", shaderCache: { hint: attributes.cacheKey, inputDependencies: ["rank", "rank"] }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }, { inputs: [inputs[0], inputSliceOffsets] } ); }; parseGatherNDAttributes = (attributes) => { const batchDims = attributes.batch_dims; return { batchDims, cacheKey: "" }; }; } }); // web/lib/wasm/jsep/webgpu/ops/gather-block-quantized.ts var validateInputs13, createGatherBlockQuantizedProgramInfo, gatherBlockQuantized, parseGatherBlockQuantizedAttributes; var init_gather_block_quantized = __esm({ "web/lib/wasm/jsep/webgpu/ops/gather-block-quantized.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs13 = (inputs, attributes) => { if (inputs.length < 3 || inputs.length > 4) { throw new Error("GatherBlockQuantized requires 3 or 4 inputs."); } const quantizeAxis = ShapeUtil.normalizeAxis(attributes.quantizeAxis, inputs[0].dims.length); const blockSize = attributes.blockSize; const data = inputs[0]; const scales = inputs[2]; const zeroPoint = inputs.length === 4 ? inputs[3] : void 0; if (scales.dims.length !== data.dims.length || !data.dims.map((d, i) => i === quantizeAxis ? Math.ceil(d / blockSize) === scales.dims[i] : d === scales.dims[i]).reduce((a, b) => a && b, true)) { throw new Error( "Scales must have the same rank as the input tensor and the dims should match except on gatherAxis." ); } if (zeroPoint) { if (zeroPoint.dataType !== data.dataType) { throw new Error("Zero point must have the same data type as the input tensor."); } if (zeroPoint.dims.length !== scales.dims.length || !zeroPoint.dims.map((d, i) => d === scales.dims[i]).reduce((a, b) => a && b, true)) { throw new Error( "Zero point must have the same rank as the input tensor and the dims should match except on quantizeAxis." ); } } }; createGatherBlockQuantizedProgramInfo = (inputs, attributes) => { const inputShape = inputs[0].dims; const indicesShape = inputs[1].dims; const inputRank = inputShape.length; const gatherAxis = ShapeUtil.normalizeAxis(attributes.gatherAxis, inputRank); const quantizeAxis = ShapeUtil.normalizeAxis(attributes.quantizeAxis, inputRank); const outputShape = inputShape.slice(0); outputShape.splice(gatherAxis, 1, ...indicesShape); const outputSize = ShapeUtil.size(outputShape); const outputType = inputs[2].dataType; const inputType = inputs[0].dataType; const isSigned = inputType === 22 /* int4 */; const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: quantizeAxis }, { type: 12 /* uint32 */, data: gatherAxis }, { type: 12 /* uint32 */, data: attributes.blockSize }, ...createTensorShapeVariables(...inputs.map((input, _) => input.dims), outputShape) ]; const getShaderSource = (shaderHelper) => { const data = inputVariable("data", inputs[0].dataType, inputs[0].dims.length); const indices = inputVariable("inputIndices", inputs[1].dataType, inputs[1].dims.length); const scales = inputVariable("scales", inputs[2].dataType, inputs[2].dims.length); const zeroPoint = inputs.length > 3 ? inputVariable("zeroPoint", inputs[3].dataType, inputs[3].dims.length) : void 0; const output = outputVariable("output", outputType, outputShape.length); const inputVariables = [data, indices, scales]; if (zeroPoint) { inputVariables.push(zeroPoint); } const uniforms = [ { name: "output_size", type: "u32" }, { name: "quantize_axis", type: "u32" }, { name: "gather_axis", type: "u32" }, { name: "block_size", type: "u32" } ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} ${shaderHelper.mainStart()} let output_indices = ${output.offsetToIndices("global_idx")}; var indices_indices = ${indices.type.indices}(0); ${(() => { if (indicesShape.length > 1) { return ` for (var i: u32 = 0; i < ${indicesShape.length}; i++) { let index = ${output.indicesGet("output_indices", "uniforms.gather_axis + i")}; ${indices.indicesSet("indices_indices", "i", "index")}; }`; } else { return `indices_indices = ${output.indicesGet("output_indices", "uniforms.gather_axis")};`; } })()}; var data_indices = ${data.type.indices}(0); for (var i: u32 = 0; i < uniforms.gather_axis; i++) { let index = ${output.indicesGet("output_indices", "i")}; ${data.indicesSet("data_indices", "i", "index")}; } var index_from_indices = ${indices.getByIndices("indices_indices")}; if (index_from_indices < 0) { index_from_indices += ${inputShape[gatherAxis]}; } ${data.indicesSet("data_indices", "uniforms.gather_axis", "u32(index_from_indices)")}; for (var i = uniforms.gather_axis + 1; i < ${outputShape.length}; i++) { let index = ${output.indicesGet("output_indices", `i + ${indicesShape.length} - 1`)}; ${data.indicesSet("data_indices", "i", "index")}; } let data_offset = ${data.indicesToOffset("data_indices")}; let data_index = data_offset % 8; // Convert 4-bit packed data to 8-bit packed data. let packed_4bit_quantized_data = ${data.getByOffset("data_offset / 8")}; let packed_8bit_quantized_data = (packed_4bit_quantized_data >> (4 * (data_index % 2))) & 0x0f0f0f0f; let quantized_data_vec = ${isSigned ? "unpack4xI8" : "unpack4xU8"}(u32(packed_8bit_quantized_data)); let quantized_data = quantized_data_vec[data_index / 2]; var scale_indices = data_indices; let quantize_axis_index = ${scales.indicesGet("data_indices", "uniforms.quantize_axis")} / uniforms.block_size; ${scales.indicesSet("scale_indices", "uniforms.quantize_axis", "quantize_axis_index")}; var scale = ${scales.getByIndices("scale_indices")}; ${(() => { if (!zeroPoint) { return "var zero_point = 0"; } else { return ` let zero_point_indices = scale_indices; let zero_point_offset = ${zeroPoint.indicesToOffset("zero_point_indices")}; let zero_point_index = zero_point_offset % 8; let packed_4bit_zero_points = ${zeroPoint.getByOffset("zero_point_offset / 8")}; let packed_8bit_zero_points = (packed_4bit_zero_points >> (4 * (zero_point_index % 2))) & 0x0f0f0f0f; let zero_point_vec = ${isSigned ? "unpack4xI8" : "unpack4xU8"}(u32(packed_8bit_zero_points)); let zero_point = zero_point_vec[zero_point_index / 2];`; } })()}; let dequantized_data = ${tensorTypeToWsglValueType(outputType)}(quantized_data - zero_point) * scale; ${output.setByOffset("global_idx", "dequantized_data")}; }`; }; return { name: "GatherBlockQuantized", shaderCache: { hint: `${attributes.cacheKey};${inputs.filter((_, i) => i !== 1).map((input) => input.dims.join("_")).join(";")}`, inputDependencies: Array.from({ length: inputs.length }, (_v, _i) => "rank") }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: outputType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; gatherBlockQuantized = (context, attributes) => { const inputs = context.inputs; validateInputs13(inputs, attributes); context.compute(createGatherBlockQuantizedProgramInfo(context.inputs, attributes)); }; parseGatherBlockQuantizedAttributes = (attributes) => createAttributeWithCacheKey({ blockSize: attributes.blockSize, gatherAxis: attributes.gatherAxis, quantizeAxis: attributes.quantizeAxis }); } }); // web/lib/wasm/jsep/webgpu/ops/gather-elements.ts var validateInputs14, createGatherElementsProgramInfo, parseGatherElementsAttributes, gatherElements; var init_gather_elements = __esm({ "web/lib/wasm/jsep/webgpu/ops/gather-elements.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs14 = (inputs) => { if (!inputs || inputs.length !== 2) { throw new Error("GatherElements requires 2 inputs."); } if (inputs[0].dims.length < 1) { throw new Error("GatherElements requires that the data input be rank >= 1."); } if (inputs[0].dims.length !== inputs[1].dims.length) { throw new Error(`GatherElements requires that the data input and indices input tensors be of same rank.`); } }; createGatherElementsProgramInfo = (inputs, attributes) => { const inputShape = inputs[0].dims; const inputOutputDataType = inputs[0].dataType; const inputRank = inputShape.length; const indicesShape = inputs[1].dims; const indicesDataType = inputs[1].dataType; const axis = ShapeUtil.normalizeAxis(attributes.axis, inputRank); const axisDimLimit = inputShape[axis]; const outputShape = indicesShape.slice(0); const outputSize = ShapeUtil.size(outputShape); const input = inputVariable("input", inputOutputDataType, inputRank); const indices = inputVariable("indicesInput", indicesDataType, indicesShape.length); const output = outputVariable("output", inputOutputDataType, outputShape.length); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 6 /* int32 */, data: axisDimLimit }, { type: 12 /* uint32 */, data: axis } ]; programUniforms.push(...createTensorShapeVariables(inputShape, indicesShape, outputShape)); const inputDependencies = ["rank", "rank"]; const getShaderSource = (shaderHelper) => ` ${shaderHelper.registerUniform("outputSize", "u32").registerUniform("axisDimLimit", "i32").registerUniform("axis", "u32").declareVariables(input, indices, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} let outputIndices = ${output.offsetToIndices("global_idx")}; var idx = ${indices.getByOffset("global_idx")}; if (idx < 0) { idx = idx + uniforms.axisDimLimit; } var inputIndices = ${input.type.indices}(outputIndices); ${input.indicesSet("inputIndices", "uniforms.axis", "u32(idx)")}; let value = ${input.getByIndices("inputIndices")}; ${output.setByOffset("global_idx", "value")}; }`; return { name: "GatherElements", shaderCache: { inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; parseGatherElementsAttributes = (attributes) => createAttributeWithCacheKey({ axis: attributes.axis }); gatherElements = (context, attributes) => { const inputs = context.inputs; validateInputs14(inputs); context.compute(createGatherElementsProgramInfo(context.inputs, attributes)); }; } }); // web/lib/wasm/jsep/webgpu/ops/gemm.ts var validateInputs15, createGemmProgramInfo, parseGemmAttributes, gemm; var init_gemm = __esm({ "web/lib/wasm/jsep/webgpu/ops/gemm.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); validateInputs15 = (inputs) => { if (!inputs) { throw new Error("Input is missing"); } if (inputs.length < 2 || inputs.length > 3) { throw new Error("Invaid input number."); } if (inputs.length === 3 && inputs[2].dims.length > 2) { throw new Error("Invalid input shape of C"); } if (inputs[0].dataType !== inputs[1].dataType || inputs.length === 3 && inputs[0].dataType !== inputs[2].dataType) { throw new Error("Input types are mismatched"); } }; createGemmProgramInfo = (inputs, attributes) => { const aShape = inputs[0].dims.slice(); const bShape = inputs[1].dims.slice(); const [M, N, K] = GemmUtil.getShapeOfGemmResult( aShape, attributes.transA, bShape, attributes.transB, inputs.length === 3 ? inputs[2].dims : void 0 ); const outputShape = [M, N]; if (!outputShape) { throw new Error("Can't use gemm on the given tensors"); } const tileSize = 16; const numTileN = Math.ceil(N / tileSize); const numTileM = Math.ceil(M / tileSize); const useShared = true; const outputSize = ShapeUtil.size(outputShape); const programUniforms = [ { type: 12 /* uint32 */, data: useShared ? numTileN : outputSize }, { type: 12 /* uint32 */, data: M }, { type: 12 /* uint32 */, data: N }, { type: 12 /* uint32 */, data: K }, { type: 1 /* float */, data: attributes.alpha }, { type: 1 /* float */, data: attributes.beta } ]; const inputDependencies = ["type", "type"]; if (inputs.length === 3) { programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); inputDependencies.push("rank"); } programUniforms.push(...createTensorShapeVariables(outputShape)); const getShaderSource = (shaderHelper) => { let line = ""; if (attributes.transA && attributes.transB) { line = "value += a[k * uniforms.M + m] * b[n * uniforms.K + k];"; } else if (attributes.transA && !attributes.transB) { line = "value += a[k * uniforms.M + m] * b[k * uniforms.N + n];"; } else if (!attributes.transA && attributes.transB) { line = "value += a[m * uniforms.K + k] * b[n * uniforms.K + k];"; } else if (!attributes.transA && !attributes.transB) { line = "value += a[m * uniforms.K + k] * b[k * uniforms.N + n];"; } const calculateAlpha = attributes.alpha === 1 ? "" : "value *= uniforms.alpha;"; const a = inputVariable("a", inputs[0].dataType, inputs[0].dims); const b = inputVariable("b", inputs[1].dataType, inputs[1].dims); const dataType = a.type.value; let c = null; const variables = [a, b]; if (inputs.length === 3) { c = inputVariable("c", inputs[2].dataType, inputs[2].dims.length); variables.push(c); } const output = outputVariable("output", inputs[0].dataType, outputShape.length); variables.push(output); const uniforms = [ { name: "output_size", type: "u32" }, { name: "M", type: "u32" }, { name: "N", type: "u32" }, { name: "K", type: "u32" }, { name: "alpha", type: "f32" }, { name: "beta", type: "f32" } ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...variables)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let m = global_idx / uniforms.N; let n = global_idx % uniforms.N; var value = ${dataType}(0); for (var k: u32 = 0u; k < uniforms.K; k++) { ${line} } ${calculateAlpha} ${(() => { if (c != null) { return `let cOffset = ${c.broadcastedIndicesToOffset("vec2(m, n)", output)}; value += ${dataType}(uniforms.beta) * ${c.getByOffset("cOffset")};`; } return ""; })()} output[global_idx] = value; }`; }; const getShaderSourceShared = (shaderHelper) => { const a = inputVariable("a", inputs[0].dataType, inputs[0].dims); const b = inputVariable("b", inputs[1].dataType, inputs[1].dims); let c = null; const variables = [a, b]; if (inputs.length === 3) { c = inputVariable("c", inputs[2].dataType, inputs[2].dims.length); variables.push(c); } const output = outputVariable("output", inputs[0].dataType, outputShape.length); variables.push(output); const uniforms = [ { name: "num_tile_n", type: "u32" }, { name: "M", type: "u32" }, { name: "N", type: "u32" }, { name: "K", type: "u32" }, { name: "alpha", type: "f32" }, { name: "beta", type: "f32" } ]; let calcResult = ""; let fillWorkgroupMemory = ""; if (attributes.transA && attributes.transB) { fillWorkgroupMemory = ` var col = tile_row_start + local_id.x; var row = k_start + local_id.y; if (col < uniforms.M && row < uniforms.K) { tile_a[local_id.y][local_id.x] = a[row * uniforms.M + col]; } else { tile_a[local_id.y][local_id.x] = ${a.type.value}(0); } col = k_start + local_id.x; row = tile_col_start + local_id.y; if (col < uniforms.K && row < uniforms.N) { tile_b[local_id.y][local_id.x] = b[row * uniforms.K + col]; } else { tile_b[local_id.y][local_id.x] = ${b.type.value}(0); } `; calcResult = `value += tile_a[k][local_id.y] * tile_b[local_id.x][k];`; } else if (attributes.transA && !attributes.transB) { fillWorkgroupMemory = ` var col = tile_row_start + local_id.x; var row = k_start + local_id.y; if (col < uniforms.M && row < uniforms.K) { tile_a[local_id.y][local_id.x] = a[row * uniforms.M + col]; } else { tile_a[local_id.y][local_id.x] = ${a.type.value}(0); } col = tile_col_start + local_id.x; row = k_start + local_id.y; if (col < uniforms.N && row < uniforms.K) { tile_b[local_id.y][local_id.x] = b[row * uniforms.N + col]; } else { tile_b[local_id.y][local_id.x] = ${b.type.value}(0); } `; calcResult = `value += tile_a[k][local_id.y] * tile_b[k][local_id.x];`; } else if (!attributes.transA && attributes.transB) { fillWorkgroupMemory = ` var col = k_start + local_id.x; var row = tile_row_start + local_id.y; if (col < uniforms.K && row < uniforms.M) { tile_a[local_id.y][local_id.x] = a[row * uniforms.K + col]; } else { tile_a[local_id.y][local_id.x] = ${a.type.value}(0); } col = k_start + local_id.x; row = tile_col_start + local_id.y; if (col < uniforms.K && row < uniforms.N) { tile_b[local_id.y][local_id.x] = b[row * uniforms.K + col]; } else { tile_b[local_id.y][local_id.x] = ${b.type.value}(0); } `; calcResult = `value += tile_a[local_id.y][k] * tile_b[local_id.x][k];`; } else if (!attributes.transA && !attributes.transB) { fillWorkgroupMemory = ` var col = k_start + local_id.x; var row = tile_row_start + local_id.y; if (col < uniforms.K && row < uniforms.M) { tile_a[local_id.y][local_id.x] = a[row * uniforms.K + col]; } else { tile_a[local_id.y][local_id.x] = ${a.type.value}(0); } col = tile_col_start + local_id.x; row = k_start + local_id.y; if (col < uniforms.N && row < uniforms.K) { tile_b[local_id.y][local_id.x] = b[row * uniforms.N + col]; } else { tile_b[local_id.y][local_id.x] = ${b.type.value}(0); } `; calcResult = `value += tile_a[local_id.y][k] * tile_b[k][local_id.x];`; } const calculateAlpha = attributes.alpha === 1 ? "" : "value *= uniforms.alpha;"; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...variables)} var tile_a: array, ${tileSize}>; var tile_b: array, ${tileSize}>; ${shaderHelper.mainStart([tileSize, tileSize, 1])} let tile_col_start = (workgroup_index % uniforms.num_tile_n) * ${tileSize}; let tile_row_start = (workgroup_index / uniforms.num_tile_n) * ${tileSize}; let num_tiles = (uniforms.K - 1) / ${tileSize} + 1; var k_start = 0u; var value = ${output.type.value}(0); for (var t: u32 = 0u; t < num_tiles; t++) { ${fillWorkgroupMemory} k_start = k_start + ${tileSize}; workgroupBarrier(); for (var k: u32 = 0u; k < ${tileSize}; k++) { ${calcResult} } workgroupBarrier(); } ${calculateAlpha} let m = tile_row_start + local_id.y; let n = tile_col_start + local_id.x; ${(() => { if (c != null) { return `let cOffset = ${c.broadcastedIndicesToOffset("vec2(m, n)", output)}; value += ${output.type.value}(uniforms.beta) * ${c.getByOffset("cOffset")};`; } return ""; })()} if (m < uniforms.M && n < uniforms.N) { output[m * uniforms.N + n] = value; } }`; }; if (useShared) { return { name: "GemmShared", shaderCache: { hint: `${attributes.cacheKey}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: numTileN * numTileM }, programUniforms }), getShaderSource: getShaderSourceShared }; } return { name: "Gemm", shaderCache: { hint: `${attributes.cacheKey}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; parseGemmAttributes = (attributes) => { const transA = attributes.transA; const transB = attributes.transB; const alpha = attributes.alpha; const beta = attributes.beta; return { transA, transB, alpha, beta, cacheKey: `${attributes.transA};${attributes.transB};${attributes.alpha === 1}` }; }; gemm = (context, attributes) => { validateInputs15(context.inputs); context.compute(createGemmProgramInfo(context.inputs, attributes)); }; } }); // web/lib/wasm/jsep/webgpu/ops/grid-sample.ts var idxN, idxC, idxH, idxW, validateInputs16, gsGetCubicCoeffs, gsBicubicInterpolate, gsDenormalize, gsReflect, pixelAtGrid, computePixel, createGridSampleProgramInfo, gridSample, parseGridSampleAttributes; var init_grid_sample = __esm({ "web/lib/wasm/jsep/webgpu/ops/grid-sample.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); [idxN, idxC, idxH, idxW] = [0, 1, 2, 3]; validateInputs16 = (inputs) => { if (inputs[0].dims.length !== 4) { throw new Error("only 4-D tensor is supported."); } if (inputs[0].dims.length !== inputs[1].dims.length) { throw new Error("input dimensions must be equal to grid dimensions"); } if (inputs[0].dims.length - 2 !== inputs[1].dims[inputs[1].dims.length - 1]) { throw new Error(`last dimension of grid must be equal to ${inputs[0].dims.length - 2}`); } if (inputs[0].dims[0] !== inputs[1].dims[0]) { throw new Error("grid batch size must match input batch size"); } }; gsGetCubicCoeffs = ` fn gs_get_cubic_coeffs(x: f32) -> vec4 { let cubic_alpha = -0.75f; let x_abs = abs(x); var coeffs: vec4; coeffs[0] = (((cubic_alpha * (x_abs + 1) - 5 * cubic_alpha) * (x_abs + 1) + 8 * cubic_alpha) * (x_abs + 1) - 4 * cubic_alpha); coeffs[1] = (((cubic_alpha + 2) * x_abs - (cubic_alpha + 3)) * x_abs * x_abs + 1); coeffs[2] = (((cubic_alpha + 2) * (1 - x_abs) - (cubic_alpha + 3)) * (1 - x_abs) * (1 - x_abs) + 1); coeffs[3] = (((cubic_alpha * (2 - x_abs) - 5 * cubic_alpha) * (2 - x_abs) + 8 * cubic_alpha) * (2 - x_abs) - 4 * cubic_alpha); return coeffs; } `; gsBicubicInterpolate = (dataType) => ` fn gs_bicubic_interpolate(p: mat4x4<${dataType}>, x: f32, y: f32) -> ${dataType} { var v: vec4; var coeffs = gs_get_cubic_coeffs(x); for (var i = 0; i < 4; i++) { v[i] = coeffs[0] * p[i][0] + coeffs[1] * p[i][1] + coeffs[2] * p[i][2] + coeffs[3] * p[i][3]; } coeffs = gs_get_cubic_coeffs(y); let pixel = ${dataType}(coeffs[0] * v[0] + coeffs[1] * v[1] + coeffs[2] * v[2] + coeffs[3] * v[3]); return pixel; } `; gsDenormalize = (attributes) => ` fn gs_denormalize(n: f32, length: i32) -> f32 { ${attributes.alignCorners === 0 ? ` // alignCorners: false => [-1, 1] to [-0.5, length - 0.5] return ((n + 1.0) * f32(length) - 1.0) / 2.0; ` : ` // alignCorners: true => [-1, 1] to [0, length - 1] return (n + 1.0) / 2.0 * (f32(length - 1)); `} } `; gsReflect = (attributes) => ` ${attributes.paddingMode === "reflection" ? ` fn gs_reflect(x: i32, x_min: f32, x_max: f32) -> u32 { var dx = 0.0; var fx = f32(x); let range = x_max - x_min; if (fx < x_min) { dx = x_min - fx; let n = u32(dx / range); let r = dx - f32(n) * range; if (n % 2 == 0) { fx = x_min + r; } else { fx = x_max - r; } } else if (fx > x_max) { dx = fx - x_max; let n = u32(dx / range); let r = dx - f32(n) * range; if (n % 2 == 0) { fx = x_max - r; } else { fx = x_min + r; } } return u32(fx); }` : ""} `; pixelAtGrid = (input, dataType, attributes) => ` fn pixel_at_grid(r: i32, c: i32, H: i32, W: i32, batch: u32, channel: u32, border: vec4) -> ${dataType} { var pixel = ${dataType}(0); var indices = vec4(0); indices[${idxN}] = batch; indices[${idxC}] = channel;` + (() => { switch (attributes.paddingMode) { case "zeros": return ` if (r >= 0 && r < H && c >=0 && c < W) { indices[${idxH}] = u32(r); indices[${idxW}] = u32(c); } else { return ${dataType}(0); } `; case "border": return ` indices[${idxH}] = u32(clamp(r, 0, H - 1)); indices[${idxW}] = u32(clamp(c, 0, W - 1)); `; case "reflection": return ` indices[${idxH}] = gs_reflect(r, border[1], border[3]); indices[${idxW}] = gs_reflect(c, border[0], border[2]); `; default: throw new Error(`padding mode ${attributes.paddingMode} is not supported`); } })() + ` return ${input.getByIndices("indices")}; } `; computePixel = (output, dataType, attributes) => (() => { switch (attributes.mode) { case "nearest": return ` let result = pixel_at_grid(i32(round(y)), i32(round(x)), H_in, W_in, indices[${idxN}], indices[${idxC}], border); `; case "bilinear": return ` let x1 = i32(floor(x)); let y1 = i32(floor(y)); let x2 = x1 + 1; let y2 = y1 + 1; let p11 = pixel_at_grid(y1, x1, H_in, W_in, indices[${idxN}], indices[${idxC}], border); let p12 = pixel_at_grid(y1, x2, H_in, W_in, indices[${idxN}], indices[${idxC}], border); let p21 = pixel_at_grid(y2, x1, H_in, W_in, indices[${idxN}], indices[${idxC}], border); let p22 = pixel_at_grid(y2, x2, H_in, W_in, indices[${idxN}], indices[${idxC}], border); let dx2 = ${dataType}(f32(x2) - x); let dx1 = ${dataType}(x - f32(x1)); let dy2 = ${dataType}(f32(y2) - y); let dy1 = ${dataType}(y - f32(y1)); let result = dy2 * (dx2 * p11 + dx1 * p12) + dy1 * (dx2 * p21 + dx1 * p22); `; case "bicubic": return ` let x0 = i32(floor(x)) - 1; let y0 = i32(floor(y)) - 1; var p: mat4x4<${dataType}>; for (var h = 0; h < 4; h++) { for (var w = 0; w < 4; w++) { p[h][w] = pixel_at_grid(h + y0, w + x0, H_in, W_in, indices[${idxN}], indices[${idxC}], border); } } let dx = x - f32(x0 + 1); let dy = y - f32(y0 + 1); let result = gs_bicubic_interpolate(p, dx, dy); `; default: throw new Error(`mode ${attributes.mode} is not supported`); } })() + `${output.setByOffset("global_idx", "result")}`; createGridSampleProgramInfo = (inputs, attributes) => { const x = inputVariable("x", inputs[0].dataType, inputs[0].dims.length); const gridShape = [inputs[1].dims[0], inputs[1].dims[1], inputs[1].dims[2]]; const grid = inputVariable("grid", inputs[1].dataType, gridShape.length, 2); let outputShape = [inputs[0].dims[0], inputs[0].dims[1], inputs[1].dims[1], inputs[1].dims[2]]; if (attributes.format === "NHWC") { outputShape = [inputs[0].dims[0], inputs[1].dims[1], inputs[1].dims[2], inputs[0].dims[3]]; [idxN, idxC, idxH, idxW] = [0, 3, 1, 2]; } const output = outputVariable("output", inputs[0].dataType, outputShape.length); const dataType = x.type.value; const outputSize = ShapeUtil.size(outputShape); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, ...createTensorShapeVariables(inputs[0].dims, gridShape, outputShape) ]; const getShaderSource = (shaderHelper) => ` ${shaderHelper.registerUniform("output_size", "u32").declareVariables(x, grid, output)} ${gsGetCubicCoeffs} ${gsBicubicInterpolate(dataType)} ${gsDenormalize(attributes)} ${gsReflect(attributes)} ${pixelAtGrid(x, dataType, attributes)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let H_in = i32(uniforms.x_shape[${idxH}]); let W_in = i32(uniforms.x_shape[${idxW}]); ${attributes.alignCorners === 0 ? ` let x_min = -0.5; let x_max = f32(W_in) - 0.5; let y_min = -0.5; let y_max = f32(H_in) - 0.5; ` : ` let x_min = 0.0; let x_max = f32(W_in) - 1.0; let y_min = 0.0; let y_max = f32(H_in) - 1.0; `}; let border = vec4(x_min, y_min, x_max, y_max); let indices = ${output.offsetToIndices("global_idx")}; var grid_indices = vec3(indices[${idxN}], indices[${idxH}], indices[${idxW}]); let nxy = ${grid.getByIndices("grid_indices")}; var x = gs_denormalize(f32(nxy[0]), W_in); var y = gs_denormalize(f32(nxy[1]), H_in); ${computePixel(output, dataType, attributes)} }`; return { name: "GridSample", shaderCache: { hint: `${attributes.cacheKey}`, inputDependencies: ["type", "type"] }, getRunData: (inputs2) => { const outputSize2 = ShapeUtil.size(outputShape); return { outputs: [{ dims: outputShape, dataType: inputs2[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize2 / 64 /* workgroup size */ ) }, programUniforms }; }, getShaderSource }; }; gridSample = (context, attributes) => { validateInputs16(context.inputs); context.compute(createGridSampleProgramInfo(context.inputs, attributes)); }; parseGridSampleAttributes = (attributes) => createAttributeWithCacheKey({ alignCorners: attributes.align_corners, mode: attributes.mode, paddingMode: attributes.padding_mode, format: attributes.format }); } }); // web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts var getInput, validateInputs17, parseMultiHeadAttentionAttributes, weightTransposeAttribute2, addBiasTranspose, maybeTransposeToBNSHAndAddBias, multiHeadAttention; var init_multihead_attention = __esm({ "web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_types(); init_attention(); init_common(); init_transpose(); getInput = (inputs, i) => inputs.length > i && inputs[i].dims.length > 0 ? inputs[i] : void 0; validateInputs17 = (inputs, attributes) => { const query = inputs[0]; const key = getInput(inputs, 1); const value = getInput(inputs, 2); const bias = getInput(inputs, 3); const keyPaddingMask = getInput(inputs, 4); const attentionBias = getInput(inputs, 5); const pastKey = getInput(inputs, 6); const pastValue = getInput(inputs, 7); if (query.dims.length !== 3 && query.dims.length !== 5) { throw new Error("Input query is expected to have 3 or 5 dimensions"); } const batchSize = query.dims[0]; const sequenceLength = query.dims[1]; const hiddenSize = query.dims.length === 3 ? query.dims[2] : attributes.numHeads * query.dims[4]; let kvSequenceLength = sequenceLength; let pastSequenceLength = 0; let maxSequenceLength = 0; const headSize = Math.floor(hiddenSize / attributes.numHeads); if (pastKey && pastValue && ShapeUtil.size(pastKey.dims) && ShapeUtil.size(pastValue.dims)) { if (pastKey.dims.length !== 4) { throw new Error('Input "past_key" is expected to have 4 dimensions'); } if (pastKey.dims[0] !== batchSize || pastKey.dims[1] !== attributes.numHeads || pastKey.dims[3] !== headSize) { throw new Error('Input "past_key" shape (batch_size, num_heads, past_sequence_length, head_size)'); } if (pastValue.dims[0] !== batchSize || pastValue.dims[1] !== attributes.numHeads || pastValue.dims[3] !== headSize) { throw new Error('Input "past_value" shape (batch_size, num_heads, past_sequence_length, head_size)'); } if (pastKey.dims[2] !== pastValue.dims[2]) { throw new Error('Input "past_key" and "past_value" shall have same dim 2 (past_sequence_length)'); } if (pastValue.dims.length !== 4) { throw new Error('Input "past_value" is expected to have 4 dimensions'); } pastSequenceLength = pastKey.dims[2]; maxSequenceLength = pastKey.dims[2]; } else if (pastKey && ShapeUtil.size(pastKey.dims) || pastValue && ShapeUtil.size(pastValue.dims)) { throw new Error('Input "past_key" and "past_value" shall be both present or both absent'); } let qkvFormat; if (key && ShapeUtil.size(key.dims) > 0) { if (query.dims.length !== 3) { throw new Error('Input "query" is expected to have 3 dimensions when key is given'); } if (key.dims.length < 3 || key.dims.length > 5) { throw new Error('Input "key" is expected to have 3, 4, or 5 dimensions'); } if (query.dims[0] !== key.dims[0]) { throw new Error('Input "query" and "key" shall have same dim 0 (batch size)'); } if (key.dims.length === 3) { if (key.dims[2] !== query.dims[2]) { throw new Error('Input "query" and "key" shall have same dim 2 (hidden_size)'); } qkvFormat = 2 /* qkvBSNH */; kvSequenceLength = key.dims[1]; } else if (key.dims.length === 5) { if (key.dims[2] !== attributes.numHeads || key.dims[3] !== 2 || key.dims[4] !== headSize) { throw new Error('Expect "key" shape (batch_size, kv_sequence_length, num_heads, 2, head_size) for packed kv'); } if (value) { throw new Error('Expect "value" be none when "key" has packed kv format.'); } qkvFormat = 5 /* qKvBSNHxBSN2H */; kvSequenceLength = key.dims[1]; } else { if (key.dims[1] !== attributes.numHeads || key.dims[3] !== headSize) { throw new Error('Expect "key" shape (batch_size, num_heads, kv_sequence_length, head_size) for past_key'); } qkvFormat = 0 /* unknown */; kvSequenceLength = key.dims[2]; } } else { if (query.dims.length !== 5) { throw new Error('Input "query" is expected to have 5 dimensions when key is empty'); } if (query.dims[2] !== attributes.numHeads || query.dims[3] !== 3) { throw new Error('Expect "query" shape (batch_size, kv_sequence_length, num_heads, 3, head_size) for packed kv'); } qkvFormat = 3 /* qkvBSN3H */; } if (bias && ShapeUtil.size(bias.dims) > 0) { if (bias.dims.length !== 1) { throw new Error('Input "bias" is expected to have 1 dimension'); } if (key) { if (key.dims.length === 5 && key.dims[3] === 2) { throw new Error("bias is not allowed for packed kv."); } } } const totalSequenceLength = pastSequenceLength + kvSequenceLength; let maskType = 0 /* none */; if (keyPaddingMask && ShapeUtil.size(keyPaddingMask.dims) > 0) { maskType = 8 /* maskUnknown */; const maskDims = keyPaddingMask.dims; if (maskDims.length === 1) { if (maskDims[0] === batchSize) { maskType = 1 /* mask1dKeySeqLen */; } else if (maskDims[0] === 3 * batchSize + 2) { maskType = 3 /* mask1DKeySeqLenStart */; } } else if (maskDims.length === 2 && maskDims[0] === batchSize && maskDims[1] === totalSequenceLength) { maskType = 5 /* mask2dKeyPadding */; } if (maskType === 8 /* maskUnknown */) { throw new Error('Input "key_padding_mask" shape shall be (batch_size) or (batch_size, total_sequence_length)'); } throw new Error("Mask not supported"); } let passPastInKv = false; let vHiddenSize = hiddenSize; if (value && ShapeUtil.size(value.dims) > 0) { if (value.dims.length !== 3 && value.dims.length !== 4) { throw new Error('Input "value" is expected to have 3 or 4 dimensions'); } if (query.dims[0] !== value.dims[0]) { throw new Error('Input "query" and "value" shall have same dim 0 (batch_size)'); } if (value.dims.length === 3) { if (kvSequenceLength !== value.dims[1]) { throw new Error('Input "key" and "value" shall have the same dim 1 (kv_sequence_length)'); } vHiddenSize = value.dims[2]; } else { if (kvSequenceLength !== value.dims[2]) { throw new Error('Input "key" and "value" shall have the same dim 2 (kv_sequence_length)'); } vHiddenSize = value.dims[1] * value.dims[3]; passPastInKv = true; } } const broadcastResPosBias = false; if (keyPaddingMask && ShapeUtil.size(keyPaddingMask.dims) > 0) { throw new Error("Key padding mask is not supported"); } if (attentionBias && ShapeUtil.size(attentionBias.dims) > 0) { if (attentionBias.dims.length !== 4) { throw new Error('Input "attention_bias" is expected to have 4 dimensions'); } if (attentionBias.dims[0] !== batchSize || attentionBias.dims[1] !== attributes.numHeads || attentionBias.dims[2] !== sequenceLength || attentionBias.dims[3] !== totalSequenceLength) { throw new Error('Expect "attention_bias" shape (batch_size, num_heads, sequence_length, total_sequence_length)'); } } return { batchSize, sequenceLength, pastSequenceLength, kvSequenceLength, totalSequenceLength, maxSequenceLength, inputHiddenSize: 0, hiddenSize, vHiddenSize, headSize, vHeadSize: Math.floor(vHiddenSize / attributes.numHeads), numHeads: attributes.numHeads, isUnidirectional: false, pastPresentShareBuffer: false, maskFilterValue: attributes.maskFilterValue, maskType, scale: attributes.scale, broadcastResPosBias, passPastInKv, qkvFormat }; }; parseMultiHeadAttentionAttributes = (attributes) => createAttributeWithCacheKey({ ...attributes }); weightTransposeAttribute2 = createAttributeWithCacheKey({ perm: [0, 2, 1, 3] }); addBiasTranspose = (context, qkv, bias, batchSize, sequenceLength, hiddenSize, biasOffset) => { const outputShape = [batchSize, sequenceLength, hiddenSize]; const outputSize = ShapeUtil.size(outputShape); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: biasOffset }, { type: 12 /* uint32 */, data: hiddenSize } ]; const getShaderSource = (shaderHelper) => { const output = outputVariable("qkv_with_bias", qkv.dataType, outputShape); const qkvInput = inputVariable("qkv", qkv.dataType, outputShape); const biasInput = inputVariable("bias", bias.dataType, outputShape); const uniforms = [ { name: "output_size", type: "u32" }, { name: "bias_offset", type: "u32" }, { name: "hidden_size", type: "u32" } ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(qkvInput, biasInput, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let bias_offset_idx = (global_idx % uniforms.hidden_size) + uniforms.bias_offset; qkv_with_bias[global_idx] = qkv[global_idx] + bias[bias_offset_idx]; }`; }; return context.compute( { name: "MultiHeadAttentionAddBias", shaderCache: { inputDependencies: ["type", "type"] }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: qkv.dataType, gpuDataType: 0 /* default */ }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }, { inputs: [qkv, bias], outputs: [-1] } )[0]; }; maybeTransposeToBNSHAndAddBias = (context, batchSize, numHeads, sequenceLength, headSize, input, bias, biasOffset) => { let reshapedInput = input; if (!(bias && ShapeUtil.size(bias.dims) > 0)) { if (input.dims.length === 3) { reshapedInput = input.reshape([batchSize, sequenceLength, numHeads, headSize]); } if (numHeads === 1 || sequenceLength === 1) { return reshapedInput; } return context.compute(createTransposeProgramInfo(reshapedInput, weightTransposeAttribute2.perm), { inputs: [reshapedInput], outputs: [-1] })[0]; } else { if (sequenceLength === 1) { throw new Error("AddBiasReshape is not implemented. Please export your model with packed QKV or KV"); } else { reshapedInput = addBiasTranspose( context, input, bias, batchSize, sequenceLength, numHeads * headSize, biasOffset ); reshapedInput = reshapedInput.reshape([batchSize, sequenceLength, numHeads, headSize]); if (numHeads === 1 || sequenceLength === 1) { return reshapedInput; } return context.compute(createTransposeProgramInfo(reshapedInput, weightTransposeAttribute2.perm), { inputs: [reshapedInput], outputs: [-1] })[0]; } } }; multiHeadAttention = (context, attributes) => { const params = validateInputs17(context.inputs, attributes); const query = context.inputs[0]; const key = getInput(context.inputs, 1); const value = getInput(context.inputs, 2); const bias = getInput(context.inputs, 3); const keyPaddingMask = getInput(context.inputs, 4); const attentionBias = getInput(context.inputs, 5); const pastKey = getInput(context.inputs, 6); const pastValue = getInput(context.inputs, 7); if (query.dims.length === 5) { throw new Error("Packed QKV is not implemented"); } if (key?.dims.length === 5) { throw new Error("Packed KV is not implemented"); } const kvBNSH = key && value && key.dims.length === 4 && value.dims.length === 4; const Q = maybeTransposeToBNSHAndAddBias( context, params.batchSize, params.numHeads, params.sequenceLength, params.headSize, query, bias, 0 ); if (kvBNSH) { return applyAttention(context, Q, key, value, keyPaddingMask, void 0, pastKey, pastValue, attentionBias, params); } if (!key || !value) { throw new Error("key and value must be provided"); } const K = maybeTransposeToBNSHAndAddBias( context, params.batchSize, params.numHeads, params.kvSequenceLength, params.headSize, key, bias, params.hiddenSize ); const V = maybeTransposeToBNSHAndAddBias( context, params.batchSize, params.numHeads, params.kvSequenceLength, params.vHeadSize, value, bias, 2 * params.hiddenSize ); applyAttention(context, Q, K, V, keyPaddingMask, void 0, pastKey, pastValue, attentionBias, params); }; } }); // web/lib/wasm/jsep/webgpu/ops/split.ts var validateInputs18, createSplitAttributesFromInputs, calculateOutputIndexImpl, writeBufferDataImpl, createSplitProgramInfo, split, parseSplitAttributes; var init_split = __esm({ "web/lib/wasm/jsep/webgpu/ops/split.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs18 = (inputs) => { if (!inputs || inputs.length < 1) { throw new Error("too few inputs"); } }; createSplitAttributesFromInputs = (inputs, attributes) => { const splitSizes = []; let numOutputs = attributes.numOutputs; if (inputs[1].dims[0] > 0) { inputs[1].getBigInt64Array().forEach((v) => splitSizes.push(Number(v))); numOutputs = splitSizes.length; } return createAttributeWithCacheKey({ numOutputs, axis: attributes.axis, splitSizes }); }; calculateOutputIndexImpl = (numberOfTensors) => ` fn calculateOutputIndex(index: u32) -> u32 { for (var i: u32 = 0u; i < ${numberOfTensors}u; i += 1u ) { if (index < ${getElementAt("uniforms.size_in_split_axis", "i", numberOfTensors)}) { return i; } } return ${numberOfTensors}u; }`; writeBufferDataImpl = (outputs) => { const numberOfTensors = outputs.length; const codeLines = []; for (let i = 0; i < numberOfTensors; ++i) { const returnSnippet = outputs[i].setByIndices("indices", "input[global_idx]"); if (numberOfTensors === 1) { codeLines.push(returnSnippet); } else if (i === 0) { codeLines.push(`if (output_number == ${i}u) { ${returnSnippet} }`); } else if (i === numberOfTensors - 1) { codeLines.push(`else { ${returnSnippet} }`); } else { codeLines.push(`else if (output_number == ${i}) { ${returnSnippet} }`); } } return ` fn writeBufferData(output_number: u32, indices: ${outputs[0].type.indices}, global_idx: u32) { ${codeLines.join("\n")} }`; }; createSplitProgramInfo = (inputs, attributes) => { const inputShape = inputs[0].dims; const inputSize = ShapeUtil.size(inputShape); const dataType = inputs[0].dataType; const axis = ShapeUtil.normalizeAxis(attributes.axis, inputShape.length); const outputs = new Array(attributes.numOutputs); const input = inputVariable("input", dataType, inputShape.length); const sizeInSplitAxis = new Array(attributes.numOutputs); const outputsTensorInfo = []; const outputShapes = []; let previousSum = 0; const programUniforms = [{ type: 12 /* uint32 */, data: inputSize }]; for (let i = 0; i < attributes.numOutputs; i++) { previousSum += attributes.splitSizes[i]; sizeInSplitAxis[i] = previousSum; const outputShape = inputShape.slice(); outputShape[axis] = attributes.splitSizes[i]; outputShapes.push(outputShape); outputs[i] = outputVariable(`output${i}`, dataType, outputShape.length); outputsTensorInfo.push({ dims: outputShapes[i], dataType: inputs[0].dataType }); } programUniforms.push( { type: 12 /* uint32 */, data: sizeInSplitAxis }, ...createTensorShapeVariables(inputShape, ...outputShapes) ); const getShaderSource = (shaderHelper) => ` ${shaderHelper.registerUniform("input_size", "u32").registerUniform("size_in_split_axis", "u32", sizeInSplitAxis.length).declareVariables(input, ...outputs)} ${calculateOutputIndexImpl(sizeInSplitAxis.length)} ${writeBufferDataImpl(outputs)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.input_size")} var indices = ${input.offsetToIndices("global_idx")}; var index = ${input.indicesGet("indices", axis)}; let output_number = calculateOutputIndex(index); if (output_number != 0) { index -= ${getElementAt("uniforms.size_in_split_axis", "output_number - 1u", sizeInSplitAxis.length)}; ${input.indicesSet("indices", axis, "index")}; } writeBufferData(output_number, indices, global_idx); }`; return { name: "Split", shaderCache: { hint: attributes.cacheKey, inputDependencies: ["rank"] }, getShaderSource, getRunData: () => ({ outputs: outputsTensorInfo, dispatchGroup: { x: Math.ceil( inputSize / 64 /* workgroup size */ ) }, programUniforms }) }; }; split = (context, attributes) => { validateInputs18(context.inputs); const updatedAttributes = context.inputs.length === 1 ? attributes : createSplitAttributesFromInputs(context.inputs, attributes); context.compute(createSplitProgramInfo(context.inputs, updatedAttributes), { inputs: [0] }); }; parseSplitAttributes = (attributes) => { const axis = attributes.axis; const splitSizes = attributes.splitSizes; const numOutputs = attributes.numOutputs < 0 ? splitSizes.length : attributes.numOutputs; if (numOutputs !== splitSizes.length) { throw new Error("numOutputs and splitSizes length must be equal"); } return createAttributeWithCacheKey({ axis, numOutputs, splitSizes }); }; } }); // web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts var validateInputs19, createRotaryEmbeddingProgramInfo, rotaryEmbedding; var init_rotary_embedding = __esm({ "web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs19 = (inputs, attributes) => { const [input, positionIds, cosCache, sinCache] = inputs; const { numHeads, rotaryEmbeddingDim } = attributes; if (input.dims.length !== 3 && input.dims.length !== 4) { throw new Error(`Input 'x' is expected to have 3 or 4 dimensions, got ${input.dims.length}`); } if (!ShapeUtil.areEqual(positionIds.dims, []) && !ShapeUtil.areEqual(positionIds.dims, [1]) && positionIds.dims.length !== 2) { throw new Error(`Input 'position_ids' is expected to have 0, 1, or 2 dimensions, got ${positionIds.dims.length}`); } if (cosCache.dims.length !== 2) { throw new Error(`Input 'cos_cache' is expected to have 2 dimensions, got ${cosCache.dims.length}`); } if (sinCache.dims.length !== 2) { throw new Error(`Input 'sin_cache' is expected to have 2 dimensions, got ${sinCache.dims.length}`); } if (!ShapeUtil.areEqual(cosCache.dims, sinCache.dims)) { throw new Error("Inputs 'cos_cache' and 'sin_cache' are expected to have the same shape"); } if (rotaryEmbeddingDim > 0 && numHeads === 0) { throw new Error("num_heads must be provided if rotary_embedding_dim is specified"); } const batchSize = input.dims[0]; const sequenceLength = input.dims[input.dims.length - 2]; const maxSequenceLength = cosCache.dims[0]; const hiddenSize = ShapeUtil.sizeFromDimension(input.dims, 1) / sequenceLength; const headSize = rotaryEmbeddingDim === 0 ? cosCache.dims[1] * 2 : hiddenSize / numHeads; if (rotaryEmbeddingDim > headSize) { throw new Error("rotary_embedding_dim must be less than or equal to head_size"); } if (positionIds.dims.length === 2) { if (batchSize !== positionIds.dims[0]) { throw new Error(`Input 'position_ids' dimension 0 should be of size batch_size, got ${positionIds.dims[0]}`); } if (sequenceLength !== positionIds.dims[1]) { throw new Error(`Input 'position_ids' dimension 1 should be of size sequence_length, got ${positionIds.dims[1]}`); } } if (sequenceLength > maxSequenceLength) { throw new Error("Updating cos_cache and sin_cache in RotaryEmbedding is not currently supported"); } if (headSize / 2 !== cosCache.dims[1] && rotaryEmbeddingDim / 2 !== cosCache.dims[1]) { throw new Error( `Input 'cos_cache' dimension 1 should be same as head_size / 2 or rotary_embedding_dim / 2, got ${cosCache.dims[1]}` ); } }; createRotaryEmbeddingProgramInfo = (inputs, attributes) => { const { interleaved, numHeads, rotaryEmbeddingDim, scale } = attributes; const batchSize = inputs[0].dims[0]; const batchStride = ShapeUtil.sizeFromDimension(inputs[0].dims, 1); const sequenceLength = inputs[0].dims[inputs[0].dims.length - 2]; const hiddenSize = batchStride / sequenceLength; const halfRotaryEmbeddingDim = inputs[2].dims[1]; const headSize = rotaryEmbeddingDim === 0 ? halfRotaryEmbeddingDim * 2 : hiddenSize / numHeads; const globalShape = new Array( batchSize, sequenceLength, hiddenSize / headSize, headSize - halfRotaryEmbeddingDim ); const globalStrides = ShapeUtil.computeStrides(globalShape); const programUniforms = [ { type: 1 /* float */, data: scale }, { type: 12 /* uint32 */, data: globalShape }, { type: 12 /* uint32 */, data: globalStrides }, // strides for addressing the input/output tensor, in permutated order to align with the unfolded global index, // i.e. BSNH ...inputs[0].dims.length === 3 ? new Array({ type: 12 /* uint32 */, data: [batchStride, hiddenSize, headSize, 1] }) : [], ...inputs[0].dims.length === 4 ? new Array({ type: 12 /* uint32 */, data: [batchStride, headSize, sequenceLength * headSize, 1] }) : [], ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims, inputs[2].dims, inputs[3].dims, inputs[0].dims) ]; const getShaderSource = (shaderHelper) => { const input = inputVariable("input", inputs[0].dataType, inputs[0].dims.length); const positionIds = inputVariable("position_ids", inputs[1].dataType, inputs[1].dims.length); const cosCache = inputVariable("cos_cache", inputs[2].dataType, inputs[2].dims.length); const sinCache = inputVariable("sin_cache", inputs[3].dataType, inputs[3].dims.length); const output = outputVariable("output", inputs[0].dataType, inputs[0].dims.length); shaderHelper.registerUniforms([ { name: "scale", type: "f32" }, { name: "global_shape", type: "u32", length: globalShape.length }, { name: "global_strides", type: "u32", length: globalStrides.length }, { name: "input_output_strides", type: "u32", length: globalStrides.length } ]); return ` ${shaderHelper.declareVariables(input, positionIds, cosCache, sinCache, output)} ${shaderHelper.mainStart(WORKGROUP_SIZE)} let half_rotary_emb_dim = uniforms.${cosCache.name}_shape[1]; let bsnh = global_idx / uniforms.global_strides % uniforms.global_shape; let size = uniforms.global_shape[0] * uniforms.global_strides[0]; ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("size")} if (bsnh[3] < half_rotary_emb_dim) { let position_ids_idx = ${positionIds.broadcastedIndicesToOffset("bsnh.xy", outputVariable("", positionIds.type.tensor, 2))}; let position_id = u32(${positionIds.getByOffset("position_ids_idx")}) + select(0, bsnh[1], position_ids_idx == 0); let i = dot(bsnh, uniforms.input_output_strides) + select(0, bsnh[3], ${interleaved}); let j = i + select(half_rotary_emb_dim, 1, ${interleaved}); let re = ${input.getByOffset("i")} * ${cosCache.get("position_id", "bsnh[3]")} - ${input.getByOffset("j")} * ${sinCache.get("position_id", "bsnh[3]")}; ${output.setByOffset("i", "re")} let im = ${input.getByOffset("i")} * ${sinCache.get("position_id", "bsnh[3]")} + ${input.getByOffset("j")} * ${cosCache.get("position_id", "bsnh[3]")}; ${output.setByOffset("j", "im")} } else { let k = dot(bsnh, uniforms.input_output_strides) + half_rotary_emb_dim; ${output.setByOffset("k", input.getByOffset("k"))} } }`; }; return { name: "RotaryEmbedding", shaderCache: { hint: createAttributeWithCacheKey({ interleaved }).cacheKey, inputDependencies: ["rank", "rank", "rank", "rank"] }, getShaderSource, getRunData: () => ({ outputs: [{ dims: inputs[0].dims, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil(ShapeUtil.size(globalShape) / WORKGROUP_SIZE) }, programUniforms }) }; }; rotaryEmbedding = (context, attributes) => { validateInputs19(context.inputs, attributes); context.compute(createRotaryEmbeddingProgramInfo(context.inputs, attributes)); }; } }); // web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts var validateInputs20, weightTransposeAttribute3, maybeTransposeToBNSH, generatePositionIdsProgramInfo, groupQueryAttention; var init_group_query_attention = __esm({ "web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts"() { "use strict"; init_attribute_with_cache_key(); init_wasm_common(); init_attention(); init_multihead_attention(); init_split(); init_transpose(); init_rotary_embedding(); init_common(); validateInputs20 = (inputs, attributes) => { if (attributes.doRotary && inputs.length <= 7) { throw new Error("cos_cache and sin_cache inputs are required if do_rotary is specified"); } const query = inputs[0]; const key = inputs[1]; const value = inputs[2]; const pastKey = inputs[3]; const pastValue = inputs[4]; if (attributes.doRotary !== 0 && inputs.length <= 7) { throw new Error("cos_cast and sin_cache are expected if do_rotary attribute is non-zero"); } if (attributes.localWindowSize !== -1) { throw new Error("Local attention is not supported"); } if (attributes.softcap !== 0) { throw new Error("Softcap is not supported"); } if (attributes.rotaryInterleaved !== 0) { throw new Error("Rotary interleaved is not supported"); } if (attributes.smoothSoftmax) { throw new Error("Smooth softmax is not supported"); } if (query.dims.length !== 3 && query.dims.length !== 5) { throw new Error("Input query is expected to have 3 or 5 dimensions"); } const dmmhaPacking = false; const batchSize = query.dims[0]; const sequenceLength = query.dims[1]; let hiddenSize = query.dims.length === 3 ? dmmhaPacking ? query.dims[2] / 3 : query.dims[2] : attributes.numHeads * query.dims[4]; let kvSequenceLength = sequenceLength; let pastSequenceLength = 0; const packedQKV = !key || key.dims.length === 0; const headSize = !packedQKV ? Math.floor(hiddenSize / attributes.numHeads) : Math.floor(hiddenSize / (attributes.numHeads + 2 * attributes.kvNumHeads)); if (packedQKV) { hiddenSize = headSize * attributes.numHeads; } const hasPastKey = pastKey && pastKey.dims.length !== 0; const hasPastValue = pastValue && pastValue.dims.length !== 0; const isPastkvBSNH = hasPastKey && pastKey.dims.length === 4 && pastKey.dims[0] === batchSize && pastKey.dims[1] !== attributes.kvNumHeads && pastKey.dims[2] === attributes.kvNumHeads && pastKey.dims[3] === headSize; if (isPastkvBSNH) { throw new Error("BSNH pastKey/pastValue is not supported"); } if (hasPastKey && hasPastValue) { if (pastKey.dims.length !== 4) { throw new Error('Input "past_key" is expected to have 4 dimensions'); } if (pastValue.dims.length !== 4) { throw new Error('Input "past_value" is expected to have 4 dimensions'); } pastSequenceLength = pastKey.dims[2]; } else if (hasPastKey || hasPastValue) { throw new Error('Input "past_key" and "past_value" shall be both present or both absent'); } let qkvFormat = 1 /* qkvBNSH */; if (key && key.dims.length > 0) { if (query.dims.length !== 3) { throw new Error('Input "query" is expected to have 3 dimensions when key is given'); } if (key.dims.length < 3 || key.dims.length > 5) { throw new Error('Input "key" is expected to have 3, 4, or 5 dimensions'); } if (query.dims[0] !== key.dims[0]) { throw new Error('Input "query" and "key" shall have same dim 0 (batch size)'); } if (key.dims.length === 3) { if (query.dims[2] % key.dims[2] !== 0) { throw new Error('Dimension 2 of "query" should be a multiple of "key"'); } kvSequenceLength = key.dims[1]; } else if (key.dims.length === 5) { if (key.dims[2] !== attributes.numHeads || key.dims[3] !== 2 || key.dims[4] !== headSize) { throw new Error('Expect "key" shape (batch_size, kv_sequence_length, num_heads, 2, head_size) for packed kv'); } if (value) { throw new Error('Expect "value" be none when "key" has packed kv format.'); } kvSequenceLength = key.dims[1]; } else { if (key.dims[1] !== attributes.numHeads || key.dims[3] !== headSize) { throw new Error('Expect "key" shape (batch_size, num_heads, kv_sequence_length, head_size) for past_key'); } kvSequenceLength = key.dims[2]; } } else { if (query.dims.length !== 3 && query.dims.length !== 5) { throw new Error('Input "query" is expected to have 3 or 5 dimensions when key is empty'); } if (query.dims.length === 5 && (query.dims[2] !== attributes.numHeads || query.dims[3] !== 3)) { throw new Error('Expect "query" shape (batch_size, kv_sequence_length, num_heads, 3, head_size) for packed kv'); } qkvFormat = 3 /* qkvBSN3H */; } const maskType = 0 /* none */; let passPastInKv = false; let vHiddenSize = attributes.kvNumHeads ? headSize * attributes.kvNumHeads : hiddenSize; if (value && value.dims.length > 0) { if (value.dims.length !== 3 && value.dims.length !== 4) { throw new Error('Input "value" is expected to have 3 or 4 dimensions'); } if (query.dims[0] !== value.dims[0]) { throw new Error('Input "query" and "value" shall have same dim 0 (batch_size)'); } if (value.dims.length === 3) { if (kvSequenceLength !== value.dims[1]) { throw new Error('Input "key" and "value" shall have the same dim 1 (kv_sequence_length)'); } vHiddenSize = value.dims[2]; } else { if (kvSequenceLength !== value.dims[2]) { throw new Error('Input "past_key" and "past_value" shall have the same dim 2 (kv_sequence_length)'); } vHiddenSize = value.dims[1] * value.dims[3]; passPastInKv = true; } } const seqlLens = inputs.length > 4 ? inputs[5] : void 0; if (seqlLens) { if (seqlLens.dims.length === 0) { throw new Error("seqlens_k must be at least 1D, got scalar."); } const seqlLenSize = seqlLens.dims.reduce((a, b) => a * b, 1); if (seqlLenSize !== batchSize) { throw new Error(`seqlens_k must have batch_size (${batchSize}) elements, got ${seqlLenSize}.`); } for (let i = 0; i < seqlLens.dims.length; i++) { if (seqlLens.dims[i] !== 1 && seqlLens.dims[i] !== batchSize) { throw new Error( `seqlens_k has unexpected shape. Each dimension must be 1 or batch_size (${batchSize}), got dims[${i}] = ${seqlLens.dims[i]}.` ); } } } const totalSequenceLength = -1; const maxSequenceLength = -1; const broadcastResPosBias = false; return { batchSize, sequenceLength, pastSequenceLength, kvSequenceLength, totalSequenceLength, maxSequenceLength, inputHiddenSize: 0, hiddenSize, vHiddenSize, headSize, vHeadSize: Math.floor(vHiddenSize / attributes.kvNumHeads), numHeads: attributes.numHeads, kvNumHeads: attributes.kvNumHeads, nReps: attributes.numHeads / attributes.kvNumHeads, pastPresentShareBuffer: false, maskType, scale: attributes.scale, broadcastResPosBias, passPastInKv, qkvFormat }; }; weightTransposeAttribute3 = createAttributeWithCacheKey({ perm: [0, 2, 1, 3] }); maybeTransposeToBNSH = (context, input, params) => { let reshapedInput = input; const numHeads = params.kvNumHeads; if (input.dims.length === 3 && params.kvSequenceLength !== 0) { reshapedInput = input.reshape([params.batchSize, params.kvSequenceLength, numHeads, params.headSize]); reshapedInput = context.compute(createTransposeProgramInfo(reshapedInput, weightTransposeAttribute3.perm), { inputs: [reshapedInput], outputs: [-1] })[0]; } return reshapedInput; }; generatePositionIdsProgramInfo = (batchSize, sequenceLength, seqLens, totalSeqLen) => { const outputDataType = 7 /* int64 */; const inputDependencies = ["type", "type"]; const outputShape = [batchSize * sequenceLength]; const outputSize = batchSize * sequenceLength; const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: sequenceLength }, { type: 12 /* uint32 */, data: batchSize } ]; const getShaderSource = (shaderHelper) => { const seqLensInputHelper = inputVariable("seq_lens", seqLens.dataType, seqLens.dims); const totalSeqLenInputHelper = inputVariable("total_seq_lens", totalSeqLen.dataType, totalSeqLen.dims); const positionIdsHelper = outputVariable("pos_ids", outputDataType, outputShape); const uniforms = [ { name: "output_size", type: "u32" }, { name: "sequence_length", type: "u32" }, { name: "batch_size", type: "u32" } ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(seqLensInputHelper, totalSeqLenInputHelper, positionIdsHelper)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let total_sequence_length = u32(${totalSeqLenInputHelper.getByOffset("0")}); let is_subsequent_prompt = uniforms.sequence_length > 1 && uniforms.sequence_length != total_sequence_length; let is_first_prompt = !is_subsequent_prompt && uniforms.sequence_length == total_sequence_length; let batch_idx = global_idx / uniforms.sequence_length; let sequence_idx = i32(global_idx % uniforms.sequence_length); var pos_id: i32 = 0; let seqlen = ${seqLensInputHelper.getByOffset("batch_idx")}; let total_seqlen = seqlen + 1; if (is_first_prompt) { if (sequence_idx < total_seqlen) { pos_id = sequence_idx; } else { pos_id = 1; } ${positionIdsHelper.setByOffset("global_idx", "pos_id")} } else if (is_subsequent_prompt) { let past_seqlen = total_seqlen - i32(uniforms.sequence_length); if (past_seqlen + sequence_idx < total_seqlen) { pos_id = past_seqlen + sequence_idx; } else { pos_id = 1; } ${positionIdsHelper.setByOffset("global_idx", "pos_id")} } else if (global_idx < uniforms.batch_size) { ${positionIdsHelper.setByOffset("global_idx", "seqlen")} }; } `; }; return { name: "GeneratePositionIds", shaderCache: { hint: `${batchSize};${sequenceLength}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: outputDataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; groupQueryAttention = (context, attributes) => { const params = validateInputs20(context.inputs, attributes); if (context.inputs[0].dims.length === 5) { throw new Error("Packed QKV is not implemented"); } if (context.inputs[1]?.dims.length === 5) { throw new Error("Packed KV is not implemented"); } const q = context.inputs[0]; const k = context.inputs[1] && context.inputs[1].dims.length > 0 ? context.inputs[1] : void 0; const v = context.inputs[2] && context.inputs[2].dims.length > 0 ? context.inputs[2] : void 0; const pastKey = context.inputs[3] && context.inputs[3].dims.length !== 0 ? context.inputs[3] : void 0; const pastValue = context.inputs[4] && context.inputs[4].dims.length !== 0 ? context.inputs[4] : void 0; const seqLens = context.inputs.length > 4 ? context.inputs[5] : void 0; const totalSequenceLengthInput = context.inputs.length > 5 ? context.inputs[6] : void 0; const kvNumHeads = params.kvNumHeads ? params.kvNumHeads : params.numHeads; const splitAttributes = createAttributeWithCacheKey({ axis: 2, numOutputs: 3, splitSizes: [params.numHeads * params.headSize, kvNumHeads * params.headSize, kvNumHeads * params.headSize] }); const [query, key, value] = !k && !v ? context.compute(createSplitProgramInfo([q], splitAttributes), { inputs: [q], outputs: [-1, -1, -1] }) : [q, k, v]; let qRotary; let kRotary; if (attributes.doRotary) { const posIds = context.compute( generatePositionIdsProgramInfo(params.batchSize, params.sequenceLength, seqLens, totalSequenceLengthInput), { inputs: [seqLens, totalSequenceLengthInput], outputs: [-1] } )[0]; const cosCache = context.inputs[7]; const sinCache = context.inputs[8]; const qRotaryEmbeddingAttributes = createAttributeWithCacheKey({ interleaved: attributes.rotaryInterleaved !== 0, numHeads: params.numHeads, rotaryEmbeddingDim: 0, scale: attributes.scale }); const inputs = [query, posIds, cosCache, sinCache]; const outputs = [-1]; qRotary = context.compute(createRotaryEmbeddingProgramInfo(inputs, qRotaryEmbeddingAttributes), { inputs, outputs })[0]; inputs.splice(0, 1, key); const kRotaryEmbeddingAttributes = createAttributeWithCacheKey({ interleaved: attributes.rotaryInterleaved !== 0, numHeads: params.kvNumHeads, rotaryEmbeddingDim: 0, scale: attributes.scale }); kRotary = context.compute(createRotaryEmbeddingProgramInfo(inputs, kRotaryEmbeddingAttributes), { inputs, outputs })[0]; } const Q = maybeTransposeToBNSHAndAddBias( context, params.batchSize, params.numHeads, params.sequenceLength, params.headSize, attributes.doRotary ? qRotary : query, void 0, 0 ); const K = maybeTransposeToBNSH(context, attributes.doRotary ? kRotary : key, params); const V = maybeTransposeToBNSH(context, value, params); applyAttention( context, Q, K, V, void 0, void 0, pastKey, pastValue, void 0, params, seqLens, totalSequenceLengthInput ); }; } }); // web/lib/wasm/jsep/webgpu/ops/instance-norm.ts var computeChannelScaleShift, createInstanceNormProgramInfo, createInstanceNormNHWCProgramInfo, instanceNorm; var init_instance_norm = __esm({ "web/lib/wasm/jsep/webgpu/ops/instance-norm.ts"() { "use strict"; init_wasm_common(); init_util(); init_transpose(); init_common(); computeChannelScaleShift = (context, input, scale, bias, n, h, c, epsilon) => { const components = getMaxComponents(h); const f32Type = components === 1 ? "f32" : `vec${components}f`; const wgType = components === 1 ? "vec2f" : `mat2x${components}f`; const unitsOfWork = n * c; let workgroupSize = 64; if (unitsOfWork === 1) { workgroupSize = 256; } const inputShape = [n, c, h / components]; const outputShape = [n, c, 2]; const inputDependencies = ["rank", "type", "type"]; const programUniforms = []; programUniforms.push(...createTensorShapeVariables(inputShape, outputShape)); const getShaderSource = (shaderHelper) => { const x = inputVariable("x", input.dataType, 3, components); const s = inputVariable("scale", scale.dataType, scale.dims); const b = inputVariable("bias", bias.dataType, bias.dims); const output = outputVariable("output", 1 /* float */, 3, 2); const variables = [x, s, b, output]; return ` var workgroup_shared : array<${wgType}, ${workgroupSize}>; const workgroup_size = ${workgroupSize}u; ${shaderHelper.declareVariables(...variables)} ${shaderHelper.mainStart(workgroupSize)} let batch = workgroup_index / uniforms.x_shape[1]; let channel = workgroup_index % uniforms.x_shape[1]; let hight = uniforms.x_shape[2]; // initialize workgroup memory var sum = ${f32Type}(0); var squared_sum = ${f32Type}(0); for (var h = local_idx; h < hight; h += workgroup_size) { let value = ${f32Type}(${x.get("batch", "channel", "h")}); sum += value; squared_sum += value * value; } workgroup_shared[local_idx] = ${wgType}(sum, squared_sum); workgroupBarrier(); for (var currSize = workgroup_size >> 1; currSize > 0; currSize = currSize >> 1) { if (local_idx < currSize) { workgroup_shared[local_idx] = workgroup_shared[local_idx] + workgroup_shared[local_idx + currSize]; } workgroupBarrier(); } if (local_idx == 0) { let sum_final = ${sumVector("workgroup_shared[0][0]", components)} / f32(hight * ${components}); let squared_sum_final = ${sumVector("workgroup_shared[0][1]", components)} / f32(hight * ${components}); let inv_std_dev = inverseSqrt(squared_sum_final - sum_final * sum_final + f32(${epsilon})); let channel_scale = inv_std_dev * f32(scale[channel]); let channel_shift = f32(bias[channel]) - sum_final * channel_scale; output[workgroup_index] = vec2f(channel_scale, channel_shift); } }`; }; return context.compute( { name: "InstanceNormComputeChannelScaleShift", // TODO: use epsilon as uniform. Currently epsilon as uniform fails test_instancenorm_epsilon. shaderCache: { hint: `${components};${epsilon};${workgroupSize}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: 1 /* float */ }], dispatchGroup: { x: unitsOfWork }, programUniforms }), getShaderSource }, { inputs: [input, scale, bias], outputs: [-1] } )[0]; }; createInstanceNormProgramInfo = (context, inputs, attributes) => { const xShape = inputs[0].dims; const outputShape = xShape; const axis = 2; const N = xShape[0]; const C = xShape[1]; const H = ShapeUtil.sizeFromDimension(xShape, axis); const components = getMaxComponents(H); const outputSize = ShapeUtil.size(outputShape) / components; const channelScaleShift = computeChannelScaleShift( context, inputs[0], inputs[1], inputs[2], N, H, C, attributes.epsilon ); const inputShape = [N, C, H / components]; const scaleShape = [N, C]; const inputDependencies = ["type", "none"]; const getShaderSource = (shaderHelper) => { const x = inputVariable("x", inputs[0].dataType, inputShape.length, components); const scale = inputVariable("scale_shift", 1 /* float */, scaleShape.length, 2); const output = outputVariable("output", inputs[0].dataType, inputShape.length, components); const variables = [x, scale, output]; return ` ${shaderHelper.registerUniform("output_size", "u32").declareVariables(...variables)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let outputIndices = ${output.offsetToIndices("global_idx")}; let batch = outputIndices[0]; let channel = outputIndices[1]; let scale_shift = ${scale.getByIndices("vec2(batch, channel)")}; let value = ${x.getByOffset("global_idx")} * ${output.type.value}(scale_shift.x) + ${output.type.value}(scale_shift.y); ${output.setByOffset("global_idx", "value")}; }`; }; context.compute( { name: "InstanceNormalization", shaderCache: { hint: `${components}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms: [ { type: 12 /* uint32 */, data: outputSize }, ...createTensorShapeVariables(inputShape, scaleShape, inputShape) ] }), getShaderSource }, { inputs: [inputs[0], channelScaleShift] } ); }; createInstanceNormNHWCProgramInfo = (context, inputs, attributes) => { const xShape = inputs[0].dims; const outputShape = xShape; const N = xShape[0]; const C = xShape[xShape.length - 1]; const H = ShapeUtil.sizeFromDimension(xShape, 1) / C; const components = getMaxComponents(C); const outputSize = ShapeUtil.size(outputShape) / components; const programUniforms = [ { type: 12 /* uint32 */, data: H }, { type: 12 /* uint32 */, data: Math.floor(C / components) } ]; const inputDependencies = ["type", "type"]; let needTranspose = false; const transposedXPerm = [0, xShape.length - 1]; for (let i = 0; i < xShape.length - 2; i++) { needTranspose = needTranspose || xShape[i + 1] !== 1; transposedXPerm.push(i + 1); } needTranspose = needTranspose && xShape[xShape.length - 1] !== 1; const transposedX = needTranspose ? context.compute(createTransposeProgramInfo(context.inputs[0], transposedXPerm), { inputs: [context.inputs[0]], outputs: [-1] })[0] : context.inputs[0].reshape(Array.from({ length: xShape.length }, (_, i) => xShape[transposedXPerm[i]])); const channelScaleShift = computeChannelScaleShift( context, transposedX, inputs[1], inputs[2], N, H, C, attributes.epsilon ); const getShaderSource = (shaderHelper) => { const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); const scaleType = components === 1 ? "vec2f" : `mat${components}x2f`; const scaleData = (num) => { const index = num === 0 ? "x" : "y"; const f32Type = components === 1 ? "f32" : `vec${components}f`; switch (components) { case 1: return `${dataType}(${f32Type}(scale.${index}))`; case 2: return `vec2<${dataType}>(${f32Type}(scale[0].${index}, scale[1].${index}))`; case 4: return `vec4<${dataType}>(${f32Type}(scale[0].${index}, scale[1].${index}, scale[2].${index}, scale[3].${index}))`; default: throw new Error(`Not supported compoents ${components}`); } }; const inputHelper = inputVariable("input", inputs[0].dataType, inputs[0].dims, components); const outputHelper = outputVariable("output", inputs[0].dataType, outputShape, components); return ` @group(0) @binding(0) var input : array<${inputHelper.type.storage}>; @group(0) @binding(1) var scale_input : array<${scaleType}>; @group(0) @binding(2) var output : array<${outputHelper.type.storage}>; struct Uniforms {H: u32, C : u32}; @group(0) @binding(3) var uniforms: Uniforms; ${shaderHelper.mainStart()} let current_image_number = global_idx / (uniforms.C * uniforms.H); let current_channel_number = global_idx % uniforms.C; let scale_offset = current_image_number * uniforms.C + current_channel_number; let scale = scale_input[scale_offset]; output[global_idx] = fma(input[global_idx], ${scaleData(0)}, ${scaleData(1)}); }`; }; context.compute( { name: "InstanceNormalizationNHWC", shaderCache: { hint: `${components}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }, { inputs: [inputs[0], channelScaleShift] } ); }; instanceNorm = (context, attributes) => { if (attributes.format === "NHWC") { createInstanceNormNHWCProgramInfo(context, context.inputs, attributes); } else { createInstanceNormProgramInfo(context, context.inputs, attributes); } }; } }); // web/lib/wasm/jsep/webgpu/ops/layer-norm.ts var validateInputs21, createLayerNormProgramInfo, layerNorm; var init_layer_norm = __esm({ "web/lib/wasm/jsep/webgpu/ops/layer-norm.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); validateInputs21 = (inputs) => { if (!inputs || inputs.length < 2) { throw new Error("layerNorm requires at least 2 inputs."); } }; createLayerNormProgramInfo = (inputs, attributes, outputCount) => { const simplified = attributes.simplified; const xShape = inputs[0].dims; const scale = inputs[1]; const bias = !simplified && inputs[2]; const outputShape = xShape; const axis = ShapeUtil.normalizeAxis(attributes.axis, xShape.length); const normCount = ShapeUtil.sizeToDimension(xShape, axis); const normSize = ShapeUtil.sizeFromDimension(xShape, axis); const scaleSize = ShapeUtil.size(scale.dims); const biasSize = bias ? ShapeUtil.size(bias.dims) : 0; if (scaleSize !== normSize || bias && biasSize !== normSize) { throw new Error(`Size of X.shape()[axis:] == ${normSize}. Size of scale and bias (if provided) must match this. Got scale size of ${scaleSize} and bias size of ${biasSize}`); } const meanInvStdDevDim = []; for (let i = 0; i < xShape.length; ++i) { if (i < axis) { meanInvStdDevDim.push(xShape[i]); } else { meanInvStdDevDim.push(1); } } const components = getMaxComponents(normSize); const inputDependencies = ["type", "type"]; const programUniforms = [ { type: 12 /* uint32 */, data: normCount }, { type: 1 /* float */, data: normSize }, { type: 12 /* uint32 */, data: Math.floor(normSize / components) }, { type: 1 /* float */, data: attributes.epsilon } ]; if (bias) { inputDependencies.push("type"); } const hasMeanDataOutput = outputCount > 1; const hasInvStdOutput = outputCount > 2; const getShaderSource = (shaderHelper) => { const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); const variables = [ inputVariable("x", inputs[0].dataType, inputs[0].dims, components), inputVariable("scale", scale.dataType, scale.dims, components) ]; if (bias) { variables.push(inputVariable("bias", bias.dataType, bias.dims, components)); } variables.push(outputVariable("output", inputs[0].dataType, outputShape, components)); if (hasMeanDataOutput) { variables.push(outputVariable("mean_data_output", 1 /* float */, meanInvStdDevDim)); } if (hasInvStdOutput) { variables.push(outputVariable("inv_std_output", 1 /* float */, meanInvStdDevDim)); } const uniforms = [ { name: "norm_count", type: "u32" }, { name: "norm_size", type: "f32" }, { name: "norm_size_vectorized", type: "u32" }, { name: "epsilon", type: "f32" } ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...variables)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.norm_count")} let offset = global_idx * uniforms.norm_size_vectorized; var mean_vector = ${fillVector("f32", components)}; var mean_square_vector = ${fillVector("f32", components)}; for (var h: u32 = 0u; h < uniforms.norm_size_vectorized; h++) { let value = ${castToF32(dataType, components, "x[h + offset]")}; mean_vector += value; mean_square_vector += value * value; } let mean = ${sumVector("mean_vector", components)} / uniforms.norm_size; let inv_std_dev = inverseSqrt(${sumVector("mean_square_vector", components)} / uniforms.norm_size ${simplified ? "" : "- mean * mean"} + uniforms.epsilon); for (var j: u32 = 0; j < uniforms.norm_size_vectorized; j++) { let f32input = ${castToF32(dataType, components, "x[j + offset]")}; let f32scale = ${castToF32(dataType, components, "scale[j]")}; output[j + offset] = ${variables[0].type.value}((f32input ${simplified ? "" : "- mean"}) * inv_std_dev * f32scale ${bias ? `+ ${castToF32(dataType, components, "bias[j]")}` : ""} ); } ${hasMeanDataOutput ? "mean_data_output[global_idx] = mean" : ""}; ${hasInvStdOutput ? "inv_std_output[global_idx] = inv_std_dev" : ""}; }`; }; const outputs = [{ dims: outputShape, dataType: inputs[0].dataType }]; if (hasMeanDataOutput) { outputs.push({ dims: meanInvStdDevDim, dataType: 1 /* float */ }); } if (hasInvStdOutput) { outputs.push({ dims: meanInvStdDevDim, dataType: 1 /* float */ }); } return { name: "LayerNormalization", shaderCache: { hint: `${components};${outputCount};${simplified}`, inputDependencies }, getRunData: () => ({ outputs, dispatchGroup: { x: Math.ceil( normCount / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; layerNorm = (context, attributes) => { validateInputs21(context.inputs); context.compute(createLayerNormProgramInfo(context.inputs, attributes, context.outputCount)); }; } }); // web/lib/wasm/jsep/webgpu/ops/matmul.ts var validateInputs22, matMul; var init_matmul = __esm({ "web/lib/wasm/jsep/webgpu/ops/matmul.ts"() { "use strict"; init_util(); init_matmul_shaders(); init_matmul_packed_webgpu(); validateInputs22 = (inputs) => { if (!inputs || inputs.length !== 2) { throw new Error("MatMul requires 2 inputs."); } if (inputs[0].dims[inputs[0].dims.length - 1] !== inputs[1].dims[inputs[1].dims.length - 2]) { throw new Error("shared dimension does not match."); } }; matMul = (context) => { validateInputs22(context.inputs); const outputShape = BroadcastUtil.calcShape(context.inputs[0].dims, context.inputs[1].dims, true); if (!outputShape) { throw new Error("Can't use matmul on the given tensors"); } const N = outputShape[outputShape.length - 1]; const K = context.inputs[0].dims[context.inputs[0].dims.length - 1]; if (N < 8 && K < 8) { context.compute(createNaiveMatmulProgramInfo(context.inputs, { activation: "" }, outputShape)); } else { const M = outputShape[outputShape.length - 2]; const batchA = ShapeUtil.size(context.inputs[0].dims.slice(0, -2)); const batchB = ShapeUtil.size(context.inputs[1].dims.slice(0, -2)); if (batchA !== 1 && M === 1 && batchB === 1) { const reshapedA = context.inputs[0].reshape([1, batchA, K]); const reshapedB = context.inputs[1].reshape([1, K, N]); const matmulOutputShape = [1, batchA, N]; const matmulInputs = [reshapedA, reshapedB]; context.compute(createMatmulProgramInfo(matmulInputs, { activation: "" }, outputShape, matmulOutputShape), { inputs: matmulInputs }); } else { context.compute(createMatmulProgramInfo(context.inputs, { activation: "" }, outputShape)); } } }; } }); // web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts var validateInputs23, createMatMulNBitsProgramInfo, createMatMulNBitsBlockSize32ProgramInfo, matMulNBits, parseMatMulNBitsAttributes; var init_matmulnbits = __esm({ "web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs23 = (inputs, attributes) => { if (inputs.length < 3 || inputs.length > 4) { throw new Error("MatMulNBits requires 3 or 4 inputs"); } const a = inputs[0]; const aRank = a.dims.length; if (a.dims[aRank - 1] !== attributes.k) { throw new Error("The last dim of input shape does not match the k value"); } const nBlocksPerCol = Math.floor((attributes.k + attributes.blockSize - 1) / attributes.blockSize); const blobSize = attributes.blockSize / 8 * attributes.bits; const b = inputs[1]; if (!ShapeUtil.areEqual(b.dims, [attributes.n, nBlocksPerCol, blobSize])) { throw new Error("The second inputs must be 3D tensor with shape N X nBlocksPerCol X blobSize"); } const scales = inputs[2]; const scalesShape = scales.dims; if (ShapeUtil.size(scalesShape) !== attributes.n * nBlocksPerCol) { throw new Error("scales input size error."); } if (inputs.length === 4) { const zeroPoints = inputs[3]; const zeroPointsShape = zeroPoints.dims; const expectedZeroPointsSize = attributes.n * (attributes.bits === 8 ? nBlocksPerCol : Math.floor((nBlocksPerCol * attributes.bits + 7) / 8)); if (ShapeUtil.size(zeroPointsShape) !== expectedZeroPointsSize) { throw new Error("zeroPoints input size error."); } } }; createMatMulNBitsProgramInfo = (inputs, attributes) => { const inputShape = inputs[0].dims; const aRank = inputShape.length; const dimAOuter = inputShape[aRank - 2]; const dimInner = attributes.k; const dimBOuter = attributes.n; const batchDims = inputShape.slice(0, aRank - 2); const batchSize = ShapeUtil.size(batchDims); const blobSize = inputs[1].dims[2]; const blobSizeInWords = blobSize / 4; const dataType = inputs[0].dataType; const aComponents = getMaxComponents(attributes.k); const bComponents = getMaxComponents(blobSizeInWords); const components = getMaxComponents(dimBOuter); const outputShape = batchDims.concat([dimAOuter, dimBOuter]); const outputNumber = dimAOuter > 1 && dimBOuter / components % 2 === 0 ? 2 : 1; const dispatchSize = ShapeUtil.size(outputShape) / components / outputNumber; const workgroupSize = 64; const programUniforms = []; const inputShapeTemp = [batchSize, dimAOuter, dimInner / aComponents]; const bShape = ShapeUtil.convertShape(inputs[1].dims).slice(); bShape.splice(-1, 1, blobSizeInWords / bComponents); programUniforms.push(...createTensorShapeVariables(inputShapeTemp)); programUniforms.push(...createTensorShapeVariables(bShape)); programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); if (inputs.length === 4) { programUniforms.push(...createTensorShapeVariables(ShapeUtil.convertShape(inputs[3].dims))); } const outputShapeTemp = [batchSize, dimAOuter, dimBOuter / components]; programUniforms.push(...createTensorShapeVariables(outputShapeTemp)); const getShaderSource = (shaderHelper) => { const inputRank = inputShapeTemp.length; const a = inputVariable("a", inputs[0].dataType, inputRank, aComponents); const b = inputVariable("b", 12 /* uint32 */, bShape.length, bComponents); const scales = inputVariable("scales", inputs[2].dataType, inputs[2].dims.length); const inputVariables = [a, b, scales]; const zeroPoints = inputs.length === 4 ? inputVariable("zero_points", 12 /* uint32 */, inputs[3].dims.length) : void 0; if (zeroPoints) { inputVariables.push(zeroPoints); } const outputRank = outputShapeTemp.length; const output = outputVariable("output", inputs[0].dataType, outputRank, components); const dataType2 = tensorTypeToWsglStorageType(inputs[0].dataType); const qDqDataType = (() => { switch (aComponents) { case 1: return `array<${dataType2}, 8>`; case 2: return `mat4x2<${dataType2}>`; case 4: return `mat2x4<${dataType2}>`; default: throw new Error(`${aComponents}-component is not supported.`); } })(); const valuesPerWord = Math.floor(32 / attributes.bits); const passesPerWord = Math.floor(valuesPerWord / 8); const processOneWord = () => { let calcStr = ""; for (let pass = 0; pass < passesPerWord; pass++) { const lowerShift = pass * attributes.bits * 4; const upperShift = lowerShift + attributes.bits; calcStr += ` // reuse a data (pass ${pass}) var input_offset${pass > 0 ? pass : ""} = ${pass === 0 ? a.indicesToOffset(`${a.type.indices}(batch, row, word_offset)`) : `input_offset`}; var a_data${pass > 0 ? pass : ""}: ${qDqDataType}; for (var j${pass > 0 ? pass : ""}: u32 = 0; j${pass > 0 ? pass : ""} < ${8 / aComponents}; j${pass > 0 ? pass : ""}++) { a_data${pass > 0 ? pass : ""}[j${pass > 0 ? pass : ""}] = ${a.getByOffset(`input_offset${pass > 0 ? pass : ""}`)}; input_offset${pass > 0 ? pass : ""}++; } `; for (let c = 0; c < components * outputNumber; c++) { calcStr += ` b_value = ${bComponents === 1 ? `b${c}_data` : `b${c}_data[i]`}; ${attributes.bits === 2 ? `{ let half_word = b_value >> ${pass * 16}u; let byte_lo = half_word & 0xFFu; let byte_hi = (half_word >> 8u) & 0xFFu; let spread_word = (byte_lo & 0xFu) | ((byte_lo >> 4u) << 8u) | ((byte_hi & 0xFu) << 16u) | ((byte_hi >> 4u) << 24u); b_value_lower = unpack4xU8(spread_word & b_mask); b_value_upper = unpack4xU8((spread_word >> 2u) & b_mask); }` : `b_value_lower = unpack4xU8((b_value >> ${lowerShift}u) & b_mask); b_value_upper = unpack4xU8((b_value >> ${upperShift}u) & b_mask);`} b_quantized_values = ${qDqDataType}(${Array.from( { length: 4 }, (_, i) => `${dataType2}(b_value_lower[${i}]), ${dataType2}(b_value_upper[${i}])` ).join(", ")}); b_dequantized_values = ${(() => { if (aComponents === 1) { return `${qDqDataType}(${Array.from( { length: 8 }, (_, i) => `(b_quantized_values[${i}] - ${zeroPoints ? `zero_point${c}` : "zero_point"}) * scale${c}` ).join(", ")});`; } else { return `(b_quantized_values - ${qDqDataType}(${Array(8).fill(`${zeroPoints ? `zero_point${c}` : "zero_point"}`).join(",")})) * scale${c};`; } })()}; workgroup_shared[local_id.x * ${outputNumber} + ${Math.floor(c / components)}]${components > 1 ? `[${c % components}]` : ""} += ${Array.from( { length: 8 / aComponents }, (_, i) => `${aComponents === 1 ? `a_data${pass > 0 ? pass : ""}[${i}] * b_dequantized_values[${i}]` : `dot(a_data${pass > 0 ? pass : ""}[${i}], b_dequantized_values[${i}])`}` ).join(" + ")}; `; } } return calcStr; }; const prepareScaleAndZeroPoint = () => { let calcStr = ` var col_index = col * ${components}; ${zeroPoints ? ` let zero_point_values_per_byte: u32 = ${Math.floor(8 / attributes.bits)}u; let zero_point_bytes_per_col = (nBlocksPerCol + zero_point_values_per_byte - 1u) / zero_point_values_per_byte; var zero_point_byte_count: u32; var zero_point_word_index: u32; var zero_point_byte_offset: u32; let zero_point_sub_offset: u32 = block % zero_point_values_per_byte; var zero_point_bits_offset: u32; var zero_point_word: u32;` : ` // The default zero point is ${Math.pow(2, attributes.bits - 1)} for unsigned ${attributes.bits}-bit quantization. let zero_point = ${dataType2}(${Math.pow(2, attributes.bits - 1).toFixed(1)});`} `; for (let c = 0; c < components * outputNumber; c++) { calcStr += ` let scale${c} = ${scales.getByOffset(`col_index * nBlocksPerCol + block`)}; ${zeroPoints ? ` zero_point_byte_count = col_index * zero_point_bytes_per_col + (block / zero_point_values_per_byte); zero_point_word_index = zero_point_byte_count >> 0x2u; zero_point_byte_offset = zero_point_byte_count & 0x3u; zero_point_bits_offset = (zero_point_byte_offset << 3) + (zero_point_sub_offset * ${attributes.bits}u); zero_point_word = ${zeroPoints.getByOffset("zero_point_word_index")} >> zero_point_bits_offset; let zero_point${c} = ${dataType2}((zero_point_word) & ${attributes.bits === 2 ? "0x3u" : "0xFu"});` : ""} col_index += 1;`; } return calcStr; }; const prepareBData = () => { let calcStr = `col_index = col * ${components};`; for (let c = 0; c < components * outputNumber; c++) { calcStr += ` let b${c}_data = ${b.getByIndices(`${b.type.indices}(col_index, block, word)`)}; col_index += 1;`; } calcStr += ` var b_value: u32; let b_mask: u32 = ${attributes.bits === 2 ? "0x03030303u" : "0x0F0F0F0Fu"}; var b_value_lower: vec4; var b_value_upper: vec4; var b_quantized_values: ${qDqDataType}; var b_dequantized_values: ${qDqDataType};`; return calcStr; }; return ` var workgroup_shared: array<${output.type.value}, ${outputNumber * workgroupSize}>; ${shaderHelper.declareVariables(...inputVariables, output)} ${shaderHelper.mainStart([workgroupSize, 1, 1])} let output_indices = ${output.offsetToIndices(`(global_idx / ${workgroupSize}) * ${outputNumber}`)}; let col = output_indices[2]; let row = output_indices[1]; let batch = output_indices[0]; let nBlocksPerCol = uniforms.b_shape[1]; for (var block = local_id.x; block < nBlocksPerCol; block += ${workgroupSize}) { //process one block var word_offset: u32 = block * ${attributes.blockSize / aComponents}; ${prepareScaleAndZeroPoint()} for (var word: u32 = 0; word < ${blobSizeInWords}; word += ${bComponents}) { ${prepareBData()} for (var i: u32 = 0; i < ${bComponents}; i++) { ${processOneWord()} word_offset += ${valuesPerWord / aComponents}; } } } workgroupBarrier(); if (local_id.x < ${outputNumber}) { var output_value: ${output.type.value} = ${output.type.value}(0); var workgroup_shared_offset: u32 = local_id.x; for (var b: u32 = 0u; b < ${workgroupSize}u; b++) { output_value += workgroup_shared[workgroup_shared_offset]; workgroup_shared_offset += ${outputNumber}; } ${output.setByIndices(`${output.type.indices}(batch, row, col + local_id.x)`, "output_value")}; } }`; }; return { name: "MatMulNBits", shaderCache: { hint: `${attributes.blockSize};${attributes.bits};${aComponents};${bComponents};${components};${outputNumber};${workgroupSize}`, inputDependencies: Array(inputs.length).fill("rank") }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType }], dispatchGroup: { x: dispatchSize }, programUniforms }), getShaderSource }; }; createMatMulNBitsBlockSize32ProgramInfo = (inputs, attributes) => { const inputShape = inputs[0].dims; const aRank = inputShape.length; const dimAOuter = inputShape[aRank - 2]; const dimInner = attributes.k; const dimBOuter = attributes.n; const batchDims = inputShape.slice(0, aRank - 2); const batchSize = ShapeUtil.size(batchDims); const blobSize = inputs[1].dims[2]; const blobSizeInWords = blobSize / 4; const dataType = inputs[0].dataType; const aComponents = getMaxComponents(attributes.k); const bComponents = getMaxComponents(blobSizeInWords); const outputShape = batchDims.concat([dimAOuter, dimBOuter]); const workgroupSize = 128; const workgroupY = dimBOuter % 8 === 0 ? 8 : dimBOuter % 4 === 0 ? 4 : 1; const workgroupX = workgroupSize / workgroupY; const valuesPerWordBs32 = Math.floor(32 / attributes.bits); const tileSize = workgroupX * bComponents * valuesPerWordBs32; const aLengthPerTile = tileSize / aComponents; const blocksPerTile = tileSize / attributes.blockSize; const dispatchSize = ShapeUtil.size(outputShape) / workgroupY; const programUniforms = []; const inputShapeTemp = [batchSize, dimAOuter, dimInner / aComponents]; const bShape = ShapeUtil.convertShape(inputs[1].dims).slice(); bShape.splice(-1, 1, blobSizeInWords / bComponents); programUniforms.push(...createTensorShapeVariables(inputShapeTemp)); programUniforms.push(...createTensorShapeVariables(bShape)); programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); if (inputs.length === 4) { programUniforms.push(...createTensorShapeVariables(ShapeUtil.convertShape(inputs[3].dims))); } const outputShapeTemp = [batchSize, dimAOuter, dimBOuter]; programUniforms.push(...createTensorShapeVariables(outputShapeTemp)); const getShaderSource = (shaderHelper) => { const inputRank = inputShapeTemp.length; const a = inputVariable("a", inputs[0].dataType, inputRank, aComponents); const b = inputVariable("b", 12 /* uint32 */, bShape.length, bComponents); const scales = inputVariable("scales", inputs[2].dataType, inputs[2].dims.length); const inputVariables = [a, b, scales]; const zeroPoints = inputs.length === 4 ? inputVariable("zero_points", 12 /* uint32 */, inputs[3].dims.length) : void 0; if (zeroPoints) { inputVariables.push(zeroPoints); } const outputRank = outputShapeTemp.length; const output = outputVariable("output", inputs[0].dataType, outputRank); const dataType2 = tensorTypeToWsglStorageType(inputs[0].dataType); const readA = () => { switch (aComponents) { case 1: return ` let a_data0 = vec4<${dataType2}>(sub_a[word_offset], sub_a[word_offset + 1], sub_a[word_offset + 2], sub_a[word_offset + 3]); let a_data1 = vec4<${dataType2}>(sub_a[word_offset + 4], sub_a[word_offset + 5], sub_a[word_offset + 6], sub_a[word_offset + 7]);`; case 2: return ` let a_data0 = vec4<${dataType2}>(sub_a[word_offset], sub_a[word_offset + 1]); let a_data1 = vec4<${dataType2}>(sub_a[word_offset + 2], sub_a[word_offset + 3]);`; case 4: return ` let a_data0 = sub_a[word_offset]; let a_data1 = sub_a[word_offset + 1];`; default: throw new Error(`${aComponents}-component is not supported.`); } }; return ` var sub_a: array<${a.type.value}, ${aLengthPerTile}>; var inter_results: array, ${workgroupY}>; ${shaderHelper.declareVariables(...inputVariables, output)} ${shaderHelper.mainStart([workgroupX, workgroupY, 1])} let output_indices = ${output.offsetToIndices(`workgroup_index * ${workgroupY}`)}; let col = output_indices[2]; let row = output_indices[1]; let batch = output_indices[0]; let n_blocks_per_col = uniforms.b_shape[1]; let num_tiles = (n_blocks_per_col - 1) / ${blocksPerTile} + 1; // Loop over shared dimension. for (var tile: u32 = 0; tile < num_tiles; tile += 1) { let a_col_start = tile * ${aLengthPerTile}; // load one tile A data into shared memory. for (var a_offset = local_idx; a_offset < ${aLengthPerTile}; a_offset += ${workgroupSize}) { let a_col = a_col_start + a_offset; if (a_col < uniforms.a_shape[2]) { sub_a[a_offset] = ${a.getByIndices(`${a.type.indices}(batch, row, a_col)`)}; } else { sub_a[a_offset] = ${a.type.value}(0); } } workgroupBarrier(); // each thread process one block let b_row = col + local_id.y; let block = tile * ${blocksPerTile} + local_id.x; ${zeroPoints ? ` let zero_point_values_per_byte: u32 = ${Math.floor(8 / attributes.bits)}u; let zero_point_bytes_per_col = (n_blocks_per_col + zero_point_values_per_byte - 1u) / zero_point_values_per_byte; let zero_point_byte_count = b_row * zero_point_bytes_per_col + (block / zero_point_values_per_byte); let zero_point_word_index = zero_point_byte_count >> 0x2u; let zero_point_byte_offset = zero_point_byte_count & 0x3u; let zero_point_sub_offset: u32 = block % zero_point_values_per_byte; let zero_point_bits_offset = (zero_point_byte_offset << 3) + (zero_point_sub_offset * ${attributes.bits}u); let zero_point_word = ${zeroPoints.getByOffset("zero_point_word_index")} >> zero_point_bits_offset; let zero_point = ${dataType2}((zero_point_word) & ${attributes.bits === 2 ? "0x3u" : "0xFu"});` : ` // The default zero point is ${Math.pow(2, attributes.bits - 1)} for unsigned ${attributes.bits}-bit quantization. let zero_point = ${dataType2}(${Math.pow(2, attributes.bits - 1).toFixed(1)});`} let scale = ${scales.getByOffset(`b_row * n_blocks_per_col + block`)}; let b_data = ${b.getByIndices(`${b.type.indices}(b_row, block, 0)`)}; var word_offset = local_id.x * ${attributes.blockSize / aComponents}; for (var i: u32 = 0; i < ${bComponents}; i++) { let b_value = ${bComponents === 1 ? `b_data` : `b_data[i]`}; ${(() => { const passesPerWordBs32 = Math.floor(valuesPerWordBs32 / 8); let code = ""; for (let pass = 0; pass < passesPerWordBs32; pass++) { const lowerShift = pass * attributes.bits * 4; const upperShift = lowerShift + attributes.bits; code += ` ${readA()} {${attributes.bits === 2 ? ` let half_word = b_value >> ${pass * 16}u; let byte_lo = half_word & 0xFFu; let byte_hi = (half_word >> 8u) & 0xFFu; let spread_word = (byte_lo & 0xFu) | ((byte_lo >> 4u) << 8u) | ((byte_hi & 0xFu) << 16u) | ((byte_hi >> 4u) << 24u); let b_value_lower = unpack4xU8(spread_word & 0x03030303u); let b_value_upper = unpack4xU8((spread_word >> 2u) & 0x03030303u);` : ` let b_value_lower = unpack4xU8((b_value >> ${lowerShift}u) & 0x0F0F0F0Fu); let b_value_upper = unpack4xU8((b_value >> ${upperShift}u) & 0x0F0F0F0Fu);`} let b_quantized_values = mat2x4<${dataType2}>(${Array.from( { length: 4 }, (_, i) => `${dataType2}(b_value_lower[${i}]), ${dataType2}(b_value_upper[${i}])` ).join(", ")}); let b_dequantized_values = (b_quantized_values - mat2x4<${dataType2}>(${Array(8).fill("zero_point").join(",")})) * scale; inter_results[local_id.y][local_id.x] += ${Array.from( { length: 2 }, (_, i) => `${`dot(a_data${i}, b_dequantized_values[${i}])`}` ).join(" + ")}; } word_offset += ${8 / aComponents};`; } return code; })()} } workgroupBarrier(); } if (local_idx < ${workgroupY}) { var output_value: ${output.type.value} = ${output.type.value}(0); for (var b = 0u; b < ${workgroupX}; b++) { output_value += inter_results[local_idx][b]; } if (col + local_idx < uniforms.output_shape[2]) { ${output.setByIndices(`${output.type.indices}(batch, row, col + local_idx)`, "output_value")} } } }`; }; return { name: "BlockwiseMatMulNBits32", shaderCache: { hint: `${attributes.blockSize};${aComponents};${bComponents};${workgroupX};${workgroupY}`, inputDependencies: Array(inputs.length).fill("rank") }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType }], dispatchGroup: { x: dispatchSize }, programUniforms }), getShaderSource }; }; matMulNBits = (context, attributes) => { validateInputs23(context.inputs, attributes); if (attributes.blockSize === 32 && context.adapterInfo.isVendor("intel") && context.adapterInfo.isArchitecture("gen-12lp")) { context.compute(createMatMulNBitsBlockSize32ProgramInfo(context.inputs, attributes)); } else { context.compute(createMatMulNBitsProgramInfo(context.inputs, attributes)); } }; parseMatMulNBitsAttributes = (attributes) => createAttributeWithCacheKey(attributes); } }); // web/lib/wasm/jsep/webgpu/ops/pad.ts var validateInputs24, getPadConstant, getPadReflect, getPadEdge, getPadWrap, getPadSnippet, createPadProgramInfo, createPadAttributesFromInputs, pad; var init_pad = __esm({ "web/lib/wasm/jsep/webgpu/ops/pad.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); validateInputs24 = (inputs) => { if (!inputs || inputs.length < 1) { throw new Error("Too few inputs"); } if (inputs[0].dataType !== 1 /* float */ && inputs[0].dataType !== 10 /* float16 */) { throw new Error("Input type must be float or float16."); } if (inputs.length >= 2) { let validPads = inputs[0].dims.length * 2 === inputs[1].dims[0]; if (inputs.length === 4) { validPads = inputs[3].dims[0] * 2 === inputs[1].dims[0]; } if (!validPads) { throw new Error("The pads should be a 1D tensor of shape [2 * input_rank] or [2 * num_axes]."); } } }; getPadConstant = (output, inputRank, padsLength) => { let block = ""; for (let i = inputRank - 1; i >= 0; --i) { block += ` k = i32(${output.indicesGet("indices", i)}) - ${getElementAt("uniforms.pads", i, padsLength)}; if (k < 0) { break; } if (k >= i32(${getElementAt("uniforms.x_shape", i, inputRank)})) { break; } offset += k * i32(${getElementAt("uniforms.x_strides", i, inputRank)}); `; } return ` value = ${output.type.value}(uniforms.constant_value); for (var i = 0; i < 1; i++) { var offset = 0; var k = 0; ${block} value = x[offset]; } `; }; getPadReflect = (output, inputRank, padsLength) => { let block = ""; for (let i = inputRank - 1; i >= 0; --i) { block += ` k = i32(${output.indicesGet("indices", i)}) - ${getElementAt("uniforms.pads", i, padsLength)}; if (k < 0) { k = -k; } { let _2n_1 = 2 * (i32(${getElementAt("uniforms.x_shape", i, inputRank)}) - 1); k = k % _2n_1; if(k >= i32(${getElementAt("uniforms.x_shape", i, inputRank)})) { k = _2n_1 - k; } } offset += k * i32(${getElementAt("uniforms.x_strides", i, inputRank)}); `; } return ` var offset = 0; var k = 0; ${block} value = x[offset]; `; }; getPadEdge = (output, inputRank, padsLength) => { let block = ""; for (let i = inputRank - 1; i >= 0; --i) { block += ` k = i32(${output.indicesGet("indices", i)}) - ${getElementAt("uniforms.pads", i, padsLength)}; if (k < 0) { k = 0; } if (k >= i32(${getElementAt("uniforms.x_shape", i, inputRank)})) { k = i32(${getElementAt("uniforms.x_shape", i, inputRank)}) - 1; } offset += k * i32(${getElementAt("uniforms.x_strides", i, inputRank)}); `; } return ` var offset = 0; var k = 0; ${block} value = x[offset]; `; }; getPadWrap = (output, inputRank, padsLength) => { let block = ""; for (let i = inputRank - 1; i >= 0; --i) { block += ` k = i32(${output.indicesGet("indices", i)}) - ${getElementAt("uniforms.pads", i, padsLength)}; if (k < 0) { k += i32(${getElementAt("uniforms.x_shape", i, inputRank)}]); } if (k >= i32(${getElementAt("uniforms.x_shape", i, inputRank)})) { k -= i32(${getElementAt("uniforms.x_shape", i, inputRank)}); } offset += k * i32(${getElementAt("uniforms.x_strides", i, inputRank)}); `; } return ` var offset = 0; var k = 0; ${block} value = x[offset]; `; }; getPadSnippet = (output, inputRank, attributes) => { switch (attributes.mode) { case 0: return getPadConstant(output, inputRank, attributes.pads.length); case 1: return getPadReflect(output, inputRank, attributes.pads.length); case 2: return getPadEdge(output, inputRank, attributes.pads.length); case 3: return getPadWrap(output, inputRank, attributes.pads.length); default: throw new Error("Invalid mode"); } }; createPadProgramInfo = (inputs, attributes) => { const outputShape = ShapeUtil.padShape(inputs[0].dims.slice(), attributes.pads); const inputDims = inputs[0].dims; const outputSize = ShapeUtil.size(outputShape); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 6 /* int32 */, data: attributes.pads } ]; const isValueFromInput = inputs.length >= 3 && inputs[2].data; if (attributes.mode === 0) { programUniforms.push({ type: isValueFromInput ? inputs[2].dataType : 1 /* float */, data: attributes.value }); } programUniforms.push(...createTensorShapeVariables(inputs[0].dims, outputShape)); const inputDependencies = ["rank"]; const getShaderSource = (shaderHelper) => { const output = outputVariable("output", inputs[0].dataType, outputShape.length); const input = inputVariable("x", inputs[0].dataType, inputDims.length); const dataType = input.type.value; const padSnippet = getPadSnippet(output, inputDims.length, attributes); const uniforms = [ { name: "output_size", type: "u32" }, { name: "pads", type: "i32", length: attributes.pads.length } ]; if (attributes.mode === 0) { uniforms.push({ name: "constant_value", type: isValueFromInput ? dataType : "f32" }); } return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let indices = ${output.offsetToIndices("global_idx")}; var value = ${dataType}(0); ${padSnippet} output[global_idx] = value; }`; }; return { name: "Pad", shaderCache: { hint: `${attributes.mode}${isValueFromInput}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( ShapeUtil.size(outputShape) / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; createPadAttributesFromInputs = (inputs, attributes) => { if (inputs.length > 1) { const bigInt64Pads = inputs[1].getBigInt64Array(); const value = inputs.length >= 3 && inputs[2].data ? inputs[2].dataType === 10 /* float16 */ ? inputs[2].getUint16Array()[0] : inputs[2].getFloat32Array()[0] : 0; const inputRank = inputs[0].dims.length; const updatePads = new Int32Array(2 * inputRank).fill(0); if (inputs.length >= 4) { const axes = inputs[3].getBigInt64Array(); for (let i = 0; i < axes.length; i++) { updatePads[Number(axes[i])] = Number(bigInt64Pads[i]); updatePads[Number(axes[i]) + inputRank] = Number(bigInt64Pads[i + axes.length]); } } else { bigInt64Pads.forEach((v, i) => updatePads[Number(i)] = Number(v)); } const pads = []; updatePads.forEach((v) => pads.push(v)); return { mode: attributes.mode, value, pads }; } else { return attributes; } }; pad = (context, attributes) => { validateInputs24(context.inputs); const updatedAttributes = createPadAttributesFromInputs(context.inputs, attributes); context.compute(createPadProgramInfo(context.inputs, updatedAttributes), { inputs: [0] }); }; } }); // web/lib/wasm/jsep/webgpu/ops/pool.ts var validateInputs25, getAdjustedPoolAttributesAndOutputShape, getUniformAndPadInfo, generatePoolingCode, createShaderKeyFromAttributes, createAveragePoolShaderKeyFromAttributes, createMaxPoolShaderKeyFromAttributes, parsePoolCommonAttributes, createAveragePoolProgramInfo, parseAveragePoolAttributes, averagePool, globalPoolAttributes, parseGlobalAveragePoolAttributes, globalAveragePool, createMaxPoolProgramInfo, maxPool, parseMaxPoolAttributes, parseGlobalMaxPoolAttributes, globalMaxPool; var init_pool = __esm({ "web/lib/wasm/jsep/webgpu/ops/pool.ts"() { "use strict"; init_esm(); init_wasm_common(); init_util(); init_common(); validateInputs25 = (inputs) => { if (env2.webgpu.validateInputContent && (!inputs || inputs.length !== 1)) { throw new Error("Pool ops requires 1 input."); } }; getAdjustedPoolAttributesAndOutputShape = (input, attributes, isGlobalOperator) => { const isChannelsLast = attributes.format === "NHWC"; const inputShapeAsChannelFirst = input.dims.slice(); if (isChannelsLast) { inputShapeAsChannelFirst.splice(1, 0, inputShapeAsChannelFirst.pop()); } const hasDilations = Object.hasOwnProperty.call(attributes, "dilations"); const kernelShape = attributes.kernelShape.slice(); const strides = attributes.strides.slice(); const dilations = hasDilations ? attributes.dilations.slice() : []; const pads = attributes.pads.slice(); PoolConvUtil.adjustPoolAttributes(isGlobalOperator, inputShapeAsChannelFirst, kernelShape, strides, dilations, pads); const outputShapeAsChannelFirst = PoolConvUtil.computePoolOutputShape( isGlobalOperator, inputShapeAsChannelFirst, strides, dilations, kernelShape, pads, attributes.autoPad ); const newAttributes = Object.assign({}, attributes); if (hasDilations) { Object.assign(newAttributes, { kernelShape, strides, pads, dilations, cacheKey: attributes.cacheKey }); } else { Object.assign(newAttributes, { kernelShape, strides, pads, cacheKey: attributes.cacheKey }); } const outputShapeAsChannelLast = outputShapeAsChannelFirst.slice(); outputShapeAsChannelLast.push(outputShapeAsChannelLast.splice(1, 1)[0]); return [newAttributes, isChannelsLast ? outputShapeAsChannelLast : outputShapeAsChannelFirst]; }; getUniformAndPadInfo = (outputShape, attributes) => { const isChannelsLast = attributes.format === "NHWC"; const outputSize = ShapeUtil.size(outputShape); const kernelSize = ShapeUtil.size(attributes.kernelShape); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: kernelSize } ]; const uniforms = [ { name: "outputSize", type: "u32" }, { name: "kernelSize", type: "u32" } ]; if (attributes.kernelShape.length <= 2) { const kw = attributes.kernelShape[attributes.kernelShape.length - 1]; const sw = attributes.strides[attributes.strides.length - 1]; const pwStart = attributes.pads[attributes.pads.length / 2 - 1]; const pwEnd = attributes.pads[attributes.pads.length - 1]; const pwStartEndNotZero = !!(pwStart + pwEnd); programUniforms.push( { type: 12 /* uint32 */, data: kw }, { type: 12 /* uint32 */, data: sw }, { type: 12 /* uint32 */, data: pwStart }, { type: 12 /* uint32 */, data: pwEnd } ); uniforms.push( { name: "kw", type: "u32" }, { name: "sw", type: "u32" }, { name: "pwStart", type: "u32" }, { name: "pwEnd", type: "u32" } ); let phStartEndNotZero = false; if (attributes.kernelShape.length === 2) { const kh = attributes.kernelShape[attributes.kernelShape.length - 2]; const sh = attributes.strides[attributes.strides.length - 2]; const phStart = attributes.pads[attributes.pads.length / 2 - 2]; const phEnd = attributes.pads[attributes.pads.length - 2]; phStartEndNotZero = !!(phStart + phEnd); programUniforms.push( { type: 12 /* uint32 */, data: kh }, { type: 12 /* uint32 */, data: sh }, { type: 12 /* uint32 */, data: phStart }, { type: 12 /* uint32 */, data: phEnd } ); uniforms.push( { name: "kh", type: "u32" }, { name: "sh", type: "u32" }, { name: "phStart", type: "u32" }, { name: "phEnd", type: "u32" } ); } return [programUniforms, uniforms, true, pwStartEndNotZero, phStartEndNotZero]; } else { if (isChannelsLast) { throw new Error("Pooling with kernelShape.length > 2 is not supported for NHWC format."); } const kernelStrides = ShapeUtil.computeStrides(attributes.kernelShape); programUniforms.push( { type: 12 /* uint32 */, data: kernelStrides }, { type: 12 /* uint32 */, data: attributes.pads }, { type: 12 /* uint32 */, data: attributes.strides } ); uniforms.push( { name: "kernelStrides", type: "u32", length: kernelStrides.length }, { name: "pads", type: "u32", length: attributes.pads.length }, { name: "strides", type: "u32", length: attributes.strides.length } ); const hasPads = attributes.pads.reduce((sum, cur) => sum + cur); return [programUniforms, uniforms, !!hasPads, false, false]; } }; generatePoolingCode = (shaderHelper, x, rank, outputShapeRank, attributes, op1, op2, start, uniforms, hasPads, pwStartEndNotZero, phStartEndNotZero) => { const isChannelsLast = attributes.format === "NHWC"; const dataType = x.type.value; const output = outputVariable("output", x.type.tensor, outputShapeRank); if (attributes.kernelShape.length <= 2) { let codeW = ""; let codeH = ""; let codeHEnd = ""; const dimIdxW = rank - (isChannelsLast ? 2 : 1); if (pwStartEndNotZero) { codeW = ` for (var i: u32 = 0u; i < uniforms.kw; i++) { xIndices[${dimIdxW}] = indices[${dimIdxW}] * uniforms.sw - uniforms.pwStart + i; if (xIndices[${dimIdxW}] < 0 || xIndices[${dimIdxW}] >= uniforms.x_shape[${dimIdxW}]) { pad++; continue; } let x_val = x[${x.indicesToOffset("xIndices")}]; ${op1} }`; } else { codeW = ` for (var i: u32 = 0u; i < uniforms.kw; i++) { xIndices[${dimIdxW}] = indices[${dimIdxW}] * uniforms.sw - uniforms.pwStart + i; let x_val = x[${x.indicesToOffset("xIndices")}]; ${op1} }`; } if (attributes.kernelShape.length === 2) { const dimIdxH = rank - (isChannelsLast ? 3 : 2); if (phStartEndNotZero) { codeH = ` for (var j: u32 = 0u; j < uniforms.kh; j++) { xIndices[${dimIdxH}] = indices[${dimIdxH}] * uniforms.sh - uniforms.phStart + j; if (xIndices[${dimIdxH}] < 0 || xIndices[${dimIdxH}] >= uniforms.x_shape[${dimIdxH}]) { pad += i32(uniforms.kw); continue; } `; } else { codeH = ` for (var j: u32 = 0u; j < uniforms.kh; j++) { xIndices[${dimIdxH}] = indices[${dimIdxH}] * uniforms.sh - uniforms.phStart + j; `; } codeHEnd = ` } `; } const poolingCode = ` ${shaderHelper.registerUniforms(uniforms).declareVariables(x, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} let indices = ${output.offsetToIndices("global_idx")}; var xIndices = ${output.offsetToIndices("global_idx")}; var value = ${dataType}(${start}); var pad = 0; ${codeH} ${codeW} ${codeHEnd} ${op2} output[global_idx] = value; }`; return poolingCode; } else { if (isChannelsLast) { throw new Error("Pooling with kernelShape.length > 2 is not supported for NHWC format."); } const stridesRank = attributes.kernelShape.length; const padsRank = attributes.pads.length; let padCode = ""; if (hasPads) { padCode = ` if (xIndices[j] >= uniforms.x_shape[j]) { pad++; isPad = true; break; } } if (!isPad) { let x_val = x[${x.indicesToOffset("xIndices")}]; ${op1} }`; } else { padCode = ` } let x_val = x[${x.indicesToOffset("xIndices")}]; ${op1} `; } const poolingCode = ` ${shaderHelper.registerUniforms(uniforms).declareVariables(x, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} let indices = ${output.offsetToIndices("global_idx")}; var xIndices = ${output.offsetToIndices("global_idx")}; var offsets: array; var value = ${dataType}(${start}); var pad = 0; var isPad = false; for (var i: u32 = 0u; i < uniforms.kernelSize; i++) { var offset = i; for (var j = 0u; j < ${stridesRank - 1}u; j++) { offsets[j] = offset / ${getElementAt("uniforms.kernelStrides", "j", stridesRank)}; offset -= offsets[j] * ${getElementAt("uniforms.kernelStrides", "j", stridesRank)}; } offsets[${stridesRank - 1}] = offset; isPad = false; for (var j = ${rank - stridesRank}u; j < ${rank}u; j++) { xIndices[j] = indices[j] * ${getElementAt( "uniforms.strides", `j - ${rank - stridesRank}u`, stridesRank )} + offsets[j - ${rank - stridesRank}u] - ${getElementAt("uniforms.pads", "j - 2u", padsRank)}; ${padCode} } ${op2} output[global_idx] = value; }`; return poolingCode; } }; createShaderKeyFromAttributes = (attributes) => `${attributes.format};${attributes.ceilMode};${attributes.autoPad};${attributes.kernelShape.length}`; createAveragePoolShaderKeyFromAttributes = (attributes) => `${createShaderKeyFromAttributes(attributes)};${attributes.countIncludePad}`; createMaxPoolShaderKeyFromAttributes = (attributes) => `${createShaderKeyFromAttributes(attributes)};${attributes.storageOrder};${attributes.dilations}`; parsePoolCommonAttributes = (attributes) => ({ format: attributes.format, autoPad: ["NOTSET", "VALID", "SAME_UPPER", "SAME_LOWER"][attributes.auto_pad], ceilMode: attributes.ceil_mode, kernelShape: attributes.kernel_shape, strides: attributes.strides, pads: attributes.pads }); createAveragePoolProgramInfo = (name, input, isGlobalOperator, attributes) => { const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape( input, attributes, isGlobalOperator ); const x = inputVariable("x", input.dataType, input.dims.length); const dataType = x.type.value; const op1 = "value += x_val;"; let op2 = ""; if (adjustedAttributes.countIncludePad) { op2 += `value /= ${dataType}(uniforms.kernelSize);`; } else { op2 += `value /= ${dataType}(i32(uniforms.kernelSize) - pad);`; } const [programUniforms, uniforms, hasPads, pwStartEndNotZero, phStartEndNotZero] = getUniformAndPadInfo( outputShape, adjustedAttributes ); programUniforms.push(...createTensorShapeVariables(input.dims, outputShape)); const inputDependencies = ["rank"]; return { name, shaderCache: { hint: `${attributes.cacheKey};${hasPads};${pwStartEndNotZero};${phStartEndNotZero}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: input.dataType }], dispatchGroup: { x: Math.ceil( ShapeUtil.size(outputShape) / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource: (shaderHelper) => generatePoolingCode( shaderHelper, x, input.dims.length, outputShape.length, adjustedAttributes, op1, op2, 0, uniforms, hasPads, pwStartEndNotZero, phStartEndNotZero ) }; }; parseAveragePoolAttributes = (attributes) => { const countIncludePad = attributes.count_include_pad === 0 ? false : true; const attr = parsePoolCommonAttributes(attributes); if (attr.ceilMode !== 0) { throw new Error("using ceil() in shape computation is not yet supported for AveragePool"); } const averagePoolAttributes = { countIncludePad, ...attr, cacheKey: "" }; return { ...averagePoolAttributes, cacheKey: createAveragePoolShaderKeyFromAttributes(averagePoolAttributes) }; }; averagePool = (context, attributes) => { validateInputs25(context.inputs); context.compute(createAveragePoolProgramInfo("AveragePool", context.inputs[0], false, attributes)); }; globalPoolAttributes = { autoPad: "", ceilMode: 0, countIncludePad: false, kernelShape: [], strides: [], pads: [], storageOrder: 0, dilations: [] }; parseGlobalAveragePoolAttributes = (attributes) => { const format = attributes.format; return { format, ...globalPoolAttributes, cacheKey: format }; }; globalAveragePool = (context, attributes) => { validateInputs25(context.inputs); context.compute(createAveragePoolProgramInfo("GlobalAveragePool", context.inputs[0], true, attributes)); }; createMaxPoolProgramInfo = (name, input, isGlobalOperator, attributes) => { const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape( input, attributes, isGlobalOperator ); const op1 = ` value = max(x_val, value); `; const op2 = ""; const x = inputVariable("x", input.dataType, input.dims.length); const inputDependencies = ["rank"]; const [programUniforms, uniforms, hasPads, pwStartEndNotZero, phStartEndNotZero] = getUniformAndPadInfo( outputShape, adjustedAttributes ); programUniforms.push(...createTensorShapeVariables(input.dims, outputShape)); return { name, shaderCache: { hint: `${attributes.cacheKey};${hasPads};${pwStartEndNotZero};${phStartEndNotZero}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: input.dataType }], dispatchGroup: { x: Math.ceil( ShapeUtil.size(outputShape) / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource: (shaderHelper) => generatePoolingCode( shaderHelper, x, input.dims.length, outputShape.length, adjustedAttributes, op1, op2, input.dataType === 10 /* float16 */ ? -65504 : -1e5, uniforms, hasPads, pwStartEndNotZero, phStartEndNotZero ) }; }; maxPool = (context, attributes) => { validateInputs25(context.inputs); context.compute(createMaxPoolProgramInfo("MaxPool", context.inputs[0], false, attributes)); }; parseMaxPoolAttributes = (attributes) => { const storageOrder = attributes.storage_order; const dilations = attributes.dilations; const attr = parsePoolCommonAttributes(attributes); if (storageOrder !== 0) { throw new Error("column major storage order is not yet supported for MaxPool"); } if (attr.ceilMode !== 0) { throw new Error("using ceil() in shape computation is not yet supported for MaxPool"); } const maxPoolAttributes = { storageOrder, dilations, ...attr, cacheKey: "" }; return { ...maxPoolAttributes, cacheKey: createMaxPoolShaderKeyFromAttributes(maxPoolAttributes) }; }; parseGlobalMaxPoolAttributes = (attributes) => { const format = attributes.format; return { format, ...globalPoolAttributes, cacheKey: format }; }; globalMaxPool = (context, attributes) => { validateInputs25(context.inputs); context.compute(createMaxPoolProgramInfo("GlobalMaxPool", context.inputs[0], true, attributes)); }; } }); // web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts var validateInputs26, createDequantizeLinearProgramInfo, dequantizeLinear, parseDequantizeLinearAttributes; var init_quantize_linear = __esm({ "web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs26 = (inputs, attributes) => { if (inputs.length < 2 || inputs.length > 3) { throw new Error("DequantizeLinear requires 2 or 3 inputs."); } if (inputs.length === 3 && inputs[1].dims === inputs[2].dims) { throw new Error("x-scale and x-zero-point must have the same shape."); } if (inputs.length === 3 && inputs[0].dataType !== inputs[2].dataType) { throw new Error("x and x-zero-point must have the same data type."); } if (inputs[1].dims.length !== 0 && inputs[1].dims.length !== 1 && inputs[1].dims.length !== inputs[0].dims.length) { throw new Error("scale input must be a scalar, a 1D tensor, or have the same rank as the input tensor."); } if (inputs.length > 2) { if (inputs[0].dataType !== inputs[2].dataType) { throw new Error("x and x-zero-point must have the same data type."); } if (inputs[1].dims.length !== inputs[2].dims.length) { throw new Error("scale and zero-point inputs must have the same rank."); } if (!inputs[1].dims.map((d, i) => d === inputs[2].dims[i]).reduce((a, b) => a && b, true)) { throw new Error("scale and zero-point inputs must have the same shape."); } } if (attributes.blockSize > 0) { if (inputs[1].dims.length === 0 || inputs[1].dims.length === 1 && inputs[1].dims[0] === 1) { throw new Error("blockSize must be set only for block quantization."); } if (!inputs[1].dims.map((d, i) => i === attributes.axis || d === inputs[0].dims[i]).reduce((a, b) => a && b, true)) { throw new Error("For block qunatization, scale input shape to match the input shape except for the axis"); } if (inputs[1].dims.length !== inputs[0].dims.length) { throw new Error("For block qunatization the scale input rank must be the same as the x rank."); } const dI = inputs[0].dims[attributes.axis]; const si = inputs[1].dims[attributes.axis]; if (attributes.blockSize < Math.ceil(dI / si) || attributes.blockSize > Math.ceil(dI / (si - 1) - 1)) { throw new Error("blockSize must be with in the range [ceil(dI / Si), ceil(dI / (Si - 1) - 1)]."); } } }; createDequantizeLinearProgramInfo = (inputs, attributes) => { const axis = ShapeUtil.normalizeAxis(attributes.axis, inputs[0].dims.length); const inputType = inputs[0].dataType; const isSigned = inputType === 3 /* int8 */; const outputShape = inputs[0].dims; const dataType = inputs[1].dataType; const outputSize = ShapeUtil.size(outputShape); const isPacked = inputType === 3 /* int8 */ || inputType === 2 /* uint8 */; const inputShape = isPacked ? [Math.ceil(ShapeUtil.size(inputs[0].dims) / 4)] : inputs[0].dims; const scaleShape = inputs[1].dims; const zeroPointInput = inputs.length > 2 ? inputs[2] : void 0; const zeroPointShape = zeroPointInput ? isPacked ? [Math.ceil(ShapeUtil.size(zeroPointInput.dims) / 4)] : zeroPointInput.dims : void 0; const perLayerQuantization = scaleShape.length === 0 || scaleShape.length === 1 && scaleShape[0] === 1; const perAxisQuantization = perLayerQuantization === false && scaleShape.length === 1; const maxComponents = getMaxComponents(outputSize); const useComponents = perLayerQuantization && (!isPacked || maxComponents === 4); const components = useComponents ? maxComponents : 1; const inputComponent = useComponents && !isPacked ? maxComponents : 1; const input = inputVariable("input", isPacked ? 12 /* uint32 */ : inputType, inputShape.length, inputComponent); const scale = inputVariable("scale", dataType, scaleShape.length); const zeroPoint = zeroPointInput ? inputVariable("zero_point", isPacked ? 12 /* uint32 */ : inputType, zeroPointShape.length) : void 0; const output = outputVariable("output", dataType, outputShape.length, components); const inputVariables = [input, scale]; if (zeroPoint) { inputVariables.push(zeroPoint); } const inputShapes = [inputShape, scaleShape]; if (zeroPointInput) { inputShapes.push(zeroPointShape); } const programUniforms = [ { type: 12 /* uint32 */, data: outputSize / components }, { type: 12 /* uint32 */, data: axis }, { type: 12 /* uint32 */, data: attributes.blockSize }, ...createTensorShapeVariables(...inputShapes, outputShape) ]; const getShaderSource = (shaderHelper) => { const uniforms = [ { name: "output_size", type: "u32" }, { name: "axis", type: "u32" }, { name: "block_size", type: "u32" } ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let output_indices = ${output.offsetToIndices("global_idx")}; // Set input x ${(() => { if (isPacked) { return ` let input = ${input.getByOffset("global_idx / 4")}; let x_vec = ${isSigned ? "unpack4xI8(input)" : "unpack4xU8(input)"}; let x_value = ${components === 1 ? "x_vec[global_idx % 4]" : "x_vec"};`; } else { return `let x_value = ${input.getByOffset("global_idx")};`; } })()}; // Set scale input ${(() => { if (perLayerQuantization) { return `let scale_value= ${scale.getByOffset("0")}`; } else if (perAxisQuantization) { return ` let scale_index = ${output.indicesGet("output_indices", "uniforms.axis")}; let scale_value= ${scale.getByOffset("scale_index")};`; } else { return ` var scale_indices: ${scale.type.indices} = output_indices; let index = ${scale.indicesGet("scale_indices", "uniforms.axis")} / uniforms.block_size; ${scale.indicesSet("scale_indices", "uniforms.axis", "index")}; let scale_value= ${scale.getByIndices("scale_indices")};`; } })()}; // Set zero-point input ${(() => { if (zeroPoint) { if (perLayerQuantization) { if (isPacked) { return ` let zero_point_input = ${zeroPoint.getByOffset("0")}; let zero_point_vec = ${isSigned ? "unpack4xI8(zero_point_input)" : "unpack4xU8(zero_point_input)"}; let zero_point_value= zero_point_vec[0]`; } else { return `let zero_point_value = ${zeroPoint.getByOffset("0")}`; } } else if (perAxisQuantization) { if (isPacked) { return ` let zero_point_index = ${output.indicesGet("output_indices", "uniforms.axis")}; let zero_point_input = ${zeroPoint.getByOffset("zero_point_index / 4")}; let zero_point_vec = ${isSigned ? "unpack4xI8(zero_point_input)" : "unpack4xU8(zero_point_input)"}; let zero_point_value = zero_point_vec[zero_point_index % 4]`; } else { return ` let zero_point_index = ${output.indicesGet("output_indices", "uniforms.axis")}; let zero_point_value = ${zeroPoint.getByOffset("zero_point_index")};`; } } else { if (isPacked) { return ` let zero_point_offset = ${scale.indicesToOffset("scale_indices")}; let zero_point_input = ${zeroPoint.getByOffset("zero_point_offset / 4")}; let zero_point_vec = ${isSigned ? "unpack4xI8(zero_point_input)" : "unpack4xU8(zero_point_input)"}; let zero_point_value = zero_point_vec[zero_point_offset % 4];`; } else { return `let zero_point_value = ${zeroPoint.getByIndices("scale_indices")};`; } } } else { return `let zero_point_value = ${isPacked ? isSigned ? "i32" : "u32" : input.type.value}(0);`; } })()}; // Compute and write output ${output.setByOffset("global_idx", `${output.type.value}(x_value - zero_point_value) * scale_value`)}; }`; }; return { name: "DequantizeLinear", shaderCache: { hint: attributes.cacheKey, inputDependencies: zeroPoint ? ["rank", "rank", "rank"] : ["rank", "rank"] }, getShaderSource, getRunData: () => ({ outputs: [{ dims: outputShape, dataType }], dispatchGroup: { x: Math.ceil(outputSize / components / 64), y: 1, z: 1 }, programUniforms }) }; }; dequantizeLinear = (context, attributes) => { validateInputs26(context.inputs, attributes); context.compute(createDequantizeLinearProgramInfo(context.inputs, attributes)); }; parseDequantizeLinearAttributes = (attributes) => createAttributeWithCacheKey({ axis: attributes.axis, blockSize: attributes.blockSize }); } }); // web/lib/wasm/jsep/webgpu/ops/range.ts var validateInputsContent, createRangeProgramInfo, range; var init_range = __esm({ "web/lib/wasm/jsep/webgpu/ops/range.ts"() { "use strict"; init_esm(); init_wasm_common(); init_common(); validateInputsContent = (start, limit, delta) => { const sameStartLimit = start === limit; const increasingRangeNegativeStep = start < limit && delta < 0; const decreasingRangePositiveStep = start > limit && delta > 0; if (sameStartLimit || increasingRangeNegativeStep || decreasingRangePositiveStep) { throw new Error("Range these inputs' contents are invalid."); } }; createRangeProgramInfo = (start, limit, delta, dataType) => { const numElements = Math.abs(Math.ceil((limit - start) / delta)); const outputShape = [numElements]; const outputSize = numElements; const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: dataType, data: start }, { type: dataType, data: delta }, ...createTensorShapeVariables(outputShape) ]; const getShaderSource = (shaderHelper) => { const output = outputVariable("output", dataType, outputShape.length); const wgslType = output.type.value; const uniforms = [ { name: "outputSize", type: "u32" }, { name: "start", type: wgslType }, { name: "delta", type: wgslType } ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} output[global_idx] = uniforms.start + ${wgslType}(global_idx) * uniforms.delta; }`; }; return { name: "Range", shaderCache: { hint: `${dataType}` }, getShaderSource, getRunData: () => ({ outputs: [{ dims: outputShape, dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }) }; }; range = (context) => { let start = 0; let limit = 0; let delta = 0; if (context.inputs[0].dataType === 6 /* int32 */) { start = context.inputs[0].getInt32Array()[0]; limit = context.inputs[1].getInt32Array()[0]; delta = context.inputs[2].getInt32Array()[0]; } else if (context.inputs[0].dataType === 1 /* float */) { start = context.inputs[0].getFloat32Array()[0]; limit = context.inputs[1].getFloat32Array()[0]; delta = context.inputs[2].getFloat32Array()[0]; } if (env2.webgpu.validateInputContent) { validateInputsContent(start, limit, delta); } context.compute(createRangeProgramInfo(start, limit, delta, context.inputs[0].dataType), { inputs: [] }); }; } }); // web/lib/wasm/jsep/webgpu/ops/scatter-nd.ts var atomicReductionSnippet, createScatterNDProgramInfo, parseScatterNDAttributes, scatterND; var init_scatter_nd = __esm({ "web/lib/wasm/jsep/webgpu/ops/scatter-nd.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); atomicReductionSnippet = (reduction, ptr, v, type) => { if (reduction !== "none" && type !== "i32" && type !== "u32" && type !== "f32") { throw new Error(`Input ${type} is not supported with reduction ${reduction}.`); } const floatStart = `{ var oldValue = 0; loop { let newValueF32 =`; const floatEnd = `; let newValue = bitcast(newValueF32); let res = atomicCompareExchangeWeak(&${ptr}, oldValue, newValue); if res.exchanged { break; } oldValue = res.old_value; } }`; switch (reduction) { case "none": return `${ptr}=${v};`; case "add": if (type === "i32" || type === "u32") { return `atomicAdd(&${ptr}, bitcast<${type}>(${v}));`; } else { return ` ${floatStart}bitcast<${type}>(oldValue) + (${v})${floatEnd}`; } case "max": if (type === "i32" || type === "u32") { return `atomicMax(&${ptr}, bitcast<${type}>(${v}));`; } else { return ` ${floatStart}max(bitcast(oldValue), (${v}))${floatEnd}`; } case "min": if (type === "i32" || type === "u32") { return `atomicMin(&${ptr}, bitcast<${type}>(${v}));`; } else { return `${floatStart}min(bitcast<${type}>(oldValue), (${v}))${floatEnd}`; } case "mul": return `${floatStart}(bitcast<${type}>(oldValue) * (${v}))${floatEnd}`; default: throw new Error(`Reduction ${reduction} is not supported.`); } }; createScatterNDProgramInfo = (inputs, attributes) => { const inputShape = inputs[0].dims; const indicesShape = inputs[1].dims; const outputShape = inputShape; const components = 1; const outputSize = Math.ceil(ShapeUtil.sizeToDimension(indicesShape, indicesShape.length - 1) / components); const lastIndexDimension = indicesShape[indicesShape.length - 1]; const numUpdatesElements = ShapeUtil.sizeFromDimension(inputShape, lastIndexDimension); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: lastIndexDimension }, { type: 12 /* uint32 */, data: numUpdatesElements }, ...createTensorShapeVariables(inputs[1].dims, inputs[2].dims, outputShape) ]; const getShaderSource = (shaderHelper) => { const indices = inputVariable("indices", inputs[1].dataType, inputs[1].dims.length); const updates = inputVariable("updates", inputs[2].dataType, inputs[2].dims.length, components); const output = attributes.reduction !== "none" && attributes.reduction !== "" ? atomicOutputVariable("output", inputs[0].dataType, outputShape.length) : outputVariable("output", inputs[0].dataType, outputShape.length, components); return ` ${shaderHelper.registerUniform("output_size", "u32").registerUniform("last_index_dimension", "u32").registerUniform("num_updates_elements", "u32").declareVariables(indices, updates, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} var data_offset = 0u; let indices_start = uniforms.last_index_dimension * global_idx; let indices_end = indices_start + uniforms.last_index_dimension; for (var i = indices_start; i < indices_end; i++) { var index = i32(indices[i].x); ${inputs[0].dims.length === 1 ? ` let element_count_dim = uniforms.output_strides; let dim_value = uniforms.output_shape;` : ` let element_count_dim = uniforms.output_strides[i - indices_start]; let dim_value = uniforms.output_shape[i - indices_start];`} if (index >= 0) { if (index >= i32(dim_value)) { index = i32(dim_value - 1); } } else { if (index < -i32(dim_value)) { index = 0; } else { index += i32(dim_value); } } data_offset += u32((u32(index) * element_count_dim)); } for (var i = 0u; i < uniforms.num_updates_elements; i++) { let value = updates[uniforms.num_updates_elements * global_idx + i]; ${atomicReductionSnippet( attributes.reduction, "output[data_offset + i]", "value", output.type.value )} } }`; }; return { name: "ScatterND", shaderCache: { hint: `${attributes.cacheKey}_${attributes.reduction}`, inputDependencies: ["rank", "rank"] }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms }), getShaderSource }; }; parseScatterNDAttributes = (attributes) => createAttributeWithCacheKey({ reduction: attributes.reduction }); scatterND = (context, attributes) => { context.compute(createScatterNDProgramInfo(context.inputs, attributes), { inputs: [context.inputs[1], context.inputs[2]], outputs: [] }); }; } }); // web/lib/wasm/jsep/webgpu/ops/resize.ts var validateScales, updateScales, validateInputs27, getSafeIntegerDivision, getOriginalCoordinateFromResizedCoordinate, getNearestPixelFromOriginal, updateRoI, initOutputShape, adjustOutputShape, calculateOriginalIndicesFromOutputIndices, calculateInputIndicesFromOutputIndices, checkInputIndices, setChannelAndBatchIndices, bilinearInterpolation, bicubicInterpolation, trilinearInterpolation, createResizeProgramInfo, getOpsetVersionFromCustomDataBuffer, resize, parseResizeAttributes; var init_resize = __esm({ "web/lib/wasm/jsep/webgpu/ops/resize.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateScales = (scales, attributes) => { scales.every( (value) => value > 0 || (() => { throw new Error("Resize requires scales input values to be positive"); }) ); if (scales.length > 0) { if (attributes.mode === "linear") { if (!(scales.length === 2 || scales.length === 3 || scales.length === 4 && scales[0] === 1 && scales[1] === 1 || scales.length === 4 && scales[0] === 1 && scales[3] === 1 || scales.length === 5 && scales[0] === 1 && scales[1] === 1)) { throw new Error( `For linear mode, Resize requires scales to be 2D, 3D, 4D with either two outermost or one innermost and one outermost scale values equal to 1, or 5D with two outermost scale values equal to 1` ); } } else if (attributes.mode === "cubic") { if (!(scales.length === 2 || scales.length === 4 && scales[0] === 1 && scales[1] === 1 || scales.length === 4 && scales[0] === 1 && scales[3] === 1)) { throw new Error("Resize requires scales input size to be 2 or 4 for cubic mode"); } } } }; updateScales = (scales, axes, rank) => { axes.every( (value) => value >= 0 && value < rank || (() => { throw new Error("Resize requires axes input values to be positive and less than rank"); }) ); const newScales = new Array(rank).fill(1); axes.forEach((value, index) => newScales[value] = scales[index]); return newScales; }; validateInputs27 = (inputs, attributes, opsetVersion, scales, sizes, roi) => { const [roiInputIndex, scalesInputIndex, sizesInputIndex] = opsetVersion > 10 ? [1, 2, 3] : [-1, inputs.length > 1 ? 1 : -1, -1]; const rank = inputs[0].dims.length; if (roiInputIndex > 0 && inputs.length > roiInputIndex && inputs[roiInputIndex].dims.length > 0) { inputs[roiInputIndex].getFloat32Array().forEach((value) => roi.push(value)); } else if (attributes.coordinateTransformMode === "tf_crop_and_resize") { throw new Error("Resize requires RoI input to be specified when coordinateTransformMode is tfCropAndResize"); } if (scalesInputIndex > 0 && inputs.length > scalesInputIndex && inputs[scalesInputIndex].dims.length === 1 && inputs[scalesInputIndex].dims[0] > 0) { inputs[scalesInputIndex].getFloat32Array().forEach((value) => scales.push(value)); if (scales.length !== 0 && scales.length !== rank && opsetVersion >= 18 && scales.length !== attributes.axes.length) { throw new Error("Resize requires scales input size to be same as input rank or axes size for opset 18 and up"); } validateScales(scales, attributes); if (attributes.axes.length > 0) { updateScales(scales, attributes.axes, rank).forEach((value, index) => scales[index] = value); } } if (sizesInputIndex > 0 && inputs.length > sizesInputIndex && inputs[sizesInputIndex].dims.length === 1 && inputs[sizesInputIndex].dims[0] > 0) { inputs[sizesInputIndex].getBigInt64Array().forEach((value) => sizes.push(Number(value))); if (sizes.length !== 0 && sizes.length !== rank && opsetVersion >= 18 && sizes.length !== attributes.axes.length) { throw new Error("Resize requires sizes input size to be same as input rank or axes size for opset 18 and up"); } } if (attributes.axes.length > 0) { if (scales.length !== 0 && scales.length !== attributes.axes.length) { throw new Error('Resize requires "scales" input size to be of axes rank when axes attributes is specified'); } if (sizes.length !== 0 && sizes.length !== attributes.axes.length) { throw new Error('Resize requires "sizes" input size to be of rank axes rank when axes attributes is specified'); } } if (typeof scales !== "undefined" && typeof sizes !== "undefined" && scales.length > 0 && sizes.length > rank) { throw new Error("Resize requires only of scales or sizes to be specified"); } }; getSafeIntegerDivision = (a, b, c, dType) => ` // The whole part and the fractional part are calculated separately due to inaccuracy of floating // point division. As an example, f32(21) / f32(7) may evaluate to 2.99... instead of 3, causing an // offset-by-one error later in floor(). let big = (${a}) * (${b}); let whole = ${dType}(big / (${c})); let fract = ${dType}(big % (${c})) / ${dType}(${c}); return whole + fract; `; getOriginalCoordinateFromResizedCoordinate = (coordinateTransferMode, dType) => `fn getOriginalCoordinateFromResizedCoordinate(xResized: u32, xScale: f32, lengthResized: u32, lengthOriginal: u32, roiStart: f32, roiEnd: f32) -> ${dType} { ` + (() => { switch (coordinateTransferMode) { case "asymmetric": return ` if (xScale < 1.0 || floor(xScale) != xScale) { return ${dType}(xResized) / ${dType}(xScale); } else { ${getSafeIntegerDivision("xResized", "lengthOriginal", "lengthResized", dType)} } `; case "pytorch_half_pixel": return `if (lengthResized > 1) { return (${dType}(xResized) + 0.5) / ${dType}(xScale) - 0.5; } else { return 0.0; }`; case "tf_half_pixel_for_nn": return `return (${dType}(xResized) + 0.5) / ${dType}(xScale);`; case "align_corners": return `if (lengthResized == 1) { return 0.0; } else { ${getSafeIntegerDivision("xResized", "lengthOriginal - 1", "lengthResized - 1", dType)} }`; case "tf_crop_and_resize": return `if (lengthResized > 1) { return ${dType}(roiStart) * ${dType}(lengthOriginal - 1) + (${dType}(xResized) * ${dType}(roiEnd - roiStart) * ${dType}(lengthOriginal - 1)) / ${dType}(lengthResized - 1); } else { return 0.5 * ${dType}(roiStart + roiEnd) * ${dType}(lengthOriginal - 1); }`; case "half_pixel_symmetric": return `const outputWidth = ${dType}xScale * ${dType}(lengthResized); const adjustment = ${dType}(lengthResized) / outputWidth; const center = ${dType}(lengthOriginal) / 2; const offset = center * (1 - adjustment); return offset + ((${dType}(xResized) + 0.5) / ${dType}(xScale)) - 0.5;`; case "half_pixel": return `return ((${dType}(xResized) + 0.5) / ${dType}(xScale)) - 0.5;`; default: throw new Error(`Coordinate transform mode ${coordinateTransferMode} is not supported`); } })() + "}"; getNearestPixelFromOriginal = (nearestMode, opsetVersion, dType) => `fn getNearestPixelFromOriginal(xOriginal: ${dType}, isDownSample: bool) -> ${dType} {` + (() => { switch (nearestMode) { case "round_prefer_ceil": return "if (fract(xOriginal) == 0.5) { return ceil(xOriginal); } else { return round(xOriginal); }"; case "floor": return "return floor(xOriginal);"; case "ceil": return "return ceil(xOriginal);"; case "round_prefer_floor": return "if (fract(xOriginal) == 0.5) { return floor(xOriginal); } else { return round(xOriginal); }"; case "simple": default: if (opsetVersion < 11) { return "if (isDownSample) { return ceil(xOriginal); } else { return xOriginal; }"; } throw new Error(`Nearest mode ${nearestMode} is not supported`); } })() + "}"; updateRoI = (roi, axes, rank) => { const roiTmp = new Array(rank).fill(0).concat(new Array(rank).fill(1)); const roiLocal = roi.length === 0 ? roiTmp : roi.slice(); if (axes.length > 0) { axes.forEach((v, i) => { roiTmp[v] = roiLocal[i]; roiTmp[i + rank] = roiLocal[axes.length + i]; }); return roiTmp; } return roiLocal; }; initOutputShape = (inputShape, scales, sizes, axes) => { let outputShape = []; if (sizes.length > 0) { if (axes.length > 0) { inputShape.forEach((v) => outputShape.push(v)); if (Math.max(...axes) > inputShape.length) { throw new Error("axes is out of bound"); } axes.forEach((v, i) => outputShape[v] = sizes[i]); } else { sizes.forEach((v) => outputShape.push(v)); } } else { if (scales.length === 0) { throw new Error("Resize requires either scales or sizes."); } else { outputShape = inputShape.map((value, index) => Math.round(value * scales[index])); } } return outputShape; }; adjustOutputShape = (inputShape, scales, attributes) => { const scaleInPolicy = (() => { switch (attributes.keepAspectRatioPolicy) { case "not_larger": return attributes.axes.length > 0 ? Math.min(...attributes.axes.map((i) => scales[i]), Number.MAX_VALUE) : Math.min(...scales, Number.MAX_VALUE); case "not_smaller": return attributes.axes.length > 0 ? Math.max(...attributes.axes.map((i) => scales[i]), Number.MIN_VALUE) : Math.max(...scales, Number.MIN_VALUE); default: throw new Error(`Keep aspect ratio policy ${attributes.keepAspectRatioPolicy} is not supported`); } })(); scales.fill(1, 0, scales.length); const adjustedOutputShape = inputShape.slice(); if (attributes.axes.length > 0) { attributes.axes.forEach((v) => scales[v] = scaleInPolicy); attributes.axes.forEach((v) => adjustedOutputShape[v] = Math.round(inputShape[v] * scales[v])); } else { scales.fill(scaleInPolicy, 0, scales.length); adjustedOutputShape.forEach((v, i) => adjustedOutputShape[i] = Math.round(v * scales[i])); } return adjustedOutputShape; }; calculateOriginalIndicesFromOutputIndices = (output, inputShape, outputShape, scalesLength, roiLength) => ` fn calculateOriginalIndicesFromOutputIndices(output_indices: ${output.type.indices}) -> array<${output.type.value}, ${outputShape.length}> { var original_indices: array<${output.type.value}, ${outputShape.length}>; for (var i:u32 = 0; i < ${outputShape.length}; i++) { var output_index = ${output.indicesGet("output_indices", "i")}; var scale = ${getElementAt("uniforms.scales", "i", scalesLength)}; var roi_low = ${getElementAt("uniforms.roi", "i", roiLength)}; var roi_hi = ${getElementAt("uniforms.roi", `i + ${inputShape.length}`, roiLength)}; if (scale == 1.0) { original_indices[i] = ${output.type.value}(output_index); } else { var input_shape_i = ${getElementAt("uniforms.input_shape", "i", inputShape.length)}; var output_shape_i = ${getElementAt("uniforms.output_shape", "i", outputShape.length)}; original_indices[i] = getOriginalCoordinateFromResizedCoordinate(output_index, scale, output_shape_i, input_shape_i, roi_low, roi_hi); } } return original_indices; }`; calculateInputIndicesFromOutputIndices = (input, output, inputShape, outputShape, scalesLength, roiLength, useExtrapolation) => ` fn calculateInputIndicesFromOutputIndices(output_indices: ${output.type.indices}) -> ${input.type.indices} { var input_indices: ${input.type.indices}; for (var i:u32 = 0; i < ${outputShape.length}; i++) { var output_index = ${output.indicesGet("output_indices", "i")}; var input_index: u32; var scale = ${getElementAt("uniforms.scales", "i", scalesLength)}; if (scale == 1.0) { input_index = output_index; } else { var roi_low = ${getElementAt("uniforms.roi", "i", roiLength)}; var roi_hi = ${getElementAt("uniforms.roi", `i + ${inputShape.length}`, roiLength)}; var input_shape_i = ${getElementAt("uniforms.input_shape", "i", inputShape.length)}; var output_shape_i = ${getElementAt("uniforms.output_shape", "i", outputShape.length)}; var original_idx = getOriginalCoordinateFromResizedCoordinate(output_index, scale, output_shape_i, input_shape_i, roi_low, roi_hi); if (!${useExtrapolation} || (original_idx >= 0 && original_idx < ${output.type.value}(input_shape_i))) { if (original_idx < 0) { input_index = 0; } else if (original_idx > ${output.type.value}(input_shape_i - 1)) { input_index = input_shape_i - 1; } else { input_index = u32(getNearestPixelFromOriginal(original_idx, scale < 1)); } } else { input_index = u32(original_idx); } } ${input.indicesSet("input_indices", "i", "input_index")} } return input_indices; }`; checkInputIndices = (input, inputShape) => ` fn checkInputIndices(input_indices: ${input.type.indices}) -> bool { for (var i:u32 = 0; i < ${inputShape.length}; i++) { var input_index = ${input.indicesGet("input_indices", "i")}; if (input_index < 0 || input_index >= ${getElementAt("uniforms.input_shape", "i", inputShape.length)}) { return false; } } return true; }`; setChannelAndBatchIndices = (input, channelIdx, batchIdx, spacialDims) => input.rank > spacialDims ? ` ${input.indicesSet("input_indices", channelIdx, "channel")}; ${input.indicesSet("input_indices", batchIdx, "batch")}; ` : ""; bilinearInterpolation = (input, output, inputShape, useExtrapolation, extrapolationValue) => { const isNchw = true; const [batchIdx, heightIdx, widthIdx, channelIdx] = inputShape.length === 2 ? [-1, 0, 1, -1] : isNchw ? [0, 2, 3, 1] : [0, 1, 2, 3]; const dType = input.type.value; return ` fn getInputValue(batch: u32, channel: u32, row: u32, col: u32) -> ${dType} { var input_indices: ${input.type.indices}; ${input.indicesSet("input_indices", heightIdx, `max(0, min(row, ${inputShape[heightIdx]} - 1))`)}; ${input.indicesSet("input_indices", widthIdx, `max(0, min(col, ${inputShape[widthIdx]} - 1))`)}; ${setChannelAndBatchIndices(input, channelIdx, batchIdx, 2)} return ${input.getByIndices("input_indices")}; } fn bilinearInterpolation(output_indices: ${output.type.indices}) -> ${dType} { var originalIndices = calculateOriginalIndicesFromOutputIndices(output_indices); var row:${dType} = originalIndices[${heightIdx}]; var col:${dType} = originalIndices[${widthIdx}]; ${useExtrapolation ? `if (row < 0 || row > (${inputShape[heightIdx]} - 1) || col < 0 || col > (${inputShape[widthIdx]} - 1)) { return ${extrapolationValue}; }` : ""}; row = max(0, min(row, ${inputShape[heightIdx]} - 1)); col = max(0, min(col, ${inputShape[widthIdx]} - 1)); var row1: u32 = u32(row); var col1: u32 = u32(col); var row2: u32 = u32(row + 1); var col2: u32 = u32(col + 1); var channel: u32 = ${inputShape.length > 2 ? `u32(originalIndices[${channelIdx}])` : "0"}; var batch: u32 = ${inputShape.length > 2 ? `u32(originalIndices[${batchIdx}])` : "0"}; var x11: ${dType} = getInputValue(batch, channel, row1, col1); var x12: ${dType} = getInputValue(batch, channel, row1, col2); var x21: ${dType} = getInputValue(batch, channel, row2, col1); var x22: ${dType} = getInputValue(batch, channel, row2, col2); var dx1: ${dType} = abs(row - ${dType}(row1)); var dx2: ${dType} = abs(${dType}(row2) - row); var dy1: ${dType} = abs(col - ${dType}(col1)); var dy2: ${dType} = abs(${dType}(col2) - col); if (row1 == row2) { dx1 = 0.5; dx2 = 0.5; } if (col1 == col2) { dy1 = 0.5; dy2 = 0.5; } return (x11 * dx2 * dy2 + x12 * dx2 * dy1 + x21 * dx1 * dy2 + x22 * dx1 * dy1); }`; }; bicubicInterpolation = (input, output, inputShape, outputShape, scales, roi, cubicCoeffA, useExtrapolation, extrapolationValue, excludeOutside) => { const is2D = inputShape.length === 2; const isNchw = true; const [heightIdx, widthIdx] = is2D ? [0, 1] : isNchw ? [2, 3] : [1, 2]; const dType = input.type.value; const createCubicInterpolationFunction = (idx) => { const direction = idx === heightIdx ? "row" : "col"; return ` fn ${direction}CubicInterpolation(input_indices: ${input.type.indices}, output_indices: ${output.type.indices}) -> ${dType} { var output_index = ${output.indicesGet("output_indices", idx)}; var originalIdx: ${dType} = getOriginalCoordinateFromResizedCoordinate(output_index, ${scales[idx]}, ${outputShape[idx]}, ${inputShape[idx]}, ${roi[idx]}, ${roi[idx]} + ${inputShape.length}); var fractOriginalIdx: ${dType} = originalIdx - floor(originalIdx); var coefs = getCubicInterpolationCoefs(fractOriginalIdx); if (${useExtrapolation} && (originalIdx < 0 || originalIdx > (${inputShape[idx]} - 1))) { return ${extrapolationValue}; } var data: array<${dType}, 4> = array<${dType}, 4>(0.0, 0.0, 0.0, 0.0); for (var i: i32 = -1; i < 3; i++) { var ${direction}: ${dType} = originalIdx + ${dType}(i); if (${direction} < 0 || ${direction} >= ${inputShape[idx]}) { ${(() => { if (excludeOutside) { return `coefs[i + 1] = 0.0; continue;`; } else if (useExtrapolation) { return `return ${extrapolationValue};`; } else { return `${direction} = max(0, min(${direction}, ${inputShape[idx]} - 1));`; } })()}; } var input_indices_copy: ${input.type.indices} = input_indices; ${input.indicesSet("input_indices_copy", idx, `u32(${direction})`)}; data[i + 1] = ${idx === heightIdx ? input.getByIndices("input_indices_copy") : "rowCubicInterpolation(input_indices_copy, output_indices)"}; } return cubicInterpolation1D(data, coefs); }`; }; return ` ${createCubicInterpolationFunction(heightIdx)}; ${createCubicInterpolationFunction(widthIdx)}; fn getCubicInterpolationCoefs(s: ${dType}) -> array<${dType}, 4> { var absS = abs(s); var coeffs: array<${dType}, 4> = array<${dType}, 4>(0.0, 0.0, 0.0, 0.0); var oneMinusAbsS: ${dType} = 1.0 - absS; var twoMinusAbsS: ${dType} = 2.0 - absS; var onePlusAbsS: ${dType} = 1.0 + absS; coeffs[0] = ((${cubicCoeffA} * onePlusAbsS - 5 * ${cubicCoeffA}) * onePlusAbsS + 8 * ${cubicCoeffA}) * onePlusAbsS - 4 * ${cubicCoeffA}; coeffs[1] = ((${cubicCoeffA} + 2) * absS - (${cubicCoeffA} + 3)) * absS * absS + 1; coeffs[2] = ((${cubicCoeffA} + 2) * oneMinusAbsS - (${cubicCoeffA} + 3)) * oneMinusAbsS * oneMinusAbsS + 1; coeffs[3] = ((${cubicCoeffA} * twoMinusAbsS - 5 * ${cubicCoeffA}) * twoMinusAbsS + 8 * ${cubicCoeffA}) * twoMinusAbsS - 4 * ${cubicCoeffA}; return coeffs; } fn cubicInterpolation1D(x: array<${dType}, 4>, coefs: array<${dType}, 4>) -> ${dType} { var coefsSum: ${dType} = coefs[0] + coefs[1] + coefs[2] + coefs[3]; return (x[0] * coefs[0] + x[1] * coefs[1]+ x[2] * coefs[2]+ x[3] * coefs[3]) / coefsSum; } fn bicubicInterpolation(output_indices: ${output.type.indices}) -> ${dType} { var input_indices: ${input.type.indices} = output_indices; return colCubicInterpolation(input_indices, output_indices); } `; }; trilinearInterpolation = (input, output, inputShape, useExtrapolation, extrapolationValue) => { const isNchw = true; const [batchIdx, depthIdx, heightIdx, widthIdx, channelIdx] = inputShape.length === 3 ? [-1, 0, 1, 2, -1] : isNchw ? [0, 2, 3, 4, 1] : [0, 1, 2, 3, 4]; const dType = input.type.value; return ` fn getInputValue(batch: u32, channel: u32, depth:u32, height: u32, width: u32) -> ${dType} { var input_indices: ${input.type.indices}; ${input.indicesSet("input_indices", depthIdx, `max(0, min(depth, ${inputShape[depthIdx]} - 1))`)}; ${input.indicesSet("input_indices", heightIdx, `max(0, min(height, ${inputShape[heightIdx]} - 1))`)}; ${input.indicesSet("input_indices", widthIdx, `max(0, min(width, ${inputShape[widthIdx]} - 1))`)}; ${setChannelAndBatchIndices(input, channelIdx, batchIdx, 3)} return ${input.getByIndices("input_indices")}; } fn trilinearInterpolation(output_indices: ${output.type.indices}) -> ${dType} { var originalIndices = calculateOriginalIndicesFromOutputIndices(output_indices); var depth:${dType} = originalIndices[${depthIdx}]; var height:${dType} = originalIndices[${heightIdx}]; var width:${dType} = originalIndices[${widthIdx}]; ${useExtrapolation ? `if (depth < 0 || depth > (${inputShape[depthIdx]} - 1) || height < 0 || height > (${inputShape[heightIdx]} - 1) || width < 0 || (width > ${inputShape[widthIdx]} - 1)) { return ${extrapolationValue}; }` : ""}; depth = max(0, min(depth, ${inputShape[depthIdx]} - 1)); height = max(0, min(height, ${inputShape[heightIdx]} - 1)); width = max(0, min(width, ${inputShape[widthIdx]} - 1)); var depth1: u32 = u32(depth); var height1: u32 = u32(height); var width1: u32 = u32(width); var depth2: u32 = u32(depth + 1); var height2: u32 = u32(height + 1); var width2: u32 = u32(width + 1); var channel: u32 = ${inputShape.length > 3 ? `u32(originalIndices[${channelIdx}])` : "0"}; var batch: u32 = ${inputShape.length > 3 ? `u32(originalIndices[${batchIdx}])` : "0"}; var x111: ${dType} = getInputValue(batch, channel, depth1, height1, width1); var x112: ${dType} = getInputValue(batch, channel, depth1, height1, width2); var x121: ${dType} = getInputValue(batch, channel, depth1, height2, width1); var x122: ${dType} = getInputValue(batch, channel, depth1, height2, width2); var x211: ${dType} = getInputValue(batch, channel, depth2, height1, width1); var x212: ${dType} = getInputValue(batch, channel, depth2, height1, width2); var x221: ${dType} = getInputValue(batch, channel, depth2, height2, width1); var x222: ${dType} = getInputValue(batch, channel, depth2, height2, width2); var dx1: ${dType} = abs(depth - ${dType}(depth1)); var dx2: ${dType} = abs(${dType}(depth2) - depth); var dy1: ${dType} = abs(height - ${dType}(height1)); var dy2: ${dType} = abs(${dType}(height2) - height); var dz1: ${dType} = abs(width - ${dType}(width1)); var dz2: ${dType} = abs(${dType}(width2) - width); if (depth1 == depth2) { dx1 = 0.5; dx2 = 0.5; } if (height1 == height2) { dy1 = 0.5; dy2 = 0.5; } if (width1 == width2) { dz1 = 0.5; dz2 = 0.5; } return (x111 * dx2 * dy2 * dz2 + x112 * dx2 * dy2 * dz1 + x121 * dx2 * dy1 *dz2 + x122 * dx2 * dy1 * dz1 + x211 * dx1 * dy2 * dz2 + x212 * dx1 * dy2 * dz1 + x221 * dx1 * dy1 *dz2 + x222 * dx1 * dy1 * dz1); }`; }; createResizeProgramInfo = (inputTensor, attributes, opsetVersion, scalesInput, sizes, roiInput) => { const inputShape = inputTensor.dims; const roi = updateRoI(roiInput, attributes.axes, inputShape.length); let outputShape = initOutputShape(inputShape, scalesInput, sizes, attributes.axes); let scales = scalesInput.slice(); if (scalesInput.length === 0) { scales = inputShape.map((value, index) => value === 0 ? 1 : outputShape[index] / value); if (attributes.keepAspectRatioPolicy !== "stretch") { outputShape = adjustOutputShape(inputShape, scales, attributes); } } const output = outputVariable("output", inputTensor.dataType, outputShape.length); const input = inputVariable("input", inputTensor.dataType, inputShape.length); const outputSize = ShapeUtil.size(outputShape); const noScale = inputShape.length === outputShape.length && inputShape.every((d, i) => d === outputShape[i]); const useExtrapolation = attributes.coordinateTransformMode === "tf_crop_and_resize"; const extrapolationValue = attributes.extrapolationValue; const dataType = input.type.value; const getShaderSource = (shaderHelper) => ` ${noScale ? "" : ` ${getOriginalCoordinateFromResizedCoordinate(attributes.coordinateTransformMode, dataType)}; ${(() => { switch (attributes.mode) { case "nearest": return ` ${checkInputIndices(input, inputShape)}; ${getNearestPixelFromOriginal(attributes.nearestMode, opsetVersion, dataType)}; ${calculateInputIndicesFromOutputIndices( input, output, inputShape, outputShape, scales.length, roi.length, useExtrapolation )}; `; case "linear": return ` ${calculateOriginalIndicesFromOutputIndices(output, inputShape, outputShape, scales.length, roi.length)}; ${(() => { if (inputShape.length === 2 || inputShape.length === 4) { return `${bilinearInterpolation(input, output, inputShape, useExtrapolation, extrapolationValue)}`; } else if (inputShape.length === 3 || inputShape.length === 5) { return `${trilinearInterpolation(input, output, inputShape, useExtrapolation, extrapolationValue)}`; } else { throw Error("Linear mode only supports input dims 2, 3, 4 and 5 are supported in linear mode."); } })()}; `; case "cubic": return ` ${(() => { if (inputShape.length === 2 || inputShape.length === 4) { return `${bicubicInterpolation( input, output, inputShape, outputShape, scales, roi, attributes.cubicCoeffA, useExtrapolation, attributes.extrapolationValue, attributes.excludeOutside )}`; } else { throw Error("Cubic mode only supports input dims 2 and 4 are supported in linear mode."); } })()}; `; default: throw Error("Invalid resize mode"); } })()}; `} ${shaderHelper.registerUniform("output_size", "u32").registerUniform("scales", "f32", scales.length).registerUniform("roi", "f32", roi.length).declareVariables(input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} ${noScale ? "output[global_idx] = input[global_idx];" : ` let output_indices = ${output.offsetToIndices("global_idx")}; var input_indices: ${input.type.indices}; ${(() => { switch (attributes.mode) { case "nearest": return `input_indices = calculateInputIndicesFromOutputIndices(output_indices); if (checkInputIndices(input_indices)) { output[global_idx] = ${input.getByIndices("input_indices")}; } else { output[global_idx] = ${attributes.extrapolationValue}; }`; case "linear": return `output[global_idx] = ${inputShape.length === 2 || inputShape.length === 4 ? "bilinearInterpolation" : "trilinearInterpolation"}(output_indices);`; case "cubic": return "output[global_idx] = bicubicInterpolation(output_indices);"; default: throw Error(`Unsupported resize mode: ${attributes.mode}`); } })()}; `} }`; return { name: "Resize", shaderCache: { hint: `${attributes.cacheKey}|${opsetVersion}|${scales.length > 0 ? attributes.mode === "cubic" ? scales : scales.length : ""}|${sizes.length > 0 ? sizes : ""}|${roi.length > 0 ? roi : ""}|${noScale}|${attributes.mode === "nearest" ? inputShape.length : inputShape}`, inputDependencies: ["rank"] }, getShaderSource, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputTensor.dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms: [ { type: 12 /* uint32 */, data: outputSize }, { type: 1 /* float */, data: scales }, { type: 1 /* float */, data: roi }, ...createTensorShapeVariables(inputShape, outputShape) ] }) }; }; getOpsetVersionFromCustomDataBuffer = (context) => { const customDataBuffer = context.customDataBuffer; const customDataBuffer32 = new Uint32Array(customDataBuffer, customDataBuffer.byteOffset, 1); const opsetVersion = customDataBuffer32[0]; return opsetVersion; }; resize = (context, attributes) => { const scales = []; const sizes = []; const roi = []; const opsetVersion = getOpsetVersionFromCustomDataBuffer(context); if (attributes.antialias !== 0) { throw Error("Only default value (0) for Antialias attribute is supported"); } validateInputs27(context.inputs, attributes, opsetVersion, scales, sizes, roi); context.compute(createResizeProgramInfo(context.inputs[0], attributes, opsetVersion, scales, sizes, roi), { inputs: [0] }); }; parseResizeAttributes = (attributes) => { const antialias = attributes.antialias; const axes = attributes.axes; const coordinateTransformMode = attributes.coordinateTransformMode; const cubicCoeffA = attributes.cubicCoeffA; const excludeOutside = attributes.excludeOutside !== 0; const extrapolationValue = attributes.extrapolationValue; const keepAspectRatioPolicy = attributes.keepAspectRatioPolicy; const mode = attributes.mode; const nearestMode = attributes.nearestMode === "" ? "simple" : attributes.nearestMode; return createAttributeWithCacheKey({ antialias, axes, coordinateTransformMode, cubicCoeffA, excludeOutside, extrapolationValue, keepAspectRatioPolicy, mode, nearestMode }); }; } }); // web/lib/wasm/jsep/webgpu/ops/skip-layer-norm.ts var validateInputs28, createSkipLayerNormProgramInfo, skipLayerNorm; var init_skip_layer_norm = __esm({ "web/lib/wasm/jsep/webgpu/ops/skip-layer-norm.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); validateInputs28 = (inputs) => { if (!inputs || inputs.length < 3) { throw new Error("layerNorm requires at least 3 inputs."); } const input = inputs[0]; const skip = inputs[1]; const gamma = inputs[2]; if (input.dataType !== skip.dataType || input.dataType !== gamma.dataType) { throw new Error("All inputs must have the same data type"); } if (input.dims.length !== 3 && input.dims.length !== 2) { throw new Error("Input must be 2D or 3D"); } if (skip.dims.length !== 3 && skip.dims.length !== 2) { throw new Error("Skip must be 2D or 3D"); } const hiddenSize = input.dims[input.dims.length - 1]; const sequenceLength = input.dims[input.dims.length - 2]; if (skip.dims[skip.dims.length - 1] !== hiddenSize) { throw new Error("Skip must have the same hidden size as input"); } if (skip.dims[skip.dims.length - 2] !== sequenceLength) { throw new Error("Skip must have the same sequence length as input"); } if (gamma.dims.length !== 1) { throw new Error("Gamma must be 1D"); } if (gamma.dims[gamma.dims.length - 1] !== hiddenSize) { throw new Error("Gamma must have the same hidden size as input"); } if (inputs.length > 3) { const beta = inputs[3]; if (beta.dims.length !== 1) { throw new Error("Beta must be 1D"); } if (beta.dims[beta.dims.length - 1] !== hiddenSize) { throw new Error("Beta must have the same hidden size as input"); } } if (inputs.length > 4) { const bias = inputs[4]; if (bias.dims.length !== 1) { throw new Error("Bias must be 1D"); } if (bias.dims[bias.dims.length - 1] !== hiddenSize) { throw new Error("Bias must have the same hidden size as input"); } } }; createSkipLayerNormProgramInfo = (inputs, attributes, outputCount, isTraining) => { const simplified = attributes.simplified; const inputShape = inputs[0].dims; const inputSize = ShapeUtil.size(inputShape); const outputShape = inputShape; const outputSize = inputSize; const hiddenSize = inputShape.slice(-1)[0]; const meanInvStdDevDim = isTraining ? inputShape.slice(0, -1).concat(1) : []; const hasBetaInput = !simplified && inputs.length > 3; const hasBiasInput = inputs.length > 4; const hasMeanOutput = isTraining && outputCount > 1; const hasInvStdDevOutput = isTraining && outputCount > 2; const hasInputSkipBiasSumOutput = outputCount > 3; const workgroupSize = 64; const components = getMaxComponents(hiddenSize); const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: components }, { type: 12 /* uint32 */, data: hiddenSize }, { type: 1 /* float */, data: attributes.epsilon } ]; const getShaderSource = (shaderHelper) => { const uniformsArray = [ { name: "output_size", type: "u32" }, { name: "components", type: "u32" }, { name: "hidden_size", type: "u32" }, { name: "epsilon", type: "f32" } ]; const variables = [ inputVariable("x", inputs[0].dataType, inputs[0].dims, components), inputVariable("skip", inputs[1].dataType, inputs[1].dims, components), inputVariable("gamma", inputs[2].dataType, inputs[2].dims, components) ]; if (hasBetaInput) { variables.push(inputVariable("beta", inputs[3].dataType, inputs[3].dims, components)); } if (hasBiasInput) { variables.push(inputVariable("bias", inputs[4].dataType, inputs[4].dims, components)); } variables.push(outputVariable("output", inputs[0].dataType, outputShape, components)); if (hasMeanOutput) { variables.push(outputVariable("mean_output", 1 /* float */, meanInvStdDevDim)); } if (hasInvStdDevOutput) { variables.push(outputVariable("inv_std_output", 1 /* float */, meanInvStdDevDim)); } if (hasInputSkipBiasSumOutput) { variables.push(outputVariable("input_skip_bias_sum", inputs[0].dataType, outputShape, components)); } const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); const vecDataType = tensorTypeToWsglStorageType(1 /* float */, components); return ` ${shaderHelper.registerUniforms(uniformsArray).declareVariables(...variables)} var sum_shared : array<${vecDataType}, ${workgroupSize}>; var sum_squared_shared : array<${vecDataType}, ${workgroupSize}>; ${shaderHelper.mainStart([workgroupSize, 1, 1])} let ix = local_id.x; let iy = global_id.x / ${workgroupSize}; let hidden_size_vectorized: u32 = uniforms.hidden_size / uniforms.components; var stride = hidden_size_vectorized / ${workgroupSize}; let offset = ix * stride + iy * hidden_size_vectorized; let offset1d = stride * ix; if (ix == ${workgroupSize - 1}) { stride = hidden_size_vectorized - stride * ix; } for (var i: u32 = 0; i < stride; i++) { let skip_value = skip[offset + i]; let bias_value = ${hasBiasInput ? "bias[offset1d + i]" : dataType + "(0.0)"}; let input_value = x[offset + i]; let value = input_value + skip_value + bias_value; ${hasInputSkipBiasSumOutput ? "input_skip_bias_sum[offset + i] = value;" : ""} output[offset + i] = value; let f32_value = ${castToF32(dataType, components, "value")}; sum_shared[ix] += f32_value; sum_squared_shared[ix] += f32_value * f32_value; } workgroupBarrier(); var reduce_size : u32 = ${workgroupSize}; for (var curr_size = reduce_size >> 1; curr_size > 0; curr_size = reduce_size >> 1) { reduce_size = curr_size + (reduce_size & 1); if (ix < curr_size) { sum_shared[ix] += sum_shared[ix + reduce_size]; sum_squared_shared[ix] += sum_squared_shared[ix + reduce_size]; } workgroupBarrier(); } let sum = sum_shared[0]; let square_sum = sum_squared_shared[0]; let mean = ${sumVector("sum", components)} / f32(uniforms.hidden_size); let inv_std_dev = inverseSqrt(${sumVector("square_sum", components)} / f32(uniforms.hidden_size) ${simplified ? "" : "- mean * mean"} + uniforms.epsilon); ${hasMeanOutput ? "mean_output[global_idx] = mean;" : ""} ${hasInvStdDevOutput ? "inv_std_output[global_idx] = inv_std_dev;" : ""} for (var i: u32 = 0; i < stride; i++) { output[offset + i] = (output[offset + i] ${simplified ? "" : `- ${dataType}(mean)`}) * ${dataType}(inv_std_dev) * gamma[offset1d + i] ${hasBetaInput ? "+ beta[offset1d + i]" : ""}; } }`; }; const outputs = [{ dims: outputShape, dataType: inputs[0].dataType }]; if (outputCount > 1) { outputs.push({ dims: meanInvStdDevDim, dataType: 1 /* float */ }); } if (outputCount > 2) { outputs.push({ dims: meanInvStdDevDim, dataType: 1 /* float */ }); } if (outputCount > 3) { outputs.push({ dims: inputShape, dataType: inputs[0].dataType }); } return { name: "SkipLayerNormalization", shaderCache: { hint: `${components};${hasMeanOutput};${hasInvStdDevOutput};${hasInputSkipBiasSumOutput}`, inputDependencies: inputs.map((_input, _index) => "type") }, getShaderSource, getRunData: () => ({ outputs, dispatchGroup: { x: Math.ceil(outputSize / hiddenSize) }, programUniforms }) }; }; skipLayerNorm = (context, attributes) => { const isTraining = false; validateInputs28(context.inputs); const outputs = [0]; if (context.outputCount > 1) { outputs.push(isTraining ? 1 : -3); } if (context.outputCount > 2) { outputs.push(isTraining ? 2 : -3); } if (context.outputCount > 3) { outputs.push(3); } context.compute(createSkipLayerNormProgramInfo(context.inputs, attributes, context.outputCount, isTraining), { outputs }); }; } }); // web/lib/wasm/jsep/webgpu/ops/slice.ts var validateInputs29, readInput, createSliceAttributesFromInputs, fixStartEndValues, calculateInputIndicesImpl, createSliceProgramInfo, slice, parseSliceAttributes; var init_slice = __esm({ "web/lib/wasm/jsep/webgpu/ops/slice.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_common(); validateInputs29 = (inputs, attributes) => { if (!inputs || inputs.length < 1) { throw new Error("too few inputs"); } if (attributes.axes.length !== 0) { if (attributes.axes.length !== attributes.starts.length || attributes.axes.length !== attributes.ends.length) { throw new Error("axes, starts and ends must have the same length"); } } else if (attributes.starts.length !== attributes.ends.length) { throw new Error("starts and ends must have the same length"); } inputs.slice(1).forEach((_, idx) => { if (inputs[idx + 1].dataType !== 6 /* int32 */ && inputs[idx + 1].dataType !== 7 /* int64 */) { throw new Error(`Input ${idx} must be an array of int32 or int64`); } }); }; readInput = (inputs, idx) => { const input = []; if (inputs.length > idx) { if (inputs[idx].dataType === 7 /* int64 */) { inputs[idx].getBigInt64Array().forEach((v) => input.push(Number(v))); } else if (inputs[idx].dataType === 6 /* int32 */) { inputs[idx].getInt32Array().forEach((v) => input.push(Number(v))); } else { throw new Error(`Input ${idx} must be an array of int32 or int64`); } } return input; }; createSliceAttributesFromInputs = (inputs, attributes) => { if (inputs.length > 1) { const starts = readInput(inputs, 1); const ends = readInput(inputs, 2); let axes = readInput(inputs, 3); if (axes.length === 0) { axes = [...Array(inputs[0].dims.length).keys()]; } return createAttributeWithCacheKey({ starts, ends, axes }); } else { return attributes; } }; fixStartEndValues = (value, index, inputShape, axes, steps) => { let newValue = value; if (value < 0) { newValue += inputShape[axes[index]]; } if (steps[index] < 0) { return Math.max(0, Math.min(newValue, inputShape[axes[index]] - 1)); } else { return Math.max(0, Math.min(newValue, inputShape[axes[index]])); } }; calculateInputIndicesImpl = (input, output, inputShape) => `fn calculateInputIndices(output_indices: ${output.type.indices}) -> ${input.type.indices} { var input_indices: ${input.type.indices}; var carry = 0u; for (var i = ${inputShape.length - 1}; i >= 0; i--) { let input_shape_i = ${getElementAt("uniforms.input_shape", "i", inputShape.length)}; let steps_i = ${getElementAt("uniforms.steps", "i", inputShape.length)}; let signs_i = ${getElementAt("uniforms.signs", "i", inputShape.length)}; let starts_i = ${getElementAt("uniforms.starts", "i", inputShape.length)}; var output_index = ${output.indicesGet("output_indices", "i")}; var input_index = output_index * steps_i + starts_i + carry; carry = input_index / input_shape_i; input_index = input_index % input_shape_i; if (signs_i < 0) { input_index = input_shape_i - input_index - 1u + starts_i; } ${input.indicesSet("input_indices", "i", "input_index")}; } return input_indices; }`; createSliceProgramInfo = (inputs, attributes) => { const inputShape = inputs[0].dims; const inputSize = ShapeUtil.size(inputShape); const axes = attributes.axes.length > 0 ? ShapeUtil.normalizeAxes(attributes.axes, inputShape.length) : [...Array(inputShape.length).keys()]; let steps = readInput(inputs, 4); steps.forEach( (step) => step !== 0 || (() => { throw new Error("step cannot be 0"); }) ); if (steps.length === 0) { steps = Array(axes.length).fill(1); } const starts = attributes.starts.map((start, i) => fixStartEndValues(start, i, inputShape, axes, steps)); const ends = attributes.ends.map((end, i) => fixStartEndValues(end, i, inputShape, axes, steps)); if (axes.length !== starts.length || axes.length !== ends.length) { throw new Error("start, ends and axes should have the same number of elements"); } if (axes.length !== inputShape.length) { for (let i = 0; i < inputShape.length; ++i) { if (!axes.includes(i)) { starts.splice(i, 0, 0); ends.splice(i, 0, inputShape[i]); steps.splice(i, 0, 1); } } } const signs = steps.map((step) => Math.sign(step)); steps.forEach((step, i, array) => { if (step < 0) { const numSteps = (ends[i] - starts[i]) / step; const newEnd = starts[i]; const newStart = newEnd + numSteps * steps[i]; starts[i] = newStart; ends[i] = newEnd; array[i] = -step; } }); const outputShape = inputShape.slice(0); axes.forEach((axis, _) => { outputShape[axis] = Math.ceil((ends[axis] - starts[axis]) / steps[axis]); }); const outputTensorInfo = { dims: outputShape, dataType: inputs[0].dataType }; const output = outputVariable("output", inputs[0].dataType, outputShape.length); const input = inputVariable("input", inputs[0].dataType, inputs[0].dims.length); const outputSize = ShapeUtil.size(outputShape); const uniforms = [ { name: "outputSize", type: "u32" }, { name: "starts", type: "u32", length: starts.length }, { name: "signs", type: "i32", length: signs.length }, { name: "steps", type: "u32", length: steps.length } ]; const programUniforms = [ { type: 12 /* uint32 */, data: outputSize }, { type: 12 /* uint32 */, data: starts }, { type: 6 /* int32 */, data: signs }, { type: 12 /* uint32 */, data: steps }, ...createTensorShapeVariables(inputs[0].dims, outputShape) ]; const getShaderSource = (shaderHelper) => ` ${shaderHelper.registerUniforms(uniforms).declareVariables(input, output)} ${calculateInputIndicesImpl(input, output, inputShape)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} let output_indices = ${output.offsetToIndices("global_idx")}; let input_indices = calculateInputIndices(output_indices); ${output.setByOffset("global_idx", input.getByIndices("input_indices"))} }`; return { name: "Slice", shaderCache: { hint: `${signs.length}_${starts.length}_${steps.length}`, inputDependencies: ["rank"] }, getShaderSource, getRunData: () => ({ outputs: [outputTensorInfo], dispatchGroup: { x: Math.ceil( inputSize / 64 /* workgroup size */ ) }, programUniforms }) }; }; slice = (context, attributes) => { validateInputs29(context.inputs, attributes); const updatedAttributes = createSliceAttributesFromInputs(context.inputs, attributes); context.compute(createSliceProgramInfo(context.inputs, updatedAttributes), { inputs: [0] }); }; parseSliceAttributes = (attributes) => { const starts = attributes.starts; const ends = attributes.ends; const axes = attributes.axes; return createAttributeWithCacheKey({ starts, ends, axes }); }; } }); // web/lib/wasm/jsep/webgpu/ops/softmax.ts var validateInputs30, createSoftmaxProgramInfo, softmax, parseSoftmaxAttributes; var init_softmax = __esm({ "web/lib/wasm/jsep/webgpu/ops/softmax.ts"() { "use strict"; init_wasm_common(); init_util(); init_attribute_with_cache_key(); init_transpose(); init_common(); validateInputs30 = (inputs) => { if (!inputs || inputs.length !== 1) { throw new Error("Softmax op requires 1 input."); } }; createSoftmaxProgramInfo = (context, attributes) => { const input = context.inputs[0]; const inputShape = input.dims; const outputSize = ShapeUtil.size(inputShape); const inputRank = inputShape.length; const axis = ShapeUtil.normalizeAxis(attributes.axis, inputRank); const isTransposeRequired = axis < inputShape.length - 1; let transposedInput; let perm = []; if (isTransposeRequired) { perm = Array.from({ length: inputRank }, (_, i) => i); perm[axis] = inputRank - 1; perm[inputRank - 1] = axis; transposedInput = context.compute(createTransposeProgramInfo(input, perm), { inputs: [input], outputs: [-1] })[0]; } else { transposedInput = input; } const transposedInputShape = transposedInput.dims; const cols = transposedInputShape[inputRank - 1]; const rows = outputSize / cols; const components = getMaxComponents(cols); const packedCols = cols / components; let WG = 64; if (rows === 1) { WG = 256; } const maxVector = (name, components2) => { if (components2 === 4) { return `max(max(${name}.x, ${name}.y), max(${name}.z, ${name}.w))`; } else if (components2 === 2) { return `max(${name}.x, ${name}.y)`; } else if (components2 === 3) { return `max(max(${name}.x, ${name}.y), ${name}.z)`; } return name; }; const x = inputVariable("x", transposedInput.dataType, transposedInput.dims, components); const output = outputVariable("result", transposedInput.dataType, transposedInput.dims, components); const valueType = x.type.value; const threadMaxDecl = tensorTypeToWsglStorageType(transposedInput.dataType) === "f32" ? `var threadMax = ${valueType}(-3.4028234663852886e+38f);` : `var threadMax = ${valueType}(-65504.0h);`; const getShaderSource = (shaderHelper) => ` var rowMaxShared : ${valueType}; var rowSumShared : ${valueType}; var threadShared : array<${valueType}, ${WG}>; fn getValue(row: i32, col: i32, row_stride: i32) -> ${valueType} { let index = row * row_stride + col; return x[index]; } fn setValue(row: i32, col: i32, row_stride: i32, value: ${valueType}) { let index = row * row_stride + col; result[index] = value; } ${shaderHelper.registerUniform("packedCols", "i32").declareVariables(x, output)} ${shaderHelper.mainStart(WG)} let gindex = i32(global_idx); let lindex = i32(local_idx); const wg = ${WG}; let row = gindex / wg; let cols = uniforms.packedCols; let row_stride : i32 = uniforms.packedCols; // find the rows max ${threadMaxDecl} for (var col = lindex; col < cols; col += wg) { let value = getValue(row, col, row_stride); threadMax = max(threadMax, value); } if (lindex < cols) { threadShared[lindex] = threadMax; } workgroupBarrier(); var reduceSize = min(cols, wg); for (var currSize = reduceSize >> 1; currSize > 0; currSize = reduceSize >> 1) { reduceSize = currSize + (reduceSize & 1); if (lindex < currSize) { threadShared[lindex] = max(threadShared[lindex], threadShared[lindex + reduceSize]); } workgroupBarrier(); } if (lindex == 0) { rowMaxShared = ${valueType}(${maxVector("threadShared[0]", components)}); } workgroupBarrier(); // find the rows sum var threadSum = ${valueType}(0.0); for (var col = lindex; col < cols; col += wg) { let subExp = exp(getValue(row, col, row_stride) - rowMaxShared); threadSum += subExp; } threadShared[lindex] = threadSum; workgroupBarrier(); for (var currSize = wg >> 1; currSize > 0; currSize = currSize >> 1) { if (lindex < currSize) { threadShared[lindex] = threadShared[lindex] + threadShared[lindex + currSize]; } workgroupBarrier(); } if (lindex == 0) { rowSumShared = ${valueType}(${sumVector("threadShared[0]", components)}); } workgroupBarrier(); // calculate final value for each element in the row for (var col = lindex; col < cols; col += wg) { var value = exp(getValue(row, col, row_stride) - rowMaxShared) / rowSumShared; // max operation protects against NaN since all values should be >=0 value = max(value, ${valueType}(0.0)); setValue(row, col, row_stride, value); } }`; const result = context.compute( { name: "Softmax", // Note that in JSEP, WG size is not included in cache by default, but WebGPU EP it is. shaderCache: { hint: `${components};${WG}`, inputDependencies: ["type"] }, getRunData: () => ({ outputs: [{ dims: transposedInputShape, dataType: transposedInput.dataType }], dispatchGroup: { x: rows }, programUniforms: [{ type: 6 /* int32 */, data: packedCols }] }), getShaderSource }, { inputs: [transposedInput], outputs: [isTransposeRequired ? -1 : 0] } )[0]; if (isTransposeRequired) { context.compute(createTransposeProgramInfo(result, perm), { inputs: [result] }); } }; softmax = (context, attributes) => { validateInputs30(context.inputs); createSoftmaxProgramInfo(context, attributes); }; parseSoftmaxAttributes = (attributes) => createAttributeWithCacheKey({ axis: attributes.axis }); } }); // web/lib/wasm/jsep/webgpu/ops/tile.ts var getRepeats, validateInputs31, getOutputShape2, createTileProgramInfo, tile; var init_tile = __esm({ "web/lib/wasm/jsep/webgpu/ops/tile.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); getRepeats = (repeatsTensorView) => Array.from(repeatsTensorView.getBigInt64Array(), Number); validateInputs31 = (inputs) => { if (!inputs || inputs.length !== 2) { throw new Error("Tile requires 2 inputs."); } if (inputs[0].dataType !== 1 /* float */ && inputs[0].dataType !== 10 /* float16 */ && inputs[0].dataType !== 6 /* int32 */ && inputs[0].dataType !== 12 /* uint32 */) { throw new Error("Tile only support float, float16, int32, and uint32 data types"); } if (inputs[1].dataType !== 7 /* int64 */) { throw new Error("Tile `repeats` input should be of int64 data type"); } if (inputs[1].dims.length !== 1) { throw new Error("Tile `repeats` input should be 1-D"); } const repeats = getRepeats(inputs[1]); if (repeats.length !== inputs[0].dims.length) { throw new Error("Tile `repeats` input should have same number of elements as rank of input data tensor"); } }; getOutputShape2 = (inputShape, repeats) => { const outputShape = []; for (let i = 0; i < inputShape.length; ++i) { outputShape.push(inputShape[i] * repeats[i]); } return outputShape; }; createTileProgramInfo = (inputs, shape) => { const inputShape = inputs[0].dims; const repeats = shape == null ? getRepeats(inputs[1]) : shape; const outputShape = getOutputShape2(inputShape, repeats); const outputSize = ShapeUtil.size(outputShape); const dataType = inputs[0].dataType; const input = inputVariable("input", dataType, inputShape.length); const output = outputVariable("output", dataType, outputShape.length); const getShaderSource = (shaderHelper) => ` const inputShape = ${input.indices(...inputShape)}; ${shaderHelper.registerUniform("output_size", "u32").declareVariables(input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} let output_indices = ${output.offsetToIndices("global_idx")}; var input_indices: ${input.type.indices}; for (var i = 0; i < ${inputShape.length}; i++) { let input_dim_i = ${input.indicesGet("uniforms.input_shape", "i")}; let input_dim_value = ${output.indicesGet("output_indices", "i")} % input_dim_i; ${input.indicesSet("input_indices", "i", "input_dim_value")} } ${output.setByOffset("global_idx", input.getByIndices("input_indices"))} }`; return { name: "Tile", shaderCache: { hint: `${repeats}`, inputDependencies: ["rank"] }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 /* workgroup size */ ) }, programUniforms: [ { type: 12 /* uint32 */, data: outputSize }, ...createTensorShapeVariables(inputs[0].dims, outputShape) ] }), getShaderSource }; }; tile = (context) => { validateInputs31(context.inputs); context.compute(createTileProgramInfo(context.inputs), { inputs: [0] }); }; } }); // web/lib/wasm/jsep/webgpu/ops/where.ts var createWhereOpProgramShader, createWhereOpProgramInfo, where; var init_where = __esm({ "web/lib/wasm/jsep/webgpu/ops/where.ts"() { "use strict"; init_wasm_common(); init_util(); init_common(); createWhereOpProgramShader = (shaderHelper, inputs, dimsOutput, isBroadcast, typeOutput) => { const output = outputVariable("output_data", typeOutput, dimsOutput.length, 4); const a = inputVariable("a_data", inputs[1].dataType, inputs[1].dims.length, 4); const b = inputVariable("b_data", inputs[2].dataType, inputs[2].dims.length, 4); const c = inputVariable("c_data", inputs[0].dataType, inputs[0].dims.length, 4); let assignment; const expression = (a2, b2, c2) => `select(${b2}, ${a2}, ${c2})`; if (!isBroadcast) { assignment = output.setByOffset( "global_idx", expression(a.getByOffset("global_idx"), b.getByOffset("global_idx"), c.getByOffset("global_idx")) ); } else { const singleAssignment = (resStr, x, typeCast = "") => { const expressionA = `a_data[index_a${x}][component_a${x}]`; const expressionB = `b_data[index_b${x}][component_b${x}]`; const expressionC = `bool(c_data[index_c${x}] & (0xffu << (component_c${x} * 8)))`; return ` let output_indices${x} = ${output.offsetToIndices(`global_idx * 4u + ${x}u`)}; let offset_a${x} = ${a.broadcastedIndicesToOffset(`output_indices${x}`, output)}; let offset_b${x} = ${b.broadcastedIndicesToOffset(`output_indices${x}`, output)}; let offset_c${x} = ${c.broadcastedIndicesToOffset(`output_indices${x}`, output)}; let index_a${x} = offset_a${x} / 4u; let index_b${x} = offset_b${x} / 4u; let index_c${x} = offset_c${x} / 4u; let component_a${x} = offset_a${x} % 4u; let component_b${x} = offset_b${x} % 4u; let component_c${x} = offset_c${x} % 4u; ${resStr}[${x}] = ${typeCast}(${expression(expressionA, expressionB, expressionC)}); `; }; if (typeOutput === 9 /* bool */) { assignment = ` var data = vec4(0); ${singleAssignment("data", 0, "u32")} ${singleAssignment("data", 1, "u32")} ${singleAssignment("data", 2, "u32")} ${singleAssignment("data", 3, "u32")} output_data[global_idx] = dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(data));`; } else { assignment = ` ${singleAssignment("output_data[global_idx]", 0)} ${singleAssignment("output_data[global_idx]", 1)} ${singleAssignment("output_data[global_idx]", 2)} ${singleAssignment("output_data[global_idx]", 3)} `; } } return ` ${shaderHelper.registerUniform("vec_size", "u32").declareVariables(c, a, b, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.vec_size")} ${assignment} }`; }; createWhereOpProgramInfo = (inputs) => { const dimsA = inputs[1].dims; const dimsB = inputs[2].dims; const dimsC = inputs[0].dims; const outputDataType = inputs[1].dataType; const isBroadcast = !(ShapeUtil.areEqual(dimsA, dimsB) && ShapeUtil.areEqual(dimsB, dimsC)); let outputShape = dimsA; let outputSize = ShapeUtil.size(dimsA); if (isBroadcast) { const calculatedShape = BroadcastUtil.calcShape(BroadcastUtil.calcShape(dimsA, dimsB, false), dimsC, false); if (!calculatedShape) { throw new Error("Can't perform where op on the given tensors"); } outputShape = calculatedShape; outputSize = ShapeUtil.size(outputShape); } const vecSize = Math.ceil(outputSize / 4); return { name: "Where", shaderCache: { inputDependencies: ["rank", "rank", "rank"] }, getShaderSource: (shaderHelper) => createWhereOpProgramShader(shaderHelper, inputs, outputShape, isBroadcast, outputDataType), getRunData: () => ({ outputs: [{ dims: outputShape, dataType: outputDataType }], dispatchGroup: { x: Math.ceil( outputSize / 64 / 4 /* vec size */ ) }, programUniforms: [ { type: 12 /* uint32 */, data: vecSize }, ...createTensorShapeVariables(dimsC, dimsA, dimsB, outputShape) ] }) }; }; where = (context) => { context.compute(createWhereOpProgramInfo(context.inputs)); }; } }); // web/lib/wasm/jsep/webgpu/op-resolve-rules.ts var WEBGPU_OP_RESOLVE_RULES; var init_op_resolve_rules = __esm({ "web/lib/wasm/jsep/webgpu/op-resolve-rules.ts"() { "use strict"; init_argminmax(); init_attention(); init_batch_norm(); init_bias_add(); init_bias_split_gelu(); init_binary_op(); init_concat(); init_conv(); init_conv_transpose(); init_cumsum(); init_depth_to_space(); init_einsum(); init_expand(); init_fast_gelu(); init_gather(); init_gather_nd(); init_gather_block_quantized(); init_gather_elements(); init_gemm(); init_grid_sample(); init_group_query_attention(); init_instance_norm(); init_layer_norm(); init_matmul(); init_matmulnbits(); init_multihead_attention(); init_pad(); init_pool(); init_quantize_linear(); init_range(); init_scatter_nd(); init_reduce(); init_resize(); init_rotary_embedding(); init_skip_layer_norm(); init_slice(); init_softmax(); init_split(); init_tile(); init_transpose(); init_unary_op(); init_where(); WEBGPU_OP_RESOLVE_RULES = /* @__PURE__ */ new Map([ ["Abs", [abs]], ["Acos", [acos]], ["Acosh", [acosh]], ["Add", [add]], ["ArgMax", [argMax, parseArgMinMaxAttributes]], ["ArgMin", [argMin, parseArgMinMaxAttributes]], ["Asin", [asin]], ["Asinh", [asinh]], ["Atan", [atan]], ["Atanh", [atanh]], ["Attention", [attention]], // TODO: support new attributes for AveragePool-10 ["AveragePool", [averagePool, parseAveragePoolAttributes]], ["BatchNormalization", [batchNorm]], ["BiasAdd", [biasAdd]], ["BiasSplitGelu", [biasSplitGelu]], ["Cast", [cast, parseCastAttributes]], ["Ceil", [ceil]], ["Clip", [clip]], ["Concat", [concat, parseConcatAttributes]], ["Conv", [conv, parseConvAttributes]], ["ConvTranspose", [convTranspose, parseConvTransposeAttributes]], ["Cos", [cos]], ["Cosh", [cosh]], ["CumSum", [cumsum, parseCumSumAttributes]], ["DepthToSpace", [depthToSpace, parseDepthToSpaceAttributes]], ["DequantizeLinear", [dequantizeLinear, parseDequantizeLinearAttributes]], ["Div", [div]], ["Einsum", [einsum, parseEinsumAttributes]], ["Elu", [elu, parseAlphaAttributes]], ["Equal", [equal]], ["Erf", [erf]], ["Exp", [exp]], ["Expand", [expand]], ["FastGelu", [fastGelu2]], ["Floor", [floor]], ["FusedConv", [conv, parseConvAttributes]], ["Gather", [gather, parseGatherAttributes]], ["GatherElements", [gatherElements, parseGatherElementsAttributes]], ["GatherBlockQuantized", [gatherBlockQuantized, parseGatherBlockQuantizedAttributes]], ["GatherND", [gatherND, parseGatherNDAttributes]], ["Gelu", [gelu]], ["Gemm", [gemm, parseGemmAttributes]], ["GlobalAveragePool", [globalAveragePool, parseGlobalAveragePoolAttributes]], ["GlobalMaxPool", [globalMaxPool, parseGlobalMaxPoolAttributes]], ["Greater", [greater]], ["GreaterOrEqual", [greaterOrEqual]], ["GridSample", [gridSample, parseGridSampleAttributes]], ["GroupQueryAttention", [groupQueryAttention]], ["HardSigmoid", [hardSigmoid, parseHardSigmoidAttributes]], ["InstanceNormalization", [instanceNorm]], ["LayerNormalization", [layerNorm]], ["LeakyRelu", [leakyRelu, parseAlphaAttributes]], ["Less", [less]], ["LessOrEqual", [lessOrEqual]], ["Log", [log]], ["MatMul", [matMul]], ["MatMulNBits", [matMulNBits, parseMatMulNBitsAttributes]], // TODO: support new attributes for MaxPool-8 and MaxPool-10 ["MaxPool", [maxPool, parseMaxPoolAttributes]], ["Mul", [mul]], ["MultiHeadAttention", [multiHeadAttention, parseMultiHeadAttentionAttributes]], ["Neg", [neg]], ["Not", [not]], ["Pad", [pad]], ["Pow", [pow]], ["QuickGelu", [quickgelu, parseAlphaAttributes]], ["Range", [range]], ["Reciprocal", [reciprocal]], ["ReduceMin", [reduceMin]], ["ReduceMean", [reduceMean]], ["ReduceMax", [reduceMax]], ["ReduceSum", [reduceSum]], ["ReduceProd", [reduceProd]], ["ReduceL1", [reduceL1]], ["ReduceL2", [reduceL2]], ["ReduceLogSum", [reduceLogSum]], ["ReduceLogSumExp", [reduceLogSumExp]], ["ReduceSumSquare", [reduceSumSquare]], ["Relu", [relu]], ["Resize", [resize, parseResizeAttributes]], ["RotaryEmbedding", [rotaryEmbedding]], ["ScatterND", [scatterND, parseScatterNDAttributes]], ["Sigmoid", [sigmoid]], ["Sin", [sin]], ["Sinh", [sinh]], ["Slice", [slice, parseSliceAttributes]], ["SkipLayerNormalization", [skipLayerNorm]], ["Split", [split, parseSplitAttributes]], ["Sqrt", [sqrt]], ["Softmax", [softmax, parseSoftmaxAttributes]], ["Sub", [sub]], ["Tan", [tan]], ["Tanh", [tanh]], ["ThresholdedRelu", [thresholdedRelu, parseAlphaAttributes]], ["Tile", [tile]], ["Transpose", [transpose, parseTransposeAttributes]], ["Where", [where]] ]); } }); // web/lib/wasm/jsep/webgpu/program-manager.ts var ProgramManager; var init_program_manager = __esm({ "web/lib/wasm/jsep/webgpu/program-manager.ts"() { "use strict"; init_esm(); init_log(); init_common(); ProgramManager = class { constructor(backend) { this.backend = backend; this.repo = /* @__PURE__ */ new Map(); this.attributesBound = false; } getArtifact(key) { return this.repo.get(key); } setArtifact(key, artifact) { this.repo.set(key, artifact); } run(buildArtifact, inputs, outputs, dispatchGroup, uniformBufferBinding) { TRACE_FUNC_BEGIN(buildArtifact.programInfo.name); const device = this.backend.device; const computePassEncoder = this.backend.getComputePassEncoder(); this.backend.writeTimestamp(this.backend.pendingDispatchNumber * 2); const entries = []; for (const input of inputs) { entries.push({ binding: entries.length, resource: { buffer: input.buffer } }); } for (const output of outputs) { entries.push({ binding: entries.length, resource: { buffer: output.buffer } }); } if (uniformBufferBinding) { entries.push({ binding: entries.length, resource: uniformBufferBinding }); } const bindGroup = device.createBindGroup({ layout: buildArtifact.computePipeline.getBindGroupLayout(0), entries, label: buildArtifact.programInfo.name }); if (this.backend.sessionStatus === "capturing") { const commandInfo = { kernelId: this.backend.currentKernelId, computePipeline: buildArtifact.computePipeline, bindGroup, dispatchGroup }; const sessionCommandList = this.backend.capturedCommandList.get(this.backend.currentSessionId); sessionCommandList.push(commandInfo); } computePassEncoder.setPipeline(buildArtifact.computePipeline); computePassEncoder.setBindGroup(0, bindGroup); computePassEncoder.dispatchWorkgroups(...dispatchGroup); this.backend.writeTimestamp(this.backend.pendingDispatchNumber * 2 + 1); this.backend.pendingDispatchNumber++; if (this.backend.pendingDispatchNumber >= this.backend.maxDispatchNumber || this.backend.queryType === "at-passes") { this.backend.endComputePass(); } if (this.backend.pendingDispatchNumber >= this.backend.maxDispatchNumber) { this.backend.flush(); } TRACE_FUNC_END(buildArtifact.programInfo.name); } dispose() { } build(programInfo, normalizedDispatchGroupSize) { TRACE_FUNC_BEGIN(programInfo.name); const device = this.backend.device; const enableDirectives = []; const extensionsInfo = [ { feature: "shader-f16", extension: "f16" }, { feature: "subgroups", extension: "subgroups" } ]; extensionsInfo.forEach((info) => { if (device.features.has(info.feature)) { enableDirectives.push(`enable ${info.extension};`); } }); const shaderHelper = createShaderHelper(normalizedDispatchGroupSize, this.backend.device.limits); const userCode = programInfo.getShaderSource(shaderHelper); const code = `${enableDirectives.join("\n")} ${shaderHelper.additionalImplementations} ${userCode}`; const shaderModule = device.createShaderModule({ code, label: programInfo.name }); LOG_DEBUG("verbose", () => `[WebGPU] ${programInfo.name} shader code: ${code}`); const computePipeline = device.createComputePipeline({ compute: { module: shaderModule, entryPoint: "main" }, layout: "auto", label: programInfo.name }); TRACE_FUNC_END(programInfo.name); return { programInfo, computePipeline, uniformVariablesInfo: shaderHelper.variablesInfo }; } normalizeDispatchGroupSize(dispatchGroup) { const x = typeof dispatchGroup === "number" ? dispatchGroup : dispatchGroup.x; const y = typeof dispatchGroup === "number" ? 1 : dispatchGroup.y || 1; const z = typeof dispatchGroup === "number" ? 1 : dispatchGroup.z || 1; const limitPerDimension = this.backend.device.limits.maxComputeWorkgroupsPerDimension; if (x <= limitPerDimension && y <= limitPerDimension && z <= limitPerDimension) { return [x, y, z]; } const size = x * y * z; let dispatchAverage = Math.ceil(Math.sqrt(size)); if (dispatchAverage > limitPerDimension) { dispatchAverage = Math.ceil(Math.cbrt(size)); if (dispatchAverage > limitPerDimension) { throw new Error("Total dispatch size exceeds WebGPU maximum."); } return [dispatchAverage, dispatchAverage, dispatchAverage]; } else { return [dispatchAverage, dispatchAverage, 1]; } } }; } }); // web/lib/wasm/jsep/backend-webgpu.ts var backend_webgpu_exports = {}; __export(backend_webgpu_exports, { WebGpuBackend: () => WebGpuBackend }); var getProgramInputTensorInfoDependencyKey, getProgramInfoUniqueKey, AdapterInfoImpl, WebGpuBackend; var init_backend_webgpu = __esm({ "web/lib/wasm/jsep/backend-webgpu.ts"() { "use strict"; init_esm(); init_wasm_common(); init_log(); init_tensor_view(); init_gpu_data_manager(); init_op_resolve_rules(); init_program_manager(); getProgramInputTensorInfoDependencyKey = (inputTensors, inputDependencies) => { if (inputDependencies.length !== inputTensors.length) { throw new Error( `inputDependencies length ${inputDependencies.length} is not equal to inputTensors length ${inputTensors.length}.` ); } const inputInfos = []; for (let i = 0; i < inputTensors.length; ++i) { const type = inputTensors[i].dataType; switch (inputDependencies[i]) { case "none": { inputInfos.push(""); break; } case "type": { inputInfos.push(`${type}`); break; } case "rank": { const rank = inputTensors[i].dims.length; inputInfos.push(`${type};${rank}`); break; } case "dims": { const dims = inputTensors[i].dims.join(","); inputInfos.push(`${type};${dims}`); break; } default: throw new Error(`unsupported input dependency: ${inputDependencies[i]}`); } } return inputInfos.join("|"); }; getProgramInfoUniqueKey = (programInfo, inputTensors, is1DimensionDispatch) => { let key = programInfo.name; if (programInfo.shaderCache?.hint) { key += "[" + programInfo.shaderCache.hint + "]"; } key += ":" + is1DimensionDispatch + `:${getProgramInputTensorInfoDependencyKey( inputTensors, programInfo.shaderCache?.inputDependencies ?? new Array(inputTensors.length).fill("dims") )}`; return key; }; AdapterInfoImpl = class { constructor(adapterInfo) { if (adapterInfo) { this.architecture = adapterInfo.architecture; this.vendor = adapterInfo.vendor; } } isArchitecture(architecture) { return this.architecture === architecture; } isVendor(vendor) { return this.vendor === vendor; } }; WebGpuBackend = class { constructor() { /** * representing the session ID of which is currently being run. * `null` means no session is being run. * only valid when session.run is executed. */ this.currentSessionId = null; /** * representing the kernel ID of which is currently being computed (CPU code perspective). * `null` means no kernel is being computed. * only one kernel can be computed at a moment. */ this.currentKernelId = null; this.commandEncoder = null; this.computePassEncoder = null; this.maxDispatchNumber = 16; this.pendingDispatchNumber = 0; // info of kernels pending submission for a single batch this.pendingKernels = []; // queryReadBuffer -> pendingKernels mapping for all the batches this.pendingQueries = /* @__PURE__ */ new Map(); this.sessionStatus = "default"; /** * a SessionID -> CommandInfo[] mapping. It's used to record all GPU commands for corresponding session. */ this.capturedCommandList = /* @__PURE__ */ new Map(); /** * a SessionID -> PendingKernelInfo[] mapping for profiling. */ this.capturedPendingKernels = /* @__PURE__ */ new Map(); /** * a SessionID -> a Map of (InputOutputIndex -> [ID, GPUBuffer]) mapping. */ this.sessionExternalDataMapping = /* @__PURE__ */ new Map(); } /** * get the custom data of the current kernel */ get currentKernelCustomData() { if (this.currentKernelId === null) { throw new Error("currentKernelCustomData(): currentKernelId is null. (should not happen)"); } let data = this.kernelCustomData.get(this.currentKernelId); if (!data) { data = {}; this.kernelCustomData.set(this.currentKernelId, data); } return data; } async initialize(env3, adapter) { this.env = env3; const requiredFeatures = []; const deviceDescriptor = { requiredLimits: { maxComputeWorkgroupStorageSize: adapter.limits.maxComputeWorkgroupStorageSize, maxComputeWorkgroupsPerDimension: adapter.limits.maxComputeWorkgroupsPerDimension, maxStorageBufferBindingSize: adapter.limits.maxStorageBufferBindingSize, maxBufferSize: adapter.limits.maxBufferSize, maxComputeInvocationsPerWorkgroup: adapter.limits.maxComputeInvocationsPerWorkgroup, maxComputeWorkgroupSizeX: adapter.limits.maxComputeWorkgroupSizeX, maxComputeWorkgroupSizeY: adapter.limits.maxComputeWorkgroupSizeY, maxComputeWorkgroupSizeZ: adapter.limits.maxComputeWorkgroupSizeZ }, requiredFeatures }; const requireFeatureIfAvailable = (feature) => adapter.features.has(feature) && requiredFeatures.push(feature) && true; if (!requireFeatureIfAvailable("chromium-experimental-timestamp-query-inside-passes")) { requireFeatureIfAvailable("timestamp-query"); } requireFeatureIfAvailable("shader-f16"); requireFeatureIfAvailable("subgroups"); this.device = await adapter.requestDevice(deviceDescriptor); this.adapterInfo = new AdapterInfoImpl(adapter.info || await adapter.requestAdapterInfo()); this.gpuDataManager = createGpuDataManager(this); this.programManager = new ProgramManager(this); this.kernels = /* @__PURE__ */ new Map(); this.kernelPersistentData = /* @__PURE__ */ new Map(); this.kernelCustomData = /* @__PURE__ */ new Map(); configureLogger(env3.logLevel, !!env3.debug); this.device.onuncapturederror = (ev) => { if (ev.error instanceof GPUValidationError) { console.error(`An uncaught WebGPU validation error was raised: ${ev.error.message}`); } }; Object.defineProperty(this.env.webgpu, "device", { value: this.device, writable: false, enumerable: true, configurable: true // Allow deletion when device is destroyed }); Object.defineProperty(this.env.webgpu, "adapter", { value: adapter, writable: false, enumerable: true, configurable: false }); this.setQueryType(); } dispose() { if (typeof this.querySet !== "undefined") { this.querySet.destroy(); } this.gpuDataManager.dispose(); if (this.device && this.env?.webgpu) { void this.device.lost.then(() => { delete this.env.webgpu.device; }); } } getCommandEncoder() { if (!this.commandEncoder) { this.commandEncoder = this.device.createCommandEncoder(); } return this.commandEncoder; } getComputePassEncoder() { if (!this.computePassEncoder) { const commandEncoder = this.getCommandEncoder(); const computePassDescriptor = {}; if (this.queryType === "at-passes") { computePassDescriptor.timestampWrites = { querySet: this.querySet, beginningOfPassWriteIndex: this.pendingDispatchNumber * 2, endOfPassWriteIndex: this.pendingDispatchNumber * 2 + 1 }; } this.computePassEncoder = commandEncoder.beginComputePass(computePassDescriptor); } return this.computePassEncoder; } endComputePass() { if (this.computePassEncoder) { this.computePassEncoder.end(); this.computePassEncoder = null; } } flush() { if (!this.commandEncoder) { return; } TRACE_FUNC_BEGIN(); this.endComputePass(); let queryReadBuffer; if (this.queryType !== "none") { this.commandEncoder.resolveQuerySet( this.querySet, 0, this.pendingDispatchNumber * 2, this.queryResolveBuffer, 0 ); queryReadBuffer = this.device.createBuffer( // eslint-disable-next-line no-bitwise { size: this.pendingDispatchNumber * 2 * 8, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST } ); this.pendingQueries.set(queryReadBuffer, this.pendingKernels); this.pendingKernels = []; this.commandEncoder.copyBufferToBuffer( this.queryResolveBuffer, 0, queryReadBuffer, 0, this.pendingDispatchNumber * 2 * 8 ); } this.device.queue.submit([this.commandEncoder.finish()]); this.gpuDataManager.refreshPendingBuffers(); this.commandEncoder = null; this.pendingDispatchNumber = 0; if (this.queryType !== "none") { void queryReadBuffer.mapAsync(GPUMapMode.READ).then(() => { const mappedData = new BigUint64Array(queryReadBuffer.getMappedRange()); const pendingKernels = this.pendingQueries.get(queryReadBuffer); for (let i = 0; i < mappedData.length / 2; i++) { const pendingKernelInfo = pendingKernels[i]; const kernelId = pendingKernelInfo.kernelId; const kernelInfo = this.kernels.get(kernelId); const kernelType = kernelInfo.kernelType; const kernelName = kernelInfo.kernelName; const programName = pendingKernelInfo.programName; const inputTensorViews = pendingKernelInfo.inputTensorViews; const outputTensorViews = pendingKernelInfo.outputTensorViews; const startTimeU64 = mappedData[i * 2]; const endTimeU64 = mappedData[i * 2 + 1]; if (typeof this.queryTimeBase === "undefined") { this.queryTimeBase = startTimeU64; } const startTime = Number(startTimeU64 - this.queryTimeBase); const endTime = Number(endTimeU64 - this.queryTimeBase); if (!Number.isSafeInteger(startTime) || !Number.isSafeInteger(endTime)) { throw new RangeError("incorrect timestamp range"); } if (this.env.webgpu.profiling?.ondata) { this.env.webgpu.profiling.ondata({ version: 1, inputsMetadata: inputTensorViews.map((value) => ({ dims: value.dims, dataType: tensorDataTypeEnumToString(value.dataType) })), outputsMetadata: outputTensorViews.map((value) => ({ dims: value.dims, dataType: tensorDataTypeEnumToString(value.dataType) })), kernelId, kernelType, kernelName, programName, startTime, endTime }); } else { let inputShapes = ""; inputTensorViews.forEach((value, i2) => { inputShapes += `input[${i2}]: [${value.dims}] | ${tensorDataTypeEnumToString(value.dataType)}, `; }); let outputShapes = ""; outputTensorViews.forEach((value, i2) => { outputShapes += `output[${i2}]: [${value.dims}] | ${tensorDataTypeEnumToString(value.dataType)}, `; }); console.log( `[profiling] kernel "${kernelId}|${kernelType}|${kernelName}|${programName}" ${inputShapes}${outputShapes}start time: ${startTime} ns, execution time: ${endTime - startTime} ns` ); } TRACE("GPU", `${programName}::${startTimeU64}::${endTimeU64}`); } queryReadBuffer.unmap(); this.pendingQueries.delete(queryReadBuffer); }); } TRACE_FUNC_END(); } /** * run a WebGPU program. * @param program a ProgramInfo instance * @param inputTensorViews a TensorView array. each element represents a value already exists in GPU. * @param outputIndices an indices array. each element can be either -1 (temporary data), -2 (persistent data) or an * index to the kernel's output. * @param createKernelOutput a callback function that create a value to kernel's output with the given index * @param createIntermediateOutput a callback function that create a value as a intermediate value, either temporary * or persistent (owned by the current kernel) * @returns a TensorView array representing the result. */ run(program, inputTensorViews, outputIndices, createKernelOutput, createIntermediateOutput, outputCount) { TRACE_FUNC_BEGIN(program.name); const inputDatas = []; for (let i = 0; i < inputTensorViews.length; ++i) { const data = inputTensorViews[i].data; if (data === 0) { continue; } const gpuData = this.gpuDataManager.get(data); if (!gpuData) { throw new Error(`no GPU data for input: ${data}`); } inputDatas.push(gpuData); } const { outputs, dispatchGroup, programUniforms } = program.getRunData(inputTensorViews); const validatedOutputIndices = outputIndices.length === 0 ? outputs.map((_, i) => i) : outputIndices; if (validatedOutputIndices.length !== outputs.length) { throw new Error(`Output size ${validatedOutputIndices.length} must be equal to ${outputs.length}.`); } const outputTensorViews = []; const outputDatas = []; for (let i = 0; i < outputs.length; ++i) { if (!Number.isInteger(validatedOutputIndices[i]) || validatedOutputIndices[i] < -3 || validatedOutputIndices[i] >= outputCount) { throw new Error(`Invalid output index: ${validatedOutputIndices[i]}`); } if (validatedOutputIndices[i] === -3) { continue; } const isTemporary = validatedOutputIndices[i] === -1; const isPersistent = validatedOutputIndices[i] === -2; const tensorView = isTemporary || isPersistent ? createIntermediateOutput(outputs[i].dataType, outputs[i].dims) : createKernelOutput(validatedOutputIndices[i], outputs[i].dataType, outputs[i].dims); outputTensorViews.push(tensorView); if (tensorView.data === 0) { continue; } const gpuData = this.gpuDataManager.get(tensorView.data); if (!gpuData) { throw new Error(`no GPU data for output: ${tensorView.data}`); } if (isTemporary) { this.temporaryData.push(gpuData); } if (isPersistent) { let persistentData = this.kernelPersistentData.get(this.currentKernelId); if (!persistentData) { persistentData = []; this.kernelPersistentData.set(this.currentKernelId, persistentData); } persistentData.push(gpuData); } outputDatas.push(gpuData); } if (inputDatas.length !== inputTensorViews.length || outputDatas.length !== outputTensorViews.length) { if (outputDatas.length === 0) { TRACE_FUNC_END(program.name); return outputTensorViews; } throw new Error( `Program ${program.name} has zero-sized tensor(s) in inputs or outputs. This is not supported now.` ); } let uniformBufferBinding; if (programUniforms) { let currentOffset = 0; const offsets = []; programUniforms.forEach((v) => { const data = typeof v.data === "number" ? [v.data] : v.data; if (data.length === 0) { return; } const sizeOfElement = v.type === 10 /* float16 */ ? 2 : 4; let sizeOfVecOrMat; let baseAlignment; if (v.type === 10 /* float16 */) { baseAlignment = data.length > 4 ? 16 : data.length > 2 ? 8 : data.length * sizeOfElement; sizeOfVecOrMat = data.length > 4 ? 16 : sizeOfElement * data.length; } else { baseAlignment = data.length <= 2 ? data.length * sizeOfElement : 16; sizeOfVecOrMat = 16; } currentOffset = Math.ceil(currentOffset / baseAlignment) * baseAlignment; offsets.push(currentOffset); const elementPerVecOrMat = v.type === 10 /* float16 */ ? 8 : 4; currentOffset += data.length > 4 ? Math.ceil(data.length / elementPerVecOrMat) * sizeOfVecOrMat : data.length * sizeOfElement; }); const maxAlignmentOfField = 16; currentOffset = Math.ceil(currentOffset / maxAlignmentOfField) * maxAlignmentOfField; const arrayBuffer = new ArrayBuffer(currentOffset); programUniforms.forEach((v, i) => { const offset = offsets[i]; const data = typeof v.data === "number" ? [v.data] : v.data; if (v.type === 6 /* int32 */) { new Int32Array(arrayBuffer, offset, data.length).set(data); } else if (v.type === 12 /* uint32 */) { new Uint32Array(arrayBuffer, offset, data.length).set(data); } else if (v.type === 10 /* float16 */) { new Uint16Array(arrayBuffer, offset, data.length).set(data); } else if (v.type === 1 /* float */) { new Float32Array(arrayBuffer, offset, data.length).set(data); } else { throw new Error(`Unsupported uniform type: ${tensorDataTypeEnumToString(v.type)}`); } }); const uniformBufferData = ( // eslint-disable-next-line no-bitwise this.gpuDataManager.create(currentOffset, GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM) ); this.device.queue.writeBuffer(uniformBufferData.buffer, 0, arrayBuffer, 0, currentOffset); this.gpuDataManager.release(uniformBufferData.id); uniformBufferBinding = { offset: 0, size: currentOffset, buffer: uniformBufferData.buffer }; } const normalizedDispatchGroup = this.programManager.normalizeDispatchGroupSize(dispatchGroup); const is1DimensionDispatch = normalizedDispatchGroup[1] === 1 && normalizedDispatchGroup[2] === 1; const key = getProgramInfoUniqueKey(program, inputTensorViews, is1DimensionDispatch); let artifact = this.programManager.getArtifact(key); if (!artifact) { artifact = this.programManager.build(program, normalizedDispatchGroup); this.programManager.setArtifact(key, artifact); LOG_DEBUG("info", () => `[artifact] key: ${key}, programName: ${program.name}`); } if (programUniforms && artifact.uniformVariablesInfo) { if (programUniforms.length !== artifact.uniformVariablesInfo.length) { throw new Error( `Uniform variables count mismatch: expect ${artifact.uniformVariablesInfo.length}, got ${programUniforms.length} in program "${artifact.programInfo.name}".` ); } for (let i = 0; i < programUniforms.length; i++) { const uniform = programUniforms[i]; const actualType = uniform.type; const actualLength = typeof uniform.data === "number" ? 1 : uniform.data.length; const [type, length] = artifact.uniformVariablesInfo[i]; if (actualType !== type || actualLength !== length) { throw new Error( `Uniform variable ${i} mismatch: expect type ${type} with size ${length}, got type ${actualType} with size ${actualLength} in program "${artifact.programInfo.name}".` ); } } } LOG_DEBUG( "info", () => `[ProgramManager] run "${program.name}" (key=${key}) with ${normalizedDispatchGroup[0]}x${normalizedDispatchGroup[1]}x${normalizedDispatchGroup[2]}` ); if (this.queryType !== "none" || this.sessionStatus === "capturing") { const pendingKernelInfo = { kernelId: this.currentKernelId, programName: artifact.programInfo.name, inputTensorViews, outputTensorViews }; this.pendingKernels.push(pendingKernelInfo); if (this.sessionStatus === "capturing") { const sessionPendingKernels = this.capturedPendingKernels.get(this.currentSessionId); sessionPendingKernels.push(pendingKernelInfo); } } this.programManager.run(artifact, inputDatas, outputDatas, normalizedDispatchGroup, uniformBufferBinding); TRACE_FUNC_END(program.name); return outputTensorViews; } upload(gpuDataId, data) { this.gpuDataManager.upload(gpuDataId, data); } memcpy(src, dst) { this.gpuDataManager.memcpy(src, dst); } async download(gpuDataId, getTargetBuffer) { await this.gpuDataManager.download(gpuDataId, getTargetBuffer); } alloc(size) { return this.gpuDataManager.create(size).id; } free(ptr) { return this.gpuDataManager.release(ptr); } createKernel(kernelType, kernelId, attribute, kernelName) { const op = WEBGPU_OP_RESOLVE_RULES.get(kernelType); if (!op) { throw new Error(`kernel not implemented: ${kernelType}`); } const kernelInfo = { kernelType, kernelName, kernelEntry: op[0], attributes: [op[1], attribute] }; this.kernels.set(kernelId, kernelInfo); } releaseKernel(kernelId) { const persistentData = this.kernelPersistentData.get(kernelId); if (persistentData) { for (const data of persistentData) { this.gpuDataManager.release(data.id); } this.kernelPersistentData.delete(kernelId); } this.kernelCustomData.delete(kernelId); this.kernels.delete(kernelId); } computeKernel(kernelId, context, errors) { const kernel = this.kernels.get(kernelId); if (!kernel) { throw new Error(`kernel not created: ${kernelId}`); } const kernelType = kernel.kernelType; const kernelName = kernel.kernelName; const kernelEntry = kernel.kernelEntry; const attributes = kernel.attributes; if (this.currentKernelId !== null) { throw new Error(`kernel "[${kernelType}] ${kernelName}" is not allowed to be called recursively`); } this.currentKernelId = kernelId; if (attributes[0]) { attributes[1] = attributes[0](attributes[1]); attributes[0] = void 0; } LOG_DEBUG("info", () => `[WebGPU] Start to run kernel "[${kernelType}] ${kernelName}"...`); const useErrorScope = this.env.debug; this.temporaryData = []; try { if (useErrorScope) { this.device.pushErrorScope("validation"); } kernelEntry(context, attributes[1]); return 0; } catch (e) { errors.push(Promise.resolve(`[WebGPU] Kernel "[${kernelType}] ${kernelName}" failed. ${e}`)); return 1; } finally { if (useErrorScope) { errors.push( this.device.popErrorScope().then( (err) => err ? `GPU validation error for kernel "[${kernelType}] ${kernelName}": ${err.message}` : null ) ); } for (const data of this.temporaryData) { this.gpuDataManager.release(data.id); } this.temporaryData = []; this.currentKernelId = null; } } // #region external buffer registerBuffer(sessionId, index, buffer, size) { let sessionInputOutputMapping = this.sessionExternalDataMapping.get(sessionId); if (!sessionInputOutputMapping) { sessionInputOutputMapping = /* @__PURE__ */ new Map(); this.sessionExternalDataMapping.set(sessionId, sessionInputOutputMapping); } const previousBuffer = sessionInputOutputMapping.get(index); const id = this.gpuDataManager.registerExternalBuffer(buffer, size, previousBuffer); sessionInputOutputMapping.set(index, [id, buffer]); return id; } unregisterBuffers(sessionId) { const sessionInputOutputMapping = this.sessionExternalDataMapping.get(sessionId); if (sessionInputOutputMapping) { sessionInputOutputMapping.forEach((bufferInfo) => this.gpuDataManager.unregisterExternalBuffer(bufferInfo[0])); this.sessionExternalDataMapping.delete(sessionId); } } getBuffer(gpuDataId) { const gpuData = this.gpuDataManager.get(gpuDataId); if (!gpuData) { throw new Error(`no GPU data for buffer: ${gpuDataId}`); } return gpuData.buffer; } createDownloader(gpuBuffer, size, type) { return async () => { const data = await downloadGpuData(this, gpuBuffer, size); return createView(data.buffer, type); }; } // #endregion writeTimestamp(index) { if (this.queryType !== "inside-passes") { return; } this.computePassEncoder.writeTimestamp(this.querySet, index); } setQueryType() { this.queryType = "none"; if (this.env.webgpu.profiling?.mode === "default" || (typeof this.env.trace === "undefined" ? this.env.wasm.trace : this.env.trace)) { if (this.device.features.has("chromium-experimental-timestamp-query-inside-passes")) { this.queryType = "inside-passes"; } else if (this.device.features.has("timestamp-query")) { this.queryType = "at-passes"; } if (this.queryType !== "none" && typeof this.querySet === "undefined") { this.querySet = this.device.createQuerySet({ type: "timestamp", count: this.maxDispatchNumber * 2 }); this.queryResolveBuffer = this.device.createBuffer( // eslint-disable-next-line no-bitwise { size: this.maxDispatchNumber * 2 * 8, usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.QUERY_RESOLVE } ); } } } captureBegin() { LOG_DEBUG("info", "captureBegin"); if (!this.capturedCommandList.get(this.currentSessionId)) { this.capturedCommandList.set(this.currentSessionId, []); } if (!this.capturedPendingKernels.get(this.currentSessionId)) { this.capturedPendingKernels.set(this.currentSessionId, []); } this.flush(); this.sessionStatus = "capturing"; } captureEnd() { LOG_DEBUG("info", "captureEnd"); this.flush(); this.sessionStatus = "default"; } replay() { LOG_DEBUG("info", "replay"); this.sessionStatus = "replaying"; const sessionCommandList = this.capturedCommandList.get(this.currentSessionId); const sessionPendingKernels = this.capturedPendingKernels.get(this.currentSessionId); const length = sessionCommandList.length; this.pendingKernels = []; for (let i = 0; i < length; i++) { const computePassEncoder = this.getComputePassEncoder(); const command = sessionCommandList[i]; this.writeTimestamp(this.pendingDispatchNumber * 2); computePassEncoder.setPipeline(command.computePipeline); computePassEncoder.setBindGroup(0, command.bindGroup); computePassEncoder.dispatchWorkgroups(...command.dispatchGroup); this.writeTimestamp(this.pendingDispatchNumber * 2 + 1); this.pendingDispatchNumber++; if (this.queryType !== "none") { this.pendingKernels.push(sessionPendingKernels[i]); } if (this.pendingDispatchNumber >= this.maxDispatchNumber || this.queryType === "at-passes") { this.endComputePass(); } if (this.pendingDispatchNumber >= this.maxDispatchNumber) { this.flush(); } } this.flush(); this.sessionStatus = "default"; } onCreateSession() { this.gpuDataManager.onCreateSession(); } onReleaseSession(sessionId) { this.unregisterBuffers(sessionId); if (this.capturedCommandList.has(sessionId)) { this.capturedCommandList.delete(sessionId); } if (this.capturedPendingKernels.has(sessionId)) { this.capturedPendingKernels.delete(sessionId); } this.gpuDataManager.onReleaseSession(sessionId); } onRunStart(sessionId) { this.currentSessionId = sessionId; this.setQueryType(); } }; } }); // web/lib/wasm/jsep/init.ts var init_exports = {}; __export(init_exports, { init: () => init }); var TensorViewImpl, ComputeContextImpl, init; var init_init = __esm({ "web/lib/wasm/jsep/init.ts"() { "use strict"; init_wasm_common(); init_log(); init_util(); init_backend_webnn(); TensorViewImpl = class _TensorViewImpl { constructor(module, dataType, data, dims) { this.module = module; this.dataType = dataType; this.data = data; this.dims = dims; } getFloat32Array() { if (this.dataType !== 1 /* float */) { throw new Error("Invalid data type"); } const elementCount = ShapeUtil.size(this.dims); return elementCount === 0 ? new Float32Array() : new Float32Array(this.module.HEAP8.buffer, this.data, elementCount); } getBigInt64Array() { if (this.dataType !== 7 /* int64 */) { throw new Error("Invalid data type"); } const elementCount = ShapeUtil.size(this.dims); return elementCount === 0 ? new BigInt64Array() : new BigInt64Array(this.module.HEAP8.buffer, this.data, elementCount); } getInt32Array() { if (this.dataType !== 6 /* int32 */) { throw new Error("Invalid data type"); } const elementCount = ShapeUtil.size(this.dims); return elementCount === 0 ? new Int32Array() : new Int32Array(this.module.HEAP8.buffer, this.data, elementCount); } getUint16Array() { if (this.dataType !== 10 /* float16 */ && this.dataType !== 4 /* uint16 */) { throw new Error("Invalid data type"); } const elementCount = ShapeUtil.size(this.dims); return elementCount === 0 ? new Uint16Array() : new Uint16Array(this.module.HEAP8.buffer, this.data, elementCount); } reshape(newDims) { if (ShapeUtil.size(newDims) !== ShapeUtil.size(this.dims)) { throw new Error("Invalid new shape"); } return new _TensorViewImpl(this.module, this.dataType, this.data, newDims); } }; ComputeContextImpl = class { constructor(module, backend, contextDataOffset) { this.module = module; this.backend = backend; this.customDataOffset = 0; this.customDataSize = 0; this.adapterInfo = backend.adapterInfo; const ptrSize = module.PTR_SIZE; let dataIndex = contextDataOffset / module.PTR_SIZE; const type = ptrSize === 4 ? "i32" : "i64"; this.opKernelContext = Number(module.getValue(ptrSize * dataIndex++, type)); const inputCount = Number(module.getValue(ptrSize * dataIndex++, type)); this.outputCount = Number(module.getValue(ptrSize * dataIndex++, type)); this.customDataOffset = Number(module.getValue(ptrSize * dataIndex++, "*")); this.customDataSize = Number(module.getValue(ptrSize * dataIndex++, type)); const inputs = []; for (let i = 0; i < inputCount; i++) { const dataType = Number(module.getValue(ptrSize * dataIndex++, type)); const data = Number(module.getValue(ptrSize * dataIndex++, "*")); const dim = Number(module.getValue(ptrSize * dataIndex++, type)); const dims = []; for (let d = 0; d < dim; d++) { dims.push(Number(module.getValue(ptrSize * dataIndex++, type))); } inputs.push(new TensorViewImpl(module, dataType, data, dims)); } this.inputs = inputs; } get kernelCustomData() { return this.backend.currentKernelCustomData; } get customDataBuffer() { return this.module.HEAPU8.subarray(this.customDataOffset, this.customDataOffset + this.customDataSize); } compute(program, inputsOutputsMapping) { const mappedInputs = inputsOutputsMapping?.inputs?.map((i) => typeof i === "number" ? this.inputs[i] : i) ?? this.inputs; const outputIndices = inputsOutputsMapping?.outputs ?? []; const createKernelOutput = (index, dataType, dims) => new TensorViewImpl(this.module, dataType, this.output(index, dims), dims); const createTemporaryOutput = (dataType, dims) => { const bufferSize = calculateTensorSizeInBytes(dataType, dims); if (!bufferSize) { throw new Error(`Unsupported data type: ${dataType}`); } const gpuDataId = bufferSize > 0 ? this.backend.gpuDataManager.create(bufferSize).id : 0; return new TensorViewImpl(this.module, dataType, gpuDataId, dims); }; return this.backend.run( program, mappedInputs, outputIndices, createKernelOutput, createTemporaryOutput, this.outputCount ); } output(index, dims) { const stack = this.module.stackSave(); try { const ptrSize = this.module.PTR_SIZE; const type = ptrSize === 4 ? "i32" : "i64"; const data = this.module.stackAlloc( (1 + dims.length) * ptrSize /* sizeof(size_t) */ ); this.module.setValue(data, dims.length, type); for (let i = 0; i < dims.length; i++) { this.module.setValue(data + ptrSize * (i + 1), dims[i], type); } return this.module._JsepOutput(this.opKernelContext, index, data); } catch (e) { throw new Error( `Failed to generate kernel's output[${index}] with dims [${dims}]. If you are running with pre-allocated output, please make sure the output type/dims are correct. Error: ${e}` ); } finally { this.module.stackRestore(stack); } } }; init = async (name, module, env3, gpuAdapter) => { const jsepInit = module.jsepInit; if (!jsepInit) { throw new Error("Failed to initialize JSEP. The WebAssembly module is not built with JSEP support."); } if (name === "webgpu") { const webGpuBackendImpl = (init_backend_webgpu(), __toCommonJS(backend_webgpu_exports)).WebGpuBackend; const backend = new webGpuBackendImpl(); await backend.initialize(env3, gpuAdapter); jsepInit("webgpu", [ // backend backend, // jsepAlloc() (size) => backend.alloc(Number(size)), // jsepFree() (ptr) => backend.free(ptr), // jsepCopy(src, dst, size, isSourceGpu) (src, dst, size, isSourceGpu = false) => { if (isSourceGpu) { LOG_DEBUG( "verbose", () => `[WebGPU] jsepCopyGpuToGpu: src=${Number(src)}, dst=${Number(dst)}, size=${Number(size)}` ); backend.memcpy(Number(src), Number(dst)); } else { LOG_DEBUG( "verbose", () => `[WebGPU] jsepCopyCpuToGpu: dataOffset=${Number(src)}, gpuDataId=${Number(dst)}, size=${Number(size)}` ); const data = module.HEAPU8.subarray(Number(src >>> 0), Number(src >>> 0) + Number(size)); backend.upload(Number(dst), data); } }, // jsepCopyAsync(src, dst, size) async (gpuDataId, dataOffset, size) => { LOG_DEBUG( "verbose", () => `[WebGPU] jsepCopyGpuToCpu: gpuDataId=${gpuDataId}, dataOffset=${dataOffset}, size=${size}` ); await backend.download( Number(gpuDataId), () => module.HEAPU8.subarray(Number(dataOffset) >>> 0, Number(dataOffset + size) >>> 0) ); }, // jsepCreateKernel (kernelType, kernelId, attribute) => backend.createKernel( kernelType, Number(kernelId), attribute, module.UTF8ToString(module._JsepGetNodeName(Number(kernelId))) ), // jsepReleaseKernel (kernel) => backend.releaseKernel(kernel), // jsepRun (kernel, contextDataOffset, sessionHandle, errors) => { LOG_DEBUG( "verbose", () => `[WebGPU] jsepRun: sessionHandle=${sessionHandle}, kernel=${kernel}, contextDataOffset=${contextDataOffset}` ); const context = new ComputeContextImpl(module, backend, Number(contextDataOffset)); return backend.computeKernel(Number(kernel), context, errors); }, // jsepCaptureBegin () => backend.captureBegin(), // jsepCaptureEnd () => backend.captureEnd(), // jsepReplay () => backend.replay() ]); } else { const backend = new WebNNBackend(env3); jsepInit("webnn", [ backend, // webnnReserveTensorId () => backend.reserveTensorId(), // webnnReleaseTensorId (tensorId) => backend.releaseTensorId(tensorId), // webnnEnsureTensor async (sessionId, tensorId, onnxDataType, shape, copyOld) => backend.ensureTensor(sessionId, tensorId, onnxDataType, shape, copyOld), // webnnUploadTensor (tensorId, data) => { backend.uploadTensor(tensorId, data); }, // webnnDownloadTensor async (tensorId, dstBuffer) => backend.downloadTensor(tensorId, dstBuffer), // webnnRegisterMLContext (sessionId, mlContext) => backend.registerMLContext(sessionId, mlContext), // webnnEnableTraceEvent !!env3.trace ]); } }; } }); // web/lib/wasm/wasm-core-impl.ts var initOrt, initRuntime, initEp, activeSessions, getSessionInputOutputCount, getSessionInputOutputMetadata, copyFromExternalBuffer, createSession, releaseSession, prepareInputOutputTensor, run, endProfiling, extractTransferableBuffers; var init_wasm_core_impl = __esm({ "web/lib/wasm/wasm-core-impl.ts"() { "use strict"; init_esm(); init_run_options(); init_session_options(); init_wasm_common(); init_wasm_factory(); init_wasm_utils(); init_wasm_utils_load_file(); initOrt = (numThreads, loggingLevel) => { const errorCode = getInstance()._OrtInit(numThreads, loggingLevel); if (errorCode !== 0) { checkLastError("Can't initialize onnxruntime."); } }; initRuntime = async (env3) => { initOrt(env3.wasm.numThreads, logLevelStringToEnum(env3.logLevel)); }; initEp = async (env3, epName) => { getInstance().asyncInit?.(); let webgpuAdapter = env3.webgpu.adapter; if (epName === "webgpu") { if (typeof navigator === "undefined" || !navigator.gpu) { throw new Error("WebGPU is not supported in current environment"); } if (!webgpuAdapter) { const powerPreference = env3.webgpu.powerPreference; if (powerPreference !== void 0 && powerPreference !== "low-power" && powerPreference !== "high-performance") { throw new Error(`Invalid powerPreference setting: "${powerPreference}"`); } const forceFallbackAdapter = env3.webgpu.forceFallbackAdapter; if (forceFallbackAdapter !== void 0 && typeof forceFallbackAdapter !== "boolean") { throw new Error(`Invalid forceFallbackAdapter setting: "${forceFallbackAdapter}"`); } webgpuAdapter = await navigator.gpu.requestAdapter({ powerPreference, forceFallbackAdapter }); if (!webgpuAdapter) { throw new Error( 'Failed to get GPU adapter. You may need to enable flag "--enable-unsafe-webgpu" if you are using Chrome.' ); } } else { if (typeof webgpuAdapter.limits !== "object" || typeof webgpuAdapter.features !== "object" || typeof webgpuAdapter.requestDevice !== "function") { throw new Error("Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object."); } } } if (epName === "webnn") { if (typeof navigator === "undefined" || !navigator.ml) { throw new Error("WebNN is not supported in current environment"); } } if (true) { const initJsep = (init_init(), __toCommonJS(init_exports)).init; if (epName === "webgpu") { await initJsep("webgpu", getInstance(), env3, webgpuAdapter); } if (epName === "webnn") { await initJsep("webnn", getInstance(), env3); } } else { if (false) { getInstance().webgpuInit((device) => { env3.webgpu.device = device; }); } if (epName === "webnn") { const backend = new null.WebNNBackend(env3); getInstance().webnnInit([ backend, // webnnReserveTensorId () => backend.reserveTensorId(), // webnnReleaseTensorId, (tensorId) => backend.releaseTensorId(tensorId), // webnnEnsureTensor async (sessionId, tensorId, onnxDataType, shape, copyOld) => backend.ensureTensor(sessionId, tensorId, onnxDataType, shape, copyOld), // webnnUploadTensor (tensorId, data) => { backend.uploadTensor(tensorId, data); }, // webnnDownloadTensor async (tensorId, dstBuffer) => backend.downloadTensor(tensorId, dstBuffer), // webnnRegisterMLContext (sessionId, mlContext) => backend.registerMLContext(sessionId, mlContext), // webnnEnableTraceEvent !!env3.trace ]); } } }; activeSessions = /* @__PURE__ */ new Map(); getSessionInputOutputCount = (sessionHandle) => { const wasm2 = getInstance(); const stack = wasm2.stackSave(); try { const ptrSize = wasm2.PTR_SIZE; const dataOffset = wasm2.stackAlloc(2 * ptrSize); const errorCode = wasm2._OrtGetInputOutputCount(sessionHandle, dataOffset, dataOffset + ptrSize); if (errorCode !== 0) { checkLastError("Can't get session input/output count."); } const type = ptrSize === 4 ? "i32" : "i64"; return [Number(wasm2.getValue(dataOffset, type)), Number(wasm2.getValue(dataOffset + ptrSize, type))]; } finally { wasm2.stackRestore(stack); } }; getSessionInputOutputMetadata = (sessionHandle, index) => { const wasm2 = getInstance(); const stack = wasm2.stackSave(); let metadataOffset = 0; try { const ptrSize = wasm2.PTR_SIZE; const dataOffset = wasm2.stackAlloc(2 * ptrSize); const errorCode = wasm2._OrtGetInputOutputMetadata(sessionHandle, index, dataOffset, dataOffset + ptrSize); if (errorCode !== 0) { checkLastError("Can't get session input/output metadata."); } const nameOffset = Number(wasm2.getValue(dataOffset, "*")); metadataOffset = Number(wasm2.getValue(dataOffset + ptrSize, "*")); const elementType = wasm2.HEAP32[metadataOffset / 4]; if (elementType === 0) { return [nameOffset, 0]; } const dimsCount = wasm2.HEAPU32[metadataOffset / 4 + 1]; const dims = []; for (let i = 0; i < dimsCount; i++) { const symbolicDimNameOffset = Number(wasm2.getValue(metadataOffset + 8 + i * ptrSize, "*")); dims.push( symbolicDimNameOffset !== 0 ? wasm2.UTF8ToString(symbolicDimNameOffset) : Number(wasm2.getValue(metadataOffset + 8 + (i + dimsCount) * ptrSize, "*")) ); } return [nameOffset, elementType, dims]; } finally { wasm2.stackRestore(stack); if (metadataOffset !== 0) { wasm2._OrtFree(metadataOffset); } } }; copyFromExternalBuffer = (model) => { const wasm2 = getInstance(); const modelDataOffset = wasm2._malloc(model.byteLength); if (modelDataOffset === 0) { throw new Error(`Can't create a session. failed to allocate a buffer of size ${model.byteLength}.`); } wasm2.HEAPU8.set(model, modelDataOffset); return [modelDataOffset, model.byteLength]; }; createSession = async (modelData, options) => { let modelDataOffset, modelDataLength; const wasm2 = getInstance(); if (Array.isArray(modelData)) { [modelDataOffset, modelDataLength] = modelData; } else if (modelData.buffer === wasm2.HEAPU8.buffer) { [modelDataOffset, modelDataLength] = [modelData.byteOffset, modelData.byteLength]; } else { [modelDataOffset, modelDataLength] = copyFromExternalBuffer(modelData); } let sessionHandle = 0; let sessionOptionsHandle = 0; let ioBindingHandle = 0; let allocs = []; const inputNamesUTF8Encoded = []; const outputNamesUTF8Encoded = []; try { [sessionOptionsHandle, allocs] = await setSessionOptions(options); if (options?.externalData && wasm2.mountExternalData) { const loadingPromises = []; for (const file of options.externalData) { const path = typeof file === "string" ? file : file.path; loadingPromises.push( loadFile(typeof file === "string" ? file : file.data).then((data) => { wasm2.mountExternalData(path, data); }) ); } await Promise.all(loadingPromises); } for (const provider of options?.executionProviders ?? []) { const providerName = typeof provider === "string" ? provider : provider.name; if (providerName === "webnn") { wasm2.shouldTransferToMLTensor = false; if (typeof provider !== "string") { const webnnOptions = provider; const context = webnnOptions?.context; const gpuDevice = webnnOptions?.gpuDevice; const deviceType = webnnOptions?.deviceType; const powerPreference = webnnOptions?.powerPreference; if (context) { wasm2.currentContext = context; } else if (gpuDevice) { wasm2.currentContext = await wasm2.webnnCreateMLContext(gpuDevice); } else { wasm2.currentContext = await wasm2.webnnCreateMLContext({ deviceType, powerPreference }); } } else { wasm2.currentContext = await wasm2.webnnCreateMLContext(); } break; } } sessionHandle = await wasm2._OrtCreateSession(modelDataOffset, modelDataLength, sessionOptionsHandle); wasm2.webgpuOnCreateSession?.(sessionHandle); if (sessionHandle === 0) { checkLastError("Can't create a session."); } wasm2.jsepOnCreateSession?.(); if (wasm2.currentContext) { wasm2.webnnRegisterMLContext(sessionHandle, wasm2.currentContext); wasm2.currentContext = void 0; wasm2.shouldTransferToMLTensor = true; } const [inputCount, outputCount] = getSessionInputOutputCount(sessionHandle); const enableGraphCapture = !!options?.enableGraphCapture; const inputNames = []; const outputNames = []; const inputMetadata = []; const outputMetadata = []; const outputPreferredLocations = []; for (let i = 0; i < inputCount; i++) { const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i); if (nameOffset === 0) { checkLastError("Can't get an input name."); } inputNamesUTF8Encoded.push(nameOffset); const name = wasm2.UTF8ToString(nameOffset); inputNames.push(name); inputMetadata.push( elementType === 0 ? { name, isTensor: false } : { name, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape } ); } for (let i = 0; i < outputCount; i++) { const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i + inputCount); if (nameOffset === 0) { checkLastError("Can't get an output name."); } outputNamesUTF8Encoded.push(nameOffset); const nameString = wasm2.UTF8ToString(nameOffset); outputNames.push(nameString); outputMetadata.push( elementType === 0 ? { name: nameString, isTensor: false } : { name: nameString, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape } ); if (true) { if (enableGraphCapture && options?.preferredOutputLocation === void 0) { outputPreferredLocations.push("gpu-buffer"); continue; } const location2 = typeof options?.preferredOutputLocation === "string" ? options.preferredOutputLocation : options?.preferredOutputLocation?.[nameString] ?? "cpu"; const isGraphOutput = wasm2.webnnIsGraphOutput; if (location2 === "cpu" && isGraphOutput && isGraphOutput(sessionHandle, nameString)) { outputPreferredLocations.push("ml-tensor-cpu-output"); continue; } if (location2 !== "cpu" && location2 !== "cpu-pinned" && location2 !== "gpu-buffer" && location2 !== "ml-tensor") { throw new Error(`Not supported preferred output location: ${location2}.`); } if (enableGraphCapture && location2 !== "gpu-buffer") { throw new Error( `Not supported preferred output location: ${location2}. Only 'gpu-buffer' location is supported when enableGraphCapture is true.` ); } outputPreferredLocations.push(location2); } } let bindingState = null; if (outputPreferredLocations.some((l) => l === "gpu-buffer" || l === "ml-tensor" || l === "ml-tensor-cpu-output")) { ioBindingHandle = wasm2._OrtCreateBinding(sessionHandle); if (ioBindingHandle === 0) { checkLastError("Can't create IO binding."); } bindingState = { handle: ioBindingHandle, outputPreferredLocations, outputPreferredLocationsEncoded: outputPreferredLocations.map((l) => l === "ml-tensor-cpu-output" ? "ml-tensor" : l).map((l) => dataLocationStringToEnum(l)) }; } activeSessions.set(sessionHandle, [ sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, bindingState, enableGraphCapture, false ]); return [sessionHandle, inputNames, outputNames, inputMetadata, outputMetadata]; } catch (e) { inputNamesUTF8Encoded.forEach((buf) => wasm2._OrtFree(buf)); outputNamesUTF8Encoded.forEach((buf) => wasm2._OrtFree(buf)); if (ioBindingHandle !== 0) { if (wasm2._OrtReleaseBinding(ioBindingHandle) !== 0) { checkLastError("Can't release IO binding."); } } if (sessionHandle !== 0) { if (wasm2._OrtReleaseSession(sessionHandle) !== 0) { checkLastError("Can't release session."); } } throw e; } finally { wasm2._free(modelDataOffset); if (sessionOptionsHandle !== 0) { if (wasm2._OrtReleaseSessionOptions(sessionOptionsHandle) !== 0) { checkLastError("Can't release session options."); } } allocs.forEach((alloc) => wasm2._free(alloc)); wasm2.unmountExternalData?.(); } }; releaseSession = (sessionId) => { const wasm2 = getInstance(); const session = activeSessions.get(sessionId); if (!session) { throw new Error(`cannot release session. invalid session id: ${sessionId}`); } const [sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, ioBindingState, enableGraphCapture] = session; if (ioBindingState) { if (enableGraphCapture) { if (wasm2._OrtClearBoundOutputs(ioBindingState.handle) !== 0) { checkLastError("Can't clear bound outputs."); } } if (wasm2._OrtReleaseBinding(ioBindingState.handle) !== 0) { checkLastError("Can't release IO binding."); } } wasm2.jsepOnReleaseSession?.(sessionId); wasm2.webnnOnReleaseSession?.(sessionId); wasm2.webgpuOnReleaseSession?.(sessionId); inputNamesUTF8Encoded.forEach((buf) => wasm2._OrtFree(buf)); outputNamesUTF8Encoded.forEach((buf) => wasm2._OrtFree(buf)); if (wasm2._OrtReleaseSession(sessionHandle) !== 0) { checkLastError("Can't release session."); } activeSessions.delete(sessionId); }; prepareInputOutputTensor = async (tensor, tensorHandles, allocs, sessionId, tensorNameUTF8Encoded, index, enableGraphCapture = false) => { if (!tensor) { tensorHandles.push(0); return; } const wasm2 = getInstance(); const ptrSize = wasm2.PTR_SIZE; const dataType = tensor[0]; const dims = tensor[1]; const location2 = tensor[3]; let actualLocation = location2; let rawData; let dataByteLength; if (dataType === "string" && (location2 === "gpu-buffer" || location2 === "ml-tensor")) { throw new Error("String tensor is not supported on GPU."); } if (enableGraphCapture && location2 !== "gpu-buffer") { throw new Error( `External buffer must be provided for input/output index ${index} when enableGraphCapture is true.` ); } if (location2 === "gpu-buffer") { const gpuBuffer = tensor[2].gpuBuffer; dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims); if (false) { const registerBuffer = wasm2.webgpuRegisterBuffer; if (!registerBuffer) { throw new Error('Tensor location "gpu-buffer" is not supported without using WebGPU.'); } rawData = registerBuffer(gpuBuffer, sessionId); } else { const registerBuffer = wasm2.jsepRegisterBuffer; if (!registerBuffer) { throw new Error('Tensor location "gpu-buffer" is not supported without using WebGPU.'); } rawData = registerBuffer(sessionId, index, gpuBuffer, dataByteLength); } } else if (location2 === "ml-tensor") { const mlTensor = tensor[2].mlTensor; dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims); const registerMLTensor = wasm2.webnnRegisterMLTensor; if (!registerMLTensor) { throw new Error('Tensor location "ml-tensor" is not supported without using WebNN.'); } rawData = registerMLTensor(sessionId, mlTensor, tensorDataTypeStringToEnum(dataType), dims); } else { const data = tensor[2]; if (Array.isArray(data)) { dataByteLength = ptrSize * data.length; rawData = wasm2._malloc(dataByteLength); allocs.push(rawData); for (let i = 0; i < data.length; i++) { if (typeof data[i] !== "string") { throw new TypeError(`tensor data at index ${i} is not a string`); } wasm2.setValue(rawData + i * ptrSize, allocWasmString(data[i], allocs), "*"); } } else { const isGraphInput = wasm2.webnnIsGraphInput; const isGraphOutput = wasm2.webnnIsGraphOutput; if (dataType !== "string" && isGraphInput && isGraphOutput) { const tensorName = wasm2.UTF8ToString(tensorNameUTF8Encoded); if (isGraphInput(sessionId, tensorName) || isGraphOutput(sessionId, tensorName)) { const dataTypeEnum = tensorDataTypeStringToEnum(dataType); dataByteLength = calculateTensorSizeInBytes(dataTypeEnum, dims); actualLocation = "ml-tensor"; const createTemporaryTensor = wasm2.webnnCreateTemporaryTensor; const uploadTensor = wasm2.webnnUploadTensor; if (!createTemporaryTensor || !uploadTensor) { throw new Error('Tensor location "ml-tensor" is not supported without using WebNN.'); } const tensorId = await createTemporaryTensor(sessionId, dataTypeEnum, dims); uploadTensor(tensorId, new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); rawData = tensorId; } else { dataByteLength = data.byteLength; rawData = wasm2._malloc(dataByteLength); allocs.push(rawData); wasm2.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData); } } else { dataByteLength = data.byteLength; rawData = wasm2._malloc(dataByteLength); allocs.push(rawData); wasm2.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData); } } } const stack = wasm2.stackSave(); const dimsOffset = wasm2.stackAlloc(4 * dims.length); try { dims.forEach((d, index2) => wasm2.setValue(dimsOffset + index2 * ptrSize, d, ptrSize === 4 ? "i32" : "i64")); const tensor2 = wasm2._OrtCreateTensor( tensorDataTypeStringToEnum(dataType), rawData, dataByteLength, dimsOffset, dims.length, dataLocationStringToEnum(actualLocation) ); if (tensor2 === 0) { checkLastError(`Can't create tensor for input/output. session=${sessionId}, index=${index}.`); } tensorHandles.push(tensor2); } finally { wasm2.stackRestore(stack); } }; run = async (sessionId, inputIndices, inputTensors, outputIndices, outputTensors, options) => { const wasm2 = getInstance(); const ptrSize = wasm2.PTR_SIZE; const session = activeSessions.get(sessionId); if (!session) { throw new Error(`cannot run inference. invalid session id: ${sessionId}`); } const sessionHandle = session[0]; const inputNamesUTF8Encoded = session[1]; const outputNamesUTF8Encoded = session[2]; const ioBindingState = session[3]; const enableGraphCapture = session[4]; const inputOutputBound = session[5]; const inputCount = inputIndices.length; const outputCount = outputIndices.length; let runOptionsHandle = 0; let runOptionsAllocs = []; const inputTensorHandles = []; const outputTensorHandles = []; const inputOutputAllocs = []; const preAllocatedOutputs = []; const beforeRunStack = wasm2.stackSave(); const inputValuesOffset = wasm2.stackAlloc(inputCount * ptrSize); const inputNamesOffset = wasm2.stackAlloc(inputCount * ptrSize); const outputValuesOffset = wasm2.stackAlloc(outputCount * ptrSize); const outputNamesOffset = wasm2.stackAlloc(outputCount * ptrSize); try { [runOptionsHandle, runOptionsAllocs] = setRunOptions(options); TRACE_EVENT_BEGIN("wasm prepareInputOutputTensor"); for (let i = 0; i < inputCount; i++) { await prepareInputOutputTensor( inputTensors[i], inputTensorHandles, inputOutputAllocs, sessionId, inputNamesUTF8Encoded[inputIndices[i]], inputIndices[i], enableGraphCapture ); } for (let i = 0; i < outputCount; i++) { await prepareInputOutputTensor( outputTensors[i], outputTensorHandles, inputOutputAllocs, sessionId, outputNamesUTF8Encoded[outputIndices[i]], inputCount + outputIndices[i], enableGraphCapture ); } TRACE_EVENT_END("wasm prepareInputOutputTensor"); for (let i = 0; i < inputCount; i++) { wasm2.setValue(inputValuesOffset + i * ptrSize, inputTensorHandles[i], "*"); wasm2.setValue(inputNamesOffset + i * ptrSize, inputNamesUTF8Encoded[inputIndices[i]], "*"); } for (let i = 0; i < outputCount; i++) { wasm2.setValue(outputValuesOffset + i * ptrSize, outputTensorHandles[i], "*"); wasm2.setValue(outputNamesOffset + i * ptrSize, outputNamesUTF8Encoded[outputIndices[i]], "*"); } if (ioBindingState && !inputOutputBound) { const { handle, outputPreferredLocations, outputPreferredLocationsEncoded } = ioBindingState; if (inputNamesUTF8Encoded.length !== inputCount) { throw new Error( `input count from feeds (${inputCount}) is expected to be always equal to model's input count (${inputNamesUTF8Encoded.length}).` ); } TRACE_EVENT_BEGIN("wasm bindInputsOutputs"); for (let i = 0; i < inputCount; i++) { const index = inputIndices[i]; const errorCode2 = await wasm2._OrtBindInput(handle, inputNamesUTF8Encoded[index], inputTensorHandles[i]); if (errorCode2 !== 0) { checkLastError(`Can't bind input[${i}] for session=${sessionId}.`); } } for (let i = 0; i < outputCount; i++) { const index = outputIndices[i]; const location2 = outputTensors[i]?.[3]; if (location2) { preAllocatedOutputs.push(outputTensorHandles[i]); const errorCode2 = wasm2._OrtBindOutput(handle, outputNamesUTF8Encoded[index], outputTensorHandles[i], 0); if (errorCode2 !== 0) { checkLastError(`Can't bind pre-allocated output[${i}] for session=${sessionId}.`); } } else { const errorCode2 = wasm2._OrtBindOutput( handle, outputNamesUTF8Encoded[index], 0, outputPreferredLocationsEncoded[index] ); if (errorCode2 !== 0) { checkLastError(`Can't bind output[${i}] to ${outputPreferredLocations[i]} for session=${sessionId}.`); } } } TRACE_EVENT_END("wasm bindInputsOutputs"); activeSessions.set(sessionId, [ sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, ioBindingState, enableGraphCapture, true ]); } wasm2.jsepOnRunStart?.(sessionHandle); wasm2.webnnOnRunStart?.(sessionHandle); let errorCode; if (ioBindingState) { errorCode = await wasm2._OrtRunWithBinding( sessionHandle, ioBindingState.handle, outputCount, outputValuesOffset, runOptionsHandle ); } else { errorCode = await wasm2._OrtRun( sessionHandle, inputNamesOffset, inputValuesOffset, inputCount, outputNamesOffset, outputCount, outputValuesOffset, runOptionsHandle ); } if (errorCode !== 0) { checkLastError("failed to call OrtRun()."); } const output = []; const outputPromises = []; TRACE_EVENT_BEGIN("wasm ProcessOutputTensor"); for (let i = 0; i < outputCount; i++) { const tensor = Number(wasm2.getValue(outputValuesOffset + i * ptrSize, "*")); if (tensor === outputTensorHandles[i] || preAllocatedOutputs.includes(outputTensorHandles[i])) { output.push(outputTensors[i]); if (tensor !== outputTensorHandles[i]) { if (wasm2._OrtReleaseTensor(tensor) !== 0) { checkLastError("Can't release tensor."); } } continue; } const beforeGetTensorDataStack = wasm2.stackSave(); const tensorDataOffset = wasm2.stackAlloc(4 * ptrSize); let keepOutputTensor = false; let type, dataOffset = 0; try { const errorCode2 = wasm2._OrtGetTensorData( tensor, tensorDataOffset, tensorDataOffset + ptrSize, tensorDataOffset + 2 * ptrSize, tensorDataOffset + 3 * ptrSize ); if (errorCode2 !== 0) { checkLastError(`Can't access output tensor data on index ${i}.`); } const valueType = ptrSize === 4 ? "i32" : "i64"; const dataType = Number(wasm2.getValue(tensorDataOffset, valueType)); dataOffset = wasm2.getValue(tensorDataOffset + ptrSize, "*"); const dimsOffset = wasm2.getValue(tensorDataOffset + ptrSize * 2, "*"); const dimsLength = Number(wasm2.getValue(tensorDataOffset + ptrSize * 3, valueType)); const dims = []; for (let i2 = 0; i2 < dimsLength; i2++) { dims.push(Number(wasm2.getValue(dimsOffset + i2 * ptrSize, valueType))); } if (wasm2._OrtFree(dimsOffset) !== 0) { checkLastError("Can't free memory for tensor dims."); } const size = dims.reduce((a, b) => a * b, 1); type = tensorDataTypeEnumToString(dataType); const preferredLocation = ioBindingState?.outputPreferredLocations[outputIndices[i]]; if (type === "string") { if (preferredLocation === "gpu-buffer" || preferredLocation === "ml-tensor") { throw new Error("String tensor is not supported on GPU."); } const stringData = []; for (let i2 = 0; i2 < size; i2++) { const offset = wasm2.getValue(dataOffset + i2 * ptrSize, "*"); const nextOffset = wasm2.getValue(dataOffset + (i2 + 1) * ptrSize, "*"); const maxBytesToRead = i2 === size - 1 ? void 0 : nextOffset - offset; stringData.push(wasm2.UTF8ToString(offset, maxBytesToRead)); } output.push([type, dims, stringData, "cpu"]); } else { if (preferredLocation === "gpu-buffer" && size > 0) { const getBuffer = false ? wasm2.webgpuGetBuffer : wasm2.jsepGetBuffer; if (!getBuffer) { throw new Error('preferredLocation "gpu-buffer" is not supported without using WebGPU.'); } const gpuBuffer = getBuffer(dataOffset); const bufferSize = calculateTensorSizeInBytes(dataType, size); if (bufferSize === void 0 || !isGpuBufferSupportedType(type)) { throw new Error(`Unsupported data type: ${type}`); } keepOutputTensor = true; if (false) { wasm2.webgpuRegisterBuffer(gpuBuffer, sessionId, dataOffset); const downloadDataFunction = wasm2.webgpuCreateDownloader(gpuBuffer, bufferSize, sessionId); output.push([ type, dims, { gpuBuffer, download: async () => { const arrayBuffer = await downloadDataFunction(); const data = new (tensorTypeToTypedArrayConstructor(type))(arrayBuffer); return data; }, dispose: () => { if (wasm2._OrtReleaseTensor(tensor) !== 0) { checkLastError("Can't release tensor."); } } }, "gpu-buffer" ]); } else { output.push([ type, dims, { gpuBuffer, download: wasm2.jsepCreateDownloader(gpuBuffer, bufferSize, type), dispose: () => { if (wasm2._OrtReleaseTensor(tensor) !== 0) { checkLastError("Can't release tensor."); } } }, "gpu-buffer" ]); } } else if (preferredLocation === "ml-tensor" && size > 0) { const ensureTensor = wasm2.webnnEnsureTensor; const isGraphInputOutputTypeSupported = wasm2.webnnIsGraphInputOutputTypeSupported; if (!ensureTensor || !isGraphInputOutputTypeSupported) { throw new Error('preferredLocation "ml-tensor" is not supported without using WebNN.'); } const tensorSize = calculateTensorSizeInBytes(dataType, size); if (tensorSize === void 0 || !isMLTensorSupportedType(type)) { throw new Error(`Unsupported data type: ${type}`); } if (!isGraphInputOutputTypeSupported(sessionId, type, false)) { throw new Error( `preferredLocation "ml-tensor" for ${type} output is not supported by current WebNN Context.` ); } const mlTensor = await ensureTensor(sessionId, dataOffset, dataType, dims, false); keepOutputTensor = true; output.push([ type, dims, { mlTensor, download: wasm2.webnnCreateMLTensorDownloader(dataOffset, type), dispose: () => { wasm2.webnnReleaseTensorId(dataOffset); wasm2._OrtReleaseTensor(tensor); } }, "ml-tensor" ]); } else if (preferredLocation === "ml-tensor-cpu-output" && size > 0) { const data = wasm2.webnnCreateMLTensorDownloader(dataOffset, type)(); const index = output.length; keepOutputTensor = true; outputPromises.push( (async () => { const result = [index, await data]; wasm2.webnnReleaseTensorId(dataOffset); wasm2._OrtReleaseTensor(tensor); return result; })() ); output.push([type, dims, [], "cpu"]); } else { const typedArrayConstructor = tensorTypeToTypedArrayConstructor(type); const data = new typedArrayConstructor(size); new Uint8Array(data.buffer, data.byteOffset, data.byteLength).set( wasm2.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength) ); output.push([type, dims, data, "cpu"]); } } } finally { wasm2.stackRestore(beforeGetTensorDataStack); if (type === "string" && dataOffset) { wasm2._free(dataOffset); } if (!keepOutputTensor) { wasm2._OrtReleaseTensor(tensor); } } } if (ioBindingState && !enableGraphCapture) { if (wasm2._OrtClearBoundOutputs(ioBindingState.handle) !== 0) { checkLastError("Can't clear bound outputs."); } activeSessions.set(sessionId, [ sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, ioBindingState, enableGraphCapture, false ]); } for (const [index, data] of await Promise.all(outputPromises)) { output[index][2] = data; } TRACE_EVENT_END("wasm ProcessOutputTensor"); return output; } finally { wasm2.webnnOnRunEnd?.(sessionHandle); wasm2.stackRestore(beforeRunStack); if (false) { inputTensors.forEach((t) => { if (t && t[3] === "gpu-buffer") { wasm2.webgpuUnregisterBuffer(t[2].gpuBuffer); } }); outputTensors.forEach((t) => { if (t && t[3] === "gpu-buffer") { wasm2.webgpuUnregisterBuffer(t[2].gpuBuffer); } }); } inputTensorHandles.forEach((v) => wasm2._OrtReleaseTensor(v)); outputTensorHandles.forEach((v) => wasm2._OrtReleaseTensor(v)); inputOutputAllocs.forEach((p) => wasm2._free(p)); if (runOptionsHandle !== 0) { wasm2._OrtReleaseRunOptions(runOptionsHandle); } runOptionsAllocs.forEach((p) => wasm2._free(p)); } }; endProfiling = (sessionId) => { const wasm2 = getInstance(); const session = activeSessions.get(sessionId); if (!session) { throw new Error("invalid session id"); } const sessionHandle = session[0]; const profileFileName = wasm2._OrtEndProfiling(sessionHandle); if (profileFileName === 0) { checkLastError("Can't get an profile file name."); } wasm2._OrtFree(profileFileName); }; extractTransferableBuffers = (tensors) => { const buffers = []; for (const tensor of tensors) { const data = tensor[2]; if (!Array.isArray(data) && "buffer" in data) { buffers.push(data.buffer); } } return buffers; }; } }); // web/lib/wasm/proxy-wrapper.ts var isProxy, proxyWorker, initializing2, initialized2, aborted2, temporaryObjectUrl, initWasmCallbacks, queuedCallbacks, enqueueCallbacks, ensureWorker, onProxyWorkerMessage, initializeWebAssemblyAndOrtRuntime, initializeOrtEp, copyFromExternalBuffer2, createSession2, releaseSession2, run2, endProfiling2; var init_proxy_wrapper = __esm({ "web/lib/wasm/proxy-wrapper.ts"() { "use strict"; init_esm(); init_wasm_core_impl(); init_wasm_factory(); init_wasm_utils_import(); isProxy = () => !!env2.wasm.proxy && typeof document !== "undefined"; initializing2 = false; initialized2 = false; aborted2 = false; queuedCallbacks = /* @__PURE__ */ new Map(); enqueueCallbacks = (type, callbacks) => { const queue = queuedCallbacks.get(type); if (queue) { queue.push(callbacks); } else { queuedCallbacks.set(type, [callbacks]); } }; ensureWorker = () => { if (initializing2 || !initialized2 || aborted2 || !proxyWorker) { throw new Error("worker not ready"); } }; onProxyWorkerMessage = (ev) => { switch (ev.data.type) { case "init-wasm": initializing2 = false; if (ev.data.err) { aborted2 = true; initWasmCallbacks[1](ev.data.err); } else { initialized2 = true; initWasmCallbacks[0](); } if (temporaryObjectUrl) { URL.revokeObjectURL(temporaryObjectUrl); temporaryObjectUrl = void 0; } break; case "init-ep": case "copy-from": case "create": case "release": case "run": case "end-profiling": { const callbacks = queuedCallbacks.get(ev.data.type); if (ev.data.err) { callbacks.shift()[1](ev.data.err); } else { callbacks.shift()[0](ev.data.out); } break; } default: } }; initializeWebAssemblyAndOrtRuntime = async () => { if (initialized2) { return; } if (initializing2) { throw new Error("multiple calls to 'initWasm()' detected."); } if (aborted2) { throw new Error("previous call to 'initWasm()' failed."); } initializing2 = true; if (isProxy()) { return new Promise((resolve, reject) => { proxyWorker?.terminate(); void importProxyWorker().then(([objectUrl, worker]) => { try { proxyWorker = worker; proxyWorker.onerror = (ev) => reject(ev); proxyWorker.onmessage = onProxyWorkerMessage; initWasmCallbacks = [resolve, reject]; const message = { type: "init-wasm", in: env2 }; if (!message.in.wasm.wasmPaths && objectUrl) { const inferredWasmPathPrefix = inferWasmPathPrefixFromScriptSrc(); if (inferredWasmPathPrefix) { message.in.wasm.wasmPaths = inferredWasmPathPrefix; } } if (false) { message.in.wasm.wasmPaths = { wasm: true ? new URL("ort-wasm-simd-threaded.jsep.wasm", void 0).href : false ? new URL("ort-wasm-simd-threaded.jspi.wasm", void 0).href : false ? new URL("ort-wasm-simd-threaded.asyncify.wasm", void 0).href : new URL("ort-wasm-simd-threaded.wasm", void 0).href }; } proxyWorker.postMessage(message); temporaryObjectUrl = objectUrl; } catch (e) { reject(e); } }, reject); }); } else { try { await initializeWebAssembly(env2.wasm); await initRuntime(env2); initialized2 = true; } catch (e) { aborted2 = true; throw e; } finally { initializing2 = false; } } }; initializeOrtEp = async (epName) => { if (isProxy()) { ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks("init-ep", [resolve, reject]); const message = { type: "init-ep", in: { epName, env: env2 } }; proxyWorker.postMessage(message); }); } else { await initEp(env2, epName); } }; copyFromExternalBuffer2 = async (buffer) => { if (isProxy()) { ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks("copy-from", [resolve, reject]); const message = { type: "copy-from", in: { buffer } }; proxyWorker.postMessage(message, [buffer.buffer]); }); } else { return copyFromExternalBuffer(buffer); } }; createSession2 = async (model, options) => { if (isProxy()) { if (options?.preferredOutputLocation) { throw new Error('session option "preferredOutputLocation" is not supported for proxy.'); } ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks("create", [resolve, reject]); const message = { type: "create", in: { model, options: { ...options } } }; const transferable = []; if (model instanceof Uint8Array) { transferable.push(model.buffer); } proxyWorker.postMessage(message, transferable); }); } else { return createSession(model, options); } }; releaseSession2 = async (sessionId) => { if (isProxy()) { ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks("release", [resolve, reject]); const message = { type: "release", in: sessionId }; proxyWorker.postMessage(message); }); } else { releaseSession(sessionId); } }; run2 = async (sessionId, inputIndices, inputs, outputIndices, outputs, options) => { if (isProxy()) { if (inputs.some((t) => t[3] !== "cpu")) { throw new Error("input tensor on GPU is not supported for proxy."); } if (outputs.some((t) => t)) { throw new Error("pre-allocated output tensor is not supported for proxy."); } ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks("run", [resolve, reject]); const serializableInputs = inputs; const message = { type: "run", in: { sessionId, inputIndices, inputs: serializableInputs, outputIndices, options } }; proxyWorker.postMessage(message, extractTransferableBuffers(serializableInputs)); }); } else { return run(sessionId, inputIndices, inputs, outputIndices, outputs, options); } }; endProfiling2 = async (sessionId) => { if (isProxy()) { ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks("end-profiling", [resolve, reject]); const message = { type: "end-profiling", in: sessionId }; proxyWorker.postMessage(message); }); } else { endProfiling(sessionId); } }; } }); // web/lib/wasm/session-handler-inference.ts var encodeTensorMetadata, decodeTensorMetadata, OnnxruntimeWebAssemblySessionHandler; var init_session_handler_inference = __esm({ "web/lib/wasm/session-handler-inference.ts"() { "use strict"; init_esm(); init_proxy_wrapper(); init_wasm_common(); init_wasm_utils_env(); init_wasm_utils_load_file(); encodeTensorMetadata = (tensor, getName) => { switch (tensor.location) { case "cpu": return [tensor.type, tensor.dims, tensor.data, "cpu"]; case "gpu-buffer": return [tensor.type, tensor.dims, { gpuBuffer: tensor.gpuBuffer }, "gpu-buffer"]; case "ml-tensor": return [tensor.type, tensor.dims, { mlTensor: tensor.mlTensor }, "ml-tensor"]; default: throw new Error(`invalid data location: ${tensor.location} for ${getName()}`); } }; decodeTensorMetadata = (tensor) => { switch (tensor[3]) { case "cpu": return new Tensor2(tensor[0], tensor[2], tensor[1]); case "gpu-buffer": { const dataType = tensor[0]; if (!isGpuBufferSupportedType(dataType)) { throw new Error(`not supported data type: ${dataType} for deserializing GPU tensor`); } const { gpuBuffer, download, dispose } = tensor[2]; return Tensor2.fromGpuBuffer(gpuBuffer, { dataType, dims: tensor[1], download, dispose }); } case "ml-tensor": { const dataType = tensor[0]; if (!isMLTensorSupportedType(dataType)) { throw new Error(`not supported data type: ${dataType} for deserializing MLTensor tensor`); } const { mlTensor, download, dispose } = tensor[2]; return Tensor2.fromMLTensor(mlTensor, { dataType, dims: tensor[1], download, dispose }); } default: throw new Error(`invalid data location: ${tensor[3]}`); } }; OnnxruntimeWebAssemblySessionHandler = class { async fetchModelAndCopyToWasmMemory(path) { return copyFromExternalBuffer2(await loadFile(path)); } async loadModel(pathOrBuffer, options) { TRACE_FUNC_BEGIN(); let model; if (typeof pathOrBuffer === "string") { if (isNode) { model = await loadFile(pathOrBuffer); } else { model = await this.fetchModelAndCopyToWasmMemory(pathOrBuffer); } } else { model = pathOrBuffer; } [this.sessionId, this.inputNames, this.outputNames, this.inputMetadata, this.outputMetadata] = await createSession2( model, options ); TRACE_FUNC_END(); } async dispose() { return releaseSession2(this.sessionId); } async run(feeds, fetches, options) { TRACE_FUNC_BEGIN(); const inputArray = []; const inputIndices = []; Object.entries(feeds).forEach((kvp) => { const name = kvp[0]; const tensor = kvp[1]; const index = this.inputNames.indexOf(name); if (index === -1) { throw new Error(`invalid input '${name}'`); } inputArray.push(tensor); inputIndices.push(index); }); const outputArray = []; const outputIndices = []; Object.entries(fetches).forEach((kvp) => { const name = kvp[0]; const tensor = kvp[1]; const index = this.outputNames.indexOf(name); if (index === -1) { throw new Error(`invalid output '${name}'`); } outputArray.push(tensor); outputIndices.push(index); }); const inputs = inputArray.map( (t, i) => encodeTensorMetadata(t, () => `input "${this.inputNames[inputIndices[i]]}"`) ); const outputs = outputArray.map( (t, i) => t ? encodeTensorMetadata(t, () => `output "${this.outputNames[outputIndices[i]]}"`) : null ); const results = await run2(this.sessionId, inputIndices, inputs, outputIndices, outputs, options); const resultMap = {}; for (let i = 0; i < results.length; i++) { resultMap[this.outputNames[outputIndices[i]]] = outputArray[i] ?? decodeTensorMetadata(results[i]); } TRACE_FUNC_END(); return resultMap; } startProfiling() { } endProfiling() { void endProfiling2(this.sessionId); } }; } }); // web/lib/backend-wasm.ts var backend_wasm_exports = {}; __export(backend_wasm_exports, { OnnxruntimeWebAssemblyBackend: () => OnnxruntimeWebAssemblyBackend, initializeFlags: () => initializeFlags, wasmBackend: () => wasmBackend }); var initializeFlags, OnnxruntimeWebAssemblyBackend, wasmBackend; var init_backend_wasm = __esm({ "web/lib/backend-wasm.ts"() { "use strict"; init_esm(); init_proxy_wrapper(); init_session_handler_inference(); initializeFlags = () => { if (typeof env2.wasm.initTimeout !== "number" || env2.wasm.initTimeout < 0) { env2.wasm.initTimeout = 0; } const simd = env2.wasm.simd; if (typeof simd !== "boolean" && simd !== void 0 && simd !== "fixed" && simd !== "relaxed") { console.warn( `Property "env.wasm.simd" is set to unknown value "${simd}". Reset it to \`false\` and ignore SIMD feature checking.` ); env2.wasm.simd = false; } if (typeof env2.wasm.proxy !== "boolean") { env2.wasm.proxy = false; } if (typeof env2.wasm.trace !== "boolean") { env2.wasm.trace = false; } if (typeof env2.wasm.numThreads !== "number" || !Number.isInteger(env2.wasm.numThreads) || env2.wasm.numThreads <= 0) { if (typeof self !== "undefined" && !self.crossOriginIsolated) { env2.wasm.numThreads = 1; } else { const numCpuLogicalCores = typeof navigator === "undefined" ? __require("node:os").cpus().length : navigator.hardwareConcurrency; env2.wasm.numThreads = Math.min(4, Math.ceil((numCpuLogicalCores || 1) / 2)); } } }; OnnxruntimeWebAssemblyBackend = class { /** * This function initializes the WebAssembly backend. * * This function will be called only once for each backend name. It will be called the first time when * `ort.InferenceSession.create()` is called with a registered backend name. * * @param backendName - the registered backend name. */ async init(backendName) { initializeFlags(); await initializeWebAssemblyAndOrtRuntime(); await initializeOrtEp(backendName); } async createInferenceSessionHandler(pathOrBuffer, options) { const handler = new OnnxruntimeWebAssemblySessionHandler(); await handler.loadModel(pathOrBuffer, options); return handler; } }; wasmBackend = new OnnxruntimeWebAssemblyBackend(); } }); // web/lib/index.ts var index_exports = {}; __export(index_exports, { InferenceSession: () => InferenceSession2, TRACE: () => TRACE, TRACE_EVENT_BEGIN: () => TRACE_EVENT_BEGIN, TRACE_EVENT_END: () => TRACE_EVENT_END, TRACE_FUNC_BEGIN: () => TRACE_FUNC_BEGIN, TRACE_FUNC_END: () => TRACE_FUNC_END, Tensor: () => Tensor2, default: () => index_default, env: () => env2, registerBackend: () => registerBackend }); init_esm(); init_esm(); init_esm(); // web/lib/version.ts var version2 = "1.26.0"; // web/lib/index.ts var index_default = esm_exports; if (false) { const onnxjsBackend = null.onnxjsBackend; registerBackend("webgl", onnxjsBackend, -10); } if (false) { throw new Error( "The current build is specified to enable both JSEP and WebGPU EP. This is not a valid configuration. JSEP and WebGPU EPs cannot be enabled at the same time." ); } if (false) { throw new Error( "The current build is specified to enable WebNN EP without JSEP or WebGPU EP. This is not a valid configuration. WebNN EP requires either JSEP or WebGPU EP to be enabled." ); } if (true) { const wasmBackend2 = (init_backend_wasm(), __toCommonJS(backend_wasm_exports)).wasmBackend; if (true) { registerBackend("webgpu", wasmBackend2, 5); } if (true) { registerBackend("webnn", wasmBackend2, 5); } registerBackend("cpu", wasmBackend2, 10); registerBackend("wasm", wasmBackend2, 10); } Object.defineProperty(env2.versions, "web", { value: version2, enumerable: true }); return __toCommonJS(index_exports); })(); /** * @license * Copyright 2021 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================= */ /** * @license * Copyright 2020 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================= */ /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================= */ typeof exports=="object"&&typeof module=="object"&&(module.exports=ort); //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vY29tbW9uL2xpYi9iYWNrZW5kLWltcGwudHMiLCAiLi4vLi4vY29tbW9uL2xpYi9iYWNrZW5kLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvdmVyc2lvbi50cyIsICIuLi8uLi9jb21tb24vbGliL2Vudi1pbXBsLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvZW52LnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvdGVuc29yLWNvbnZlcnNpb24taW1wbC50cyIsICIuLi8uLi9jb21tb24vbGliL3RlbnNvci1mYWN0b3J5LWltcGwudHMiLCAiLi4vLi4vY29tbW9uL2xpYi90ZW5zb3ItaW1wbC10eXBlLW1hcHBpbmcudHMiLCAiLi4vLi4vY29tbW9uL2xpYi90ZW5zb3ItdXRpbHMtaW1wbC50cyIsICIuLi8uLi9jb21tb24vbGliL3RlbnNvci1pbXBsLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvdGVuc29yLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvdHJhY2UudHMiLCAiLi4vLi4vY29tbW9uL2xpYi9pbmZlcmVuY2Utc2Vzc2lvbi1pbXBsLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvaW5mZXJlbmNlLXNlc3Npb24udHMiLCAiLi4vLi4vY29tbW9uL2xpYi90ZW5zb3ItY29udmVyc2lvbi50cyIsICIuLi8uLi9jb21tb24vbGliL3RlbnNvci1mYWN0b3J5LnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvb25ueC1tb2RlbC50cyIsICIuLi8uLi9jb21tb24vbGliL29ubngtdmFsdWUudHMiLCAiLi4vLi4vY29tbW9uL2xpYi9pbmRleC50cyIsICIuLi9saWIvd2FzbS93YXNtLXV0aWxzLWVudi50cyIsICIuLi9saWIvd2FzbS9wcm94eS13b3JrZXIvbWFpbi50cyIsICIuLi9saWIvd2FzbS93YXNtLXV0aWxzLWltcG9ydC50cyIsICIuLi9saWIvd2FzbS93YXNtLWZhY3RvcnkudHMiLCAiLi4vbGliL3dhc20vd2FzbS11dGlscy50cyIsICIuLi9saWIvd2FzbS9ydW4tb3B0aW9ucy50cyIsICIuLi9saWIvd2FzbS9zZXNzaW9uLW9wdGlvbnMudHMiLCAiLi4vbGliL3dhc20vd2FzbS1jb21tb24udHMiLCAiLi4vbGliL3dhc20vd2FzbS11dGlscy1sb2FkLWZpbGUudHMiLCAiLi4vbGliL3dhc20vanNlcC9sb2cudHMiLCAiLi4vbGliL3dhc20vanNlcC91dGlsLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvdGVuc29yLXZpZXcudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJubi90ZW5zb3ItbWFuYWdlci50cyIsICIuLi9saWIvd2FzbS9qc2VwL2JhY2tlbmQtd2Vibm4udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvdHlwZXMudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvZ3B1LWRhdGEtbWFuYWdlci50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXkudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2NvbW1vbi50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvdHJhbnNwb3NlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9yZWR1Y2Utc2hhcmVkLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9yZWR1Y2UudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2FyZ21pbm1heC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvYXR0ZW50aW9uLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9iYXRjaC1ub3JtLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9iaWFzLWFkZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvdW5hcnktb3AudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2JpYXMtc3BsaXQtZ2VsdS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvYmluYXJ5LW9wLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jb25jYXQudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2Z1c2UtdXRpbHMudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzLzNyZC1wYXJ0eS9hY3RpdmF0aW9uX3V0aWwudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzLzNyZC1wYXJ0eS9jb252X3V0aWwudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL21hdG11bC1zaGFkZXJzLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvbWF0bXVsX3BhY2tlZF93ZWJncHUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzLzNyZC1wYXJ0eS9jb252MmRfbW1fd2ViZ3B1LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvY29udjNkX25haXZlX3dlYmdwdS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvY29udi1ncm91cGVkLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jb252LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvY29udl9iYWNrcHJvcF93ZWJncHUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2NvbnYtdHJhbnNwb3NlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jdW1zdW0udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2RlcHRoLXRvLXNwYWNlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9laW5zdW0udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2V4cGFuZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZmFzdC1nZWx1LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9nYXRoZXIudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2dhdGhlci1uZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZ2F0aGVyLWJsb2NrLXF1YW50aXplZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZ2F0aGVyLWVsZW1lbnRzLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9nZW1tLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9ncmlkLXNhbXBsZS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvbXVsdGloZWFkLWF0dGVudGlvbi50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvc3BsaXQudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3JvdGFyeS1lbWJlZGRpbmcudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2dyb3VwLXF1ZXJ5LWF0dGVudGlvbi50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvaW5zdGFuY2Utbm9ybS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvbGF5ZXItbm9ybS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvbWF0bXVsLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9tYXRtdWxuYml0cy50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvcGFkLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9wb29sLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9xdWFudGl6ZS1saW5lYXIudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3JhbmdlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9zY2F0dGVyLW5kLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9yZXNpemUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3NraXAtbGF5ZXItbm9ybS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvc2xpY2UudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3NvZnRtYXgudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3RpbGUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3doZXJlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wLXJlc29sdmUtcnVsZXMudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvcHJvZ3JhbS1tYW5hZ2VyLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvYmFja2VuZC13ZWJncHUudHMiLCAiLi4vbGliL3dhc20vanNlcC9pbml0LnRzIiwgIi4uL2xpYi93YXNtL3dhc20tY29yZS1pbXBsLnRzIiwgIi4uL2xpYi93YXNtL3Byb3h5LXdyYXBwZXIudHMiLCAiLi4vbGliL3dhc20vc2Vzc2lvbi1oYW5kbGVyLWluZmVyZW5jZS50cyIsICIuLi9saWIvYmFja2VuZC13YXNtLnRzIiwgIi4uL2xpYi9pbmRleC50cyIsICIuLi9saWIvdmVyc2lvbi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IEJhY2tlbmQgfSBmcm9tICcuL2JhY2tlbmQuanMnO1xuaW1wb3J0IHsgSW5mZXJlbmNlU2Vzc2lvbiB9IGZyb20gJy4vaW5mZXJlbmNlLXNlc3Npb24uanMnO1xuXG5pbnRlcmZhY2UgQmFja2VuZEluZm8ge1xuICBiYWNrZW5kOiBCYWNrZW5kO1xuICBwcmlvcml0eTogbnVtYmVyO1xuXG4gIGluaXRQcm9taXNlPzogUHJvbWlzZTx2b2lkPjtcbiAgaW5pdGlhbGl6ZWQ/OiBib29sZWFuO1xuICBhYm9ydGVkPzogYm9vbGVhbjtcbiAgZXJyb3I/OiBzdHJpbmc7XG59XG5cbmNvbnN0IGJhY2tlbmRzOiBNYXA8c3RyaW5nLCBCYWNrZW5kSW5mbz4gPSBuZXcgTWFwKCk7XG5jb25zdCBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHk6IHN0cmluZ1tdID0gW107XG5cbi8qKlxuICogUmVnaXN0ZXIgYSBiYWNrZW5kLlxuICpcbiAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgYXMgYSBrZXkgdG8gbG9va3VwIGFzIGFuIGV4ZWN1dGlvbiBwcm92aWRlci5cbiAqIEBwYXJhbSBiYWNrZW5kIC0gdGhlIGJhY2tlbmQgb2JqZWN0LlxuICogQHBhcmFtIHByaW9yaXR5IC0gYW4gaW50ZWdlciBpbmRpY2F0aW5nIHRoZSBwcmlvcml0eSBvZiB0aGUgYmFja2VuZC4gSGlnaGVyIG51bWJlciBtZWFucyBoaWdoZXIgcHJpb3JpdHkuIGlmIHByaW9yaXR5XG4gKiA8IDAsIGl0IHdpbGwgYmUgY29uc2lkZXJlZCBhcyBhICdiZXRhJyB2ZXJzaW9uIGFuZCB3aWxsIG5vdCBiZSB1c2VkIGFzIGEgZmFsbGJhY2sgYmFja2VuZCBieSBkZWZhdWx0LlxuICpcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGNvbnN0IHJlZ2lzdGVyQmFja2VuZCA9IChuYW1lOiBzdHJpbmcsIGJhY2tlbmQ6IEJhY2tlbmQsIHByaW9yaXR5OiBudW1iZXIpOiB2b2lkID0+IHtcbiAgaWYgKGJhY2tlbmQgJiYgdHlwZW9mIGJhY2tlbmQuaW5pdCA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgYmFja2VuZC5jcmVhdGVJbmZlcmVuY2VTZXNzaW9uSGFuZGxlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGNvbnN0IGN1cnJlbnRCYWNrZW5kID0gYmFja2VuZHMuZ2V0KG5hbWUpO1xuICAgIGlmIChjdXJyZW50QmFja2VuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBiYWNrZW5kcy5zZXQobmFtZSwgeyBiYWNrZW5kLCBwcmlvcml0eSB9KTtcbiAgICB9IGVsc2UgaWYgKGN1cnJlbnRCYWNrZW5kLnByaW9yaXR5ID4gcHJpb3JpdHkpIHtcbiAgICAgIC8vIHNhbWUgbmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgd2l0aCBhIGhpZ2hlciBwcmlvcml0eS4gc2tpcCByZWdpc3RlcmF0aW9uLlxuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSBpZiAoY3VycmVudEJhY2tlbmQucHJpb3JpdHkgPT09IHByaW9yaXR5KSB7XG4gICAgICBpZiAoY3VycmVudEJhY2tlbmQuYmFja2VuZCAhPT0gYmFja2VuZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWdpc3RlciBiYWNrZW5kIFwiJHtuYW1lfVwiIHVzaW5nIHByaW9yaXR5ICR7cHJpb3JpdHl9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHByaW9yaXR5ID49IDApIHtcbiAgICAgIGNvbnN0IGkgPSBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHkuaW5kZXhPZihuYW1lKTtcbiAgICAgIGlmIChpICE9PSAtMSkge1xuICAgICAgICBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHkuc3BsaWNlKGksIDEpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoYmFja2VuZHMuZ2V0KGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eVtpXSkhLnByaW9yaXR5IDw9IHByaW9yaXR5KSB7XG4gICAgICAgICAgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5LnNwbGljZShpLCAwLCBuYW1lKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eS5wdXNoKG5hbWUpO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCdub3QgYSB2YWxpZCBiYWNrZW5kJyk7XG59O1xuXG4vKipcbiAqIFRyeSB0byByZXNvbHZlIGFuZCBpbml0aWFsaXplIGEgYmFja2VuZC5cbiAqXG4gKiBAcGFyYW0gYmFja2VuZE5hbWUgLSB0aGUgbmFtZSBvZiB0aGUgYmFja2VuZC5cbiAqIEByZXR1cm5zIHRoZSBiYWNrZW5kIGluc3RhbmNlIGlmIHJlc29sdmVkIGFuZCBpbml0aWFsaXplZCBzdWNjZXNzZnVsbHksIG9yIGFuIGVycm9yIG1lc3NhZ2UgaWYgZmFpbGVkLlxuICovXG5jb25zdCB0cnlSZXNvbHZlQW5kSW5pdGlhbGl6ZUJhY2tlbmQgPSBhc3luYyAoYmFja2VuZE5hbWU6IHN0cmluZyk6IFByb21pc2U8QmFja2VuZCB8IHN0cmluZz4gPT4ge1xuICBjb25zdCBiYWNrZW5kSW5mbyA9IGJhY2tlbmRzLmdldChiYWNrZW5kTmFtZSk7XG4gIGlmICghYmFja2VuZEluZm8pIHtcbiAgICByZXR1cm4gJ2JhY2tlbmQgbm90IGZvdW5kLic7XG4gIH1cblxuICBpZiAoYmFja2VuZEluZm8uaW5pdGlhbGl6ZWQpIHtcbiAgICByZXR1cm4gYmFja2VuZEluZm8uYmFja2VuZDtcbiAgfSBlbHNlIGlmIChiYWNrZW5kSW5mby5hYm9ydGVkKSB7XG4gICAgcmV0dXJuIGJhY2tlbmRJbmZvLmVycm9yITtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBpc0luaXRpYWxpemluZyA9ICEhYmFja2VuZEluZm8uaW5pdFByb21pc2U7XG4gICAgdHJ5IHtcbiAgICAgIGlmICghaXNJbml0aWFsaXppbmcpIHtcbiAgICAgICAgYmFja2VuZEluZm8uaW5pdFByb21pc2UgPSBiYWNrZW5kSW5mby5iYWNrZW5kLmluaXQoYmFja2VuZE5hbWUpO1xuICAgICAgfVxuICAgICAgYXdhaXQgYmFja2VuZEluZm8uaW5pdFByb21pc2U7XG4gICAgICBiYWNrZW5kSW5mby5pbml0aWFsaXplZCA9IHRydWU7XG4gICAgICByZXR1cm4gYmFja2VuZEluZm8uYmFja2VuZDtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIWlzSW5pdGlhbGl6aW5nKSB7XG4gICAgICAgIGJhY2tlbmRJbmZvLmVycm9yID0gYCR7ZX1gO1xuICAgICAgICBiYWNrZW5kSW5mby5hYm9ydGVkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYWNrZW5kSW5mby5lcnJvciE7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGRlbGV0ZSBiYWNrZW5kSW5mby5pbml0UHJvbWlzZTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogUmVzb2x2ZSBleGVjdXRpb24gcHJvdmlkZXJzIGZyb20gdGhlIHNwZWNpZmljIHNlc3Npb24gb3B0aW9ucy5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIHRoZSBzZXNzaW9uIG9wdGlvbnMgb2JqZWN0LlxuICogQHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSB0dXBsZSBvZiBhbiBpbml0aWFsaXplZCBiYWNrZW5kIGluc3RhbmNlIGFuZCBhIHNlc3Npb24gb3B0aW9ucyBvYmplY3Qgd2l0aFxuICogZmlsdGVyZWQgRVAgbGlzdC5cbiAqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCByZXNvbHZlQmFja2VuZEFuZEV4ZWN1dGlvblByb3ZpZGVycyA9IGFzeW5jIChcbiAgb3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyxcbik6IFByb21pc2U8W2JhY2tlbmQ6IEJhY2tlbmQsIG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnNdPiA9PiB7XG4gIC8vIGV4dHJhY3QgYmFja2VuZCBoaW50cyBmcm9tIHNlc3Npb24gb3B0aW9uc1xuICBjb25zdCBlcHMgPSBvcHRpb25zLmV4ZWN1dGlvblByb3ZpZGVycyB8fCBbXTtcbiAgY29uc3QgYmFja2VuZEhpbnRzID0gZXBzLm1hcCgoaSkgPT4gKHR5cGVvZiBpID09PSAnc3RyaW5nJyA/IGkgOiBpLm5hbWUpKTtcbiAgY29uc3QgYmFja2VuZE5hbWVzID0gYmFja2VuZEhpbnRzLmxlbmd0aCA9PT0gMCA/IGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eSA6IGJhY2tlbmRIaW50cztcblxuICAvLyB0cnkgdG8gcmVzb2x2ZSBhbmQgaW5pdGlhbGl6ZSBhbGwgcmVxdWVzdGVkIGJhY2tlbmRzXG4gIGxldCBiYWNrZW5kOiBCYWNrZW5kIHwgdW5kZWZpbmVkO1xuICBjb25zdCBlcnJvcnMgPSBbXTtcbiAgY29uc3QgYXZhaWxhYmxlQmFja2VuZE5hbWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGZvciAoY29uc3QgYmFja2VuZE5hbWUgb2YgYmFja2VuZE5hbWVzKSB7XG4gICAgY29uc3QgcmVzb2x2ZVJlc3VsdCA9IGF3YWl0IHRyeVJlc29sdmVBbmRJbml0aWFsaXplQmFja2VuZChiYWNrZW5kTmFtZSk7XG4gICAgaWYgKHR5cGVvZiByZXNvbHZlUmVzdWx0ID09PSAnc3RyaW5nJykge1xuICAgICAgZXJyb3JzLnB1c2goeyBuYW1lOiBiYWNrZW5kTmFtZSwgZXJyOiByZXNvbHZlUmVzdWx0IH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIWJhY2tlbmQpIHtcbiAgICAgICAgYmFja2VuZCA9IHJlc29sdmVSZXN1bHQ7XG4gICAgICB9XG4gICAgICBpZiAoYmFja2VuZCA9PT0gcmVzb2x2ZVJlc3VsdCkge1xuICAgICAgICBhdmFpbGFibGVCYWNrZW5kTmFtZXMuYWRkKGJhY2tlbmROYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBpZiBubyBiYWNrZW5kIGlzIGF2YWlsYWJsZSwgdGhyb3cgZXJyb3IuXG4gIGlmICghYmFja2VuZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgbm8gYXZhaWxhYmxlIGJhY2tlbmQgZm91bmQuIEVSUjogJHtlcnJvcnMubWFwKChlKSA9PiBgWyR7ZS5uYW1lfV0gJHtlLmVycn1gKS5qb2luKCcsICcpfWApO1xuICB9XG5cbiAgLy8gZm9yIGVhY2ggZXhwbGljaXRseSByZXF1ZXN0ZWQgYmFja2VuZCwgaWYgaXQncyBub3QgYXZhaWxhYmxlLCBvdXRwdXQgd2FybmluZyBtZXNzYWdlLlxuICBmb3IgKGNvbnN0IHsgbmFtZSwgZXJyIH0gb2YgZXJyb3JzKSB7XG4gICAgaWYgKGJhY2tlbmRIaW50cy5pbmNsdWRlcyhuYW1lKSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYHJlbW92aW5nIHJlcXVlc3RlZCBleGVjdXRpb24gcHJvdmlkZXIgXCIke25hbWV9XCIgZnJvbSBzZXNzaW9uIG9wdGlvbnMgYmVjYXVzZSBpdCBpcyBub3QgYXZhaWxhYmxlOiAke2Vycn1gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBmaWx0ZXJlZEVwcyA9IGVwcy5maWx0ZXIoKGkpID0+IGF2YWlsYWJsZUJhY2tlbmROYW1lcy5oYXModHlwZW9mIGkgPT09ICdzdHJpbmcnID8gaSA6IGkubmFtZSkpO1xuXG4gIHJldHVybiBbXG4gICAgYmFja2VuZCxcbiAgICBuZXcgUHJveHkob3B0aW9ucywge1xuICAgICAgZ2V0OiAodGFyZ2V0LCBwcm9wKSA9PiB7XG4gICAgICAgIGlmIChwcm9wID09PSAnZXhlY3V0aW9uUHJvdmlkZXJzJykge1xuICAgICAgICAgIHJldHVybiBmaWx0ZXJlZEVwcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXQodGFyZ2V0LCBwcm9wKTtcbiAgICAgIH0sXG4gICAgfSksXG4gIF07XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBJbmZlcmVuY2VTZXNzaW9uIH0gZnJvbSAnLi9pbmZlcmVuY2Utc2Vzc2lvbi5qcyc7XG5pbXBvcnQgeyBPbm54VmFsdWUgfSBmcm9tICcuL29ubngtdmFsdWUuanMnO1xuXG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIFNlc3Npb25IYW5kbGVyIHtcbiAgdHlwZSBGZWVkc1R5cGUgPSB7IFtuYW1lOiBzdHJpbmddOiBPbm54VmFsdWUgfTtcbiAgdHlwZSBGZXRjaGVzVHlwZSA9IHsgW25hbWU6IHN0cmluZ106IE9ubnhWYWx1ZSB8IG51bGwgfTtcbiAgdHlwZSBSZXR1cm5UeXBlID0geyBbbmFtZTogc3RyaW5nXTogT25ueFZhbHVlIH07XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBzaGFyZWQgU2Vzc2lvbkhhbmRsZXIgZnVuY3Rpb25hbGl0eVxuICpcbiAqIEBpZ25vcmVcbiAqL1xuaW50ZXJmYWNlIFNlc3Npb25IYW5kbGVyIHtcbiAgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+O1xuXG4gIHJlYWRvbmx5IGlucHV0TmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICByZWFkb25seSBvdXRwdXROYW1lczogcmVhZG9ubHkgc3RyaW5nW107XG5cbiAgcmVhZG9ubHkgaW5wdXRNZXRhZGF0YTogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbi5WYWx1ZU1ldGFkYXRhW107XG4gIHJlYWRvbmx5IG91dHB1dE1ldGFkYXRhOiByZWFkb25seSBJbmZlcmVuY2VTZXNzaW9uLlZhbHVlTWV0YWRhdGFbXTtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnQgYSBoYW5kbGVyIGluc3RhbmNlIG9mIGFuIGluZmVyZW5jZSBzZXNzaW9uLlxuICpcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbmZlcmVuY2VTZXNzaW9uSGFuZGxlciBleHRlbmRzIFNlc3Npb25IYW5kbGVyIHtcbiAgc3RhcnRQcm9maWxpbmcoKTogdm9pZDtcbiAgZW5kUHJvZmlsaW5nKCk6IHZvaWQ7XG5cbiAgcnVuKFxuICAgIGZlZWRzOiBTZXNzaW9uSGFuZGxlci5GZWVkc1R5cGUsXG4gICAgZmV0Y2hlczogU2Vzc2lvbkhhbmRsZXIuRmV0Y2hlc1R5cGUsXG4gICAgb3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zLFxuICApOiBQcm9taXNlPFNlc3Npb25IYW5kbGVyLlJldHVyblR5cGU+O1xufVxuXG4vKipcbiAqIFJlcHJlc2VudCBhIGJhY2tlbmQgdGhhdCBwcm92aWRlcyBpbXBsZW1lbnRhdGlvbiBvZiBtb2RlbCBpbmZlcmVuY2luZy5cbiAqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmFja2VuZCB7XG4gIC8qKlxuICAgKiBJbml0aWFsaXplIHRoZSBiYWNrZW5kIGFzeW5jaHJvbm91c2x5LiBTaG91bGQgdGhyb3cgd2hlbiBmYWlsZWQuXG4gICAqL1xuICBpbml0KGJhY2tlbmROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+O1xuXG4gIGNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKFxuICAgIHVyaU9yQnVmZmVyOiBzdHJpbmcgfCBVaW50OEFycmF5LFxuICAgIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zLFxuICApOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25IYW5kbGVyPjtcbn1cblxuZXhwb3J0IHsgcmVnaXN0ZXJCYWNrZW5kIH0gZnJvbSAnLi9iYWNrZW5kLWltcGwuanMnO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vLyBUaGlzIGZpbGUgaXMgZ2VuZXJhdGVkIGJ5IC9qcy9zY3JpcHRzL3VwZGF0ZS12ZXJzaW9uLnRzXG4vLyBEbyBub3QgbW9kaWZ5IGZpbGUgY29udGVudCBtYW51YWxseS5cblxuZXhwb3J0IGNvbnN0IHZlcnNpb24gPSAnMS4yNi4wJztcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRW52IH0gZnJvbSAnLi9lbnYuanMnO1xuaW1wb3J0IHsgdmVyc2lvbiB9IGZyb20gJy4vdmVyc2lvbi5qcyc7XG5cbnR5cGUgTG9nTGV2ZWxUeXBlID0gRW52Wydsb2dMZXZlbCddO1xuXG5sZXQgbG9nTGV2ZWxWYWx1ZTogUmVxdWlyZWQ8TG9nTGV2ZWxUeXBlPiA9ICd3YXJuaW5nJztcblxuZXhwb3J0IGNvbnN0IGVudjogRW52ID0ge1xuICB3YXNtOiB7fSBhcyBFbnYuV2ViQXNzZW1ibHlGbGFncyxcbiAgd2ViZ2w6IHt9IGFzIEVudi5XZWJHTEZsYWdzLFxuICB3ZWJncHU6IHt9IGFzIEVudi5XZWJHcHVGbGFncyxcbiAgdmVyc2lvbnM6IHsgY29tbW9uOiB2ZXJzaW9uIH0sXG5cbiAgc2V0IGxvZ0xldmVsKHZhbHVlOiBMb2dMZXZlbFR5cGUpIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyB8fCBbJ3ZlcmJvc2UnLCAnaW5mbycsICd3YXJuaW5nJywgJ2Vycm9yJywgJ2ZhdGFsJ10uaW5kZXhPZih2YWx1ZSkgPT09IC0xKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGxvZ2dpbmcgbGV2ZWw6ICR7dmFsdWV9YCk7XG4gICAgfVxuICAgIGxvZ0xldmVsVmFsdWUgPSB2YWx1ZTtcbiAgfSxcbiAgZ2V0IGxvZ0xldmVsKCk6IFJlcXVpcmVkPExvZ0xldmVsVHlwZT4ge1xuICAgIHJldHVybiBsb2dMZXZlbFZhbHVlO1xuICB9LFxufTtcblxuLy8gc2V0IHByb3BlcnR5ICdsb2dMZXZlbCcgc28gdGhhdCB0aGV5IGNhbiBiZSBjb3JyZWN0bHkgdHJhbnNmZXJyZWQgdG8gd29ya2VyIGJ5IGBwb3N0TWVzc2FnZSgpYC5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShlbnYsICdsb2dMZXZlbCcsIHsgZW51bWVyYWJsZTogdHJ1ZSB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgZW52IGFzIGVudkltcGwgfSBmcm9tICcuL2Vudi1pbXBsLmpzJztcbmltcG9ydCB7IFRyeUdldEdsb2JhbFR5cGUgfSBmcm9tICcuL3R5cGUtaGVscGVyLmpzJztcblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIEVudiB7XG4gIGV4cG9ydCB0eXBlIFdhc21QYXRoUHJlZml4ID0gc3RyaW5nO1xuICBleHBvcnQgaW50ZXJmYWNlIFdhc21GaWxlUGF0aHMge1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgdGhlIG92ZXJyaWRlIHBhdGggZm9yIHRoZSBtYWluIC53YXNtIGZpbGUuXG4gICAgICpcbiAgICAgKiBUaGlzIHBhdGggc2hvdWxkIGJlIGFuIGFic29sdXRlIHBhdGguXG4gICAgICpcbiAgICAgKiBJZiBub3QgbW9kaWZpZWQsIHRoZSBmaWxlbmFtZSBvZiB0aGUgLndhc20gZmlsZSBpczpcbiAgICAgKiAtIGBvcnQtd2FzbS1zaW1kLXRocmVhZGVkLndhc21gIGZvciBkZWZhdWx0IGJ1aWxkXG4gICAgICogLSBgb3J0LXdhc20tc2ltZC10aHJlYWRlZC5qc2VwLndhc21gIGZvciBKU0VQIGJ1aWxkICh3aXRoIFdlYkdQVSBhbmQgV2ViTk4pXG4gICAgICogLSBgb3J0LXdhc20tc2ltZC10aHJlYWRlZC5hc3luY2lmeS53YXNtYCBmb3IgV2ViR1BVIGJ1aWxkIHdpdGggQXN5bmNpZnkgKHdpdGggV2ViTk4pXG4gICAgICogLSBgb3J0LXdhc20tc2ltZC10aHJlYWRlZC5qc3BpLndhc21gIGZvciBXZWJHUFUgYnVpbGQgd2l0aCBKU1BJIHN1cHBvcnQgKHdpdGggV2ViTk4pXG4gICAgICovXG4gICAgd2FzbT86IFVSTCB8IHN0cmluZztcbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IHRoZSBvdmVycmlkZSBwYXRoIGZvciB0aGUgbWFpbiAubWpzIGZpbGUuXG4gICAgICpcbiAgICAgKiBUaGlzIHBhdGggc2hvdWxkIGJlIGFuIGFic29sdXRlIHBhdGguXG4gICAgICpcbiAgICAgKiBJZiBub3QgbW9kaWZpZWQsIHRoZSBmaWxlbmFtZSBvZiB0aGUgLm1qcyBmaWxlIGlzOlxuICAgICAqIC0gYG9ydC13YXNtLXNpbWQtdGhyZWFkZWQubWpzYCBmb3IgZGVmYXVsdCBidWlsZFxuICAgICAqIC0gYG9ydC13YXNtLXNpbWQtdGhyZWFkZWQuanNlcC5tanNgIGZvciBKU0VQIGJ1aWxkICh3aXRoIFdlYkdQVSBhbmQgV2ViTk4pXG4gICAgICogLSBgb3J0LXdhc20tc2ltZC10aHJlYWRlZC5hc3luY2lmeS5tanNgIGZvciBXZWJHUFUgYnVpbGQgd2l0aCBBc3luY2lmeSAod2l0aCBXZWJOTilcbiAgICAgKiAtIGBvcnQtd2FzbS1zaW1kLXRocmVhZGVkLmpzcGkubWpzYCBmb3IgV2ViR1BVIGJ1aWxkIHdpdGggSlNQSSBzdXBwb3J0ICh3aXRoIFdlYk5OKVxuICAgICAqL1xuICAgIG1qcz86IFVSTCB8IHN0cmluZztcbiAgfVxuICBleHBvcnQgdHlwZSBXYXNtUHJlZml4T3JGaWxlUGF0aHMgPSBXYXNtUGF0aFByZWZpeCB8IFdhc21GaWxlUGF0aHM7XG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViQXNzZW1ibHlGbGFncyB7XG4gICAgLyoqXG4gICAgICogc2V0IG9yIGdldCBudW1iZXIgb2YgdGhyZWFkKHMpLiBJZiBvbWl0dGVkIG9yIHNldCB0byAwLCBudW1iZXIgb2YgdGhyZWFkKHMpIHdpbGwgYmUgZGV0ZXJtaW5lZCBieSBzeXN0ZW0uIElmIHNldFxuICAgICAqIHRvIDEsIG5vIHdvcmtlciB0aHJlYWQgd2lsbCBiZSBzcGF3bmVkLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IHdoZW4gV2ViQXNzZW1ibHkgbXVsdGl0aHJlYWQgZmVhdHVyZSBpcyBhdmFpbGFibGUgaW4gY3VycmVudCBjb250ZXh0LlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgMGBcbiAgICAgKi9cbiAgICBudW1UaHJlYWRzPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogc2V0IGEgdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRvIGVuYWJsZSBTSU1ELlxuICAgICAqXG4gICAgICogT05OWCBSdW50aW1lIHdpbGwgcGVyZm9ybSBmZWF0dXJlIGRldGVjdGlvbiBiYXNlZCBvbiB0aGUgdmFsdWUgb2YgdGhpcyBwcm9wZXJ0eS4gU3BlY2lmaWNhbGx5LCB3aGVuIHRoZSB2YWx1ZSBpc1xuICAgICAqIHNldCB0bzpcbiAgICAgKiAtIGB1bmRlZmluZWRgLCBgdHJ1ZWAgb3IgYFwiZml4ZWRcImA6IHdpbGwgY2hlY2sgYXZhaWxhYmlsaXR5IG9mIEZpeGVkLXdpZHRoIFNJTUQuXG4gICAgICogLSBgXCJyZWxheGVkXCJgOiB3aWxsIGNoZWNrIGF2YWlsYWJpbGl0eSBvZiBSZWxheGVkIFNJTUQuXG4gICAgICogLSBgZmFsc2VgOiB3aWxsIG5vdCBwZXJmb3JtIFNJTUQgZmVhdHVyZSBjaGVja2luZy5cbiAgICAgKlxuICAgICAqIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBkb2VzIG5vdCBtYWtlIE9OTlggUnVudGltZSB0byBzd2l0Y2ggdG8gdGhlIGNvcnJlc3BvbmRpbmcgcnVudGltZSBhdXRvbWF0aWNhbGx5LiBVc2VyIG5lZWRcbiAgICAgKiB0byBzZXQgYHdhc21QYXRoc2Agb3IgYHdhc21CaW5hcnlgIHByb3BlcnR5IHRvIGxvYWQgdGhlIGNvcnJlc3BvbmRpbmcgcnVudGltZS5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSB3aGVuIFdlYkFzc2VtYmx5IFNJTUQgZmVhdHVyZSBpcyBhdmFpbGFibGUgaW4gY3VycmVudCBjb250ZXh0LlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgdHJ1ZWBcbiAgICAgKi9cbiAgICBzaW1kPzogYm9vbGVhbiB8ICdmaXhlZCcgfCAncmVsYXhlZCc7XG5cbiAgICAvKipcbiAgICAgKiBzZXQgb3IgZ2V0IGEgYm9vbGVhbiB2YWx1ZSBpbmRpY2F0aW5nIHdoZXRoZXIgdG8gZW5hYmxlIHRyYWNlLlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgZmFsc2VgXG4gICAgICpcbiAgICAgKiBAZGVwcmVjYXRlZCBVc2UgYGVudi50cmFjZWAgaW5zdGVhZC4gSWYgYGVudi50cmFjZWAgaXMgc2V0LCB0aGlzIHByb3BlcnR5IHdpbGwgYmUgaWdub3JlZC5cbiAgICAgKi9cbiAgICB0cmFjZT86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IGEgbnVtYmVyIHNwZWNpZnlpbmcgdGhlIHRpbWVvdXQgZm9yIGluaXRpYWxpemF0aW9uIG9mIFdlYkFzc2VtYmx5IGJhY2tlbmQsIGluIG1pbGxpc2Vjb25kcy4gQSB6ZXJvXG4gICAgICogdmFsdWUgaW5kaWNhdGVzIG5vIHRpbWVvdXQgaXMgc2V0LlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgMGBcbiAgICAgKi9cbiAgICBpbml0VGltZW91dD86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFNldCBhIGN1c3RvbSBVUkwgcHJlZml4IHRvIHRoZSAud2FzbS8ubWpzIGZpbGVzLCBvciBhbiBvYmplY3Qgb2Ygb3ZlcnJpZGVzIGZvciBib3RoIC53YXNtLy5tanMgZmlsZS4gVGhlIG92ZXJyaWRlXG4gICAgICogcGF0aCBzaG91bGQgYmUgYW4gYWJzb2x1dGUgcGF0aC5cbiAgICAgKi9cbiAgICB3YXNtUGF0aHM/OiBXYXNtUHJlZml4T3JGaWxlUGF0aHM7XG5cbiAgICAvKipcbiAgICAgKiBTZXQgYSBjdXN0b20gYnVmZmVyIHdoaWNoIGNvbnRhaW5zIHRoZSBXZWJBc3NlbWJseSBiaW5hcnkuIElmIHRoaXMgcHJvcGVydHkgaXMgc2V0LCB0aGUgYHdhc21QYXRoc2AgcHJvcGVydHkgd2lsbFxuICAgICAqIGJlIGlnbm9yZWQuXG4gICAgICovXG4gICAgd2FzbUJpbmFyeT86IEFycmF5QnVmZmVyTGlrZSB8IFVpbnQ4QXJyYXk7XG5cbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IGEgYm9vbGVhbiB2YWx1ZSBpbmRpY2F0aW5nIHdoZXRoZXIgdG8gcHJveHkgdGhlIGV4ZWN1dGlvbiBvZiBtYWluIHRocmVhZCB0byBhIHdvcmtlciB0aHJlYWQuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGBmYWxzZWBcbiAgICAgKi9cbiAgICBwcm94eT86IGJvb2xlYW47XG4gIH1cblxuICBleHBvcnQgaW50ZXJmYWNlIFdlYkdMRmxhZ3Mge1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIFdlYkdMIENvbnRleHQgSUQgKHdlYmdsIG9yIHdlYmdsMikuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGAnd2ViZ2wyJ2BcbiAgICAgKi9cbiAgICBjb250ZXh0SWQ/OiAnd2ViZ2wnIHwgJ3dlYmdsMic7XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBXZWJHTCByZW5kZXJpbmcgY29udGV4dC5cbiAgICAgKi9cbiAgICByZWFkb25seSBjb250ZXh0OiBXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgbWF4aW11bSBiYXRjaCBzaXplIGZvciBtYXRtdWwuIDAgbWVhbnMgdG8gZGlzYWJsZSBiYXRjaGluZy5cbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkXG4gICAgICovXG4gICAgbWF0bXVsTWF4QmF0Y2hTaXplPzogbnVtYmVyO1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIHRleHR1cmUgY2FjaGUgbW9kZS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYCdmdWxsJ2BcbiAgICAgKi9cbiAgICB0ZXh0dXJlQ2FjaGVNb2RlPzogJ2luaXRpYWxpemVyT25seScgfCAnZnVsbCc7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgcGFja2VkIHRleHR1cmUgbW9kZVxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgZmFsc2VgXG4gICAgICovXG4gICAgcGFjaz86IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB3aGV0aGVyIGVuYWJsZSBhc3luYyBkb3dubG9hZC5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYGZhbHNlYFxuICAgICAqL1xuICAgIGFzeW5jPzogYm9vbGVhbjtcbiAgfVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViR3B1UHJvZmlsaW5nRGF0YVYxVGVuc29yTWV0YWRhdGEge1xuICAgIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICAgIGRhdGFUeXBlOiBzdHJpbmc7XG4gIH1cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJHcHVQcm9maWxpbmdEYXRhVjEge1xuICAgIHZlcnNpb246IDE7XG4gICAgaW5wdXRzTWV0YWRhdGE6IHJlYWRvbmx5IFdlYkdwdVByb2ZpbGluZ0RhdGFWMVRlbnNvck1ldGFkYXRhW107XG4gICAgb3V0cHV0c01ldGFkYXRhOiByZWFkb25seSBXZWJHcHVQcm9maWxpbmdEYXRhVjFUZW5zb3JNZXRhZGF0YVtdO1xuICAgIGtlcm5lbElkOiBudW1iZXI7XG4gICAga2VybmVsVHlwZTogc3RyaW5nO1xuICAgIGtlcm5lbE5hbWU6IHN0cmluZztcbiAgICBwcm9ncmFtTmFtZTogc3RyaW5nO1xuICAgIHN0YXJ0VGltZTogbnVtYmVyO1xuICAgIGVuZFRpbWU6IG51bWJlcjtcbiAgfVxuXG4gIGV4cG9ydCB0eXBlIFdlYkdwdVByb2ZpbGluZ0RhdGEgPSBXZWJHcHVQcm9maWxpbmdEYXRhVjE7XG5cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJHcHVGbGFncyB7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgcHJvZmlsaW5nIG1vZGUuXG4gICAgICpcbiAgICAgKiBAZGVwcmVjYXRlZCBVc2UgYGVudi53ZWJncHUucHJvZmlsaW5nLm1vZGVgIGluc3RlYWQuIElmIGBlbnYud2ViZ3B1LnByb2ZpbGluZy5tb2RlYCBpcyBzZXQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZVxuICAgICAqIGlnbm9yZWQuXG4gICAgICovXG4gICAgcHJvZmlsaW5nTW9kZT86ICdvZmYnIHwgJ2RlZmF1bHQnO1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIHByb2ZpbGluZyBjb25maWd1cmF0aW9uLlxuICAgICAqL1xuICAgIHByb2ZpbGluZzoge1xuICAgICAgLyoqXG4gICAgICAgKiBTZXQgb3IgZ2V0IHRoZSBwcm9maWxpbmcgbW9kZS5cbiAgICAgICAqXG4gICAgICAgKiBAZGVmYXVsdFZhbHVlIGAnb2ZmJ2BcbiAgICAgICAqL1xuICAgICAgbW9kZT86ICdvZmYnIHwgJ2RlZmF1bHQnO1xuXG4gICAgICAvKipcbiAgICAgICAqIFNldCBvciBnZXQgYSBjYWxsYmFjayBmdW5jdGlvbiB3aGVuIGEgcHJvZmlsaW5nIGRhdGEgaXMgcmVjZWl2ZWQuIElmIG5vdCBzZXQsIHRoZSBwcm9maWxpbmcgZGF0YSB3aWxsIGJlXG4gICAgICAgKiBwcmludGVkIHRvIGNvbnNvbGUuXG4gICAgICAgKi9cbiAgICAgIG9uZGF0YT86IChkYXRhOiBXZWJHcHVQcm9maWxpbmdEYXRhKSA9PiB2b2lkO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgcG93ZXIgcHJlZmVyZW5jZS5cbiAgICAgKlxuICAgICAqIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBvbmx5IGhhcyBlZmZlY3QgYmVmb3JlIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhlIHZhbHVlIHdpbGwgYmVcbiAgICAgKiB1c2VkIGFzIG9wdGlvbnMgZm9yIGBuYXZpZ2F0b3IuZ3B1LnJlcXVlc3RBZGFwdGVyKClgLlxuICAgICAqXG4gICAgICogU2VlIHtAbGluayBodHRwczovL2dwdXdlYi5naXRodWIuaW8vZ3B1d2ViLyNkaWN0ZGVmLWdwdXJlcXVlc3RhZGFwdGVyb3B0aW9uc30gZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYHVuZGVmaW5lZGBcbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkIENyZWF0ZSB5b3VyIG93biBHUFVBZGFwdGVyLCB1c2UgaXQgdG8gY3JlYXRlIGEgR1BVRGV2aWNlIGluc3RhbmNlIGFuZCBzZXQge0BsaW5rIGRldmljZX0gcHJvcGVydHkgaWZcbiAgICAgKiB5b3Ugd2FudCB0byB1c2UgYSBzcGVjaWZpYyBwb3dlciBwcmVmZXJlbmNlLlxuICAgICAqL1xuICAgIHBvd2VyUHJlZmVyZW5jZT86ICdsb3ctcG93ZXInIHwgJ2hpZ2gtcGVyZm9ybWFuY2UnO1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIGZvcmNlIGZhbGxiYWNrIGFkYXB0ZXIgZmxhZy5cbiAgICAgKlxuICAgICAqIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBvbmx5IGhhcyBlZmZlY3QgYmVmb3JlIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhlIHZhbHVlIHdpbGwgYmVcbiAgICAgKiB1c2VkIGFzIG9wdGlvbnMgZm9yIGBuYXZpZ2F0b3IuZ3B1LnJlcXVlc3RBZGFwdGVyKClgLlxuICAgICAqXG4gICAgICogU2VlIHtAbGluayBodHRwczovL2dwdXdlYi5naXRodWIuaW8vZ3B1d2ViLyNkaWN0ZGVmLWdwdXJlcXVlc3RhZGFwdGVyb3B0aW9uc30gZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYHVuZGVmaW5lZGBcbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkIENyZWF0ZSB5b3VyIG93biBHUFVBZGFwdGVyLCB1c2UgaXQgdG8gY3JlYXRlIGEgR1BVRGV2aWNlIGluc3RhbmNlIGFuZCBzZXQge0BsaW5rIGRldmljZX0gcHJvcGVydHkgaWZcbiAgICAgKiB5b3Ugd2FudCB0byB1c2UgYSBzcGVjaWZpYyBmYWxsYmFjayBvcHRpb24uXG4gICAgICovXG4gICAgZm9yY2VGYWxsYmFja0FkYXB0ZXI/OiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIGFkYXB0ZXIgZm9yIFdlYkdQVS5cbiAgICAgKlxuICAgICAqIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBvbmx5IGhhcyBlZmZlY3QgYmVmb3JlIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhlIHZhbHVlIHdpbGwgYmVcbiAgICAgKiB1c2VkIGFzIHRoZSBHUFUgYWRhcHRlciBmb3IgdGhlIHVuZGVybHlpbmcgV2ViR1BVIGJhY2tlbmQgdG8gY3JlYXRlIEdQVSBkZXZpY2UuXG4gICAgICpcbiAgICAgKiBJZiB0aGlzIHByb3BlcnR5IGlzIG5vdCBzZXQsIGl0IHdpbGwgYmUgYXZhaWxhYmxlIHRvIGdldCBhZnRlciB0aGUgZmlyc3QgV2ViR1BVIGluZmVyZW5jZSBzZXNzaW9uIGlzIGNyZWF0ZWQuIFRoZVxuICAgICAqIHZhbHVlIHdpbGwgYmUgdGhlIEdQVSBhZGFwdGVyIHRoYXQgY3JlYXRlZCBieSB0aGUgdW5kZXJseWluZyBXZWJHUFUgYmFja2VuZC5cbiAgICAgKlxuICAgICAqIFdoZW4gdXNlIHdpdGggVHlwZVNjcmlwdCwgdGhlIHR5cGUgb2YgdGhpcyBwcm9wZXJ0eSBpcyBgR1BVQWRhcHRlcmAgZGVmaW5lZCBpbiBcIkB3ZWJncHUvdHlwZXNcIi5cbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkIEl0IGlzIG5vIGxvbmdlciByZWNvbW1lbmRlZCB0byB1c2UgdGhpcyBwcm9wZXJ0eS4gVGhlIGxhdGVzdCBXZWJHUFUgc3BlYyBhZGRzIGBHUFVEZXZpY2UuYWRhcHRlckluZm9gXG4gICAgICogKGh0dHBzOi8vd3d3LnczLm9yZy9UUi93ZWJncHUvI2RvbS1ncHVkZXZpY2UtYWRhcHRlcmluZm8pLCB3aGljaCBhbGxvd3MgdG8gZ2V0IHRoZSBhZGFwdGVyIGluZm9ybWF0aW9uIGZyb20gdGhlXG4gICAgICogZGV2aWNlLiBXaGVuIGl0J3MgYXZhaWxhYmxlLCB0aGVyZSBpcyBubyBuZWVkIHRvIHNldC9nZXQgdGhlIHtAbGluayBhZGFwdGVyfSBwcm9wZXJ0eS5cbiAgICAgKi9cbiAgICBhZGFwdGVyOiBUcnlHZXRHbG9iYWxUeXBlPCdHUFVBZGFwdGVyJz47XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgR1BVIGRldmljZSBmb3IgV2ViR1BVLlxuICAgICAqXG4gICAgICogVGhlcmUgYXJlIDMgdmFsaWQgc2NlbmFyaW9zIG9mIGFjY2Vzc2luZyB0aGlzIHByb3BlcnR5OlxuICAgICAqIC0gU2V0IGEgdmFsdWUgYmVmb3JlIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhlIHZhbHVlIHdpbGwgYmUgdXNlZCBieSB0aGUgV2ViR1BVIGJhY2tlbmRcbiAgICAgKiB0byBwZXJmb3JtIGNhbGN1bGF0aW9ucy4gSWYgdGhlIHZhbHVlIGlzIG5vdCBhIGBHUFVEZXZpY2VgIG9iamVjdCwgYW4gZXJyb3Igd2lsbCBiZSB0aHJvd24uXG4gICAgICogLSBHZXQgdGhlIHZhbHVlIGJlZm9yZSB0aGUgZmlyc3QgV2ViR1BVIGluZmVyZW5jZSBzZXNzaW9uIGlzIGNyZWF0ZWQuIFRoaXMgd2lsbCB0cnkgdG8gY3JlYXRlIGEgbmV3IEdQVURldmljZVxuICAgICAqIGluc3RhbmNlLiBSZXR1cm5zIGEgYFByb21pc2VgIHRoYXQgcmVzb2x2ZXMgdG8gYSBgR1BVRGV2aWNlYCBvYmplY3QuXG4gICAgICogLSBHZXQgdGhlIHZhbHVlIGFmdGVyIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gUmV0dXJucyBhIHJlc29sdmVkIGBQcm9taXNlYCB0byB0aGVcbiAgICAgKiBgR1BVRGV2aWNlYCBvYmplY3QgdXNlZCBieSB0aGUgV2ViR1BVIGJhY2tlbmQuXG4gICAgICovXG4gICAgZ2V0IGRldmljZSgpOiBQcm9taXNlPFRyeUdldEdsb2JhbFR5cGU8J0dQVURldmljZSc+PjtcbiAgICBzZXQgZGV2aWNlKHZhbHVlOiBUcnlHZXRHbG9iYWxUeXBlPCdHUFVEZXZpY2UnPik7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB3aGV0aGVyIHZhbGlkYXRlIGlucHV0IGNvbnRlbnQuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGBmYWxzZWBcbiAgICAgKi9cbiAgICB2YWxpZGF0ZUlucHV0Q29udGVudD86IGJvb2xlYW47XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBFbnYge1xuICAvKipcbiAgICogc2V0IHRoZSBzZXZlcml0eSBsZXZlbCBmb3IgbG9nZ2luZy5cbiAgICpcbiAgICogQGRlZmF1bHRWYWx1ZSBgJ3dhcm5pbmcnYFxuICAgKi9cbiAgbG9nTGV2ZWw/OiAndmVyYm9zZScgfCAnaW5mbycgfCAnd2FybmluZycgfCAnZXJyb3InIHwgJ2ZhdGFsJztcblxuICAvKipcbiAgICogSW5kaWNhdGUgd2hldGhlciBydW4gaW4gZGVidWcgbW9kZS5cbiAgICpcbiAgICogQGRlZmF1bHRWYWx1ZSBgZmFsc2VgXG4gICAqL1xuICBkZWJ1Zz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIHNldCBvciBnZXQgYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgd2hldGhlciB0byBlbmFibGUgdHJhY2UuXG4gICAqXG4gICAqIEBkZWZhdWx0VmFsdWUgYGZhbHNlYFxuICAgKi9cbiAgdHJhY2U/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBHZXQgdmVyc2lvbiBvZiB0aGUgY3VycmVudCBwYWNrYWdlLlxuICAgKi9cbiAgcmVhZG9ubHkgdmVyc2lvbnM6IHtcbiAgICByZWFkb25seSBjb21tb246IHN0cmluZztcbiAgICByZWFkb25seSB3ZWI/OiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgbm9kZT86IHN0cmluZztcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG4gICAgcmVhZG9ubHkgJ3JlYWN0LW5hdGl2ZSc/OiBzdHJpbmc7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudCBhIHNldCBvZiBmbGFncyBmb3IgV2ViQXNzZW1ibHlcbiAgICovXG4gIHJlYWRvbmx5IHdhc206IEVudi5XZWJBc3NlbWJseUZsYWdzO1xuXG4gIC8qKlxuICAgKiBSZXByZXNlbnQgYSBzZXQgb2YgZmxhZ3MgZm9yIFdlYkdMXG4gICAqL1xuICByZWFkb25seSB3ZWJnbDogRW52LldlYkdMRmxhZ3M7XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudCBhIHNldCBvZiBmbGFncyBmb3IgV2ViR1BVXG4gICAqL1xuICByZWFkb25seSB3ZWJncHU6IEVudi5XZWJHcHVGbGFncztcblxuICBbbmFtZTogc3RyaW5nXTogdW5rbm93bjtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnQgYSBzZXQgb2YgZmxhZ3MgYXMgYSBnbG9iYWwgc2luZ2xldG9uLlxuICovXG5leHBvcnQgY29uc3QgZW52OiBFbnYgPSBlbnZJbXBsO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3JUb0RhdGFVcmxPcHRpb25zLCBUZW5zb3JUb0ltYWdlRGF0YU9wdGlvbnMgfSBmcm9tICcuL3RlbnNvci1jb252ZXJzaW9uLmpzJztcbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yLmpzJztcblxuLyoqXG4gKiBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IudG9EYXRhVVJMKClcbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvclRvRGF0YVVSTCA9ICh0ZW5zb3I6IFRlbnNvciwgb3B0aW9ucz86IFRlbnNvclRvRGF0YVVybE9wdGlvbnMpOiBzdHJpbmcgPT4ge1xuICBjb25zdCBjYW52YXMgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykgOiBuZXcgT2Zmc2NyZWVuQ2FudmFzKDEsIDEpO1xuICBjYW52YXMud2lkdGggPSB0ZW5zb3IuZGltc1szXTtcbiAgY2FudmFzLmhlaWdodCA9IHRlbnNvci5kaW1zWzJdO1xuICBjb25zdCBwaXhlbHMyRENvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKSBhc1xuICAgIHwgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEXG4gICAgfCBPZmZzY3JlZW5DYW52YXNSZW5kZXJpbmdDb250ZXh0MkRcbiAgICB8IG51bGw7XG5cbiAgaWYgKHBpeGVsczJEQ29udGV4dCAhPSBudWxsKSB7XG4gICAgLy8gRGVmYXVsdCB2YWx1ZXMgZm9yIGhlaWdodCBhbmQgd2lkdGggJiBmb3JtYXRcbiAgICBsZXQgd2lkdGg6IG51bWJlcjtcbiAgICBsZXQgaGVpZ2h0OiBudW1iZXI7XG4gICAgaWYgKG9wdGlvbnM/LnRlbnNvckxheW91dCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMudGVuc29yTGF5b3V0ID09PSAnTkhXQycpIHtcbiAgICAgIHdpZHRoID0gdGVuc29yLmRpbXNbMl07XG4gICAgICBoZWlnaHQgPSB0ZW5zb3IuZGltc1szXTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGVmYXVsdCBsYXlvdXQgaXMgTkNXSFxuICAgICAgd2lkdGggPSB0ZW5zb3IuZGltc1szXTtcbiAgICAgIGhlaWdodCA9IHRlbnNvci5kaW1zWzJdO1xuICAgIH1cblxuICAgIGNvbnN0IGlucHV0Zm9ybWF0ID0gb3B0aW9ucz8uZm9ybWF0ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmZvcm1hdCA6ICdSR0InO1xuXG4gICAgY29uc3Qgbm9ybSA9IG9wdGlvbnM/Lm5vcm07XG4gICAgbGV0IG5vcm1NZWFuOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgICBsZXQgbm9ybUJpYXM6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICAgIGlmIChub3JtID09PSB1bmRlZmluZWQgfHwgbm9ybS5tZWFuID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5vcm1NZWFuID0gWzI1NSwgMjU1LCAyNTUsIDI1NV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0eXBlb2Ygbm9ybS5tZWFuID09PSAnbnVtYmVyJykge1xuICAgICAgICBub3JtTWVhbiA9IFtub3JtLm1lYW4sIG5vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW5dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9ybU1lYW4gPSBbbm9ybS5tZWFuWzBdLCBub3JtLm1lYW5bMV0sIG5vcm0ubWVhblsyXSwgMF07XG4gICAgICAgIGlmIChub3JtLm1lYW5bM10gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG5vcm1NZWFuWzNdID0gbm9ybS5tZWFuWzNdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChub3JtID09PSB1bmRlZmluZWQgfHwgbm9ybS5iaWFzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5vcm1CaWFzID0gWzAsIDAsIDAsIDBdO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodHlwZW9mIG5vcm0uYmlhcyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgbm9ybUJpYXMgPSBbbm9ybS5iaWFzLCBub3JtLmJpYXMsIG5vcm0uYmlhcywgbm9ybS5iaWFzXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5vcm1CaWFzID0gW25vcm0uYmlhc1swXSwgbm9ybS5iaWFzWzFdLCBub3JtLmJpYXNbMl0sIDBdO1xuICAgICAgICBpZiAobm9ybS5iaWFzWzNdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBub3JtQmlhc1szXSA9IG5vcm0uYmlhc1szXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHN0cmlkZSA9IGhlaWdodCAqIHdpZHRoO1xuICAgIC8vIERlZmF1bHQgcG9pbnRlciBhc3NpZ25tZW50c1xuICAgIGxldCByVGVuc29yUG9pbnRlciA9IDAsXG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSxcbiAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMixcbiAgICAgIGFUZW5zb3JQb2ludGVyID0gLTE7XG5cbiAgICAvLyBVcGRhdGluZyB0aGUgcG9pbnRlciBhc3NpZ25tZW50cyBiYXNlZCBvbiB0aGUgaW5wdXQgaW1hZ2UgZm9ybWF0XG4gICAgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCQScpIHtcbiAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgICAgYVRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAzO1xuICAgIH0gZWxzZSBpZiAoaW5wdXRmb3JtYXQgPT09ICdSR0InKSB7XG4gICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMjtcbiAgICB9IGVsc2UgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkJHJykge1xuICAgICAgclRlbnNvclBvaW50ZXIgPSAwO1xuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykge1xuICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7XG4gICAgICAgIGNvbnN0IFIgPSAoKHRlbnNvci5kYXRhW3JUZW5zb3JQb2ludGVyKytdIGFzIG51bWJlcikgLSBub3JtQmlhc1swXSkgKiBub3JtTWVhblswXTsgLy8gUiB2YWx1ZVxuICAgICAgICBjb25zdCBHID0gKCh0ZW5zb3IuZGF0YVtnVGVuc29yUG9pbnRlcisrXSBhcyBudW1iZXIpIC0gbm9ybUJpYXNbMV0pICogbm9ybU1lYW5bMV07IC8vIEcgdmFsdWVcbiAgICAgICAgY29uc3QgQiA9ICgodGVuc29yLmRhdGFbYlRlbnNvclBvaW50ZXIrK10gYXMgbnVtYmVyKSAtIG5vcm1CaWFzWzJdKSAqIG5vcm1NZWFuWzJdOyAvLyBCIHZhbHVlXG4gICAgICAgIGNvbnN0IEEgPSBhVGVuc29yUG9pbnRlciA9PT0gLTEgPyAyNTUgOiAoKHRlbnNvci5kYXRhW2FUZW5zb3JQb2ludGVyKytdIGFzIG51bWJlcikgLSBub3JtQmlhc1szXSkgKiBub3JtTWVhblszXTsgLy8gQSB2YWx1ZVxuXG4gICAgICAgIHBpeGVsczJEQ29udGV4dC5maWxsU3R5bGUgPSAncmdiYSgnICsgUiArICcsJyArIEcgKyAnLCcgKyBCICsgJywnICsgQSArICcpJztcbiAgICAgICAgcGl4ZWxzMkRDb250ZXh0LmZpbGxSZWN0KGosIGksIDEsIDEpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoJ3RvRGF0YVVSTCcgaW4gY2FudmFzKSB7XG4gICAgICByZXR1cm4gY2FudmFzLnRvRGF0YVVSTCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RvRGF0YVVSTCBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YScpO1xuICB9XG59O1xuXG4vKipcbiAqIGltcGxlbWVudGF0aW9uIG9mIFRlbnNvci50b0ltYWdlRGF0YSgpXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JUb0ltYWdlRGF0YSA9ICh0ZW5zb3I6IFRlbnNvciwgb3B0aW9ucz86IFRlbnNvclRvSW1hZ2VEYXRhT3B0aW9ucyk6IEltYWdlRGF0YSA9PiB7XG4gIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9XG4gICAgdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJ1xuICAgICAgPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKS5nZXRDb250ZXh0KCcyZCcpXG4gICAgICA6IChuZXcgT2Zmc2NyZWVuQ2FudmFzKDEsIDEpLmdldENvbnRleHQoJzJkJykgYXMgT2Zmc2NyZWVuQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTtcbiAgbGV0IGltYWdlOiBJbWFnZURhdGE7XG4gIGlmIChwaXhlbHMyRENvbnRleHQgIT0gbnVsbCkge1xuICAgIC8vIERlZmF1bHQgdmFsdWVzIGZvciBoZWlnaHQgYW5kIHdpZHRoICYgZm9ybWF0XG4gICAgbGV0IHdpZHRoOiBudW1iZXI7XG4gICAgbGV0IGhlaWdodDogbnVtYmVyO1xuICAgIGxldCBjaGFubmVsczogbnVtYmVyO1xuICAgIGlmIChvcHRpb25zPy50ZW5zb3JMYXlvdXQgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLnRlbnNvckxheW91dCA9PT0gJ05IV0MnKSB7XG4gICAgICB3aWR0aCA9IHRlbnNvci5kaW1zWzJdO1xuICAgICAgaGVpZ2h0ID0gdGVuc29yLmRpbXNbMV07XG4gICAgICBjaGFubmVscyA9IHRlbnNvci5kaW1zWzNdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBEZWZhdWx0IGxheW91dCBpcyBOQ1dIXG4gICAgICB3aWR0aCA9IHRlbnNvci5kaW1zWzNdO1xuICAgICAgaGVpZ2h0ID0gdGVuc29yLmRpbXNbMl07XG4gICAgICBjaGFubmVscyA9IHRlbnNvci5kaW1zWzFdO1xuICAgIH1cbiAgICBjb25zdCBpbnB1dGZvcm1hdCA9IG9wdGlvbnMgIT09IHVuZGVmaW5lZCA/IChvcHRpb25zLmZvcm1hdCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5mb3JtYXQgOiAnUkdCJykgOiAnUkdCJztcblxuICAgIGNvbnN0IG5vcm0gPSBvcHRpb25zPy5ub3JtO1xuICAgIGxldCBub3JtTWVhbjogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gICAgbGV0IG5vcm1CaWFzOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgICBpZiAobm9ybSA9PT0gdW5kZWZpbmVkIHx8IG5vcm0ubWVhbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBub3JtTWVhbiA9IFsyNTUsIDI1NSwgMjU1LCAyNTVdO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodHlwZW9mIG5vcm0ubWVhbiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgbm9ybU1lYW4gPSBbbm9ybS5tZWFuLCBub3JtLm1lYW4sIG5vcm0ubWVhbiwgbm9ybS5tZWFuXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5vcm1NZWFuID0gW25vcm0ubWVhblswXSwgbm9ybS5tZWFuWzFdLCBub3JtLm1lYW5bMl0sIDI1NV07XG4gICAgICAgIGlmIChub3JtLm1lYW5bM10gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG5vcm1NZWFuWzNdID0gbm9ybS5tZWFuWzNdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChub3JtID09PSB1bmRlZmluZWQgfHwgbm9ybS5iaWFzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5vcm1CaWFzID0gWzAsIDAsIDAsIDBdO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodHlwZW9mIG5vcm0uYmlhcyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgbm9ybUJpYXMgPSBbbm9ybS5iaWFzLCBub3JtLmJpYXMsIG5vcm0uYmlhcywgbm9ybS5iaWFzXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5vcm1CaWFzID0gW25vcm0uYmlhc1swXSwgbm9ybS5iaWFzWzFdLCBub3JtLmJpYXNbMl0sIDBdO1xuICAgICAgICBpZiAobm9ybS5iaWFzWzNdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBub3JtQmlhc1szXSA9IG5vcm0uYmlhc1szXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHN0cmlkZSA9IGhlaWdodCAqIHdpZHRoO1xuICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChcbiAgICAgICAgKG9wdGlvbnMuZm9ybWF0ICE9PSB1bmRlZmluZWQgJiYgY2hhbm5lbHMgPT09IDQgJiYgb3B0aW9ucy5mb3JtYXQgIT09ICdSR0JBJykgfHxcbiAgICAgICAgKGNoYW5uZWxzID09PSAzICYmIG9wdGlvbnMuZm9ybWF0ICE9PSAnUkdCJyAmJiBvcHRpb25zLmZvcm1hdCAhPT0gJ0JHUicpXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGVuc29yIGZvcm1hdCBkb2Vzbid0IG1hdGNoIGlucHV0IHRlbnNvciBkaW1zXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIERlZmF1bHQgcG9pbnRlciBhc3NpZ25tZW50c1xuICAgIGNvbnN0IHN0ZXAgPSA0O1xuICAgIGxldCBySW1hZ2VQb2ludGVyID0gMCxcbiAgICAgIGdJbWFnZVBvaW50ZXIgPSAxLFxuICAgICAgYkltYWdlUG9pbnRlciA9IDIsXG4gICAgICBhSW1hZ2VQb2ludGVyID0gMztcbiAgICBsZXQgclRlbnNvclBvaW50ZXIgPSAwLFxuICAgICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGUsXG4gICAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDIsXG4gICAgICBhVGVuc29yUG9pbnRlciA9IC0xO1xuXG4gICAgLy8gVXBkYXRpbmcgdGhlIHBvaW50ZXIgYXNzaWdubWVudHMgYmFzZWQgb24gdGhlIGlucHV0IGltYWdlIGZvcm1hdFxuICAgIGlmIChpbnB1dGZvcm1hdCA9PT0gJ1JHQkEnKSB7XG4gICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMjtcbiAgICAgIGFUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMztcbiAgICB9IGVsc2UgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCJykge1xuICAgICAgclRlbnNvclBvaW50ZXIgPSAwO1xuICAgICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gICAgfSBlbHNlIGlmIChpbnB1dGZvcm1hdCA9PT0gJ1JCRycpIHtcbiAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgIH1cblxuICAgIGltYWdlID0gcGl4ZWxzMkRDb250ZXh0LmNyZWF0ZUltYWdlRGF0YSh3aWR0aCwgaGVpZ2h0KTtcblxuICAgIGZvciAoXG4gICAgICBsZXQgaSA9IDA7XG4gICAgICBpIDwgaGVpZ2h0ICogd2lkdGg7XG4gICAgICBySW1hZ2VQb2ludGVyICs9IHN0ZXAsIGdJbWFnZVBvaW50ZXIgKz0gc3RlcCwgYkltYWdlUG9pbnRlciArPSBzdGVwLCBhSW1hZ2VQb2ludGVyICs9IHN0ZXAsIGkrK1xuICAgICkge1xuICAgICAgaW1hZ2UuZGF0YVtySW1hZ2VQb2ludGVyXSA9ICgodGVuc29yLmRhdGFbclRlbnNvclBvaW50ZXIrK10gYXMgbnVtYmVyKSAtIG5vcm1CaWFzWzBdKSAqIG5vcm1NZWFuWzBdOyAvLyBSIHZhbHVlXG4gICAgICBpbWFnZS5kYXRhW2dJbWFnZVBvaW50ZXJdID0gKCh0ZW5zb3IuZGF0YVtnVGVuc29yUG9pbnRlcisrXSBhcyBudW1iZXIpIC0gbm9ybUJpYXNbMV0pICogbm9ybU1lYW5bMV07IC8vIEcgdmFsdWVcbiAgICAgIGltYWdlLmRhdGFbYkltYWdlUG9pbnRlcl0gPSAoKHRlbnNvci5kYXRhW2JUZW5zb3JQb2ludGVyKytdIGFzIG51bWJlcikgLSBub3JtQmlhc1syXSkgKiBub3JtTWVhblsyXTsgLy8gQiB2YWx1ZVxuICAgICAgaW1hZ2UuZGF0YVthSW1hZ2VQb2ludGVyXSA9XG4gICAgICAgIGFUZW5zb3JQb2ludGVyID09PSAtMSA/IDI1NSA6ICgodGVuc29yLmRhdGFbYVRlbnNvclBvaW50ZXIrK10gYXMgbnVtYmVyKSAtIG5vcm1CaWFzWzNdKSAqIG5vcm1NZWFuWzNdOyAvLyBBIHZhbHVlXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YScpO1xuICB9XG4gIHJldHVybiBpbWFnZTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7XG4gIE9wdGlvbnNEaW1lbnNpb25zLFxuICBPcHRpb25zRm9ybWF0LFxuICBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMsXG4gIE9wdGlvbnNUZW5zb3JGb3JtYXQsXG4gIE9wdGlvbnNUZW5zb3JMYXlvdXQsXG4gIFRlbnNvckZyb21HcHVCdWZmZXJPcHRpb25zLFxuICBUZW5zb3JGcm9tSW1hZ2VCaXRtYXBPcHRpb25zLFxuICBUZW5zb3JGcm9tSW1hZ2VEYXRhT3B0aW9ucyxcbiAgVGVuc29yRnJvbUltYWdlRWxlbWVudE9wdGlvbnMsXG4gIFRlbnNvckZyb21NTFRlbnNvck9wdGlvbnMsXG4gIFRlbnNvckZyb21UZXh0dXJlT3B0aW9ucyxcbiAgVGVuc29yRnJvbVVybE9wdGlvbnMsXG59IGZyb20gJy4vdGVuc29yLWZhY3RvcnkuanMnO1xuaW1wb3J0IHsgVGVuc29yIH0gZnJvbSAnLi90ZW5zb3ItaW1wbC5qcyc7XG5pbXBvcnQgeyBUZW5zb3IgYXMgVGVuc29ySW50ZXJmYWNlIH0gZnJvbSAnLi90ZW5zb3IuanMnO1xuXG5pbnRlcmZhY2UgQnVmZmVyVG9UZW5zb3JPcHRpb25zXG4gIGV4dGVuZHMgT3B0aW9uc0RpbWVuc2lvbnMsXG4gICAgT3B0aW9uc1RlbnNvckxheW91dCxcbiAgICBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMsXG4gICAgT3B0aW9uc0Zvcm1hdCxcbiAgICBPcHRpb25zVGVuc29yRm9ybWF0IHt9XG5cbi8qKlxuICogQ3JlYXRlIGEgbmV3IHRlbnNvciBvYmplY3QgZnJvbSBpbWFnZSBvYmplY3RcbiAqXG4gKiBAcGFyYW0gYnVmZmVyIC0gRXh0cmFjdGVkIGltYWdlIGJ1ZmZlciBkYXRhIC0gYXNzdW1pbmcgUkdCQSBmb3JtYXRcbiAqIEBwYXJhbSBpbWFnZUZvcm1hdCAtIGlucHV0IGltYWdlIGNvbmZpZ3VyYXRpb24gLSByZXF1aXJlZCBjb25maWd1cmF0aW9ucyBoZWlnaHQsIHdpZHRoLCBmb3JtYXRcbiAqIEBwYXJhbSB0ZW5zb3JGb3JtYXQgLSBvdXRwdXQgdGVuc29yIGNvbmZpZ3VyYXRpb24gLSBEZWZhdWx0IGlzIFJHQiBmb3JtYXRcbiAqL1xuZXhwb3J0IGNvbnN0IGJ1ZmZlclRvVGVuc29yID0gKGJ1ZmZlcjogVWludDhDbGFtcGVkQXJyYXkgfCB1bmRlZmluZWQsIG9wdGlvbnM6IEJ1ZmZlclRvVGVuc29yT3B0aW9ucyk6IFRlbnNvciA9PiB7XG4gIGlmIChidWZmZXIgPT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgYnVmZmVyIG11c3QgYmUgZGVmaW5lZCcpO1xuICB9XG4gIGlmIChvcHRpb25zLmhlaWdodCA9PT0gdW5kZWZpbmVkIHx8IG9wdGlvbnMud2lkdGggPT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgaGVpZ2h0IGFuZCB3aWR0aCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgfVxuICBpZiAob3B0aW9ucy50ZW5zb3JMYXlvdXQgPT09ICdOSFdDJykge1xuICAgIHRocm93IG5ldyBFcnJvcignTkhXQyBUZW5zb3IgbGF5b3V0IGlzIG5vdCBzdXBwb3J0ZWQgeWV0Jyk7XG4gIH1cblxuICBjb25zdCB7IGhlaWdodCwgd2lkdGggfSA9IG9wdGlvbnM7XG5cbiAgY29uc3Qgbm9ybSA9IG9wdGlvbnMubm9ybSA/PyB7IG1lYW46IDI1NSwgYmlhczogMCB9O1xuICBsZXQgbm9ybU1lYW46IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICBsZXQgbm9ybUJpYXM6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuXG4gIGlmICh0eXBlb2Ygbm9ybS5tZWFuID09PSAnbnVtYmVyJykge1xuICAgIG5vcm1NZWFuID0gW25vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW4sIG5vcm0ubWVhbl07XG4gIH0gZWxzZSB7XG4gICAgbm9ybU1lYW4gPSBbbm9ybS5tZWFuIVswXSwgbm9ybS5tZWFuIVsxXSwgbm9ybS5tZWFuIVsyXSwgbm9ybS5tZWFuIVszXSA/PyAyNTVdO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBub3JtLmJpYXMgPT09ICdudW1iZXInKSB7XG4gICAgbm9ybUJpYXMgPSBbbm9ybS5iaWFzLCBub3JtLmJpYXMsIG5vcm0uYmlhcywgbm9ybS5iaWFzXTtcbiAgfSBlbHNlIHtcbiAgICBub3JtQmlhcyA9IFtub3JtLmJpYXMhWzBdLCBub3JtLmJpYXMhWzFdLCBub3JtLmJpYXMhWzJdLCBub3JtLmJpYXMhWzNdID8/IDBdO1xuICB9XG5cbiAgY29uc3QgaW5wdXRmb3JtYXQgPSBvcHRpb25zLmZvcm1hdCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5mb3JtYXQgOiAnUkdCQSc7XG4gIC8vIGRlZmF1bHQgdmFsdWUgaXMgUkdCQSBzaW5jZSBpbWFnZWRhdGEgYW5kIEhUTUxJbWFnZUVsZW1lbnQgdXNlcyBpdFxuXG4gIGNvbnN0IG91dHB1dGZvcm1hdCA9XG4gICAgb3B0aW9ucy50ZW5zb3JGb3JtYXQgIT09IHVuZGVmaW5lZCA/IChvcHRpb25zLnRlbnNvckZvcm1hdCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy50ZW5zb3JGb3JtYXQgOiAnUkdCJykgOiAnUkdCJztcbiAgY29uc3Qgc3RyaWRlID0gaGVpZ2h0ICogd2lkdGg7XG4gIGNvbnN0IGZsb2F0MzJEYXRhID0gb3V0cHV0Zm9ybWF0ID09PSAnUkdCQScgPyBuZXcgRmxvYXQzMkFycmF5KHN0cmlkZSAqIDQpIDogbmV3IEZsb2F0MzJBcnJheShzdHJpZGUgKiAzKTtcblxuICAvLyBEZWZhdWx0IHBvaW50ZXIgYXNzaWdubWVudHNcbiAgbGV0IHN0ZXAgPSA0LFxuICAgIHJJbWFnZVBvaW50ZXIgPSAwLFxuICAgIGdJbWFnZVBvaW50ZXIgPSAxLFxuICAgIGJJbWFnZVBvaW50ZXIgPSAyLFxuICAgIGFJbWFnZVBvaW50ZXIgPSAzO1xuICBsZXQgclRlbnNvclBvaW50ZXIgPSAwLFxuICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlLFxuICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMixcbiAgICBhVGVuc29yUG9pbnRlciA9IC0xO1xuXG4gIC8vIFVwZGF0aW5nIHRoZSBwb2ludGVyIGFzc2lnbm1lbnRzIGJhc2VkIG9uIHRoZSBpbnB1dCBpbWFnZSBmb3JtYXRcbiAgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCJykge1xuICAgIHN0ZXAgPSAzO1xuICAgIHJJbWFnZVBvaW50ZXIgPSAwO1xuICAgIGdJbWFnZVBvaW50ZXIgPSAxO1xuICAgIGJJbWFnZVBvaW50ZXIgPSAyO1xuICAgIGFJbWFnZVBvaW50ZXIgPSAtMTtcbiAgfVxuXG4gIC8vIFVwZGF0aW5nIHRoZSBwb2ludGVyIGFzc2lnbm1lbnRzIGJhc2VkIG9uIHRoZSBvdXRwdXQgdGVuc29yIGZvcm1hdFxuICBpZiAob3V0cHV0Zm9ybWF0ID09PSAnUkdCQScpIHtcbiAgICBhVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDM7XG4gIH0gZWxzZSBpZiAob3V0cHV0Zm9ybWF0ID09PSAnUkJHJykge1xuICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gIH0gZWxzZSBpZiAob3V0cHV0Zm9ybWF0ID09PSAnQkdSJykge1xuICAgIGJUZW5zb3JQb2ludGVyID0gMDtcbiAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICByVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gIH1cblxuICBmb3IgKFxuICAgIGxldCBpID0gMDtcbiAgICBpIDwgc3RyaWRlO1xuICAgIGkrKywgckltYWdlUG9pbnRlciArPSBzdGVwLCBiSW1hZ2VQb2ludGVyICs9IHN0ZXAsIGdJbWFnZVBvaW50ZXIgKz0gc3RlcCwgYUltYWdlUG9pbnRlciArPSBzdGVwXG4gICkge1xuICAgIGZsb2F0MzJEYXRhW3JUZW5zb3JQb2ludGVyKytdID0gKGJ1ZmZlcltySW1hZ2VQb2ludGVyXSArIG5vcm1CaWFzWzBdKSAvIG5vcm1NZWFuWzBdO1xuICAgIGZsb2F0MzJEYXRhW2dUZW5zb3JQb2ludGVyKytdID0gKGJ1ZmZlcltnSW1hZ2VQb2ludGVyXSArIG5vcm1CaWFzWzFdKSAvIG5vcm1NZWFuWzFdO1xuICAgIGZsb2F0MzJEYXRhW2JUZW5zb3JQb2ludGVyKytdID0gKGJ1ZmZlcltiSW1hZ2VQb2ludGVyXSArIG5vcm1CaWFzWzJdKSAvIG5vcm1NZWFuWzJdO1xuICAgIGlmIChhVGVuc29yUG9pbnRlciAhPT0gLTEgJiYgYUltYWdlUG9pbnRlciAhPT0gLTEpIHtcbiAgICAgIGZsb2F0MzJEYXRhW2FUZW5zb3JQb2ludGVyKytdID0gKGJ1ZmZlclthSW1hZ2VQb2ludGVyXSArIG5vcm1CaWFzWzNdKSAvIG5vcm1NZWFuWzNdO1xuICAgIH1cbiAgfVxuXG4gIC8vIEZsb2F0MzJBcnJheSAtPiBvcnQuVGVuc29yXG4gIGNvbnN0IG91dHB1dFRlbnNvciA9XG4gICAgb3V0cHV0Zm9ybWF0ID09PSAnUkdCQSdcbiAgICAgID8gbmV3IFRlbnNvcignZmxvYXQzMicsIGZsb2F0MzJEYXRhLCBbMSwgNCwgaGVpZ2h0LCB3aWR0aF0pXG4gICAgICA6IG5ldyBUZW5zb3IoJ2Zsb2F0MzInLCBmbG9hdDMyRGF0YSwgWzEsIDMsIGhlaWdodCwgd2lkdGhdKTtcbiAgcmV0dXJuIG91dHB1dFRlbnNvcjtcbn07XG5cbi8qKlxuICogaW1wbGVtZW50YXRpb24gb2YgVGVuc29yLmZyb21JbWFnZSgpLlxuICovXG5leHBvcnQgY29uc3QgdGVuc29yRnJvbUltYWdlID0gYXN5bmMgKFxuICBpbWFnZTogSW1hZ2VEYXRhIHwgSFRNTEltYWdlRWxlbWVudCB8IEltYWdlQml0bWFwIHwgc3RyaW5nLFxuICBvcHRpb25zPzpcbiAgICB8IFRlbnNvckZyb21JbWFnZURhdGFPcHRpb25zXG4gICAgfCBUZW5zb3JGcm9tSW1hZ2VFbGVtZW50T3B0aW9uc1xuICAgIHwgVGVuc29yRnJvbUltYWdlQml0bWFwT3B0aW9uc1xuICAgIHwgVGVuc29yRnJvbVVybE9wdGlvbnMsXG4pOiBQcm9taXNlPFRlbnNvcj4gPT4ge1xuICAvLyBjaGVja2luZyB0aGUgdHlwZSBvZiBpbWFnZSBvYmplY3RcbiAgY29uc3QgaXNIVE1MSW1hZ2VFbGUgPSB0eXBlb2YgSFRNTEltYWdlRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgaW1hZ2UgaW5zdGFuY2VvZiBIVE1MSW1hZ2VFbGVtZW50O1xuICBjb25zdCBpc0ltYWdlRGF0YUVsZSA9IHR5cGVvZiBJbWFnZURhdGEgIT09ICd1bmRlZmluZWQnICYmIGltYWdlIGluc3RhbmNlb2YgSW1hZ2VEYXRhO1xuICBjb25zdCBpc0ltYWdlQml0bWFwID0gdHlwZW9mIEltYWdlQml0bWFwICE9PSAndW5kZWZpbmVkJyAmJiBpbWFnZSBpbnN0YW5jZW9mIEltYWdlQml0bWFwO1xuICBjb25zdCBpc1N0cmluZyA9IHR5cGVvZiBpbWFnZSA9PT0gJ3N0cmluZyc7XG5cbiAgbGV0IGRhdGE6IFVpbnQ4Q2xhbXBlZEFycmF5IHwgdW5kZWZpbmVkO1xuICBsZXQgYnVmZmVyVG9UZW5zb3JPcHRpb25zOiBCdWZmZXJUb1RlbnNvck9wdGlvbnMgPSBvcHRpb25zID8/IHt9O1xuXG4gIGNvbnN0IGNyZWF0ZUNhbnZhcyA9ICgpID0+IHtcbiAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIE9mZnNjcmVlbkNhbnZhcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBuZXcgT2Zmc2NyZWVuQ2FudmFzKDEsIDEpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbnZhcyBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gICAgfVxuICB9O1xuICBjb25zdCBjcmVhdGVDYW52YXNDb250ZXh0ID0gKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQgfCBPZmZzY3JlZW5DYW52YXMpID0+IHtcbiAgICBpZiAodHlwZW9mIEhUTUxDYW52YXNFbGVtZW50ICE9PSAndW5kZWZpbmVkJyAmJiBjYW52YXMgaW5zdGFuY2VvZiBIVE1MQ2FudmFzRWxlbWVudCkge1xuICAgICAgcmV0dXJuIGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIH0gZWxzZSBpZiAoY2FudmFzIGluc3RhbmNlb2YgT2Zmc2NyZWVuQ2FudmFzKSB7XG4gICAgICByZXR1cm4gY2FudmFzLmdldENvbnRleHQoJzJkJykgYXMgT2Zmc2NyZWVuQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH07XG4gIC8vIGZpbGxpbmcgYW5kIGNoZWNraW5nIGltYWdlIGNvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICBpZiAoaXNIVE1MSW1hZ2VFbGUpIHtcbiAgICAvLyBIVE1MSW1hZ2VFbGVtZW50IC0gaW1hZ2Ugb2JqZWN0IC0gZm9ybWF0IGlzIFJHQkEgYnkgZGVmYXVsdFxuICAgIGNvbnN0IGNhbnZhcyA9IGNyZWF0ZUNhbnZhcygpO1xuICAgIGNhbnZhcy53aWR0aCA9IGltYWdlLndpZHRoO1xuICAgIGNhbnZhcy5oZWlnaHQgPSBpbWFnZS5oZWlnaHQ7XG4gICAgY29uc3QgcGl4ZWxzMkRDb250ZXh0ID0gY3JlYXRlQ2FudmFzQ29udGV4dChjYW52YXMpO1xuXG4gICAgaWYgKHBpeGVsczJEQ29udGV4dCAhPSBudWxsKSB7XG4gICAgICBsZXQgaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0O1xuICAgICAgbGV0IHdpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMucmVzaXplZEhlaWdodCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMucmVzaXplZFdpZHRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaGVpZ2h0ID0gb3B0aW9ucy5yZXNpemVkSGVpZ2h0O1xuICAgICAgICB3aWR0aCA9IG9wdGlvbnMucmVzaXplZFdpZHRoO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgIGlmIChvcHRpb25zLnRlbnNvckZvcm1hdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBpbnB1dCBjb25maWcgZm9ybWF0IG11c3QgYmUgUkdCQSBmb3IgSFRNTEltYWdlRWxlbWVudCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy50ZW5zb3JGb3JtYXQgPSAnUkdCQSc7XG4gICAgICAgIH1cbiAgICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLndpZHRoID0gd2lkdGg7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMudGVuc29yRm9ybWF0ID0gJ1JHQkEnO1xuICAgICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMud2lkdGggPSB3aWR0aDtcbiAgICAgIH1cblxuICAgICAgcGl4ZWxzMkRDb250ZXh0LmRyYXdJbWFnZShpbWFnZSwgMCwgMCk7XG4gICAgICBkYXRhID0gcGl4ZWxzMkRDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCB3aWR0aCwgaGVpZ2h0KS5kYXRhO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoaXNJbWFnZURhdGFFbGUpIHtcbiAgICBsZXQgaGVpZ2h0OiBudW1iZXI7XG4gICAgbGV0IHdpZHRoOiBudW1iZXI7XG5cbiAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMucmVzaXplZFdpZHRoICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkSGVpZ2h0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGhlaWdodCA9IG9wdGlvbnMucmVzaXplZEhlaWdodDtcbiAgICAgIHdpZHRoID0gb3B0aW9ucy5yZXNpemVkV2lkdGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIGhlaWdodCA9IGltYWdlLmhlaWdodDtcbiAgICAgIHdpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zID0gb3B0aW9ucztcbiAgICB9XG4gICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLmZvcm1hdCA9ICdSR0JBJztcbiAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy53aWR0aCA9IHdpZHRoO1xuXG4gICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgdGVtcENhbnZhcyA9IGNyZWF0ZUNhbnZhcygpO1xuXG4gICAgICB0ZW1wQ2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgICB0ZW1wQ2FudmFzLmhlaWdodCA9IGhlaWdodDtcblxuICAgICAgY29uc3QgcGl4ZWxzMkRDb250ZXh0ID0gY3JlYXRlQ2FudmFzQ29udGV4dCh0ZW1wQ2FudmFzKTtcblxuICAgICAgaWYgKHBpeGVsczJEQ29udGV4dCAhPSBudWxsKSB7XG4gICAgICAgIHBpeGVsczJEQ29udGV4dC5wdXRJbWFnZURhdGEoaW1hZ2UsIDAsIDApO1xuICAgICAgICBkYXRhID0gcGl4ZWxzMkRDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCB3aWR0aCwgaGVpZ2h0KS5kYXRhO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGRhdGEgPSBpbWFnZS5kYXRhO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpc0ltYWdlQml0bWFwKSB7XG4gICAgLy8gSW1hZ2VCaXRtYXAgLSBpbWFnZSBvYmplY3QgLSBmb3JtYXQgbXVzdCBiZSBwcm92aWRlZCBieSB1c2VyXG4gICAgaWYgKG9wdGlvbnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdQbGVhc2UgcHJvdmlkZSBpbWFnZSBjb25maWcgd2l0aCBmb3JtYXQgZm9yIEltYWdlYml0bWFwJyk7XG4gICAgfVxuXG4gICAgY29uc3QgY2FudmFzID0gY3JlYXRlQ2FudmFzKCk7XG4gICAgY2FudmFzLndpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgY2FudmFzLmhlaWdodCA9IGltYWdlLmhlaWdodDtcbiAgICBjb25zdCBwaXhlbHMyRENvbnRleHQgPSBjcmVhdGVDYW52YXNDb250ZXh0KGNhbnZhcyk7XG5cbiAgICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAgIGNvbnN0IGhlaWdodCA9IGltYWdlLmhlaWdodDtcbiAgICAgIGNvbnN0IHdpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgICBwaXhlbHMyRENvbnRleHQuZHJhd0ltYWdlKGltYWdlLCAwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgIGRhdGEgPSBwaXhlbHMyRENvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIHdpZHRoLCBoZWlnaHQpLmRhdGE7XG4gICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLndpZHRoID0gd2lkdGg7XG4gICAgICByZXR1cm4gYnVmZmVyVG9UZW5zb3IoZGF0YSwgYnVmZmVyVG9UZW5zb3JPcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhJyk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGlzU3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGNhbnZhcyA9IGNyZWF0ZUNhbnZhcygpO1xuICAgICAgY29uc3QgY29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQoY2FudmFzKTtcbiAgICAgIGlmICghaW1hZ2UgfHwgIWNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdCgpO1xuICAgICAgfVxuICAgICAgY29uc3QgbmV3SW1hZ2UgPSBuZXcgSW1hZ2UoKTtcbiAgICAgIG5ld0ltYWdlLmNyb3NzT3JpZ2luID0gJ0Fub255bW91cyc7XG4gICAgICBuZXdJbWFnZS5zcmMgPSBpbWFnZTtcbiAgICAgIG5ld0ltYWdlLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgY2FudmFzLndpZHRoID0gbmV3SW1hZ2Uud2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBuZXdJbWFnZS5oZWlnaHQ7XG4gICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKG5ld0ltYWdlLCAwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuICAgICAgICBjb25zdCBpbWcgPSBjb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG4gICAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy5oZWlnaHQgPSBjYW52YXMuaGVpZ2h0O1xuICAgICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMud2lkdGggPSBjYW52YXMud2lkdGg7XG4gICAgICAgIHJlc29sdmUoYnVmZmVyVG9UZW5zb3IoaW1nLmRhdGEsIGJ1ZmZlclRvVGVuc29yT3B0aW9ucykpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGRhdGEgcHJvdmlkZWQgaXMgbm90IHN1cHBvcnRlZCAtIGFib3J0ZWQgdGVuc29yIGNyZWF0aW9uJyk7XG4gIH1cblxuICBpZiAoZGF0YSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGJ1ZmZlclRvVGVuc29yKGRhdGEsIGJ1ZmZlclRvVGVuc29yT3B0aW9ucyk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbicpO1xuICB9XG59O1xuXG4vKipcbiAqIGltcGxlbWVudGF0aW9uIG9mIFRlbnNvci5mcm9tVGV4dHVyZSgpLlxuICovXG5leHBvcnQgY29uc3QgdGVuc29yRnJvbVRleHR1cmUgPSA8VCBleHRlbmRzIFRlbnNvckludGVyZmFjZS5UZXh0dXJlRGF0YVR5cGVzPihcbiAgdGV4dHVyZTogVGVuc29ySW50ZXJmYWNlLlRleHR1cmVUeXBlLFxuICBvcHRpb25zOiBUZW5zb3JGcm9tVGV4dHVyZU9wdGlvbnM8VD4sXG4pOiBUZW5zb3IgPT4ge1xuICBjb25zdCB7IHdpZHRoLCBoZWlnaHQsIGRvd25sb2FkLCBkaXNwb3NlIH0gPSBvcHRpb25zO1xuICAvLyBBbHdheXMgYXNzdW1lIFJHQkFGMzIuIFRPRE86IHN1cHBvcnQgZGlmZmVyZW50IHRleHR1cmUgZm9ybWF0XG4gIGNvbnN0IGRpbXMgPSBbMSwgaGVpZ2h0LCB3aWR0aCwgNF07XG4gIHJldHVybiBuZXcgVGVuc29yKHsgbG9jYXRpb246ICd0ZXh0dXJlJywgdHlwZTogJ2Zsb2F0MzInLCB0ZXh0dXJlLCBkaW1zLCBkb3dubG9hZCwgZGlzcG9zZSB9KTtcbn07XG5cbi8qKlxuICogaW1wbGVtZW50YXRpb24gb2YgVGVuc29yLmZyb21HcHVCdWZmZXIoKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvckZyb21HcHVCdWZmZXIgPSA8VCBleHRlbmRzIFRlbnNvckludGVyZmFjZS5HcHVCdWZmZXJEYXRhVHlwZXM+KFxuICBncHVCdWZmZXI6IFRlbnNvckludGVyZmFjZS5HcHVCdWZmZXJUeXBlLFxuICBvcHRpb25zOiBUZW5zb3JGcm9tR3B1QnVmZmVyT3B0aW9uczxUPixcbik6IFRlbnNvciA9PiB7XG4gIGNvbnN0IHsgZGF0YVR5cGUsIGRpbXMsIGRvd25sb2FkLCBkaXNwb3NlIH0gPSBvcHRpb25zO1xuICByZXR1cm4gbmV3IFRlbnNvcih7IGxvY2F0aW9uOiAnZ3B1LWJ1ZmZlcicsIHR5cGU6IGRhdGFUeXBlID8/ICdmbG9hdDMyJywgZ3B1QnVmZmVyLCBkaW1zLCBkb3dubG9hZCwgZGlzcG9zZSB9KTtcbn07XG5cbi8qKlxuICogaW1wbGVtZW50YXRpb24gb2YgVGVuc29yLmZyb21NTFRlbnNvcigpLlxuICovXG5leHBvcnQgY29uc3QgdGVuc29yRnJvbU1MVGVuc29yID0gPFQgZXh0ZW5kcyBUZW5zb3JJbnRlcmZhY2UuTUxUZW5zb3JEYXRhVHlwZXM+KFxuICBtbFRlbnNvcjogVGVuc29ySW50ZXJmYWNlLk1MVGVuc29yVHlwZSxcbiAgb3B0aW9uczogVGVuc29yRnJvbU1MVGVuc29yT3B0aW9uczxUPixcbik6IFRlbnNvciA9PiB7XG4gIGNvbnN0IHsgZGF0YVR5cGUsIGRpbXMsIGRvd25sb2FkLCBkaXNwb3NlIH0gPSBvcHRpb25zO1xuICByZXR1cm4gbmV3IFRlbnNvcih7IGxvY2F0aW9uOiAnbWwtdGVuc29yJywgdHlwZTogZGF0YVR5cGUgPz8gJ2Zsb2F0MzInLCBtbFRlbnNvciwgZGltcywgZG93bmxvYWQsIGRpc3Bvc2UgfSk7XG59O1xuXG4vKipcbiAqIGltcGxlbWVudGF0aW9uIG9mIFRlbnNvci5mcm9tUGlubmVkQnVmZmVyKCkuXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JGcm9tUGlubmVkQnVmZmVyID0gPFQgZXh0ZW5kcyBUZW5zb3JJbnRlcmZhY2UuQ3B1UGlubmVkRGF0YVR5cGVzPihcbiAgdHlwZTogVCxcbiAgYnVmZmVyOiBUZW5zb3JJbnRlcmZhY2UuRGF0YVR5cGVNYXBbVF0sXG4gIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbik6IFRlbnNvciA9PiBuZXcgVGVuc29yKHsgbG9jYXRpb246ICdjcHUtcGlubmVkJywgdHlwZSwgZGF0YTogYnVmZmVyLCBkaW1zOiBkaW1zID8/IFtidWZmZXIubGVuZ3RoXSB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yIH0gZnJvbSAnLi90ZW5zb3IuanMnO1xuXG5leHBvcnQgdHlwZSBTdXBwb3J0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3JzID1cbiAgfCBGbG9hdDMyQXJyYXlDb25zdHJ1Y3RvclxuICB8IFVpbnQ4QXJyYXlDb25zdHJ1Y3RvclxuICB8IEludDhBcnJheUNvbnN0cnVjdG9yXG4gIHwgVWludDE2QXJyYXlDb25zdHJ1Y3RvclxuICB8IEludDE2QXJyYXlDb25zdHJ1Y3RvclxuICB8IEludDMyQXJyYXlDb25zdHJ1Y3RvclxuICB8IEJpZ0ludDY0QXJyYXlDb25zdHJ1Y3RvclxuICB8IFVpbnQ4QXJyYXlDb25zdHJ1Y3RvclxuICB8IEZsb2F0NjRBcnJheUNvbnN0cnVjdG9yXG4gIHwgVWludDMyQXJyYXlDb25zdHJ1Y3RvclxuICB8IEJpZ1VpbnQ2NEFycmF5Q29uc3RydWN0b3I7XG5leHBvcnQgdHlwZSBTdXBwb3J0ZWRUeXBlZEFycmF5ID0gSW5zdGFuY2VUeXBlPFN1cHBvcnRlZFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnM+O1xuXG4vLyBhIHJ1bnRpbWUgbWFwIHRoYXQgbWFwcyB0eXBlIHN0cmluZyB0byBUeXBlZEFycmF5IGNvbnN0cnVjdG9yLiBTaG91bGQgbWF0Y2ggVGVuc29yLkRhdGFUeXBlTWFwLlxuZXhwb3J0IGNvbnN0IE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAgPSBuZXcgTWFwPHN0cmluZywgU3VwcG9ydGVkVHlwZWRBcnJheUNvbnN0cnVjdG9ycz4oW1xuICBbJ2Zsb2F0MzInLCBGbG9hdDMyQXJyYXldLFxuICBbJ3VpbnQ4JywgVWludDhBcnJheV0sXG4gIFsnaW50OCcsIEludDhBcnJheV0sXG4gIFsndWludDE2JywgVWludDE2QXJyYXldLFxuICBbJ2ludDE2JywgSW50MTZBcnJheV0sXG4gIFsnaW50MzInLCBJbnQzMkFycmF5XSxcbiAgWydib29sJywgVWludDhBcnJheV0sXG4gIFsnZmxvYXQ2NCcsIEZsb2F0NjRBcnJheV0sXG4gIFsndWludDMyJywgVWludDMyQXJyYXldLFxuICBbJ2ludDQnLCBVaW50OEFycmF5XSxcbiAgWyd1aW50NCcsIFVpbnQ4QXJyYXldLFxuXSk7XG5cbi8vIGEgcnVudGltZSBtYXAgdGhhdCBtYXBzIHR5cGUgc3RyaW5nIHRvIFR5cGVkQXJyYXkgY29uc3RydWN0b3IuIFNob3VsZCBtYXRjaCBUZW5zb3IuRGF0YVR5cGVNYXAuXG5leHBvcnQgY29uc3QgTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUCA9IG5ldyBNYXA8U3VwcG9ydGVkVHlwZWRBcnJheUNvbnN0cnVjdG9ycywgVGVuc29yLlR5cGU+KFtcbiAgW0Zsb2F0MzJBcnJheSwgJ2Zsb2F0MzInXSxcbiAgW1VpbnQ4QXJyYXksICd1aW50OCddLFxuICBbSW50OEFycmF5LCAnaW50OCddLFxuICBbVWludDE2QXJyYXksICd1aW50MTYnXSxcbiAgW0ludDE2QXJyYXksICdpbnQxNiddLFxuICBbSW50MzJBcnJheSwgJ2ludDMyJ10sXG4gIFtGbG9hdDY0QXJyYXksICdmbG9hdDY0J10sXG4gIFtVaW50MzJBcnJheSwgJ3VpbnQzMiddLFxuXSk7XG5cbi8vIHRoZSBmb2xsb3dpbmcgY29kZSBhbGxvd3MgZGVsYXlpbmcgZXhlY3V0aW9uIG9mIEJpZ0ludC9GbG9hdDE2QXJyYXkgY2hlY2tpbmcuIFRoaXMgYWxsb3dzIGxhenkgaW5pdGlhbGl6YXRpb24gZm9yXG4vLyBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQIGFuZCBOVU1FUklDX1RFTlNPUl9UWVBFREFSUkFZX1RPX1RZUEVfTUFQLCB3aGljaCBhbGxvd3MgQmlnSW50L0Zsb2F0MTZBcnJheVxuLy8gcG9seWZpbGwgaWYgYXZhaWxhYmxlLlxubGV0IGlzVHlwZWRBcnJheUNoZWNrZWQgPSBmYWxzZTtcbmV4cG9ydCBjb25zdCBjaGVja1R5cGVkQXJyYXkgPSAoKSA9PiB7XG4gIGlmICghaXNUeXBlZEFycmF5Q2hlY2tlZCkge1xuICAgIGlzVHlwZWRBcnJheUNoZWNrZWQgPSB0cnVlO1xuICAgIGNvbnN0IGlzQmlnSW50NjRBcnJheUF2YWlsYWJsZSA9IHR5cGVvZiBCaWdJbnQ2NEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiBCaWdJbnQ2NEFycmF5LmZyb207XG4gICAgY29uc3QgaXNCaWdVaW50NjRBcnJheUF2YWlsYWJsZSA9IHR5cGVvZiBCaWdVaW50NjRBcnJheSAhPT0gJ3VuZGVmaW5lZCcgJiYgQmlnVWludDY0QXJyYXkuZnJvbTtcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb24sIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBjb25zdCBGbG9hdDE2QXJyYXkgPSAoZ2xvYmFsVGhpcyBhcyBhbnkpLkZsb2F0MTZBcnJheTtcbiAgICBjb25zdCBpc0Zsb2F0MTZBcnJheUF2YWlsYWJsZSA9IHR5cGVvZiBGbG9hdDE2QXJyYXkgIT09ICd1bmRlZmluZWQnICYmIEZsb2F0MTZBcnJheS5mcm9tO1xuXG4gICAgaWYgKGlzQmlnSW50NjRBcnJheUF2YWlsYWJsZSkge1xuICAgICAgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5zZXQoJ2ludDY0JywgQmlnSW50NjRBcnJheSk7XG4gICAgICBOVU1FUklDX1RFTlNPUl9UWVBFREFSUkFZX1RPX1RZUEVfTUFQLnNldChCaWdJbnQ2NEFycmF5LCAnaW50NjQnKTtcbiAgICB9XG4gICAgaWYgKGlzQmlnVWludDY0QXJyYXlBdmFpbGFibGUpIHtcbiAgICAgIE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAuc2V0KCd1aW50NjQnLCBCaWdVaW50NjRBcnJheSk7XG4gICAgICBOVU1FUklDX1RFTlNPUl9UWVBFREFSUkFZX1RPX1RZUEVfTUFQLnNldChCaWdVaW50NjRBcnJheSwgJ3VpbnQ2NCcpO1xuICAgIH1cbiAgICBpZiAoaXNGbG9hdDE2QXJyYXlBdmFpbGFibGUpIHtcbiAgICAgIE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAuc2V0KCdmbG9hdDE2JywgRmxvYXQxNkFycmF5KTtcbiAgICAgIE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAuc2V0KEZsb2F0MTZBcnJheSwgJ2Zsb2F0MTYnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgRmxvYXQxNkFycmF5IGlzIG5vdCBhdmFpbGFibGUsIHVzZSAnVWludDE2QXJyYXknIHRvIHN0b3JlIHRoZSBkYXRhLlxuICAgICAgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5zZXQoJ2Zsb2F0MTYnLCBVaW50MTZBcnJheSk7XG4gICAgfVxuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1xuICBDcHVQaW5uZWRDb25zdHJ1Y3RvclBhcmFtZXRlcnMsXG4gIEdwdUJ1ZmZlckNvbnN0cnVjdG9yUGFyYW1ldGVycyxcbiAgTUxUZW5zb3JDb25zdHJ1Y3RvclBhcmFtZXRlcnMsXG4gIFRleHR1cmVDb25zdHJ1Y3RvclBhcmFtZXRlcnMsXG59IGZyb20gJy4vdGVuc29yLWZhY3RvcnkuanMnO1xuaW1wb3J0IHsgVGVuc29yIH0gZnJvbSAnLi90ZW5zb3ItaW1wbC5qcyc7XG5cbi8qKlxuICogY2FsY3VsYXRlIHNpemUgZnJvbSBkaW1zLlxuICpcbiAqIEBwYXJhbSBkaW1zIHRoZSBkaW1zIGFycmF5LiBNYXkgYmUgYW4gaWxsZWdhbCBpbnB1dC5cbiAqL1xuZXhwb3J0IGNvbnN0IGNhbGN1bGF0ZVNpemUgPSAoZGltczogcmVhZG9ubHkgdW5rbm93bltdKTogbnVtYmVyID0+IHtcbiAgbGV0IHNpemUgPSAxO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGRpbXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBkaW0gPSBkaW1zW2ldO1xuICAgIGlmICh0eXBlb2YgZGltICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzU2FmZUludGVnZXIoZGltKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgZGltc1ske2l9XSBtdXN0IGJlIGFuIGludGVnZXIsIGdvdDogJHtkaW19YCk7XG4gICAgfVxuICAgIGlmIChkaW0gPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgZGltc1ske2l9XSBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIsIGdvdDogJHtkaW19YCk7XG4gICAgfVxuICAgIHNpemUgKj0gZGltO1xuICB9XG4gIHJldHVybiBzaXplO1xufTtcblxuLyoqXG4gKiBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IucmVzaGFwZSgpXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JSZXNoYXBlID0gKHRlbnNvcjogVGVuc29yLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IFRlbnNvciA9PiB7XG4gIHN3aXRjaCAodGVuc29yLmxvY2F0aW9uKSB7XG4gICAgY2FzZSAnY3B1JzpcbiAgICAgIHJldHVybiBuZXcgVGVuc29yKHRlbnNvci50eXBlLCB0ZW5zb3IuZGF0YSwgZGltcyk7XG4gICAgY2FzZSAnY3B1LXBpbm5lZCc6XG4gICAgICByZXR1cm4gbmV3IFRlbnNvcih7XG4gICAgICAgIGxvY2F0aW9uOiAnY3B1LXBpbm5lZCcsXG4gICAgICAgIGRhdGE6IHRlbnNvci5kYXRhIGFzIENwdVBpbm5lZENvbnN0cnVjdG9yUGFyYW1ldGVyc1snZGF0YSddLFxuICAgICAgICB0eXBlOiB0ZW5zb3IudHlwZSBhcyBDcHVQaW5uZWRDb25zdHJ1Y3RvclBhcmFtZXRlcnNbJ3R5cGUnXSxcbiAgICAgICAgZGltcyxcbiAgICAgIH0pO1xuICAgIGNhc2UgJ3RleHR1cmUnOlxuICAgICAgcmV0dXJuIG5ldyBUZW5zb3Ioe1xuICAgICAgICBsb2NhdGlvbjogJ3RleHR1cmUnLFxuICAgICAgICB0ZXh0dXJlOiB0ZW5zb3IudGV4dHVyZSxcbiAgICAgICAgdHlwZTogdGVuc29yLnR5cGUgYXMgVGV4dHVyZUNvbnN0cnVjdG9yUGFyYW1ldGVyc1sndHlwZSddLFxuICAgICAgICBkaW1zLFxuICAgICAgfSk7XG4gICAgY2FzZSAnZ3B1LWJ1ZmZlcic6XG4gICAgICByZXR1cm4gbmV3IFRlbnNvcih7XG4gICAgICAgIGxvY2F0aW9uOiAnZ3B1LWJ1ZmZlcicsXG4gICAgICAgIGdwdUJ1ZmZlcjogdGVuc29yLmdwdUJ1ZmZlcixcbiAgICAgICAgdHlwZTogdGVuc29yLnR5cGUgYXMgR3B1QnVmZmVyQ29uc3RydWN0b3JQYXJhbWV0ZXJzWyd0eXBlJ10sXG4gICAgICAgIGRpbXMsXG4gICAgICB9KTtcbiAgICBjYXNlICdtbC10ZW5zb3InOlxuICAgICAgcmV0dXJuIG5ldyBUZW5zb3Ioe1xuICAgICAgICBsb2NhdGlvbjogJ21sLXRlbnNvcicsXG4gICAgICAgIG1sVGVuc29yOiB0ZW5zb3IubWxUZW5zb3IsXG4gICAgICAgIHR5cGU6IHRlbnNvci50eXBlIGFzIE1MVGVuc29yQ29uc3RydWN0b3JQYXJhbWV0ZXJzWyd0eXBlJ10sXG4gICAgICAgIGRpbXMsXG4gICAgICB9KTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGB0ZW5zb3JSZXNoYXBlOiB0ZW5zb3IgbG9jYXRpb24gJHt0ZW5zb3IubG9jYXRpb259IGlzIG5vdCBzdXBwb3J0ZWRgKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgdGVuc29yVG9EYXRhVVJMLCB0ZW5zb3JUb0ltYWdlRGF0YSB9IGZyb20gJy4vdGVuc29yLWNvbnZlcnNpb24taW1wbC5qcyc7XG5pbXBvcnQgeyBUZW5zb3JUb0RhdGFVcmxPcHRpb25zLCBUZW5zb3JUb0ltYWdlRGF0YU9wdGlvbnMgfSBmcm9tICcuL3RlbnNvci1jb252ZXJzaW9uLmpzJztcbmltcG9ydCB7XG4gIHRlbnNvckZyb21HcHVCdWZmZXIsXG4gIHRlbnNvckZyb21JbWFnZSxcbiAgdGVuc29yRnJvbU1MVGVuc29yLFxuICB0ZW5zb3JGcm9tUGlubmVkQnVmZmVyLFxuICB0ZW5zb3JGcm9tVGV4dHVyZSxcbn0gZnJvbSAnLi90ZW5zb3ItZmFjdG9yeS1pbXBsLmpzJztcbmltcG9ydCB7XG4gIENwdVBpbm5lZENvbnN0cnVjdG9yUGFyYW1ldGVycyxcbiAgR3B1QnVmZmVyQ29uc3RydWN0b3JQYXJhbWV0ZXJzLFxuICBNTFRlbnNvckNvbnN0cnVjdG9yUGFyYW1ldGVycyxcbiAgVGVuc29yRnJvbUdwdUJ1ZmZlck9wdGlvbnMsXG4gIFRlbnNvckZyb21JbWFnZUJpdG1hcE9wdGlvbnMsXG4gIFRlbnNvckZyb21JbWFnZURhdGFPcHRpb25zLFxuICBUZW5zb3JGcm9tSW1hZ2VFbGVtZW50T3B0aW9ucyxcbiAgVGVuc29yRnJvbU1MVGVuc29yT3B0aW9ucyxcbiAgVGVuc29yRnJvbVRleHR1cmVPcHRpb25zLFxuICBUZW5zb3JGcm9tVXJsT3B0aW9ucyxcbiAgVGV4dHVyZUNvbnN0cnVjdG9yUGFyYW1ldGVycyxcbn0gZnJvbSAnLi90ZW5zb3ItZmFjdG9yeS5qcyc7XG5pbXBvcnQge1xuICBjaGVja1R5cGVkQXJyYXksXG4gIE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAsXG4gIE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAsXG4gIFN1cHBvcnRlZFR5cGVkQXJyYXksXG4gIFN1cHBvcnRlZFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnMsXG59IGZyb20gJy4vdGVuc29yLWltcGwtdHlwZS1tYXBwaW5nLmpzJztcbmltcG9ydCB7IGNhbGN1bGF0ZVNpemUsIHRlbnNvclJlc2hhcGUgfSBmcm9tICcuL3RlbnNvci11dGlscy1pbXBsLmpzJztcbmltcG9ydCB7IFRlbnNvciBhcyBUZW5zb3JJbnRlcmZhY2UgfSBmcm9tICcuL3RlbnNvci5qcyc7XG5cbi8vIHR5cGUgYWxpYXNlcyBmb3IgdGhvc2UgZXhwb3J0ZWQgZnJvbSBUZW5zb3IgaW50ZXJmYWNlXG5cbnR5cGUgVGVuc29yVHlwZSA9IFRlbnNvckludGVyZmFjZS5UeXBlO1xudHlwZSBUZW5zb3JEYXRhVHlwZSA9IFRlbnNvckludGVyZmFjZS5EYXRhVHlwZTtcbnR5cGUgVGVuc29yRGF0YUxvY2F0aW9uID0gVGVuc29ySW50ZXJmYWNlLkRhdGFMb2NhdGlvbjtcbnR5cGUgVGVuc29yVGV4dHVyZVR5cGUgPSBUZW5zb3JJbnRlcmZhY2UuVGV4dHVyZVR5cGU7XG50eXBlIFRlbnNvckdwdUJ1ZmZlclR5cGUgPSBUZW5zb3JJbnRlcmZhY2UuR3B1QnVmZmVyVHlwZTtcbnR5cGUgVGVuc29yTUxUZW5zb3JUeXBlID0gVGVuc29ySW50ZXJmYWNlLk1MVGVuc29yVHlwZTtcblxuLyoqXG4gKiB0aGUgaW1wbGVtZW50YXRpb24gb2YgVGVuc29yIGludGVyZmFjZS5cbiAqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjbGFzcyBUZW5zb3IgaW1wbGVtZW50cyBUZW5zb3JJbnRlcmZhY2Uge1xuICAvLyAjcmVnaW9uIGNvbnN0cnVjdG9yc1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgQ1BVIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gdHlwZSwgZGF0YSBhbmQgZGltcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIHR5cGU6IFRlbnNvclR5cGUsXG4gICAgZGF0YTogVGVuc29yRGF0YVR5cGUgfCBVaW50OENsYW1wZWRBcnJheSB8IHJlYWRvbmx5IHN0cmluZ1tdIHwgcmVhZG9ubHkgbnVtYmVyW10gfCByZWFkb25seSBib29sZWFuW10sXG4gICAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuICApO1xuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IENQVSB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuIFR5cGUgaXMgaW5mZXJyZWQgZnJvbSBkYXRhLlxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgZGF0YTogVGVuc29yRGF0YVR5cGUgfCBVaW50OENsYW1wZWRBcnJheSB8IHJlYWRvbmx5IHN0cmluZ1tdIHwgcmVhZG9ubHkgYm9vbGVhbltdLFxuICAgIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTtcbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIHBpbm5lZCBDUFUgZGF0YSB3aXRoIHRoZSBnaXZlbiB0eXBlIGFuZCBkaW1zLlxuICAgKlxuICAgKiBUZW5zb3IncyBsb2NhdGlvbiB3aWxsIGJlIHNldCB0byAnY3B1LXBpbm5lZCcuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBTcGVjaWZ5IHRoZSBwYXJhbWV0ZXJzIHRvIGNvbnN0cnVjdCB0aGUgdGVuc29yLlxuICAgKi9cbiAgY29uc3RydWN0b3IocGFyYW1zOiBDcHVQaW5uZWRDb25zdHJ1Y3RvclBhcmFtZXRlcnMpO1xuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgV2ViR0wgdGV4dHVyZSB3aXRoIHRoZSBnaXZlbiB0eXBlIGFuZCBkaW1zLlxuICAgKlxuICAgKiBUZW5zb3IncyBsb2NhdGlvbiB3aWxsIGJlIHNldCB0byAndGV4dHVyZScuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBTcGVjaWZ5IHRoZSBwYXJhbWV0ZXJzIHRvIGNvbnN0cnVjdCB0aGUgdGVuc29yLlxuICAgKi9cbiAgY29uc3RydWN0b3IocGFyYW1zOiBUZXh0dXJlQ29uc3RydWN0b3JQYXJhbWV0ZXJzKTtcbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIFdlYkdQVSBidWZmZXIgd2l0aCB0aGUgZ2l2ZW4gdHlwZSBhbmQgZGltcy5cbiAgICpcbiAgICogVGVuc29yJ3MgbG9jYXRpb24gd2lsbCBiZSBzZXQgdG8gJ2dwdS1idWZmZXInLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gU3BlY2lmeSB0aGUgcGFyYW1ldGVycyB0byBjb25zdHJ1Y3QgdGhlIHRlbnNvci5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHBhcmFtczogR3B1QnVmZmVyQ29uc3RydWN0b3JQYXJhbWV0ZXJzKTtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgV2ViTk4gTUxUZW5zb3Igd2l0aCB0aGUgZ2l2ZW4gdHlwZSBhbmQgZGltcy5cbiAgICpcbiAgICogVGVuc29yJ3MgbG9jYXRpb24gd2lsbCBiZSBzZXQgdG8gJ21sLXRlbnNvcicuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBTcGVjaWZ5IHRoZSBwYXJhbWV0ZXJzIHRvIGNvbnN0cnVjdCB0aGUgdGVuc29yLlxuICAgKi9cbiAgY29uc3RydWN0b3IocGFyYW1zOiBNTFRlbnNvckNvbnN0cnVjdG9yUGFyYW1ldGVycyk7XG5cbiAgLyoqXG4gICAqIGltcGxlbWVudGF0aW9uLlxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgYXJnMDpcbiAgICAgIHwgVGVuc29yVHlwZVxuICAgICAgfCBUZW5zb3JEYXRhVHlwZVxuICAgICAgfCBVaW50OENsYW1wZWRBcnJheVxuICAgICAgfCByZWFkb25seSBzdHJpbmdbXVxuICAgICAgfCByZWFkb25seSBib29sZWFuW11cbiAgICAgIHwgQ3B1UGlubmVkQ29uc3RydWN0b3JQYXJhbWV0ZXJzXG4gICAgICB8IFRleHR1cmVDb25zdHJ1Y3RvclBhcmFtZXRlcnNcbiAgICAgIHwgR3B1QnVmZmVyQ29uc3RydWN0b3JQYXJhbWV0ZXJzXG4gICAgICB8IE1MVGVuc29yQ29uc3RydWN0b3JQYXJhbWV0ZXJzLFxuICAgIGFyZzE/OiBUZW5zb3JEYXRhVHlwZSB8IFVpbnQ4Q2xhbXBlZEFycmF5IHwgcmVhZG9ubHkgbnVtYmVyW10gfCByZWFkb25seSBzdHJpbmdbXSB8IHJlYWRvbmx5IGJvb2xlYW5bXSxcbiAgICBhcmcyPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICkge1xuICAgIC8vIHBlcmZvcm0gb25lLXRpbWUgY2hlY2sgZm9yIEJpZ0ludC9GbG9hdDE2QXJyYXkgc3VwcG9ydFxuICAgIGNoZWNrVHlwZWRBcnJheSgpO1xuXG4gICAgbGV0IHR5cGU6IFRlbnNvclR5cGU7XG4gICAgbGV0IGRpbXM6IHJlYWRvbmx5IG51bWJlcltdO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcwID09PSAnb2JqZWN0JyAmJiAnbG9jYXRpb24nIGluIGFyZzApIHtcbiAgICAgIC8vXG4gICAgICAvLyBjb25zdHJ1Y3RpbmcgdGVuc29yIGZyb20gc3BlY2lmaWMgbG9jYXRpb25cbiAgICAgIC8vXG4gICAgICB0aGlzLmRhdGFMb2NhdGlvbiA9IGFyZzAubG9jYXRpb247XG4gICAgICB0eXBlID0gYXJnMC50eXBlO1xuICAgICAgZGltcyA9IGFyZzAuZGltcztcbiAgICAgIHN3aXRjaCAoYXJnMC5sb2NhdGlvbikge1xuICAgICAgICBjYXNlICdjcHUtcGlubmVkJzoge1xuICAgICAgICAgIGNvbnN0IGV4cGVjdGVkVHlwZWRBcnJheUNvbnN0cnVjdG9yID0gTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5nZXQodHlwZSk7XG4gICAgICAgICAgaWYgKCFleHBlY3RlZFR5cGVkQXJyYXlDb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZSBcIiR7dHlwZX1cIiB0byBjcmVhdGUgdGVuc29yIGZyb20gcGlubmVkIGJ1ZmZlcmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIShhcmcwLmRhdGEgaW5zdGFuY2VvZiBleHBlY3RlZFR5cGVkQXJyYXlDb25zdHJ1Y3RvcikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGJ1ZmZlciBzaG91bGQgYmUgb2YgdHlwZSAke2V4cGVjdGVkVHlwZWRBcnJheUNvbnN0cnVjdG9yLm5hbWV9YCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuY3B1RGF0YSA9IGFyZzAuZGF0YTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICd0ZXh0dXJlJzoge1xuICAgICAgICAgIGlmICh0eXBlICE9PSAnZmxvYXQzMicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgXCIke3R5cGV9XCIgdG8gY3JlYXRlIHRlbnNvciBmcm9tIHRleHR1cmVgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5ncHVUZXh0dXJlRGF0YSA9IGFyZzAudGV4dHVyZTtcbiAgICAgICAgICB0aGlzLmRvd25sb2FkZXIgPSBhcmcwLmRvd25sb2FkO1xuICAgICAgICAgIHRoaXMuZGlzcG9zZXIgPSBhcmcwLmRpc3Bvc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnZ3B1LWJ1ZmZlcic6IHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB0eXBlICE9PSAnZmxvYXQzMicgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdmbG9hdDE2JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2ludDMyJyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2ludDY0JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ3VpbnQzMicgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICd1aW50OCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdib29sJyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ3VpbnQ0JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2ludDQnXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGB1bnN1cHBvcnRlZCB0eXBlIFwiJHt0eXBlfVwiIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSBncHUgYnVmZmVyYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuZ3B1QnVmZmVyRGF0YSA9IGFyZzAuZ3B1QnVmZmVyO1xuICAgICAgICAgIHRoaXMuZG93bmxvYWRlciA9IGFyZzAuZG93bmxvYWQ7XG4gICAgICAgICAgdGhpcy5kaXNwb3NlciA9IGFyZzAuZGlzcG9zZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdtbC10ZW5zb3InOiB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdHlwZSAhPT0gJ2Zsb2F0MzInICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnZmxvYXQxNicgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdpbnQzMicgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdpbnQ2NCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICd1aW50MzInICYmXG4gICAgICAgICAgICB0eXBlICE9PSAndWludDY0JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2ludDgnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAndWludDgnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnYm9vbCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICd1aW50NCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdpbnQ0J1xuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZSBcIiR7dHlwZX1cIiB0byBjcmVhdGUgdGVuc29yIGZyb20gTUxUZW5zb3JgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5tbFRlbnNvckRhdGEgPSBhcmcwLm1sVGVuc29yO1xuICAgICAgICAgIHRoaXMuZG93bmxvYWRlciA9IGFyZzAuZG93bmxvYWQ7XG4gICAgICAgICAgdGhpcy5kaXNwb3NlciA9IGFyZzAuZGlzcG9zZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVGVuc29yIGNvbnN0cnVjdG9yOiB1bnN1cHBvcnRlZCBsb2NhdGlvbiAnJHt0aGlzLmRhdGFMb2NhdGlvbn0nYCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vXG4gICAgICAvLyBjb25zdHJ1Y3RpbmcgdGVuc29yIG9mIGxvY2F0aW9uICdjcHUnXG4gICAgICAvL1xuICAgICAgbGV0IGRhdGE6IFRlbnNvckRhdGFUeXBlO1xuICAgICAgbGV0IG1heWJlRGltczogdHlwZW9mIGFyZzEgfCB0eXBlb2YgYXJnMjtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgYXJnMCBpcyB0eXBlIG9yIGRhdGFcbiAgICAgIGlmICh0eXBlb2YgYXJnMCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgLy9cbiAgICAgICAgLy8gT3ZlcnJpZGU6IGNvbnN0cnVjdG9yKHR5cGUsIGRhdGEsIC4uLilcbiAgICAgICAgLy9cbiAgICAgICAgdHlwZSA9IGFyZzA7XG4gICAgICAgIG1heWJlRGltcyA9IGFyZzI7XG4gICAgICAgIGlmIChhcmcwID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIC8vIHN0cmluZyB0ZW5zb3JcbiAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoYXJnMSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJBIHN0cmluZyB0ZW5zb3IncyBkYXRhIG11c3QgYmUgYSBzdHJpbmcgYXJyYXkuXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyB3ZSBkb24ndCBjaGVjayB3aGV0aGVyIGV2ZXJ5IGVsZW1lbnQgaW4gdGhlIGFycmF5IGlzIHN0cmluZzsgdGhpcyBpcyB0b28gc2xvdy4gd2UgYXNzdW1lIGl0J3MgY29ycmVjdCBhbmRcbiAgICAgICAgICAvLyBlcnJvciB3aWxsIGJlIHBvcHVsYXRlZCBhdCBpbmZlcmVuY2VcbiAgICAgICAgICBkYXRhID0gYXJnMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBudW1lcmljIHRlbnNvclxuICAgICAgICAgIGNvbnN0IHR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAuZ2V0KGFyZzApO1xuICAgICAgICAgIGlmICh0eXBlZEFycmF5Q29uc3RydWN0b3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgVW5zdXBwb3J0ZWQgdGVuc29yIHR5cGU6ICR7YXJnMH0uYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGFyZzEpKSB7XG4gICAgICAgICAgICBpZiAoKGFyZzAgPT09ICdmbG9hdDE2JyAmJiB0eXBlZEFycmF5Q29uc3RydWN0b3IgPT09IFVpbnQxNkFycmF5KSB8fCBhcmcwID09PSAndWludDQnIHx8IGFyZzAgPT09ICdpbnQ0Jykge1xuICAgICAgICAgICAgICAvLyAtICdmbG9hdDE2JzpcbiAgICAgICAgICAgICAgLy8gICBXaGVuIG5vIEZsb2F0MTZBcnJheSBwb2x5ZmlsbCBpcyB1c2VkLCB3ZSBjYW5ub3QgY3JlYXRlICdmbG9hdDE2JyB0ZW5zb3IgZnJvbSBudW1iZXIgYXJyYXkuXG4gICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgIC8vICAgVGhyb3cgZXJyb3IgaGVyZSBiZWNhdXNlIHdoZW4gdXNlciB0cnkgdG8gdXNlIG51bWJlciBhcnJheSBhcyBkYXRhLFxuICAgICAgICAgICAgICAvLyAgIGUuZy4gbmV3IFRlbnNvcignZmxvYXQxNicsIFsxLCAyLCAzLCA0XSwgZGltcykpLCBpdCB3aWxsIGFjdHVhbGx5IGNhbGxcbiAgICAgICAgICAgICAgLy8gICBVaW50MTZBcnJheS5mcm9tKGFyZzEpIHdoaWNoIGdlbmVyYXRlcyB3cm9uZyBkYXRhLlxuICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAvLyAtICd1aW50NCcgYW5kICdpbnQ0JzpcbiAgICAgICAgICAgICAgLy8gICBVaW50OEFycmF5LmZyb20oYXJnMSkgd2lsbCBnZW5lcmF0ZSB3cm9uZyBkYXRhIGZvciAndWludDQnIGFuZCAnaW50NCcgdGVuc29yLlxuICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgIGBDcmVhdGluZyBhICR7YXJnMH0gdGVuc29yIGZyb20gbnVtYmVyIGFycmF5IGlzIG5vdCBzdXBwb3J0ZWQuIFBsZWFzZSB1c2UgJHt0eXBlZEFycmF5Q29uc3RydWN0b3IubmFtZX0gYXMgZGF0YS5gLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChhcmcwID09PSAndWludDY0JyB8fCBhcmcwID09PSAnaW50NjQnKSB7XG4gICAgICAgICAgICAgIC8vIHVzZSAnYXMgYW55JyBoZXJlIGJlY2F1c2U6XG4gICAgICAgICAgICAgIC8vIDEuIFR5cGVTY3JpcHQncyBjaGVjayBvbiB0eXBlIG9mICdBcnJheS5pc0FycmF5KCknIGRvZXMgbm90IHdvcmsgd2l0aCByZWFkb25seSBhcnJheXMuXG4gICAgICAgICAgICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vbWljcm9zb2Z0L1R5cGVTY3JpcHQvaXNzdWVzLzE3MDAyXG4gICAgICAgICAgICAgIC8vIDIuIFR5cGVTY3JpcHQncyBjaGVjayBvbiB1bmlvbiB0eXBlIG9mICcoQmlnSW50NjRBcnJheUNvbnN0cnVjdG9yfEJpZ1VpbnQ2NEFycmF5Q29uc3RydWN0b3IpLmZyb20oKSdcbiAgICAgICAgICAgICAgLy8gZG9lcyBub3QgYWNjZXB0IHBhcmFtZXRlciBtYXBGbi5cbiAgICAgICAgICAgICAgLy8gMy4gcGFyYW1ldGVycyBvZiAnU3VwcG9ydGVkVHlwZWRBcnJheUNvbnN0cnVjdG9ycy5mcm9tKCknIGRvZXMgbm90IG1hdGNoIHRoZSByZXF1aXJlbWVudCBvZiB0aGUgdW5pb25cbiAgICAgICAgICAgICAgLy8gdHlwZS5cblxuICAgICAgICAgICAgICAvLyBhc3N1bWUgJ2FyZzEnIGlzIG9mIHR5cGUgXCJyZWFkb25seSBudW1iZXJbXXxyZWFkb25seSBiaWdpbnRbXVwiIGhlcmUuXG5cbiAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAgICAgZGF0YSA9ICh0eXBlZEFycmF5Q29uc3RydWN0b3IgYXMgYW55KS5mcm9tKGFyZzEsIEJpZ0ludCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBhc3N1bWUgJ2FyZzEnIGlzIG9mIHR5cGUgXCJyZWFkb25seSBudW1iZXJbXVwiIGhlcmUuXG4gICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICAgIGRhdGEgPSAodHlwZWRBcnJheUNvbnN0cnVjdG9yIGFzIGFueSkuZnJvbShhcmcxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKGFyZzEgaW5zdGFuY2VvZiB0eXBlZEFycmF5Q29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgIGRhdGEgPSBhcmcxO1xuICAgICAgICAgIH0gZWxzZSBpZiAoYXJnMSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5KSB7XG4gICAgICAgICAgICBpZiAoYXJnMCA9PT0gJ3VpbnQ4Jykge1xuICAgICAgICAgICAgICBkYXRhID0gVWludDhBcnJheS5mcm9tKGFyZzEpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgQSBVaW50OENsYW1wZWRBcnJheSB0ZW5zb3IncyBkYXRhIG11c3QgYmUgdHlwZSBvZiB1aW50OGApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoYXJnMCA9PT0gJ2Zsb2F0MTYnICYmIGFyZzEgaW5zdGFuY2VvZiBVaW50MTZBcnJheSAmJiB0eXBlZEFycmF5Q29uc3RydWN0b3IgIT09IFVpbnQxNkFycmF5KSB7XG4gICAgICAgICAgICAvLyB3aGVuIEZsb2F0MTZBcnJheSBpcyBhdmFpbGFibGUgYW5kIGRhdGEgaXMgb2YgdHlwZSBVaW50MTZBcnJheS5cbiAgICAgICAgICAgIC8vIFdlIGFsbG93IFVpbnQxNkFycmF5IHRvIGJlIHBhc3NlZCBpbiBhcyBkYXRhIGZvciAnZmxvYXQxNicgdGVuc29yIHVudGlsIEZsb2F0MTZBcnJheSBpcyBnZW5lcmFsbHlcbiAgICAgICAgICAgIC8vIHN1cHBvcnRlZCBpbiBKYXZhU2NyaXB0IGVudmlyb25tZW50LlxuXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgICAgZGF0YSA9IG5ldyAoZ2xvYmFsVGhpcyBhcyBhbnkpLkZsb2F0MTZBcnJheShhcmcxLmJ1ZmZlciwgYXJnMS5ieXRlT2Zmc2V0LCBhcmcxLmxlbmd0aCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEEgJHt0eXBlfSB0ZW5zb3IncyBkYXRhIG11c3QgYmUgdHlwZSBvZiAke3R5cGVkQXJyYXlDb25zdHJ1Y3Rvcn1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vXG4gICAgICAgIC8vIE92ZXJyaWRlOiBjb25zdHJ1Y3RvcihkYXRhLCAuLi4pXG4gICAgICAgIC8vXG4gICAgICAgIG1heWJlRGltcyA9IGFyZzE7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGFyZzApKSB7XG4gICAgICAgICAgLy8gb25seSBib29sZWFuW10gYW5kIHN0cmluZ1tdIGlzIHN1cHBvcnRlZFxuICAgICAgICAgIGlmIChhcmcwLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVGVuc29yIHR5cGUgY2Fubm90IGJlIGluZmVycmVkIGZyb20gYW4gZW1wdHkgYXJyYXkuJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGZpcnN0RWxlbWVudFR5cGUgPSB0eXBlb2YgYXJnMFswXTtcbiAgICAgICAgICBpZiAoZmlyc3RFbGVtZW50VHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHR5cGUgPSAnc3RyaW5nJztcbiAgICAgICAgICAgIGRhdGEgPSBhcmcwO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZmlyc3RFbGVtZW50VHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICB0eXBlID0gJ2Jvb2wnO1xuICAgICAgICAgICAgLy8gJ2FyZzAnIGlzIG9mIHR5cGUgJ2Jvb2xlYW5bXScuIFVpbnQ4QXJyYXkuZnJvbShib29sZWFuW10pIGFjdHVhbGx5IHdvcmtzLCBidXQgdHlwZXNjcmlwdCB0aGlua3MgdGhpcyBpc1xuICAgICAgICAgICAgLy8gd3JvbmcgdHlwZS4gV2UgdXNlICdhcyBhbnknIHRvIG1ha2UgaXQgaGFwcHkuXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgICAgZGF0YSA9IFVpbnQ4QXJyYXkuZnJvbShhcmcwIGFzIGFueVtdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBlbGVtZW50IHR5cGUgb2YgZGF0YSBhcnJheTogJHtmaXJzdEVsZW1lbnRUeXBlfS5gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoYXJnMCBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5KSB7XG4gICAgICAgICAgdHlwZSA9ICd1aW50OCc7XG4gICAgICAgICAgZGF0YSA9IFVpbnQ4QXJyYXkuZnJvbShhcmcwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBnZXQgdGVuc29yIHR5cGUgZnJvbSBUeXBlZEFycmF5XG4gICAgICAgICAgY29uc3QgbWFwcGVkVHlwZSA9IE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAuZ2V0KFxuICAgICAgICAgICAgYXJnMC5jb25zdHJ1Y3RvciBhcyBTdXBwb3J0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3JzLFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKG1hcHBlZFR5cGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgVW5zdXBwb3J0ZWQgdHlwZSBmb3IgdGVuc29yIGRhdGE6ICR7YXJnMC5jb25zdHJ1Y3Rvcn0uYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHR5cGUgPSBtYXBwZWRUeXBlO1xuICAgICAgICAgIGRhdGEgPSBhcmcwIGFzIFN1cHBvcnRlZFR5cGVkQXJyYXk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gdHlwZSBhbmQgZGF0YSBpcyBwcm9jZXNzZWQsIG5vdyBwcm9jZXNzaW5nIGRpbXNcbiAgICAgIGlmIChtYXliZURpbXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyBhc3N1bWUgMS1EIHRlbnNvciBpZiBkaW1zIG9taXR0ZWRcbiAgICAgICAgbWF5YmVEaW1zID0gW2RhdGEubGVuZ3RoXTtcbiAgICAgIH0gZWxzZSBpZiAoIUFycmF5LmlzQXJyYXkobWF5YmVEaW1zKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQSB0ZW5zb3IncyBkaW1zIG11c3QgYmUgYSBudW1iZXIgYXJyYXlcIik7XG4gICAgICB9XG4gICAgICBkaW1zID0gbWF5YmVEaW1zIGFzIHJlYWRvbmx5IG51bWJlcltdO1xuXG4gICAgICB0aGlzLmNwdURhdGEgPSBkYXRhO1xuICAgICAgdGhpcy5kYXRhTG9jYXRpb24gPSAnY3B1JztcbiAgICB9XG5cbiAgICAvLyBwZXJmb3JtIGNoZWNrIG9uIGRpbXNcbiAgICBjb25zdCBzaXplID0gY2FsY3VsYXRlU2l6ZShkaW1zKTtcbiAgICAvLyBpZiBkYXRhIGlzIG9uIENQVSwgY2hlY2sgd2hldGhlciBkYXRhIGxlbmd0aCBtYXRjaGVzIHRlbnNvciBzaXplXG4gICAgaWYgKHRoaXMuY3B1RGF0YSAmJiBzaXplICE9PSB0aGlzLmNwdURhdGEubGVuZ3RoKSB7XG4gICAgICBpZiAoKHR5cGUgPT09ICd1aW50NCcgfHwgdHlwZSA9PT0gJ2ludDQnKSAmJiBNYXRoLmNlaWwoc2l6ZSAvIDIpID09PSB0aGlzLmNwdURhdGEubGVuZ3RoKSB7XG4gICAgICAgIC8vIGZvciAodSlpbnQ0LCB0aGUgZGF0YSBsZW5ndGggaXMgaGFsZiBvZiB0aGUgdGVuc29yIHNpemUuIFNvIHdlIGNoZWNrIHRoaXMgc3BlY2lhbCBjYXNlIHdoZW4gc2l6ZSBpcyBvZGQuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRlbnNvcidzIHNpemUoJHtzaXplfSkgZG9lcyBub3QgbWF0Y2ggZGF0YSBsZW5ndGgoJHt0aGlzLmNwdURhdGEubGVuZ3RofSkuYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLmRpbXMgPSBkaW1zO1xuICAgIHRoaXMuc2l6ZSA9IHNpemU7XG4gIH1cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gZmFjdG9yeVxuICBzdGF0aWMgYXN5bmMgZnJvbUltYWdlKFxuICAgIGltYWdlOiBJbWFnZURhdGEgfCBIVE1MSW1hZ2VFbGVtZW50IHwgSW1hZ2VCaXRtYXAgfCBzdHJpbmcsXG4gICAgb3B0aW9ucz86XG4gICAgICB8IFRlbnNvckZyb21JbWFnZURhdGFPcHRpb25zXG4gICAgICB8IFRlbnNvckZyb21JbWFnZUVsZW1lbnRPcHRpb25zXG4gICAgICB8IFRlbnNvckZyb21JbWFnZUJpdG1hcE9wdGlvbnNcbiAgICAgIHwgVGVuc29yRnJvbVVybE9wdGlvbnMsXG4gICk6IFByb21pc2U8VGVuc29ySW50ZXJmYWNlPiB7XG4gICAgcmV0dXJuIHRlbnNvckZyb21JbWFnZShpbWFnZSwgb3B0aW9ucyk7XG4gIH1cblxuICBzdGF0aWMgZnJvbVRleHR1cmU8VCBleHRlbmRzIFRlbnNvckludGVyZmFjZS5UZXh0dXJlRGF0YVR5cGVzPihcbiAgICB0ZXh0dXJlOiBUZW5zb3JUZXh0dXJlVHlwZSxcbiAgICBvcHRpb25zOiBUZW5zb3JGcm9tVGV4dHVyZU9wdGlvbnM8VD4sXG4gICk6IFRlbnNvckludGVyZmFjZSB7XG4gICAgcmV0dXJuIHRlbnNvckZyb21UZXh0dXJlKHRleHR1cmUsIG9wdGlvbnMpO1xuICB9XG5cbiAgc3RhdGljIGZyb21HcHVCdWZmZXI8VCBleHRlbmRzIFRlbnNvckludGVyZmFjZS5HcHVCdWZmZXJEYXRhVHlwZXM+KFxuICAgIGdwdUJ1ZmZlcjogVGVuc29yR3B1QnVmZmVyVHlwZSxcbiAgICBvcHRpb25zOiBUZW5zb3JGcm9tR3B1QnVmZmVyT3B0aW9uczxUPixcbiAgKTogVGVuc29ySW50ZXJmYWNlIHtcbiAgICByZXR1cm4gdGVuc29yRnJvbUdwdUJ1ZmZlcihncHVCdWZmZXIsIG9wdGlvbnMpO1xuICB9XG5cbiAgc3RhdGljIGZyb21NTFRlbnNvcjxUIGV4dGVuZHMgVGVuc29ySW50ZXJmYWNlLk1MVGVuc29yRGF0YVR5cGVzPihcbiAgICBtbFRlbnNvcjogVGVuc29yTUxUZW5zb3JUeXBlLFxuICAgIG9wdGlvbnM6IFRlbnNvckZyb21NTFRlbnNvck9wdGlvbnM8VD4sXG4gICk6IFRlbnNvckludGVyZmFjZSB7XG4gICAgcmV0dXJuIHRlbnNvckZyb21NTFRlbnNvcihtbFRlbnNvciwgb3B0aW9ucyk7XG4gIH1cblxuICBzdGF0aWMgZnJvbVBpbm5lZEJ1ZmZlcjxUIGV4dGVuZHMgVGVuc29ySW50ZXJmYWNlLkNwdVBpbm5lZERhdGFUeXBlcz4oXG4gICAgdHlwZTogVCxcbiAgICBidWZmZXI6IFRlbnNvckludGVyZmFjZS5EYXRhVHlwZU1hcFtUXSxcbiAgICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk6IFRlbnNvciB7XG4gICAgcmV0dXJuIHRlbnNvckZyb21QaW5uZWRCdWZmZXIodHlwZSwgYnVmZmVyLCBkaW1zKTtcbiAgfVxuXG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIGNvbnZlcnNpb25zXG4gIHRvRGF0YVVSTChvcHRpb25zPzogVGVuc29yVG9EYXRhVXJsT3B0aW9ucyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRlbnNvclRvRGF0YVVSTCh0aGlzLCBvcHRpb25zKTtcbiAgfVxuXG4gIHRvSW1hZ2VEYXRhKG9wdGlvbnM/OiBUZW5zb3JUb0ltYWdlRGF0YU9wdGlvbnMpOiBJbWFnZURhdGEge1xuICAgIHJldHVybiB0ZW5zb3JUb0ltYWdlRGF0YSh0aGlzLCBvcHRpb25zKTtcbiAgfVxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBwdWJsaWMgZmllbGRzXG4gIHJlYWRvbmx5IGRpbXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSB0eXBlOiBUZW5zb3JUeXBlO1xuICByZWFkb25seSBzaXplOiBudW1iZXI7XG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIHByaXZhdGUgZmllbGRzXG5cbiAgLyoqXG4gICAqIHN0b3JlcyB0aGUgbG9jYXRpb24gb2YgdGhlIGRhdGEuXG4gICAqL1xuICBwcml2YXRlIGRhdGFMb2NhdGlvbjogVGVuc29yRGF0YUxvY2F0aW9uO1xuXG4gIC8qKlxuICAgKiBzdG9yZXMgdGhlIGRhdGEgb24gQ1BVLCBpZiBsb2NhdGlvbiBpcyAnY3B1JyBvciAnY3B1LXBpbm5lZCcuIG90aGVyd2lzZSBlbXB0eS5cbiAgICovXG4gIHByaXZhdGUgY3B1RGF0YT86IFRlbnNvckRhdGFUeXBlO1xuXG4gIC8qKlxuICAgKiBzdG9yZXMgdGhlIHVuZGVybHlpbmcgdGV4dHVyZSB3aGVuIGxvY2F0aW9uIGlzICd0ZXh0dXJlJy4gb3RoZXJ3aXNlIGVtcHR5LlxuICAgKi9cbiAgcHJpdmF0ZSBncHVUZXh0dXJlRGF0YT86IFRlbnNvclRleHR1cmVUeXBlO1xuXG4gIC8qKlxuICAgKiBzdG9yZXMgdGhlIHVuZGVybHlpbmcgR1BVIGJ1ZmZlciB3aGVuIGxvY2F0aW9uIGlzICdncHUtYnVmZmVyJy4gb3RoZXJ3aXNlIGVtcHR5LlxuICAgKi9cbiAgcHJpdmF0ZSBncHVCdWZmZXJEYXRhPzogVGVuc29yR3B1QnVmZmVyVHlwZTtcblxuICAvKipcbiAgICogc3RvcmVzIHRoZSB1bmRlcmx5aW5nIFdlYk5OIE1MVGVuc29yIHdoZW4gbG9jYXRpb24gaXMgJ21sLXRlbnNvcicuIG90aGVyd2lzZSBlbXB0eS5cbiAgICovXG4gIHByaXZhdGUgbWxUZW5zb3JEYXRhPzogVGVuc29yTUxUZW5zb3JUeXBlO1xuXG4gIC8qKlxuICAgKiBzdG9yZXMgYW4gb3B0aW9uYWwgZG93bmxvYWRlciBmdW5jdGlvbiB0byBkb3dubG9hZCBkYXRhIGZyb20gR1BVIHRvIENQVS5cbiAgICovXG4gIHByaXZhdGUgZG93bmxvYWRlcj8oKTogUHJvbWlzZTxUZW5zb3JEYXRhVHlwZT47XG5cbiAgLyoqXG4gICAqIGEgZmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIGRhdGEgaXMgYmVpbmcgZG93bmxvYWRlZCBmcm9tIEdQVSB0byBDUFUuXG4gICAqL1xuICBwcml2YXRlIGlzRG93bmxvYWRpbmc/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBzdG9yZXMgYW4gb3B0aW9uYWwgZGlzcG9zZXIgZnVuY3Rpb24gdG8gZGlzcG9zZSB0aGUgdW5kZXJseWluZyBkYXRhLlxuICAgKi9cbiAgcHJpdmF0ZSBkaXNwb3Nlcj8oKTogdm9pZDtcbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gcHJvcGVydGllc1xuICBnZXQgZGF0YSgpOiBUZW5zb3JEYXRhVHlwZSB7XG4gICAgdGhpcy5lbnN1cmVWYWxpZCgpO1xuICAgIGlmICghdGhpcy5jcHVEYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdUaGUgZGF0YSBpcyBub3Qgb24gQ1BVLiBVc2UgYGdldERhdGEoKWAgdG8gZG93bmxvYWQgR1BVIGRhdGEgdG8gQ1BVLCAnICtcbiAgICAgICAgICAnb3IgdXNlIGB0ZXh0dXJlYCBvciBgZ3B1QnVmZmVyYCBwcm9wZXJ0eSB0byBhY2Nlc3MgdGhlIEdQVSBkYXRhIGRpcmVjdGx5LicsXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jcHVEYXRhO1xuICB9XG5cbiAgZ2V0IGxvY2F0aW9uKCk6IFRlbnNvckRhdGFMb2NhdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YUxvY2F0aW9uO1xuICB9XG5cbiAgZ2V0IHRleHR1cmUoKTogVGVuc29yVGV4dHVyZVR5cGUge1xuICAgIHRoaXMuZW5zdXJlVmFsaWQoKTtcbiAgICBpZiAoIXRoaXMuZ3B1VGV4dHVyZURhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGRhdGEgaXMgbm90IHN0b3JlZCBhcyBhIFdlYkdMIHRleHR1cmUuJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdwdVRleHR1cmVEYXRhO1xuICB9XG5cbiAgZ2V0IGdwdUJ1ZmZlcigpOiBUZW5zb3JHcHVCdWZmZXJUeXBlIHtcbiAgICB0aGlzLmVuc3VyZVZhbGlkKCk7XG4gICAgaWYgKCF0aGlzLmdwdUJ1ZmZlckRhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGRhdGEgaXMgbm90IHN0b3JlZCBhcyBhIFdlYkdQVSBidWZmZXIuJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdwdUJ1ZmZlckRhdGE7XG4gIH1cblxuICBnZXQgbWxUZW5zb3IoKTogVGVuc29yTUxUZW5zb3JUeXBlIHtcbiAgICB0aGlzLmVuc3VyZVZhbGlkKCk7XG4gICAgaWYgKCF0aGlzLm1sVGVuc29yRGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViTk4gTUxUZW5zb3IuJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm1sVGVuc29yRGF0YTtcbiAgfVxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBtZXRob2RzXG5cbiAgYXN5bmMgZ2V0RGF0YShyZWxlYXNlRGF0YT86IGJvb2xlYW4pOiBQcm9taXNlPFRlbnNvckRhdGFUeXBlPiB7XG4gICAgdGhpcy5lbnN1cmVWYWxpZCgpO1xuICAgIHN3aXRjaCAodGhpcy5kYXRhTG9jYXRpb24pIHtcbiAgICAgIGNhc2UgJ2NwdSc6XG4gICAgICBjYXNlICdjcHUtcGlubmVkJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0YTtcbiAgICAgIGNhc2UgJ3RleHR1cmUnOlxuICAgICAgY2FzZSAnZ3B1LWJ1ZmZlcic6XG4gICAgICBjYXNlICdtbC10ZW5zb3InOiB7XG4gICAgICAgIGlmICghdGhpcy5kb3dubG9hZGVyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgY3VycmVudCB0ZW5zb3IgaXMgbm90IGNyZWF0ZWQgd2l0aCBhIHNwZWNpZmllZCBkYXRhIGRvd25sb2FkZXIuJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNEb3dubG9hZGluZykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGN1cnJlbnQgdGVuc29yIGlzIGJlaW5nIGRvd25sb2FkZWQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0aGlzLmlzRG93bmxvYWRpbmcgPSB0cnVlO1xuICAgICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLmRvd25sb2FkZXIoKTtcbiAgICAgICAgICB0aGlzLmRvd25sb2FkZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgdGhpcy5kYXRhTG9jYXRpb24gPSAnY3B1JztcbiAgICAgICAgICB0aGlzLmNwdURhdGEgPSBkYXRhO1xuXG4gICAgICAgICAgaWYgKHJlbGVhc2VEYXRhICYmIHRoaXMuZGlzcG9zZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcG9zZXIoKTtcbiAgICAgICAgICAgIHRoaXMuZGlzcG9zZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgdGhpcy5pc0Rvd25sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2Fubm90IGdldCBkYXRhIGZyb20gbG9jYXRpb246ICR7dGhpcy5kYXRhTG9jYXRpb259YCk7XG4gICAgfVxuICB9XG5cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc0Rvd25sb2FkaW5nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjdXJyZW50IHRlbnNvciBpcyBiZWluZyBkb3dubG9hZGVkLicpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRpc3Bvc2VyKSB7XG4gICAgICB0aGlzLmRpc3Bvc2VyKCk7XG4gICAgICB0aGlzLmRpc3Bvc2VyID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0aGlzLmNwdURhdGEgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5ncHVUZXh0dXJlRGF0YSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmdwdUJ1ZmZlckRhdGEgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5tbFRlbnNvckRhdGEgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5kb3dubG9hZGVyID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuaXNEb3dubG9hZGluZyA9IHVuZGVmaW5lZDtcblxuICAgIHRoaXMuZGF0YUxvY2F0aW9uID0gJ25vbmUnO1xuICB9XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gdGVuc29yIHV0aWxpdGllc1xuICBwcml2YXRlIGVuc3VyZVZhbGlkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRhdGFMb2NhdGlvbiA9PT0gJ25vbmUnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSB0ZW5zb3IgaXMgZGlzcG9zZWQuJyk7XG4gICAgfVxuICB9XG5cbiAgcmVzaGFwZShkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IFRlbnNvckludGVyZmFjZSB7XG4gICAgdGhpcy5lbnN1cmVWYWxpZCgpO1xuICAgIGlmICh0aGlzLmRvd25sb2FkZXIgfHwgdGhpcy5kaXNwb3Nlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgcmVzaGFwZSBhIHRlbnNvciB0aGF0IG93bnMgR1BVIHJlc291cmNlLicpO1xuICAgIH1cbiAgICByZXR1cm4gdGVuc29yUmVzaGFwZSh0aGlzLCBkaW1zKTtcbiAgfVxuICAvLyAjZW5kcmVnaW9uXG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvckZhY3RvcnkgfSBmcm9tICcuL3RlbnNvci1mYWN0b3J5LmpzJztcbmltcG9ydCB7IFRlbnNvciBhcyBUZW5zb3JJbXBsIH0gZnJvbSAnLi90ZW5zb3ItaW1wbC5qcyc7XG5pbXBvcnQgeyBUeXBlZFRlbnNvclV0aWxzIH0gZnJvbSAnLi90ZW5zb3ItdXRpbHMuanMnO1xuaW1wb3J0IHsgVHJ5R2V0R2xvYmFsVHlwZSB9IGZyb20gJy4vdHlwZS1oZWxwZXIuanMnO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVkZWNsYXJlICovXG5cbi8qKlxuICogcmVwcmVzZW50IGEgYmFzaWMgdGVuc29yIHdpdGggc3BlY2lmaWVkIGRpbWVuc2lvbnMgYW5kIGRhdGEgdHlwZS5cbiAqL1xuaW50ZXJmYWNlIFR5cGVkVGVuc29yQmFzZTxUIGV4dGVuZHMgVGVuc29yLlR5cGU+IHtcbiAgLyoqXG4gICAqIEdldCB0aGUgZGltZW5zaW9ucyBvZiB0aGUgdGVuc29yLlxuICAgKi9cbiAgcmVhZG9ubHkgZGltczogcmVhZG9ubHkgbnVtYmVyW107XG4gIC8qKlxuICAgKiBHZXQgdGhlIGRhdGEgdHlwZSBvZiB0aGUgdGVuc29yLlxuICAgKi9cbiAgcmVhZG9ubHkgdHlwZTogVDtcbiAgLyoqXG4gICAqIEdldCB0aGUgYnVmZmVyIGRhdGEgb2YgdGhlIHRlbnNvci5cbiAgICpcbiAgICogSWYgdGhlIGRhdGEgaXMgbm90IG9uIENQVSAoZWcuIGl0J3MgaW4gdGhlIGZvcm0gb2YgV2ViR0wgdGV4dHVyZSBvciBXZWJHUFUgYnVmZmVyKSwgdGhyb3cgZXJyb3IuXG4gICAqL1xuICByZWFkb25seSBkYXRhOiBUZW5zb3IuRGF0YVR5cGVNYXBbVF07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGxvY2F0aW9uIG9mIHRoZSBkYXRhLlxuICAgKi9cbiAgcmVhZG9ubHkgbG9jYXRpb246IFRlbnNvci5EYXRhTG9jYXRpb247XG4gIC8qKlxuICAgKiBHZXQgdGhlIFdlYkdMIHRleHR1cmUgdGhhdCBob2xkcyB0aGUgdGVuc29yIGRhdGEuXG4gICAqXG4gICAqIElmIHRoZSBkYXRhIGlzIG5vdCBvbiBHUFUgYXMgV2ViR0wgdGV4dHVyZSwgdGhyb3cgZXJyb3IuXG4gICAqL1xuICByZWFkb25seSB0ZXh0dXJlOiBUZW5zb3IuVGV4dHVyZVR5cGU7XG4gIC8qKlxuICAgKiBHZXQgdGhlIFdlYkdQVSBidWZmZXIgdGhhdCBob2xkcyB0aGUgdGVuc29yIGRhdGEuXG4gICAqXG4gICAqIElmIHRoZSBkYXRhIGlzIG5vdCBvbiBHUFUgYXMgV2ViR1BVIGJ1ZmZlciwgdGhyb3cgZXJyb3IuXG4gICAqL1xuICByZWFkb25seSBncHVCdWZmZXI6IFRlbnNvci5HcHVCdWZmZXJUeXBlO1xuXG4gIC8qKlxuICAgKiBHZXQgdGhlIFdlYk5OIE1MVGVuc29yIHRoYXQgaG9sZHMgdGhlIHRlbnNvciBkYXRhLlxuICAgKlxuICAgKiBJZiB0aGUgZGF0YSBpcyBub3QgaW4gYSBXZWJOTiBNTFRlbnNvciwgdGhyb3cgZXJyb3IuXG4gICAqL1xuICByZWFkb25seSBtbFRlbnNvcjogVGVuc29yLk1MVGVuc29yVHlwZTtcblxuICAvKipcbiAgICogR2V0IHRoZSBidWZmZXIgZGF0YSBvZiB0aGUgdGVuc29yLlxuICAgKlxuICAgKiBJZiB0aGUgZGF0YSBpcyBvbiBDUFUsIHJldHVybnMgdGhlIGRhdGEgaW1tZWRpYXRlbHkuXG4gICAqIElmIHRoZSBkYXRhIGlzIG9uIEdQVSwgZG93bmxvYWRzIHRoZSBkYXRhIGFuZCByZXR1cm5zIHRoZSBwcm9taXNlLlxuICAgKlxuICAgKiBAcGFyYW0gcmVsZWFzZURhdGEgLSB3aGV0aGVyIHJlbGVhc2UgdGhlIGRhdGEgb24gR1BVLiBJZ25vcmUgaWYgZGF0YSBpcyBhbHJlYWR5IG9uIENQVS5cbiAgICovXG4gIGdldERhdGEocmVsZWFzZURhdGE/OiBib29sZWFuKTogUHJvbWlzZTxUZW5zb3IuRGF0YVR5cGVNYXBbVF0+O1xuXG4gIC8qKlxuICAgKiBEaXNwb3NlIHRoZSB0ZW5zb3IgZGF0YS5cbiAgICpcbiAgICogSWYgdGhlIGRhdGEgaXMgb24gQ1BVLCByZW1vdmUgaXRzIGludGVybmFsIHJlZmVyZW5jZSB0byB0aGUgdW5kZXJseWluZyBkYXRhLlxuICAgKiBJZiB0aGUgZGF0YSBpcyBvbiBHUFUsIHJlbGVhc2UgdGhlIGRhdGEgb24gR1BVLlxuICAgKlxuICAgKiBBZnRlciBjYWxsaW5nIHRoaXMgZnVuY3Rpb24sIHRoZSB0ZW5zb3IgaXMgY29uc2lkZXJlZCBubyBsb25nZXIgdmFsaWQuIEl0cyBsb2NhdGlvbiB3aWxsIGJlIHNldCB0byAnbm9uZScuXG4gICAqL1xuICBkaXNwb3NlKCk6IHZvaWQ7XG59XG5cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBUZW5zb3Ige1xuICBpbnRlcmZhY2UgRGF0YVR5cGVNYXAge1xuICAgIGZsb2F0MzI6IEZsb2F0MzJBcnJheTtcbiAgICB1aW50ODogVWludDhBcnJheTtcbiAgICBpbnQ4OiBJbnQ4QXJyYXk7XG4gICAgdWludDE2OiBVaW50MTZBcnJheTtcbiAgICBpbnQxNjogSW50MTZBcnJheTtcbiAgICBpbnQzMjogSW50MzJBcnJheTtcbiAgICBpbnQ2NDogQmlnSW50NjRBcnJheTtcbiAgICBzdHJpbmc6IHN0cmluZ1tdO1xuICAgIGJvb2w6IFVpbnQ4QXJyYXk7XG4gICAgZmxvYXQxNjogVWludDE2QXJyYXk7IC8vIEtlZXAgdXNpbmcgVWludDE2QXJyYXkgdW50aWwgd2UgaGF2ZSBhIGNvbmNyZXRlIHNvbHV0aW9uIGZvciBmbG9hdCAxNi5cbiAgICBmbG9hdDY0OiBGbG9hdDY0QXJyYXk7XG4gICAgdWludDMyOiBVaW50MzJBcnJheTtcbiAgICB1aW50NjQ6IEJpZ1VpbnQ2NEFycmF5O1xuICAgIC8vIGNvbXBsZXg2NDogbmV2ZXI7XG4gICAgLy8gY29tcGxleDEyODogbmV2ZXI7XG4gICAgLy8gYmZsb2F0MTY6IG5ldmVyO1xuICAgIHVpbnQ0OiBVaW50OEFycmF5O1xuICAgIGludDQ6IEludDhBcnJheTtcbiAgfVxuXG4gIGludGVyZmFjZSBFbGVtZW50VHlwZU1hcCB7XG4gICAgZmxvYXQzMjogbnVtYmVyO1xuICAgIHVpbnQ4OiBudW1iZXI7XG4gICAgaW50ODogbnVtYmVyO1xuICAgIHVpbnQxNjogbnVtYmVyO1xuICAgIGludDE2OiBudW1iZXI7XG4gICAgaW50MzI6IG51bWJlcjtcbiAgICBpbnQ2NDogYmlnaW50O1xuICAgIHN0cmluZzogc3RyaW5nO1xuICAgIGJvb2w6IGJvb2xlYW47XG4gICAgZmxvYXQxNjogbnVtYmVyOyAvLyBLZWVwIHVzaW5nIFVpbnQxNkFycmF5IHVudGlsIHdlIGhhdmUgYSBjb25jcmV0ZSBzb2x1dGlvbiBmb3IgZmxvYXQgMTYuXG4gICAgZmxvYXQ2NDogbnVtYmVyO1xuICAgIHVpbnQzMjogbnVtYmVyO1xuICAgIHVpbnQ2NDogYmlnaW50O1xuICAgIC8vIGNvbXBsZXg2NDogbmV2ZXI7XG4gICAgLy8gY29tcGxleDEyODogbmV2ZXI7XG4gICAgLy8gYmZsb2F0MTY6IG5ldmVyO1xuICAgIHVpbnQ0OiBudW1iZXI7XG4gICAgaW50NDogbnVtYmVyO1xuICB9XG5cbiAgdHlwZSBEYXRhVHlwZSA9IERhdGFUeXBlTWFwW1R5cGVdO1xuICB0eXBlIEVsZW1lbnRUeXBlID0gRWxlbWVudFR5cGVNYXBbVHlwZV07XG5cbiAgLyoqXG4gICAqIHN1cHBvcnRlZCBkYXRhIHR5cGVzIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIHBpbm5lZCBDUFUgYnVmZmVyXG4gICAqL1xuICBleHBvcnQgdHlwZSBDcHVQaW5uZWREYXRhVHlwZXMgPSBFeGNsdWRlPFRlbnNvci5UeXBlLCAnc3RyaW5nJz47XG5cbiAgLyoqXG4gICAqIHR5cGUgYWxpYXMgZm9yIFdlYkdMIHRleHR1cmVcbiAgICovXG4gIGV4cG9ydCB0eXBlIFRleHR1cmVUeXBlID0gV2ViR0xUZXh0dXJlO1xuXG4gIC8qKlxuICAgKiBzdXBwb3J0ZWQgZGF0YSB0eXBlcyBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBXZWJHTCB0ZXh0dXJlXG4gICAqL1xuICBleHBvcnQgdHlwZSBUZXh0dXJlRGF0YVR5cGVzID0gJ2Zsb2F0MzInO1xuXG4gIHR5cGUgR3B1QnVmZmVyVHlwZUZhbGxiYWNrID0geyBzaXplOiBudW1iZXI7IG1hcFN0YXRlOiAndW5tYXBwZWQnIHwgJ3BlbmRpbmcnIHwgJ21hcHBlZCcgfTtcbiAgLyoqXG4gICAqIHR5cGUgYWxpYXMgZm9yIFdlYkdQVSBidWZmZXJcbiAgICovXG4gIGV4cG9ydCB0eXBlIEdwdUJ1ZmZlclR5cGUgPSBUcnlHZXRHbG9iYWxUeXBlPCdHUFVCdWZmZXInLCBHcHVCdWZmZXJUeXBlRmFsbGJhY2s+O1xuXG4gIHR5cGUgTUxUZW5zb3JUeXBlRmFsbGJhY2sgPSB7IGRlc3Ryb3koKTogdm9pZCB9O1xuICAvKipcbiAgICogdHlwZSBhbGlhcyBmb3IgV2ViTk4gTUxUZW5zb3JcbiAgICpcbiAgICogVGhlIHNwZWNpZmljYXRpb24gZm9yIFdlYk5OJ3MgTUxUZW5zb3IgaXMgY3VycmVudGx5IGluIGZsdXguXG4gICAqL1xuICBleHBvcnQgdHlwZSBNTFRlbnNvclR5cGUgPSBUcnlHZXRHbG9iYWxUeXBlPCdNTFRlbnNvcicsIE1MVGVuc29yVHlwZUZhbGxiYWNrPjtcblxuICAvKipcbiAgICogc3VwcG9ydGVkIGRhdGEgdHlwZXMgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgV2ViR1BVIGJ1ZmZlclxuICAgKi9cbiAgZXhwb3J0IHR5cGUgR3B1QnVmZmVyRGF0YVR5cGVzID0gJ2Zsb2F0MzInIHwgJ2Zsb2F0MTYnIHwgJ2ludDMyJyB8ICdpbnQ2NCcgfCAndWludDMyJyB8ICd1aW50OCcgfCAnYm9vbCc7XG5cbiAgLyoqXG4gICAqIHN1cHBvcnRlZCBkYXRhIHR5cGVzIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIFdlYk5OIE1MVGVuc29yXG4gICAqL1xuICBleHBvcnQgdHlwZSBNTFRlbnNvckRhdGFUeXBlcyA9XG4gICAgfCAnZmxvYXQzMidcbiAgICB8ICdmbG9hdDE2J1xuICAgIHwgJ2ludDgnXG4gICAgfCAndWludDgnXG4gICAgfCAnaW50MzInXG4gICAgfCAndWludDMyJ1xuICAgIHwgJ2ludDY0J1xuICAgIHwgJ3VpbnQ2NCdcbiAgICB8ICdib29sJ1xuICAgIHwgJ3VpbnQ0J1xuICAgIHwgJ2ludDQnO1xuXG4gIC8qKlxuICAgKiByZXByZXNlbnQgd2hlcmUgdGhlIHRlbnNvciBkYXRhIGlzIHN0b3JlZFxuICAgKi9cbiAgZXhwb3J0IHR5cGUgRGF0YUxvY2F0aW9uID0gJ25vbmUnIHwgJ2NwdScgfCAnY3B1LXBpbm5lZCcgfCAndGV4dHVyZScgfCAnZ3B1LWJ1ZmZlcicgfCAnbWwtdGVuc29yJztcblxuICAvKipcbiAgICogcmVwcmVzZW50IHRoZSBkYXRhIHR5cGUgb2YgYSB0ZW5zb3JcbiAgICovXG4gIGV4cG9ydCB0eXBlIFR5cGUgPSBrZXlvZiBEYXRhVHlwZU1hcDtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnQgbXVsdGktZGltZW5zaW9uYWwgYXJyYXlzIHRvIGZlZWQgdG8gb3IgZmV0Y2ggZnJvbSBtb2RlbCBpbmZlcmVuY2luZy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUeXBlZFRlbnNvcjxUIGV4dGVuZHMgVGVuc29yLlR5cGU+IGV4dGVuZHMgVHlwZWRUZW5zb3JCYXNlPFQ+LCBUeXBlZFRlbnNvclV0aWxzPFQ+IHt9XG4vKipcbiAqIFJlcHJlc2VudCBtdWx0aS1kaW1lbnNpb25hbCBhcnJheXMgdG8gZmVlZCB0byBvciBmZXRjaCBmcm9tIG1vZGVsIGluZmVyZW5jaW5nLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvciBleHRlbmRzIFR5cGVkVGVuc29yQmFzZTxUZW5zb3IuVHlwZT4sIFR5cGVkVGVuc29yVXRpbHM8VGVuc29yLlR5cGU+IHt9XG5cbi8qKlxuICogdHlwZSBUZW5zb3JDb25zdHJ1Y3RvciBkZWZpbmVzIHRoZSBjb25zdHJ1Y3RvcnMgb2YgJ1RlbnNvcicgdG8gY3JlYXRlIENQVSB0ZW5zb3IgaW5zdGFuY2VzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckNvbnN0cnVjdG9yIGV4dGVuZHMgVGVuc29yRmFjdG9yeSB7XG4gIC8vICNyZWdpb24gQ1BVIHRlbnNvciAtIHNwZWNpZnkgZWxlbWVudCB0eXBlXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgc3RyaW5nIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gdHlwZSwgZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgLSBTcGVjaWZ5IHRoZSBlbGVtZW50IHR5cGUuXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoXG4gICAgdHlwZTogJ3N0cmluZycsXG4gICAgZGF0YTogVGVuc29yLkRhdGFUeXBlTWFwWydzdHJpbmcnXSB8IHJlYWRvbmx5IHN0cmluZ1tdLFxuICAgIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogVHlwZWRUZW5zb3I8J3N0cmluZyc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgYm9vbCB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIHR5cGUsIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gU3BlY2lmeSB0aGUgZWxlbWVudCB0eXBlLlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKFxuICAgIHR5cGU6ICdib29sJyxcbiAgICBkYXRhOiBUZW5zb3IuRGF0YVR5cGVNYXBbJ2Jvb2wnXSB8IHJlYWRvbmx5IGJvb2xlYW5bXSxcbiAgICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk6IFR5cGVkVGVuc29yPCdib29sJz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB1aW50OCB0ZW5zb3Igb2JqZWN0IGZyb20gYSBVaW50OENsYW1wZWRBcnJheSwgZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgLSBTcGVjaWZ5IHRoZSBlbGVtZW50IHR5cGUuXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAodHlwZTogJ3VpbnQ4JywgZGF0YTogVWludDhDbGFtcGVkQXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCd1aW50OCc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgNjQtYml0IGludGVnZXIgdHlwZWQgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiB0eXBlLCBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIFNwZWNpZnkgdGhlIGVsZW1lbnQgdHlwZS5cbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IDxUIGV4dGVuZHMgJ3VpbnQ2NCcgfCAnaW50NjQnPihcbiAgICB0eXBlOiBULFxuICAgIGRhdGE6IFRlbnNvci5EYXRhVHlwZU1hcFtUXSB8IHJlYWRvbmx5IGJpZ2ludFtdIHwgcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiBUeXBlZFRlbnNvcjxUPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IG51bWVyaWMgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiB0eXBlLCBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIFNwZWNpZnkgdGhlIGVsZW1lbnQgdHlwZS5cbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IDxUIGV4dGVuZHMgRXhjbHVkZTxUZW5zb3IuVHlwZSwgJ3N0cmluZycgfCAnYm9vbCcgfCAndWludDY0JyB8ICdpbnQ2NCc+PihcbiAgICB0eXBlOiBULFxuICAgIGRhdGE6IFRlbnNvci5EYXRhVHlwZU1hcFtUXSB8IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogVHlwZWRUZW5zb3I8VD47XG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIENQVSB0ZW5zb3IgLSBpbmZlciBlbGVtZW50IHR5cGVzXG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBmbG9hdDMyIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBGbG9hdDMyQXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCdmbG9hdDMyJz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBpbnQ4IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBJbnQ4QXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCdpbnQ4Jz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB1aW50OCB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogVWludDhBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J3VpbnQ4Jz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB1aW50OCB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogVWludDhDbGFtcGVkQXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCd1aW50OCc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdWludDE2IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBVaW50MTZBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J3VpbnQxNic+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgaW50MTYgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IEludDE2QXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCdpbnQxNic+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgaW50MzIgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IEludDMyQXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCdpbnQzMic+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgaW50NjQgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IEJpZ0ludDY0QXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCdpbnQ2NCc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgc3RyaW5nIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiByZWFkb25seSBzdHJpbmdbXSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J3N0cmluZyc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgYm9vbCB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogcmVhZG9ubHkgYm9vbGVhbltdLCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwnYm9vbCc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgZmxvYXQ2NCB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogRmxvYXQ2NEFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwnZmxvYXQ2NCc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdWludDMyIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBVaW50MzJBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J3VpbnQzMic+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdWludDY0IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBCaWdVaW50NjRBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J3VpbnQ2NCc+O1xuXG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIENQVSB0ZW5zb3IgLSBmYWxsIGJhY2sgdG8gbm9uLWdlbmVyaWMgdGVuc29yIHR5cGUgZGVjbGFyYXRpb25cblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gdHlwZSwgZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgLSBTcGVjaWZ5IHRoZSBlbGVtZW50IHR5cGUuXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoXG4gICAgdHlwZTogVGVuc29yLlR5cGUsXG4gICAgZGF0YTogVGVuc29yLkRhdGFUeXBlIHwgcmVhZG9ubHkgbnVtYmVyW10gfCByZWFkb25seSBzdHJpbmdbXSB8IHJlYWRvbmx5IGJpZ2ludFtdIHwgcmVhZG9ubHkgYm9vbGVhbltdLFxuICAgIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogVGVuc29yO1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IFRlbnNvci5EYXRhVHlwZSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yO1xuICAvLyAjZW5kcmVnaW9uXG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbmV4cG9ydCBjb25zdCBUZW5zb3IgPSBUZW5zb3JJbXBsIGFzIFRlbnNvckNvbnN0cnVjdG9yO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBlbnYgfSBmcm9tICcuL2Vudi1pbXBsLmpzJztcblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCBUUkFDRSA9IChkZXZpY2VUeXBlOiBzdHJpbmcsIGxhYmVsOiBzdHJpbmcpID0+IHtcbiAgaWYgKHR5cGVvZiBlbnYudHJhY2UgPT09ICd1bmRlZmluZWQnID8gIWVudi53YXNtLnRyYWNlIDogIWVudi50cmFjZSkge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLnRpbWVTdGFtcChgJHtkZXZpY2VUeXBlfTo6T1JUOjoke2xhYmVsfWApO1xufTtcblxuY29uc3QgVFJBQ0VfRlVOQyA9IChtc2c6IHN0cmluZywgZXh0cmFNc2c/OiBzdHJpbmcpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaz8uc3BsaXQoL1xcclxcbnxcXHJ8XFxuL2cpIHx8IFtdO1xuICBsZXQgaGFzVHJhY2VGdW5jID0gZmFsc2U7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RhY2subGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaGFzVHJhY2VGdW5jICYmICFzdGFja1tpXS5pbmNsdWRlcygnVFJBQ0VfRlVOQycpKSB7XG4gICAgICBsZXQgbGFiZWwgPSBgRlVOQ18ke21zZ306OiR7c3RhY2tbaV0udHJpbSgpLnNwbGl0KCcgJylbMV19YDtcbiAgICAgIGlmIChleHRyYU1zZykge1xuICAgICAgICBsYWJlbCArPSBgOjoke2V4dHJhTXNnfWA7XG4gICAgICB9XG4gICAgICBUUkFDRSgnQ1BVJywgbGFiZWwpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoc3RhY2tbaV0uaW5jbHVkZXMoJ1RSQUNFX0ZVTkMnKSkge1xuICAgICAgaGFzVHJhY2VGdW5jID0gdHJ1ZTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgY29uc3QgVFJBQ0VfRlVOQ19CRUdJTiA9IChleHRyYU1zZz86IHN0cmluZykgPT4ge1xuICBpZiAodHlwZW9mIGVudi50cmFjZSA9PT0gJ3VuZGVmaW5lZCcgPyAhZW52Lndhc20udHJhY2UgOiAhZW52LnRyYWNlKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIFRSQUNFX0ZVTkMoJ0JFR0lOJywgZXh0cmFNc2cpO1xufTtcblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCBUUkFDRV9GVU5DX0VORCA9IChleHRyYU1zZz86IHN0cmluZykgPT4ge1xuICBpZiAodHlwZW9mIGVudi50cmFjZSA9PT0gJ3VuZGVmaW5lZCcgPyAhZW52Lndhc20udHJhY2UgOiAhZW52LnRyYWNlKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIFRSQUNFX0ZVTkMoJ0VORCcsIGV4dHJhTXNnKTtcbn07XG5cbi8qKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgY29uc3QgVFJBQ0VfRVZFTlRfQkVHSU4gPSAoZXh0cmFNc2c/OiBzdHJpbmcpID0+IHtcbiAgaWYgKHR5cGVvZiBlbnYudHJhY2UgPT09ICd1bmRlZmluZWQnID8gIWVudi53YXNtLnRyYWNlIDogIWVudi50cmFjZSkge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLnRpbWUoYE9SVDo6JHtleHRyYU1zZ31gKTtcbn07XG5cbi8qKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgY29uc3QgVFJBQ0VfRVZFTlRfRU5EID0gKGV4dHJhTXNnPzogc3RyaW5nKSA9PiB7XG4gIGlmICh0eXBlb2YgZW52LnRyYWNlID09PSAndW5kZWZpbmVkJyA/ICFlbnYud2FzbS50cmFjZSA6ICFlbnYudHJhY2UpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS50aW1lRW5kKGBPUlQ6OiR7ZXh0cmFNc2d9YCk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyByZXNvbHZlQmFja2VuZEFuZEV4ZWN1dGlvblByb3ZpZGVycyB9IGZyb20gJy4vYmFja2VuZC1pbXBsLmpzJztcbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb25IYW5kbGVyIH0gZnJvbSAnLi9iYWNrZW5kLmpzJztcbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb24gYXMgSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZSB9IGZyb20gJy4vaW5mZXJlbmNlLXNlc3Npb24uanMnO1xuaW1wb3J0IHsgT25ueFZhbHVlIH0gZnJvbSAnLi9vbm54LXZhbHVlLmpzJztcbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yLmpzJztcbmltcG9ydCB7IFRSQUNFX0ZVTkNfQkVHSU4sIFRSQUNFX0ZVTkNfRU5ELCBUUkFDRV9FVkVOVF9CRUdJTiwgVFJBQ0VfRVZFTlRfRU5EIH0gZnJvbSAnLi90cmFjZS5qcyc7XG5cbnR5cGUgU2Vzc2lvbk9wdGlvbnMgPSBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLlNlc3Npb25PcHRpb25zO1xudHlwZSBSdW5PcHRpb25zID0gSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5SdW5PcHRpb25zO1xudHlwZSBGZWVkc1R5cGUgPSBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLkZlZWRzVHlwZTtcbnR5cGUgRmV0Y2hlc1R5cGUgPSBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLkZldGNoZXNUeXBlO1xudHlwZSBSZXR1cm5UeXBlID0gSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5SZXR1cm5UeXBlO1xuXG5leHBvcnQgY2xhc3MgSW5mZXJlbmNlU2Vzc2lvbiBpbXBsZW1lbnRzIEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2Uge1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKGhhbmRsZXI6IEluZmVyZW5jZVNlc3Npb25IYW5kbGVyKSB7XG4gICAgdGhpcy5oYW5kbGVyID0gaGFuZGxlcjtcbiAgfVxuICBydW4oZmVlZHM6IEZlZWRzVHlwZSwgb3B0aW9ucz86IFJ1bk9wdGlvbnMpOiBQcm9taXNlPFJldHVyblR5cGU+O1xuICBydW4oZmVlZHM6IEZlZWRzVHlwZSwgZmV0Y2hlczogRmV0Y2hlc1R5cGUsIG9wdGlvbnM/OiBSdW5PcHRpb25zKTogUHJvbWlzZTxSZXR1cm5UeXBlPjtcbiAgYXN5bmMgcnVuKGZlZWRzOiBGZWVkc1R5cGUsIGFyZzE/OiBGZXRjaGVzVHlwZSB8IFJ1bk9wdGlvbnMsIGFyZzI/OiBSdW5PcHRpb25zKTogUHJvbWlzZTxSZXR1cm5UeXBlPiB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTigpO1xuICAgIFRSQUNFX0VWRU5UX0JFR0lOKCdJbmZlcmVuY2VTZXNzaW9uLnJ1bicpO1xuICAgIGNvbnN0IGZldGNoZXM6IHsgW25hbWU6IHN0cmluZ106IE9ubnhWYWx1ZSB8IG51bGwgfSA9IHt9O1xuICAgIGxldCBvcHRpb25zOiBSdW5PcHRpb25zID0ge307XG4gICAgLy8gY2hlY2sgaW5wdXRzXG4gICAgaWYgKHR5cGVvZiBmZWVkcyAhPT0gJ29iamVjdCcgfHwgZmVlZHMgPT09IG51bGwgfHwgZmVlZHMgaW5zdGFuY2VvZiBUZW5zb3IgfHwgQXJyYXkuaXNBcnJheShmZWVkcykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgIFwiJ2ZlZWRzJyBtdXN0IGJlIGFuIG9iamVjdCB0aGF0IHVzZSBpbnB1dCBuYW1lcyBhcyBrZXlzIGFuZCBPbm54VmFsdWUgYXMgY29ycmVzcG9uZGluZyB2YWx1ZXMuXCIsXG4gICAgICApO1xuICAgIH1cblxuICAgIGxldCBpc0ZldGNoZXNFbXB0eSA9IHRydWU7XG4gICAgLy8gZGV0ZXJtaW5lIHdoaWNoIG92ZXJyaWRlIGlzIGJlaW5nIHVzZWRcbiAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAoYXJnMSA9PT0gbnVsbCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmV4cGVjdGVkIGFyZ3VtZW50WzFdOiBjYW5ub3QgYmUgbnVsbC4nKTtcbiAgICAgIH1cbiAgICAgIGlmIChhcmcxIGluc3RhbmNlb2YgVGVuc29yKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInZmV0Y2hlcycgY2Fubm90IGJlIGEgVGVuc29yXCIpO1xuICAgICAgfVxuXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcxKSkge1xuICAgICAgICBpZiAoYXJnMS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ2ZldGNoZXMnIGNhbm5vdCBiZSBhbiBlbXB0eSBhcnJheS5cIik7XG4gICAgICAgIH1cbiAgICAgICAgaXNGZXRjaGVzRW1wdHkgPSBmYWxzZTtcbiAgICAgICAgLy8gb3V0cHV0IG5hbWVzXG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBhcmcxKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBuYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidmZXRjaGVzJyBtdXN0IGJlIGEgc3RyaW5nIGFycmF5IG9yIGFuIG9iamVjdC5cIik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0aGlzLm91dHB1dE5hbWVzLmluZGV4T2YobmFtZSkgPT09IC0xKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2ZldGNoZXMnIGNvbnRhaW5zIGludmFsaWQgb3V0cHV0IG5hbWU6ICR7bmFtZX0uYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGZldGNoZXNbbmFtZV0gPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBhcmcyID09PSAnb2JqZWN0JyAmJiBhcmcyICE9PSBudWxsKSB7XG4gICAgICAgICAgb3B0aW9ucyA9IGFyZzI7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC5cIik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGRlY2lkZSB3aGV0aGVyIGFyZzEgaXMgZmV0Y2hlcyBvciBvcHRpb25zXG4gICAgICAgIC8vIGlmIGFueSBvdXRwdXQgbmFtZSBpcyBwcmVzZW50IGFuZCBpdHMgdmFsdWUgaXMgdmFsaWQgT25ueFZhbHVlLCB3ZSBjb25zaWRlciBpdCBmZXRjaGVzXG4gICAgICAgIGxldCBpc0ZldGNoZXMgPSBmYWxzZTtcbiAgICAgICAgY29uc3QgYXJnMUtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhhcmcxKTtcbiAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIHRoaXMub3V0cHV0TmFtZXMpIHtcbiAgICAgICAgICBpZiAoYXJnMUtleXMuaW5kZXhPZihuYW1lKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNvbnN0IHYgPSAoYXJnMSBhcyBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLk51bGxhYmxlT25ueFZhbHVlTWFwVHlwZSlbbmFtZV07XG4gICAgICAgICAgICBpZiAodiA9PT0gbnVsbCB8fCB2IGluc3RhbmNlb2YgVGVuc29yKSB7XG4gICAgICAgICAgICAgIGlzRmV0Y2hlcyA9IHRydWU7XG4gICAgICAgICAgICAgIGlzRmV0Y2hlc0VtcHR5ID0gZmFsc2U7XG4gICAgICAgICAgICAgIGZldGNoZXNbbmFtZV0gPSB2O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0ZldGNoZXMpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGFyZzIgPT09ICdvYmplY3QnICYmIGFyZzIgIT09IG51bGwpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBhcmcyO1xuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ29wdGlvbnMnIG11c3QgYmUgYW4gb2JqZWN0LlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3B0aW9ucyA9IGFyZzEgYXMgUnVuT3B0aW9ucztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5leHBlY3RlZCBhcmd1bWVudFsxXTogbXVzdCBiZSAnZmV0Y2hlcycgb3IgJ29wdGlvbnMnLlwiKTtcbiAgICB9XG5cbiAgICAvLyBjaGVjayBpZiBhbGwgaW5wdXRzIGFyZSBpbiBmZWVkXG4gICAgZm9yIChjb25zdCBuYW1lIG9mIHRoaXMuaW5wdXROYW1lcykge1xuICAgICAgaWYgKHR5cGVvZiBmZWVkc1tuYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnB1dCAnJHtuYW1lfScgaXMgbWlzc2luZyBpbiAnZmVlZHMnLmApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGlmIG5vIGZldGNoZXMgaXMgc3BlY2lmaWVkLCB3ZSB1c2UgdGhlIGZ1bGwgb3V0cHV0IG5hbWVzIGxpc3RcbiAgICBpZiAoaXNGZXRjaGVzRW1wdHkpIHtcbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiB0aGlzLm91dHB1dE5hbWVzKSB7XG4gICAgICAgIGZldGNoZXNbbmFtZV0gPSBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGZlZWRzLCBmZXRjaGVzIGFuZCBvcHRpb25zIGFyZSBwcmVwYXJlZFxuXG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHRoaXMuaGFuZGxlci5ydW4oZmVlZHMsIGZldGNoZXMsIG9wdGlvbnMpO1xuICAgIGNvbnN0IHJldHVyblZhbHVlOiB7IFtuYW1lOiBzdHJpbmddOiBPbm54VmFsdWUgfSA9IHt9O1xuICAgIGZvciAoY29uc3Qga2V5IGluIHJlc3VsdHMpIHtcbiAgICAgIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHRzLCBrZXkpKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHJlc3VsdHNba2V5XTtcbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFRlbnNvcikge1xuICAgICAgICAgIHJldHVyblZhbHVlW2tleV0gPSByZXN1bHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVba2V5XSA9IG5ldyBUZW5zb3IocmVzdWx0LnR5cGUsIHJlc3VsdC5kYXRhLCByZXN1bHQuZGltcyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgVFJBQ0VfRVZFTlRfRU5EKCdJbmZlcmVuY2VTZXNzaW9uLnJ1bicpO1xuICAgIFRSQUNFX0ZVTkNfRU5EKCk7XG4gICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICB9XG5cbiAgYXN5bmMgcmVsZWFzZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVyLmRpc3Bvc2UoKTtcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGUocGF0aDogc3RyaW5nLCBvcHRpb25zPzogU2Vzc2lvbk9wdGlvbnMpOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2U+O1xuICBzdGF0aWMgY3JlYXRlKGJ1ZmZlcjogQXJyYXlCdWZmZXJMaWtlLCBvcHRpb25zPzogU2Vzc2lvbk9wdGlvbnMpOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2U+O1xuICBzdGF0aWMgY3JlYXRlKFxuICAgIGJ1ZmZlcjogQXJyYXlCdWZmZXJMaWtlLFxuICAgIGJ5dGVPZmZzZXQ6IG51bWJlcixcbiAgICBieXRlTGVuZ3RoPzogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiBTZXNzaW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlPjtcbiAgc3RhdGljIGNyZWF0ZShidWZmZXI6IFVpbnQ4QXJyYXksIG9wdGlvbnM/OiBTZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZT47XG4gIHN0YXRpYyBhc3luYyBjcmVhdGUoXG4gICAgYXJnMDogc3RyaW5nIHwgQXJyYXlCdWZmZXJMaWtlIHwgVWludDhBcnJheSxcbiAgICBhcmcxPzogU2Vzc2lvbk9wdGlvbnMgfCBudW1iZXIsXG4gICAgYXJnMj86IG51bWJlcixcbiAgICBhcmczPzogU2Vzc2lvbk9wdGlvbnMsXG4gICk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZT4ge1xuICAgIFRSQUNFX0ZVTkNfQkVHSU4oKTtcbiAgICBUUkFDRV9FVkVOVF9CRUdJTignSW5mZXJlbmNlU2Vzc2lvbi5jcmVhdGUnKTtcbiAgICAvLyBlaXRoZXIgbG9hZCBmcm9tIGEgZmlsZSBvciBidWZmZXJcbiAgICBsZXQgZmlsZVBhdGhPclVpbnQ4QXJyYXk6IHN0cmluZyB8IFVpbnQ4QXJyYXk7XG4gICAgbGV0IG9wdGlvbnM6IFNlc3Npb25PcHRpb25zID0ge307XG5cbiAgICBpZiAodHlwZW9mIGFyZzAgPT09ICdzdHJpbmcnKSB7XG4gICAgICBmaWxlUGF0aE9yVWludDhBcnJheSA9IGFyZzA7XG4gICAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnICYmIGFyZzEgIT09IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucyA9IGFyZzE7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcxICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ29wdGlvbnMnIG11c3QgYmUgYW4gb2JqZWN0LlwiKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGFyZzAgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICBmaWxlUGF0aE9yVWludDhBcnJheSA9IGFyZzA7XG4gICAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnICYmIGFyZzEgIT09IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucyA9IGFyZzE7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcxICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ29wdGlvbnMnIG11c3QgYmUgYW4gb2JqZWN0LlwiKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKFxuICAgICAgYXJnMCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyIHx8XG4gICAgICAodHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyICE9PSAndW5kZWZpbmVkJyAmJiBhcmcwIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXIpXG4gICAgKSB7XG4gICAgICBjb25zdCBidWZmZXIgPSBhcmcwO1xuICAgICAgbGV0IGJ5dGVPZmZzZXQgPSAwO1xuICAgICAgbGV0IGJ5dGVMZW5ndGggPSBhcmcwLmJ5dGVMZW5ndGg7XG4gICAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnICYmIGFyZzEgIT09IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucyA9IGFyZzE7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcxID09PSAnbnVtYmVyJykge1xuICAgICAgICBieXRlT2Zmc2V0ID0gYXJnMTtcbiAgICAgICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihieXRlT2Zmc2V0KSkge1xuICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKFwiJ2J5dGVPZmZzZXQnIG11c3QgYmUgYW4gaW50ZWdlci5cIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJ5dGVPZmZzZXQgPCAwIHx8IGJ5dGVPZmZzZXQgPj0gYnVmZmVyLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2J5dGVPZmZzZXQnIGlzIG91dCBvZiByYW5nZSBbMCwgJHtidWZmZXIuYnl0ZUxlbmd0aH0pLmApO1xuICAgICAgICB9XG4gICAgICAgIGJ5dGVMZW5ndGggPSBhcmcwLmJ5dGVMZW5ndGggLSBieXRlT2Zmc2V0O1xuICAgICAgICBpZiAodHlwZW9mIGFyZzIgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgYnl0ZUxlbmd0aCA9IGFyZzI7XG4gICAgICAgICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihieXRlTGVuZ3RoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCInYnl0ZUxlbmd0aCcgbXVzdCBiZSBhbiBpbnRlZ2VyLlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGJ5dGVMZW5ndGggPD0gMCB8fCBieXRlT2Zmc2V0ICsgYnl0ZUxlbmd0aCA+IGJ1ZmZlci5ieXRlTGVuZ3RoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2J5dGVMZW5ndGgnIGlzIG91dCBvZiByYW5nZSAoMCwgJHtidWZmZXIuYnl0ZUxlbmd0aCAtIGJ5dGVPZmZzZXR9XS5gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHR5cGVvZiBhcmczID09PSAnb2JqZWN0JyAmJiBhcmczICE9PSBudWxsKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gYXJnMztcbiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmczICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC5cIik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInYnl0ZUxlbmd0aCcgbXVzdCBiZSBhIG51bWJlci5cIik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuXCIpO1xuICAgICAgfVxuICAgICAgZmlsZVBhdGhPclVpbnQ4QXJyYXkgPSBuZXcgVWludDhBcnJheShidWZmZXIsIGJ5dGVPZmZzZXQsIGJ5dGVMZW5ndGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5leHBlY3RlZCBhcmd1bWVudFswXTogbXVzdCBiZSAncGF0aCcgb3IgJ2J1ZmZlcicuXCIpO1xuICAgIH1cblxuICAgIC8vIHJlc29sdmUgYmFja2VuZCwgdXBkYXRlIHNlc3Npb24gb3B0aW9ucyB3aXRoIHZhbGlkYXRlZCBFUHMsIGFuZCBjcmVhdGUgc2Vzc2lvbiBoYW5kbGVyXG4gICAgY29uc3QgW2JhY2tlbmQsIG9wdGlvbnNXaXRoVmFsaWRhdGVkRVBzXSA9IGF3YWl0IHJlc29sdmVCYWNrZW5kQW5kRXhlY3V0aW9uUHJvdmlkZXJzKG9wdGlvbnMpO1xuICAgIGNvbnN0IGhhbmRsZXIgPSBhd2FpdCBiYWNrZW5kLmNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKGZpbGVQYXRoT3JVaW50OEFycmF5LCBvcHRpb25zV2l0aFZhbGlkYXRlZEVQcyk7XG4gICAgVFJBQ0VfRVZFTlRfRU5EKCdJbmZlcmVuY2VTZXNzaW9uLmNyZWF0ZScpO1xuICAgIFRSQUNFX0ZVTkNfRU5EKCk7XG4gICAgcmV0dXJuIG5ldyBJbmZlcmVuY2VTZXNzaW9uKGhhbmRsZXIpO1xuICB9XG5cbiAgc3RhcnRQcm9maWxpbmcoKTogdm9pZCB7XG4gICAgdGhpcy5oYW5kbGVyLnN0YXJ0UHJvZmlsaW5nKCk7XG4gIH1cbiAgZW5kUHJvZmlsaW5nKCk6IHZvaWQge1xuICAgIHRoaXMuaGFuZGxlci5lbmRQcm9maWxpbmcoKTtcbiAgfVxuXG4gIGdldCBpbnB1dE5hbWVzKCk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVyLmlucHV0TmFtZXM7XG4gIH1cbiAgZ2V0IG91dHB1dE5hbWVzKCk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVyLm91dHB1dE5hbWVzO1xuICB9XG5cbiAgZ2V0IGlucHV0TWV0YWRhdGEoKTogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5WYWx1ZU1ldGFkYXRhW10ge1xuICAgIHJldHVybiB0aGlzLmhhbmRsZXIuaW5wdXRNZXRhZGF0YTtcbiAgfVxuXG4gIGdldCBvdXRwdXRNZXRhZGF0YSgpOiByZWFkb25seSBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLlZhbHVlTWV0YWRhdGFbXSB7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlci5vdXRwdXRNZXRhZGF0YTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlcjogSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXI7XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb24gYXMgSW5mZXJlbmNlU2Vzc2lvbkltcGwgfSBmcm9tICcuL2luZmVyZW5jZS1zZXNzaW9uLWltcGwuanMnO1xuaW1wb3J0IHsgT25ueE1vZGVsT3B0aW9ucyB9IGZyb20gJy4vb25ueC1tb2RlbC5qcyc7XG5pbXBvcnQgeyBPbm54VmFsdWUsIE9ubnhWYWx1ZURhdGFMb2NhdGlvbiB9IGZyb20gJy4vb25ueC12YWx1ZS5qcyc7XG5pbXBvcnQgdHlwZSB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yLmpzJztcbmltcG9ydCB7IFRyeUdldEdsb2JhbFR5cGUgfSBmcm9tICcuL3R5cGUtaGVscGVyLmpzJztcblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlZGVjbGFyZSAqL1xuXG5leHBvcnQgZGVjbGFyZSBuYW1lc3BhY2UgSW5mZXJlbmNlU2Vzc2lvbiB7XG4gIC8vICNyZWdpb24gaW5wdXQvb3V0cHV0IHR5cGVzXG5cbiAgdHlwZSBPbm54VmFsdWVNYXBUeXBlID0geyByZWFkb25seSBbbmFtZTogc3RyaW5nXTogT25ueFZhbHVlIH07XG4gIHR5cGUgTnVsbGFibGVPbm54VmFsdWVNYXBUeXBlID0geyByZWFkb25seSBbbmFtZTogc3RyaW5nXTogT25ueFZhbHVlIHwgbnVsbCB9O1xuXG4gIC8qKlxuICAgKiBBIGZlZWRzIChtb2RlbCBpbnB1dHMpIGlzIGFuIG9iamVjdCB0aGF0IHVzZXMgaW5wdXQgbmFtZXMgYXMga2V5cyBhbmQgT25ueFZhbHVlIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgKi9cbiAgdHlwZSBGZWVkc1R5cGUgPSBPbm54VmFsdWVNYXBUeXBlO1xuXG4gIC8qKlxuICAgKiBBIGZldGNoZXMgKG1vZGVsIG91dHB1dHMpIGNvdWxkIGJlIG9uZSBvZiB0aGUgZm9sbG93aW5nOlxuICAgKlxuICAgKiAtIE9taXR0ZWQuIFVzZSBtb2RlbCdzIG91dHB1dCBuYW1lcyBkZWZpbml0aW9uLlxuICAgKiAtIEFuIGFycmF5IG9mIHN0cmluZyBpbmRpY2F0aW5nIHRoZSBvdXRwdXQgbmFtZXMuXG4gICAqIC0gQW4gb2JqZWN0IHRoYXQgdXNlIG91dHB1dCBuYW1lcyBhcyBrZXlzIGFuZCBPbm54VmFsdWUgb3IgbnVsbCBhcyBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgICpcbiAgICogQHJlbWFya1xuICAgKiBkaWZmZXJlbnQgZnJvbSBpbnB1dCBhcmd1bWVudCwgaW4gb3V0cHV0LCBPbm54VmFsdWUgaXMgb3B0aW9uYWwuIElmIGFuIE9ubnhWYWx1ZSBpcyBwcmVzZW50IGl0IHdpbGwgYmVcbiAgICogdXNlZCBhcyBhIHByZS1hbGxvY2F0ZWQgdmFsdWUgYnkgdGhlIGluZmVyZW5jZSBlbmdpbmU7IGlmIG9taXR0ZWQsIGluZmVyZW5jZSBlbmdpbmUgd2lsbCBhbGxvY2F0ZSBidWZmZXJcbiAgICogaW50ZXJuYWxseS5cbiAgICovXG4gIHR5cGUgRmV0Y2hlc1R5cGUgPSByZWFkb25seSBzdHJpbmdbXSB8IE51bGxhYmxlT25ueFZhbHVlTWFwVHlwZTtcblxuICAvKipcbiAgICogQSBpbmZlcmVuY2luZyByZXR1cm4gdHlwZSBpcyBhbiBvYmplY3QgdGhhdCB1c2VzIG91dHB1dCBuYW1lcyBhcyBrZXlzIGFuZCBPbm54VmFsdWUgYXMgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAqL1xuICB0eXBlIFJldHVyblR5cGUgPSBPbm54VmFsdWVNYXBUeXBlO1xuXG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIHNlc3Npb24gb3B0aW9uc1xuXG4gIC8qKlxuICAgKiBBIHNldCBvZiBjb25maWd1cmF0aW9ucyBmb3Igc2Vzc2lvbiBiZWhhdmlvci5cbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgU2Vzc2lvbk9wdGlvbnMgZXh0ZW5kcyBPbm54TW9kZWxPcHRpb25zIHtcbiAgICAvKipcbiAgICAgKiBBbiBhcnJheSBvZiBleGVjdXRpb24gcHJvdmlkZXIgb3B0aW9ucy5cbiAgICAgKlxuICAgICAqIEFuIGV4ZWN1dGlvbiBwcm92aWRlciBvcHRpb24gY2FuIGJlIGEgc3RyaW5nIGluZGljYXRpbmcgdGhlIG5hbWUgb2YgdGhlIGV4ZWN1dGlvbiBwcm92aWRlcixcbiAgICAgKiBvciBhbiBvYmplY3Qgb2YgY29ycmVzcG9uZGluZyB0eXBlLlxuICAgICAqL1xuICAgIGV4ZWN1dGlvblByb3ZpZGVycz86IHJlYWRvbmx5IEV4ZWN1dGlvblByb3ZpZGVyQ29uZmlnW107XG5cbiAgICAvKipcbiAgICAgKiBUaGUgaW50cmEgT1AgdGhyZWFkcyBudW1iZXIuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKS5cbiAgICAgKi9cbiAgICBpbnRyYU9wTnVtVGhyZWFkcz86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBpbnRlciBPUCB0aHJlYWRzIG51bWJlci5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpLlxuICAgICAqL1xuICAgIGludGVyT3BOdW1UaHJlYWRzPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyZWUgZGltZW5zaW9uIG92ZXJyaWRlLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIGZyZWVEaW1lbnNpb25PdmVycmlkZXM/OiB7IHJlYWRvbmx5IFtkaW1lbnNpb25OYW1lOiBzdHJpbmddOiBudW1iZXIgfTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHRpbWl6YXRpb24gbGV2ZWwuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKSBvciBXZWJBc3NlbWJseSBiYWNrZW5kXG4gICAgICovXG4gICAgZ3JhcGhPcHRpbWl6YXRpb25MZXZlbD86ICdkaXNhYmxlZCcgfCAnYmFzaWMnIHwgJ2V4dGVuZGVkJyB8ICdsYXlvdXQnIHwgJ2FsbCc7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIGVuYWJsZSBDUFUgbWVtb3J5IGFyZW5hLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIGVuYWJsZUNwdU1lbUFyZW5hPzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgZW5hYmxlIG1lbW9yeSBwYXR0ZXJuLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIGVuYWJsZU1lbVBhdHRlcm4/OiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogRXhlY3V0aW9uIG1vZGUuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKSBvciBXZWJBc3NlbWJseSBiYWNrZW5kXG4gICAgICovXG4gICAgZXhlY3V0aW9uTW9kZT86ICdzZXF1ZW50aWFsJyB8ICdwYXJhbGxlbCc7XG5cbiAgICAvKipcbiAgICAgKiBPcHRpbWl6ZWQgbW9kZWwgZmlsZSBwYXRoLlxuICAgICAqXG4gICAgICogSWYgdGhpcyBzZXR0aW5nIGlzIHNwZWNpZmllZCwgdGhlIG9wdGltaXplZCBtb2RlbCB3aWxsIGJlIGR1bXBlZC4gSW4gYnJvd3NlciwgYSBibG9iIHdpbGwgYmUgY3JlYXRlZFxuICAgICAqIHdpdGggYSBwb3AtdXAgd2luZG93LlxuICAgICAqL1xuICAgIG9wdGltaXplZE1vZGVsRmlsZVBhdGg/OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIGVuYWJsZSBwcm9maWxpbmcuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYSBwbGFjZWhvbGRlciBmb3IgYSBmdXR1cmUgdXNlLlxuICAgICAqL1xuICAgIGVuYWJsZVByb2ZpbGluZz86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBGaWxlIHByZWZpeCBmb3IgcHJvZmlsaW5nLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGEgcGxhY2Vob2xkZXIgZm9yIGEgZnV0dXJlIHVzZS5cbiAgICAgKi9cbiAgICBwcm9maWxlRmlsZVByZWZpeD86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIExvZyBJRC5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpIG9yIFdlYkFzc2VtYmx5IGJhY2tlbmRcbiAgICAgKi9cbiAgICBsb2dJZD86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIExvZyBzZXZlcml0eSBsZXZlbC4gU2VlXG4gICAgICogaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9vbm54cnVudGltZS9ibG9iL21haW4vaW5jbHVkZS9vbm54cnVudGltZS9jb3JlL2NvbW1vbi9sb2dnaW5nL3NldmVyaXR5LmhcbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpIG9yIFdlYkFzc2VtYmx5IGJhY2tlbmRcbiAgICAgKi9cbiAgICBsb2dTZXZlcml0eUxldmVsPzogMCB8IDEgfCAyIHwgMyB8IDQ7XG5cbiAgICAvKipcbiAgICAgKiBMb2cgdmVyYm9zaXR5IGxldmVsLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIFdlYkFzc2VtYmx5IGJhY2tlbmQuIFdpbGwgc3VwcG9ydCBOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSBsYXRlclxuICAgICAqL1xuICAgIGxvZ1ZlcmJvc2l0eUxldmVsPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogU3BlY2lmeSBzdHJpbmcgYXMgYSBwcmVmZXJyZWQgZGF0YSBsb2NhdGlvbiBmb3IgYWxsIG91dHB1dHMsIG9yIGFuIG9iamVjdCB0aGF0IHVzZSBvdXRwdXQgbmFtZXMgYXMga2V5cyBhbmQgYVxuICAgICAqIHByZWZlcnJlZCBkYXRhIGxvY2F0aW9uIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIFdlYiBmb3IgV2ViR0wgYW5kIFdlYkdQVSBFUC5cbiAgICAgKi9cbiAgICBwcmVmZXJyZWRPdXRwdXRMb2NhdGlvbj86IE9ubnhWYWx1ZURhdGFMb2NhdGlvbiB8IHsgcmVhZG9ubHkgW291dHB1dE5hbWU6IHN0cmluZ106IE9ubnhWYWx1ZURhdGFMb2NhdGlvbiB9O1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciBlbmFibGUgZ3JhcGggY2FwdHVyZS5cbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgV2ViIGZvciBXZWJHUFUgRVAuXG4gICAgICovXG4gICAgZW5hYmxlR3JhcGhDYXB0dXJlPzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFN0b3JlIGNvbmZpZ3VyYXRpb25zIGZvciBhIHNlc3Npb24uIFNlZVxuICAgICAqIGh0dHBzOi8vZ2l0aHViLmNvbS9taWNyb3NvZnQvb25ueHJ1bnRpbWUvYmxvYi9tYWluL2luY2x1ZGUvb25ueHJ1bnRpbWUvY29yZS9zZXNzaW9uL1xuICAgICAqIG9ubnhydW50aW1lX3Nlc3Npb25fb3B0aW9uc19jb25maWdfa2V5cy5oXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gV2ViQXNzZW1ibHkgYmFja2VuZC4gV2lsbCBzdXBwb3J0IE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlIGxhdGVyXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZXh0cmE6IHtcbiAgICAgKiAgIHNlc3Npb246IHtcbiAgICAgKiAgICAgc2V0X2Rlbm9ybWFsX2FzX3plcm86IFwiMVwiLFxuICAgICAqICAgICBkaXNhYmxlX3ByZXBhY2tpbmc6IFwiMVwiXG4gICAgICogICB9LFxuICAgICAqICAgb3B0aW1pemF0aW9uOiB7XG4gICAgICogICAgIGVuYWJsZV9nZWx1X2FwcHJveGltYXRpb246IFwiMVwiXG4gICAgICogICB9XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGV4dHJhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH1cblxuICAvLyAjcmVnaW9uIGV4ZWN1dGlvbiBwcm92aWRlcnNcblxuICAvLyBDdXJyZW50bHksIHdlIGhhdmUgdGhlIGZvbGxvd2luZyBiYWNrZW5kcyB0byBzdXBwb3J0IGV4ZWN1dGlvbiBwcm92aWRlcnM6XG4gIC8vIEJhY2tlbmQgTm9kZS5qcyBiaW5kaW5nOiBzdXBwb3J0cyAnY3B1JywgJ2RtbCcgKHdpbjMyKSwgJ2NvcmVtbCcgKG1hY09TKSBhbmQgJ2N1ZGEnIChsaW51eCkuXG4gIC8vIEJhY2tlbmQgV2ViQXNzZW1ibHk6IHN1cHBvcnRzICdjcHUnLCAnd2FzbScsICd3ZWJncHUnIGFuZCAnd2Vibm4nLlxuICAvLyBCYWNrZW5kIE9OTlguanM6IHN1cHBvcnRzICd3ZWJnbCcuXG4gIC8vIEJhY2tlbmQgUmVhY3QgTmF0aXZlOiBzdXBwb3J0cyAnY3B1JywgJ3hubnBhY2snLCAnY29yZW1sJyAoaU9TKSwgJ25uYXBpJyAoQW5kcm9pZCkuXG4gIGludGVyZmFjZSBFeGVjdXRpb25Qcm92aWRlck9wdGlvbk1hcCB7XG4gICAgY29yZW1sOiBDb3JlTUxFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICBjcHU6IENwdUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIGN1ZGE6IEN1ZGFFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICBkbWw6IERtbEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIG5uYXBpOiBObmFwaUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIHRlbnNvcnJ0OiBUZW5zb3JSdEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIHdhc206IFdlYkFzc2VtYmx5RXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgd2ViZ2w6IFdlYkdMRXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgd2ViZ3B1OiBXZWJHcHVFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICB3ZWJubjogV2ViTk5FeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICBxbm46IFFubkV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIHhubnBhY2s6IFhubnBhY2tFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgfVxuXG4gIHR5cGUgRXhlY3V0aW9uUHJvdmlkZXJOYW1lID0ga2V5b2YgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb25NYXA7XG4gIHR5cGUgRXhlY3V0aW9uUHJvdmlkZXJDb25maWcgPVxuICAgIHwgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb25NYXBbRXhlY3V0aW9uUHJvdmlkZXJOYW1lXVxuICAgIHwgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb25cbiAgICB8IEV4ZWN1dGlvblByb3ZpZGVyTmFtZVxuICAgIHwgc3RyaW5nO1xuXG4gIGV4cG9ydCBpbnRlcmZhY2UgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIENwdUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICdjcHUnO1xuICAgIHVzZUFyZW5hPzogYm9vbGVhbjtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIEN1ZGFFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnY3VkYSc7XG4gICAgZGV2aWNlSWQ/OiBudW1iZXI7XG4gIH1cbiAgZXhwb3J0IGludGVyZmFjZSBEbWxFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnZG1sJztcbiAgICBkZXZpY2VJZD86IG51bWJlcjtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIFRlbnNvclJ0RXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ3RlbnNvcnJ0JztcbiAgICBkZXZpY2VJZD86IG51bWJlcjtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIFdlYkFzc2VtYmx5RXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ3dhc20nO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViR0xFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnd2ViZ2wnO1xuICAgIC8vIFRPRE86IGFkZCBmbGFnc1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgWG5ucGFja0V4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICd4bm5wYWNrJztcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIFdlYkdwdUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICd3ZWJncHUnO1xuXG4gICAgLyoqXG4gICAgICogU3BlY2lmeSB0aGUgcHJlZmVycmVkIGxheW91dCB3aGVuIHJ1bm5pbmcgbGF5b3V0IHNlbnNpdGl2ZSBvcGVyYXRvcnMuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCAnTkNIVydcbiAgICAgKi9cbiAgICBwcmVmZXJyZWRMYXlvdXQ/OiAnTkNIVycgfCAnTkhXQyc7XG5cbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IGEgbGlzdCBvZiBub2RlIG5hbWVzIHRoYXQgc2hvdWxkIGJlIGV4ZWN1dGVkIG9uIENQVSBldmVuIHdoZW4gV2ViR1BVIEVQIGlzIHVzZWQuXG4gICAgICovXG4gICAgZm9yY2VDcHVOb2RlTmFtZXM/OiByZWFkb25seSBzdHJpbmdbXTtcblxuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgdGhlIHZhbGlkYXRpb24gbW9kZSBmb3IgV2ViR1BVIGV4ZWN1dGlvbiBwcm92aWRlci5cbiAgICAgKiAtICdkaXNhYmxlZCc6IERpc2FibGUgYWxsIHZhbGlkYXRpb24uXG4gICAgICogV2hlbiB1c2VkIGluIE5vZGUuanMsIGRpc2FibGUgdmFsaWRhdGlvbiBtYXkgY2F1c2UgcHJvY2VzcyBjcmFzaCBpZiBXZWJHUFUgZXJyb3JzIG9jY3VyLiBCZSBjYXV0aW91cyB3aGVuIHVzaW5nXG4gICAgICogdGhpcyBtb2RlLlxuICAgICAqIFdoZW4gdXNlZCBpbiB3ZWIsIHRoaXMgbW9kZSBpcyBlcXVpdmFsZW50IHRvICd3Z3B1T25seScuXG4gICAgICogLSAnd2dwdU9ubHknOiBQZXJmb3JtIFdlYkdQVSBpbnRlcm5hbCB2YWxpZGF0aW9uIG9ubHkuXG4gICAgICogLSAnYmFzaWMnOiBQZXJmb3JtIGJhc2ljIHZhbGlkYXRpb24gaW5jbHVkaW5nIFdlYkdQVSBpbnRlcm5hbCB2YWxpZGF0aW9uLiBUaGlzIGlzIHRoZSBkZWZhdWx0IG1vZGUuXG4gICAgICogLSAnZnVsbCc6IFBlcmZvcm0gZnVsbCB2YWxpZGF0aW9uLiBUaGlzIG1vZGUgbWF5IGhhdmUgcGVyZm9ybWFuY2UgaW1wYWN0LiBVc2UgaXQgZm9yIGRlYnVnZ2luZyBwdXJwb3NlLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgJ2Jhc2ljJ1xuICAgICAqL1xuICAgIHZhbGlkYXRpb25Nb2RlPzogJ2Rpc2FibGVkJyB8ICd3Z3B1T25seScgfCAnYmFzaWMnIHwgJ2Z1bGwnO1xuXG4gICAgLyoqXG4gICAgICogU3BlY2lmeSBhbiBvcHRpb25hbCBXZWJHUFUgZGV2aWNlIHRvIGJlIHVzZWQgYnkgdGhlIFdlYkdQVSBleGVjdXRpb24gcHJvdmlkZXIuXG4gICAgICovXG4gICAgZGV2aWNlPzogVHJ5R2V0R2xvYmFsVHlwZTwnR1BVRGV2aWNlJz47XG4gIH1cblxuICAvLyAjcmVnaW9uIFdlYk5OIG9wdGlvbnNcblxuICBpbnRlcmZhY2UgV2ViTk5FeGVjdXRpb25Qcm92aWRlck5hbWUgZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ3dlYm5uJztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIGEgc2V0IG9mIG9wdGlvbnMgZm9yIGNyZWF0aW5nIGEgV2ViTk4gTUxDb250ZXh0LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vd3d3LnczLm9yZy9UUi93ZWJubi8jZGljdGRlZi1tbGNvbnRleHRvcHRpb25zXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIFdlYk5OQ29udGV4dE9wdGlvbnMge1xuICAgIGRldmljZVR5cGU/OiAnY3B1JyB8ICdncHUnIHwgJ25wdSc7XG4gICAgbnVtVGhyZWFkcz86IG51bWJlcjtcbiAgICBwb3dlclByZWZlcmVuY2U/OiAnZGVmYXVsdCcgfCAnbG93LXBvd2VyJyB8ICdoaWdoLXBlcmZvcm1hbmNlJztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIGEgc2V0IG9mIG9wdGlvbnMgZm9yIFdlYk5OIGV4ZWN1dGlvbiBwcm92aWRlciB3aXRob3V0IE1MQ29udGV4dC5cbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViTk5PcHRpb25zV2l0aG91dE1MQ29udGV4dCBleHRlbmRzIFdlYk5ORXhlY3V0aW9uUHJvdmlkZXJOYW1lLCBXZWJOTkNvbnRleHRPcHRpb25zIHtcbiAgICBjb250ZXh0PzogbmV2ZXI7XG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyBhIHNldCBvZiBvcHRpb25zIGZvciBXZWJOTiBleGVjdXRpb24gcHJvdmlkZXIgd2l0aCBNTENvbnRleHQuXG4gICAqXG4gICAqIFdoZW4gTUxDb250ZXh0IGlzIHByb3ZpZGVkLCB0aGUgZGV2aWNlVHlwZSBpcyBhbHNvIHJlcXVpcmVkIHNvIHRoYXQgdGhlIFdlYk5OIEVQIGNhbiBkZXRlcm1pbmUgdGhlIHByZWZlcnJlZFxuICAgKiBjaGFubmVsIGxheW91dC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL3d3dy53My5vcmcvVFIvd2Vibm4vI2RvbS1tbC1jcmVhdGVjb250ZXh0XG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIFdlYk5OT3B0aW9uc1dpdGhNTENvbnRleHRcbiAgICBleHRlbmRzIFdlYk5ORXhlY3V0aW9uUHJvdmlkZXJOYW1lLFxuICAgICAgT21pdDxXZWJOTkNvbnRleHRPcHRpb25zLCAnZGV2aWNlVHlwZSc+LFxuICAgICAgUmVxdWlyZWQ8UGljazxXZWJOTkNvbnRleHRPcHRpb25zLCAnZGV2aWNlVHlwZSc+PiB7XG4gICAgY29udGV4dDogVHJ5R2V0R2xvYmFsVHlwZTwnTUxDb250ZXh0Jz47XG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyBhIHNldCBvZiBvcHRpb25zIGZvciBXZWJOTiBleGVjdXRpb24gcHJvdmlkZXIgd2l0aCBNTENvbnRleHQgd2hpY2ggaXMgY3JlYXRlZCBmcm9tIEdQVURldmljZS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL3d3dy53My5vcmcvVFIvd2Vibm4vI2RvbS1tbC1jcmVhdGVjb250ZXh0LWdwdWRldmljZVxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJOTk9wdGlvbnNXZWJHcHUgZXh0ZW5kcyBXZWJOTkV4ZWN1dGlvblByb3ZpZGVyTmFtZSB7XG4gICAgY29udGV4dDogVHJ5R2V0R2xvYmFsVHlwZTwnTUxDb250ZXh0Jz47XG4gICAgZ3B1RGV2aWNlOiBUcnlHZXRHbG9iYWxUeXBlPCdHUFVEZXZpY2UnPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcHRpb25zIGZvciBXZWJOTiBleGVjdXRpb24gcHJvdmlkZXIuXG4gICAqL1xuICBleHBvcnQgdHlwZSBXZWJOTkV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uID1cbiAgICB8IFdlYk5OT3B0aW9uc1dpdGhvdXRNTENvbnRleHRcbiAgICB8IFdlYk5OT3B0aW9uc1dpdGhNTENvbnRleHRcbiAgICB8IFdlYk5OT3B0aW9uc1dlYkdwdTtcblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgZXhwb3J0IGludGVyZmFjZSBRbm5FeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAncW5uJztcbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IHRoZSBRTk4gYmFja2VuZCB0eXBlLiBFLmcuLCAnY3B1JyBvciAnaHRwJy5cbiAgICAgKiBNdXR1YWxseSBleGNsdXNpdmUgd2l0aCBgYmFja2VuZFBhdGhgLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgJ2h0cCdcbiAgICAgKi9cbiAgICBiYWNrZW5kVHlwZT86IHN0cmluZztcbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IGEgcGF0aCB0byB0aGUgUU5OIGJhY2tlbmQgbGlicmFyeS5cbiAgICAgKiBNdXR1YWxseSBleGNsdXNpdmUgd2l0aCBgYmFja2VuZFR5cGVgLlxuICAgICAqL1xuICAgIGJhY2tlbmRQYXRoPzogc3RyaW5nO1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgd2hldGhlciB0byBlbmFibGUgSFRQIEZQMTYgcHJlY2lzaW9uLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgdHJ1ZVxuICAgICAqL1xuICAgIGVuYWJsZUZwMTZQcmVjaXNpb24/OiBib29sZWFuO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgQ29yZU1MRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ2NvcmVtbCc7XG4gICAgLyoqXG4gICAgICogVGhlIGJpdCBmbGFncyBmb3IgQ29yZU1MIGV4ZWN1dGlvbiBwcm92aWRlci5cbiAgICAgKlxuICAgICAqIGBgYFxuICAgICAqIENPUkVNTF9GTEFHX1VTRV9DUFVfT05MWSA9IDB4MDAxXG4gICAgICogQ09SRU1MX0ZMQUdfRU5BQkxFX09OX1NVQkdSQVBIID0gMHgwMDJcbiAgICAgKiBDT1JFTUxfRkxBR19PTkxZX0VOQUJMRV9ERVZJQ0VfV0lUSF9BTkUgPSAweDAwNFxuICAgICAqIENPUkVNTF9GTEFHX09OTFlfQUxMT1dfU1RBVElDX0lOUFVUX1NIQVBFUyA9IDB4MDA4XG4gICAgICogQ09SRU1MX0ZMQUdfQ1JFQVRFX01MUFJPR1JBTSA9IDB4MDEwXG4gICAgICogQ09SRU1MX0ZMQUdfVVNFX0NQVV9BTkRfR1BVID0gMHgwMjBcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFNlZSBpbmNsdWRlL29ubnhydW50aW1lL2NvcmUvcHJvdmlkZXJzL2NvcmVtbC9jb3JlbWxfcHJvdmlkZXJfZmFjdG9yeS5oIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBUaGlzIGZsYWcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZykuXG4gICAgICovXG4gICAgY29yZU1sRmxhZ3M/OiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSB3aGV0aGVyIHRvIHVzZSBDUFUgb25seSBpbiBDb3JlTUwgRVAuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKHJlYWN0LW5hdGl2ZSkuXG4gICAgICovXG4gICAgdXNlQ1BVT25seT86IGJvb2xlYW47XG4gICAgdXNlQ1BVQW5kR1BVPzogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IHdoZXRoZXIgdG8gZW5hYmxlIENvcmVNTCBFUCBvbiBzdWJncmFwaC5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAocmVhY3QtbmF0aXZlKS5cbiAgICAgKi9cbiAgICBlbmFibGVPblN1YmdyYXBoPzogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IHdoZXRoZXIgdG8gb25seSBlbmFibGUgQ29yZU1MIEVQIGZvciBBcHBsZSBkZXZpY2VzIHdpdGggQU5FIChBcHBsZSBOZXVyYWwgRW5naW5lKS5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAocmVhY3QtbmF0aXZlKS5cbiAgICAgKi9cbiAgICBvbmx5RW5hYmxlRGV2aWNlV2l0aEFORT86IGJvb2xlYW47XG4gIH1cbiAgZXhwb3J0IGludGVyZmFjZSBObmFwaUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICdubmFwaSc7XG4gICAgdXNlRlAxNj86IGJvb2xlYW47XG4gICAgdXNlTkNIVz86IGJvb2xlYW47XG4gICAgY3B1RGlzYWJsZWQ/OiBib29sZWFuO1xuICAgIGNwdU9ubHk/OiBib29sZWFuO1xuICB9XG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBydW4gb3B0aW9uc1xuXG4gIC8qKlxuICAgKiBBIHNldCBvZiBjb25maWd1cmF0aW9ucyBmb3IgaW5mZXJlbmNlIHJ1biBiZWhhdmlvclxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBSdW5PcHRpb25zIHtcbiAgICAvKipcbiAgICAgKiBMb2cgc2V2ZXJpdHkgbGV2ZWwuIFNlZVxuICAgICAqIGh0dHBzOi8vZ2l0aHViLmNvbS9taWNyb3NvZnQvb25ueHJ1bnRpbWUvYmxvYi9tYWluL2luY2x1ZGUvb25ueHJ1bnRpbWUvY29yZS9jb21tb24vbG9nZ2luZy9zZXZlcml0eS5oXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKSBvciBXZWJBc3NlbWJseSBiYWNrZW5kXG4gICAgICovXG4gICAgbG9nU2V2ZXJpdHlMZXZlbD86IDAgfCAxIHwgMiB8IDMgfCA0O1xuXG4gICAgLyoqXG4gICAgICogTG9nIHZlcmJvc2l0eSBsZXZlbC5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBXZWJBc3NlbWJseSBiYWNrZW5kLiBXaWxsIHN1cHBvcnQgTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUgbGF0ZXJcbiAgICAgKi9cbiAgICBsb2dWZXJib3NpdHlMZXZlbD86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFRlcm1pbmF0ZSBhbGwgaW5jb21wbGV0ZSBPcnRSdW4gY2FsbHMgYXMgc29vbiBhcyBwb3NzaWJsZSBpZiB0cnVlXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gV2ViQXNzZW1ibHkgYmFja2VuZC4gV2lsbCBzdXBwb3J0IE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlIGxhdGVyXG4gICAgICovXG4gICAgdGVybWluYXRlPzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIEEgdGFnIGZvciB0aGUgUnVuKCkgY2FsbHMgdXNpbmcgdGhpc1xuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIHRhZz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFNldCBhIHNpbmdsZSBydW4gY29uZmlndXJhdGlvbiBlbnRyeS4gU2VlXG4gICAgICogaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9vbm54cnVudGltZS9ibG9iL21haW4vaW5jbHVkZS9vbm54cnVudGltZS9jb3JlL3Nlc3Npb24vXG4gICAgICogb25ueHJ1bnRpbWVfcnVuX29wdGlvbnNfY29uZmlnX2tleXMuaFxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIFdlYkFzc2VtYmx5IGJhY2tlbmQuIFdpbGwgc3VwcG9ydCBOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSBsYXRlclxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogZXh0cmE6IHtcbiAgICAgKiAgIG1lbW9yeToge1xuICAgICAqICAgICBlbmFibGVfbWVtb3J5X2FyZW5hX3Nocmlua2FnZTogXCIxXCIsXG4gICAgICogICB9XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGV4dHJhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH1cblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiB2YWx1ZSBtZXRhZGF0YVxuXG4gIC8qKlxuICAgKiBUaGUgY29tbW9uIHBhcnQgb2YgdGhlIHZhbHVlIG1ldGFkYXRhIHR5cGUgZm9yIGJvdGggdGVuc29yIGFuZCBub24tdGVuc29yIHZhbHVlcy5cbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgVmFsdWVNZXRhZGF0YUJhc2Uge1xuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBzcGVjaWZpZWQgaW5wdXQgb3Igb3V0cHV0LlxuICAgICAqL1xuICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIHRoZSBtZXRhZGF0YSBvZiBhIG5vbi10ZW5zb3IgdmFsdWUuXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIE5vblRlbnNvclZhbHVlTWV0YWRhdGEgZXh0ZW5kcyBWYWx1ZU1ldGFkYXRhQmFzZSB7XG4gICAgLyoqXG4gICAgICogR2V0IGEgdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSB2YWx1ZSBpcyBhIHRlbnNvci5cbiAgICAgKi9cbiAgICByZWFkb25seSBpc1RlbnNvcjogZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyB0aGUgbWV0YWRhdGEgb2YgYSB0ZW5zb3IgdmFsdWUuXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIFRlbnNvclZhbHVlTWV0YWRhdGEgZXh0ZW5kcyBWYWx1ZU1ldGFkYXRhQmFzZSB7XG4gICAgLyoqXG4gICAgICogR2V0IGEgdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSB2YWx1ZSBpcyBhIHRlbnNvci5cbiAgICAgKi9cbiAgICByZWFkb25seSBpc1RlbnNvcjogdHJ1ZTtcbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGRhdGEgdHlwZSBvZiB0aGUgdGVuc29yLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IHR5cGU6IFRlbnNvci5UeXBlO1xuICAgIC8qKlxuICAgICAqIEdldCB0aGUgc2hhcGUgb2YgdGhlIHRlbnNvci5cbiAgICAgKlxuICAgICAqIElmIHRoZSBzaGFwZSBpcyBub3QgZGVmaW5lZCwgdGhlIHZhbHVlIHdpbGwgYW4gZW1wdHkgYXJyYXkuIE90aGVyd2lzZSwgaXQgd2lsbCBiZSBhbiBhcnJheSByZXByZXNlbnRpbmcgdGhlIHNoYXBlXG4gICAgICogb2YgdGhlIHRlbnNvci4gRWFjaCBlbGVtZW50IGluIHRoZSBhcnJheSBjYW4gYmUgYSBudW1iZXIgb3IgYSBzdHJpbmcuIElmIHRoZSBlbGVtZW50IGlzIGEgbnVtYmVyLCBpdCByZXByZXNlbnRzXG4gICAgICogdGhlIGNvcnJlc3BvbmRpbmcgZGltZW5zaW9uIHNpemUuIElmIHRoZSBlbGVtZW50IGlzIGEgc3RyaW5nLCBpdCByZXByZXNlbnRzIGEgc3ltYm9saWMgZGltZW5zaW9uLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IHNoYXBlOiBSZWFkb25seUFycmF5PG51bWJlciB8IHN0cmluZz47XG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyB0aGUgbWV0YWRhdGEgb2YgYSB2YWx1ZS5cbiAgICovXG4gIGV4cG9ydCB0eXBlIFZhbHVlTWV0YWRhdGEgPSBOb25UZW5zb3JWYWx1ZU1ldGFkYXRhIHwgVGVuc29yVmFsdWVNZXRhZGF0YTtcblxuICAvLyAjZW5kcmVnaW9uXG59XG5cbi8qKlxuICogUmVwcmVzZW50IGEgcnVudGltZSBpbnN0YW5jZSBvZiBhbiBPTk5YIG1vZGVsLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEluZmVyZW5jZVNlc3Npb24ge1xuICAvLyAjcmVnaW9uIHJ1bigpXG5cbiAgLyoqXG4gICAqIEV4ZWN1dGUgdGhlIG1vZGVsIGFzeW5jaHJvbm91c2x5IHdpdGggdGhlIGdpdmVuIGZlZWRzIGFuZCBvcHRpb25zLlxuICAgKlxuICAgKiBAcGFyYW0gZmVlZHMgLSBSZXByZXNlbnRhdGlvbiBvZiB0aGUgbW9kZWwgaW5wdXQuIFNlZSB0eXBlIGRlc2NyaXB0aW9uIG9mIGBJbmZlcmVuY2VTZXNzaW9uLklucHV0VHlwZWAgZm9yIGRldGFpbC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBPcHRpb25hbC4gQSBzZXQgb2Ygb3B0aW9ucyB0aGF0IGNvbnRyb2xzIHRoZSBiZWhhdmlvciBvZiBtb2RlbCBpbmZlcmVuY2UuXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgbWFwLCB3aGljaCB1c2VzIG91dHB1dCBuYW1lcyBhcyBrZXlzIGFuZCBPbm54VmFsdWUgYXMgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAqL1xuICBydW4oZmVlZHM6IEluZmVyZW5jZVNlc3Npb24uRmVlZHNUeXBlLCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uLlJldHVyblR5cGU+O1xuXG4gIC8qKlxuICAgKiBFeGVjdXRlIHRoZSBtb2RlbCBhc3luY2hyb25vdXNseSB3aXRoIHRoZSBnaXZlbiBmZWVkcywgZmV0Y2hlcyBhbmQgb3B0aW9ucy5cbiAgICpcbiAgICogQHBhcmFtIGZlZWRzIC0gUmVwcmVzZW50YXRpb24gb2YgdGhlIG1vZGVsIGlucHV0LiBTZWUgdHlwZSBkZXNjcmlwdGlvbiBvZiBgSW5mZXJlbmNlU2Vzc2lvbi5JbnB1dFR5cGVgIGZvciBkZXRhaWwuXG4gICAqIEBwYXJhbSBmZXRjaGVzIC0gUmVwcmVzZW50YXRpb24gb2YgdGhlIG1vZGVsIG91dHB1dC4gU2VlIHR5cGUgZGVzY3JpcHRpb24gb2YgYEluZmVyZW5jZVNlc3Npb24uT3V0cHV0VHlwZWAgZm9yXG4gICAqIGRldGFpbC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBPcHRpb25hbC4gQSBzZXQgb2Ygb3B0aW9ucyB0aGF0IGNvbnRyb2xzIHRoZSBiZWhhdmlvciBvZiBtb2RlbCBpbmZlcmVuY2UuXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgbWFwLCB3aGljaCB1c2VzIG91dHB1dCBuYW1lcyBhcyBrZXlzIGFuZCBPbm54VmFsdWUgYXMgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAqL1xuICBydW4oXG4gICAgZmVlZHM6IEluZmVyZW5jZVNlc3Npb24uRmVlZHNUeXBlLFxuICAgIGZldGNoZXM6IEluZmVyZW5jZVNlc3Npb24uRmV0Y2hlc1R5cGUsXG4gICAgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uLlJldHVyblR5cGU+O1xuXG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIHJlbGVhc2UoKVxuXG4gIC8qKlxuICAgKiBSZWxlYXNlIHRoZSBpbmZlcmVuY2Ugc2Vzc2lvbiBhbmQgdGhlIHVuZGVybHlpbmcgcmVzb3VyY2VzLlxuICAgKi9cbiAgcmVsZWFzZSgpOiBQcm9taXNlPHZvaWQ+O1xuXG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIHByb2ZpbGluZ1xuXG4gIC8qKlxuICAgKiBTdGFydCBwcm9maWxpbmcuXG4gICAqL1xuICBzdGFydFByb2ZpbGluZygpOiB2b2lkO1xuXG4gIC8qKlxuICAgKiBFbmQgcHJvZmlsaW5nLlxuICAgKi9cbiAgZW5kUHJvZmlsaW5nKCk6IHZvaWQ7XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gbWV0YWRhdGFcblxuICAvKipcbiAgICogR2V0IGlucHV0IG5hbWVzIG9mIHRoZSBsb2FkZWQgbW9kZWwuXG4gICAqL1xuICByZWFkb25seSBpbnB1dE5hbWVzOiByZWFkb25seSBzdHJpbmdbXTtcblxuICAvKipcbiAgICogR2V0IG91dHB1dCBuYW1lcyBvZiB0aGUgbG9hZGVkIG1vZGVsLlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0TmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBHZXQgaW5wdXQgbWV0YWRhdGEgb2YgdGhlIGxvYWRlZCBtb2RlbC5cbiAgICovXG4gIHJlYWRvbmx5IGlucHV0TWV0YWRhdGE6IHJlYWRvbmx5IEluZmVyZW5jZVNlc3Npb24uVmFsdWVNZXRhZGF0YVtdO1xuXG4gIC8qKlxuICAgKiBHZXQgb3V0cHV0IG1ldGFkYXRhIG9mIHRoZSBsb2FkZWQgbW9kZWwuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRNZXRhZGF0YTogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbi5WYWx1ZU1ldGFkYXRhW107XG5cbiAgLy8gI2VuZHJlZ2lvblxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEluZmVyZW5jZVNlc3Npb25GYWN0b3J5IHtcbiAgLy8gI3JlZ2lvbiBjcmVhdGUoKVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgaW5mZXJlbmNlIHNlc3Npb24gYW5kIGxvYWQgbW9kZWwgYXN5bmNocm9ub3VzbHkgZnJvbSBhbiBPTk5YIG1vZGVsIGZpbGUuXG4gICAqXG4gICAqIEBwYXJhbSB1cmkgLSBUaGUgVVJJIG9yIGZpbGUgcGF0aCBvZiB0aGUgbW9kZWwgdG8gbG9hZC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBzcGVjaWZ5IGNvbmZpZ3VyYXRpb24gZm9yIGNyZWF0aW5nIGEgbmV3IGluZmVyZW5jZSBzZXNzaW9uLlxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBJbmZlcmVuY2VTZXNzaW9uIG9iamVjdC5cbiAgICovXG4gIGNyZWF0ZSh1cmk6IHN0cmluZywgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb24+O1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgaW5mZXJlbmNlIHNlc3Npb24gYW5kIGxvYWQgbW9kZWwgYXN5bmNocm9ub3VzbHkgZnJvbSBhbiBhcnJheSBidWZlci5cbiAgICpcbiAgICogQHBhcmFtIGJ1ZmZlciAtIEFuIEFycmF5QnVmZmVyIHJlcHJlc2VudGF0aW9uIG9mIGFuIE9OTlggbW9kZWwuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gc3BlY2lmeSBjb25maWd1cmF0aW9uIGZvciBjcmVhdGluZyBhIG5ldyBpbmZlcmVuY2Ugc2Vzc2lvbi5cbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gSW5mZXJlbmNlU2Vzc2lvbiBvYmplY3QuXG4gICAqL1xuICBjcmVhdGUoYnVmZmVyOiBBcnJheUJ1ZmZlckxpa2UsIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uPjtcblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IGluZmVyZW5jZSBzZXNzaW9uIGFuZCBsb2FkIG1vZGVsIGFzeW5jaHJvbm91c2x5IGZyb20gc2VnbWVudCBvZiBhbiBhcnJheSBidWZlci5cbiAgICpcbiAgICogQHBhcmFtIGJ1ZmZlciAtIEFuIEFycmF5QnVmZmVyIHJlcHJlc2VudGF0aW9uIG9mIGFuIE9OTlggbW9kZWwuXG4gICAqIEBwYXJhbSBieXRlT2Zmc2V0IC0gVGhlIGJlZ2lubmluZyBvZiB0aGUgc3BlY2lmaWVkIHBvcnRpb24gb2YgdGhlIGFycmF5IGJ1ZmZlci5cbiAgICogQHBhcmFtIGJ5dGVMZW5ndGggLSBUaGUgbGVuZ3RoIGluIGJ5dGVzIG9mIHRoZSBhcnJheSBidWZmZXIuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gc3BlY2lmeSBjb25maWd1cmF0aW9uIGZvciBjcmVhdGluZyBhIG5ldyBpbmZlcmVuY2Ugc2Vzc2lvbi5cbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gSW5mZXJlbmNlU2Vzc2lvbiBvYmplY3QuXG4gICAqL1xuICBjcmVhdGUoXG4gICAgYnVmZmVyOiBBcnJheUJ1ZmZlckxpa2UsXG4gICAgYnl0ZU9mZnNldDogbnVtYmVyLFxuICAgIGJ5dGVMZW5ndGg/OiBudW1iZXIsXG4gICAgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMsXG4gICk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbj47XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBpbmZlcmVuY2Ugc2Vzc2lvbiBhbmQgbG9hZCBtb2RlbCBhc3luY2hyb25vdXNseSBmcm9tIGEgVWludDhBcnJheS5cbiAgICpcbiAgICogQHBhcmFtIGJ1ZmZlciAtIEEgVWludDhBcnJheSByZXByZXNlbnRhdGlvbiBvZiBhbiBPTk5YIG1vZGVsLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIHNwZWNpZnkgY29uZmlndXJhdGlvbiBmb3IgY3JlYXRpbmcgYSBuZXcgaW5mZXJlbmNlIHNlc3Npb24uXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIEluZmVyZW5jZVNlc3Npb24gb2JqZWN0LlxuICAgKi9cbiAgY3JlYXRlKGJ1ZmZlcjogVWludDhBcnJheSwgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb24+O1xuXG4gIC8vICNlbmRyZWdpb25cbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuZXhwb3J0IGNvbnN0IEluZmVyZW5jZVNlc3Npb246IEluZmVyZW5jZVNlc3Npb25GYWN0b3J5ID0gSW5mZXJlbmNlU2Vzc2lvbkltcGw7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IE9wdGlvbnNGb3JtYXQsIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycywgT3B0aW9uc1RlbnNvckxheW91dCB9IGZyb20gJy4vdGVuc29yLWZhY3RvcnkuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvclRvRGF0YVVybE9wdGlvbnMgZXh0ZW5kcyBPcHRpb25zVGVuc29yTGF5b3V0LCBPcHRpb25zRm9ybWF0LCBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMge31cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JUb0ltYWdlRGF0YU9wdGlvbnMgZXh0ZW5kcyBPcHRpb25zVGVuc29yTGF5b3V0LCBPcHRpb25zRm9ybWF0LCBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMge31cblxuZXhwb3J0IGludGVyZmFjZSBDb252ZXJzaW9uVXRpbHMge1xuICAvKipcbiAgICogY3JlYXRlcyBhIERhdGFVUkwgaW5zdGFuY2UgZnJvbSB0ZW5zb3JcbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBbiBvcHRpb25hbCBvYmplY3QgcmVwcmVzZW50aW5nIG9wdGlvbnMgZm9yIGNyZWF0aW5nIGEgRGF0YVVSTCBpbnN0YW5jZSBmcm9tIHRoZSB0ZW5zb3IuXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgZGVmYXVsdCBzZXR0aW5ncyB3aWxsIGJlIGFwcGxpZWQ6XG4gICAqIC0gYGZvcm1hdGA6IGAnUkdCJ2BcbiAgICogLSBgdGVuc29yTGF5b3V0YDogYCdOQ0hXJ2BcbiAgICogQHJldHVybnMgYSBEYXRhVVJMIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGltYWdlIGNvbnZlcnRlZCBmcm9tIHRlbnNvciBkYXRhXG4gICAqL1xuICB0b0RhdGFVUkwob3B0aW9ucz86IFRlbnNvclRvRGF0YVVybE9wdGlvbnMpOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIGNyZWF0ZXMgYW4gSW1hZ2VEYXRhIGluc3RhbmNlIGZyb20gdGVuc29yXG4gICAqXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQW4gb3B0aW9uYWwgb2JqZWN0IHJlcHJlc2VudGluZyBvcHRpb25zIGZvciBjcmVhdGluZyBhbiBJbWFnZURhdGEgaW5zdGFuY2UgZnJvbSB0aGUgdGVuc29yLlxuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGRlZmF1bHQgc2V0dGluZ3Mgd2lsbCBiZSBhcHBsaWVkOlxuICAgKiAtIGBmb3JtYXRgOiBgJ1JHQidgXG4gICAqIC0gYHRlbnNvckxheW91dGA6IGAnTkNIVydgXG4gICAqIEByZXR1cm5zIGFuIEltYWdlRGF0YSBpbnN0YW5jZSByZXByZXNlbnRpbmcgdGhlIGltYWdlIGNvbnZlcnRlZCBmcm9tIHRlbnNvciBkYXRhXG4gICAqL1xuICB0b0ltYWdlRGF0YShvcHRpb25zPzogVGVuc29yVG9JbWFnZURhdGFPcHRpb25zKTogSW1hZ2VEYXRhO1xufVxuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3IsIFR5cGVkVGVuc29yIH0gZnJvbSAnLi90ZW5zb3IuanMnO1xuXG5leHBvcnQgdHlwZSBJbWFnZUZvcm1hdCA9ICdSR0InIHwgJ1JHQkEnIHwgJ0JHUicgfCAnUkJHJztcbmV4cG9ydCB0eXBlIEltYWdlVGVuc29yTGF5b3V0ID0gJ05IV0MnIHwgJ05DSFcnO1xuXG4vLyB0aGUgZm9sbG93aW5nIHJlZ2lvbiBjb250YWlucyB0eXBlIGRlZmluaXRpb25zIGZvciBjb25zdHJ1Y3RpbmcgdGVuc29yIGZyb20gYSBzcGVjaWZpYyBsb2NhdGlvbi5cblxuLy8gI3JlZ2lvbiB0eXBlcyBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBzcGVjaWZpYyBsb2NhdGlvblxuXG4vKipcbiAqIHJlcHJlc2VudCBjb21tb24gcHJvcGVydGllcyBvZiB0aGUgcGFyYW1ldGVyIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIHNwZWNpZmljIGxvY2F0aW9uLlxuICovXG5pbnRlcmZhY2UgQ29tbW9uQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+IGV4dGVuZHMgUGljazxUZW5zb3IsICdkaW1zJz4ge1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgZGF0YSB0eXBlIG9mIHRoZSB0ZW5zb3IuXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBUO1xufVxuXG4vKipcbiAqIHJlcHJlc2VudCB0aGUgcGFyYW1ldGVyIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIEdQVSByZXNvdXJjZS5cbiAqL1xuaW50ZXJmYWNlIEdwdVJlc291cmNlQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQgZXh0ZW5kcyBUZW5zb3IuVHlwZT4ge1xuICAvKipcbiAgICogYW4gb3B0aW9uYWwgY2FsbGJhY2sgZnVuY3Rpb24gdG8gZG93bmxvYWQgZGF0YSBmcm9tIEdQVSB0byBDUFUuXG4gICAqXG4gICAqIElmIG5vdCBwcm92aWRlZCwgdGhlIHRlbnNvciB0cmVhdCB0aGUgR1BVIGRhdGEgYXMgZXh0ZXJuYWwgcmVzb3VyY2UuXG4gICAqL1xuICBkb3dubG9hZD8oKTogUHJvbWlzZTxUZW5zb3IuRGF0YVR5cGVNYXBbVF0+O1xuXG4gIC8qKlxuICAgKiBhbiBvcHRpb25hbCBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgY2FsbGVkIHdoZW4gdGhlIHRlbnNvciBpcyBkaXNwb3NlZC5cbiAgICpcbiAgICogSWYgbm90IHByb3ZpZGVkLCB0aGUgdGVuc29yIHRyZWF0IHRoZSBHUFUgZGF0YSBhcyBleHRlcm5hbCByZXNvdXJjZS5cbiAgICovXG4gIGRpc3Bvc2U/KCk6IHZvaWQ7XG59XG5cbi8qKlxuICogcmVwcmVzZW50IHRoZSBwYXJhbWV0ZXIgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgcGlubmVkIENQVSBidWZmZXJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDcHVQaW5uZWRDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VCBleHRlbmRzIFRlbnNvci5DcHVQaW5uZWREYXRhVHlwZXMgPSBUZW5zb3IuQ3B1UGlubmVkRGF0YVR5cGVzPlxuICBleHRlbmRzIENvbW1vbkNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPiB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBsb2NhdGlvbiBvZiB0aGUgZGF0YSB0byBiZSAnY3B1LXBpbm5lZCcuXG4gICAqL1xuICByZWFkb25seSBsb2NhdGlvbjogJ2NwdS1waW5uZWQnO1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgQ1BVIHBpbm5lZCBidWZmZXIgdGhhdCBob2xkcyB0aGUgdGVuc29yIGRhdGEuXG4gICAqL1xuICByZWFkb25seSBkYXRhOiBUZW5zb3IuRGF0YVR5cGVNYXBbVF07XG59XG5cbi8qKlxuICogcmVwcmVzZW50IHRoZSBwYXJhbWV0ZXIgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgV2ViR0wgdGV4dHVyZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRleHR1cmVDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VCBleHRlbmRzIFRlbnNvci5UZXh0dXJlRGF0YVR5cGVzID0gVGVuc29yLlRleHR1cmVEYXRhVHlwZXM+XG4gIGV4dGVuZHMgQ29tbW9uQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+LFxuICAgIEdwdVJlc291cmNlQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+IHtcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIGxvY2F0aW9uIG9mIHRoZSBkYXRhIHRvIGJlICd0ZXh0dXJlJy5cbiAgICovXG4gIHJlYWRvbmx5IGxvY2F0aW9uOiAndGV4dHVyZSc7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBXZWJHTCB0ZXh0dXJlIHRoYXQgaG9sZHMgdGhlIHRlbnNvciBkYXRhLlxuICAgKi9cbiAgcmVhZG9ubHkgdGV4dHVyZTogVGVuc29yLlRleHR1cmVUeXBlO1xufVxuXG4vKipcbiAqIHJlcHJlc2VudCB0aGUgcGFyYW1ldGVyIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIFdlYkdQVSBidWZmZXJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHcHVCdWZmZXJDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VCBleHRlbmRzIFRlbnNvci5HcHVCdWZmZXJEYXRhVHlwZXMgPSBUZW5zb3IuR3B1QnVmZmVyRGF0YVR5cGVzPlxuICBleHRlbmRzIENvbW1vbkNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPixcbiAgICBHcHVSZXNvdXJjZUNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPiB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBsb2NhdGlvbiBvZiB0aGUgZGF0YSB0byBiZSAnZ3B1LWJ1ZmZlcicuXG4gICAqL1xuICByZWFkb25seSBsb2NhdGlvbjogJ2dwdS1idWZmZXInO1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgV2ViR1BVIGJ1ZmZlciB0aGF0IGhvbGRzIHRoZSB0ZW5zb3IgZGF0YS5cbiAgICovXG4gIHJlYWRvbmx5IGdwdUJ1ZmZlcjogVGVuc29yLkdwdUJ1ZmZlclR5cGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTUxUZW5zb3JDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VCBleHRlbmRzIFRlbnNvci5NTFRlbnNvckRhdGFUeXBlcyA9IFRlbnNvci5NTFRlbnNvckRhdGFUeXBlcz5cbiAgZXh0ZW5kcyBDb21tb25Db25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4sXG4gICAgR3B1UmVzb3VyY2VDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4ge1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgbG9jYXRpb24gb2YgdGhlIGRhdGEgdG8gYmUgJ21sLXRlbnNvcicuXG4gICAqL1xuICByZWFkb25seSBsb2NhdGlvbjogJ21sLXRlbnNvcic7XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIFdlYk5OIE1MVGVuc29yIHRoYXQgaG9sZHMgdGhlIHRlbnNvciBkYXRhLlxuICAgKi9cbiAgcmVhZG9ubHkgbWxUZW5zb3I6IFRlbnNvci5NTFRlbnNvclR5cGU7XG59XG5cbi8vICNlbmRyZWdpb25cblxuLy8gdGhlIGZvbGxvd2luZyByZWdpb24gY29udGFpbnMgdHlwZSBkZWZpbml0aW9ucyBvZiBlYWNoIGluZGl2aWR1YWwgb3B0aW9ucy5cbi8vIHRoZSB0ZW5zb3IgZmFjdG9yeSBmdW5jdGlvbnMgdXNlIGEgY29tcG9zaXRpb24gb2YgdGhvc2Ugb3B0aW9ucyBhcyB0aGUgcGFyYW1ldGVyIHR5cGUuXG5cbi8vICNyZWdpb24gT3B0aW9ucyBmaWVsZHNcblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zRm9ybWF0IHtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyB0aGUgaW1hZ2UgZm9ybWF0IHJlcHJlc2VudGVkIGluIFJHQkEgY29sb3Igc3BhY2UuXG4gICAqL1xuICBmb3JtYXQ/OiBJbWFnZUZvcm1hdDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zVGVuc29yRm9ybWF0IHtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyB0aGUgaW1hZ2UgZm9ybWF0IG9mIHRoZSB0ZW5zb3IuXG4gICAqXG4gICAqIE5PVEU6IHRoaXMgaXMgZGlmZmVyZW50IGZyb20gb3B0aW9uICdmb3JtYXQnLiBXaGlsZSBvcHRpb24gJ2Zvcm1hdCcgcmVwcmVzZW50cyB0aGUgb3JpZ2luYWwgaW1hZ2UsICd0ZW5zb3JGb3JtYXQnXG4gICAqIHJlcHJlc2VudHMgdGhlIHRhcmdldCBmb3JtYXQgb2YgdGhlIHRlbnNvci4gQSB0cmFuc3Bvc2Ugd2lsbCBiZSBwZXJmb3JtZWQgaWYgdGhleSBhcmUgZGlmZmVyZW50LlxuICAgKi9cbiAgdGVuc29yRm9ybWF0PzogSW1hZ2VGb3JtYXQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uc1RlbnNvckRhdGFUeXBlIHtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyB0aGUgZGF0YSB0eXBlIG9mIHRoZSB0ZW5zb3IuXG4gICAqL1xuICBkYXRhVHlwZT86ICdmbG9hdDMyJyB8ICd1aW50OCc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uc1RlbnNvckxheW91dCB7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIHRlbnNvciBsYXlvdXQgd2hlbiByZXByZXNlbnRpbmcgZGF0YSBvZiBvbmUgb3IgbW9yZSBpbWFnZShzKS5cbiAgICovXG4gIHRlbnNvckxheW91dD86IEltYWdlVGVuc29yTGF5b3V0O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvbnNEaW1lbnNpb25zIHtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyB0aGUgaW1hZ2UgaGVpZ2h0IGluIHBpeGVsXG4gICAqL1xuICBoZWlnaHQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIGltYWdlIHdpZHRoIGluIHBpeGVsXG4gICAqL1xuICB3aWR0aD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25SZXNpemVkRGltZW5zaW9ucyB7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIHJlc2l6ZWQgaGVpZ2h0LiBJZiBvbWl0dGVkLCBvcmlnaW5hbCBoZWlnaHQgd2lsbCBiZSB1c2VkLlxuICAgKi9cbiAgcmVzaXplZEhlaWdodD86IG51bWJlcjtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyByZXNpemVkIHdpZHRoIC0gY2FuIGJlIGFjY2Vzc2VkIHZpYSB0ZW5zb3IgZGltZW5zaW9ucyBhcyB3ZWxsXG4gICAqL1xuICByZXNpemVkV2lkdGg/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzIHtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyBub3JtYWxpemF0aW9uIHBhcmFtZXRlcnMgd2hlbiBwcmVwcm9jZXNzaW5nIHRoZSBpbWFnZSBhcyBtb2RlbCBpbnB1dC5cbiAgICpcbiAgICogRGF0YSBlbGVtZW50IGFyZSByYW5nZWQgZnJvbSAwIHRvIDI1NS5cbiAgICovXG4gIG5vcm0/OiB7XG4gICAgLyoqXG4gICAgICogVGhlICdiaWFzJyB2YWx1ZSBmb3IgaW1hZ2Ugbm9ybWFsaXphdGlvbi5cbiAgICAgKiAtIElmIG9taXR0ZWQsIHVzZSBkZWZhdWx0IHZhbHVlIDAuXG4gICAgICogLSBJZiBpdCdzIGEgc2luZ2xlIG51bWJlciwgYXBwbHkgdG8gZWFjaCBjaGFubmVsXG4gICAgICogLSBJZiBpdCdzIGFuIGFycmF5IG9mIDMgb3IgNCBudW1iZXJzLCBhcHBseSBlbGVtZW50LXdpc2UuIE51bWJlciBvZiBlbGVtZW50cyBuZWVkIHRvIG1hdGNoIHRoZSBudW1iZXIgb2YgY2hhbm5lbHNcbiAgICAgKiBmb3IgdGhlIGNvcnJlc3BvbmRpbmcgaW1hZ2UgZm9ybWF0XG4gICAgICovXG4gICAgYmlhcz86IG51bWJlciB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICAgIC8qKlxuICAgICAqIFRoZSAnbWVhbicgdmFsdWUgZm9yIGltYWdlIG5vcm1hbGl6YXRpb24uXG4gICAgICogLSBJZiBvbWl0dGVkLCB1c2UgZGVmYXVsdCB2YWx1ZSAyNTUuXG4gICAgICogLSBJZiBpdCdzIGEgc2luZ2xlIG51bWJlciwgYXBwbHkgdG8gZWFjaCBjaGFubmVsXG4gICAgICogLSBJZiBpdCdzIGFuIGFycmF5IG9mIDMgb3IgNCBudW1iZXJzLCBhcHBseSBlbGVtZW50LXdpc2UuIE51bWJlciBvZiBlbGVtZW50cyBuZWVkIHRvIG1hdGNoIHRoZSBudW1iZXIgb2YgY2hhbm5lbHNcbiAgICAgKiBmb3IgdGhlIGNvcnJlc3BvbmRpbmcgaW1hZ2UgZm9ybWF0XG4gICAgICovXG4gICAgbWVhbj86IG51bWJlciB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICB9O1xufVxuXG4vLyAjZW5kcmVnaW9uXG5cbi8vICNyZWdpb24gT3B0aW9ucyBjb21wb3NpdGlvblxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckZyb21JbWFnZURhdGFPcHRpb25zXG4gIGV4dGVuZHMgT3B0aW9uUmVzaXplZERpbWVuc2lvbnMsXG4gICAgT3B0aW9uc1RlbnNvckZvcm1hdCxcbiAgICBPcHRpb25zVGVuc29yTGF5b3V0LFxuICAgIE9wdGlvbnNUZW5zb3JEYXRhVHlwZSxcbiAgICBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMge31cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JGcm9tSW1hZ2VFbGVtZW50T3B0aW9uc1xuICBleHRlbmRzIE9wdGlvblJlc2l6ZWREaW1lbnNpb25zLFxuICAgIE9wdGlvbnNUZW5zb3JGb3JtYXQsXG4gICAgT3B0aW9uc1RlbnNvckxheW91dCxcbiAgICBPcHRpb25zVGVuc29yRGF0YVR5cGUsXG4gICAgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yRnJvbVVybE9wdGlvbnNcbiAgZXh0ZW5kcyBPcHRpb25zRGltZW5zaW9ucyxcbiAgICBPcHRpb25SZXNpemVkRGltZW5zaW9ucyxcbiAgICBPcHRpb25zVGVuc29yRm9ybWF0LFxuICAgIE9wdGlvbnNUZW5zb3JMYXlvdXQsXG4gICAgT3B0aW9uc1RlbnNvckRhdGFUeXBlLFxuICAgIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycyB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckZyb21JbWFnZUJpdG1hcE9wdGlvbnNcbiAgZXh0ZW5kcyBPcHRpb25SZXNpemVkRGltZW5zaW9ucyxcbiAgICBPcHRpb25zVGVuc29yRm9ybWF0LFxuICAgIE9wdGlvbnNUZW5zb3JMYXlvdXQsXG4gICAgT3B0aW9uc1RlbnNvckRhdGFUeXBlLFxuICAgIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycyB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckZyb21UZXh0dXJlT3B0aW9uczxUIGV4dGVuZHMgVGVuc29yLlRleHR1cmVEYXRhVHlwZXM+XG4gIGV4dGVuZHMgUmVxdWlyZWQ8T3B0aW9uc0RpbWVuc2lvbnM+LFxuICAgIE9wdGlvbnNGb3JtYXQsXG4gICAgR3B1UmVzb3VyY2VDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4gLyogVE9ETzogYWRkIG1vcmUgKi8ge31cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JGcm9tR3B1QnVmZmVyT3B0aW9uczxUIGV4dGVuZHMgVGVuc29yLkdwdUJ1ZmZlckRhdGFUeXBlcz5cbiAgZXh0ZW5kcyBQaWNrPFRlbnNvciwgJ2RpbXMnPixcbiAgICBHcHVSZXNvdXJjZUNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPiB7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIGRhdGEgdHlwZSBvZiB0aGUgdGVuc29yLlxuICAgKi9cbiAgZGF0YVR5cGU/OiBUO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckZyb21NTFRlbnNvck9wdGlvbnM8VCBleHRlbmRzIFRlbnNvci5NTFRlbnNvckRhdGFUeXBlcz5cbiAgZXh0ZW5kcyBQaWNrPFRlbnNvciwgJ2RpbXMnPixcbiAgICBHcHVSZXNvdXJjZUNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPiB7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIGRhdGEgdHlwZSBvZiB0aGUgdGVuc29yLlxuICAgKi9cbiAgZGF0YVR5cGU/OiBUO1xufVxuXG4vLyAjZW5kcmVnaW9uXG5cbi8qKlxuICogdHlwZSBUZW5zb3JGYWN0b3J5IGRlZmluZXMgdGhlIGZhY3RvcnkgZnVuY3Rpb25zIG9mICdUZW5zb3InIHRvIGNyZWF0ZSB0ZW5zb3IgaW5zdGFuY2VzIGZyb20gZXhpc3RpbmcgZGF0YSBvclxuICogcmVzb3VyY2VzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckZhY3Rvcnkge1xuICAvKipcbiAgICogY3JlYXRlIGEgdGVuc29yIGZyb20gYW4gSW1hZ2VEYXRhIG9iamVjdFxuICAgKlxuICAgKiBAcGFyYW0gaW1hZ2VEYXRhIC0gdGhlIEltYWdlRGF0YSBvYmplY3QgdG8gY3JlYXRlIHRlbnNvciBmcm9tXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQW4gb3B0aW9uYWwgb2JqZWN0IHJlcHJlc2VudGluZyBvcHRpb25zIGZvciBjcmVhdGluZyB0ZW5zb3IgZnJvbSBJbWFnZURhdGEuXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgZGVmYXVsdCBzZXR0aW5ncyB3aWxsIGJlIGFwcGxpZWQ6XG4gICAqIC0gYHRlbnNvckZvcm1hdGA6IGAnUkdCJ2BcbiAgICogLSBgdGVuc29yTGF5b3V0YDogYCdOQ0hXJ2BcbiAgICogLSBgZGF0YVR5cGVgOiBgJ2Zsb2F0MzInYFxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIHRlbnNvciBvYmplY3RcbiAgICovXG4gIGZyb21JbWFnZShcbiAgICBpbWFnZURhdGE6IEltYWdlRGF0YSxcbiAgICBvcHRpb25zPzogVGVuc29yRnJvbUltYWdlRGF0YU9wdGlvbnMsXG4gICk6IFByb21pc2U8VHlwZWRUZW5zb3I8J2Zsb2F0MzInPiB8IFR5cGVkVGVuc29yPCd1aW50OCc+PjtcblxuICAvKipcbiAgICogY3JlYXRlIGEgdGVuc29yIGZyb20gYSBIVE1MSW1hZ2VFbGVtZW50IG9iamVjdFxuICAgKlxuICAgKiBAcGFyYW0gaW1hZ2VFbGVtZW50IC0gdGhlIEhUTUxJbWFnZUVsZW1lbnQgb2JqZWN0IHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIG9iamVjdCByZXByZXNlbnRpbmcgb3B0aW9ucyBmb3IgY3JlYXRpbmcgdGVuc29yIGZyb20gSFRNTEltYWdlRWxlbWVudC5cbiAgICpcbiAgICogVGhlIGZvbGxvd2luZyBkZWZhdWx0IHNldHRpbmdzIHdpbGwgYmUgYXBwbGllZDpcbiAgICogLSBgdGVuc29yRm9ybWF0YDogYCdSR0InYFxuICAgKiAtIGB0ZW5zb3JMYXlvdXRgOiBgJ05DSFcnYFxuICAgKiAtIGBkYXRhVHlwZWA6IGAnZmxvYXQzMidgXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgdGVuc29yIG9iamVjdFxuICAgKi9cbiAgZnJvbUltYWdlKFxuICAgIGltYWdlRWxlbWVudDogSFRNTEltYWdlRWxlbWVudCxcbiAgICBvcHRpb25zPzogVGVuc29yRnJvbUltYWdlRWxlbWVudE9wdGlvbnMsXG4gICk6IFByb21pc2U8VHlwZWRUZW5zb3I8J2Zsb2F0MzInPiB8IFR5cGVkVGVuc29yPCd1aW50OCc+PjtcblxuICAvKipcbiAgICogY3JlYXRlIGEgdGVuc29yIGZyb20gVVJMXG4gICAqXG4gICAqIEBwYXJhbSB1cmxTb3VyY2UgLSBhIHN0cmluZyBhcyBhIFVSTCB0byB0aGUgaW1hZ2Ugb3IgYSBkYXRhIFVSTCBjb250YWluaW5nIHRoZSBpbWFnZSBkYXRhLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIG9iamVjdCByZXByZXNlbnRpbmcgb3B0aW9ucyBmb3IgY3JlYXRpbmcgdGVuc29yIGZyb20gVVJMLlxuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGRlZmF1bHQgc2V0dGluZ3Mgd2lsbCBiZSBhcHBsaWVkOlxuICAgKiAtIGB0ZW5zb3JGb3JtYXRgOiBgJ1JHQidgXG4gICAqIC0gYHRlbnNvckxheW91dGA6IGAnTkNIVydgXG4gICAqIC0gYGRhdGFUeXBlYDogYCdmbG9hdDMyJ2BcbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSB0ZW5zb3Igb2JqZWN0XG4gICAqL1xuICBmcm9tSW1hZ2UodXJsU291cmNlOiBzdHJpbmcsIG9wdGlvbnM/OiBUZW5zb3JGcm9tVXJsT3B0aW9ucyk6IFByb21pc2U8VHlwZWRUZW5zb3I8J2Zsb2F0MzInPiB8IFR5cGVkVGVuc29yPCd1aW50OCc+PjtcblxuICAvKipcbiAgICogY3JlYXRlIGEgdGVuc29yIGZyb20gYW4gSW1hZ2VCaXRtYXAgb2JqZWN0XG4gICAqXG4gICAqIEBwYXJhbSBiaXRtYXAgLSB0aGUgSW1hZ2VCaXRtYXAgb2JqZWN0IHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIG9iamVjdCByZXByZXNlbnRpbmcgb3B0aW9ucyBmb3IgY3JlYXRpbmcgdGVuc29yIGZyb20gVVJMLlxuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGRlZmF1bHQgc2V0dGluZ3Mgd2lsbCBiZSBhcHBsaWVkOlxuICAgKiAtIGB0ZW5zb3JGb3JtYXRgOiBgJ1JHQidgXG4gICAqIC0gYHRlbnNvckxheW91dGA6IGAnTkNIVydgXG4gICAqIC0gYGRhdGFUeXBlYDogYCdmbG9hdDMyJ2BcbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSB0ZW5zb3Igb2JqZWN0XG4gICAqL1xuICBmcm9tSW1hZ2UoXG4gICAgYml0bWFwOiBJbWFnZUJpdG1hcCxcbiAgICBvcHRpb25zOiBUZW5zb3JGcm9tSW1hZ2VCaXRtYXBPcHRpb25zLFxuICApOiBQcm9taXNlPFR5cGVkVGVuc29yPCdmbG9hdDMyJz4gfCBUeXBlZFRlbnNvcjwndWludDgnPj47XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhIHRlbnNvciBmcm9tIGEgV2ViR0wgdGV4dHVyZVxuICAgKlxuICAgKiBAcGFyYW0gdGV4dHVyZSAtIHRoZSBXZWJHTFRleHR1cmUgb2JqZWN0IHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIG9iamVjdCByZXByZXNlbnRpbmcgb3B0aW9ucyBmb3IgY3JlYXRpbmcgdGVuc29yIGZyb20gV2ViR0wgdGV4dHVyZS5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgaW5jbHVkZSBmb2xsb3dpbmcgcHJvcGVydGllczpcbiAgICogLSBgd2lkdGhgOiB0aGUgd2lkdGggb2YgdGhlIHRleHR1cmUuIFJlcXVpcmVkLlxuICAgKiAtIGBoZWlnaHRgOiB0aGUgaGVpZ2h0IG9mIHRoZSB0ZXh0dXJlLiBSZXF1aXJlZC5cbiAgICogLSBgZm9ybWF0YDogdGhlIGZvcm1hdCBvZiB0aGUgdGV4dHVyZS4gSWYgb21pdHRlZCwgYXNzdW1lICdSR0JBJy5cbiAgICogLSBgZG93bmxvYWRgOiBhbiBvcHRpb25hbCBmdW5jdGlvbiB0byBkb3dubG9hZCB0aGUgdGVuc29yIGRhdGEgZnJvbSBHUFUgdG8gQ1BVLiBJZiBvbWl0dGVkLCB0aGUgR1BVIGRhdGFcbiAgICogd2lsbCBub3QgYmUgYWJsZSB0byBkb3dubG9hZC4gVXN1YWxseSwgdGhpcyBpcyBwcm92aWRlZCBieSBhIEdQVSBiYWNrZW5kIGZvciB0aGUgaW5mZXJlbmNlIG91dHB1dHMuIFVzZXJzIGRvbid0XG4gICAqIG5lZWQgdG8gcHJvdmlkZSB0aGlzIGZ1bmN0aW9uLlxuICAgKiAtIGBkaXNwb3NlYDogYW4gb3B0aW9uYWwgZnVuY3Rpb24gdG8gZGlzcG9zZSB0aGUgdGVuc29yIGRhdGEgb24gR1BVLiBJZiBvbWl0dGVkLCB0aGUgR1BVIGRhdGEgd2lsbCBub3QgYmUgZGlzcG9zZWQuXG4gICAqIFVzdWFsbHksIHRoaXMgaXMgcHJvdmlkZWQgYnkgYSBHUFUgYmFja2VuZCBmb3IgdGhlIGluZmVyZW5jZSBvdXRwdXRzLiBVc2VycyBkb24ndCBuZWVkIHRvIHByb3ZpZGUgdGhpcyBmdW5jdGlvbi5cbiAgICpcbiAgICogQHJldHVybnMgYSB0ZW5zb3Igb2JqZWN0XG4gICAqL1xuICBmcm9tVGV4dHVyZTxUIGV4dGVuZHMgVGVuc29yLlRleHR1cmVEYXRhVHlwZXMgPSAnZmxvYXQzMic+KFxuICAgIHRleHR1cmU6IFRlbnNvci5UZXh0dXJlVHlwZSxcbiAgICBvcHRpb25zOiBUZW5zb3JGcm9tVGV4dHVyZU9wdGlvbnM8VD4sXG4gICk6IFR5cGVkVGVuc29yPCdmbG9hdDMyJz47XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhIHRlbnNvciBmcm9tIGEgV2ViR1BVIGJ1ZmZlclxuICAgKlxuICAgKiBAcGFyYW0gYnVmZmVyIC0gdGhlIEdQVUJ1ZmZlciBvYmplY3QgdG8gY3JlYXRlIHRlbnNvciBmcm9tXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQW4gb3B0aW9uYWwgb2JqZWN0IHJlcHJlc2VudGluZyBvcHRpb25zIGZvciBjcmVhdGluZyB0ZW5zb3IgZnJvbSBXZWJHUFUgYnVmZmVyLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBpbmNsdWRlIGZvbGxvd2luZyBwcm9wZXJ0aWVzOlxuICAgKiAtIGBkYXRhVHlwZWA6IHRoZSBkYXRhIHR5cGUgb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYXNzdW1lICdmbG9hdDMyJy5cbiAgICogLSBgZGltc2A6IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gUmVxdWlyZWQuXG4gICAqIC0gYGRvd25sb2FkYDogYW4gb3B0aW9uYWwgZnVuY3Rpb24gdG8gZG93bmxvYWQgdGhlIHRlbnNvciBkYXRhIGZyb20gR1BVIHRvIENQVS4gSWYgb21pdHRlZCwgdGhlIEdQVSBkYXRhXG4gICAqIHdpbGwgbm90IGJlIGFibGUgdG8gZG93bmxvYWQuIFVzdWFsbHksIHRoaXMgaXMgcHJvdmlkZWQgYnkgYSBHUFUgYmFja2VuZCBmb3IgdGhlIGluZmVyZW5jZSBvdXRwdXRzLiBVc2VycyBkb24ndFxuICAgKiBuZWVkIHRvIHByb3ZpZGUgdGhpcyBmdW5jdGlvbi5cbiAgICogLSBgZGlzcG9zZWA6IGFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRvIGRpc3Bvc2UgdGhlIHRlbnNvciBkYXRhIG9uIEdQVS4gSWYgb21pdHRlZCwgdGhlIEdQVSBkYXRhIHdpbGwgbm90IGJlIGRpc3Bvc2VkLlxuICAgKiBVc3VhbGx5LCB0aGlzIGlzIHByb3ZpZGVkIGJ5IGEgR1BVIGJhY2tlbmQgZm9yIHRoZSBpbmZlcmVuY2Ugb3V0cHV0cy4gVXNlcnMgZG9uJ3QgbmVlZCB0byBwcm92aWRlIHRoaXMgZnVuY3Rpb24uXG4gICAqXG4gICAqIEByZXR1cm5zIGEgdGVuc29yIG9iamVjdFxuICAgKi9cbiAgZnJvbUdwdUJ1ZmZlcjxUIGV4dGVuZHMgVGVuc29yLkdwdUJ1ZmZlckRhdGFUeXBlcz4oXG4gICAgYnVmZmVyOiBUZW5zb3IuR3B1QnVmZmVyVHlwZSxcbiAgICBvcHRpb25zOiBUZW5zb3JGcm9tR3B1QnVmZmVyT3B0aW9uczxUPixcbiAgKTogVHlwZWRUZW5zb3I8VD47XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhIHRlbnNvciBmcm9tIGEgV2ViTk4gTUxUZW5zb3JcbiAgICpcbiAgICogQHBhcmFtIHRlbnNvciAtIHRoZSBNTFRlbnNvciBvYmplY3QgdG8gY3JlYXRlIHRlbnNvciBmcm9tXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQW4gb3B0aW9uYWwgb2JqZWN0IHJlcHJlc2VudGluZyBvcHRpb25zIGZvciBjcmVhdGluZyB0ZW5zb3IgZnJvbSBhIFdlYk5OIE1MVGVuc29yLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBpbmNsdWRlIGZvbGxvd2luZyBwcm9wZXJ0aWVzOlxuICAgKiAtIGBkYXRhVHlwZWA6IHRoZSBkYXRhIHR5cGUgb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYXNzdW1lICdmbG9hdDMyJy5cbiAgICogLSBgZGltc2A6IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gUmVxdWlyZWQuXG4gICAqIC0gYGRvd25sb2FkYDogYW4gb3B0aW9uYWwgZnVuY3Rpb24gdG8gZG93bmxvYWQgdGhlIHRlbnNvciBkYXRhIGZyb20gdGhlIE1MVGVuc29yIHRvIENQVS4gSWYgb21pdHRlZCwgdGhlIE1MVGVuc29yXG4gICAqIGRhdGEgd2lsbCBub3QgYmUgYWJsZSB0byBkb3dubG9hZC4gVXN1YWxseSwgdGhpcyBpcyBwcm92aWRlZCBieSB0aGUgV2ViTk4gYmFja2VuZCBmb3IgdGhlIGluZmVyZW5jZSBvdXRwdXRzLlxuICAgKiBVc2VycyBkb24ndCBuZWVkIHRvIHByb3ZpZGUgdGhpcyBmdW5jdGlvbi5cbiAgICogLSBgZGlzcG9zZWA6IGFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRvIGRpc3Bvc2UgdGhlIHRlbnNvciBkYXRhIG9uIHRoZSBXZWJOTiBNTFRlbnNvci4gSWYgb21pdHRlZCwgdGhlIE1MVGVuc29yIHdpbGxcbiAgICogbm90IGJlIGRpc3Bvc2VkLiBVc3VhbGx5LCB0aGlzIGlzIHByb3ZpZGVkIGJ5IHRoZSBXZWJOTiBiYWNrZW5kIGZvciB0aGUgaW5mZXJlbmNlIG91dHB1dHMuIFVzZXJzIGRvbid0IG5lZWQgdG9cbiAgICogcHJvdmlkZSB0aGlzIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJucyBhIHRlbnNvciBvYmplY3RcbiAgICovXG4gIGZyb21NTFRlbnNvcjxUIGV4dGVuZHMgVGVuc29yLk1MVGVuc29yRGF0YVR5cGVzPihcbiAgICB0ZW5zb3I6IFRlbnNvci5NTFRlbnNvclR5cGUsXG4gICAgb3B0aW9uczogVGVuc29yRnJvbU1MVGVuc29yT3B0aW9uczxUPixcbiAgKTogVHlwZWRUZW5zb3I8VD47XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhIHRlbnNvciBmcm9tIGEgcHJlLWFsbG9jYXRlZCBidWZmZXIuIFRoZSBidWZmZXIgd2lsbCBiZSB1c2VkIGFzIGEgcGlubmVkIGJ1ZmZlci5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgLSB0aGUgdGVuc29yIGVsZW1lbnQgdHlwZS5cbiAgICogQHBhcmFtIGJ1ZmZlciAtIGEgVHlwZWRBcnJheSBjb3JyZXNwb25kaW5nIHRvIHRoZSB0eXBlLlxuICAgKiBAcGFyYW0gZGltcyAtIHNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICpcbiAgICogQHJldHVybnMgYSB0ZW5zb3Igb2JqZWN0XG4gICAqL1xuICBmcm9tUGlubmVkQnVmZmVyPFQgZXh0ZW5kcyBFeGNsdWRlPFRlbnNvci5UeXBlLCAnc3RyaW5nJz4+KFxuICAgIHR5cGU6IFQsXG4gICAgYnVmZmVyOiBUZW5zb3IuRGF0YVR5cGVNYXBbVF0sXG4gICAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiBUeXBlZFRlbnNvcjxUPjtcbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLyoqXG4gKiBBIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgYSBmaWxlJ3MgVVJMIG9yIHBhdGguXG4gKlxuICogUGF0aCBpcyB2YWlsYWJsZSBvbmx5IGluIG9ubnhydW50aW1lLW5vZGUgb3Igb25ueHJ1bnRpbWUtd2ViIHJ1bm5pbmcgaW4gTm9kZS5qcy5cbiAqL1xuZXhwb3J0IHR5cGUgRmlsZVVybE9yUGF0aCA9IHN0cmluZztcblxuLyoqXG4gKiBBIEJsb2Igb2JqZWN0IHRoYXQgcmVwcmVzZW50cyBhIGZpbGUuXG4gKi9cbmV4cG9ydCB0eXBlIEZpbGVCbG9iID0gQmxvYjtcblxuLyoqXG4gKiBBIFVpbnQ4QXJyYXksIEFycmF5QnVmZmVyIG9yIFNoYXJlZEFycmF5QnVmZmVyIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgYSBmaWxlIGNvbnRlbnQuXG4gKlxuICogV2hlbiBpdCBpcyBhbiBBcnJheUJ1ZmZlciBvciBTaGFyZWRBcnJheUJ1ZmZlciwgdGhlIHdob2xlIGJ1ZmZlciBpcyBhc3N1bWVkIHRvIGJlIHRoZSBmaWxlIGNvbnRlbnQuXG4gKi9cbmV4cG9ydCB0eXBlIEZpbGVEYXRhID0gVWludDhBcnJheSB8IEFycmF5QnVmZmVyTGlrZTtcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgZmlsZSB0aGF0IGNhbiBiZSBsb2FkZWQgYnkgdGhlIE9OTlggUnVudGltZSBKYXZhU2NyaXB0IEFQSS5cbiAqL1xuZXhwb3J0IHR5cGUgRmlsZVR5cGUgPSBGaWxlVXJsT3JQYXRoIHwgRmlsZUJsb2IgfCBGaWxlRGF0YTtcblxuLyoqXG4gKiBSZXByZXNlbnRzIGFuIGV4dGVybmFsIGRhdGEgZmlsZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFeHRlcm5hbERhdGFGaWxlRGVzY3JpcHRpb24ge1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgZXh0ZXJuYWwgZGF0YSBmaWxlLlxuICAgKi9cbiAgZGF0YTogRmlsZVR5cGU7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBmaWxlIHBhdGguXG4gICAqL1xuICBwYXRoOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBleHRlcm5hbCBkYXRhIGZpbGUuXG4gKlxuICogV2hlbiB1c2luZyBhIHN0cmluZywgaXQgc2hvdWxkIGJlIGEgZmlsZSBVUkwgb3IgcGF0aCB0aGF0IGluIHRoZSBzYW1lIGRpcmVjdG9yeSBhcyB0aGUgbW9kZWwgZmlsZS5cbiAqL1xuZXhwb3J0IHR5cGUgRXh0ZXJuYWxEYXRhRmlsZVR5cGUgPSBFeHRlcm5hbERhdGFGaWxlRGVzY3JpcHRpb24gfCBGaWxlVXJsT3JQYXRoO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIG1vZGVsIGxvYWRpbmcuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT25ueE1vZGVsT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5aW5nIGEgbGlzdCBvZiBmaWxlcyB0aGF0IHJlcHJlc2VudHMgdGhlIGV4dGVybmFsIGRhdGEuXG4gICAqL1xuICBleHRlcm5hbERhdGE/OiByZWFkb25seSBFeHRlcm5hbERhdGFGaWxlVHlwZVtdO1xufVxuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3IgfSBmcm9tICcuL3RlbnNvci5qcyc7XG5cbmV4cG9ydCB0eXBlIE5vblRlbnNvclR5cGUgPSBuZXZlcjtcblxuLyoqXG4gKiBUeXBlIE9ubnhWYWx1ZSBSZXByZXNlbnRzIGJvdGggdGVuc29ycyBhbmQgbm9uLXRlbnNvcnMgdmFsdWUgZm9yIG1vZGVsJ3MgaW5wdXRzL291dHB1dHMuXG4gKlxuICogTk9URTogY3VycmVudGx5IG5vdCBzdXBwb3J0IG5vbi10ZW5zb3JcbiAqL1xuZXhwb3J0IHR5cGUgT25ueFZhbHVlID0gVGVuc29yIHwgTm9uVGVuc29yVHlwZTtcblxuLyoqXG4gKiBUeXBlIE9ubnhWYWx1ZURhdGFMb2NhdGlvbiByZXByZXNlbnRzIHRoZSBsb2NhdGlvbiBvZiB0aGUgZGF0YSBvZiBhbiBPbm54VmFsdWUuXG4gKi9cbmV4cG9ydCB0eXBlIE9ubnhWYWx1ZURhdGFMb2NhdGlvbiA9IFRlbnNvci5EYXRhTG9jYXRpb247XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8qKlxuICogIyBPTk5YIFJ1bnRpbWUgSmF2YVNjcmlwdCBBUElcbiAqXG4gKiBPTk5YIFJ1bnRpbWUgSmF2YVNjcmlwdCBBUEkgaXMgYSB1bmlmaWVkIEFQSSBmb3IgYWxsIEphdmFTY3JpcHQgdXNhZ2VzLCBpbmNsdWRpbmcgdGhlIGZvbGxvd2luZyBOUE0gcGFja2FnZXM6XG4gKlxuICogLSBbb25ueHJ1bnRpbWUtbm9kZV0oaHR0cHM6Ly93d3cubnBtanMuY29tL3BhY2thZ2Uvb25ueHJ1bnRpbWUtbm9kZSlcbiAqIC0gW29ubnhydW50aW1lLXdlYl0oaHR0cHM6Ly93d3cubnBtanMuY29tL3BhY2thZ2Uvb25ueHJ1bnRpbWUtd2ViKVxuICogLSBbb25ueHJ1bnRpbWUtcmVhY3QtbmF0aXZlXShodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9vbm54cnVudGltZS1yZWFjdC1uYXRpdmUpXG4gKlxuICogU2VlIGFsc286XG4gKiAtIFtHZXQgU3RhcnRlZF0oaHR0cHM6Ly9vbm54cnVudGltZS5haS9kb2NzL2dldC1zdGFydGVkL3dpdGgtamF2YXNjcmlwdC8pXG4gKiAtIFtJbmZlcmVuY2UgZXhhbXBsZXNdKGh0dHBzOi8vZ2l0aHViLmNvbS9taWNyb3NvZnQvb25ueHJ1bnRpbWUtaW5mZXJlbmNlLWV4YW1wbGVzL3RyZWUvbWFpbi9qcylcbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL2JhY2tlbmQuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9lbnYuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9pbmZlcmVuY2Utc2Vzc2lvbi5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3RlbnNvci5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3RlbnNvci1jb252ZXJzaW9uLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vdGVuc29yLWZhY3RvcnkuanMnO1xuZXhwb3J0ICogZnJvbSAnLi90cmFjZS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL29ubngtbW9kZWwuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9vbm54LXZhbHVlLmpzJztcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuZXhwb3J0IGNvbnN0IGlzTm9kZSA9ICEhKHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8vLyA8cmVmZXJlbmNlIGxpYj1cIndlYndvcmtlclwiIC8+XG5cbi8vXG4vLyAqIHR5cGUgaGFjayBmb3IgXCJIVE1MSW1hZ2VFbGVtZW50XCJcbi8vXG4vLyBpbiB0eXBlc2NyaXB0LCB0aGUgdHlwZSBvZiBcIkhUTUxJbWFnZUVsZW1lbnRcIiBpcyBkZWZpbmVkIGluIGxpYi5kb20uZC50cywgd2hpY2ggaXMgY29uZmxpY3Qgd2l0aCBsaWIud2Vid29ya2VyLmQudHMuXG4vLyB3aGVuIHdlIHVzZSB3ZWJ3b3JrZXIsIHRoZSBsaWIud2Vid29ya2VyLmQudHMgd2lsbCBiZSB1c2VkLCB3aGljaCBkb2VzIG5vdCBoYXZlIEhUTUxJbWFnZUVsZW1lbnQgZGVmaW5lZC5cbi8vXG4vLyB3ZSB3aWxsIGdldCB0aGUgZm9sbG93aW5nIGVycm9ycyBjb21wbGFpbmluZyB0aGF0IEhUTUxJbWFnZUVsZW1lbnQgaXMgbm90IGRlZmluZWQ6XG4vL1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vXG4vLyAuLi9jb21tb24vZGlzdC9janMvdGVuc29yLWZhY3RvcnkuZC50czoxODc6MjkgLSBlcnJvciBUUzI1NTI6IENhbm5vdCBmaW5kIG5hbWUgJ0hUTUxJbWFnZUVsZW1lbnQnLiBEaWQgeW91IG1lYW5cbi8vICdIVE1MTElFbGVtZW50Jz9cbi8vXG4vLyAxODcgICAgIGZyb21JbWFnZShpbWFnZUVsZW1lbnQ6IEhUTUxJbWFnZUVsZW1lbnQsIG9wdGlvbnM/OiBUZW5zb3JGcm9tSW1hZ2VFbGVtZW50T3B0aW9ucyk6XG4vLyBQcm9taXNlPFR5cGVkVGVuc29yPCdmbG9hdDMyJz4gfCBUeXBlZFRlbnNvcjwndWludDgnPj47XG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH5+fn5+fn5+fn5+fn5+fn5cbi8vXG4vLyBub2RlX21vZHVsZXMvQHdlYmdwdS90eXBlcy9kaXN0L2luZGV4LmQudHM6ODM6NyAtIGVycm9yIFRTMjU1MjogQ2Fubm90IGZpbmQgbmFtZSAnSFRNTEltYWdlRWxlbWVudCcuIERpZCB5b3UgbWVhblxuLy8gJ0hUTUxMSUVsZW1lbnQnP1xuLy9cbi8vIDgzICAgICB8IEhUTUxJbWFnZUVsZW1lbnRcbi8vICAgICAgICAgIH5+fn5+fn5+fn5+fn5+fn5cbi8vXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy9cbi8vIGBIVE1MSW1hZ2VFbGVtZW50YCBpcyBvbmx5IHVzZWQgaW4gdHlwZSBkZWNsYXJhdGlvbiBhbmQgbm90IGluIHJlYWwgY29kZS4gU28gd2UgZGVmaW5lIGl0IGFzIGB1bmtub3duYCBoZXJlIHRvXG4vLyBieXBhc3MgdGhlIHR5cGUgY2hlY2suXG5cbi8vXG4vLyAqIHR5cGUgaGFjayBmb3IgXCJkb2N1bWVudFwiXG4vL1xuLy8gaW4gdHlwZXNjcmlwdCwgdGhlIHR5cGUgb2YgXCJkb2N1bWVudFwiIGlzIGRlZmluZWQgaW4gbGliLmRvbS5kLnRzLCBzbyBpdCdzIG5vdCBhdmFpbGFibGUgaW4gd2Vid29ya2VyLlxuLy9cbi8vIHdlIHdpbGwgZ2V0IHRoZSBmb2xsb3dpbmcgZXJyb3JzIGNvbXBsYWluaW5nIHRoYXQgZG9jdW1lbnQgaXMgbm90IGRlZmluZWQ6XG4vL1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vXG4vLyBsaWIvd2FzbS93YXNtLXV0aWxzLWltcG9ydC50czo3OjMzIC0gZXJyb3IgVFMyNTg0OiBDYW5ub3QgZmluZCBuYW1lICdkb2N1bWVudCcuIERvIHlvdSBuZWVkIHRvIGNoYW5nZSB5b3VyIHRhcmdldFxuLy8gbGlicmFyeT8gVHJ5IGNoYW5naW5nIHRoZSAnbGliJyBjb21waWxlciBvcHRpb24gdG8gaW5jbHVkZSAnZG9tJy5cbi8vXG4vLyA3IGV4cG9ydCBjb25zdCBzY3JpcHRTcmMgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnID8gKGRvY3VtZW50Py5jdXJyZW50U2NyaXB0IGFzIEhUTUxTY3JpcHRFbGVtZW50KT8uc3JjIDpcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB+fn5+fn5+flxuLy9cbi8vIGxpYi93YXNtL3dhc20tdXRpbHMtaW1wb3J0LnRzOjc6NjEgLSBlcnJvciBUUzI1ODQ6IENhbm5vdCBmaW5kIG5hbWUgJ2RvY3VtZW50Jy4gRG8geW91IG5lZWQgdG8gY2hhbmdlIHlvdXIgdGFyZ2V0XG4vLyBsaWJyYXJ5PyBUcnkgY2hhbmdpbmcgdGhlICdsaWInIGNvbXBpbGVyIG9wdGlvbiB0byBpbmNsdWRlICdkb20nLlxuLy9cbi8vIDcgZXhwb3J0IGNvbnN0IHNjcmlwdFNyYyA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgPyAoZG9jdW1lbnQ/LmN1cnJlbnRTY3JpcHQgYXMgSFRNTFNjcmlwdEVsZW1lbnQpPy5zcmMgOlxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB+fn5+fn5+flxuLy9cbi8vIGxpYi93YXNtL3dhc20tdXRpbHMtaW1wb3J0LnRzOjc6ODggLSBlcnJvciBUUzI1NTI6IENhbm5vdCBmaW5kIG5hbWUgJ0hUTUxTY3JpcHRFbGVtZW50Jy4gRGlkIHlvdSBtZWFuXG4vLyAnSFRNTExJRWxlbWVudCc/XG4vL1xuLy8gNyBleHBvcnQgY29uc3Qgc2NyaXB0U3JjID0gdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyA/IChkb2N1bWVudD8uY3VycmVudFNjcmlwdCBhcyBIVE1MU2NyaXB0RWxlbWVudCk/LnNyYyA6XG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH5+fn5+fn5+fn5+fn5+fn5+XG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy9cbi8vIGBkb2N1bWVudGAgaXMgdXNlZCB0byBnZXQgdGhlIGN1cnJlbnQgc2NyaXB0IFVSTCwgd2hpY2ggaXMgbm90IGF2YWlsYWJsZSBpbiB3ZWJ3b3JrZXIuIFRoaXMgZmlsZSBpcyBzZXJ2ZWQgYXMgYVxuLy8gXCJkdWFsXCIgZmlsZSBmb3IgZW50cmllcyBvZiBib3RoIHdlYndvcmtlciBhbmQgdGhlIGVzbSBtb2R1bGUuXG4vL1xuZGVjbGFyZSBnbG9iYWwge1xuICB0eXBlIEhUTUxJbWFnZUVsZW1lbnQgPSB1bmtub3duO1xuICB0eXBlIEhUTUxTY3JpcHRFbGVtZW50ID0geyBzcmM/OiBzdHJpbmcgfTtcbiAgY29uc3QgZG9jdW1lbnQ6IHVuZGVmaW5lZCB8IHsgY3VycmVudFNjcmlwdD86IEhUTUxTY3JpcHRFbGVtZW50IH07XG59XG5cbi8qKlxuICogQHN1bW1hcnlcbiAqXG4gKiBUaGlzIGZpbGUgaXMgc2VydmVkIGFzIGEgXCJkdWFsXCIgZmlsZSBmb3IgYm90aCBlbnRyaWVzIG9mIHRoZSBmb2xsb3dpbmc6XG4gKiAtIFRoZSBwcm94eSB3b3JrZXIgaXRzZWxmLlxuICogICAtIFdoZW4gdXNlZCBhcyBhIHdvcmtlciwgaXQgbGlzdGVucyB0byB0aGUgbWVzc2FnZXMgZnJvbSB0aGUgbWFpbiB0aHJlYWQgYW5kIHBlcmZvcm1zIHRoZSBjb3JyZXNwb25kaW5nIG9wZXJhdGlvbnMuXG4gKiAgIC0gU2hvdWxkIGJlIGltcG9ydGVkIGRpcmVjdGx5IHVzaW5nIGBuZXcgV29ya2VyKClgIGluIHRoZSBtYWluIHRocmVhZC5cbiAqXG4gKiAtIFRoZSBFU00gbW9kdWxlIHRoYXQgY3JlYXRlcyB0aGUgcHJveHkgd29ya2VyIChhcyBhIHdvcmtlciBsYXVuY2hlcikuXG4gKiAgIC0gV2hlbiB1c2VkIGFzIGEgd29ya2VyIGxhdW5jaGVyLCBpdCBjcmVhdGVzIHRoZSBwcm94eSB3b3JrZXIgYW5kIHJldHVybnMgaXQuXG4gKiAgIC0gU2hvdWxkIGJlIGltcG9ydGVkIHVzaW5nIGBpbXBvcnQoKWAgaW4gdGhlIG1haW4gdGhyZWFkLCB3aXRoIHRoZSBxdWVyeSBwYXJhbWV0ZXIgYGltcG9ydD0xYC5cbiAqXG4gKiBUaGlzIGZpbGUgd2lsbCBiZSBhbHdheXMgY29tcGlsaW5nIGludG8gRVNNIGZvcm1hdC5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IE9ydFdhc21NZXNzYWdlLCBTZXJpYWxpemFibGVUZW5zb3JNZXRhZGF0YSB9IGZyb20gJy4uL3Byb3h5LW1lc3NhZ2VzLmpzJztcbmltcG9ydCB7XG4gIGNyZWF0ZVNlc3Npb24sXG4gIGNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIsXG4gIGVuZFByb2ZpbGluZyxcbiAgZXh0cmFjdFRyYW5zZmVyYWJsZUJ1ZmZlcnMsXG4gIGluaXRFcCxcbiAgaW5pdFJ1bnRpbWUsXG4gIHJlbGVhc2VTZXNzaW9uLFxuICBydW4sXG59IGZyb20gJy4uL3dhc20tY29yZS1pbXBsLmpzJztcbmltcG9ydCB7IGluaXRpYWxpemVXZWJBc3NlbWJseSB9IGZyb20gJy4uL3dhc20tZmFjdG9yeS5qcyc7XG5pbXBvcnQgeyBzY3JpcHRTcmMgfSBmcm9tICcuLi93YXNtLXV0aWxzLWltcG9ydC5qcyc7XG5cbmNvbnN0IFdPUktFUl9OQU1FID0gJ29ydC13YXNtLXByb3h5LXdvcmtlcic7XG5jb25zdCBpc1Byb3h5V29ya2VyID0gZ2xvYmFsVGhpcy5zZWxmPy5uYW1lID09PSBXT1JLRVJfTkFNRTtcblxuaWYgKGlzUHJveHlXb3JrZXIpIHtcbiAgLy8gV29ya2VyIHRocmVhZFxuICBzZWxmLm9ubWVzc2FnZSA9IChldjogTWVzc2FnZUV2ZW50PE9ydFdhc21NZXNzYWdlPik6IHZvaWQgPT4ge1xuICAgIGNvbnN0IHsgdHlwZSwgaW46IG1lc3NhZ2UgfSA9IGV2LmRhdGE7XG4gICAgdHJ5IHtcbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlICdpbml0LXdhc20nOlxuICAgICAgICAgIGluaXRpYWxpemVXZWJBc3NlbWJseShtZXNzYWdlIS53YXNtKS50aGVuKFxuICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICBpbml0UnVudGltZShtZXNzYWdlISkudGhlbihcbiAgICAgICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUgfSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUsIGVyciB9KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlLCBlcnIgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2luaXQtZXAnOiB7XG4gICAgICAgICAgY29uc3QgeyBlcE5hbWUsIGVudiB9ID0gbWVzc2FnZSE7XG4gICAgICAgICAgaW5pdEVwKGVudiwgZXBOYW1lKS50aGVuKFxuICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUsIGVyciB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdjb3B5LWZyb20nOiB7XG4gICAgICAgICAgY29uc3QgeyBidWZmZXIgfSA9IG1lc3NhZ2UhO1xuICAgICAgICAgIGNvbnN0IGJ1ZmZlckRhdGEgPSBjb3B5RnJvbUV4dGVybmFsQnVmZmVyKGJ1ZmZlcik7XG4gICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlLCBvdXQ6IGJ1ZmZlckRhdGEgfSBhcyBPcnRXYXNtTWVzc2FnZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnY3JlYXRlJzoge1xuICAgICAgICAgIGNvbnN0IHsgbW9kZWwsIG9wdGlvbnMgfSA9IG1lc3NhZ2UhO1xuICAgICAgICAgIGNyZWF0ZVNlc3Npb24obW9kZWwsIG9wdGlvbnMpLnRoZW4oXG4gICAgICAgICAgICAoc2Vzc2lvbk1ldGFkYXRhKSA9PiB7XG4gICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSwgb3V0OiBzZXNzaW9uTWV0YWRhdGEgfSBhcyBPcnRXYXNtTWVzc2FnZSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUsIGVyciB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdyZWxlYXNlJzpcbiAgICAgICAgICByZWxlYXNlU2Vzc2lvbihtZXNzYWdlISk7XG4gICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlIH0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdydW4nOiB7XG4gICAgICAgICAgY29uc3QgeyBzZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRzLCBvdXRwdXRJbmRpY2VzLCBvcHRpb25zIH0gPSBtZXNzYWdlITtcbiAgICAgICAgICBydW4oc2Vzc2lvbklkLCBpbnB1dEluZGljZXMsIGlucHV0cywgb3V0cHV0SW5kaWNlcywgbmV3IEFycmF5KG91dHB1dEluZGljZXMubGVuZ3RoKS5maWxsKG51bGwpLCBvcHRpb25zKS50aGVuKFxuICAgICAgICAgICAgKG91dHB1dHMpID0+IHtcbiAgICAgICAgICAgICAgaWYgKG91dHB1dHMuc29tZSgobykgPT4gb1szXSAhPT0gJ2NwdScpKSB7XG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlLCBlcnI6ICdQcm94eSBkb2VzIG5vdCBzdXBwb3J0IG5vbi1jcHUgdGVuc29yIGxvY2F0aW9uLicgfSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgICB7IHR5cGUsIG91dDogb3V0cHV0cyB9IGFzIE9ydFdhc21NZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgZXh0cmFjdFRyYW5zZmVyYWJsZUJ1ZmZlcnMoWy4uLmlucHV0cywgLi4ub3V0cHV0c10gYXMgU2VyaWFsaXphYmxlVGVuc29yTWV0YWRhdGFbXSksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlLCBlcnIgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnZW5kLXByb2ZpbGluZyc6XG4gICAgICAgICAgZW5kUHJvZmlsaW5nKG1lc3NhZ2UhKTtcbiAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBwb3N0TWVzc2FnZSh7IHR5cGUsIGVyciB9IGFzIE9ydFdhc21NZXNzYWdlKTtcbiAgICB9XG4gIH07XG59XG5cbmV4cG9ydCBkZWZhdWx0IGlzUHJveHlXb3JrZXJcbiAgPyBudWxsXG4gIDogKHVybE92ZXJyaWRlPzogc3RyaW5nKSA9PlxuICAgICAgbmV3IFdvcmtlcih1cmxPdmVycmlkZSA/PyBzY3JpcHRTcmMhLCB7IHR5cGU6IEJVSUxEX0RFRlMuSVNfRVNNID8gJ21vZHVsZScgOiAnY2xhc3NpYycsIG5hbWU6IFdPUktFUl9OQU1FIH0pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgdHlwZSB7IE9ydFdhc21Nb2R1bGUgfSBmcm9tICcuL3dhc20tdHlwZXMnO1xuaW1wb3J0IHsgaXNOb2RlIH0gZnJvbSAnLi93YXNtLXV0aWxzLWVudic7XG5cbi8qKlxuICogVGhlIG9yaWdpbiBvZiB0aGUgY3VycmVudCBsb2NhdGlvbi5cbiAqXG4gKiBJbiBOb2RlLmpzLCB0aGlzIGlzIHVuZGVmaW5lZC5cbiAqL1xuY29uc3Qgb3JpZ2luID0gaXNOb2RlIHx8IHR5cGVvZiBsb2NhdGlvbiA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBsb2NhdGlvbi5vcmlnaW47XG5cbi8qKlxuICogU29tZSBidW5kbGVycyAoZWcuIFdlYnBhY2spIHdpbGwgcmV3cml0ZSBgaW1wb3J0Lm1ldGEudXJsYCB0byBhIGZpbGUgVVJMIGF0IGNvbXBpbGUgdGltZS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGNoZWNrcyBpZiBgaW1wb3J0Lm1ldGEudXJsYCBzdGFydHMgd2l0aCBgZmlsZTpgLCBidXQgdXNpbmcgdGhlIGA+YCBhbmQgYDxgIG9wZXJhdG9ycyBpbnN0ZWFkIG9mXG4gKiBgc3RhcnRzV2l0aGAgZnVuY3Rpb24gc28gdGhhdCBjb2RlIG1pbmltaXplcnMgY2FuIHJlbW92ZSB0aGUgZGVhZCBjb2RlIGNvcnJlY3RseS5cbiAqXG4gKiBGb3IgZXhhbXBsZSwgaWYgd2UgdXNlIHRlcnNlciB0byBtaW5pZnkgdGhlIGZvbGxvd2luZyBjb2RlOlxuICogYGBganNcbiAqIGlmIChcImZpbGU6Ly9oYXJkLWNvZGVkLWZpbGVuYW1lXCIuc3RhcnRzV2l0aChcImZpbGU6XCIpKSB7XG4gKiAgIGNvbnNvbGUubG9nKDEpXG4gKiB9IGVsc2Uge1xuICogICBjb25zb2xlLmxvZygyKVxuICogfVxuICpcbiAqIGlmIChcImZpbGU6Ly9oYXJkLWNvZGVkLWZpbGVuYW1lXCIgPiBcImZpbGU6XCIgJiYgXCJmaWxlOi8vaGFyZC1jb2RlZC1maWxlbmFtZVwiIDwgXCJmaWxlO1wiKSB7XG4gKiAgIGNvbnNvbGUubG9nKDMpXG4gKiB9IGVsc2Uge1xuICogICBjb25zb2xlLmxvZyg0KVxuICogfVxuICogYGBgXG4gKlxuICogVGhlIG1pbmlmaWVkIGNvZGUgd2lsbCBiZTpcbiAqIGBgYGpzXG4gKiBcImZpbGU6Ly9oYXJkLWNvZGVkLWZpbGVuYW1lXCIuc3RhcnRzV2l0aChcImZpbGU6XCIpP2NvbnNvbGUubG9nKDEpOmNvbnNvbGUubG9nKDIpLGNvbnNvbGUubG9nKDMpO1xuICogYGBgXG4gKlxuICogKHVzZSBUZXJzZXIgNS4zOS4wIHdpdGggZGVmYXVsdCBvcHRpb25zLCBodHRwczovL3RyeS50ZXJzZXIub3JnLylcbiAqXG4gKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBpbXBvcnQubWV0YS51cmwgaXMgaGFyZGNvZGVkIGFzIGEgZmlsZSBVUkkuXG4gKi9cbmV4cG9ydCBjb25zdCBpc0VzbUltcG9ydE1ldGFVcmxIYXJkY29kZWRBc0ZpbGVVcmkgPVxuICBCVUlMRF9ERUZTLklTX0VTTSAmJiBCVUlMRF9ERUZTLkVTTV9JTVBPUlRfTUVUQV9VUkwhID4gJ2ZpbGU6JyAmJiBCVUlMRF9ERUZTLkVTTV9JTVBPUlRfTUVUQV9VUkwhIDwgJ2ZpbGU7JztcblxuY29uc3QgZ2V0U2NyaXB0U3JjID0gKCk6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gIC8vIGlmIE5vZGVqcywgcmV0dXJuIHVuZGVmaW5lZFxuICBpZiAoaXNOb2RlKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICAvLyBpZiBJdCdzIEVTTSwgdXNlIGltcG9ydC5tZXRhLnVybFxuICBpZiAoQlVJTERfREVGUy5JU19FU00pIHtcbiAgICAvLyBGb3IgRVNNLCBpZiB0aGUgaW1wb3J0Lm1ldGEudXJsIGlzIGEgZmlsZSBVUkwsIHRoaXMgdXN1YWxseSBtZWFucyB0aGUgYnVuZGxlciByZXdyaXRlcyBgaW1wb3J0Lm1ldGEudXJsYCB0b1xuICAgIC8vIHRoZSBmaWxlIHBhdGggYXQgY29tcGlsZSB0aW1lLiBJbiB0aGlzIGNhc2UsIHRoaXMgZmlsZSBwYXRoIGNhbm5vdCBiZSB1c2VkIHRvIGRldGVybWluZSB0aGUgcnVudGltZSBVUkwuXG4gICAgLy9cbiAgICAvLyBXZSBuZWVkIHRvIHVzZSB0aGUgVVJMIGNvbnN0cnVjdG9yIGxpa2UgdGhpczpcbiAgICAvLyBgYGBqc1xuICAgIC8vIG5ldyBVUkwoJ2FjdHVhbC1idW5kbGUtbmFtZS5qcycsIGltcG9ydC5tZXRhLnVybCkuaHJlZlxuICAgIC8vIGBgYFxuICAgIC8vIFNvIHRoYXQgYnVuZGxlciBjYW4gcHJlcHJvY2VzcyB0aGUgVVJMIGNvcnJlY3RseS5cbiAgICBpZiAoaXNFc21JbXBvcnRNZXRhVXJsSGFyZGNvZGVkQXNGaWxlVXJpKSB7XG4gICAgICAvLyBpZiB0aGUgcmV3cml0dGVuIFVSTCBpcyBhIHJlbGF0aXZlIHBhdGgsIHdlIG5lZWQgdG8gdXNlIHRoZSBvcmlnaW4gdG8gcmVzb2x2ZSB0aGUgVVJMLlxuXG4gICAgICAvLyBUaGUgZm9sbG93aW5nIGlzIGEgd29ya2Fyb3VuZCBmb3IgVml0ZS5cbiAgICAgIC8vXG4gICAgICAvLyBWaXRlIHVzZXMgYSBidW5kbGVyKHJvbGx1cC9yb2xsZG93bikgdGhhdCBkb2VzIG5vdCByZXdyaXRlIGBpbXBvcnQubWV0YS51cmxgIHRvIGEgZmlsZSBVUkwuIFNvIGluIHRoZW9yeSwgdGhpc1xuICAgICAgLy8gY29kZSBwYXRoIHNob3VsZCBub3QgYmUgZXhlY3V0ZWQgaW4gVml0ZS4gSG93ZXZlciwgdGhlIGJ1bmRsZXIgZG9lcyBub3Qga25vdyBpdCBhbmQgaXQgc3RpbGwgdHJ5IHRvIGxvYWQgdGhlXG4gICAgICAvLyBmb2xsb3dpbmcgcGF0dGVybjpcbiAgICAgIC8vIC0gYHJldHVybiBuZXcgVVJMKCdmaWxlbmFtZScsIGltcG9ydC5tZXRhLnVybCkuaHJlZmBcbiAgICAgIC8vXG4gICAgICAvLyBCeSByZXBsYWNpbmcgdGhlIHBhdHRlcm4gYWJvdmUgd2l0aCB0aGUgZm9sbG93aW5nIGNvZGUsIHdlIGNhbiBza2lwIHRoZSByZXNvdXJjZSBsb2FkaW5nIGJlaGF2aW9yOlxuICAgICAgLy8gLSBgY29uc3QgVVJMMiA9IFVSTDsgcmV0dXJuIG5ldyBVUkwyKCdmaWxlbmFtZScsIGltcG9ydC5tZXRhLnVybCkuaHJlZjtgXG4gICAgICAvL1xuICAgICAgLy8gQW5kIGl0IHN0aWxsIHdvcmtzIGluIFdlYnBhY2suXG4gICAgICBjb25zdCBVUkwyID0gVVJMO1xuICAgICAgcmV0dXJuIG5ldyBVUkwobmV3IFVSTDIoQlVJTERfREVGUy5CVU5ETEVfRklMRU5BTUUsIEJVSUxEX0RFRlMuRVNNX0lNUE9SVF9NRVRBX1VSTCkuaHJlZiwgb3JpZ2luKS5ocmVmO1xuICAgIH1cblxuICAgIHJldHVybiBCVUlMRF9ERUZTLkVTTV9JTVBPUlRfTUVUQV9VUkw7XG4gIH1cblxuICByZXR1cm4gdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJ1xuICAgID8gKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgYXMgSFRNTFNjcmlwdEVsZW1lbnQpPy5zcmNcbiAgICA6IC8vIHVzZSBgc2VsZi5sb2NhdGlvbi5ocmVmYCBpZiBhdmFpbGFibGVcbiAgICAgIHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJ1xuICAgICAgPyBzZWxmLmxvY2F0aW9uPy5ocmVmXG4gICAgICA6IHVuZGVmaW5lZDtcbn07XG5cbi8qKlxuICogVGhlIGNsYXNzaWMgc2NyaXB0IHNvdXJjZSBVUkwuIFRoaXMgaXMgbm90IGFsd2F5cyBhdmFpbGFibGUgaW4gbm9uIEVTTW9kdWxlIGVudmlyb25tZW50cy5cbiAqXG4gKiBJbiBOb2RlLmpzLCB0aGlzIGlzIHVuZGVmaW5lZC5cbiAqL1xuZXhwb3J0IGNvbnN0IHNjcmlwdFNyYyA9IGdldFNjcmlwdFNyYygpO1xuXG4vKipcbiAqIEluZmVyIHRoZSB3YXNtIHBhdGggcHJlZml4IGZyb20gdGhlIHNjcmlwdCBzb3VyY2UgVVJMLlxuICpcbiAqIEByZXR1cm5zIFRoZSBpbmZlcnJlZCB3YXNtIHBhdGggcHJlZml4LCBvciB1bmRlZmluZWQgaWYgdGhlIHNjcmlwdCBzb3VyY2UgVVJMIGlzIG5vdCBhdmFpbGFibGUgb3IgaXMgYSBibG9iIFVSTC5cbiAqL1xuZXhwb3J0IGNvbnN0IGluZmVyV2FzbVBhdGhQcmVmaXhGcm9tU2NyaXB0U3JjID0gKCk6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gIGlmIChzY3JpcHRTcmMgJiYgIXNjcmlwdFNyYy5zdGFydHNXaXRoKCdibG9iOicpKSB7XG4gICAgcmV0dXJuIHNjcmlwdFNyYy5zdWJzdHJpbmcoMCwgc2NyaXB0U3JjLmxhc3RJbmRleE9mKCcvJykgKyAxKTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufTtcblxuLyoqXG4gKiBDaGVjayBpZiB0aGUgZ2l2ZW4gZmlsZW5hbWUgd2l0aCBwcmVmaXggaXMgZnJvbSB0aGUgc2FtZSBvcmlnaW4uXG4gKi9cbmNvbnN0IGlzU2FtZU9yaWdpbiA9IChmaWxlbmFtZTogc3RyaW5nLCBwcmVmaXhPdmVycmlkZT86IHN0cmluZykgPT4ge1xuICB0cnkge1xuICAgIGNvbnN0IGJhc2VVcmwgPSBwcmVmaXhPdmVycmlkZSA/PyBzY3JpcHRTcmM7XG4gICAgY29uc3QgdXJsID0gYmFzZVVybCA/IG5ldyBVUkwoZmlsZW5hbWUsIGJhc2VVcmwpIDogbmV3IFVSTChmaWxlbmFtZSk7XG4gICAgcmV0dXJuIHVybC5vcmlnaW4gPT09IG9yaWdpbjtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG4vKipcbiAqIE5vcm1hbGl6ZSB0aGUgaW5wdXRzIHRvIGFuIGFic29sdXRlIFVSTCB3aXRoIHRoZSBnaXZlbiBwcmVmaXggb3ZlcnJpZGUuIElmIGZhaWxlZCwgcmV0dXJuIHVuZGVmaW5lZC5cbiAqL1xuY29uc3Qgbm9ybWFsaXplVXJsID0gKGZpbGVuYW1lOiBzdHJpbmcsIHByZWZpeE92ZXJyaWRlPzogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IGJhc2VVcmwgPSBwcmVmaXhPdmVycmlkZSA/PyBzY3JpcHRTcmM7XG4gIHRyeSB7XG4gICAgY29uc3QgdXJsID0gYmFzZVVybCA/IG5ldyBVUkwoZmlsZW5hbWUsIGJhc2VVcmwpIDogbmV3IFVSTChmaWxlbmFtZSk7XG4gICAgcmV0dXJuIHVybC5ocmVmO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIGZhbGxiYWNrIFVSTCBpZiBhbiBhYnNvbHV0ZSBVUkwgY2Fubm90IGJlIGNyZWF0ZWQgYnkgdGhlIG5vcm1hbGl6ZVVybCBmdW5jdGlvbi5cbiAqL1xuY29uc3QgZmFsbGJhY2tVcmwgPSAoZmlsZW5hbWU6IHN0cmluZywgcHJlZml4T3ZlcnJpZGU/OiBzdHJpbmcpID0+IGAke3ByZWZpeE92ZXJyaWRlID8/ICcuLyd9JHtmaWxlbmFtZX1gO1xuXG4vKipcbiAqIFRoaXMgaGVscGVyIGZ1bmN0aW9uIGlzIHVzZWQgdG8gcHJlbG9hZCBhIG1vZHVsZSBmcm9tIGEgVVJMLlxuICpcbiAqIElmIHRoZSBvcmlnaW4gb2YgdGhlIHdvcmtlciBVUkwgaXMgZGlmZmVyZW50IGZyb20gdGhlIGN1cnJlbnQgb3JpZ2luLCB0aGUgd29ya2VyIGNhbm5vdCBiZSBsb2FkZWQgZGlyZWN0bHkuXG4gKiBTZWUgZGlzY3Vzc2lvbnMgaW4gaHR0cHM6Ly9naXRodWIuY29tL3dlYnBhY2stY29udHJpYi93b3JrZXItbG9hZGVyL2lzc3Vlcy8xNTRcbiAqXG4gKiBJbiB0aGlzIGNhc2UsIHdlIHdpbGwgZmV0Y2ggdGhlIHdvcmtlciBVUkwgYW5kIGNyZWF0ZSBhIG5ldyBCbG9iIFVSTCB3aXRoIHRoZSBzYW1lIG9yaWdpbiBhcyBhIHdvcmthcm91bmQuXG4gKlxuICogQHBhcmFtIGFic29sdXRlVXJsIC0gVGhlIGFic29sdXRlIFVSTCB0byBwcmVsb2FkLlxuICpcbiAqIEByZXR1cm5zIC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBuZXcgQmxvYiBVUkxcbiAqL1xuY29uc3QgcHJlbG9hZCA9IGFzeW5jIChhYnNvbHV0ZVVybDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChhYnNvbHV0ZVVybCwgeyBjcmVkZW50aWFsczogJ3NhbWUtb3JpZ2luJyB9KTtcbiAgY29uc3QgYmxvYiA9IGF3YWl0IHJlc3BvbnNlLmJsb2IoKTtcbiAgcmV0dXJuIFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG59O1xuXG4vKipcbiAqIFRoaXMgaGVscGVyIGZ1bmN0aW9uIGlzIHVzZWQgdG8gZHluYW1pY2FsbHkgaW1wb3J0IGEgbW9kdWxlIGZyb20gYSBVUkwuXG4gKlxuICogVGhlIGJ1aWxkIHNjcmlwdCBoYXMgc3BlY2lhbCBoYW5kbGluZyBmb3IgdGhpcyBmdW5jdGlvbiB0byBlbnN1cmUgdGhhdCB0aGUgVVJMIGlzIG5vdCBidW5kbGVkIGludG8gdGhlIGZpbmFsIG91dHB1dC5cbiAqXG4gKiBAcGFyYW0gdXJsIC0gVGhlIFVSTCB0byBpbXBvcnQuXG4gKlxuICogQHJldHVybnMgLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgZGVmYXVsdCBleHBvcnQgb2YgdGhlIG1vZHVsZS5cbiAqL1xuY29uc3QgZHluYW1pY0ltcG9ydERlZmF1bHQgPSBhc3luYyA8VD4odXJsOiBzdHJpbmcpOiBQcm9taXNlPFQ+ID0+XG4gIChhd2FpdCBpbXBvcnQoLyogd2VicGFja0lnbm9yZTogdHJ1ZSAqLyAvKiBAdml0ZS1pZ25vcmUgKi8gdXJsKSkuZGVmYXVsdDtcblxuLyoqXG4gKiBUaGUgcHJveHkgd29ya2VyIGZhY3RvcnkgaW1wb3J0ZWQgZnJvbSB0aGUgcHJveHkgd29ya2VyIG1vZHVsZS5cbiAqXG4gKiBUaGlzIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gdGhlIFdlYkFzc2VtYmx5IHByb3h5IGlzIG5vdCBkaXNhYmxlZC5cbiAqL1xuY29uc3QgY3JlYXRlUHJveHlXb3JrZXI6ICgodXJsT3ZlcnJpZGU/OiBzdHJpbmcpID0+IFdvcmtlcikgfCB1bmRlZmluZWQgPVxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICBCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSA/IHVuZGVmaW5lZCA6IHJlcXVpcmUoJy4vcHJveHktd29ya2VyL21haW4nKS5kZWZhdWx0O1xuXG4vKipcbiAqIEltcG9ydCB0aGUgcHJveHkgd29ya2VyLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBwZXJmb3JtIHRoZSBmb2xsb3dpbmcgc3RlcHM6XG4gKiAxLiBJZiBhIHByZWxvYWQgaXMgbmVlZGVkLCBpdCB3aWxsIHByZWxvYWQgdGhlIG1vZHVsZSBhbmQgcmV0dXJuIHRoZSBvYmplY3QgVVJMLlxuICogMi4gVXNlIHRoZSBwcm94eSB3b3JrZXIgZmFjdG9yeSB0byBjcmVhdGUgdGhlIHByb3h5IHdvcmtlci5cbiAqXG4gKiBAcmV0dXJucyAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgdHVwbGUgb2YgMiBlbGVtZW50czpcbiAqICAgICAgICAgICAgLSBUaGUgb2JqZWN0IFVSTCBvZiB0aGUgcHJlbG9hZGVkIG1vZHVsZSwgb3IgdW5kZWZpbmVkIGlmIG5vIHByZWxvYWQgaXMgbmVlZGVkLlxuICogICAgICAgICAgICAtIFRoZSBwcm94eSB3b3JrZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBpbXBvcnRQcm94eVdvcmtlciA9IGFzeW5jICgpOiBQcm9taXNlPFt1bmRlZmluZWQgfCBzdHJpbmcsIFdvcmtlcl0+ID0+IHtcbiAgaWYgKCFzY3JpcHRTcmMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBsb2FkIHByb3h5IHdvcmtlcjogY2Fubm90IGRldGVybWluZSB0aGUgc2NyaXB0IHNvdXJjZSBVUkwuJyk7XG4gIH1cblxuICAvLyBJZiB0aGUgc2NyaXB0IHNvdXJjZSBpcyBmcm9tIHRoZSBzYW1lIG9yaWdpbiwgd2UgY2FuIHVzZSB0aGUgZW1iZWRkZWQgcHJveHkgbW9kdWxlIGRpcmVjdGx5LlxuICBpZiAoaXNTYW1lT3JpZ2luKHNjcmlwdFNyYykpIHtcbiAgICByZXR1cm4gW3VuZGVmaW5lZCwgY3JlYXRlUHJveHlXb3JrZXIhKCldO1xuICB9XG5cbiAgLy8gT3RoZXJ3aXNlLCBuZWVkIHRvIHByZWxvYWRcbiAgY29uc3QgdXJsID0gYXdhaXQgcHJlbG9hZChzY3JpcHRTcmMpO1xuICByZXR1cm4gW3VybCwgY3JlYXRlUHJveHlXb3JrZXIhKHVybCldO1xufTtcblxuLyoqXG4gKiBUaGUgZW1iZWRkZWQgV2ViQXNzZW1ibHkgbW9kdWxlLlxuICpcbiAqIFRoaXMgaXMgb25seSBhdmFpbGFibGUgaW4gRVNNIGFuZCB3aGVuIGVtYmVkZGluZyBpcyBub3QgZGlzYWJsZWQuXG4gKi9cbmNvbnN0IGVtYmVkZGVkV2FzbU1vZHVsZTogRW1zY3JpcHRlbk1vZHVsZUZhY3Rvcnk8T3J0V2FzbU1vZHVsZT4gfCB1bmRlZmluZWQgPVxuICBCVUlMRF9ERUZTLklTX0VTTSAmJiBCVUlMRF9ERUZTLkVOQUJMRV9CVU5ETEVfV0FTTV9KU1xuICAgID8gLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMsIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbiAgICAgIHJlcXVpcmUoXG4gICAgICAgICFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUFxuICAgICAgICAgID8gJy4uLy4uL2Rpc3Qvb3J0LXdhc20tc2ltZC10aHJlYWRlZC5qc2VwLm1qcydcbiAgICAgICAgICA6IEJVSUxEX0RFRlMuRU5BQkxFX0pTUElcbiAgICAgICAgICAgID8gJy4uLy4uL2Rpc3Qvb3J0LXdhc20tc2ltZC10aHJlYWRlZC5qc3BpLm1qcydcbiAgICAgICAgICAgIDogIUJVSUxEX0RFRlMuRElTQUJMRV9XRUJHUFVcbiAgICAgICAgICAgICAgPyAnLi4vLi4vZGlzdC9vcnQtd2FzbS1zaW1kLXRocmVhZGVkLmFzeW5jaWZ5Lm1qcydcbiAgICAgICAgICAgICAgOiAnLi4vLi4vZGlzdC9vcnQtd2FzbS1zaW1kLXRocmVhZGVkLm1qcycsXG4gICAgICApLmRlZmF1bHRcbiAgICA6IHVuZGVmaW5lZDtcblxuLyoqXG4gKiBJbXBvcnQgdGhlIFdlYkFzc2VtYmx5IG1vZHVsZS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgcGVyZm9ybSB0aGUgZm9sbG93aW5nIHN0ZXBzOlxuICogMS4gSWYgdGhlIGVtYmVkZGVkIG1vZHVsZSBleGlzdHMgYW5kIG5vIGN1c3RvbSBVUkwgaXMgc3BlY2lmaWVkLCB1c2UgdGhlIGVtYmVkZGVkIG1vZHVsZS5cbiAqIDIuIElmIGEgcHJlbG9hZCBpcyBuZWVkZWQsIGl0IHdpbGwgcHJlbG9hZCB0aGUgbW9kdWxlIGFuZCByZXR1cm4gdGhlIG9iamVjdCBVUkwuXG4gKiAzLiBPdGhlcndpc2UsIGl0IHdpbGwgcGVyZm9ybSBhIGR5bmFtaWMgaW1wb3J0IG9mIHRoZSBtb2R1bGUuXG4gKlxuICogQHJldHVybnMgLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIHR1cGxlIG9mIDIgZWxlbWVudHM6XG4gKiAgICAgICAgICAgIC0gVGhlIG9iamVjdCBVUkwgb2YgdGhlIHByZWxvYWRlZCBtb2R1bGUsIG9yIHVuZGVmaW5lZCBpZiBubyBwcmVsb2FkIGlzIG5lZWRlZC5cbiAqICAgICAgICAgICAgLSBUaGUgZGVmYXVsdCBleHBvcnQgb2YgdGhlIG1vZHVsZSwgd2hpY2ggaXMgYSBmYWN0b3J5IGZ1bmN0aW9uIHRvIGNyZWF0ZSB0aGUgV2ViQXNzZW1ibHkgbW9kdWxlLlxuICovXG5leHBvcnQgY29uc3QgaW1wb3J0V2FzbU1vZHVsZSA9IGFzeW5jIChcbiAgdXJsT3ZlcnJpZGU6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgcHJlZml4T3ZlcnJpZGU6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgaXNNdWx0aVRocmVhZGVkOiBib29sZWFuLFxuICBpc1dhc21PdmVycmlkZGVuOiBib29sZWFuLFxuKTogUHJvbWlzZTxbdW5kZWZpbmVkIHwgc3RyaW5nLCBFbXNjcmlwdGVuTW9kdWxlRmFjdG9yeTxPcnRXYXNtTW9kdWxlPl0+ID0+IHtcbiAgLy9cbiAgLy8gQ2hlY2sgaWYgd2Ugc2hvdWxkIHVzZSB0aGUgZW1iZWRkZWQgbW9kdWxlLlxuICAvL1xuXG4gIC8vIFRvIHVzZSB0aGUgZW1iZWRkZWQgbW9kdWxlLCBpdCBzaG91bGQgYmUgYXZhaWxhYmxlLCBhbmQgbm8gVVJMIG92ZXJyaWRlIG9yIHByZWZpeCBvdmVycmlkZSBzaG91bGQgYmUgc3BlY2lmaWVkLlxuICBsZXQgdXNlRW1iZWRkZWRNb2R1bGUgPSBlbWJlZGRlZFdhc21Nb2R1bGUgJiYgISh1cmxPdmVycmlkZSB8fCBwcmVmaXhPdmVycmlkZSk7XG4gIGlmICh1c2VFbWJlZGRlZE1vZHVsZSkge1xuICAgIGlmICghc2NyaXB0U3JjKSB7XG4gICAgICAvLyBubyBVUkwgaW5mbyBhdmFpbGFibGUuXG4gICAgICAvL1xuICAgICAgLy8gTm90ZTogd2hlbiB0aGUgZW1iZWRkZWQgbW9kdWxlIGlzIGF2YWlsYWJsZSwgaXQgbWVhbnMgdGhlIGN1cnJlbnQgc2NyaXB0IGlzIEVTTS4gVXN1YWxseSwgaW4gRVNNLCB0aGVcbiAgICAgIC8vIGBpbXBvcnQubWV0YS51cmxgIGlzIGF2YWlsYWJsZS4gQnV0IGluIHNvbWUgY2FzZXMgKGVnLiBDbG91ZGZsYXJlIFdvcmtlcnMpLCB0aGUgdmFsdWUgb2YgYGltcG9ydC5tZXRhLnVybGBcbiAgICAgIC8vIGNhbiBiZSBgbnVsbGAgb3IgYHVuZGVmaW5lZGAuIEluIHRoaXMgY2FzZSwgd2UgY2FuIG9ubHkgbG9hZCB0aGUgZW1iZWRkZWQgbW9kdWxlIHdoZW46XG4gICAgICAvL1xuICAgICAgLy8gMS4gVGhlIFdlYkFzc2VtYmx5IG1vZHVsZSBiaW5hcnkgaXMgb3ZlcnJpZGRlbjpcbiAgICAgIC8vICAgIGBgYGpzXG4gICAgICAvLyAgICBlbnYud2FzbS53YXNtUGF0aHMgPSB1bmRlZmluZWQ7ICAvLyBvciBub3Qgc3BlY2lmaWVkXG4gICAgICAvLyAgICBlbnYud2FzbS53YXNtQmluYXJ5ID0gLyogYSBVaW50OEFycmF5IGNvbnRhaW5pbmcgdGhlIFdlYkFzc2VtYmx5IGJpbmFyeSAqLztcbiAgICAgIC8vICAgIGBgYFxuICAgICAgLy9cbiAgICAgIC8vIDIuIFRoZSBcIi53YXNtXCIgb25seSBpcyBvdmVycmlkZGVuLlxuICAgICAgLy8gICAgYGBganNcbiAgICAgIC8vICAgIGVudi53YXNtLndhc21QYXRocyA9IHsgd2FzbTogLyogVVJMIG9mIHRoZSAud2FzbSBmaWxlICovIH07XG4gICAgICAvLyAgICBgYGBcbiAgICAgIC8vXG4gICAgICBpZiAoaXNXYXNtT3ZlcnJpZGRlbiAmJiAhaXNNdWx0aVRocmVhZGVkKSB7XG4gICAgICAgIHVzZUVtYmVkZGVkTW9kdWxlID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IGRldGVybWluZSB0aGUgc2NyaXB0IHNvdXJjZSBVUkwuJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGlmIHRoZSBzY3JpcHQgc291cmNlIGlzIGF2YWlsYWJsZSwgd2UgY2FuIGNoZWNrIGlmIGl0IGlzIGZyb20gdGhlIHNhbWUgb3JpZ2luLlxuICAgICAgLy8gQWxzbyB1c2UgdGhlIGVtYmVkZGVkIG1vZHVsZSB3aGVuIHdhc21CaW5hcnkgaXMgcHJvdmlkZWQgYW5kIHNpbmdsZS10aHJlYWRlZCAoZWcuIEJsb2IgVVJMIHdvcmtlcnNcbiAgICAgIC8vIHdoZXJlIGlzU2FtZU9yaWdpbiBmYWlscyBidXQgbm8gZmlsZSByZXNvbHV0aW9uIG9yIHdvcmtlciBzcGF3bmluZyBpcyBuZWVkZWQpLlxuICAgICAgdXNlRW1iZWRkZWRNb2R1bGUgPSBpc1NhbWVPcmlnaW4oc2NyaXB0U3JjKSB8fCAoaXNXYXNtT3ZlcnJpZGRlbiAmJiAhaXNNdWx0aVRocmVhZGVkKTtcbiAgICB9XG4gIH1cbiAgaWYgKHVzZUVtYmVkZGVkTW9kdWxlKSB7XG4gICAgcmV0dXJuIFt1bmRlZmluZWQsIGVtYmVkZGVkV2FzbU1vZHVsZSFdO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHdhc21Nb2R1bGVGaWxlbmFtZSA9ICFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUFxuICAgICAgPyAnb3J0LXdhc20tc2ltZC10aHJlYWRlZC5qc2VwLm1qcydcbiAgICAgIDogQlVJTERfREVGUy5FTkFCTEVfSlNQSVxuICAgICAgICA/ICdvcnQtd2FzbS1zaW1kLXRocmVhZGVkLmpzcGkubWpzJ1xuICAgICAgICA6ICFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVXG4gICAgICAgICAgPyAnb3J0LXdhc20tc2ltZC10aHJlYWRlZC5hc3luY2lmeS5tanMnXG4gICAgICAgICAgOiAnb3J0LXdhc20tc2ltZC10aHJlYWRlZC5tanMnO1xuICAgIGNvbnN0IHdhc21Nb2R1bGVVcmwgPSB1cmxPdmVycmlkZSA/PyBub3JtYWxpemVVcmwod2FzbU1vZHVsZUZpbGVuYW1lLCBwcmVmaXhPdmVycmlkZSk7XG4gICAgLy8gbmVlZCB0byBwcmVsb2FkIGlmIGFsbCBvZiB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcbiAgICAvLyAxLiBub3QgaW4gTm9kZS5qcy5cbiAgICAvLyAgICAtIE5vZGUuanMgZG9lcyBub3QgaGF2ZSB0aGUgc2FtZSBvcmlnaW4gcG9saWN5IGZvciBjcmVhdGluZyB3b3JrZXJzLlxuICAgIC8vIDIuIG11bHRpLXRocmVhZGVkIGlzIGVuYWJsZWQuXG4gICAgLy8gICAgLSBJZiBtdWx0aS10aHJlYWRlZCBpcyBkaXNhYmxlZCwgbm8gd29ya2VyIHdpbGwgYmUgY3JlYXRlZC4gU28gd2UgZG9uJ3QgbmVlZCB0byBwcmVsb2FkIHRoZSBtb2R1bGUuXG4gICAgLy8gMy4gdGhlIGFic29sdXRlIFVSTCBpcyBhdmFpbGFibGUuXG4gICAgLy8gICAgLSBJZiB0aGUgYWJzb2x1dGUgVVJMIGlzIGZhaWxlZCB0byBiZSBjcmVhdGVkLCB0aGUgb3JpZ2luIGNhbm5vdCBiZSBkZXRlcm1pbmVkLiBJbiB0aGlzIGNhc2UsIHdlIHdpbGwgbm90XG4gICAgLy8gICAgcHJlbG9hZCB0aGUgbW9kdWxlLlxuICAgIC8vIDQuIHRoZSB3b3JrZXIgVVJMIGlzIG5vdCBmcm9tIHRoZSBzYW1lIG9yaWdpbi5cbiAgICAvLyAgICAtIElmIHRoZSB3b3JrZXIgVVJMIGlzIGZyb20gdGhlIHNhbWUgb3JpZ2luLCB3ZSBjYW4gY3JlYXRlIHRoZSB3b3JrZXIgZGlyZWN0bHkuXG4gICAgY29uc3QgbmVlZFByZWxvYWQgPSAhaXNOb2RlICYmIGlzTXVsdGlUaHJlYWRlZCAmJiB3YXNtTW9kdWxlVXJsICYmICFpc1NhbWVPcmlnaW4od2FzbU1vZHVsZVVybCwgcHJlZml4T3ZlcnJpZGUpO1xuICAgIGNvbnN0IHVybCA9IG5lZWRQcmVsb2FkXG4gICAgICA/IGF3YWl0IHByZWxvYWQod2FzbU1vZHVsZVVybClcbiAgICAgIDogKHdhc21Nb2R1bGVVcmwgPz8gZmFsbGJhY2tVcmwod2FzbU1vZHVsZUZpbGVuYW1lLCBwcmVmaXhPdmVycmlkZSkpO1xuICAgIHJldHVybiBbbmVlZFByZWxvYWQgPyB1cmwgOiB1bmRlZmluZWQsIGF3YWl0IGR5bmFtaWNJbXBvcnREZWZhdWx0PEVtc2NyaXB0ZW5Nb2R1bGVGYWN0b3J5PE9ydFdhc21Nb2R1bGU+Pih1cmwpXTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRW52IH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHR5cGUgeyBPcnRXYXNtTW9kdWxlIH0gZnJvbSAnLi93YXNtLXR5cGVzJztcbmltcG9ydCB7IGltcG9ydFdhc21Nb2R1bGUsIGluZmVyV2FzbVBhdGhQcmVmaXhGcm9tU2NyaXB0U3JjIH0gZnJvbSAnLi93YXNtLXV0aWxzLWltcG9ydCc7XG5cbmxldCB3YXNtOiBPcnRXYXNtTW9kdWxlIHwgdW5kZWZpbmVkO1xubGV0IGluaXRpYWxpemVkID0gZmFsc2U7XG5sZXQgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG5sZXQgYWJvcnRlZCA9IGZhbHNlO1xuXG5jb25zdCBpc011bHRpVGhyZWFkU3VwcG9ydGVkID0gKCk6IGJvb2xlYW4gPT4ge1xuICAvLyBJZiAnU2hhcmVkQXJyYXlCdWZmZXInIGlzIG5vdCBhdmFpbGFibGUsIFdlYkFzc2VtYmx5IHRocmVhZHMgd2lsbCBub3Qgd29yay5cbiAgaWYgKHR5cGVvZiBTaGFyZWRBcnJheUJ1ZmZlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB0cnkge1xuICAgIC8vIFRlc3QgZm9yIHRyYW5zZmVyYWJpbGl0eSBvZiBTQUJzIChmb3IgYnJvd3NlcnMuIG5lZWRlZCBmb3IgRmlyZWZveClcbiAgICAvLyBodHRwczovL2dyb3Vwcy5nb29nbGUuY29tL2ZvcnVtLyMhbXNnL21vemlsbGEuZGV2LnBsYXRmb3JtL0lIa0JabEhFVHBBL2R3c01OY2hXRVFBSlxuICAgIGlmICh0eXBlb2YgTWVzc2FnZUNoYW5uZWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBuZXcgTWVzc2FnZUNoYW5uZWwoKS5wb3J0MS5wb3N0TWVzc2FnZShuZXcgU2hhcmVkQXJyYXlCdWZmZXIoMSkpO1xuICAgIH1cblxuICAgIC8vIFRlc3QgZm9yIFdlYkFzc2VtYmx5IHRocmVhZHMgY2FwYWJpbGl0eSAoZm9yIGJvdGggYnJvd3NlcnMgYW5kIE5vZGUuanMpXG4gICAgLy8gVGhpcyB0eXBlZCBhcnJheSBpcyBhIFdlYkFzc2VtYmx5IHByb2dyYW0gY29udGFpbmluZyB0aHJlYWRlZCBpbnN0cnVjdGlvbnMuXG4gICAgcmV0dXJuIFdlYkFzc2VtYmx5LnZhbGlkYXRlKFxuICAgICAgbmV3IFVpbnQ4QXJyYXkoW1xuICAgICAgICAwLCA5NywgMTE1LCAxMDksIDEsIDAsIDAsIDAsIDEsIDQsIDEsIDk2LCAwLCAwLCAzLCAyLCAxLCAwLCA1LCA0LCAxLCAzLCAxLCAxLCAxMCwgMTEsIDEsIDksIDAsIDY1LCAwLCAyNTQsIDE2LFxuICAgICAgICAyLCAwLCAyNiwgMTEsXG4gICAgICBdKSxcbiAgICApO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbmNvbnN0IGlzU2ltZFN1cHBvcnRlZCA9ICgpOiBib29sZWFuID0+IHtcbiAgdHJ5IHtcbiAgICAvLyBUZXN0IGZvciBXZWJBc3NlbWJseSBTSU1EIGNhcGFiaWxpdHkgKGZvciBib3RoIGJyb3dzZXJzIGFuZCBOb2RlLmpzKVxuICAgIC8vIFRoaXMgdHlwZWQgYXJyYXkgaXMgYSBXZWJBc3NlbWJseSBwcm9ncmFtIGNvbnRhaW5pbmcgU0lNRCBpbnN0cnVjdGlvbnMuXG5cbiAgICAvLyBUaGUgYmluYXJ5IGRhdGEgaXMgZ2VuZXJhdGVkIGZyb20gdGhlIGZvbGxvd2luZyBjb2RlIGJ5IHdhdDJ3YXNtOlxuICAgIC8vXG4gICAgLy8gKG1vZHVsZVxuICAgIC8vICAgKHR5cGUgJHQwIChmdW5jKSlcbiAgICAvLyAgIChmdW5jICRmMCAodHlwZSAkdDApXG4gICAgLy8gICAgIChkcm9wXG4gICAgLy8gICAgICAgKGkzMng0LmRvdF9pMTZ4OF9zXG4gICAgLy8gICAgICAgICAoaTh4MTYuc3BsYXRcbiAgICAvLyAgICAgICAgICAgKGkzMi5jb25zdCAwKSlcbiAgICAvLyAgICAgICAgICh2MTI4LmNvbnN0IGkzMng0IDB4MDAwMDAwMDAgMHgwMDAwMDAwMCAweDAwMDAwMDAwIDB4MDAwMDAwMDApKSkpKVxuXG4gICAgcmV0dXJuIFdlYkFzc2VtYmx5LnZhbGlkYXRlKFxuICAgICAgbmV3IFVpbnQ4QXJyYXkoW1xuICAgICAgICAwLCA5NywgMTE1LCAxMDksIDEsIDAsIDAsIDAsIDEsIDQsIDEsIDk2LCAwLCAwLCAzLCAyLCAxLCAwLCAxMCwgMzAsIDEsIDI4LCAwLCA2NSwgMCwgMjUzLCAxNSwgMjUzLCAxMiwgMCwgMCwgMCxcbiAgICAgICAgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMjUzLCAxODYsIDEsIDI2LCAxMSxcbiAgICAgIF0pLFxuICAgICk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuY29uc3QgaXNSZWxheGVkU2ltZFN1cHBvcnRlZCA9ICgpOiBib29sZWFuID0+IHtcbiAgdHJ5IHtcbiAgICAvLyBUZXN0IGZvciBXZWJBc3NlbWJseSBSZWxheGVkIFNJTUQgY2FwYWJpbGl0eSAoZm9yIGJvdGggYnJvd3NlcnMgYW5kIE5vZGUuanMpXG4gICAgLy8gVGhpcyB0eXBlZCBhcnJheSBpcyBhIFdlYkFzc2VtYmx5IHByb2dyYW0gY29udGFpbmluZyBSZWxheGVkIFNJTUQgaW5zdHJ1Y3Rpb25zLlxuXG4gICAgLy8gVGhlIGJpbmFyeSBkYXRhIGlzIGdlbmVyYXRlZCBmcm9tIHRoZSBmb2xsb3dpbmcgY29kZSBieSB3YXQyd2FzbTpcbiAgICAvLyAobW9kdWxlXG4gICAgLy8gICAoZnVuYyAocmVzdWx0IHYxMjgpXG4gICAgLy8gICAgICBpMzIuY29uc3QgMVxuICAgIC8vICAgICAgaTh4MTYuc3BsYXRcbiAgICAvLyAgICAgIGkzMi5jb25zdCAyXG4gICAgLy8gICAgICBpOHgxNi5zcGxhdFxuICAgIC8vICAgICAgaTMyLmNvbnN0IDNcbiAgICAvLyAgICAgIGk4eDE2LnNwbGF0XG4gICAgLy8gICAgICBpMzJ4NC5yZWxheGVkX2RvdF9pOHgxNl9pN3gxNl9hZGRfc1xuICAgIC8vICAgKVxuICAgIC8vICApXG4gICAgcmV0dXJuIFdlYkFzc2VtYmx5LnZhbGlkYXRlKFxuICAgICAgbmV3IFVpbnQ4QXJyYXkoW1xuICAgICAgICAwLCA5NywgMTE1LCAxMDksIDEsIDAsIDAsIDAsIDEsIDUsIDEsIDk2LCAwLCAxLCAxMjMsIDMsIDIsIDEsIDAsIDEwLCAxOSwgMSwgMTcsIDAsIDY1LCAxLCAyNTMsIDE1LCA2NSwgMiwgMjUzLFxuICAgICAgICAxNSwgNjUsIDMsIDI1MywgMTUsIDI1MywgMTQ3LCAyLCAxMSxcbiAgICAgIF0pLFxuICAgICk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGluaXRpYWxpemVXZWJBc3NlbWJseSA9IGFzeW5jIChmbGFnczogRW52LldlYkFzc2VtYmx5RmxhZ3MpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKGluaXRpYWxpemVkKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG4gIGlmIChpbml0aWFsaXppbmcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJtdWx0aXBsZSBjYWxscyB0byAnaW5pdGlhbGl6ZVdlYkFzc2VtYmx5KCknIGRldGVjdGVkLlwiKTtcbiAgfVxuICBpZiAoYWJvcnRlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcInByZXZpb3VzIGNhbGwgdG8gJ2luaXRpYWxpemVXZWJBc3NlbWJseSgpJyBmYWlsZWQuXCIpO1xuICB9XG5cbiAgaW5pdGlhbGl6aW5nID0gdHJ1ZTtcblxuICAvLyB3YXNtIGZsYWdzIGFyZSBhbHJlYWR5IGluaXRpYWxpemVkXG4gIGNvbnN0IHRpbWVvdXQgPSBmbGFncy5pbml0VGltZW91dCE7XG4gIGxldCBudW1UaHJlYWRzID0gZmxhZ3MubnVtVGhyZWFkcyE7XG5cbiAgLy8gZW5zdXJlIFNJTUQgaXMgc3VwcG9ydGVkXG4gIGlmIChmbGFncy5zaW1kID09PSBmYWxzZSkge1xuICAgIC8vIHNraXAgU0lNRCBmZWF0dXJlIGNoZWNraW5nIGFzIGl0IGlzIGRpc2FibGVkIGV4cGxpY2l0bHkgYnkgdXNlclxuICB9IGVsc2UgaWYgKGZsYWdzLnNpbWQgPT09ICdyZWxheGVkJykge1xuICAgIC8vIGNoZWNrIGlmIHJlbGF4ZWQgU0lNRCBpcyBzdXBwb3J0ZWRcbiAgICBpZiAoIWlzUmVsYXhlZFNpbWRTdXBwb3J0ZWQoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZWxheGVkIFdlYkFzc2VtYmx5IFNJTUQgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGUgY3VycmVudCBlbnZpcm9ubWVudC4nKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoIWlzU2ltZFN1cHBvcnRlZCgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdXZWJBc3NlbWJseSBTSU1EIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuJyk7XG4gIH1cblxuICBpZiAoQlVJTERfREVGUy5FTkFCTEVfSlNQSSkge1xuICAgIGlmICghKCdTdXNwZW5kaW5nJyBpbiBXZWJBc3NlbWJseSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignV2ViQXNzZW1ibHkgSlNQSSBpcyBub3Qgc3VwcG9ydGVkIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50LicpO1xuICAgIH1cbiAgfVxuXG4gIC8vIGNoZWNrIGlmIG11bHRpLXRocmVhZGluZyBpcyBzdXBwb3J0ZWRcbiAgY29uc3QgbXVsdGlUaHJlYWRTdXBwb3J0ZWQgPSBpc011bHRpVGhyZWFkU3VwcG9ydGVkKCk7XG4gIGlmIChudW1UaHJlYWRzID4gMSAmJiAhbXVsdGlUaHJlYWRTdXBwb3J0ZWQpIHtcbiAgICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmICFzZWxmLmNyb3NzT3JpZ2luSXNvbGF0ZWQpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICdlbnYud2FzbS5udW1UaHJlYWRzIGlzIHNldCB0byAnICtcbiAgICAgICAgICBudW1UaHJlYWRzICtcbiAgICAgICAgICAnLCBidXQgdGhpcyB3aWxsIG5vdCB3b3JrIHVubGVzcyB5b3UgZW5hYmxlIGNyb3NzT3JpZ2luSXNvbGF0ZWQgbW9kZS4gJyArXG4gICAgICAgICAgJ1NlZSBodHRwczovL3dlYi5kZXYvY3Jvc3Mtb3JpZ2luLWlzb2xhdGlvbi1ndWlkZS8gZm9yIG1vcmUgaW5mby4nLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIGNvbnNvbGUud2FybihcbiAgICAgICdXZWJBc3NlbWJseSBtdWx0aS10aHJlYWRpbmcgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGUgY3VycmVudCBlbnZpcm9ubWVudC4gJyArICdGYWxsaW5nIGJhY2sgdG8gc2luZ2xlLXRocmVhZGluZy4nLFxuICAgICk7XG5cbiAgICAvLyBzZXQgZmxhZ3MubnVtVGhyZWFkcyB0byAxIHNvIHRoYXQgT3J0SW5pdCgpIHdpbGwgbm90IGNyZWF0ZSBhIGdsb2JhbCB0aHJlYWQgcG9vbC5cbiAgICBmbGFncy5udW1UaHJlYWRzID0gbnVtVGhyZWFkcyA9IDE7XG4gIH1cblxuICBjb25zdCB3YXNtUGF0aHMgPSBmbGFncy53YXNtUGF0aHM7XG4gIGNvbnN0IHdhc21QcmVmaXhPdmVycmlkZSA9IHR5cGVvZiB3YXNtUGF0aHMgPT09ICdzdHJpbmcnID8gd2FzbVBhdGhzIDogdW5kZWZpbmVkO1xuICBjb25zdCBtanNQYXRoT3ZlcnJpZGVGbGFnID0gKHdhc21QYXRocyBhcyBFbnYuV2FzbUZpbGVQYXRocyk/Lm1qcztcbiAgY29uc3QgbWpzUGF0aE92ZXJyaWRlID0gKG1qc1BhdGhPdmVycmlkZUZsYWcgYXMgVVJMKT8uaHJlZiA/PyBtanNQYXRoT3ZlcnJpZGVGbGFnO1xuICBjb25zdCB3YXNtUGF0aE92ZXJyaWRlRmxhZyA9ICh3YXNtUGF0aHMgYXMgRW52Lldhc21GaWxlUGF0aHMpPy53YXNtO1xuICBjb25zdCB3YXNtUGF0aE92ZXJyaWRlID0gKHdhc21QYXRoT3ZlcnJpZGVGbGFnIGFzIFVSTCk/LmhyZWYgPz8gd2FzbVBhdGhPdmVycmlkZUZsYWc7XG4gIGNvbnN0IHdhc21CaW5hcnlPdmVycmlkZSA9IGZsYWdzLndhc21CaW5hcnk7XG5cbiAgY29uc3QgW29iamVjdFVybCwgb3J0V2FzbUZhY3RvcnldID0gYXdhaXQgaW1wb3J0V2FzbU1vZHVsZShcbiAgICBtanNQYXRoT3ZlcnJpZGUsXG4gICAgd2FzbVByZWZpeE92ZXJyaWRlLFxuICAgIG51bVRocmVhZHMgPiAxLFxuICAgICEhd2FzbUJpbmFyeU92ZXJyaWRlIHx8ICEhd2FzbVBhdGhPdmVycmlkZSxcbiAgKTtcblxuICBsZXQgaXNUaW1lb3V0ID0gZmFsc2U7XG5cbiAgY29uc3QgdGFza3M6IEFycmF5PFByb21pc2U8dm9pZD4+ID0gW107XG5cbiAgLy8gcHJvbWlzZSBmb3IgdGltZW91dFxuICBpZiAodGltZW91dCA+IDApIHtcbiAgICB0YXNrcy5wdXNoKFxuICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgaXNUaW1lb3V0ID0gdHJ1ZTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0sIHRpbWVvdXQpO1xuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIC8vIHByb21pc2UgZm9yIG1vZHVsZSBpbml0aWFsaXphdGlvblxuICB0YXNrcy5wdXNoKFxuICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGNvbmZpZzogUGFydGlhbDxPcnRXYXNtTW9kdWxlPiA9IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBudW1iZXIgb2YgdGhyZWFkcy4gV2ViQXNzZW1ibHkgd2lsbCBjcmVhdGUgKE1vZHVsZS5udW1UaHJlYWRzIC0gMSkgd29ya2Vycy4gSWYgaXQgaXMgMSwgbm8gd29ya2VyIHdpbGwgYmVcbiAgICAgICAgICogY3JlYXRlZC5cbiAgICAgICAgICovXG4gICAgICAgIG51bVRocmVhZHMsXG4gICAgICB9O1xuXG4gICAgICBpZiAod2FzbUJpbmFyeU92ZXJyaWRlKSB7XG4gICAgICAgIC8vIFNldCBhIGN1c3RvbSBidWZmZXIgd2hpY2ggY29udGFpbnMgdGhlIFdlYkFzc2VtYmx5IGJpbmFyeS4gVGhpcyB3aWxsIHNraXAgdGhlIHdhc20gZmlsZSBmZXRjaGluZy5cbiAgICAgICAgY29uZmlnLndhc21CaW5hcnkgPSB3YXNtQmluYXJ5T3ZlcnJpZGU7XG5cbiAgICAgICAgLy8gT2ZmZXIgYW4gaW1wbGVtZW50YXRpb24gb2YgbG9jYXRlRmlsZSgpIHRoYXQgcmV0dXJucyB0aGUgZmlsZSBuYW1lIGRpcmVjdGx5LiBUaGlzIGhlbHBzIHRvIGF2b2lkIGFuIGVycm9yXG4gICAgICAgIC8vIHRocm93biBsYXRlciBmcm9tIHRoZSBmb2xsb3dpbmcgY29kZSB3aGVuIGBpbXBvcnQubWV0YS51cmxgIGlzIGEgYmxvYiBVUkw6XG4gICAgICAgIC8vIGBgYFxuICAgICAgICAvLyAgIHJldHVybiBuZXcgVVJMKFwib3J0LXdhc20tc2ltZC10aHJlYWRlZC5qc2VwLndhc21cIiwgaW1wb3J0Lm1ldGEudXJsKS5ocmVmO1xuICAgICAgICAvLyBgYGBcbiAgICAgICAgY29uZmlnLmxvY2F0ZUZpbGUgPSAoZmlsZU5hbWUpID0+IGZpbGVOYW1lO1xuICAgICAgfSBlbHNlIGlmICh3YXNtUGF0aE92ZXJyaWRlIHx8IHdhc21QcmVmaXhPdmVycmlkZSkge1xuICAgICAgICAvLyBBIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGxvY2F0ZSB0aGUgV2ViQXNzZW1ibHkgZmlsZS4gVGhlIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gdGhlIGZ1bGwgcGF0aCBvZiB0aGUgZmlsZS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gU2luY2UgRW1zY3JpcHRlbiAzLjEuNTgsIHRoaXMgZnVuY3Rpb24gaXMgb25seSBjYWxsZWQgZm9yIHRoZSAud2FzbSBmaWxlLlxuICAgICAgICBjb25maWcubG9jYXRlRmlsZSA9IChmaWxlTmFtZSkgPT4gd2FzbVBhdGhPdmVycmlkZSA/PyB3YXNtUHJlZml4T3ZlcnJpZGUgKyBmaWxlTmFtZTtcbiAgICAgIH0gZWxzZSBpZiAobWpzUGF0aE92ZXJyaWRlICYmIG1qc1BhdGhPdmVycmlkZS5pbmRleE9mKCdibG9iOicpICE9PSAwKSB7XG4gICAgICAgIC8vIGlmIG1qcyBwYXRoIGlzIHNwZWNpZmllZCwgdXNlIGl0IGFzIHRoZSBiYXNlIHBhdGggZm9yIHRoZSAud2FzbSBmaWxlLlxuICAgICAgICBjb25maWcubG9jYXRlRmlsZSA9IChmaWxlTmFtZSkgPT4gbmV3IFVSTChmaWxlTmFtZSwgbWpzUGF0aE92ZXJyaWRlKS5ocmVmO1xuICAgICAgfSBlbHNlIGlmIChvYmplY3RVcmwpIHtcbiAgICAgICAgY29uc3QgaW5mZXJyZWRXYXNtUGF0aFByZWZpeCA9IGluZmVyV2FzbVBhdGhQcmVmaXhGcm9tU2NyaXB0U3JjKCk7XG4gICAgICAgIGlmIChpbmZlcnJlZFdhc21QYXRoUHJlZml4KSB7XG4gICAgICAgICAgLy8gaWYgdGhlIHdhc20gbW9kdWxlIGlzIHByZWxvYWRlZCwgdXNlIHRoZSBpbmZlcnJlZCB3YXNtIHBhdGggYXMgdGhlIGJhc2UgcGF0aCBmb3IgdGhlIC53YXNtIGZpbGUuXG4gICAgICAgICAgY29uZmlnLmxvY2F0ZUZpbGUgPSAoZmlsZU5hbWUpID0+IGluZmVycmVkV2FzbVBhdGhQcmVmaXggKyBmaWxlTmFtZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBvcnRXYXNtRmFjdG9yeShjb25maWcpLnRoZW4oXG4gICAgICAgIC8vIHdhc20gbW9kdWxlIGluaXRpYWxpemVkIHN1Y2Nlc3NmdWxseVxuICAgICAgICAobW9kdWxlKSA9PiB7XG4gICAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG4gICAgICAgICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICAgIHdhc20gPSBtb2R1bGU7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIGlmIChvYmplY3RVcmwpIHtcbiAgICAgICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwob2JqZWN0VXJsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIC8vIHdhc20gbW9kdWxlIGZhaWxlZCB0byBpbml0aWFsaXplXG4gICAgICAgICh3aGF0KSA9PiB7XG4gICAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG4gICAgICAgICAgYWJvcnRlZCA9IHRydWU7XG4gICAgICAgICAgcmVqZWN0KHdoYXQpO1xuICAgICAgICB9LFxuICAgICAgKTtcbiAgICB9KSxcbiAgKTtcblxuICBhd2FpdCBQcm9taXNlLnJhY2UodGFza3MpO1xuXG4gIGlmIChpc1RpbWVvdXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFdlYkFzc2VtYmx5IGJhY2tlbmQgaW5pdGlhbGl6aW5nIGZhaWxlZCBkdWUgdG8gdGltZW91dDogJHt0aW1lb3V0fW1zYCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbnN0YW5jZSA9ICgpOiBPcnRXYXNtTW9kdWxlID0+IHtcbiAgaWYgKGluaXRpYWxpemVkICYmIHdhc20pIHtcbiAgICByZXR1cm4gd2FzbTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignV2ViQXNzZW1ibHkgaXMgbm90IGluaXRpYWxpemVkIHlldC4nKTtcbn07XG5cbmV4cG9ydCBjb25zdCBkaXNwb3NlID0gKCk6IHZvaWQgPT4ge1xuICBpZiAoaW5pdGlhbGl6ZWQgJiYgIWluaXRpYWxpemluZyAmJiAhYWJvcnRlZCkge1xuICAgIC8vIFRPRE86IGN1cnJlbnRseSBcIlBUaHJlYWQudGVybWluYXRlQWxsVGhyZWFkcygpXCIgaXMgbm90IGV4cG9zZWQgaW4gdGhlIHdhc20gbW9kdWxlLlxuICAgIC8vICAgICAgIEFuZCB0aGlzIGZ1bmN0aW9uIGlzIG5vdCB5ZXQgY2FsbGVkIGJ5IGFueSBjb2RlLlxuICAgIC8vICAgICAgIElmIGl0IGlzIG5lZWRlZCBpbiB0aGUgZnV0dXJlLCB3ZSBzaG91bGQgZXhwb3NlIGl0IGluIHRoZSB3YXNtIG1vZHVsZSBhbmQgdW5jb21tZW50IHRoZSBmb2xsb3dpbmcgbGluZS5cblxuICAgIC8vIHdhc20/LlBUaHJlYWQ/LnRlcm1pbmF0ZUFsbFRocmVhZHMoKTtcbiAgICB3YXNtID0gdW5kZWZpbmVkO1xuXG4gICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG4gICAgaW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICBhYm9ydGVkID0gdHJ1ZTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgZ2V0SW5zdGFuY2UgfSBmcm9tICcuL3dhc20tZmFjdG9yeSc7XG5cbmV4cG9ydCBjb25zdCBhbGxvY1dhc21TdHJpbmcgPSAoZGF0YTogc3RyaW5nLCBhbGxvY3M6IG51bWJlcltdKTogbnVtYmVyID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG5cbiAgY29uc3QgZGF0YUxlbmd0aCA9IHdhc20ubGVuZ3RoQnl0ZXNVVEY4KGRhdGEpICsgMTtcbiAgY29uc3QgZGF0YU9mZnNldCA9IHdhc20uX21hbGxvYyhkYXRhTGVuZ3RoKTtcbiAgd2FzbS5zdHJpbmdUb1VURjgoZGF0YSwgZGF0YU9mZnNldCwgZGF0YUxlbmd0aCk7XG4gIGFsbG9jcy5wdXNoKGRhdGFPZmZzZXQpO1xuXG4gIHJldHVybiBkYXRhT2Zmc2V0O1xufTtcblxuaW50ZXJmYWNlIEV4dHJhT3B0aW9uc0hhbmRsZXIge1xuICAobmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKTogdm9pZDtcbn1cblxuZXhwb3J0IGNvbnN0IGl0ZXJhdGVFeHRyYU9wdGlvbnMgPSAoXG4gIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBwcmVmaXg6IHN0cmluZyxcbiAgc2VlbjogV2Vha1NldDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4sXG4gIGhhbmRsZXI6IEV4dHJhT3B0aW9uc0hhbmRsZXIsXG4pOiB2b2lkID0+IHtcbiAgaWYgKHR5cGVvZiBvcHRpb25zID09ICdvYmplY3QnICYmIG9wdGlvbnMgIT09IG51bGwpIHtcbiAgICBpZiAoc2Vlbi5oYXMob3B0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2lyY3VsYXIgcmVmZXJlbmNlIGluIG9wdGlvbnMnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2Vlbi5hZGQob3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgT2JqZWN0LmVudHJpZXMob3B0aW9ucykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgY29uc3QgbmFtZSA9IHByZWZpeCA/IHByZWZpeCArIGtleSA6IGtleTtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgaXRlcmF0ZUV4dHJhT3B0aW9ucyh2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgbmFtZSArICcuJywgc2VlbiwgaGFuZGxlcik7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGhhbmRsZXIobmFtZSwgdmFsdWUudG9TdHJpbmcoKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykge1xuICAgICAgaGFuZGxlcihuYW1lLCB2YWx1ZSA/ICcxJyA6ICcwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3QgaGFuZGxlIGV4dHJhIGNvbmZpZyB0eXBlOiAke3R5cGVvZiB2YWx1ZX1gKTtcbiAgICB9XG4gIH0pO1xufTtcblxuLyoqXG4gKiBjaGVjayB3ZWIgYXNzZW1ibHkgQVBJJ3MgbGFzdCBlcnJvciBhbmQgdGhyb3cgZXJyb3IgaWYgYW55IGVycm9yIG9jY3VycmVkLlxuICogQHBhcmFtIG1lc3NhZ2UgYSBtZXNzYWdlIHVzZWQgd2hlbiBhbiBlcnJvciBvY2N1cnJlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IGNoZWNrTGFzdEVycm9yID0gKG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQgPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcblxuICBjb25zdCBzdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XG4gIHRyeSB7XG4gICAgY29uc3QgcHRyU2l6ZSA9IHdhc20uUFRSX1NJWkU7XG4gICAgY29uc3QgcGFyYW1zT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKDIgKiBwdHJTaXplKTtcbiAgICB3YXNtLl9PcnRHZXRMYXN0RXJyb3IocGFyYW1zT2Zmc2V0LCBwYXJhbXNPZmZzZXQgKyBwdHJTaXplKTtcbiAgICBjb25zdCBlcnJvckNvZGUgPSBOdW1iZXIod2FzbS5nZXRWYWx1ZShwYXJhbXNPZmZzZXQsIHB0clNpemUgPT09IDQgPyAnaTMyJyA6ICdpNjQnKSk7XG4gICAgY29uc3QgZXJyb3JNZXNzYWdlUG9pbnRlciA9IHdhc20uZ2V0VmFsdWUocGFyYW1zT2Zmc2V0ICsgcHRyU2l6ZSwgJyonKTtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvck1lc3NhZ2VQb2ludGVyID8gd2FzbS5VVEY4VG9TdHJpbmcoZXJyb3JNZXNzYWdlUG9pbnRlcikgOiAnJztcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bWVzc2FnZX0gRVJST1JfQ09ERTogJHtlcnJvckNvZGV9LCBFUlJPUl9NRVNTQUdFOiAke2Vycm9yTWVzc2FnZX1gKTtcbiAgfSBmaW5hbGx5IHtcbiAgICB3YXNtLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb24gfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBnZXRJbnN0YW5jZSB9IGZyb20gJy4vd2FzbS1mYWN0b3J5JztcbmltcG9ydCB7IGFsbG9jV2FzbVN0cmluZywgY2hlY2tMYXN0RXJyb3IsIGl0ZXJhdGVFeHRyYU9wdGlvbnMgfSBmcm9tICcuL3dhc20tdXRpbHMnO1xuXG5leHBvcnQgY29uc3Qgc2V0UnVuT3B0aW9ucyA9IChvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMpOiBbbnVtYmVyLCBudW1iZXJbXV0gPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgbGV0IHJ1bk9wdGlvbnNIYW5kbGUgPSAwO1xuICBjb25zdCBhbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgY29uc3QgcnVuT3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICB0cnkge1xuICAgIGlmIChvcHRpb25zPy5sb2dTZXZlcml0eUxldmVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJ1bk9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA9IDI7IC8vIERlZmF1bHQgdG8gd2FybmluZ1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICB0eXBlb2Ygb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsICE9PSAnbnVtYmVyJyB8fFxuICAgICAgIU51bWJlci5pc0ludGVnZXIob3B0aW9ucy5sb2dTZXZlcml0eUxldmVsKSB8fFxuICAgICAgb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsIDwgMCB8fFxuICAgICAgb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsID4gNFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgc2V2ZXJpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke29wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbH1gKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucz8ubG9nVmVyYm9zaXR5TGV2ZWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcnVuT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCA9IDA7IC8vIERlZmF1bHQgdG8gMFxuICAgIH0gZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyB2ZXJib3NpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke29wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWx9YCk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LnRlcm1pbmF0ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBydW5PcHRpb25zLnRlcm1pbmF0ZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGxldCB0YWdEYXRhT2Zmc2V0ID0gMDtcbiAgICBpZiAob3B0aW9ucz8udGFnICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRhZ0RhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcob3B0aW9ucy50YWcsIGFsbG9jcyk7XG4gICAgfVxuXG4gICAgcnVuT3B0aW9uc0hhbmRsZSA9IHdhc20uX09ydENyZWF0ZVJ1bk9wdGlvbnMoXG4gICAgICBydW5PcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwhLFxuICAgICAgcnVuT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCEsXG4gICAgICAhIXJ1bk9wdGlvbnMudGVybWluYXRlISxcbiAgICAgIHRhZ0RhdGFPZmZzZXQsXG4gICAgKTtcbiAgICBpZiAocnVuT3B0aW9uc0hhbmRsZSA9PT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBjcmVhdGUgcnVuIG9wdGlvbnMuXCIpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5leHRyYSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpdGVyYXRlRXh0cmFPcHRpb25zKG9wdGlvbnMuZXh0cmEsICcnLCBuZXcgV2Vha1NldDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oKSwgKGtleSwgdmFsdWUpID0+IHtcbiAgICAgICAgY29uc3Qga2V5RGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhrZXksIGFsbG9jcyk7XG4gICAgICAgIGNvbnN0IHZhbHVlRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyh2YWx1ZSwgYWxsb2NzKTtcblxuICAgICAgICBpZiAod2FzbS5fT3J0QWRkUnVuQ29uZmlnRW50cnkocnVuT3B0aW9uc0hhbmRsZSwga2V5RGF0YU9mZnNldCwgdmFsdWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xuICAgICAgICAgIGNoZWNrTGFzdEVycm9yKGBDYW4ndCBzZXQgYSBydW4gY29uZmlnIGVudHJ5OiAke2tleX0gLSAke3ZhbHVlfS5gKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtydW5PcHRpb25zSGFuZGxlLCBhbGxvY3NdO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKHJ1bk9wdGlvbnNIYW5kbGUgIT09IDApIHtcbiAgICAgIHdhc20uX09ydFJlbGVhc2VSdW5PcHRpb25zKHJ1bk9wdGlvbnNIYW5kbGUpO1xuICAgIH1cbiAgICBhbGxvY3MuZm9yRWFjaCgoYWxsb2MpID0+IHdhc20uX2ZyZWUoYWxsb2MpKTtcbiAgICB0aHJvdyBlO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgdHlwZSB7IEluZmVyZW5jZVNlc3Npb24gfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBnZXRJbnN0YW5jZSB9IGZyb20gJy4vd2FzbS1mYWN0b3J5JztcbmltcG9ydCB7IGFsbG9jV2FzbVN0cmluZywgY2hlY2tMYXN0RXJyb3IsIGl0ZXJhdGVFeHRyYU9wdGlvbnMgfSBmcm9tICcuL3dhc20tdXRpbHMnO1xuXG5jb25zdCBnZXRHcmFwaE9wdGltemF0aW9uTGV2ZWwgPSAoZ3JhcGhPcHRpbWl6YXRpb25MZXZlbDogc3RyaW5nIHwgdW5rbm93bik6IG51bWJlciA9PiB7XG4gIHN3aXRjaCAoZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCkge1xuICAgIGNhc2UgJ2Rpc2FibGVkJzpcbiAgICAgIHJldHVybiAwO1xuICAgIGNhc2UgJ2Jhc2ljJzpcbiAgICAgIHJldHVybiAxO1xuICAgIGNhc2UgJ2V4dGVuZGVkJzpcbiAgICAgIHJldHVybiAyO1xuICAgIGNhc2UgJ2xheW91dCc6XG4gICAgICByZXR1cm4gMztcbiAgICBjYXNlICdhbGwnOlxuICAgICAgcmV0dXJuIDk5O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGdyYXBoIG9wdGltaXphdGlvbiBsZXZlbDogJHtncmFwaE9wdGltaXphdGlvbkxldmVsfWApO1xuICB9XG59O1xuXG5jb25zdCBnZXRFeGVjdXRpb25Nb2RlID0gKGV4ZWN1dGlvbk1vZGU6ICdzZXF1ZW50aWFsJyB8ICdwYXJhbGxlbCcpOiBudW1iZXIgPT4ge1xuICBzd2l0Y2ggKGV4ZWN1dGlvbk1vZGUpIHtcbiAgICBjYXNlICdzZXF1ZW50aWFsJzpcbiAgICAgIHJldHVybiAwO1xuICAgIGNhc2UgJ3BhcmFsbGVsJzpcbiAgICAgIHJldHVybiAxO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGV4ZWN1dGlvbiBtb2RlOiAke2V4ZWN1dGlvbk1vZGV9YCk7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGVuZERlZmF1bHRPcHRpb25zID0gKG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiB2b2lkID0+IHtcbiAgaWYgKCFvcHRpb25zLmV4dHJhKSB7XG4gICAgb3B0aW9ucy5leHRyYSA9IHt9O1xuICB9XG4gIGlmICghb3B0aW9ucy5leHRyYS5zZXNzaW9uKSB7XG4gICAgb3B0aW9ucy5leHRyYS5zZXNzaW9uID0ge307XG4gIH1cbiAgY29uc3Qgc2Vzc2lvbiA9IG9wdGlvbnMuZXh0cmEuc2Vzc2lvbiBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBpZiAoIXNlc3Npb24udXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjYW1lbGNhc2VcbiAgICBzZXNzaW9uLnVzZV9vcnRfbW9kZWxfYnl0ZXNfZGlyZWN0bHkgPSAnMSc7XG4gIH1cblxuICAvLyBpZiB1c2luZyBKU0VQIHdpdGggV2ViR1BVLCBhbHdheXMgZGlzYWJsZSBtZW1vcnkgcGF0dGVyblxuICBpZiAoXG4gICAgb3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMgJiZcbiAgICBvcHRpb25zLmV4ZWN1dGlvblByb3ZpZGVycy5zb21lKChlcCkgPT4gKHR5cGVvZiBlcCA9PT0gJ3N0cmluZycgPyBlcCA6IGVwLm5hbWUpID09PSAnd2ViZ3B1JylcbiAgKSB7XG4gICAgb3B0aW9ucy5lbmFibGVNZW1QYXR0ZXJuID0gZmFsc2U7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGVuZFNlc3Npb25Db25maWcgPSAoc2Vzc2lvbk9wdGlvbnNIYW5kbGU6IG51bWJlciwga2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIGFsbG9jczogbnVtYmVyW10pOiB2b2lkID0+IHtcbiAgY29uc3Qga2V5RGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhrZXksIGFsbG9jcyk7XG4gIGNvbnN0IHZhbHVlRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyh2YWx1ZSwgYWxsb2NzKTtcbiAgaWYgKGdldEluc3RhbmNlKCkuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShzZXNzaW9uT3B0aW9uc0hhbmRsZSwga2V5RGF0YU9mZnNldCwgdmFsdWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xuICAgIGNoZWNrTGFzdEVycm9yKGBDYW4ndCBzZXQgYSBzZXNzaW9uIGNvbmZpZyBlbnRyeTogJHtrZXl9IC0gJHt2YWx1ZX0uYCk7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGVuZEVwT3B0aW9uID0gKGVwT3B0aW9uczogQXJyYXk8W251bWJlciwgbnVtYmVyXT4sIGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCBhbGxvY3M6IG51bWJlcltdKTogdm9pZCA9PiB7XG4gIGNvbnN0IGtleURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcoa2V5LCBhbGxvY3MpO1xuICBjb25zdCB2YWx1ZURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcodmFsdWUsIGFsbG9jcyk7XG4gIGVwT3B0aW9ucy5wdXNoKFtrZXlEYXRhT2Zmc2V0LCB2YWx1ZURhdGFPZmZzZXRdKTtcbn07XG5cbmNvbnN0IHNldEV4ZWN1dGlvblByb3ZpZGVycyA9IGFzeW5jIChcbiAgc2Vzc2lvbk9wdGlvbnNIYW5kbGU6IG51bWJlcixcbiAgc2Vzc2lvbk9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMsXG4gIGFsbG9jczogbnVtYmVyW10sXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgY29uc3QgZXhlY3V0aW9uUHJvdmlkZXJzID0gc2Vzc2lvbk9wdGlvbnMuZXhlY3V0aW9uUHJvdmlkZXJzITtcbiAgZm9yIChjb25zdCBlcCBvZiBleGVjdXRpb25Qcm92aWRlcnMpIHtcbiAgICBsZXQgZXBOYW1lID0gdHlwZW9mIGVwID09PSAnc3RyaW5nJyA/IGVwIDogZXAubmFtZTtcbiAgICBjb25zdCBlcE9wdGlvbnM6IEFycmF5PFtudW1iZXIsIG51bWJlcl0+ID0gW107XG5cbiAgICAvLyBjaGVjayBFUCBuYW1lXG4gICAgc3dpdGNoIChlcE5hbWUpIHtcbiAgICAgIGNhc2UgJ3dlYm5uJzpcbiAgICAgICAgZXBOYW1lID0gJ1dFQk5OJztcbiAgICAgICAgLy8gRGlzYWJsZSBRRFEgZnVzaW9uIHNvIERRL1Egbm9kZXMgYXJlIHByZXNlcnZlZCBhcyBpbmRpdmlkdWFsIG9wcyBmb3IgV2ViTk4gRVAuXG4gICAgICAgIGFwcGVuZFNlc3Npb25Db25maWcoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsICdzZXNzaW9uLmRpc2FibGVfcXVhbnRfcWRxJywgJzEnLCBhbGxvY3MpO1xuICAgICAgICAvLyBGb3JjaWJseSBwcmV2ZW50IGNvbnN0YW50IGZvbGRpbmcgZnJvbSByZXBsYWNpbmcgRFEgbm9kZXMgd2l0aCBjb25zdGFudHMuXG4gICAgICAgIGFwcGVuZFNlc3Npb25Db25maWcoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsICdzZXNzaW9uLmRpc2FibGVfcWRxX2NvbnN0YW50X2ZvbGRpbmcnLCAnMScsIGFsbG9jcyk7XG4gICAgICAgIGlmICh0eXBlb2YgZXAgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgY29uc3Qgd2Vibm5PcHRpb25zID0gZXAgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJOTkV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgICAgICAgIC8vIGNvbnN0IGNvbnRleHQgPSAod2Vibm5PcHRpb25zIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViTk5PcHRpb25zV2l0aE1MQ29udGV4dCk/LmNvbnRleHQ7XG4gICAgICAgICAgY29uc3QgZGV2aWNlVHlwZSA9ICh3ZWJubk9wdGlvbnMgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJOTkNvbnRleHRPcHRpb25zKT8uZGV2aWNlVHlwZTtcbiAgICAgICAgICBpZiAoZGV2aWNlVHlwZSkge1xuICAgICAgICAgICAgYXBwZW5kU2Vzc2lvbkNvbmZpZyhzZXNzaW9uT3B0aW9uc0hhbmRsZSwgJ2RldmljZVR5cGUnLCBkZXZpY2VUeXBlLCBhbGxvY3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3dlYmdwdSc6XG4gICAgICAgIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dFQkdQVSkge1xuICAgICAgICAgIGVwTmFtZSA9ICdXZWJHUFUnO1xuICAgICAgICAgIGxldCBjdXN0b21EZXZpY2U6IEdQVURldmljZSB8IHVuZGVmaW5lZDtcblxuICAgICAgICAgIGlmICh0eXBlb2YgZXAgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCB3ZWJncHVPcHRpb25zID0gZXAgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJHcHVFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcblxuICAgICAgICAgICAgLy8gc2V0IGN1c3RvbSBHUFUgZGV2aWNlXG4gICAgICAgICAgICBpZiAod2ViZ3B1T3B0aW9ucy5kZXZpY2UpIHtcbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBHUFVEZXZpY2UgIT09ICd1bmRlZmluZWQnICYmIHdlYmdwdU9wdGlvbnMuZGV2aWNlIGluc3RhbmNlb2YgR1BVRGV2aWNlKSB7XG4gICAgICAgICAgICAgICAgY3VzdG9tRGV2aWNlID0gd2ViZ3B1T3B0aW9ucy5kZXZpY2U7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEdQVSBkZXZpY2Ugc2V0IGluIFdlYkdQVSBFUCBvcHRpb25zLicpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHNldCBncmFwaCBjYXB0dXJlIG9wdGlvbiBmcm9tIHNlc3Npb24gb3B0aW9uc1xuICAgICAgICAgICAgY29uc3QgeyBlbmFibGVHcmFwaENhcHR1cmUgfSA9IHNlc3Npb25PcHRpb25zO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBlbmFibGVHcmFwaENhcHR1cmUgPT09ICdib29sZWFuJyAmJiBlbmFibGVHcmFwaENhcHR1cmUpIHtcbiAgICAgICAgICAgICAgYXBwZW5kRXBPcHRpb24oZXBPcHRpb25zLCAnZW5hYmxlR3JhcGhDYXB0dXJlJywgJzEnLCBhbGxvY3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBzZXQgbGF5b3V0IG9wdGlvblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB3ZWJncHVPcHRpb25zLnByZWZlcnJlZExheW91dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgYXBwZW5kRXBPcHRpb24oZXBPcHRpb25zLCAncHJlZmVycmVkTGF5b3V0Jywgd2ViZ3B1T3B0aW9ucy5wcmVmZXJyZWRMYXlvdXQsIGFsbG9jcyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHNldCBmb3JjZSBDUFUgZmFsbGJhY2sgbm9kZXNcbiAgICAgICAgICAgIGlmICh3ZWJncHVPcHRpb25zLmZvcmNlQ3B1Tm9kZU5hbWVzKSB7XG4gICAgICAgICAgICAgIGNvbnN0IG5hbWVzID0gQXJyYXkuaXNBcnJheSh3ZWJncHVPcHRpb25zLmZvcmNlQ3B1Tm9kZU5hbWVzKVxuICAgICAgICAgICAgICAgID8gd2ViZ3B1T3B0aW9ucy5mb3JjZUNwdU5vZGVOYW1lc1xuICAgICAgICAgICAgICAgIDogW3dlYmdwdU9wdGlvbnMuZm9yY2VDcHVOb2RlTmFtZXNdO1xuXG4gICAgICAgICAgICAgIGFwcGVuZEVwT3B0aW9uKGVwT3B0aW9ucywgJ2ZvcmNlQ3B1Tm9kZU5hbWVzJywgbmFtZXMuam9pbignXFxuJyksIGFsbG9jcyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHNldCB2YWxpZGF0aW9uIG1vZGVcbiAgICAgICAgICAgIGlmICh3ZWJncHVPcHRpb25zLnZhbGlkYXRpb25Nb2RlKSB7XG4gICAgICAgICAgICAgIGFwcGVuZEVwT3B0aW9uKGVwT3B0aW9ucywgJ3ZhbGlkYXRpb25Nb2RlJywgd2ViZ3B1T3B0aW9ucy52YWxpZGF0aW9uTW9kZSwgYWxsb2NzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBpbmZvID0gZ2V0SW5zdGFuY2UoKS53ZWJncHVSZWdpc3RlckRldmljZSEoY3VzdG9tRGV2aWNlKTtcbiAgICAgICAgICBpZiAoaW5mbykge1xuICAgICAgICAgICAgY29uc3QgW2RldmljZUlkLCBpbnN0YW5jZUhhbmRsZSwgZGV2aWNlSGFuZGxlXSA9IGluZm87XG4gICAgICAgICAgICBhcHBlbmRFcE9wdGlvbihlcE9wdGlvbnMsICdkZXZpY2VJZCcsIGRldmljZUlkLnRvU3RyaW5nKCksIGFsbG9jcyk7XG4gICAgICAgICAgICBhcHBlbmRFcE9wdGlvbihlcE9wdGlvbnMsICd3ZWJncHVJbnN0YW5jZScsIGluc3RhbmNlSGFuZGxlLnRvU3RyaW5nKCksIGFsbG9jcyk7XG4gICAgICAgICAgICBhcHBlbmRFcE9wdGlvbihlcE9wdGlvbnMsICd3ZWJncHVEZXZpY2UnLCBkZXZpY2VIYW5kbGUudG9TdHJpbmcoKSwgYWxsb2NzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZXBOYW1lID0gJ0pTJztcbiAgICAgICAgICBpZiAodHlwZW9mIGVwICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uc3Qgd2ViZ3B1T3B0aW9ucyA9IGVwIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViR3B1RXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgICAgICAgICBpZiAod2ViZ3B1T3B0aW9ucz8ucHJlZmVycmVkTGF5b3V0KSB7XG4gICAgICAgICAgICAgIGlmICh3ZWJncHVPcHRpb25zLnByZWZlcnJlZExheW91dCAhPT0gJ05DSFcnICYmIHdlYmdwdU9wdGlvbnMucHJlZmVycmVkTGF5b3V0ICE9PSAnTkhXQycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHByZWZlcnJlZExheW91dCBtdXN0IGJlIGVpdGhlciAnTkNIVycgb3IgJ05IV0MnOiAke3dlYmdwdU9wdGlvbnMucHJlZmVycmVkTGF5b3V0fWApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGFwcGVuZFNlc3Npb25Db25maWcoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsICdwcmVmZXJyZWRMYXlvdXQnLCB3ZWJncHVPcHRpb25zLnByZWZlcnJlZExheW91dCwgYWxsb2NzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd3YXNtJzpcbiAgICAgIGNhc2UgJ2NwdSc6XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGV4ZWN1dGlvbiBwcm92aWRlcjogJHtlcE5hbWV9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgZXBOYW1lRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhlcE5hbWUsIGFsbG9jcyk7XG4gICAgY29uc3QgZXBPcHRpb25zQ291bnQgPSBlcE9wdGlvbnMubGVuZ3RoO1xuICAgIGxldCBrZXlzT2Zmc2V0ID0gMDtcbiAgICBsZXQgdmFsdWVzT2Zmc2V0ID0gMDtcbiAgICBpZiAoZXBPcHRpb25zQ291bnQgPiAwKSB7XG4gICAgICBrZXlzT2Zmc2V0ID0gZ2V0SW5zdGFuY2UoKS5fbWFsbG9jKGVwT3B0aW9uc0NvdW50ICogZ2V0SW5zdGFuY2UoKS5QVFJfU0laRSk7XG4gICAgICBhbGxvY3MucHVzaChrZXlzT2Zmc2V0KTtcbiAgICAgIHZhbHVlc09mZnNldCA9IGdldEluc3RhbmNlKCkuX21hbGxvYyhlcE9wdGlvbnNDb3VudCAqIGdldEluc3RhbmNlKCkuUFRSX1NJWkUpO1xuICAgICAgYWxsb2NzLnB1c2godmFsdWVzT2Zmc2V0KTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXBPcHRpb25zQ291bnQ7IGkrKykge1xuICAgICAgICBnZXRJbnN0YW5jZSgpLnNldFZhbHVlKGtleXNPZmZzZXQgKyBpICogZ2V0SW5zdGFuY2UoKS5QVFJfU0laRSwgZXBPcHRpb25zW2ldWzBdLCAnKicpO1xuICAgICAgICBnZXRJbnN0YW5jZSgpLnNldFZhbHVlKHZhbHVlc09mZnNldCArIGkgKiBnZXRJbnN0YW5jZSgpLlBUUl9TSVpFLCBlcE9wdGlvbnNbaV1bMV0sICcqJyk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChcbiAgICAgIChhd2FpdCBnZXRJbnN0YW5jZSgpLl9PcnRBcHBlbmRFeGVjdXRpb25Qcm92aWRlcihcbiAgICAgICAgc2Vzc2lvbk9wdGlvbnNIYW5kbGUsXG4gICAgICAgIGVwTmFtZURhdGFPZmZzZXQsXG4gICAgICAgIGtleXNPZmZzZXQsXG4gICAgICAgIHZhbHVlc09mZnNldCxcbiAgICAgICAgZXBPcHRpb25zQ291bnQsXG4gICAgICApKSAhPT0gMFxuICAgICkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoYENhbid0IGFwcGVuZCBleGVjdXRpb24gcHJvdmlkZXI6ICR7ZXBOYW1lfS5gKTtcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBzZXRTZXNzaW9uT3B0aW9ucyA9IGFzeW5jIChvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8W251bWJlciwgbnVtYmVyW11dPiA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBsZXQgc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPSAwO1xuICBjb25zdCBhbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgY29uc3Qgc2Vzc2lvbk9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICBhcHBlbmREZWZhdWx0T3B0aW9ucyhzZXNzaW9uT3B0aW9ucyk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBncmFwaE9wdGltaXphdGlvbkxldmVsID0gZ2V0R3JhcGhPcHRpbXphdGlvbkxldmVsKHNlc3Npb25PcHRpb25zLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWwgPz8gJ2FsbCcpO1xuICAgIGNvbnN0IGV4ZWN1dGlvbk1vZGUgPSBnZXRFeGVjdXRpb25Nb2RlKHNlc3Npb25PcHRpb25zLmV4ZWN1dGlvbk1vZGUgPz8gJ3NlcXVlbnRpYWwnKTtcbiAgICBjb25zdCBsb2dJZERhdGFPZmZzZXQgPVxuICAgICAgdHlwZW9mIHNlc3Npb25PcHRpb25zLmxvZ0lkID09PSAnc3RyaW5nJyA/IGFsbG9jV2FzbVN0cmluZyhzZXNzaW9uT3B0aW9ucy5sb2dJZCwgYWxsb2NzKSA6IDA7XG5cbiAgICBjb25zdCBsb2dTZXZlcml0eUxldmVsID0gc2Vzc2lvbk9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA/PyAyOyAvLyBEZWZhdWx0IHRvIDIgLSB3YXJuaW5nXG4gICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGxvZ1NldmVyaXR5TGV2ZWwpIHx8IGxvZ1NldmVyaXR5TGV2ZWwgPCAwIHx8IGxvZ1NldmVyaXR5TGV2ZWwgPiA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyBzZXZlcml0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7bG9nU2V2ZXJpdHlMZXZlbH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBsb2dWZXJib3NpdHlMZXZlbCA9IHNlc3Npb25PcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsID8/IDA7IC8vIERlZmF1bHQgdG8gMCAtIHZlcmJvc2VcbiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobG9nVmVyYm9zaXR5TGV2ZWwpIHx8IGxvZ1ZlcmJvc2l0eUxldmVsIDwgMCB8fCBsb2dWZXJib3NpdHlMZXZlbCA+IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgbG9nIHZlcmJvc2l0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7bG9nVmVyYm9zaXR5TGV2ZWx9YCk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3B0aW1pemVkTW9kZWxGaWxlUGF0aE9mZnNldCA9XG4gICAgICB0eXBlb2Ygc2Vzc2lvbk9wdGlvbnMub3B0aW1pemVkTW9kZWxGaWxlUGF0aCA9PT0gJ3N0cmluZydcbiAgICAgICAgPyBhbGxvY1dhc21TdHJpbmcoc2Vzc2lvbk9wdGlvbnMub3B0aW1pemVkTW9kZWxGaWxlUGF0aCwgYWxsb2NzKVxuICAgICAgICA6IDA7XG5cbiAgICBzZXNzaW9uT3B0aW9uc0hhbmRsZSA9IHdhc20uX09ydENyZWF0ZVNlc3Npb25PcHRpb25zKFxuICAgICAgZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCxcbiAgICAgICEhc2Vzc2lvbk9wdGlvbnMuZW5hYmxlQ3B1TWVtQXJlbmEsXG4gICAgICAhIXNlc3Npb25PcHRpb25zLmVuYWJsZU1lbVBhdHRlcm4sXG4gICAgICBleGVjdXRpb25Nb2RlLFxuICAgICAgISFzZXNzaW9uT3B0aW9ucy5lbmFibGVQcm9maWxpbmcsXG4gICAgICAwLFxuICAgICAgbG9nSWREYXRhT2Zmc2V0LFxuICAgICAgbG9nU2V2ZXJpdHlMZXZlbCxcbiAgICAgIGxvZ1ZlcmJvc2l0eUxldmVsLFxuICAgICAgb3B0aW1pemVkTW9kZWxGaWxlUGF0aE9mZnNldCxcbiAgICApO1xuICAgIGlmIChzZXNzaW9uT3B0aW9uc0hhbmRsZSA9PT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBjcmVhdGUgc2Vzc2lvbiBvcHRpb25zLlwiKTtcbiAgICB9XG5cbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnMuZXhlY3V0aW9uUHJvdmlkZXJzKSB7XG4gICAgICBhd2FpdCBzZXRFeGVjdXRpb25Qcm92aWRlcnMoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIHNlc3Npb25PcHRpb25zLCBhbGxvY3MpO1xuICAgIH1cblxuICAgIGlmIChzZXNzaW9uT3B0aW9ucy5lbmFibGVHcmFwaENhcHR1cmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHR5cGVvZiBzZXNzaW9uT3B0aW9ucy5lbmFibGVHcmFwaENhcHR1cmUgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGVuYWJsZUdyYXBoQ2FwdHVyZSBtdXN0IGJlIGEgYm9vbGVhbiB2YWx1ZTogJHtzZXNzaW9uT3B0aW9ucy5lbmFibGVHcmFwaENhcHR1cmV9YCk7XG4gICAgICB9XG4gICAgICBhcHBlbmRTZXNzaW9uQ29uZmlnKFxuICAgICAgICBzZXNzaW9uT3B0aW9uc0hhbmRsZSxcbiAgICAgICAgJ2VuYWJsZUdyYXBoQ2FwdHVyZScsXG4gICAgICAgIHNlc3Npb25PcHRpb25zLmVuYWJsZUdyYXBoQ2FwdHVyZS50b1N0cmluZygpLFxuICAgICAgICBhbGxvY3MsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChzZXNzaW9uT3B0aW9ucy5mcmVlRGltZW5zaW9uT3ZlcnJpZGVzKSB7XG4gICAgICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoc2Vzc2lvbk9wdGlvbnMuZnJlZURpbWVuc2lvbk92ZXJyaWRlcykpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBuYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgbmFtZSBtdXN0IGJlIGEgc3RyaW5nOiAke25hbWV9YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc0ludGVnZXIodmFsdWUpIHx8IHZhbHVlIDwgMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUgdmFsdWUgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyOiAke3ZhbHVlfWApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5hbWVPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcobmFtZSwgYWxsb2NzKTtcbiAgICAgICAgaWYgKHdhc20uX09ydEFkZEZyZWVEaW1lbnNpb25PdmVycmlkZShzZXNzaW9uT3B0aW9uc0hhbmRsZSwgbmFtZU9mZnNldCwgdmFsdWUpICE9PSAwKSB7XG4gICAgICAgICAgY2hlY2tMYXN0RXJyb3IoYENhbid0IHNldCBhIGZyZWUgZGltZW5zaW9uIG92ZXJyaWRlOiAke25hbWV9IC0gJHt2YWx1ZX0uYCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnMuZXh0cmEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaXRlcmF0ZUV4dHJhT3B0aW9ucyhzZXNzaW9uT3B0aW9ucy5leHRyYSwgJycsIG5ldyBXZWFrU2V0PFJlY29yZDxzdHJpbmcsIHVua25vd24+PigpLCAoa2V5LCB2YWx1ZSkgPT4ge1xuICAgICAgICBhcHBlbmRTZXNzaW9uQ29uZmlnKHNlc3Npb25PcHRpb25zSGFuZGxlLCBrZXksIHZhbHVlLCBhbGxvY3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtzZXNzaW9uT3B0aW9uc0hhbmRsZSwgYWxsb2NzXTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChzZXNzaW9uT3B0aW9uc0hhbmRsZSAhPT0gMCkge1xuICAgICAgaWYgKHdhc20uX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucyhzZXNzaW9uT3B0aW9uc0hhbmRsZSkgIT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIHNlc3Npb24gb3B0aW9ucy5cIik7XG4gICAgICB9XG4gICAgfVxuICAgIGFsbG9jcy5mb3JFYWNoKChhbGxvYykgPT4gd2FzbS5fZnJlZShhbGxvYykpO1xuICAgIHRocm93IGU7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbi8vIGEgZHVtbXkgdHlwZSBkZWNsYXJhdGlvbiBmb3IgRmxvYXQxNkFycmF5IGluIGNhc2UgYW55IHBvbHlmaWxsIGlzIGF2YWlsYWJsZS5cbmRlY2xhcmUgZ2xvYmFsIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvbiwgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBjb25zdCBGbG9hdDE2QXJyYXk6IGFueTtcbn1cblxuLy8gVGhpcyBmaWxlIGluY2x1ZGVzIGNvbW1vbiBkZWZpbml0aW9ucy4gVGhleSBkbyBOT1QgaGF2ZSBkZXBlbmRlbmN5IG9uIHRoZSBXZWJBc3NlbWJseSBpbnN0YW5jZS5cblxuLyoqXG4gKiBDb3BpZWQgZnJvbSBPTk5YIGRlZmluaXRpb24uIFVzZSB0aGlzIHRvIGRyb3AgZGVwZW5kZW5jeSAnb25ueF9wcm90bycgdG8gZGVjcmVhc2UgY29tcGlsZWQgLmpzIGZpbGUgc2l6ZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGVudW0gRGF0YVR5cGUge1xuICB1bmRlZmluZWQgPSAwLFxuICBmbG9hdCA9IDEsXG4gIHVpbnQ4ID0gMixcbiAgaW50OCA9IDMsXG4gIHVpbnQxNiA9IDQsXG4gIGludDE2ID0gNSxcbiAgaW50MzIgPSA2LFxuICBpbnQ2NCA9IDcsXG4gIHN0cmluZyA9IDgsXG4gIGJvb2wgPSA5LFxuICBmbG9hdDE2ID0gMTAsXG4gIGRvdWJsZSA9IDExLFxuICB1aW50MzIgPSAxMixcbiAgdWludDY0ID0gMTMsXG4gIGNvbXBsZXg2NCA9IDE0LFxuICBjb21wbGV4MTI4ID0gMTUsXG4gIGJmbG9hdDE2ID0gMTYsXG5cbiAgLy8gNC1iaXQgZGF0YS10eXBlc1xuICB1aW50NCA9IDIxLFxuICBpbnQ0ID0gMjIsXG59XG5cbi8qKlxuICogTWFwIHN0cmluZyB0ZW5zb3IgZGF0YSB0byBlbnVtIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JEYXRhVHlwZVN0cmluZ1RvRW51bSA9ICh0eXBlOiBzdHJpbmcpOiBEYXRhVHlwZSA9PiB7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ2ludDgnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmludDg7XG4gICAgY2FzZSAndWludDgnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnVpbnQ4O1xuICAgIGNhc2UgJ2Jvb2wnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmJvb2w7XG4gICAgY2FzZSAnaW50MTYnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmludDE2O1xuICAgIGNhc2UgJ3VpbnQxNic6XG4gICAgICByZXR1cm4gRGF0YVR5cGUudWludDE2O1xuICAgIGNhc2UgJ2ludDMyJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5pbnQzMjtcbiAgICBjYXNlICd1aW50MzInOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnVpbnQzMjtcbiAgICBjYXNlICdmbG9hdDE2JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5mbG9hdDE2O1xuICAgIGNhc2UgJ2Zsb2F0MzInOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmZsb2F0O1xuICAgIGNhc2UgJ2Zsb2F0NjQnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmRvdWJsZTtcbiAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnN0cmluZztcbiAgICBjYXNlICdpbnQ2NCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuaW50NjQ7XG4gICAgY2FzZSAndWludDY0JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS51aW50NjQ7XG4gICAgY2FzZSAnaW50NCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuaW50NDtcbiAgICBjYXNlICd1aW50NCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUudWludDQ7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dHlwZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBNYXAgZW51bSB2YWx1ZSB0byBzdHJpbmcgdGVuc29yIGRhdGFcbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nID0gKHR5cGVQcm90bzogRGF0YVR5cGUpOiBUZW5zb3IuVHlwZSA9PiB7XG4gIHN3aXRjaCAodHlwZVByb3RvKSB7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQ4OlxuICAgICAgcmV0dXJuICdpbnQ4JztcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQ4OlxuICAgICAgcmV0dXJuICd1aW50OCc7XG4gICAgY2FzZSBEYXRhVHlwZS5ib29sOlxuICAgICAgcmV0dXJuICdib29sJztcbiAgICBjYXNlIERhdGFUeXBlLmludDE2OlxuICAgICAgcmV0dXJuICdpbnQxNic7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50MTY6XG4gICAgICByZXR1cm4gJ3VpbnQxNic7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQzMjpcbiAgICAgIHJldHVybiAnaW50MzInO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDMyOlxuICAgICAgcmV0dXJuICd1aW50MzInO1xuICAgIGNhc2UgRGF0YVR5cGUuZmxvYXQxNjpcbiAgICAgIHJldHVybiAnZmxvYXQxNic7XG4gICAgY2FzZSBEYXRhVHlwZS5mbG9hdDpcbiAgICAgIHJldHVybiAnZmxvYXQzMic7XG4gICAgY2FzZSBEYXRhVHlwZS5kb3VibGU6XG4gICAgICByZXR1cm4gJ2Zsb2F0NjQnO1xuICAgIGNhc2UgRGF0YVR5cGUuc3RyaW5nOlxuICAgICAgcmV0dXJuICdzdHJpbmcnO1xuICAgIGNhc2UgRGF0YVR5cGUuaW50NjQ6XG4gICAgICByZXR1cm4gJ2ludDY0JztcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQ2NDpcbiAgICAgIHJldHVybiAndWludDY0JztcbiAgICBjYXNlIERhdGFUeXBlLmludDQ6XG4gICAgICByZXR1cm4gJ2ludDQnO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDQ6XG4gICAgICByZXR1cm4gJ3VpbnQ0JztcblxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHt0eXBlUHJvdG99YCk7XG4gIH1cbn07XG5cbi8qKlxuICogZ2V0IHRlbnNvciBzaXplIGluIGJ5dGVzIGJ5IHRoZSBnaXZlbiBkYXRhIHR5cGUgYW5kIGRpbWVuc2lvbnNcbiAqIEByZXR1cm5zIHNpemUgaW4gaW50ZWdlciBvciB1bmRlZmluZWQgaWYgdGhlIGRhdGEgdHlwZSBpcyBub3Qgc3VwcG9ydGVkXG4gKi9cbmV4cG9ydCBjb25zdCBjYWxjdWxhdGVUZW5zb3JTaXplSW5CeXRlcyA9IChcbiAgZGF0ZVR5cGU6IG51bWJlcixcbiAgZGltc09yU2l6ZTogcmVhZG9ubHkgbnVtYmVyW10gfCBudW1iZXIsXG4pOiBudW1iZXIgfCB1bmRlZmluZWQgPT4ge1xuICBjb25zdCBlbGVtZW50U2l6ZSA9IFtcbiAgICAtMSwgLy8gdW5kZWZpbmVkID0gMFxuICAgIDQsIC8vIGZsb2F0ID0gMVxuICAgIDEsIC8vIHVpbnQ4ID0gMlxuICAgIDEsIC8vIGludDggPSAzXG4gICAgMiwgLy8gdWludDE2ID0gNFxuICAgIDIsIC8vIGludDE2ID0gNVxuICAgIDQsIC8vIGludDMyID0gNlxuICAgIDgsIC8vIGludDY0ID0gN1xuICAgIC0xLCAvLyBzdHJpbmcgPSA4XG4gICAgMSwgLy8gYm9vbCA9IDlcbiAgICAyLCAvLyBmbG9hdDE2ID0gMTBcbiAgICA4LCAvLyBkb3VibGUgPSAxMVxuICAgIDQsIC8vIHVpbnQzMiA9IDEyXG4gICAgOCwgLy8gdWludDY0ID0gMTNcbiAgICAtMSwgLy8gY29tcGxleDY0ID0gMTRcbiAgICAtMSwgLy8gY29tcGxleDEyOCA9IDE1XG4gICAgLTEsIC8vIGJmbG9hdDE2ID0gMTZcbiAgICAtMSwgLy8gRkxPQVQ4RTRNM0ZOID0gMTdcbiAgICAtMSwgLy8gRkxPQVQ4RTRNM0ZOVVogPSAxOFxuICAgIC0xLCAvLyBGTE9BVDhFNU0yID0gMTlcbiAgICAtMSwgLy8gRkxPQVQ4RTVNMkZOVVogPSAyMFxuICAgIDAuNSwgLy8gdWludDQgPSAyMVxuICAgIDAuNSwgLy8gaW50NCA9IDIyXG4gIF1bZGF0ZVR5cGVdO1xuXG4gIGNvbnN0IHNpemUgPSB0eXBlb2YgZGltc09yU2l6ZSA9PT0gJ251bWJlcicgPyBkaW1zT3JTaXplIDogZGltc09yU2l6ZS5yZWR1Y2UoKGEsIGIpID0+IGEgKiBiLCAxKTtcbiAgcmV0dXJuIGVsZW1lbnRTaXplID4gMCA/IE1hdGguY2VpbChzaXplICogZWxlbWVudFNpemUpIDogdW5kZWZpbmVkO1xufTtcblxuLyoqXG4gKiBnZXQgdHlwZWQgYXJyYXkgY29uc3RydWN0b3IgYnkgdGhlIGdpdmVuIHRlbnNvciB0eXBlXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JUeXBlVG9UeXBlZEFycmF5Q29uc3RydWN0b3IgPSAoXG4gIHR5cGU6IFRlbnNvci5UeXBlLFxuKTpcbiAgfCBGbG9hdDMyQXJyYXlDb25zdHJ1Y3RvclxuICB8IFVpbnQ4QXJyYXlDb25zdHJ1Y3RvclxuICB8IEludDhBcnJheUNvbnN0cnVjdG9yXG4gIHwgVWludDE2QXJyYXlDb25zdHJ1Y3RvclxuICB8IEludDE2QXJyYXlDb25zdHJ1Y3RvclxuICB8IEludDMyQXJyYXlDb25zdHJ1Y3RvclxuICB8IEJpZ0ludDY0QXJyYXlDb25zdHJ1Y3RvclxuICB8IFVpbnQ4QXJyYXlDb25zdHJ1Y3RvclxuICB8IEZsb2F0NjRBcnJheUNvbnN0cnVjdG9yXG4gIHwgVWludDMyQXJyYXlDb25zdHJ1Y3RvclxuICB8IEJpZ1VpbnQ2NEFycmF5Q29uc3RydWN0b3IgPT4ge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdmbG9hdDE2JzpcbiAgICAgIC8vIGFsbG93IEZsb2F0MTZBcnJheSBwb2x5ZmlsbC5cbiAgICAgIHJldHVybiB0eXBlb2YgRmxvYXQxNkFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiBGbG9hdDE2QXJyYXkuZnJvbSA/IEZsb2F0MTZBcnJheSA6IFVpbnQxNkFycmF5O1xuICAgIGNhc2UgJ2Zsb2F0MzInOlxuICAgICAgcmV0dXJuIEZsb2F0MzJBcnJheTtcbiAgICBjYXNlICd1aW50OCc6XG4gICAgICByZXR1cm4gVWludDhBcnJheTtcbiAgICBjYXNlICdpbnQ4JzpcbiAgICAgIHJldHVybiBJbnQ4QXJyYXk7XG4gICAgY2FzZSAndWludDE2JzpcbiAgICAgIHJldHVybiBVaW50MTZBcnJheTtcbiAgICBjYXNlICdpbnQxNic6XG4gICAgICByZXR1cm4gSW50MTZBcnJheTtcbiAgICBjYXNlICdpbnQzMic6XG4gICAgICByZXR1cm4gSW50MzJBcnJheTtcbiAgICBjYXNlICdib29sJzpcbiAgICAgIHJldHVybiBVaW50OEFycmF5O1xuICAgIGNhc2UgJ2Zsb2F0NjQnOlxuICAgICAgcmV0dXJuIEZsb2F0NjRBcnJheTtcbiAgICBjYXNlICd1aW50MzInOlxuICAgICAgcmV0dXJuIFVpbnQzMkFycmF5O1xuICAgIGNhc2UgJ2ludDY0JzpcbiAgICAgIHJldHVybiBCaWdJbnQ2NEFycmF5O1xuICAgIGNhc2UgJ3VpbnQ2NCc6XG4gICAgICByZXR1cm4gQmlnVWludDY0QXJyYXk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZTogJHt0eXBlfWApO1xuICB9XG59O1xuXG4vKipcbiAqIE1hcCBzdHJpbmcgbG9nIGxldmVsIHRvIGludGVnZXIgdmFsdWVcbiAqL1xuZXhwb3J0IGNvbnN0IGxvZ0xldmVsU3RyaW5nVG9FbnVtID0gKGxvZ0xldmVsPzogJ3ZlcmJvc2UnIHwgJ2luZm8nIHwgJ3dhcm5pbmcnIHwgJ2Vycm9yJyB8ICdmYXRhbCcpOiBudW1iZXIgPT4ge1xuICBzd2l0Y2ggKGxvZ0xldmVsKSB7XG4gICAgY2FzZSAndmVyYm9zZSc6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlICdpbmZvJzpcbiAgICAgIHJldHVybiAxO1xuICAgIGNhc2UgJ3dhcm5pbmcnOlxuICAgICAgcmV0dXJuIDI7XG4gICAgY2FzZSAnZXJyb3InOlxuICAgICAgcmV0dXJuIDM7XG4gICAgY2FzZSAnZmF0YWwnOlxuICAgICAgcmV0dXJuIDQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgbG9nZ2luZyBsZXZlbDogJHtsb2dMZXZlbH1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBDaGVjayB3aGV0aGVyIHRoZSBnaXZlbiB0ZW5zb3IgdHlwZSBpcyBzdXBwb3J0ZWQgYnkgR1BVIGJ1ZmZlclxuICovXG5leHBvcnQgY29uc3QgaXNHcHVCdWZmZXJTdXBwb3J0ZWRUeXBlID0gKHR5cGU6IFRlbnNvci5UeXBlKTogdHlwZSBpcyBUZW5zb3IuR3B1QnVmZmVyRGF0YVR5cGVzID0+XG4gIHR5cGUgPT09ICdmbG9hdDMyJyB8fFxuICB0eXBlID09PSAnZmxvYXQxNicgfHxcbiAgdHlwZSA9PT0gJ2ludDMyJyB8fFxuICB0eXBlID09PSAnaW50NjQnIHx8XG4gIHR5cGUgPT09ICd1aW50MzInIHx8XG4gIHR5cGUgPT09ICd1aW50OCcgfHxcbiAgdHlwZSA9PT0gJ2Jvb2wnIHx8XG4gIHR5cGUgPT09ICd1aW50NCcgfHxcbiAgdHlwZSA9PT0gJ2ludDQnO1xuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIHRlbnNvciB0eXBlIGlzIHN1cHBvcnRlZCBieSBXZWJOTiBNTFRlbnNvclxuICovXG5leHBvcnQgY29uc3QgaXNNTFRlbnNvclN1cHBvcnRlZFR5cGUgPSAodHlwZTogVGVuc29yLlR5cGUpOiB0eXBlIGlzIFRlbnNvci5NTFRlbnNvckRhdGFUeXBlcyA9PlxuICB0eXBlID09PSAnZmxvYXQzMicgfHxcbiAgdHlwZSA9PT0gJ2Zsb2F0MTYnIHx8XG4gIHR5cGUgPT09ICdpbnQzMicgfHxcbiAgdHlwZSA9PT0gJ2ludDY0JyB8fFxuICB0eXBlID09PSAndWludDMyJyB8fFxuICB0eXBlID09PSAndWludDY0JyB8fFxuICB0eXBlID09PSAnaW50OCcgfHxcbiAgdHlwZSA9PT0gJ3VpbnQ4JyB8fFxuICB0eXBlID09PSAnYm9vbCcgfHxcbiAgdHlwZSA9PT0gJ3VpbnQ0JyB8fFxuICB0eXBlID09PSAnaW50NCc7XG5cbi8qKlxuICogTWFwIHN0cmluZyBkYXRhIGxvY2F0aW9uIHRvIGludGVnZXIgdmFsdWVcbiAqL1xuZXhwb3J0IGNvbnN0IGRhdGFMb2NhdGlvblN0cmluZ1RvRW51bSA9IChsb2NhdGlvbjogVGVuc29yLkRhdGFMb2NhdGlvbik6IG51bWJlciA9PiB7XG4gIHN3aXRjaCAobG9jYXRpb24pIHtcbiAgICBjYXNlICdub25lJzpcbiAgICAgIHJldHVybiAwO1xuICAgIGNhc2UgJ2NwdSc6XG4gICAgICByZXR1cm4gMTtcbiAgICBjYXNlICdjcHUtcGlubmVkJzpcbiAgICAgIHJldHVybiAyO1xuICAgIGNhc2UgJ3RleHR1cmUnOlxuICAgICAgcmV0dXJuIDM7XG4gICAgY2FzZSAnZ3B1LWJ1ZmZlcic6XG4gICAgICByZXR1cm4gNDtcbiAgICBjYXNlICdtbC10ZW5zb3InOlxuICAgICAgcmV0dXJuIDU7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSBsb2NhdGlvbjogJHtsb2NhdGlvbn1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBNYXAgaW50ZWdlciBkYXRhIGxvY2F0aW9uIHRvIHN0cmluZyB2YWx1ZVxuICovXG5leHBvcnQgY29uc3QgZGF0YUxvY2F0aW9uRW51bVRvU3RyaW5nID0gKGxvY2F0aW9uOiBudW1iZXIpOiBUZW5zb3IuRGF0YUxvY2F0aW9uIHwgdW5kZWZpbmVkID0+XG4gIChbJ25vbmUnLCAnY3B1JywgJ2NwdS1waW5uZWQnLCAndGV4dHVyZScsICdncHUtYnVmZmVyJywgJ21sLXRlbnNvciddIGFzIGNvbnN0KVtsb2NhdGlvbl07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGlzTm9kZSB9IGZyb20gJy4vd2FzbS11dGlscy1lbnYnO1xuXG4vKipcbiAqIExvYWQgYSBmaWxlIGludG8gYSBVaW50OEFycmF5LlxuICpcbiAqIEBwYXJhbSBmaWxlIC0gdGhlIGZpbGUgdG8gbG9hZC4gQ2FuIGJlIGEgVVJML3BhdGgsIGEgQmxvYiwgYW4gQXJyYXlCdWZmZXIsIG9yIGEgVWludDhBcnJheS5cbiAqIEByZXR1cm5zIGEgVWludDhBcnJheSBjb250YWluaW5nIHRoZSBmaWxlIGRhdGEuXG4gKi9cbmV4cG9ydCBjb25zdCBsb2FkRmlsZSA9IGFzeW5jIChmaWxlOiBzdHJpbmcgfCBCbG9iIHwgQXJyYXlCdWZmZXJMaWtlIHwgVWludDhBcnJheSk6IFByb21pc2U8VWludDhBcnJheT4gPT4ge1xuICBpZiAodHlwZW9mIGZpbGUgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKGlzTm9kZSkge1xuICAgICAgLy8gbG9hZCBmaWxlIGludG8gQXJyYXlCdWZmZXIgaW4gTm9kZS5qc1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgeyByZWFkRmlsZSB9ID0gcmVxdWlyZSgnbm9kZTpmcy9wcm9taXNlcycpO1xuICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYXdhaXQgcmVhZEZpbGUoZmlsZSkpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZS5jb2RlID09PSAnRVJSX0ZTX0ZJTEVfVE9PX0xBUkdFJykge1xuICAgICAgICAgIC8vIGZpbGUgaXMgdG9vIGxhcmdlLCB1c2UgZnMuY3JlYXRlUmVhZFN0cmVhbSBpbnN0ZWFkXG4gICAgICAgICAgY29uc3QgeyBjcmVhdGVSZWFkU3RyZWFtIH0gPSByZXF1aXJlKCdub2RlOmZzJyk7XG4gICAgICAgICAgY29uc3Qgc3RyZWFtID0gY3JlYXRlUmVhZFN0cmVhbShmaWxlKTtcbiAgICAgICAgICBjb25zdCBjaHVua3M6IFVpbnQ4QXJyYXlbXSA9IFtdO1xuICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgY2h1bmsgb2Ygc3RyZWFtKSB7XG4gICAgICAgICAgICBjaHVua3MucHVzaChjaHVuayk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShCdWZmZXIuY29uY2F0KGNodW5rcykpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGxvYWQgZmlsZSBpbnRvIEFycmF5QnVmZmVyIGluIGJyb3dzZXJzXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGZpbGUpO1xuICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGZhaWxlZCB0byBsb2FkIGV4dGVybmFsIGRhdGEgZmlsZTogJHtmaWxlfWApO1xuICAgICAgfVxuICAgICAgY29uc3QgY29udGVudExlbmd0aEhlYWRlciA9IHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdDb250ZW50LUxlbmd0aCcpO1xuICAgICAgY29uc3QgZmlsZVNpemUgPSBjb250ZW50TGVuZ3RoSGVhZGVyID8gcGFyc2VJbnQoY29udGVudExlbmd0aEhlYWRlciwgMTApIDogMDtcbiAgICAgIGlmIChmaWxlU2l6ZSA8IDEwNzM3NDE4MjQgLyogMUdCICovKSB7XG4gICAgICAgIC8vIHdoZW4gQ29udGVudC1MZW5ndGggaGVhZGVyIGlzIG5vdCBzZXQsIHdlIGNhbm5vdCBkZXRlcm1pbmUgdGhlIGZpbGUgc2l6ZS4gV2UgYXNzdW1lIGl0IGlzIHNtYWxsIGVub3VnaCB0b1xuICAgICAgICAvLyBsb2FkIGludG8gbWVtb3J5LlxuICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYXdhaXQgcmVzcG9uc2UuYXJyYXlCdWZmZXIoKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBmaWxlIGlzIHRvbyBsYXJnZSwgdXNlIHN0cmVhbSBpbnN0ZWFkXG4gICAgICAgIGlmICghcmVzcG9uc2UuYm9keSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIGxvYWQgZXh0ZXJuYWwgZGF0YSBmaWxlOiAke2ZpbGV9LCBubyByZXNwb25zZSBib2R5LmApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJlYWRlciA9IHJlc3BvbnNlLmJvZHkuZ2V0UmVhZGVyKCk7XG5cbiAgICAgICAgbGV0IGJ1ZmZlcjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyB0cnkgdG8gY3JlYXRlIEFycmF5QnVmZmVyIGRpcmVjdGx5XG4gICAgICAgICAgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKGZpbGVTaXplKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgUmFuZ2VFcnJvcikge1xuICAgICAgICAgICAgLy8gdXNlIFdlYkFzc2VtYmx5IE1lbW9yeSB0byBhbGxvY2F0ZSBsYXJnZXIgQXJyYXlCdWZmZXJcbiAgICAgICAgICAgIGNvbnN0IHBhZ2VzID0gTWF0aC5jZWlsKGZpbGVTaXplIC8gNjU1MzYpO1xuICAgICAgICAgICAgYnVmZmVyID0gbmV3IFdlYkFzc2VtYmx5Lk1lbW9yeSh7IGluaXRpYWw6IHBhZ2VzLCBtYXhpbXVtOiBwYWdlcyB9KS5idWZmZXI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG9mZnNldCA9IDA7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgY29uc3QgeyBkb25lLCB2YWx1ZSB9ID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICAgICAgICBpZiAoZG9uZSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IHZhbHVlLmJ5dGVMZW5ndGg7XG4gICAgICAgICAgY29uc3QgY2h1bmsgPSBuZXcgVWludDhBcnJheShidWZmZXIsIG9mZnNldCwgY2h1bmtTaXplKTtcbiAgICAgICAgICBjaHVuay5zZXQodmFsdWUpO1xuICAgICAgICAgIG9mZnNldCArPSBjaHVua1NpemU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGJ1ZmZlciwgMCwgZmlsZVNpemUpO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmIChmaWxlIGluc3RhbmNlb2YgQmxvYikge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCBmaWxlLmFycmF5QnVmZmVyKCkpO1xuICB9IGVsc2UgaWYgKGZpbGUgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgcmV0dXJuIGZpbGU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGZpbGUpO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBFbnYgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBsb2dMZXZlbFN0cmluZ1RvRW51bSB9IGZyb20gJy4uL3dhc20tY29tbW9uJztcblxudHlwZSBMb2dMZXZlbCA9IE5vbk51bGxhYmxlPEVudlsnbG9nTGV2ZWwnXT47XG50eXBlIE1lc3NhZ2VTdHJpbmcgPSBzdHJpbmc7XG50eXBlIE1lc3NhZ2VGdW5jdGlvbiA9ICgpID0+IHN0cmluZztcbnR5cGUgTWVzc2FnZSA9IE1lc3NhZ2VTdHJpbmcgfCBNZXNzYWdlRnVuY3Rpb247XG5cbmNvbnN0IGxvZ0xldmVsUHJlZml4ID0gWydWJywgJ0knLCAnVycsICdFJywgJ0YnXTtcblxuY29uc3QgZG9Mb2cgPSAobGV2ZWw6IG51bWJlciwgbWVzc2FnZTogc3RyaW5nKTogdm9pZCA9PiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGBbJHtsb2dMZXZlbFByZWZpeFtsZXZlbF19LCR7bmV3IERhdGUoKS50b0lTT1N0cmluZygpfV0ke21lc3NhZ2V9YCk7XG59O1xuXG5sZXQgY29uZmlnTG9nTGV2ZWw6IExvZ0xldmVsIHwgdW5kZWZpbmVkO1xubGV0IGRlYnVnOiBib29sZWFuIHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgY29uc3QgY29uZmlndXJlTG9nZ2VyID0gKCRjb25maWdMb2dMZXZlbDogTG9nTGV2ZWwsICRkZWJ1ZzogYm9vbGVhbik6IHZvaWQgPT4ge1xuICBjb25maWdMb2dMZXZlbCA9ICRjb25maWdMb2dMZXZlbDtcbiAgZGVidWcgPSAkZGVidWc7XG59O1xuXG4vKipcbiAqIEEgc2ltcGxlIGxvZ2dpbmcgdXRpbGl0eSB0byBsb2cgbWVzc2FnZXMgdG8gdGhlIGNvbnNvbGUuXG4gKi9cbmV4cG9ydCBjb25zdCBMT0cgPSAobG9nTGV2ZWw6IExvZ0xldmVsLCBtc2c6IE1lc3NhZ2UpOiB2b2lkID0+IHtcbiAgY29uc3QgbWVzc2FnZUxldmVsID0gbG9nTGV2ZWxTdHJpbmdUb0VudW0obG9nTGV2ZWwpO1xuICBjb25zdCBjb25maWdMZXZlbCA9IGxvZ0xldmVsU3RyaW5nVG9FbnVtKGNvbmZpZ0xvZ0xldmVsKTtcbiAgaWYgKG1lc3NhZ2VMZXZlbCA+PSBjb25maWdMZXZlbCkge1xuICAgIGRvTG9nKG1lc3NhZ2VMZXZlbCwgdHlwZW9mIG1zZyA9PT0gJ2Z1bmN0aW9uJyA/IG1zZygpIDogbXNnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBBIHNpbXBsZSBsb2dnaW5nIHV0aWxpdHkgdG8gbG9nIG1lc3NhZ2VzIHRvIHRoZSBjb25zb2xlLiBPbmx5IGxvZ3Mgd2hlbiBkZWJ1ZyBpcyBlbmFibGVkLlxuICovXG5leHBvcnQgY29uc3QgTE9HX0RFQlVHOiB0eXBlb2YgTE9HID0gKC4uLmFyZ3M6IFBhcmFtZXRlcnM8dHlwZW9mIExPRz4pID0+IHtcbiAgaWYgKGRlYnVnKSB7XG4gICAgTE9HKC4uLmFyZ3MpO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wYXJhbS1yZWFzc2lnbiAqL1xuXG5leHBvcnQgY2xhc3MgTWF0TXVsVXRpbCB7XG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIGV4cGVjdGVkIHNoYXBlIHdoZW4gbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAqIEBwYXJhbSBhIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQS4gU2hvdWxkIGJlIGEgdHVwbGUgb2YgMiBwb3NpdGl2ZSBpbnRlZ2Vyc1xuICAgKiBAcGFyYW0gYiBUaGUgc2hhcGUgb2YgdGVuc29yIEIuIFNob3VsZCBiZSBhIHR1cGxlIG9mIDIgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHJldHVybnMgVGhlIGV4cGVjdGVkIHNoYXBlIG9mIHRoZSByZXN1bHQsIG9yIHVuZGVmaW5lZCBpZiBOL0FcbiAgICovXG4gIHN0YXRpYyBjYWxjTWF0TXVsU2hhcGUoYTogW251bWJlciwgbnVtYmVyXSwgYjogW251bWJlciwgbnVtYmVyXSk6IFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBhWzFdICE9PSBiWzBdID8gdW5kZWZpbmVkIDogW2FbMF0sIGJbMV1dO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBCcm9hZGNhc3RVdGlsIHtcbiAgLyoqXG4gICAqIENhbGN1bGF0ZSB0aGUgZXhwZWN0ZWQgc2hhcGUgd2hlbiBicm9hZGNhc3RpbmcgMiB0ZW5zb3JzXG4gICAqIEBwYXJhbSBhIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQS4gU2hvdWxkIGJlIGFuIGFycmF5IG9mIHBvc2l0aXZlIGludGVnZXJzXG4gICAqIEBwYXJhbSBiIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQi4gU2hvdWxkIGJlIGFuIGFycmF5IG9mIHBvc2l0aXZlIGludGVnZXJzXG4gICAqIEBwYXJhbSBpc01hdE11bCBXaGV0aGVyIHRoZSBvcGVyYXRpb24gaXMgTWF0TXVsXG4gICAqIEByZXR1cm5zIFRoZSBleHBlY3RlZCBzaGFwZSBvZiB0aGUgcmVzdWx0LCBvciB1bmRlZmluZWQgaWYgTi9BXG4gICAqL1xuICBzdGF0aWMgY2FsY1NoYXBlKFxuICAgIGFkaW1zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBiZGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgaXNNYXRNdWwgPSBmYWxzZSxcbiAgKTogcmVhZG9ubHkgbnVtYmVyW10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGFyYW5rID0gYWRpbXMubGVuZ3RoO1xuICAgIGNvbnN0IGJyYW5rID0gYmRpbXMubGVuZ3RoO1xuICAgIGlmIChhcmFuayA9PT0gMCkge1xuICAgICAgcmV0dXJuIGJkaW1zO1xuICAgIH1cbiAgICBpZiAoYnJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBhZGltcztcbiAgICB9XG4gICAgY29uc3QgY3JhbmsgPSBNYXRoLm1heChhZGltcy5sZW5ndGgsIGJkaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgY2RpbXMgPSBuZXcgQXJyYXk8bnVtYmVyPihjcmFuayk7XG5cbiAgICAvLyBjYWxjdWxhdGUgdGhlIGxhc3QgMiBkaW1lbnNpb24gaWYgaXQgaXMgTWF0TXVsXG4gICAgaWYgKGlzTWF0TXVsKSB7XG4gICAgICBpZiAoYXJhbmsgPCAyIHx8IGJyYW5rIDwgMikge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgY29uc3QgY1NoYXBlTWF0TXVsID0gTWF0TXVsVXRpbC5jYWxjTWF0TXVsU2hhcGUoXG4gICAgICAgIFthZGltc1thcmFuayAtIDJdLCBhZGltc1thcmFuayAtIDFdXSxcbiAgICAgICAgW2JkaW1zW2JyYW5rIC0gMl0sIGJkaW1zW2JyYW5rIC0gMV1dLFxuICAgICAgKTtcbiAgICAgIGlmIChjU2hhcGVNYXRNdWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgW2NkaW1zW2NyYW5rIC0gMl0sIGNkaW1zW2NyYW5rIC0gMV1dID0gY1NoYXBlTWF0TXVsO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSBpc01hdE11bCA/IDMgOiAxOyBpIDw9IGNyYW5rOyBpKyspIHtcbiAgICAgIGNvbnN0IGFMZW4gPSBhcmFuayAtIGkgPCAwID8gMSA6IGFkaW1zW2FyYW5rIC0gaV07XG4gICAgICBjb25zdCBiTGVuID0gYnJhbmsgLSBpIDwgMCA/IDEgOiBiZGltc1ticmFuayAtIGldO1xuXG4gICAgICBpZiAoYUxlbiAhPT0gYkxlbiAmJiBhTGVuID4gMSAmJiBiTGVuID4gMSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgY29uc3QgbWF4ID0gTWF0aC5tYXgoYUxlbiwgYkxlbik7XG4gICAgICBpZiAoYUxlbiAmJiBiTGVuKSB7XG4gICAgICAgIGNkaW1zW2NyYW5rIC0gaV0gPSBNYXRoLm1heChhTGVuLCBiTGVuKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHdoZW4gZWl0aGVyIGFMZW4gb3IgYkxlbiBpcyAwLCB0aGUgb3RoZXIgc2hvdWxkIGJlIGVpdGhlciAwIG9yIDEsIG90aGVyd2lzZSBpdCBpcyBub3QgYnJvYWRjYXN0YWJsZS5cbiAgICAgICAgaWYgKG1heCA+IDEpIHtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGNkaW1zW2NyYW5rIC0gaV0gPSAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjZGltcztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmUgaWYgYSBzaGFwZSBpcyB1bmlkaXJlY3Rpb25hbCBicm9hZGNhc3RhYmxlIHRvIGFub3RoZXIgc2hhcGVcbiAgICogQHBhcmFtIHNoYXBlIFRoZSBpbnB1dCBzaGFwZVxuICAgKiBAcGFyYW0gZmluYWxTaGFwZSBUaGUgZGVzaXJlZCBzaGFwZSBhZnRlciBicm9hZGNhc3RpbmdcbiAgICovXG4gIHN0YXRpYyBpc1ZhbGlkQnJvYWRjYXN0KHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgZmluYWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOiBib29sZWFuIHtcbiAgICAvLyBhbGlnbiBzaGFwZSB0byB0aGUgcmlnaHRcbiAgICBjb25zdCBpbnB1dFJhbmsgPSBzaGFwZS5sZW5ndGg7XG4gICAgY29uc3QgZmluYWxSYW5rID0gZmluYWxTaGFwZS5sZW5ndGg7XG4gICAgaWYgKGlucHV0UmFuayA+IGZpbmFsUmFuaykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gMTsgaSA8PSBpbnB1dFJhbms7IGkrKykge1xuICAgICAgaWYgKHNoYXBlW2lucHV0UmFuayAtIGldICE9PSAxICYmIHNoYXBlW2lucHV0UmFuayAtIGldICE9PSBmaW5hbFNoYXBlW2ZpbmFsUmFuayAtIGldKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFNoYXBlVXRpbCB7XG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIHNpemUgKG51bWJlciBvZiBlbGVtZW50cylcbiAgICovXG4gIHN0YXRpYyBzaXplKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICByZXR1cm4gU2hhcGVVdGlsLmdldFNpemVGcm9tRGltZW5zaW9uUmFuZ2UoZGltcywgMCwgZGltcy5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIGNvbnZlcnQgZGltcyBjb3JyZXNwb25kaW5nIHRvIHR5cGUgY2hhbmdlIHRvIHBhY2suIGV4LiB1aW50OCBkYXRhIHRvIHVpbnQzMlxuICAgKi9cbiAgc3RhdGljIGNvbnZlcnRTaGFwZShkaW1zOiByZWFkb25seSBudW1iZXJbXSwgc2l6ZSA9IDQpOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgY29uc3QgcmFuayA9IGRpbXMubGVuZ3RoO1xuICAgIGlmIChyYW5rID09PSAwKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGNvbnN0IG5ld0RpbXMgPSBuZXcgQXJyYXkocmFuayk7XG4gICAgbGV0IGkgPSByYW5rIC0gMTtcbiAgICB3aGlsZSAoaSA+PSAwKSB7XG4gICAgICBpZiAoZGltc1tpXSAlIHNpemUgPT09IDApIHtcbiAgICAgICAgbmV3RGltc1tpXSA9IGRpbXNbaV0gLyBzaXplO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGlmIChzaXplICUgZGltc1tpXSAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBjb252ZXJ0IHNoYXBlJyk7XG4gICAgICB9XG4gICAgICBuZXdEaW1zW2ldID0gMTtcbiAgICAgIHNpemUgLz0gZGltc1tpXTtcbiAgICAgIGktLTtcbiAgICB9XG4gICAgZm9yIChpLS07IGkgPj0gMDsgaS0tKSB7XG4gICAgICBuZXdEaW1zW2ldID0gZGltc1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld0RpbXM7XG4gIH1cblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBzaXplIChudW1iZXIgb2YgZWxlbWVudHMpIGZyb20gdGhlIGdpdmVuIGF4aXMgKGluY2x1c2l2ZSlcbiAgICovXG4gIHN0YXRpYyBzaXplRnJvbURpbWVuc2lvbihkaW1zOiByZWFkb25seSBudW1iZXJbXSwgYXhpczogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoYXhpcyA8IDAgfHwgYXhpcyA+IGRpbXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGltZW5zaW9uIG9mICR7YXhpc30gZm9yIHNpemVGcm9tRGltZW5zaW9uIGFzIFRlbnNvciBoYXMgJHtkaW1zLmxlbmd0aH0gZGltZW5zaW9ucy5gKTtcbiAgICB9XG4gICAgcmV0dXJuIFNoYXBlVXRpbC5nZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXMsIGF4aXMsIGRpbXMubGVuZ3RoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIHNpemUgKG51bWJlciBvZiBlbGVtZW50cykgdG8gdGhlIGdpdmVuIGF4aXMgKGV4Y2x1c2l2ZSlcbiAgICovXG4gIHN0YXRpYyBzaXplVG9EaW1lbnNpb24oZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGF4aXM6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKGF4aXMgPCAwIHx8IGF4aXMgPiBkaW1zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGRpbWVuc2lvbiBvZiAke2F4aXN9IGZvciBzaXplVG9EaW1lbnNpb24gYXMgVGVuc29yIGhhcyAke2RpbXMubGVuZ3RofSBkaW1lbnNpb25zLmApO1xuICAgIH1cbiAgICByZXR1cm4gU2hhcGVVdGlsLmdldFNpemVGcm9tRGltZW5zaW9uUmFuZ2UoZGltcywgMCwgYXhpcyk7XG4gIH1cblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBzaXplIChudW1iZXIgb2YgZWxlbWVudHMpIGZyb20gYW5kIHRvIHRoZSBnaXZlbiBheGlzIFtzdGFydCwgZW5kKVxuICAgKi9cbiAgc3RhdGljIGdldFNpemVGcm9tRGltZW5zaW9uUmFuZ2UoZGltczogcmVhZG9ubHkgbnVtYmVyW10sIHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgc2l6ZSA9IDE7XG4gICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgIC8vIHNhZmV0eSBjaGVjayBhcyB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYnkgbXVsdGlwbGUgb3RoZXIgbWV0aG9kcyByZXF1aXJpbmcgc2l6ZS5cbiAgICAgIC8vIHNpemUgY2Fubm90IGJlIG5lZ2F0aXZlLlxuICAgICAgaWYgKGRpbXNbaV0gPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnY2Fubm90IGdldCB2YWxpZCBzaXplIGZyb20gc3BlY2lmaWVkIGRpbWVuc2lvbiByYW5nZS4gTW9zdCBsaWtlbHkgdGhlIHJhbmdlIGNvbnRhaW5zIG5lZ2F0aXZlIHZhbHVlcyBpbiB0aGVtLicsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBzaXplICo9IE51bWJlcihkaW1zW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIHNpemU7XG4gIH1cblxuICBzdGF0aWMgY29tcHV0ZVN0cmlkZXMoZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgY29uc3QgcmFuayA9IGRpbXMubGVuZ3RoO1xuICAgIGlmIChyYW5rID09PSAwKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfSBlbHNlIGlmIChyYW5rID09PSAxKSB7XG4gICAgICByZXR1cm4gWzFdO1xuICAgIH1cbiAgICBjb25zdCBzdHJpZGVzID0gbmV3IEFycmF5KHJhbmspO1xuICAgIHN0cmlkZXNbcmFuayAtIDFdID0gMTtcbiAgICBzdHJpZGVzW3JhbmsgLSAyXSA9IGRpbXNbcmFuayAtIDFdO1xuICAgIGZvciAobGV0IGkgPSByYW5rIC0gMzsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHN0cmlkZXNbaV0gPSBzdHJpZGVzW2kgKyAxXSAqIGRpbXNbaSArIDFdO1xuICAgIH1cbiAgICByZXR1cm4gc3RyaWRlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBub3JtYWxpemUgYXhpcyBvZiByYW5nZSBbLXIsIHIpIGludG8gWzAsIHIpLlxuICAgKi9cbiAgc3RhdGljIG5vcm1hbGl6ZUF4aXMoYXhpczogbnVtYmVyLCB0ZW5zb3JSYW5rOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmIChheGlzIDwgLXRlbnNvclJhbmsgJiYgYXhpcyA+PSB0ZW5zb3JSYW5rKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vuc3VwcG9ydGVkIGF4aXMgZm9yIHRoaXMgb3BlcmF0aW9uLicpO1xuICAgIH1cbiAgICByZXR1cm4gYXhpcyA8IDAgPyBheGlzICsgdGVuc29yUmFuayA6IGF4aXM7XG4gIH1cblxuICBzdGF0aWMgbm9ybWFsaXplQXhlcyhheGVzOiByZWFkb25seSBudW1iZXJbXSwgdGVuc29yUmFuaz86IG51bWJlcik6IG51bWJlcltdIHtcbiAgICByZXR1cm4gYXhlcy5tYXAoKHgpID0+IHRoaXMubm9ybWFsaXplQXhpcyh4LCB0ZW5zb3JSYW5rID8/IGF4ZXMubGVuZ3RoKSk7XG4gIH1cblxuICAvKipcbiAgICogU29ydHMgYSBnaXZlbiBhcnJheSBiYXNlZCBvbiB0aGUgaW5kaWNlcyBpbiB0aGUgUGVybSBhcnJheVxuICAgKiBVc2VkIGluIFRyYW5zcG9zZVxuICAgKiBAcGFyYW0gYSBBcnJheSB0byBiZSBzb3J0ZWQgc3VjaCBhcyBkaW1zIG9yIHN0cmlkZXNcbiAgICogQHBhcmFtIHBlcm0gUGVybSBnaXZlbjsgaWYgbnVsbCBhIHdpbGwgYmUgcmV2ZXJzZWRcbiAgICovXG4gIHN0YXRpYyBzb3J0QmFzZWRPblBlcm0oYTogcmVhZG9ubHkgbnVtYmVyW10sIHBlcm0/OiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBpZiAocGVybSkge1xuICAgICAgcmV0dXJuIHBlcm0ubWFwKCh2KSA9PiBhW3ZdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGEuc2xpY2UoKS5yZXZlcnNlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhZHMgYSBnaXZlbiBzaGFwZSBhY2NvcmRpbmcgdG8gdGhlIHBhZGRpbmcgdmFsdWVzXG4gICAqIEBwYXJhbSBkaW1zIHNoYXBlIG9mIHRoZSBUZW5zb3IgdG8gYmUgcGFkZGVkXG4gICAqIEBwYXJhbSBwYWQgcGFkIHZhbHVlc1xuICAgKi9cbiAgc3RhdGljIHBhZFNoYXBlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBwYWQ6IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGNvbnN0IHJhbmsgPSBkaW1zLmxlbmd0aDtcbiAgICByZXR1cm4gZGltcy5tYXAoKHYsIGkpID0+IHYgKyBwYWRbaV0gKyBwYWRbaSArIHJhbmtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIGlmIHRoZSB0d28gc2hhcGVzIGFyZSBpZGVudGljYWxcbiAgICogQHBhcmFtIHNoYXBlMVxuICAgKiBAcGFyYW0gc2hhcGUyXG4gICAqL1xuICBzdGF0aWMgYXJlRXF1YWwoc2hhcGUxOiByZWFkb25seSBudW1iZXJbXSwgc2hhcGUyOiByZWFkb25seSBudW1iZXJbXSk6IGJvb2xlYW4ge1xuICAgIGlmIChzaGFwZTEubGVuZ3RoICE9PSBzaGFwZTIubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBzaGFwZTEuZXZlcnkoKHYsIGkpID0+IHYgPT09IHNoYXBlMltpXSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFBvb2xDb252VXRpbCB7XG4gIC8qKlxuICAgKiBBZGp1c3QgdGhlIGtlcm5lbCwgc3RyaWRlcywgcGFkcyB0byBjb3JyZWN0IHJhbmsuIFNldCB0byBkZWZhdWx0IHZhbHVlIGlmIG5vdCBwcmVzZW50XG4gICAqIEBwYXJhbSBpc0dsb2JhbE9wZXJhdG9yIElmIHRydWUsIHBlcmZvcm0gZ2xvYmFsIHBvb2xpbmcuXG4gICAqIEBwYXJhbSBpbnB1dERpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb24uXG4gICAqIEBwYXJhbSBrZXJuZWxTaGFwZSBUaGUgc2l6ZSBvZiB0aGUga2VybmVsIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHN0cmlkZXMgU3RyaWRlIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGRpbGF0aW9ucyBEaWxhdGlvbiBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBwYWRzIFBhZGRpbmcgZm9yIHRoZSBiZWdpbm5pbmcgYW5kIGVuZGluZyBhbG9uZyBlYWNoIGF4aXMuXG4gICAqL1xuICBzdGF0aWMgYWRqdXN0UG9vbEF0dHJpYnV0ZXMoXG4gICAgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbixcbiAgICBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGtlcm5lbFNoYXBlOiBudW1iZXJbXSxcbiAgICBzdHJpZGVzOiBudW1iZXJbXSxcbiAgICBkaWxhdGlvbnM6IG51bWJlcltdLFxuICAgIHBhZHM6IG51bWJlcltdLFxuICApOiB2b2lkIHtcbiAgICBpZiAoIWlzR2xvYmFsT3BlcmF0b3IgJiYga2VybmVsU2hhcGUubGVuZ3RoICE9PSBpbnB1dERpbXMubGVuZ3RoIC0gMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2Ygc3BlY2lmaWVkIGtlcm5lbCBzaGFwZXMgc2hvdWxkIGJlIDIgbGVzcyB0aGFuIGxlbmd0aCBvZiBpbnB1dCBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKGlzR2xvYmFsT3BlcmF0b3IpIHtcbiAgICAgIC8vIGFkanVzdCBrZXJuZWwgc2hhcGUgdG8gY292ZXIgdGhlIGlucHV0IGRpbXNcbiAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGlucHV0RGltcy5sZW5ndGggLSAyOyBkaW0rKykge1xuICAgICAgICBpZiAoZGltID49IGtlcm5lbFNoYXBlLmxlbmd0aCkge1xuICAgICAgICAgIGtlcm5lbFNoYXBlLnB1c2goaW5wdXREaW1zW2RpbSArIDJdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBrZXJuZWxTaGFwZVtkaW1dID0gaW5wdXREaW1zW2RpbSArIDJdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gYWRqdXN0IHN0cmlkZXMgbGVuZ3RoIHRvIG1hdGNoIGtlcm5lbCBzaGFwZSBsZW5ndGhcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgc3RyaWRlcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHN0cmlkZXNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0cmlkZXMgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0cmlkZXMucHVzaCgxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhZGp1c3QgZGlsYXRpb24gdmFsdWVcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgZGlsYXRpb25zLmxlbmd0aCkge1xuICAgICAgICBpZiAoZGlsYXRpb25zW2RpbV0gPCAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkaWxhdGlvbnMgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRpbGF0aW9ucy5wdXNoKDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkanVzdCBwYWRzIGxlbmd0aCB0byBtYXRjaCAyICoga2VybmVsIHNoYXBlIGxlbmd0aFxuICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGtlcm5lbFNoYXBlLmxlbmd0aCAqIDI7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgcGFkcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHBhZHNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhZCBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFkcy5wdXNoKDApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNhbml0eSBjaGVja3MgZm9yIHZhbHVlcyBpbiBrZXJuZWwgc2hhcGVzIGFuZCBwYWRzXG4gICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwga2VybmVsU2hhcGUubGVuZ3RoOyBkaW0rKykge1xuICAgICAgaWYgKGtlcm5lbFNoYXBlW2RpbV0gPD0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2tlcm5lbCBzaGFwZXMgbmVlZCB0byBiZSBncmVhdGVyIHRoYW4gMCcpO1xuICAgICAgfVxuXG4gICAgICBpZiAocGFkc1tkaW1dID49IGtlcm5lbFNoYXBlW2RpbV0gfHwgcGFkc1tkaW0gKyBrZXJuZWxTaGFwZS5sZW5ndGhdID49IGtlcm5lbFNoYXBlW2RpbV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwYWRzIHNob3VsZCBiZSBzbWFsbGVyIHRoYW4ga2VybmVsJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gYWRqdXN0IHBhZCB2YWx1ZXMgYmFzZWQgb24gJ2F1dG9QYWQnIGF0dHJpYnV0ZVxuICBzdGF0aWMgYWRqdXN0UGFkc0Jhc2VkT25BdXRvUGFkKFxuICAgIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgcGFkczogbnVtYmVyW10sXG4gICAgaXNDaGFubmVsTGFzdDogYm9vbGVhbixcbiAgICBhdXRvUGFkPzogc3RyaW5nLFxuICApOiB2b2lkIHtcbiAgICBpZiAoIWF1dG9QYWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAocGFkcy5sZW5ndGggIT09IDIgKiAoaW5wdXREaW1zLmxlbmd0aCAtIDIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2xlbmd0aCBvZiBwYWRzIHNob3VsZCBiZSB0d2ljZSB0aGUgbGVuZ3RoIG9mIGRhdGEgZGltZW5zaW9ucycpO1xuICAgIH1cblxuICAgIGlmIChzdHJpZGVzLmxlbmd0aCAhPT0gaW5wdXREaW1zLmxlbmd0aCAtIDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbGVuZ3RoIG9mIHN0cmlkZXMgc2hvdWxkIGJlIHRoZSBsZW5ndGggb2YgZGF0YSBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKGtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gaW5wdXREaW1zLmxlbmd0aCAtIDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbGVuZ3RoIG9mIGtlcm5lbCBzaGFwZXMgc2hvdWxkIGJlIHRoZSBsZW5ndGggb2YgZGF0YSBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwgaW5wdXREaW1zLmxlbmd0aCAtIDI7IGRpbSsrKSB7XG4gICAgICBQb29sQ29udlV0aWwuYWRqdXN0UGFkQW5kUmV0dXJuU2hhcGUoXG4gICAgICAgIGlucHV0RGltc1tkaW0gKyAoaXNDaGFubmVsTGFzdCA/IDEgOiAyKV0sXG4gICAgICAgIHN0cmlkZXNbZGltXSxcbiAgICAgICAgZGlsYXRpb25zW2RpbV0sXG4gICAgICAgIGtlcm5lbFNoYXBlW2RpbV0sXG4gICAgICAgIHBhZHMsXG4gICAgICAgIGRpbSxcbiAgICAgICAgZGltICsgaW5wdXREaW1zLmxlbmd0aCAtIDIsXG4gICAgICAgIGF1dG9QYWQsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIG91dHB1dCBzaGFwZSBmb3IgUG9vbCBvcHMgYmFzZWQgb24gaW5wdXQgYXR0cmlidXRlcy4gKFNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIFBvb2wgb3BzKVxuICAgKiBAcGFyYW0gaXNHbG9iYWxPcGVyYXRvciBJZiB0cnVlLCBwZXJmb3JtIGdsb2JhbCBwb29saW5nLlxuICAgKiBAcGFyYW0gaW5wdXREaW1zIFRoZSBpbnB1dCB0ZW5zb3IgZGltZW5zaW9uLiAoaW5wdXRzWzBdLmRpbXMpXG4gICAqIEBwYXJhbSBzdHJpZGVzIFN0cmlkZSBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBkaWxhdGlvbnMgRGlsYXRpb24gYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0ga2VybmVsU2hhcGUgVGhlIHNpemUgb2YgdGhlIGtlcm5lbCBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBwYWRzIFBhZGRpbmcgZm9yIHRoZSBiZWdpbm5pbmcgYW5kIGVuZGluZyBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBhdXRvUGFkIERFUFJFQ0FURUQgYXR0cmlidXRlIHN1cHBvcnRlZCBmb3IgbGVnYWN5IG1vZGVscy4gU3BlY2lmaWVzIGhvdyB0byBpbXBsaWNpdGx5IGNhbGN1bGF0ZSBwYWRzIGluIGVhY2hcbiAgICogICAgIGRpbWVuc2lvbi4gQ2FuIHRha2UgdmFsdWVzIE5PVFNFVCwgU0FNRV9VUFBFUiwgU0FNRV9MT1dFUiwgb3IgVkFMSUQuXG4gICAqL1xuICBzdGF0aWMgY29tcHV0ZVBvb2xPdXRwdXRTaGFwZShcbiAgICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLFxuICAgIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgc3RyaWRlczogbnVtYmVyW10sXG4gICAgZGlsYXRpb25zOiBudW1iZXJbXSxcbiAgICBrZXJuZWxTaGFwZTogbnVtYmVyW10sXG4gICAgcGFkczogbnVtYmVyW10sXG4gICAgYXV0b1BhZD86IHN0cmluZyxcbiAgKTogbnVtYmVyW10ge1xuICAgIGlmIChpbnB1dERpbXMubGVuZ3RoIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgc2hhcGUgbXVzdCBiZSBvZiBzaXplIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgLy8gQWRkIGJhdGNoIHNpemUgYW5kIG51bWJlciBvZiBjaGFubmVscyBvZiBvdXRwdXRcbiAgICBjb25zdCBvdXRwdXREaW1zID0gW2lucHV0RGltc1swXSwgaW5wdXREaW1zWzFdXTtcblxuICAgIFBvb2xDb252VXRpbC5jb21wdXRlU2hhcGVIZWxwZXIoXG4gICAgICBpc0dsb2JhbE9wZXJhdG9yLFxuICAgICAgaW5wdXREaW1zLFxuICAgICAgb3V0cHV0RGltcyxcbiAgICAgIHN0cmlkZXMsXG4gICAgICBkaWxhdGlvbnMsXG4gICAgICBrZXJuZWxTaGFwZSxcbiAgICAgIHBhZHMsXG4gICAgICBhdXRvUGFkLFxuICAgICk7XG4gICAgcmV0dXJuIG91dHB1dERpbXM7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBvdXRwdXQgc2hhcGUgZm9yIENvbnYgb3AgYmFzZWQgb24gaW5wdXQgYXR0cmlidXRlcy4gKFNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIENvbnYgb3ApXG4gICAqIEBwYXJhbSBpbnB1dERpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb24uIChpbnB1dHNbMF0uZGltcylcbiAgICogQHBhcmFtIGZpbHRlckRpbXMgVGhlIGZpbHRlciB0ZW5zb3IgZGltZW5zaW9uLiAoaW5wdXRzWzFdLmRpbXMpXG4gICAqIEBwYXJhbSBzdHJpZGVzIFN0cmlkZSBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBrZXJuZWxTaGFwZSBUaGUgc2l6ZSBvZiB0aGUga2VybmVsIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHBhZHMgUGFkZGluZyBmb3IgdGhlIGJlZ2lubmluZyBhbmQgZW5kaW5nIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGF1dG9QYWQgREVQUkVDQVRFRCBhdHRyaWJ1dGUgc3VwcG9ydGVkIGZvciBsZWdhY3kgbW9kZWxzLiBTcGVjaWZpZXMgaG93IHRvIGltcGxpY2l0bHkgY2FsY3VsYXRlIHBhZHMgaW4gZWFjaFxuICAgKiAgICAgZGltZW5zaW9uLiBDYW4gdGFrZSB2YWx1ZXMgTk9UU0VULCBTQU1FX1VQUEVSLCBTQU1FX0xPV0VSLCBvciBWQUxJRC5cbiAgICovXG4gIHN0YXRpYyBjb21wdXRlQ29udk91dHB1dFNoYXBlKFxuICAgIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgZmlsdGVyRGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgc3RyaWRlczogbnVtYmVyW10sXG4gICAgZGlsYXRpb25zOiBudW1iZXJbXSxcbiAgICBrZXJuZWxTaGFwZTogbnVtYmVyW10sXG4gICAgcGFkczogbnVtYmVyW10sXG4gICAgYXV0b1BhZD86IHN0cmluZyxcbiAgKTogbnVtYmVyW10ge1xuICAgIGlmIChpbnB1dERpbXMubGVuZ3RoIDw9IDAgfHwgZmlsdGVyRGltcy5sZW5ndGggPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGlucHV0IHRlbnNvciBkaW1zIG9yIGludmFsaWQgZmlsdGVyIHRlbnNvciBkaW1zJyk7XG4gICAgfVxuXG4gICAgLy8gQWRkIGJhdGNoIHNpemUgYW5kIG51bWJlciBvZiBjaGFubmVscyBvZiBvdXRwdXRcbiAgICBjb25zdCBvdXRwdXREaW1zID0gW2lucHV0RGltc1swXSwgZmlsdGVyRGltc1swXV07XG5cbiAgICBQb29sQ29udlV0aWwuY29tcHV0ZVNoYXBlSGVscGVyKGZhbHNlLCBpbnB1dERpbXMsIG91dHB1dERpbXMsIHN0cmlkZXMsIGRpbGF0aW9ucywga2VybmVsU2hhcGUsIHBhZHMsIGF1dG9QYWQpO1xuICAgIHJldHVybiBvdXRwdXREaW1zO1xuICB9XG5cbiAgLy8gd2lsbCBjb21wdXRlIG91dHB1dCBzaGFwZXMgZm9yIGRhdGEgZGltZW5zaW9ucyBPTkxZIChpLmUuKSBubyBiYXRjaCBzaXplIGFuZCBjaGFubmVsc1xuICAvLyBjYWxsZWQgYnkgY29tcHV0ZVBvb2xPdXRwdXRTaGFwZSgpIGFuZCBjb21wdXRlQ29udk91dHB1dFNoYXBlKClcbiAgLy8gYWRqdXN0IHBhZHMgYmFzZWQgb24gJ2F1dG9QYWQnIGF0dHJpYnV0ZSBwcmlvciB0byBzaGFwZSBjb21wdXRhdGlvblxuICBwcml2YXRlIHN0YXRpYyBjb21wdXRlU2hhcGVIZWxwZXIoXG4gICAgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbixcbiAgICBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIG91dHB1dERpbXM6IG51bWJlcltdLFxuICAgIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIHBhZHM6IG51bWJlcltdLFxuICAgIGF1dG9QYWQ/OiBzdHJpbmcsXG4gICkge1xuICAgIGlmIChpc0dsb2JhbE9wZXJhdG9yKSB7XG4gICAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBpbnB1dERpbXMubGVuZ3RoIC0gMjsgZGltKyspIHtcbiAgICAgICAgb3V0cHV0RGltcy5wdXNoKDEpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBpbnB1dERpbXMubGVuZ3RoIC0gMjsgZGltKyspIHtcbiAgICAgICAgb3V0cHV0RGltcy5wdXNoKFxuICAgICAgICAgIFBvb2xDb252VXRpbC5hZGp1c3RQYWRBbmRSZXR1cm5TaGFwZShcbiAgICAgICAgICAgIGlucHV0RGltc1tkaW0gKyAyXSxcbiAgICAgICAgICAgIHN0cmlkZXNbZGltXSxcbiAgICAgICAgICAgIGRpbGF0aW9uc1tkaW1dLFxuICAgICAgICAgICAga2VybmVsU2hhcGVbZGltXSxcbiAgICAgICAgICAgIHBhZHMsXG4gICAgICAgICAgICBkaW0sXG4gICAgICAgICAgICBkaW0gKyBpbnB1dERpbXMubGVuZ3RoIC0gMixcbiAgICAgICAgICAgIGF1dG9QYWQsXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBoZWxwZXIgZm9yIGNvbXB1dGVTaGFwZUhlbHBlcigpIGFuZCBhZGp1c3RQYWRzQmFzZWRPbkF1dG9QYWQoKVxuICAvLyBhZGp1c3RzIHBhZCB2YWx1ZSBmb3IgZ2l2ZW4gJ2F1dG9QYWQnIHN0cmluZyBhbmQgY29tcHV0ZXMgb3V0cHV0IHNoYXBlIGFsb25nIGEgcGFydGljdWxhciBkaW1lbnNpb25cbiAgcHJpdmF0ZSBzdGF0aWMgYWRqdXN0UGFkQW5kUmV0dXJuU2hhcGUoXG4gICAgaW5TaXplOiBudW1iZXIsXG4gICAgc3RyaWRlOiBudW1iZXIsXG4gICAgZGlsYXRpb246IG51bWJlcixcbiAgICBrZXJuZWw6IG51bWJlcixcbiAgICBwYWRzOiBudW1iZXJbXSxcbiAgICBwYWRIZWFkSW5kZXg6IG51bWJlcixcbiAgICBwYWRUYWlsSW5kZXg6IG51bWJlcixcbiAgICBhdXRvUGFkPzogc3RyaW5nLFxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IGRrZXJuZWwgPSBkaWxhdGlvbiAqIChrZXJuZWwgLSAxKSArIDE7XG4gICAgaWYgKGF1dG9QYWQgJiYgYXV0b1BhZCAhPT0gJ05PVFNFVCcpIHtcbiAgICAgIHN3aXRjaCAoYXV0b1BhZCkge1xuICAgICAgICBjYXNlICdWQUxJRCc6XG4gICAgICAgICAgcGFkc1twYWRIZWFkSW5kZXhdID0gMDtcbiAgICAgICAgICBwYWRzW3BhZFRhaWxJbmRleF0gPSAwO1xuICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKChpblNpemUgLSBka2VybmVsKSAvIHN0cmlkZSArIDEpO1xuICAgICAgICBjYXNlICdTQU1FX0xPV0VSJzpcbiAgICAgICAgY2FzZSAnU0FNRV9VUFBFUic6XG4gICAgICAgICAgaWYgKGRpbGF0aW9uICE9PSAxKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RpbGF0aW9uIG5vdCBzdXBwb3J0ZWQgZm9yIFNBTUVfVVBQRVIgb3IgU0FNRV9MT1dFUicpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBsZWdhY3lUYXJnZXRTaXplID0gKGluU2l6ZSArIHN0cmlkZSAtIDEpIC8gc3RyaWRlO1xuICAgICAgICAgICAgY29uc3QgcGFkTmVlZGVkID0gKGxlZ2FjeVRhcmdldFNpemUgLSAxKSAqIHN0cmlkZSArIGtlcm5lbCAtIGluU2l6ZTtcbiAgICAgICAgICAgIHBhZHNbcGFkSGVhZEluZGV4XSA9IGF1dG9QYWQgPT09ICdTQU1FX0xPV0VSJyA/IE1hdGguZmxvb3IoKHBhZE5lZWRlZCArIDEpIC8gMikgOiBNYXRoLmZsb29yKHBhZE5lZWRlZCAvIDIpO1xuICAgICAgICAgICAgcGFkc1twYWRUYWlsSW5kZXhdID0gcGFkTmVlZGVkIC0gcGFkc1twYWRIZWFkSW5kZXhdO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGluU2l6ZSArIHBhZE5lZWRlZCAtIGtlcm5lbCkgLyBzdHJpZGUgKyAxKTtcbiAgICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBBdXRvUGFkIHR5cGUnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGluU2l6ZSArIHBhZHNbcGFkSGVhZEluZGV4XSArIHBhZHNbcGFkVGFpbEluZGV4XSAtIGRrZXJuZWwpIC8gc3RyaWRlICsgMSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBHZW1tVXRpbCB7XG4gIC8vIHdpbGwgbWFrZSBzdXJlIGlucHV0IHNoYXBlcyBhcmUgY29tcGF0aWJsZSBmb3IgdGhpcyBvcFxuICAvLyBhbmQgcmV0dXJuIGJhY2sgdGhlIHNoYXBlIG9mIHRoZSBvdXRwdXQgaW4gdGhlIGZvcm0gb2YgYSB0dXBsZVxuICAvLyB3aWxsIHRocm93IGV4Y2VwdGlvbiBpZiB0aGUgaW5wdXQgc2hhcGVzIGFyZSBub3QgY29tcGF0aWJsZVxuICBzdGF0aWMgZ2V0U2hhcGVPZkdlbW1SZXN1bHQoXG4gICAgbGVmdFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgICB0cmFuc0xlZnQ6IGJvb2xlYW4sXG4gICAgcmlnaHRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgdHJhbnNSaWdodDogYm9vbGVhbixcbiAgICBiaWFzU2hhcGU/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGlmIChsZWZ0U2hhcGUubGVuZ3RoICE9PSAyIHx8IHJpZ2h0U2hhcGUubGVuZ3RoICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NoYXBlIG5lZWQgdG8gYmUgb2Ygc2l6ZSAyJyk7XG4gICAgfVxuXG4gICAgbGV0IE06IG51bWJlcjtcbiAgICBsZXQgSzogbnVtYmVyO1xuICAgIGxldCBOOiBudW1iZXI7XG5cbiAgICBpZiAodHJhbnNMZWZ0KSB7XG4gICAgICBNID0gbGVmdFNoYXBlWzFdO1xuICAgICAgSyA9IGxlZnRTaGFwZVswXTtcbiAgICB9IGVsc2Uge1xuICAgICAgTSA9IGxlZnRTaGFwZVswXTtcbiAgICAgIEsgPSBsZWZ0U2hhcGVbMV07XG4gICAgfVxuXG4gICAgbGV0IGtEaW0gPSAtMTtcblxuICAgIGlmICh0cmFuc1JpZ2h0KSB7XG4gICAgICBOID0gcmlnaHRTaGFwZVswXTtcbiAgICAgIGtEaW0gPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICBOID0gcmlnaHRTaGFwZVsxXTtcbiAgICAgIGtEaW0gPSAwO1xuICAgIH1cblxuICAgIGlmIChyaWdodFNoYXBlW2tEaW1dICE9PSBLKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RpbWVuc2lvbiBtaXNtYXRjaCcpO1xuICAgIH1cblxuICAgIGlmIChNIDw9IDAgfHwgTiA8PSAwIHx8IEsgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNoYXBlIHNwZWNpZmllZCcpO1xuICAgIH1cblxuICAgIGlmIChiaWFzU2hhcGUgJiYgIUJyb2FkY2FzdFV0aWwuaXNWYWxpZEJyb2FkY2FzdChiaWFzU2hhcGUsIFtNLCBOXSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2VtbTogaW52YWxpZCBiaWFzIHNoYXBlIGZvciBicm9hZGNhc3QnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW00sIE4sIEtdO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBNSU5fQ0xJUCA9IC0zLjQwMjgyMzQ2NjM4NTI4ODZlMzg7XG5leHBvcnQgY29uc3QgTUFYX0NMSVAgPSAzLjQwMjgyMzQ2NjM4NTI4ODZlMzg7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3RvciB9IGZyb20gJy4uL3dhc20tY29tbW9uJztcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVZpZXcgPSAoXG4gIGRhdGFCdWZmZXI6IEFycmF5QnVmZmVyLFxuICB0eXBlOiBUZW5zb3IuVHlwZSxcbik6XG4gIHwgSW50MzJBcnJheVxuICB8IFVpbnQzMkFycmF5XG4gIHwgQmlnSW50NjRBcnJheVxuICB8IEJpZ1VpbnQ2NEFycmF5XG4gIHwgVWludDhBcnJheVxuICB8IEZsb2F0MzJBcnJheVxuICB8IEZsb2F0NjRBcnJheVxuICB8IEludDhBcnJheVxuICB8IEludDE2QXJyYXlcbiAgfCBVaW50MTZBcnJheSA9PiBuZXcgKHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3Rvcih0eXBlKSkoZGF0YUJ1ZmZlcik7XG5cbi8qKlxuICogYSBUZW5zb3JWaWV3IGRvZXMgbm90IG93biB0aGUgZGF0YS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JWaWV3IHtcbiAgcmVhZG9ubHkgZGF0YTogbnVtYmVyO1xuICByZWFkb25seSBkYXRhVHlwZTogbnVtYmVyO1xuICByZWFkb25seSBkaW1zOiByZWFkb25seSBudW1iZXJbXTtcblxuICAvKipcbiAgICogZ2V0IGEgRmxvYXQxNkFycmF5IGRhdGEgdmlldyBvZiB0aGUgdGVuc29yIGRhdGEuIHRlbnNvciBkYXRhIG11c3QgYmUgb24gQ1BVLlxuICAgKi9cbiAgZ2V0VWludDE2QXJyYXkoKTogVWludDE2QXJyYXk7XG5cbiAgLyoqXG4gICAqIGdldCBhIEZsb2F0MzJBcnJheSBkYXRhIHZpZXcgb2YgdGhlIHRlbnNvciBkYXRhLiB0ZW5zb3IgZGF0YSBtdXN0IGJlIG9uIENQVS5cbiAgICovXG4gIGdldEZsb2F0MzJBcnJheSgpOiBGbG9hdDMyQXJyYXk7XG5cbiAgLyoqXG4gICAqIGdldCBhIEJpZ0ludDY0QXJyYXkgZGF0YSB2aWV3IG9mIHRoZSB0ZW5zb3IgZGF0YS4gdGVuc29yIGRhdGEgbXVzdCBiZSBvbiBDUFUuXG4gICAqL1xuICBnZXRCaWdJbnQ2NEFycmF5KCk6IEJpZ0ludDY0QXJyYXk7XG5cbiAgLyoqXG4gICAqIGdldCBhIEludDMyQXJyYXkgZGF0YSB2aWV3IG9mIHRoZSB0ZW5zb3IgZGF0YS4gdGVuc29yIGRhdGEgbXVzdCBiZSBvbiBDUFUuXG4gICAqL1xuICBnZXRJbnQzMkFycmF5KCk6IEludDMyQXJyYXk7XG5cbiAgLyoqXG4gICAqIGdldCBhIFVpbnQxNkFycmF5IGRhdGEgdmlldyBvZiB0aGUgdGVuc29yIGRhdGEuIHRlbnNvciBkYXRhIG11c3QgYmUgb24gQ1BVLlxuICAgKi9cbiAgZ2V0VWludDE2QXJyYXkoKTogVWludDE2QXJyYXk7XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhIG5ldyB0ZW5zb3IgdmlldyB3aXRoIHRoZSBzYW1lIGRhdGEgYnV0IGRpZmZlcmVudCBkaW1lbnNpb25zLlxuICAgKi9cbiAgcmVzaGFwZShuZXdEaW1zOiByZWFkb25seSBudW1iZXJbXSk6IFRlbnNvclZpZXc7XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFdlYk5OQmFja2VuZCB9IGZyb20gJy4uL2JhY2tlbmQtd2Vibm4nO1xuaW1wb3J0IHsgdGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yIH0gZnJvbSAnLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgTE9HX0RFQlVHIH0gZnJvbSAnLi4vbG9nJztcblxuLy8gV2ViTk4gQVBJIGN1cnJlbnRseSBkb2VzIG5vdCBoYXZlIGEgVHlwZVNjcmlwdCBkZWZpbml0aW9uIGZpbGUuIFRoaXMgZmlsZSBpcyBhIHdvcmthcm91bmQgd2l0aCB0eXBlcyBnZW5lcmF0ZWQgZnJvbVxuLy8gV2ViTk4gQVBJIHNwZWNpZmljYXRpb24uXG4vLyBodHRwczovL2dpdGh1Yi5jb20vd2VibWFjaGluZWxlYXJuaW5nL3dlYm5uL2lzc3Vlcy82Nzdcbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJ3ZWJubi5kLnRzXCIgLz5cblxuLyoqXG4gKiBNYXAgZnJvbSBNTE9wZXJhbmREYXRhVHlwZSB0byBzaXplIGluIGJpdHMuIFVzaW5nIGJpdHMgaW5zdGVhZCBvZiBieXRlcyB0byBhdm9pZCBwb3NzaWJsZSBwcmVjaXNpb24gbG9zcyBvbiBpbnQ0IGFuZCB1aW50NC5cbiAqL1xuY29uc3Qgd2Vibm5EYXRhVHlwZVRvU2l6ZSA9IG5ldyBNYXA8TUxPcGVyYW5kRGF0YVR5cGUsIG51bWJlcj4oW1xuICBbJ2Zsb2F0MzInLCAzMl0sXG4gIFsnZmxvYXQxNicsIDE2XSxcbiAgWydpbnQzMicsIDMyXSxcbiAgWyd1aW50MzInLCAzMl0sXG4gIFsnaW50NjQnLCA2NF0sXG4gIFsndWludDY0JywgNjRdLFxuICBbJ2ludDgnLCA4XSxcbiAgWyd1aW50OCcsIDhdLFxuICBbJ2ludDQnLCA0XSxcbiAgWyd1aW50NCcsIDRdLFxuXSk7XG5cbi8vIENvbnZlcnQgaW50ZWdlciBkYXRhIHRvIGFuIEludDMyQXJyYXkgYnVmZmVyLlxuLy8gU3VwcG9ydHMgY29udmVyc2lvbiBmcm9tIGludDY0LCB1aW50NjQsIHVpbnQzMiwgaW50OCBhbmQgdWludDggdG8gaW50MzIuXG5leHBvcnQgY29uc3QgY29udmVydERhdGFUb0ludDMyID0gKGRhdGE6IFVpbnQ4QXJyYXksIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSk6IFVpbnQ4QXJyYXkgPT4ge1xuICBpZiAoZGF0YVR5cGUgPT09ICdpbnQzMicpIHtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIGNvbnN0IGRhdGFUeXBlU2l6ZSA9IHdlYm5uRGF0YVR5cGVUb1NpemUuZ2V0KGRhdGFUeXBlKTtcbiAgaWYgKCFkYXRhVHlwZVNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFdlYk5OIGJhY2tlbmQgZG9lcyBub3Qgc3VwcG9ydCBkYXRhIHR5cGU6ICR7ZGF0YVR5cGV9YCk7XG4gIH1cbiAgY29uc3QgYnl0ZXNQZXJFbGVtZW50ID0gZGF0YVR5cGVTaXplIC8gODtcbiAgLy8gTWFrZSBzdXJlIHRoZSBkYXRhIGxlbmd0aCBpcyBhIG11bHRpcGxlIG9mIHRoZSBkYXRhIHR5cGUgc2l6ZS5cbiAgaWYgKGRhdGEuYnl0ZUxlbmd0aCAlIGJ5dGVzUGVyRWxlbWVudCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBVaW50OEFycmF5IGxlbmd0aCAtIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAke2J5dGVzUGVyRWxlbWVudH0uYCk7XG4gIH1cblxuICAvLyBDb252ZXJ0IFVpbnQ4QXJyYXkgdG8gb3JpZ2luYWwgdHlwZWQgYXJyYXkuXG4gIGNvbnN0IG51bUVsZW1lbnRzID0gZGF0YS5ieXRlTGVuZ3RoIC8gYnl0ZXNQZXJFbGVtZW50O1xuICBjb25zdCBvcmlnaW5hbEFycmF5ID0gbmV3ICh0ZW5zb3JUeXBlVG9UeXBlZEFycmF5Q29uc3RydWN0b3IoZGF0YVR5cGUpKShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBudW1FbGVtZW50cyk7XG5cbiAgc3dpdGNoIChkYXRhVHlwZSkge1xuICAgIGNhc2UgJ2ludDY0JzpcbiAgICBjYXNlICd1aW50NjQnOiB7XG4gICAgICAvLyBDb252ZXJ0IG9yaWdpbmFsIHR5cGVkIGFycmF5IHRvIEludDMyQXJyYXkuXG4gICAgICBjb25zdCBpbnQzMkFycmF5ID0gbmV3IEludDMyQXJyYXkobnVtRWxlbWVudHMpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1FbGVtZW50czsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gb3JpZ2luYWxBcnJheVtpXTtcblxuICAgICAgICAvLyBDaGVjayBmb3Igb3ZlcmZsb3cuXG4gICAgICAgIGlmICh2YWx1ZSA+IDIxNDc0ODM2NDduIHx8IHZhbHVlIDwgLTIxNDc0ODM2NDhuKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4gbm90IGNvbnZlcnQgaW50NjQgZGF0YSB0byBpbnQzMiAtIHZhbHVlIG91dCBvZiByYW5nZS5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGludDMyQXJyYXlbaV0gPSBOdW1iZXIodmFsdWUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoaW50MzJBcnJheS5idWZmZXIpO1xuICAgIH1cbiAgICBjYXNlICdpbnQ4JzpcbiAgICBjYXNlICd1aW50OCc6XG4gICAgY2FzZSAndWludDMyJzoge1xuICAgICAgLy8gQ2hlY2sgZm9yIG92ZXJmbG93LlxuICAgICAgaWYgKGRhdGFUeXBlID09PSAndWludDMyJykge1xuICAgICAgICBpZiAob3JpZ2luYWxBcnJheS5zb21lKCh2YWx1ZSkgPT4gdmFsdWUgPiAyMTQ3NDgzNjQ3KSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuIG5vdCBjb252ZXJ0IHVpbnQzMiBkYXRhIHRvIGludDMyIC0gdmFsdWUgb3V0IG9mIHJhbmdlLmApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBDb252ZXJ0IG9yaWdpbmFsIHR5cGVkIGFycmF5IHRvIEludDMyQXJyYXkuXG4gICAgICBjb25zdCBpbnQzMkFycmF5ID0gSW50MzJBcnJheS5mcm9tKG9yaWdpbmFsQXJyYXksIE51bWJlcik7XG4gICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoaW50MzJBcnJheS5idWZmZXIpO1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIGNvbnZlcnNpb24gZnJvbSAke2RhdGFUeXBlfSB0byAnaW50MzInYCk7XG4gIH1cbn07XG5cbi8vIENvbnZlcnQgSW50MzJBcnJheSBkYXRhIHRvIG9yaWdpbmFsIGludGVnZXIgZGF0YSBidWZmZXIuXG4vLyBTdXBwb3J0cyBjb252ZXJzaW9uIGZyb20gaW50MzIgdG8gaW50NjQsIHVpbnQ2NCwgdWludDMyLCBpbnQ4IGFuZCB1aW50OC5cbmV4cG9ydCBjb25zdCBjb252ZXJ0SW50MzJUb0RhdGEgPSAoZGF0YTogVWludDhBcnJheSwgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlKTogVWludDhBcnJheSA9PiB7XG4gIGlmIChkYXRhVHlwZSA9PT0gJ2ludDMyJykge1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgLy8gTWFrZSBzdXJlIHRoZSBkYXRhIGxlbmd0aCBpcyBhIG11bHRpcGxlIG9mIDQgYnl0ZXMgKEludDMyQXJyYXkpLlxuICBpZiAoZGF0YS5ieXRlTGVuZ3RoICUgNCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBVaW50OEFycmF5IGxlbmd0aCAtIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0IChpbnQzMikuJyk7XG4gIH1cblxuICAvLyBDb252ZXJ0IFVpbnQ4QXJyYXkgdG8gSW50MzJBcnJheS5cbiAgY29uc3QgbnVtRWxlbWVudHMgPSBkYXRhLmJ5dGVMZW5ndGggLyA0O1xuICBjb25zdCBpbnQzMkFycmF5ID0gbmV3IEludDMyQXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgbnVtRWxlbWVudHMpO1xuXG4gIHN3aXRjaCAoZGF0YVR5cGUpIHtcbiAgICBjYXNlICdpbnQ2NCc6IHtcbiAgICAgIGNvbnN0IGJpZ0ludDY0QXJyYXkgPSBCaWdJbnQ2NEFycmF5LmZyb20oaW50MzJBcnJheSwgQmlnSW50KTtcbiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShiaWdJbnQ2NEFycmF5LmJ1ZmZlcik7XG4gICAgfVxuICAgIGNhc2UgJ3VpbnQ2NCc6IHtcbiAgICAgIGlmIChpbnQzMkFycmF5LnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA8IDApKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBjb252ZXJ0IGludDMyIGRhdGEgdG8gdWluNjQgLSBuZWdhdGl2ZSB2YWx1ZSBmb3VuZC4nKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGJpZ1VpbnQ2NEFycmF5ID0gQmlnVWludDY0QXJyYXkuZnJvbShpbnQzMkFycmF5LCBCaWdJbnQpO1xuICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGJpZ1VpbnQ2NEFycmF5LmJ1ZmZlcik7XG4gICAgfVxuICAgIGNhc2UgJ2ludDgnOiB7XG4gICAgICBpZiAoaW50MzJBcnJheS5zb21lKCh2YWx1ZSkgPT4gdmFsdWUgPCAtMTI4IHx8IHZhbHVlID4gMTI3KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgY29udmVydCBpbnQzMiBkYXRhIHRvIGludDggLSB2YWx1ZSBvdXQgb2YgcmFuZ2UuJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBpbnQ4QXJyYXkgPSBJbnQ4QXJyYXkuZnJvbShpbnQzMkFycmF5LCBOdW1iZXIpO1xuICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGludDhBcnJheS5idWZmZXIpO1xuICAgIH1cbiAgICBjYXNlICd1aW50OCc6IHtcbiAgICAgIGlmIChpbnQzMkFycmF5LnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA8IDAgfHwgdmFsdWUgPiAyNTUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBjb252ZXJ0IGludDMyIGRhdGEgdG8gdWludDggLSB2YWx1ZSBvdXQgb2YgcmFuZ2UuJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gVWludDhBcnJheS5mcm9tKGludDMyQXJyYXksIE51bWJlcik7XG4gICAgfVxuICAgIGNhc2UgJ3VpbnQzMic6IHtcbiAgICAgIGlmIChpbnQzMkFycmF5LnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA8IDApKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBjb252ZXJ0IGludDMyIGRhdGEgdG8gdWludDMyIC0gbmVnYXRpdmUgdmFsdWUgZm91bmQuJyk7XG4gICAgICB9XG4gICAgICBjb25zdCB1aW50MzJBcnJheSA9IFVpbnQzMkFycmF5LmZyb20oaW50MzJBcnJheSwgTnVtYmVyKTtcbiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSh1aW50MzJBcnJheS5idWZmZXIpO1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIGNvbnZlcnNpb24gZnJvbSAnaW50MzInIHRvICR7ZGF0YVR5cGV9YCk7XG4gIH1cbn07XG5cbmV4cG9ydCB0eXBlIFRlbnNvcklkID0gbnVtYmVyO1xuXG4vKipcbiAqIE1hbmFnZXMgVGVuc29ySWQgdG8gTUxUZW5zb3IgbWFwcGluZy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JNYW5hZ2VyIHtcbiAgLyoqXG4gICAqIFJlc2VydmUgYSBuZXcgVGVuc29ySWQuXG4gICAqL1xuICByZXNlcnZlVGVuc29ySWQoKTogVGVuc29ySWQ7XG4gIC8qKlxuICAgKiBSZWxlYXNlIGEgVGVuc29ySWQuXG4gICAqL1xuICByZWxlYXNlVGVuc29ySWQodGVuc29ySWQ6IFRlbnNvcklkKTogdm9pZDtcbiAgLyoqXG4gICAqIEVuc3VyZSBhIE1MVGVuc29yIGlzIGNyZWF0ZWQgZm9yIHRoZSBUZW5zb3JJZC5cbiAgICovXG4gIGVuc3VyZVRlbnNvcihcbiAgICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgICB0ZW5zb3JJZDogVGVuc29ySWQsXG4gICAgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlLFxuICAgIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBjb3B5T2xkOiBib29sZWFuLFxuICApOiBQcm9taXNlPE1MVGVuc29yPjtcbiAgLyoqXG4gICAqIFVwbG9hZCBkYXRhIHRvIGEgTUxUZW5zb3IuXG4gICAqL1xuICB1cGxvYWQodGVuc29ySWQ6IFRlbnNvcklkLCBkYXRhOiBVaW50OEFycmF5KTogdm9pZDtcbiAgLyoqXG4gICAqIERvd25sb2FkIGRhdGEgZnJvbSBhIE1MVGVuc29yLlxuICAgKi9cbiAgZG93bmxvYWQodGVuc29ySWQ6IFRlbnNvcklkKTogUHJvbWlzZTxBcnJheUJ1ZmZlcj47XG4gIGRvd25sb2FkKHRlbnNvcklkOiBUZW5zb3JJZCwgZHN0VGVuc29yOiBBcnJheUJ1ZmZlclZpZXcgfCBBcnJheUJ1ZmZlcik6IFByb21pc2U8dW5kZWZpbmVkPjtcbiAgLyoqXG4gICAqIFJlbGVhc2UgYWxsIHRlbnNvcnMgZm9yIGEgZ2l2ZW4gc2Vzc2lvbi5cbiAgICovXG4gIHJlbGVhc2VUZW5zb3JzRm9yU2Vzc2lvbihzZXNzaW9uOiBudW1iZXIpOiB2b2lkO1xuICAvKipcbiAgICogUmVnaXN0ZXIgYW4gZXh0ZXJuYWxseSBjcmVhdGVkIE1MVGVuc29yIHdpdGggYSBnaXZlbiBzZXNzaW9uIGlkIGFuZCByZXR1cm4gYSBUZW5zb3JJZC5cbiAgICovXG4gIHJlZ2lzdGVyVGVuc29yKHNlc3Npb25JZDogbnVtYmVyLCBtbFRlbnNvcjogTUxUZW5zb3IsIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSwgc2hhcGU6IG51bWJlcltdKTogVGVuc29ySWQ7XG59XG5cbmxldCB0ZW5zb3JHdWlkID0gMTtcbmNvbnN0IGNyZWF0ZU5ld1RlbnNvcklkID0gKCk6IFRlbnNvcklkID0+IHRlbnNvckd1aWQrKztcblxuLyoqXG4gKiBNYXAgZnJvbSBkYXRhIHR5cGUgdG8gZmFsbGJhY2sgZGF0YSB0eXBlLlxuICogV2hlbiB0aGUgY29udGV4dCBkb2VzIG5vdCBzdXBwb3J0IHRoZSBvcmlnaW5hbCBkYXRhIHR5cGUsIHVzZSBmYWxsYmFjayBkYXRhIHR5cGUgYXMgd29ya2Fyb3VuZC5cbiAqIE5vdGU6IEN1cnJlbnRseSwgd2Ugb25seSBzdXBwb3J0IGZhbGxiYWNrIHRvIGludDMyIGZvciBjZXJ0YWluIGludGVnZXIgZGF0YSB0eXBlcy5cbiAqL1xuY29uc3Qgd2Vibm5EYXRhVHlwZVRvRmFsbGJhY2sgPSBuZXcgTWFwPE1MT3BlcmFuZERhdGFUeXBlLCBNTE9wZXJhbmREYXRhVHlwZT4oW1xuICBbJ2ludDgnLCAnaW50MzInXSxcbiAgWyd1aW50OCcsICdpbnQzMiddLFxuICBbJ3VpbnQzMicsICdpbnQzMiddLFxuICBbJ2ludDY0JywgJ2ludDMyJ10sXG5dKTtcblxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIGJ5dGUgbGVuZ3RoIG9mIGEgdGVuc29yIHdpdGggdGhlIGdpdmVuIGRhdGEgdHlwZSBhbmQgc2hhcGUuXG4gKi9cbmNvbnN0IGNhbGN1bGF0ZUJ5dGVMZW5ndGggPSAoZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlLCBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOiBudW1iZXIgPT4ge1xuICBjb25zdCBkYXRhVHlwZVNpemUgPSB3ZWJubkRhdGFUeXBlVG9TaXplLmdldChkYXRhVHlwZSk7XG4gIGlmICghZGF0YVR5cGVTaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBXZWJOTiBiYWNrZW5kIGRvZXMgbm90IHN1cHBvcnQgZGF0YSB0eXBlOiAke2RhdGFUeXBlfWApO1xuICB9XG4gIHJldHVybiBzaGFwZS5sZW5ndGggPiAwID8gTWF0aC5jZWlsKChzaGFwZS5yZWR1Y2UoKGEsIGIpID0+IGEgKiBiKSAqIGRhdGFUeXBlU2l6ZSkgLyA4KSA6IDA7XG59O1xuXG4vKipcbiAqIFRlbnNvcldyYXBwZXIgd3JhcHMgYW4gTUxUZW5zb3IgYW5kIHByb3ZpZGVzIGEgd2F5IHRvIHRyYWNrIHRoZSBsYXN0IHNlc3Npb24gdGhhdCB1c2VkIGl0LlxuICovXG5jbGFzcyBUZW5zb3JXcmFwcGVyIHtcbiAgLy8gVGhlIGlkIG9mIHRoZSBsYXN0IHNlc3Npb24gdGhhdCB1c2VkIHRoaXMgdGVuc29yLlxuICBwdWJsaWMgc2Vzc2lvbklkOiBudW1iZXI7XG4gIC8vIFRoaXMgZmxhZyBpcyB1c2VkIHRvIGluZGljYXRlIHdoZXRoZXIgdGhlIGRhdGEgaGFzIGJlZW4gY29udmVydGVkIHRvIGZhbGxiYWNrIGRhdGEgdHlwZS5cbiAgcHVibGljIGlzRGF0YUNvbnZlcnRlZCA9IGZhbHNlO1xuXG4gIHByaXZhdGUgbWxDb250ZXh0OiBNTENvbnRleHQ7XG4gIHByaXZhdGUgbWxUZW5zb3I6IE1MVGVuc29yO1xuICBwcml2YXRlIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZTtcbiAgLy8gRmFsbGJhY2sgZGF0YSB0eXBlIHRvIHVzZSB3aGVuIHRoZSBjb250ZXh0IGRvZXMgbm90IHN1cHBvcnQgdGhlIG9yaWdpbmFsIGRhdGEgdHlwZS5cbiAgcHJpdmF0ZSBmYWxsYmFja0RhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSB0ZW5zb3JTaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG5cbiAgY29uc3RydWN0b3IoZGVzY3JpcHRvcjoge1xuICAgIHNlc3Npb25JZDogbnVtYmVyO1xuICAgIGNvbnRleHQ6IE1MQ29udGV4dDtcbiAgICB0ZW5zb3I6IE1MVGVuc29yO1xuICAgIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZTtcbiAgICBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG4gICAgZmFsbGJhY2tEYXRhVHlwZT86IE1MT3BlcmFuZERhdGFUeXBlO1xuICB9KSB7XG4gICAgY29uc3QgeyBzZXNzaW9uSWQsIGNvbnRleHQsIHRlbnNvciwgZGF0YVR5cGUsIHNoYXBlLCBmYWxsYmFja0RhdGFUeXBlIH0gPSBkZXNjcmlwdG9yO1xuICAgIHRoaXMuc2Vzc2lvbklkID0gc2Vzc2lvbklkO1xuICAgIHRoaXMubWxDb250ZXh0ID0gY29udGV4dDtcbiAgICB0aGlzLm1sVGVuc29yID0gdGVuc29yO1xuICAgIHRoaXMuZGF0YVR5cGUgPSBkYXRhVHlwZTtcbiAgICB0aGlzLnRlbnNvclNoYXBlID0gc2hhcGU7XG4gICAgdGhpcy5mYWxsYmFja0RhdGFUeXBlID0gZmFsbGJhY2tEYXRhVHlwZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdGVuc29yKCk6IE1MVGVuc29yIHtcbiAgICByZXR1cm4gdGhpcy5tbFRlbnNvcjtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdHlwZSgpOiBNTE9wZXJhbmREYXRhVHlwZSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YVR5cGU7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGZhbGxiYWNrVHlwZSgpOiBNTE9wZXJhbmREYXRhVHlwZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuZmFsbGJhY2tEYXRhVHlwZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgc2hhcGUoKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIHJldHVybiB0aGlzLnRlbnNvclNoYXBlO1xuICB9XG5cbiAgcHVibGljIGdldCBieXRlTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIGNhbGN1bGF0ZUJ5dGVMZW5ndGgodGhpcy5kYXRhVHlwZSwgdGhpcy50ZW5zb3JTaGFwZSk7XG4gIH1cblxuICBwdWJsaWMgZGVzdHJveSgpOiB2b2lkIHtcbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiAnW1dlYk5OXSBUZW5zb3JXcmFwcGVyLmRlc3Ryb3knKTtcbiAgICB0aGlzLm1sVGVuc29yLmRlc3Ryb3koKTtcbiAgfVxuXG4gIHB1YmxpYyB3cml0ZShkYXRhOiBVaW50OEFycmF5KTogdm9pZCB7XG4gICAgdGhpcy5tbENvbnRleHQud3JpdGVUZW5zb3IodGhpcy5tbFRlbnNvciwgZGF0YSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcmVhZCgpOiBQcm9taXNlPEFycmF5QnVmZmVyPjtcbiAgcHVibGljIGFzeW5jIHJlYWQoZHN0QnVmZmVyPzogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpOiBQcm9taXNlPEFycmF5QnVmZmVyIHwgdW5kZWZpbmVkPjtcbiAgcHVibGljIGFzeW5jIHJlYWQoZHN0QnVmZmVyPzogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpOiBQcm9taXNlPEFycmF5QnVmZmVyIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKHRoaXMuZmFsbGJhY2tEYXRhVHlwZSkge1xuICAgICAgLy8gVGhpcyB0ZW5zb3IgaGFzIGJlZW4gZmFsbGJhY2sgdG8gaW50MzIgYXMgd29ya2Fyb3VuZCwgd2UgbmVlZCB0byByZWFkIGl0IGFzIGl0cyBvcmlnaW5hbCBpbnRlZ2VyIGRhdGEgdHlwZS5cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLm1sQ29udGV4dC5yZWFkVGVuc29yKHRoaXMubWxUZW5zb3IpO1xuICAgICAgY29uc3Qgb3JpZ2luYWxEYXRhID0gY29udmVydEludDMyVG9EYXRhKG5ldyBVaW50OEFycmF5KGRhdGEpLCB0aGlzLmRhdGFUeXBlKTtcblxuICAgICAgaWYgKGRzdEJ1ZmZlcikge1xuICAgICAgICBjb25zdCB0YXJnZXRCdWZmZXIgPVxuICAgICAgICAgIGRzdEJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyXG4gICAgICAgICAgICA/IG5ldyBVaW50OEFycmF5KGRzdEJ1ZmZlcilcbiAgICAgICAgICAgIDogbmV3IFVpbnQ4QXJyYXkoZHN0QnVmZmVyLmJ1ZmZlciwgZHN0QnVmZmVyLmJ5dGVPZmZzZXQsIGRzdEJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgdGFyZ2V0QnVmZmVyLnNldChvcmlnaW5hbERhdGEpO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG9yaWdpbmFsRGF0YS5idWZmZXI7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBkc3RCdWZmZXIgPyB0aGlzLm1sQ29udGV4dC5yZWFkVGVuc29yKHRoaXMubWxUZW5zb3IsIGRzdEJ1ZmZlcikgOiB0aGlzLm1sQ29udGV4dC5yZWFkVGVuc29yKHRoaXMubWxUZW5zb3IpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBjYW5SZXVzZVRlbnNvcihjb250ZXh0OiBNTENvbnRleHQsIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSwgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMubWxDb250ZXh0ID09PSBjb250ZXh0ICYmXG4gICAgICB0aGlzLmRhdGFUeXBlID09PSBkYXRhVHlwZSAmJlxuICAgICAgdGhpcy50ZW5zb3JTaGFwZS5sZW5ndGggPT09IHNoYXBlLmxlbmd0aCAmJlxuICAgICAgdGhpcy50ZW5zb3JTaGFwZS5ldmVyeSgodiwgaSkgPT4gdiA9PT0gc2hhcGVbaV0pXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRJc0RhdGFDb252ZXJ0ZWQoaXNDb252ZXJ0ZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmlzRGF0YUNvbnZlcnRlZCA9IGlzQ29udmVydGVkO1xuICB9XG59XG5cbi8qKlxuICogVGVuc29yVHJhY2tlciB0cmFja3MgdGhlIE1MVGVuc29yIGFuZCBwZW5kaW5nIHVwbG9hZCBkYXRhLlxuICpcbiAqIFdlIG5lZWQgdG8gdHJhY2sgdGhlIE1MVGVuc29yIGFuZCBwZW5kaW5nIHVwbG9hZCBkYXRhIGJlY2F1c2Ugd2UgZGVsYXkgdGhlIGNyZWF0aW9uIG9mIE1MVGVuc29yIHVudGlsXG4gKiB3ZSBrbm93IHRoZSBkYXRhIHR5cGUgYW5kIHNoYXBlLiBUaGlzIGlzIGJlY2F1c2UgV2ViTk4gb25seSBzdXBwb3J0IGNyZWF0aW5nIE1MVGVuc29ycyB3aXRoIGRhdGFUeXBlcyBhbmQgc2hhcGUuXG4gKi9cbmNsYXNzIFRlbnNvcklkVHJhY2tlciB7XG4gIHByaXZhdGUgYWN0aXZlVXBsb2FkPzogVWludDhBcnJheTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHRlbnNvck1hbmFnZXI6IFRlbnNvck1hbmFnZXJJbXBsLFxuICAgIHByaXZhdGUgd3JhcHBlcj86IFRlbnNvcldyYXBwZXIsXG4gICkge31cblxuICBwdWJsaWMgZ2V0IHRlbnNvcldyYXBwZXIoKTogVGVuc29yV3JhcHBlciB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMud3JhcHBlcjtcbiAgfVxuXG4gIHB1YmxpYyByZWxlYXNlVGVuc29yKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnRlbnNvcldyYXBwZXIpIHtcbiAgICAgIHRoaXMudGVuc29yTWFuYWdlci5yZWxlYXNlVGVuc29yKHRoaXMudGVuc29yV3JhcHBlcik7XG4gICAgICB0aGlzLndyYXBwZXIgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIGVuc3VyZVRlbnNvcihcbiAgICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgICBkYXRhVHlwZTogTUxPcGVyYW5kRGF0YVR5cGUsXG4gICAgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGNvcHlPbGQ6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8TUxUZW5zb3I+IHtcbiAgICBjb25zdCBjb250ZXh0ID0gdGhpcy50ZW5zb3JNYW5hZ2VyLmdldE1MQ29udGV4dChzZXNzaW9uSWQpO1xuICAgIGNvbnN0IG9wTGltaXRzID0gdGhpcy50ZW5zb3JNYW5hZ2VyLmdldE1MT3BTdXBwb3J0TGltaXRzKHNlc3Npb25JZCk7XG4gICAgbGV0IGZhbGxiYWNrRGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlIHwgdW5kZWZpbmVkO1xuICAgIC8vIENoZWNrIGlmIHRoZSBjb250ZXh0IHN1cHBvcnRzIHRoZSBkYXRhIHR5cGUuIElmIG5vdCwgdHJ5IHRvIHVzZSB0aGUgZmFsbGJhY2sgZGF0YSB0eXBlLlxuICAgIGlmICghb3BMaW1pdHM/LmlucHV0LmRhdGFUeXBlcy5pbmNsdWRlcyhkYXRhVHlwZSkpIHtcbiAgICAgIGZhbGxiYWNrRGF0YVR5cGUgPSB3ZWJubkRhdGFUeXBlVG9GYWxsYmFjay5nZXQoZGF0YVR5cGUpO1xuICAgICAgaWYgKCFmYWxsYmFja0RhdGFUeXBlIHx8IG9wTGltaXRzPy5pbnB1dC5kYXRhVHlwZXMuaW5jbHVkZXMoZmFsbGJhY2tEYXRhVHlwZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBXZWJOTiBiYWNrZW5kIGRvZXMgbm90IHN1cHBvcnQgZGF0YSB0eXBlOiAke2RhdGFUeXBlfWApO1xuICAgICAgfVxuICAgICAgTE9HX0RFQlVHKFxuICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICgpID0+IGBbV2ViTk5dIFRlbnNvcklkVHJhY2tlci5lbnN1cmVUZW5zb3I6IGZhbGxiYWNrIGRhdGFUeXBlIGZyb20gJHtkYXRhVHlwZX0gdG8gJHtmYWxsYmFja0RhdGFUeXBlfWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLndyYXBwZXIpIHtcbiAgICAgIGlmICh0aGlzLndyYXBwZXIuY2FuUmV1c2VUZW5zb3IoY29udGV4dCwgZGF0YVR5cGUsIHNoYXBlKSkge1xuICAgICAgICByZXR1cm4gdGhpcy53cmFwcGVyLnRlbnNvcjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChjb3B5T2xkKSB7XG4gICAgICAgICAgaWYgKHRoaXMud3JhcHBlci5ieXRlTGVuZ3RoICE9PSBjYWxjdWxhdGVCeXRlTGVuZ3RoKGRhdGFUeXBlLCBzaGFwZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGNvcHkgZGF0YSB0byB0ZW5zb3Igd2l0aCBkaWZmZXJlbnQgc2l6ZS4nKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5hY3RpdmVVcGxvYWQgPSBuZXcgVWludDhBcnJheShhd2FpdCB0aGlzLndyYXBwZXIucmVhZCgpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRlbnNvck1hbmFnZXIucmVsZWFzZVRlbnNvcih0aGlzLndyYXBwZXIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgY29uc3QgdXNhZ2UgPSB0eXBlb2YgTUxUZW5zb3JVc2FnZSA9PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IE1MVGVuc29yVXNhZ2UuUkVBRCB8IE1MVGVuc29yVXNhZ2UuV1JJVEU7XG4gICAgdGhpcy53cmFwcGVyID0gYXdhaXQgdGhpcy50ZW5zb3JNYW5hZ2VyLmdldENhY2hlZFRlbnNvcihcbiAgICAgIHNlc3Npb25JZCxcbiAgICAgIGRhdGFUeXBlLFxuICAgICAgc2hhcGUsXG4gICAgICB1c2FnZSxcbiAgICAgIHRydWUsXG4gICAgICB0cnVlLFxuICAgICAgZmFsbGJhY2tEYXRhVHlwZSxcbiAgICApO1xuXG4gICAgaWYgKGNvcHlPbGQgJiYgdGhpcy5hY3RpdmVVcGxvYWQpIHtcbiAgICAgIC8vIFdlIGRvbid0IG5lZWQgdG8gY29udmVydCB0aGUgb3JpZ2luYWwgaW50ZWdlciBkYXRhIHRvIGludDMyLFxuICAgICAgLy8gYmVjYXVzZSBpdCBoYXMgYmVlbiBjb252ZXJ0ZWQgd2hlbiBpdCB3YXMgdXBsb2FkZWQuXG4gICAgICB0aGlzLndyYXBwZXIud3JpdGUodGhpcy5hY3RpdmVVcGxvYWQpO1xuICAgICAgdGhpcy5hY3RpdmVVcGxvYWQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMud3JhcHBlci50ZW5zb3I7XG4gIH1cblxuICBwdWJsaWMgdXBsb2FkKGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICBsZXQgbmV3RGF0YSA9IGRhdGE7XG4gICAgaWYgKHRoaXMud3JhcHBlcikge1xuICAgICAgaWYgKHRoaXMud3JhcHBlci5mYWxsYmFja1R5cGUpIHtcbiAgICAgICAgaWYgKHRoaXMud3JhcHBlci5mYWxsYmFja1R5cGUgPT09ICdpbnQzMicpIHtcbiAgICAgICAgICAvLyBDb252ZXJ0IG9yaWdpbmFsIGludGVnZXIgZGF0YSB0byBpbnQzMi5cbiAgICAgICAgICBuZXdEYXRhID0gY29udmVydERhdGFUb0ludDMyKGRhdGEsIHRoaXMud3JhcHBlci50eXBlKTtcbiAgICAgICAgICB0aGlzLndyYXBwZXIuc2V0SXNEYXRhQ29udmVydGVkKHRydWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgZmFsbGJhY2sgZGF0YSB0eXBlOiAke3RoaXMud3JhcHBlci5mYWxsYmFja1R5cGV9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdGhlIGRhdGEgc2l6ZSBtYXRjaGVzIHRoZSB0ZW5zb3Igc2l6ZS5cbiAgICAgIGlmIChkYXRhLmJ5dGVMZW5ndGggPT09IHRoaXMud3JhcHBlci5ieXRlTGVuZ3RoKSB7XG4gICAgICAgIC8vIFdyaXRlIHRoZSBuZXdEYXRhIHRvIHRoZSB0ZW5zb3IuXG4gICAgICAgIHRoaXMud3JhcHBlci53cml0ZShuZXdEYXRhKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gJ0RhdGEgc2l6ZSBkb2VzIG5vdCBtYXRjaCB0ZW5zb3Igc2l6ZS4gUmVsZWFzaW5nIHRlbnNvci4nKTtcbiAgICAgICAgdGhpcy5yZWxlYXNlVGVuc29yKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYWN0aXZlVXBsb2FkKSB7XG4gICAgICB0aGlzLmFjdGl2ZVVwbG9hZC5zZXQobmV3RGF0YSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYWN0aXZlVXBsb2FkID0gbmV3IFVpbnQ4QXJyYXkobmV3RGF0YSk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIGRvd25sb2FkKGRzdEJ1ZmZlcj86IEFycmF5QnVmZmVyVmlldyB8IEFycmF5QnVmZmVyKTogUHJvbWlzZTxBcnJheUJ1ZmZlciB8IHVuZGVmaW5lZD4ge1xuICAgIGlmICh0aGlzLmFjdGl2ZVVwbG9hZCkge1xuICAgICAgLy8gSWYgdGhpcy5hY3RpdmVVcGxvYWQgaGFzIGJlZW4gY29udmVydGVkIHRvIGludDMyLCB3ZSBuZWVkIHRvIGNvbnZlcnQgaXQgYmFjayB0byBvcmlnaW5hbCBpbnRlZ2VyIGRhdGEgdHlwZS5cbiAgICAgIGNvbnN0IGRzdERhdGEgPSB0aGlzLndyYXBwZXI/LmlzRGF0YUNvbnZlcnRlZFxuICAgICAgICA/IGNvbnZlcnRJbnQzMlRvRGF0YSh0aGlzLmFjdGl2ZVVwbG9hZCwgdGhpcy53cmFwcGVyPy50eXBlKVxuICAgICAgICA6IHRoaXMuYWN0aXZlVXBsb2FkO1xuXG4gICAgICBpZiAoZHN0QnVmZmVyKSB7XG4gICAgICAgIGlmIChkc3RCdWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgICAgICAgIG5ldyBVaW50OEFycmF5KGRzdEJ1ZmZlcikuc2V0KGRzdERhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5ldyBVaW50OEFycmF5KGRzdEJ1ZmZlci5idWZmZXIsIGRzdEJ1ZmZlci5ieXRlT2Zmc2V0LCBkc3RCdWZmZXIuYnl0ZUxlbmd0aCkuc2V0KGRzdERhdGEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBkc3REYXRhLmJ1ZmZlcjtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCF0aGlzLndyYXBwZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIGhhcyBub3QgYmVlbiBjcmVhdGVkLicpO1xuICAgIH1cblxuICAgIGlmICghZHN0QnVmZmVyKSB7XG4gICAgICByZXR1cm4gdGhpcy53cmFwcGVyLnJlYWQoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMud3JhcHBlci5yZWFkKGRzdEJ1ZmZlcik7XG4gIH1cbn1cblxuY2xhc3MgVGVuc29yTWFuYWdlckltcGwgaW1wbGVtZW50cyBUZW5zb3JNYW5hZ2VyIHtcbiAgcHJpdmF0ZSB0ZW5zb3JUcmFja2Vyc0J5SWQ6IE1hcDxUZW5zb3JJZCwgVGVuc29ySWRUcmFja2VyPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBmcmVlVGVuc29yczogVGVuc29yV3JhcHBlcltdID0gW107XG4gIHByaXZhdGUgZXh0ZXJuYWxUZW5zb3JzOiBTZXQ8VGVuc29yV3JhcHBlcj4gPSBuZXcgU2V0KCk7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBiYWNrZW5kOiBXZWJOTkJhY2tlbmQpIHt9XG5cbiAgcHVibGljIGdldE1MQ29udGV4dChzZXNzaW9uSWQ6IG51bWJlcik6IE1MQ29udGV4dCB7XG4gICAgY29uc3QgY29udGV4dCA9IHRoaXMuYmFja2VuZC5nZXRNTENvbnRleHQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTUxDb250ZXh0IG5vdCBmb3VuZCBmb3Igc2Vzc2lvbi4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbnRleHQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0TUxPcFN1cHBvcnRMaW1pdHMoc2Vzc2lvbklkOiBudW1iZXIpOiBNTE9wU3VwcG9ydExpbWl0cyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuYmFja2VuZC5nZXRNTE9wU3VwcG9ydExpbWl0cyhzZXNzaW9uSWQpO1xuICB9XG5cbiAgcHVibGljIHJlc2VydmVUZW5zb3JJZCgpOiBUZW5zb3JJZCB7XG4gICAgY29uc3QgdGVuc29ySWQgPSBjcmVhdGVOZXdUZW5zb3JJZCgpO1xuICAgIHRoaXMudGVuc29yVHJhY2tlcnNCeUlkLnNldCh0ZW5zb3JJZCwgbmV3IFRlbnNvcklkVHJhY2tlcih0aGlzKSk7XG4gICAgcmV0dXJuIHRlbnNvcklkO1xuICB9XG5cbiAgcHVibGljIHJlbGVhc2VUZW5zb3JJZCh0ZW5zb3JJZDogVGVuc29ySWQpOiB2b2lkIHtcbiAgICBjb25zdCB0ZW5zb3JUcmFja2VyID0gdGhpcy50ZW5zb3JUcmFja2Vyc0J5SWQuZ2V0KHRlbnNvcklkKTtcbiAgICBpZiAoIXRlbnNvclRyYWNrZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy50ZW5zb3JUcmFja2Vyc0J5SWQuZGVsZXRlKHRlbnNvcklkKTtcbiAgICBpZiAodGVuc29yVHJhY2tlci50ZW5zb3JXcmFwcGVyKSB7XG4gICAgICB0aGlzLnJlbGVhc2VUZW5zb3IodGVuc29yVHJhY2tlci50ZW5zb3JXcmFwcGVyKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZW5zdXJlVGVuc29yKFxuICAgIHNlc3Npb25JZDogbnVtYmVyLFxuICAgIHRlbnNvcklkOiBUZW5zb3JJZCxcbiAgICBkYXRhVHlwZTogTUxPcGVyYW5kRGF0YVR5cGUsXG4gICAgc2hhcGU6IG51bWJlcltdLFxuICAgIGNvcHlPbGQ6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8TUxUZW5zb3I+IHtcbiAgICBMT0dfREVCVUcoXG4gICAgICAndmVyYm9zZScsXG4gICAgICAoKSA9PlxuICAgICAgICBgW1dlYk5OXSBUZW5zb3JNYW5hZ2VyLmVuc3VyZVRlbnNvciB7dGVuc29ySWQ6ICR7dGVuc29ySWR9LCBkYXRhVHlwZTogJHtcbiAgICAgICAgICBkYXRhVHlwZVxuICAgICAgICB9LCBzaGFwZTogJHtzaGFwZX0sIGNvcHlPbGQ6ICR7Y29weU9sZH19YCxcbiAgICApO1xuICAgIGNvbnN0IHRlbnNvciA9IHRoaXMudGVuc29yVHJhY2tlcnNCeUlkLmdldCh0ZW5zb3JJZCk7XG4gICAgaWYgKCF0ZW5zb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIG5vdCBmb3VuZC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRlbnNvci5lbnN1cmVUZW5zb3Ioc2Vzc2lvbklkLCBkYXRhVHlwZSwgc2hhcGUsIGNvcHlPbGQpO1xuICB9XG5cbiAgcHVibGljIHVwbG9hZCh0ZW5zb3JJZDogVGVuc29ySWQsIGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICBjb25zdCB0ZW5zb3IgPSB0aGlzLnRlbnNvclRyYWNrZXJzQnlJZC5nZXQodGVuc29ySWQpO1xuICAgIGlmICghdGVuc29yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBub3QgZm91bmQuJyk7XG4gICAgfVxuICAgIHRlbnNvci51cGxvYWQoZGF0YSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZG93bmxvYWQodGVuc29ySWQ6IFRlbnNvcklkKTogUHJvbWlzZTxBcnJheUJ1ZmZlcj47XG4gIHB1YmxpYyBhc3luYyBkb3dubG9hZCh0ZW5zb3JJZDogVGVuc29ySWQsIGRzdEJ1ZmZlcjogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpOiBQcm9taXNlPHVuZGVmaW5lZD47XG4gIGFzeW5jIGRvd25sb2FkKHRlbnNvcklkOiBUZW5zb3JJZCwgZHN0QnVmZmVyPzogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpOiBQcm9taXNlPEFycmF5QnVmZmVyIHwgdW5kZWZpbmVkPiB7XG4gICAgTE9HX0RFQlVHKFxuICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgKCkgPT4gYFtXZWJOTl0gVGVuc29yTWFuYWdlci5kb3dubG9hZCB7dGVuc29ySWQ6ICR7dGVuc29ySWR9LCBkc3RCdWZmZXI6ICR7ZHN0QnVmZmVyPy5ieXRlTGVuZ3RofX1gLFxuICAgICk7XG4gICAgY29uc3QgdGVuc29yVHJhY2tlciA9IHRoaXMudGVuc29yVHJhY2tlcnNCeUlkLmdldCh0ZW5zb3JJZCk7XG4gICAgaWYgKCF0ZW5zb3JUcmFja2VyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBub3QgZm91bmQuJyk7XG4gICAgfVxuICAgIHJldHVybiB0ZW5zb3JUcmFja2VyLmRvd25sb2FkKGRzdEJ1ZmZlcik7XG4gIH1cblxuICBwdWJsaWMgcmVsZWFzZVRlbnNvcnNGb3JTZXNzaW9uKHNlc3Npb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCB0ZW5zb3Igb2YgdGhpcy5mcmVlVGVuc29ycykge1xuICAgICAgaWYgKHRlbnNvci5zZXNzaW9uSWQgPT09IHNlc3Npb25JZCkge1xuICAgICAgICB0ZW5zb3IuZGVzdHJveSgpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmZyZWVUZW5zb3JzID0gdGhpcy5mcmVlVGVuc29ycy5maWx0ZXIoKHRlbnNvcikgPT4gdGVuc29yLnNlc3Npb25JZCAhPT0gc2Vzc2lvbklkKTtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3RlclRlbnNvcihcbiAgICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgICBtbFRlbnNvcjogTUxUZW5zb3IsXG4gICAgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlLFxuICAgIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogVGVuc29ySWQge1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmdldE1MQ29udGV4dChzZXNzaW9uSWQpO1xuICAgIGNvbnN0IHRlbnNvcklkID0gY3JlYXRlTmV3VGVuc29ySWQoKTtcbiAgICAvLyBEZWZhdWx0aW5nIHRvIFJFQUQgfCBXUklURSBpZiB1c2FnZSBpcyBub3QgcHJvdmlkZWQuXG4gICAgY29uc3Qgd3JhcHBlciA9IG5ldyBUZW5zb3JXcmFwcGVyKHtcbiAgICAgIHNlc3Npb25JZCxcbiAgICAgIGNvbnRleHQsXG4gICAgICB0ZW5zb3I6IG1sVGVuc29yLFxuICAgICAgZGF0YVR5cGUsXG4gICAgICBzaGFwZSxcbiAgICB9KTtcbiAgICB0aGlzLnRlbnNvclRyYWNrZXJzQnlJZC5zZXQodGVuc29ySWQsIG5ldyBUZW5zb3JJZFRyYWNrZXIodGhpcywgd3JhcHBlcikpO1xuICAgIHRoaXMuZXh0ZXJuYWxUZW5zb3JzLmFkZCh3cmFwcGVyKTtcbiAgICByZXR1cm4gdGVuc29ySWQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0IG9yIGNyZWF0ZSBhbiBNTFRlbnNvciB3aXRoIHRoZSBnaXZlbiBkYXRhIHR5cGUgYW5kIHNoYXBlLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGdldENhY2hlZFRlbnNvcihcbiAgICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgICBkYXRhVHlwZTogTUxPcGVyYW5kRGF0YVR5cGUsXG4gICAgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIHVzYWdlOiBNTFRlbnNvclVzYWdlRmxhZ3MgfCB1bmRlZmluZWQsXG4gICAgd3JpdGFibGU6IGJvb2xlYW4sXG4gICAgcmVhZGFibGU6IGJvb2xlYW4sXG4gICAgZmFsbGJhY2tEYXRhVHlwZT86IE1MT3BlcmFuZERhdGFUeXBlLFxuICApOiBQcm9taXNlPFRlbnNvcldyYXBwZXI+IHtcbiAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5nZXRNTENvbnRleHQoc2Vzc2lvbklkKTtcbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgdGVuc29yXSBvZiB0aGlzLmZyZWVUZW5zb3JzLmVudHJpZXMoKSkge1xuICAgICAgaWYgKHRlbnNvci5jYW5SZXVzZVRlbnNvcihjb250ZXh0LCBkYXRhVHlwZSwgc2hhcGUpKSB7XG4gICAgICAgIExPR19ERUJVRyhcbiAgICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgIGBbV2ViTk5dIFJldXNpbmcgdGVuc29yIHtkYXRhVHlwZTogJHtkYXRhVHlwZX0sICR7XG4gICAgICAgICAgICAgIGZhbGxiYWNrRGF0YVR5cGUgPyBgZmFsbGJhY2tEYXRhVHlwZTogJHtmYWxsYmFja0RhdGFUeXBlfSxgIDogJydcbiAgICAgICAgICAgIH0gc2hhcGU6ICR7c2hhcGV9YCxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgd3JhcHBlciA9IHRoaXMuZnJlZVRlbnNvcnMuc3BsaWNlKGluZGV4LCAxKVswXTtcbiAgICAgICAgd3JhcHBlci5zZXNzaW9uSWQgPSBzZXNzaW9uSWQ7XG4gICAgICAgIHJldHVybiB3cmFwcGVyO1xuICAgICAgfVxuICAgIH1cbiAgICBMT0dfREVCVUcoXG4gICAgICAndmVyYm9zZScsXG4gICAgICAoKSA9PlxuICAgICAgICBgW1dlYk5OXSBNTENvbnRleHQuY3JlYXRlVGVuc29yIHtkYXRhVHlwZTogJHtkYXRhVHlwZX0sICR7XG4gICAgICAgICAgZmFsbGJhY2tEYXRhVHlwZSA/IGBmYWxsYmFja0RhdGFUeXBlOiAke2ZhbGxiYWNrRGF0YVR5cGV9LGAgOiAnJ1xuICAgICAgICB9IHNoYXBlOiAke3NoYXBlfX1gLFxuICAgICk7XG4gICAgY29uc3QgdGVuc29yID0gYXdhaXQgY29udGV4dC5jcmVhdGVUZW5zb3Ioe1xuICAgICAgZGF0YVR5cGU6IGZhbGxiYWNrRGF0YVR5cGUgPz8gZGF0YVR5cGUsIC8vIElmIGZhbGxiYWNrIGRhdGEgdHlwZSBpcyBwcm92aWRlZCwgdXNlIGl0LlxuICAgICAgc2hhcGUsXG4gICAgICBkaW1lbnNpb25zOiBzaGFwZSxcbiAgICAgIHVzYWdlLFxuICAgICAgd3JpdGFibGUsXG4gICAgICByZWFkYWJsZSxcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IFRlbnNvcldyYXBwZXIoeyBzZXNzaW9uSWQsIGNvbnRleHQsIHRlbnNvciwgZGF0YVR5cGUsIHNoYXBlLCBmYWxsYmFja0RhdGFUeXBlIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbGVhc2UgdGVuc29yIGZvciByZXVzZSB1bmxlc3MgZXh0ZXJuYWwuXG4gICAqL1xuICBwdWJsaWMgcmVsZWFzZVRlbnNvcih0ZW5zb3JXcmFwcGVyOiBUZW5zb3JXcmFwcGVyKSB7XG4gICAgaWYgKHRoaXMuZXh0ZXJuYWxUZW5zb3JzLmhhcyh0ZW5zb3JXcmFwcGVyKSkge1xuICAgICAgdGhpcy5leHRlcm5hbFRlbnNvcnMuZGVsZXRlKHRlbnNvcldyYXBwZXIpO1xuICAgIH1cbiAgICB0aGlzLmZyZWVUZW5zb3JzLnB1c2godGVuc29yV3JhcHBlcik7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVRlbnNvck1hbmFnZXIgPSAoLi4uYXJnczogQ29uc3RydWN0b3JQYXJhbWV0ZXJzPHR5cGVvZiBUZW5zb3JNYW5hZ2VySW1wbD4pOiBUZW5zb3JNYW5hZ2VyID0+XG4gIG5ldyBUZW5zb3JNYW5hZ2VySW1wbCguLi5hcmdzKTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLy8gV2ViTk4gQVBJIGN1cnJlbnRseSBkb2VzIG5vdCBoYXZlIGEgVHlwZVNjcmlwdCBkZWZpbml0aW9uIGZpbGUuIFRoaXMgZmlsZSBpcyBhIHdvcmthcm91bmQgd2l0aCB0eXBlcyBnZW5lcmF0ZWQgZnJvbVxuLy8gV2ViTk4gQVBJIHNwZWNpZmljYXRpb24uXG4vLyBodHRwczovL2dpdGh1Yi5jb20vd2VibWFjaGluZWxlYXJuaW5nL3dlYm5uL2lzc3Vlcy82Nzdcbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJ3ZWJubi93ZWJubi5kLnRzXCIgLz5cblxuaW1wb3J0IHsgRW52LCBUZW5zb3IgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBEYXRhVHlwZSwgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0gfSBmcm9tICcuLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBnZXRJbnN0YW5jZSB9IGZyb20gJy4uL3dhc20tZmFjdG9yeSc7XG5cbmltcG9ydCB7IGNyZWF0ZVZpZXcgfSBmcm9tICcuL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFRlbnNvcklkLCBjcmVhdGVUZW5zb3JNYW5hZ2VyLCBjb252ZXJ0RGF0YVRvSW50MzIgfSBmcm9tICcuL3dlYm5uL3RlbnNvci1tYW5hZ2VyJztcbmltcG9ydCB7IGNvbmZpZ3VyZUxvZ2dlciwgTE9HX0RFQlVHIH0gZnJvbSAnLi9sb2cnO1xuXG4vKlxuICogVGVuc29yUHJvdG86OmRhdGFfdHlwZSB0byBXZWJOTiBPcGVyYW5kVHlwZSBtYXBwaW5nLlxuICovXG5jb25zdCBvbm54RGF0YVR5cGVUb1dlYm5uRGF0YVR5cGUgPSBuZXcgTWFwPERhdGFUeXBlLCBNTE9wZXJhbmREYXRhVHlwZT4oW1xuICBbRGF0YVR5cGUuZmxvYXQsICdmbG9hdDMyJ10sXG4gIFtEYXRhVHlwZS5mbG9hdDE2LCAnZmxvYXQxNiddLFxuICBbRGF0YVR5cGUuaW50MzIsICdpbnQzMiddLFxuICBbRGF0YVR5cGUudWludDMyLCAndWludDMyJ10sXG4gIFtEYXRhVHlwZS5pbnQ2NCwgJ2ludDY0J10sXG4gIFtEYXRhVHlwZS51aW50NjQsICd1aW50NjQnXSxcbiAgW0RhdGFUeXBlLmludDQsICdpbnQ0J10sXG4gIFtEYXRhVHlwZS51aW50NCwgJ3VpbnQ0J10sXG4gIFtEYXRhVHlwZS5pbnQ4LCAnaW50OCddLFxuICBbRGF0YVR5cGUudWludDgsICd1aW50OCddLFxuICBbRGF0YVR5cGUuYm9vbCwgJ3VpbnQ4J10sXG5dKTtcblxudHlwZSBNTENvbnRleHRFbnRyeSA9IHtcbiAgZ3B1RGV2aWNlPzogR1BVRGV2aWNlO1xuICBvcHRpb25zPzogTUxDb250ZXh0T3B0aW9ucztcbiAgbWxDb250ZXh0OiBNTENvbnRleHQ7XG59O1xuXG5jb25zdCBjb21wYXJlTUxDb250ZXh0T3B0aW9ucyA9IChhPzogTUxDb250ZXh0T3B0aW9ucywgYj86IE1MQ29udGV4dE9wdGlvbnMpOiBib29sZWFuID0+IHtcbiAgaWYgKGEgPT09IGIpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBpZiAoYSA9PT0gdW5kZWZpbmVkIHx8IGIgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBjb25zdCBhS2V5cyA9IE9iamVjdC5rZXlzKGEpLnNvcnQoKSBhcyBBcnJheTxrZXlvZiB0eXBlb2YgYT47XG4gIGNvbnN0IGJLZXlzID0gT2JqZWN0LmtleXMoYikuc29ydCgpIGFzIEFycmF5PGtleW9mIHR5cGVvZiBiPjtcbiAgcmV0dXJuIGFLZXlzLmxlbmd0aCA9PT0gYktleXMubGVuZ3RoICYmIGFLZXlzLmV2ZXJ5KChrZXksIGluZGV4KSA9PiBrZXkgPT09IGJLZXlzW2luZGV4XSAmJiBhW2tleV0gPT09IGJba2V5XSk7XG59O1xuXG4vKipcbiAqIFdlYk5OIGJhY2tlbmQgaW1wbGVtZW50YXRpb24uIFRoaXMgY2xhc3MgaXMgdXNlZCB0byBrZWVwIHRyYWNrIG9mIHRoZSBNTFRlbnNvcnMgY3JlYXRlZCBieSB0aGUgYmFja2VuZCBhbmQga2VlcCB0cmFja1xuICogb2YgdGhlIGN1cnJlbnQgTUxDb250ZXh0IGJlaW5nIHVzZWQgYnkgdGhlIHNlc3Npb25zLlxuICovXG5leHBvcnQgY2xhc3MgV2ViTk5CYWNrZW5kIHtcbiAgLyoqXG4gICAqIFRlbnNvciBtYW5hZ2VycyBmb3IgZWFjaCBzZXNzaW9uLlxuICAgKi9cbiAgcHJpdmF0ZSB0ZW5zb3JNYW5hZ2VyID0gY3JlYXRlVGVuc29yTWFuYWdlcih0aGlzKTtcbiAgLyoqXG4gICAqIE1hcHMgZnJvbSBzZXNzaW9uIGlkIHRvIE1MQ29udGV4dHMuXG4gICAqL1xuICBwcml2YXRlIG1sQ29udGV4dEJ5U2Vzc2lvbklkID0gbmV3IE1hcDxudW1iZXIsIE1MQ29udGV4dD4oKTtcbiAgLyoqXG4gICAqIE1hcHMgZnJvbSBNTENvbnRleHQgdG8gc2Vzc2lvbiBpZHMuXG4gICAqL1xuICBwcml2YXRlIHNlc3Npb25JZHNCeU1MQ29udGV4dCA9IG5ldyBNYXA8TUxDb250ZXh0LCBTZXQ8bnVtYmVyPj4oKTtcbiAgLyoqXG4gICAqIENhY2hlIG9mIE1MQ29udGV4dHMuXG4gICAqL1xuICBwcml2YXRlIG1sQ29udGV4dENhY2hlOiBNTENvbnRleHRFbnRyeVtdID0gW107XG4gIC8qKlxuICAgKiBDdXJyZW50IHNlc3Npb24gaWQuXG4gICAqL1xuICBwcml2YXRlIGFjdGl2ZVNlc3Npb25JZD86IG51bWJlcjtcbiAgLyoqXG4gICAqIE1hcHMgZnJvbSBzZXNzaW9uIGlkIHRvIGxpc3Qgb2YgZ3JhcGggaW5wdXRzLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXNzaW9uR3JhcGhJbnB1dHM6IE1hcDxudW1iZXIsIHN0cmluZ1tdPiA9IG5ldyBNYXAoKTtcbiAgLyoqXG4gICAqIE1hcHMgZnJvbSBzZXNzaW9uIGlkIHRvIGxpc3Qgb2YgZ3JhcGggb3V0cHV0cy5cbiAgICovXG4gIHByaXZhdGUgc2Vzc2lvbkdyYXBoT3V0cHV0czogTWFwPG51bWJlciwgc3RyaW5nW10+ID0gbmV3IE1hcCgpO1xuICAvKipcbiAgICogVGVtcG9yYXJ5IGdyYXBoIGlucHV0cyBmb3IgdGhlIGN1cnJlbnQgc2Vzc2lvbi5cbiAgICogVGhlc2UgaW5wdXRzIHdpbGwgYmUgcmVnaXN0ZXJlZCB3aGVuIHRoZSBzZXNzaW9uIGlzIGNyZWF0ZWQuXG4gICAqL1xuICBwcml2YXRlIHRlbXBvcmFyeUdyYXBoSW5wdXRzOiBzdHJpbmdbXSA9IFtdO1xuICAvKipcbiAgICogVGVtcG9yYXJ5IGdyYXBoIG91dHB1dHMgZm9yIHRoZSBjdXJyZW50IHNlc3Npb24uXG4gICAqIFRoZXNlIG91dHB1dHMgd2lsbCBiZSByZWdpc3RlcmVkIHdoZW4gdGhlIHNlc3Npb24gaXMgY3JlYXRlZC5cbiAgICovXG4gIHByaXZhdGUgdGVtcG9yYXJ5R3JhcGhPdXRwdXRzOiBzdHJpbmdbXSA9IFtdO1xuICAvKipcbiAgICogVGVtcG9yYXJ5IHRlbnNvcnMgZm9yIHRoZSBjdXJyZW50IHNlc3Npb24uXG4gICAqL1xuICBwcml2YXRlIHRlbXBvcmFyeVNlc3Npb25UZW5zb3JJZHM6IE1hcDxudW1iZXIsIFRlbnNvcklkW10+ID0gbmV3IE1hcCgpO1xuICAvKipcbiAgICogTWFwcyBmcm9tIHNlc3Npb24gaWQgdG8gTUxPcFN1cHBvcnRMaW1pdHMuXG4gICAqL1xuICBwcml2YXRlIG1sT3BTdXBwb3J0TGltaXRzQnlTZXNzaW9uSWQgPSBuZXcgTWFwPG51bWJlciwgTUxPcFN1cHBvcnRMaW1pdHM+KCk7XG5cbiAgY29uc3RydWN0b3IoZW52OiBFbnYpIHtcbiAgICBjb25maWd1cmVMb2dnZXIoZW52LmxvZ0xldmVsISwgISFlbnYuZGVidWcpO1xuICB9XG5cbiAgcHVibGljIGdldCBjdXJyZW50U2Vzc2lvbklkKCk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuYWN0aXZlU2Vzc2lvbklkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYWN0aXZlIHNlc3Npb24nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYWN0aXZlU2Vzc2lvbklkO1xuICB9XG5cbiAgcHVibGljIG9uUnVuU3RhcnQoc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYk5OXSBvblJ1blN0YXJ0IHtzZXNzaW9uSWQ6ICR7c2Vzc2lvbklkfX1gKTtcbiAgICB0aGlzLmFjdGl2ZVNlc3Npb25JZCA9IHNlc3Npb25JZDtcbiAgfVxuXG4gIHB1YmxpYyBvblJ1bkVuZChzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViTk5dIG9uUnVuRW5kIHtzZXNzaW9uSWQ6ICR7c2Vzc2lvbklkfX1gKTtcbiAgICBjb25zdCB0ZW5zb3JJZHMgPSB0aGlzLnRlbXBvcmFyeVNlc3Npb25UZW5zb3JJZHMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCF0ZW5zb3JJZHMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCB0ZW5zb3JJZCBvZiB0ZW5zb3JJZHMpIHtcbiAgICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViTk5dIHJlbGVhc2luZyB0ZW1wb3JhcnkgdGVuc29yIHt0ZW5zb3JJZDogJHt0ZW5zb3JJZH19YCk7XG4gICAgICB0aGlzLnRlbnNvck1hbmFnZXIucmVsZWFzZVRlbnNvcklkKHRlbnNvcklkKTtcbiAgICB9XG4gICAgdGhpcy50ZW1wb3JhcnlTZXNzaW9uVGVuc29ySWRzLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIHRoaXMuYWN0aXZlU2Vzc2lvbklkID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGNyZWF0ZU1MQ29udGV4dChvcHRpb25zT3JEZXZpY2U/OiBNTENvbnRleHRPcHRpb25zIHwgR1BVRGV2aWNlKTogUHJvbWlzZTxNTENvbnRleHQ+IHtcbiAgICBpZiAob3B0aW9uc09yRGV2aWNlIGluc3RhbmNlb2YgR1BVRGV2aWNlKSB7XG4gICAgICBjb25zdCBtbENvbnRleHRJbmRleCA9IHRoaXMubWxDb250ZXh0Q2FjaGUuZmluZEluZGV4KChlbnRyeSkgPT4gZW50cnkuZ3B1RGV2aWNlID09PSBvcHRpb25zT3JEZXZpY2UpO1xuICAgICAgaWYgKG1sQ29udGV4dEluZGV4ICE9PSAtMSkge1xuICAgICAgICByZXR1cm4gdGhpcy5tbENvbnRleHRDYWNoZVttbENvbnRleHRJbmRleF0ubWxDb250ZXh0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgbWxDb250ZXh0ID0gYXdhaXQgbmF2aWdhdG9yLm1sLmNyZWF0ZUNvbnRleHQob3B0aW9uc09yRGV2aWNlKTtcbiAgICAgICAgdGhpcy5tbENvbnRleHRDYWNoZS5wdXNoKHsgZ3B1RGV2aWNlOiBvcHRpb25zT3JEZXZpY2UsIG1sQ29udGV4dCB9KTtcbiAgICAgICAgcmV0dXJuIG1sQ29udGV4dDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG9wdGlvbnNPckRldmljZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBtbENvbnRleHRJbmRleCA9IHRoaXMubWxDb250ZXh0Q2FjaGUuZmluZEluZGV4KFxuICAgICAgICAoZW50cnkpID0+IGVudHJ5Lm9wdGlvbnMgPT09IHVuZGVmaW5lZCAmJiBlbnRyeS5ncHVEZXZpY2UgPT09IHVuZGVmaW5lZCxcbiAgICAgICk7XG4gICAgICBpZiAobWxDb250ZXh0SW5kZXggIT09IC0xKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1sQ29udGV4dENhY2hlW21sQ29udGV4dEluZGV4XS5tbENvbnRleHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBtbENvbnRleHQgPSBhd2FpdCBuYXZpZ2F0b3IubWwuY3JlYXRlQ29udGV4dCgpO1xuICAgICAgICB0aGlzLm1sQ29udGV4dENhY2hlLnB1c2goeyBtbENvbnRleHQgfSk7XG4gICAgICAgIHJldHVybiBtbENvbnRleHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbWxDb250ZXh0SW5kZXggPSB0aGlzLm1sQ29udGV4dENhY2hlLmZpbmRJbmRleCgoZW50cnkpID0+XG4gICAgICBjb21wYXJlTUxDb250ZXh0T3B0aW9ucyhlbnRyeS5vcHRpb25zLCBvcHRpb25zT3JEZXZpY2UpLFxuICAgICk7XG4gICAgaWYgKG1sQ29udGV4dEluZGV4ICE9PSAtMSkge1xuICAgICAgcmV0dXJuIHRoaXMubWxDb250ZXh0Q2FjaGVbbWxDb250ZXh0SW5kZXhdLm1sQ29udGV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgbWxDb250ZXh0ID0gYXdhaXQgbmF2aWdhdG9yLm1sLmNyZWF0ZUNvbnRleHQob3B0aW9uc09yRGV2aWNlKTtcbiAgICAgIHRoaXMubWxDb250ZXh0Q2FjaGUucHVzaCh7IG9wdGlvbnM6IG9wdGlvbnNPckRldmljZSwgbWxDb250ZXh0IH0pO1xuICAgICAgcmV0dXJuIG1sQ29udGV4dDtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcmVnaXN0ZXJNTENvbnRleHQoc2Vzc2lvbklkOiBudW1iZXIsIG1sQ29udGV4dDogTUxDb250ZXh0KTogdm9pZCB7XG4gICAgdGhpcy5tbENvbnRleHRCeVNlc3Npb25JZC5zZXQoc2Vzc2lvbklkLCBtbENvbnRleHQpO1xuICAgIGxldCBzZXNzaW9uSWRzID0gdGhpcy5zZXNzaW9uSWRzQnlNTENvbnRleHQuZ2V0KG1sQ29udGV4dCk7XG4gICAgaWYgKCFzZXNzaW9uSWRzKSB7XG4gICAgICBzZXNzaW9uSWRzID0gbmV3IFNldCgpO1xuICAgICAgdGhpcy5zZXNzaW9uSWRzQnlNTENvbnRleHQuc2V0KG1sQ29udGV4dCwgc2Vzc2lvbklkcyk7XG4gICAgfVxuICAgIHNlc3Npb25JZHMuYWRkKHNlc3Npb25JZCk7XG5cbiAgICBpZiAoIXRoaXMubWxPcFN1cHBvcnRMaW1pdHNCeVNlc3Npb25JZC5oYXMoc2Vzc2lvbklkKSkge1xuICAgICAgdGhpcy5tbE9wU3VwcG9ydExpbWl0c0J5U2Vzc2lvbklkLnNldChzZXNzaW9uSWQsIG1sQ29udGV4dC5vcFN1cHBvcnRMaW1pdHMoKSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudGVtcG9yYXJ5R3JhcGhJbnB1dHMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5zZXNzaW9uR3JhcGhJbnB1dHMuc2V0KHNlc3Npb25JZCwgdGhpcy50ZW1wb3JhcnlHcmFwaElucHV0cyk7XG4gICAgICB0aGlzLnRlbXBvcmFyeUdyYXBoSW5wdXRzID0gW107XG4gICAgfVxuICAgIGlmICh0aGlzLnRlbXBvcmFyeUdyYXBoT3V0cHV0cy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnNlc3Npb25HcmFwaE91dHB1dHMuc2V0KHNlc3Npb25JZCwgdGhpcy50ZW1wb3JhcnlHcmFwaE91dHB1dHMpO1xuICAgICAgdGhpcy50ZW1wb3JhcnlHcmFwaE91dHB1dHMgPSBbXTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgb25SZWxlYXNlU2Vzc2lvbihzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuc2Vzc2lvbkdyYXBoSW5wdXRzLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIHRoaXMuc2Vzc2lvbkdyYXBoT3V0cHV0cy5kZWxldGUoc2Vzc2lvbklkKTtcbiAgICBjb25zdCBtbENvbnRleHQgPSB0aGlzLm1sQ29udGV4dEJ5U2Vzc2lvbklkLmdldChzZXNzaW9uSWQpITtcbiAgICBpZiAoIW1sQ29udGV4dCkge1xuICAgICAgLy8gQ3VycmVudCBzZXNzaW9uIGlzIG5vdCBhIFdlYk5OIHNlc3Npb24uXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMudGVuc29yTWFuYWdlci5yZWxlYXNlVGVuc29yc0ZvclNlc3Npb24oc2Vzc2lvbklkKTtcbiAgICB0aGlzLm1sQ29udGV4dEJ5U2Vzc2lvbklkLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIHRoaXMubWxPcFN1cHBvcnRMaW1pdHNCeVNlc3Npb25JZC5kZWxldGUoc2Vzc2lvbklkKTtcbiAgICBjb25zdCBzZXNzaW9uSWRzID0gdGhpcy5zZXNzaW9uSWRzQnlNTENvbnRleHQuZ2V0KG1sQ29udGV4dCkhO1xuICAgIHNlc3Npb25JZHMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgaWYgKHNlc3Npb25JZHMuc2l6ZSA9PT0gMCkge1xuICAgICAgdGhpcy5zZXNzaW9uSWRzQnlNTENvbnRleHQuZGVsZXRlKG1sQ29udGV4dCk7XG4gICAgICBjb25zdCBtbENvbnRleHRJbmRleCA9IHRoaXMubWxDb250ZXh0Q2FjaGUuZmluZEluZGV4KChlbnRyeSkgPT4gZW50cnkubWxDb250ZXh0ID09PSBtbENvbnRleHQpO1xuICAgICAgaWYgKG1sQ29udGV4dEluZGV4ICE9PSAtMSkge1xuICAgICAgICB0aGlzLm1sQ29udGV4dENhY2hlLnNwbGljZShtbENvbnRleHRJbmRleCwgMSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldE1MQ29udGV4dChzZXNzaW9uSWQ6IG51bWJlcik6IE1MQ29udGV4dCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMubWxDb250ZXh0QnlTZXNzaW9uSWQuZ2V0KHNlc3Npb25JZCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0TUxPcFN1cHBvcnRMaW1pdHMoc2Vzc2lvbklkOiBudW1iZXIpOiBNTE9wU3VwcG9ydExpbWl0cyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMubWxPcFN1cHBvcnRMaW1pdHNCeVNlc3Npb25JZC5nZXQoc2Vzc2lvbklkKTtcbiAgfVxuXG4gIHB1YmxpYyByZXNlcnZlVGVuc29ySWQoKTogVGVuc29ySWQge1xuICAgIHJldHVybiB0aGlzLnRlbnNvck1hbmFnZXIucmVzZXJ2ZVRlbnNvcklkKCk7XG4gIH1cblxuICBwdWJsaWMgcmVsZWFzZVRlbnNvcklkKHRlbnNvcklkOiBUZW5zb3JJZCk6IHZvaWQge1xuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViTk5dIHJlbGVhc2VUZW5zb3JJZCB7dGVuc29ySWQ6ICR7dGVuc29ySWR9fWApO1xuICAgIHRoaXMudGVuc29yTWFuYWdlci5yZWxlYXNlVGVuc29ySWQodGVuc29ySWQpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGVuc3VyZVRlbnNvcihcbiAgICBzZXNzaW9uSWQ6IG51bWJlciB8IHVuZGVmaW5lZCxcbiAgICB0ZW5zb3JJZDogVGVuc29ySWQsXG4gICAgb25ueERhdGFUeXBlOiBEYXRhVHlwZSxcbiAgICBkaW1lbnNpb25zOiBudW1iZXJbXSxcbiAgICBjb3B5T2xkOiBib29sZWFuLFxuICApOiBQcm9taXNlPE1MVGVuc29yPiB7XG4gICAgY29uc3Qgd2Vibm5EYXRhVHlwZSA9IG9ubnhEYXRhVHlwZVRvV2Vibm5EYXRhVHlwZS5nZXQob25ueERhdGFUeXBlKTtcbiAgICBpZiAoIXdlYm5uRGF0YVR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgT05OWCBkYXRhIHR5cGU6ICR7b25ueERhdGFUeXBlfWApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy50ZW5zb3JNYW5hZ2VyLmVuc3VyZVRlbnNvcihcbiAgICAgIHNlc3Npb25JZCA/PyB0aGlzLmN1cnJlbnRTZXNzaW9uSWQsXG4gICAgICB0ZW5zb3JJZCxcbiAgICAgIHdlYm5uRGF0YVR5cGUsXG4gICAgICBkaW1lbnNpb25zLFxuICAgICAgY29weU9sZCxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGNyZWF0ZVRlbXBvcmFyeVRlbnNvcihcbiAgICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgICBvbm54RGF0YVR5cGU6IERhdGFUeXBlLFxuICAgIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogUHJvbWlzZTxUZW5zb3JJZD4ge1xuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViTk5dIGNyZWF0ZVRlbXBvcmFyeVRlbnNvciB7b25ueERhdGFUeXBlOiAke29ubnhEYXRhVHlwZX0sIHNoYXBlOiAke3NoYXBlfX1gKTtcbiAgICBjb25zdCBkYXRhVHlwZSA9IG9ubnhEYXRhVHlwZVRvV2Vibm5EYXRhVHlwZS5nZXQob25ueERhdGFUeXBlKTtcbiAgICBpZiAoIWRhdGFUeXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIE9OTlggZGF0YSB0eXBlOiAke29ubnhEYXRhVHlwZX1gKTtcbiAgICB9XG4gICAgY29uc3QgdGVuc29ySWQgPSB0aGlzLnRlbnNvck1hbmFnZXIucmVzZXJ2ZVRlbnNvcklkKCk7XG4gICAgYXdhaXQgdGhpcy50ZW5zb3JNYW5hZ2VyLmVuc3VyZVRlbnNvcihzZXNzaW9uSWQsIHRlbnNvcklkLCBkYXRhVHlwZSwgc2hhcGUsIGZhbHNlKTtcbiAgICBjb25zdCB0ZW5zb3JJZHMgPSB0aGlzLnRlbXBvcmFyeVNlc3Npb25UZW5zb3JJZHMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCF0ZW5zb3JJZHMpIHtcbiAgICAgIHRoaXMudGVtcG9yYXJ5U2Vzc2lvblRlbnNvcklkcy5zZXQoc2Vzc2lvbklkLCBbdGVuc29ySWRdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGVuc29ySWRzLnB1c2godGVuc29ySWQpO1xuICAgIH1cbiAgICByZXR1cm4gdGVuc29ySWQ7XG4gIH1cblxuICBwdWJsaWMgdXBsb2FkVGVuc29yKHRlbnNvcklkOiBUZW5zb3JJZCwgZGF0YTogVWludDhBcnJheSk6IHZvaWQge1xuICAgIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICAgIGlmICghd2FzbS5zaG91bGRUcmFuc2ZlclRvTUxUZW5zb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVHJ5aW5nIHRvIHVwbG9hZCB0byBhIE1MVGVuc29yIHdoaWxlIHNob3VsZFRyYW5zZmVyVG9NTFRlbnNvciBpcyBmYWxzZScpO1xuICAgIH1cbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYk5OXSB1cGxvYWRUZW5zb3Ige3RlbnNvcklkOiAke3RlbnNvcklkfSwgZGF0YTogJHtkYXRhLmJ5dGVMZW5ndGh9fWApO1xuICAgIHRoaXMudGVuc29yTWFuYWdlci51cGxvYWQodGVuc29ySWQsIGRhdGEpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGRvd25sb2FkVGVuc29yKHRlbnNvcklkOiBUZW5zb3JJZCwgZHN0QnVmZmVyOiBBcnJheUJ1ZmZlclZpZXcgfCBBcnJheUJ1ZmZlcik6IFByb21pc2U8dW5kZWZpbmVkPiB7XG4gICAgcmV0dXJuIHRoaXMudGVuc29yTWFuYWdlci5kb3dubG9hZCh0ZW5zb3JJZCwgZHN0QnVmZmVyKTtcbiAgfVxuXG4gIHB1YmxpYyBjcmVhdGVNTFRlbnNvckRvd25sb2FkZXIodGVuc29ySWQ6IFRlbnNvcklkLCB0eXBlOiBUZW5zb3IuTUxUZW5zb3JEYXRhVHlwZXMpOiAoKSA9PiBQcm9taXNlPFRlbnNvci5EYXRhVHlwZT4ge1xuICAgIHJldHVybiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy50ZW5zb3JNYW5hZ2VyLmRvd25sb2FkKHRlbnNvcklkKTtcbiAgICAgIHJldHVybiBjcmVhdGVWaWV3KGRhdGEsIHR5cGUpO1xuICAgIH07XG4gIH1cblxuICBwdWJsaWMgcmVnaXN0ZXJNTFRlbnNvcihzZXNzaW9uSWQ6IG51bWJlciwgdGVuc29yOiBNTFRlbnNvciwgb25ueERhdGFUeXBlOiBEYXRhVHlwZSwgZGltZW5zaW9uczogbnVtYmVyW10pOiBUZW5zb3JJZCB7XG4gICAgY29uc3Qgd2Vibm5EYXRhVHlwZSA9IG9ubnhEYXRhVHlwZVRvV2Vibm5EYXRhVHlwZS5nZXQob25ueERhdGFUeXBlKTtcbiAgICBpZiAoIXdlYm5uRGF0YVR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgT05OWCBkYXRhIHR5cGU6ICR7b25ueERhdGFUeXBlfWApO1xuICAgIH1cblxuICAgIGNvbnN0IGlkID0gdGhpcy50ZW5zb3JNYW5hZ2VyLnJlZ2lzdGVyVGVuc29yKHNlc3Npb25JZCwgdGVuc29yLCB3ZWJubkRhdGFUeXBlLCBkaW1lbnNpb25zKTtcbiAgICBMT0dfREVCVUcoXG4gICAgICAndmVyYm9zZScsXG4gICAgICAoKSA9PlxuICAgICAgICBgW1dlYk5OXSByZWdpc3Rlck1MVGVuc29yIHt0ZW5zb3I6ICR7dGVuc29yfSwgZGF0YVR5cGU6ICR7d2Vibm5EYXRhVHlwZX0sIGRpbWVuc2lvbnM6ICR7XG4gICAgICAgICAgZGltZW5zaW9uc1xuICAgICAgICB9fSAtPiB7dGVuc29ySWQ6ICR7aWR9fWAsXG4gICAgKTtcbiAgICByZXR1cm4gaWQ7XG4gIH1cblxuICAvLyBSZWdpc3RlciBhIFdlYk5OIENvbnN0YW50IG9wZXJhbmQgZnJvbSBleHRlcm5hbCBkYXRhLlxuICBwdWJsaWMgcmVnaXN0ZXJNTENvbnN0YW50KFxuICAgIGV4dGVybmFsRmlsZVBhdGg6IHN0cmluZyxcbiAgICBkYXRhT2Zmc2V0OiBudW1iZXIsXG4gICAgZGF0YUxlbmd0aDogbnVtYmVyLFxuICAgIGJ1aWxkZXI6IE1MR3JhcGhCdWlsZGVyLFxuICAgIGRlc2M6IE1MT3BlcmFuZERlc2NyaXB0b3IsXG4gICAgbW91bnRlZEZpbGVzOiBNYXA8c3RyaW5nLCBVaW50OEFycmF5PiB8IHVuZGVmaW5lZCxcbiAgICBzaG91bGRDb252ZXJ0SW50NjRUb0ludDMyID0gZmFsc2UsXG4gICk6IE1MT3BlcmFuZCB7XG4gICAgLy8gSWYgYXZhaWxhYmxlLCBcIk1vZHVsZS5Nb3VudGVkRmlsZXNcIiBpcyBhIE1hcCBmb3IgYWxsIHByZWxvYWRlZCBmaWxlcy5cbiAgICBpZiAoIW1vdW50ZWRGaWxlcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHRlcm5hbCBtb3VudGVkIGZpbGVzIGFyZSBub3QgYXZhaWxhYmxlLicpO1xuICAgIH1cblxuICAgIGxldCBmaWxlUGF0aCA9IGV4dGVybmFsRmlsZVBhdGg7XG4gICAgaWYgKGV4dGVybmFsRmlsZVBhdGguc3RhcnRzV2l0aCgnLi8nKSkge1xuICAgICAgZmlsZVBhdGggPSBleHRlcm5hbEZpbGVQYXRoLnN1YnN0cmluZygyKTtcbiAgICB9XG4gICAgY29uc3QgZmlsZURhdGEgPSBtb3VudGVkRmlsZXMuZ2V0KGZpbGVQYXRoKTtcbiAgICBpZiAoIWZpbGVEYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZpbGUgd2l0aCBuYW1lICR7ZmlsZVBhdGh9IG5vdCBmb3VuZCBpbiBwcmVsb2FkZWQgZmlsZXMuYCk7XG4gICAgfVxuXG4gICAgaWYgKGRhdGFPZmZzZXQgKyBkYXRhTGVuZ3RoID4gZmlsZURhdGEuYnl0ZUxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdPdXQgb2YgYm91bmRzOiBkYXRhIG9mZnNldCBhbmQgbGVuZ3RoIGV4Y2VlZCB0aGUgZXh0ZXJuYWwgZmlsZSBkYXRhIHNpemUuJyk7XG4gICAgfVxuXG4gICAgY29uc3QgYnVmZmVyID0gZmlsZURhdGEuc2xpY2UoZGF0YU9mZnNldCwgZGF0YU9mZnNldCArIGRhdGFMZW5ndGgpLmJ1ZmZlcjtcbiAgICBsZXQgYnVmZmVyVmlldzogQXJyYXlCdWZmZXJWaWV3O1xuICAgIHN3aXRjaCAoZGVzYy5kYXRhVHlwZSkge1xuICAgICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICAgIGJ1ZmZlclZpZXcgPSBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZmxvYXQxNic6XG4gICAgICAgIGJ1ZmZlclZpZXcgPVxuICAgICAgICAgIHR5cGVvZiBGbG9hdDE2QXJyYXkgIT09ICd1bmRlZmluZWQnICYmIEZsb2F0MTZBcnJheS5mcm9tID8gbmV3IEZsb2F0MTZBcnJheShidWZmZXIpIDogbmV3IFVpbnQxNkFycmF5KGJ1ZmZlcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW50MzInOlxuICAgICAgICBidWZmZXJWaWV3ID0gbmV3IEludDMyQXJyYXkoYnVmZmVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd1aW50MzInOlxuICAgICAgICBidWZmZXJWaWV3ID0gbmV3IFVpbnQzMkFycmF5KGJ1ZmZlcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW50NjQnOlxuICAgICAgICBpZiAoc2hvdWxkQ29udmVydEludDY0VG9JbnQzMikge1xuICAgICAgICAgIC8vIEludDY0IGlzIG5vdCBzdXBwb3J0ZWQgYnkgY3VycmVudCBjb250ZXh0LCB1c2UgaW50MzIgaW5zdGVhZC5cbiAgICAgICAgICBjb25zdCBpbnQzMkJ1ZmZlciA9IGNvbnZlcnREYXRhVG9JbnQzMihuZXcgVWludDhBcnJheShidWZmZXIpLCAnaW50NjQnKTtcbiAgICAgICAgICBidWZmZXJWaWV3ID0gbmV3IEludDMyQXJyYXkoaW50MzJCdWZmZXIuYnVmZmVyKTtcbiAgICAgICAgICBkZXNjLmRhdGFUeXBlID0gJ2ludDMyJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBidWZmZXJWaWV3ID0gbmV3IEJpZ0ludDY0QXJyYXkoYnVmZmVyKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3VpbnQ2NCc6XG4gICAgICAgIGJ1ZmZlclZpZXcgPSBuZXcgQmlnVWludDY0QXJyYXkoYnVmZmVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpbnQ4JzpcbiAgICAgICAgYnVmZmVyVmlldyA9IG5ldyBJbnQ4QXJyYXkoYnVmZmVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpbnQ0JzpcbiAgICAgIGNhc2UgJ3VpbnQ0JzpcbiAgICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICAgICAgYnVmZmVyVmlldyA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZGVzYy5kYXRhVHlwZX0gaW4gY3JlYXRpbmcgV2ViTk4gQ29uc3RhbnQgZnJvbSBleHRlcm5hbCBkYXRhLmApO1xuICAgIH1cblxuICAgIExPR19ERUJVRyhcbiAgICAgICd2ZXJib3NlJyxcbiAgICAgICgpID0+XG4gICAgICAgIGBbV2ViTk5dIHJlZ2lzdGVyTUxDb25zdGFudCB7ZGF0YVR5cGU6ICR7ZGVzYy5kYXRhVHlwZX0sIHNoYXBlOiAke2Rlc2Muc2hhcGV9fX0gJHtcbiAgICAgICAgICBzaG91bGRDb252ZXJ0SW50NjRUb0ludDMyID8gJyhOb3RlOiBpdCB3YXMgaW50NjQgZGF0YSB0eXBlIGFuZCByZWdpc3RlcmVkIHRvIGludDMyIGFzIHdvcmthcm91bmQpJyA6ICcnXG4gICAgICAgIH1gLFxuICAgICk7XG5cbiAgICByZXR1cm4gYnVpbGRlci5jb25zdGFudChkZXNjLCBidWZmZXJWaWV3KTtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3RlckdyYXBoSW5wdXQoaW5wdXROYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnRlbXBvcmFyeUdyYXBoSW5wdXRzLnB1c2goaW5wdXROYW1lKTtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3RlckdyYXBoT3V0cHV0KG91dHB1dE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMudGVtcG9yYXJ5R3JhcGhPdXRwdXRzLnB1c2gob3V0cHV0TmFtZSk7XG4gIH1cblxuICBwdWJsaWMgaXNHcmFwaElucHV0KHNlc3Npb25JZDogbnVtYmVyLCBpbnB1dE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGlucHV0TmFtZXMgPSB0aGlzLnNlc3Npb25HcmFwaElucHV0cy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIWlucHV0TmFtZXMpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIGlucHV0TmFtZXMuaW5jbHVkZXMoaW5wdXROYW1lKTtcbiAgfVxuXG4gIHB1YmxpYyBpc0dyYXBoT3V0cHV0KHNlc3Npb25JZDogbnVtYmVyLCBvdXRwdXROYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBvdXRwdXROYW1lcyA9IHRoaXMuc2Vzc2lvbkdyYXBoT3V0cHV0cy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIW91dHB1dE5hbWVzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBvdXRwdXROYW1lcy5pbmNsdWRlcyhvdXRwdXROYW1lKTtcbiAgfVxuXG4gIHB1YmxpYyBpc0dyYXBoSW5wdXRPdXRwdXRUeXBlU3VwcG9ydGVkKHNlc3Npb25JZDogbnVtYmVyLCB0eXBlOiBUZW5zb3IuVHlwZSwgaXNJbnB1dCA9IHRydWUpOiBib29sZWFuIHtcbiAgICBjb25zdCBkYXRhVHlwZSA9IG9ubnhEYXRhVHlwZVRvV2Vibm5EYXRhVHlwZS5nZXQodGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0odHlwZSkpO1xuICAgIGNvbnN0IG9wTGltaXRzID0gdGhpcy5tbE9wU3VwcG9ydExpbWl0c0J5U2Vzc2lvbklkLmdldChzZXNzaW9uSWQpO1xuXG4gICAgaWYgKHR5cGVvZiBkYXRhVHlwZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoaXNJbnB1dCkge1xuICAgICAgcmV0dXJuICEhb3BMaW1pdHM/LmlucHV0LmRhdGFUeXBlcy5pbmNsdWRlcyhkYXRhVHlwZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAhIW9wTGltaXRzPy5vdXRwdXQuZGF0YVR5cGVzLmluY2x1ZGVzKGRhdGFUeXBlKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZmx1c2goKTogdm9pZCB7XG4gICAgLy8gVW5saWtlIHRoZSBXZWJHUFUgYmFja2VuZCwgdGhlIFdlYk5OIGJhY2tlbmQgZG9lcyBub3QgbmVlZCB0byBmbHVzaCBhbnkgcGVuZGluZyBvcGVyYXRpb25zLlxuICB9XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uL3RlbnNvci12aWV3JztcblxuaW1wb3J0IHsgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9vcHMvY29tbW9uJztcblxuZXhwb3J0IHR5cGUgU2Vzc2lvblN0YXRlID0gJ2RlZmF1bHQnIHwgJ2NhcHR1cmluZycgfCAncmVwbGF5aW5nJztcblxuZXhwb3J0IGVudW0gR3B1RGF0YVR5cGUge1xuICBkZWZhdWx0ID0gMCxcbiAgdXBsb2FkID0gMSxcbiAgcHJvZmlsZSA9IDIsXG59XG5leHBvcnQgdHlwZSBHcHVEYXRhSWQgPSBudW1iZXI7XG5cbmV4cG9ydCB0eXBlIEdwdUFyY2hpdGVjdHVyZSA9ICdhbXBlcmUnIHwgJ2dlbi0xMmxwJztcbmV4cG9ydCB0eXBlIEdwdVZlbmRvciA9ICdhbWQnIHwgJ2ludGVsJyB8ICdudmlkaWEnO1xuZXhwb3J0IGludGVyZmFjZSBBZGFwdGVySW5mbyB7XG4gIGlzQXJjaGl0ZWN0dXJlOiAoYXJjaGl0ZWN0dXJlOiBHcHVBcmNoaXRlY3R1cmUpID0+IGJvb2xlYW47XG4gIGlzVmVuZG9yOiAodmVuZG9yOiBHcHVWZW5kb3IpID0+IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR3B1RGF0YSB7XG4gIHR5cGU6IEdwdURhdGFUeXBlO1xuICBpZDogR3B1RGF0YUlkO1xuICBidWZmZXI6IEdQVUJ1ZmZlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JJbmZvIHtcbiAgZGltczogcmVhZG9ubHkgbnVtYmVyW107XG4gIGRhdGFUeXBlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJvZ3JhbVVuaWZvcm0ge1xuICB0eXBlOiBEYXRhVHlwZTtcbiAgZGF0YTogbnVtYmVyIHwgcmVhZG9ubHkgbnVtYmVyW107XG59XG5cbmV4cG9ydCB0eXBlIFByb2dyYW1Vbmlmb3JtVmFyaWFibGVJbmZvID0gW3R5cGU6IERhdGFUeXBlLCBsZW5ndGg6IG51bWJlcl07XG5cbi8qKlxuICogUmVwcmVzZW50IHRoZSBkZXBlbmRlbmN5IG9mIGEgcHJvZ3JhbSBvbiBhIHNwZWNpZmljIGlucHV0IHRlbnNvci5cbiAqXG4gKiAtICdub25lJzogdGhlIHNoYWRlci91bmlmb3JtIGRvZXMgbm90IGRlcGVuZCBvbiB0aGlzIGlucHV0J3MgaW5mb1xuICogLSAndHlwZSc6IHRoZSBzaGFkZXIvdW5pZm9ybSBkZXBlbmRzIG9uIGRhdGEgdHlwZSBvZiB0aGlzIGlucHV0XG4gKiAtICdyYW5rJzogdGhlIHNoYWRlci91bmlmb3JtIGRlcGVuZHMgb24gZGF0YSB0eXBlIGFuZCB0aGUgcmFuayBvZiB0aGlzIGlucHV0XG4gKiAtICdkaW1zJzogdGhlIHNoYWRlci91bmlmb3JtIGRlcGVuZHMgb24gZGF0YSB0eXBlIGFuZCB0aGUgZGltcyBvZiB0aGlzIGlucHV0XG4gKiAtICdkYXRhJzogdGhlIHNoYWRlci91bmlmb3JtIGRlcGVuZHMgb24gZGF0YSB0eXBlLCB0aGUgZGltcyBhbmQgdGhlIGRhdGEgb2YgdGhpcyBpbnB1dFxuICovXG5leHBvcnQgdHlwZSBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSA9ICdub25lJyB8ICd0eXBlJyB8ICdyYW5rJyB8ICdkaW1zJyB8ICdkYXRhJztcblxuLyoqXG4gKiBSZXByZXNlbnQgaW5mb3JtYXRpb24gYWJvdXQgYSBwcm9ncmFtJ3MgY2FjaGUgZm9yIHNoYWRlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm9ncmFtU2hhZGVyQ2FjaGVJbmZvIHtcbiAgLyoqXG4gICAqIGFuIG9wdGlvbmFsIHN0cmluZyBhcyBhIGNhY2hlIGhpbnQgaW4gdGhlIGFydGlmYWN0IGNhY2hlLiBJZiB0aGlzIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBjYWNoZSBoaW50IHdpbGwgYmUgZW1wdHkuXG4gICAqXG4gICAqIFRoaXMgaGludCBzdHJpbmcgc2hvdWxkIG9ubHkgY29udGFpbnMgaW5pdGlhbGl6aW5nLXRpbWUgaW5mb3JtYXRpb24sIHN1Y2ggYXMgdGhlIGF0dHJpYnV0ZXMgb3IgYW55IGluZm9ybWF0aW9uIG9mXG4gICAqIGluaXRpYWxpemVycy4gSXQgc2hvdWxkIE5PVCBjb250YWluIGFueSBydW50aW1lIGluZm9ybWF0aW9uLCBzdWNoIGFzIHRoZSBzaGFwZSBvZiBpbnB1dHMuXG4gICAqL1xuICBoaW50Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBhbiBvcHRpb25hbCBsaXN0IG9mIGRlcGVuZGVuY2llcyBvZiB0aGUgcHJvZ3JhbSBvbiB0aGUgaW5wdXQgdGVuc29ycy4gSWYgdGhpcyBpcyBub3Qgc3BlY2lmaWVkLCB0aGUgcHJvZ3JhbSBkZXBlbmRzXG4gICAqIG9uICdkaW1zJyBvZiBhbGwgaW5wdXRzLlxuICAgKi9cbiAgaW5wdXREZXBlbmRlbmNpZXM/OiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudCBpbmZvcm1hdGlvbiBhYm91dCBhIHByb2dyYW0ncyBjYWNoZSBmb3IgdW5pZm9ybS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm9ncmFtVW5pZm9ybUNhY2hlSW5mbyB7XG4gIC8qKlxuICAgKiBhbiBvcHRpb25hbCBzdHJpbmcgYXMgYSBjYWNoZSBoaW50IGluIHRoZSB1bmlmb3JtIGNhY2hlLiBJZiB0aGlzIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBjYWNoZSBoaW50IHdpbGwgYmUgZW1wdHkuXG4gICAqXG4gICAqIFRoaXMgaGludCBzdHJpbmcgc2hvdWxkIG9ubHkgY29udGFpbnMgcnVudGltZSBpbmZvcm1hdGlvbiwgc3VjaCBhcyB0aGUgc2hhcGUgb2YgaW5wdXRzLlxuICAgKi9cbiAgaGludD86IHN0cmluZztcblxuICAvKipcbiAgICogYW4gb3B0aW9uYWwgbGlzdCBvZiBkZXBlbmRlbmNpZXMgb2YgdGhlIHByb2dyYW0gb24gdGhlIGlucHV0IHRlbnNvcnMuIElmIHRoaXMgaXMgbm90IHNwZWNpZmllZCwgdGhlIHByb2dyYW0gZGVwZW5kc1xuICAgKiBvbiAnbm9uZScgb2YgYWxsIGlucHV0cy5cbiAgICovXG4gIGlucHV0RGVwZW5kZW5jaWVzPzogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXTtcbn1cblxuLyoqXG4gKiBBIHNldCBvZiBkYXRhIHRoYXQgcmVwcmVzZW50IGEgc2hhZGVyIHByb2dyYW1cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm9ncmFtSW5mbyB7XG4gIC8qKlxuICAgKiB0aGUgbmFtZSBvZiB0aGUgcHJvZ3JhbS4gdXNlZCBmb3IgZGVidWdnaW5nIGFuZCBwcm9maWxpbmdcbiAgICovXG4gIG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogYW4gb3B0aW9uYWwgb2JqZWN0IGRlc2NyaWJpbmcgdGhlIGNhY2hlIGluZm9ybWF0aW9uIG9mIHRoZSBwcm9ncmFtIHNoYWRlci5cbiAgICpcbiAgICogSWYgdGhpcyBpcyBub3Qgc3BlY2lmaWVkLCBhc3N1bWUgaGludCBpcyBlbXB0eSBhbmQgaW5wdXREZXBlbmRlbmNpZXMgYXJlIFsnZGltcyddIGZvciBhbGwgaW5wdXRzLlxuICAgKi9cbiAgc2hhZGVyQ2FjaGU/OiBQcm9ncmFtU2hhZGVyQ2FjaGVJbmZvO1xuXG4gIC8qKlxuICAgKiB0aGUgc2hhZGVyJ3MgcHJvY2Vzc2luZyBzb3VyY2UgY29kZS5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCB3aGVuIHNoYWRlciBjYWNoZSBtaXNzZWQuXG4gICAqL1xuICBnZXRTaGFkZXJTb3VyY2U6IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIGZ1bmN0aW9uIHRvIGdldCBydW4gZGF0YSByZXF1aXJlZCB0byBydW4gdGhlIHByb2dyYW0uXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgZXZlcnkgdGltZSB0aGUgcHJvZ3JhbSBpcyBleGVjdXRlZC4gU2hvdWxkIGtlZXAgdGhpcyBmdW5jdGlvbiBhcyBzaW1wbGUgYXMgcG9zc2libGUuXG4gICAqL1xuICBnZXRSdW5EYXRhOiAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pID0+IHtcbiAgICBvdXRwdXRzOiByZWFkb25seSBUZW5zb3JJbmZvW107XG4gICAgZGlzcGF0Y2hHcm91cDogeyB4OiBudW1iZXI7IHk/OiBudW1iZXI7IHo/OiBudW1iZXIgfTtcbiAgICBwcm9ncmFtVW5pZm9ybXM/OiByZWFkb25seSBQcm9ncmFtVW5pZm9ybVtdO1xuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFydGlmYWN0IHtcbiAgcHJvZ3JhbUluZm86IFByb2dyYW1JbmZvO1xuICBjb21wdXRlUGlwZWxpbmU6IEdQVUNvbXB1dGVQaXBlbGluZTtcbiAgdW5pZm9ybVZhcmlhYmxlc0luZm86IHJlYWRvbmx5IFByb2dyYW1Vbmlmb3JtVmFyaWFibGVJbmZvW10gfCB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHV0ZUNvbnRleHRJbnB1dHNPdXRwdXRzTWFwcGluZyB7XG4gIC8qKlxuICAgKiBzcGVjaWZ5IHRoZSBtYXBwaW5nIHRvIHRoZSBwcm9ncmFtJ3MgaW5wdXRzLiB0aGUgdmFsdWUgY2FuIGJlIGEgbnVtYmVyIG9yIGEgdGVuc29yIHZpZXcuXG4gICAqIC0gaWYgaXQncyBhIG51bWJlciwgaXQncyB0aGUgaW5kZXggb2YgdGhlIGtlcm5lbCdzIGlucHV0XG4gICAqIC0gaWYgaXQncyBhIHRlbnNvciB2aWV3LCBpdCdzIGFuIGV4aXN0aW5nIHRlbnNvciB2aWV3IHRoYXQgd2lsbCBiZSB1c2VkIGFzIHRoZSBpbnB1dFxuICAgKlxuICAgKiBpZiBpbnB1dHMgaXMgbm90IHNwZWNpZmllZCwgdGhlIG1hcHBpbmcgd2lsbCBiZSB0aGUga2VybmVsJ3MgaW5wdXRzIGluIG9yZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5wdXRzPzogUmVhZG9ubHlBcnJheTxUZW5zb3JWaWV3IHwgbnVtYmVyPjtcbiAgLyoqXG4gICAqIHNwZWNpZnkgdGhlIG1hcHBpbmcgdG8gdGhlIHByb2dyYW0ncyBvdXRwdXRzLiB0aGUgdmFsdWUgbXVzdCBiZSBhIG51bWJlci5cbiAgICogLSBpZiBpdCdzIGEgbm9uLW5lZ2F0aXZlIG51bWJlciwgaXQncyB0aGUgaW5kZXggb2YgdGhlIGtlcm5lbCdzIG91dHB1dFxuICAgKiAtIGlmIGl0J3MgLTEsIGl0J3MgYW4gb3V0cHV0IHRoYXQgd2lsbCBiZSBjcmVhdGVkIGFzIGEgdGVtcG9yYXJ5IHZhbHVlLiB0aGlzIHZhbHVlIHdpbGwgYmUgcmVsZWFzZWQgYWZ0ZXJcbiAgICogdGhlIGtlcm5lbCBpcyBleGVjdXRlZC5cbiAgICogLSBpZiBpdCdzIC0yLCBpdCdzIGFuIG91dHB1dCB0aGF0IHdpbGwgYmUgY3JlYXRlZCBhcyBhIHBlcnNpc3RlbnQgdmFsdWUuIHRoaXMgdmFsdWUgd2lsbCBiZSByZWxlYXNlZCB3aGVuIHRoZVxuICAgKiBrZXJuZWwgaXMgcmVsZWFzZWQuXG4gICAqXG4gICAqIGlmIG91dHB1dHMgaXMgbm90IHNwZWNpZmllZCwgdGhlIG1hcHBpbmcgd2lsbCBiZSB0aGUga2VybmVsJ3Mgb3V0cHV0cyBpbiBvcmRlci5cbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dHM/OiByZWFkb25seSBudW1iZXJbXTtcbn1cblxuLyoqXG4gKiBBIENvbXB1dGVDb250ZXh0IGluc3RhbmNlIGNhcnJpZXMgdGhlIHN0YXRlcyB0aGF0IHJlcHJlc2VudGluZyB0aGUgY3VycmVudCBydW5uaW5nIG9mIGEga2VybmVsLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbXB1dGVDb250ZXh0IHtcbiAgLyoqXG4gICAqIGdwdSBhZGFwdGVyIGluZm9cbiAgICovXG4gIHJlYWRvbmx5IGFkYXB0ZXJJbmZvOiBBZGFwdGVySW5mbztcblxuICAvKipcbiAgICogc3RvcmVzIHRoZSBwb2ludGVyIHRvIE9wS2VybmVsQ29udGV4dFxuICAgKi9cbiAgcmVhZG9ubHkgb3BLZXJuZWxDb250ZXh0OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIGEgbGlzdCBvZiBpbnB1dHMsIGVhY2ggaW5wdXQgaXMgYW4gaW5zdGFuY2Ugb2YgVGVuc29yVmlld1xuICAgKi9cbiAgcmVhZG9ubHkgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W107XG5cbiAgLyoqXG4gICAqIGEgY3VzdG9tIGRhdGEgb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gc3RvcmUgYW55IGRhdGEgdGhhdCBpcyBuZWVkZWQgYnkgdGhlIGtlcm5lbFxuICAgKi9cbiAgcmVhZG9ubHkga2VybmVsQ3VzdG9tRGF0YTogeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH07XG5cbiAgLyoqXG4gICAqIGEgYnVmZmVyIHRoYXQgY2FuIGJlIHVzZWQgdG8gYWNjZXNzIGN1c3RvbSBkYXRhIGNyZWF0ZWQgZWFjaCB0aW1lIHRoZSBrZXJuZWwgaXMgZXhlY3V0ZWRcbiAgICovXG4gIHJlYWRvbmx5IGN1c3RvbURhdGFCdWZmZXI6IFVpbnQ4QXJyYXk7XG5cbiAgLyoqXG4gICAqIGEgbnVtYmVyIG9mIG91dHB1dHMgZm9yIHRoZSBub2RlXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRDb3VudDogbnVtYmVyO1xuXG4gIGNvbXB1dGUocHJvZ3JhbTogUHJvZ3JhbUluZm8sIGlucHV0c091dHB1dHNNYXBwaW5nPzogQ29tcHV0ZUNvbnRleHRJbnB1dHNPdXRwdXRzTWFwcGluZyk6IFRlbnNvclZpZXdbXTtcbiAgb3V0cHV0KGluZGV4OiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyO1xufVxuXG5leHBvcnQgdHlwZSBUaW1lc3RhbXBRdWVyeSA9ICdub25lJyB8ICdpbnNpZGUtcGFzc2VzJyB8ICdhdC1wYXNzZXMnO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBXZWJHcHVCYWNrZW5kIH0gZnJvbSAnLi4vYmFja2VuZC13ZWJncHUnO1xuaW1wb3J0IHsgTE9HX0RFQlVHIH0gZnJvbSAnLi4vbG9nJztcblxuaW1wb3J0IHsgR3B1RGF0YSwgR3B1RGF0YUlkLCBHcHVEYXRhVHlwZSB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIG1hbmFnZXMgR3B1RGF0YUlkIC0+IEdwdUJ1ZmZlclxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdwdURhdGFNYW5hZ2VyIHtcbiAgLyoqXG4gICAqIGNvcHkgZGF0YSBmcm9tIENQVSB0byBHUFUuXG4gICAqL1xuICB1cGxvYWQoaWQ6IEdwdURhdGFJZCwgZGF0YTogVWludDhBcnJheSk6IHZvaWQ7XG4gIC8qKlxuICAgKiBjb3B5IGRhdGEgZnJvbSBHUFUgdG8gR1BVLlxuICAgKi9cbiAgbWVtY3B5KHNvdXJjZUlkOiBHcHVEYXRhSWQsIGRlc3RpbmF0aW9uSWQ6IEdwdURhdGFJZCk6IHZvaWQ7XG4gIC8qKlxuICAgKiBjcmVhdGUgbmV3IGRhdGEgb24gR1BVLlxuICAgKi9cbiAgY3JlYXRlKHNpemU6IG51bWJlciwgdXNhZ2U/OiBudW1iZXIpOiBHcHVEYXRhO1xuICAvKipcbiAgICogZ2V0IEdQVSBkYXRhIGJ5IElELlxuICAgKi9cbiAgZ2V0KGlkOiBHcHVEYXRhSWQpOiBHcHVEYXRhIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogcmVsZWFzZSB0aGUgZGF0YSBvbiBHUFUgYnkgSUQuXG4gICAqXG4gICAqIEByZXR1cm4gc2l6ZSBvZiB0aGUgZGF0YSByZWxlYXNlZFxuICAgKi9cbiAgcmVsZWFzZShpZDogR3B1RGF0YUlkKTogbnVtYmVyO1xuICAvKipcbiAgICogY29weSBkYXRhIGZyb20gR1BVIHRvIENQVS5cbiAgICovXG4gIGRvd25sb2FkKGlkOiBHcHVEYXRhSWQsIGdldFRhcmdldEJ1ZmZlcjogKCkgPT4gVWludDhBcnJheSk6IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIHJlZnJlc2ggdGhlIGJ1ZmZlcnMgdGhhdCBtYXJrZWQgZm9yIHJlbGVhc2UuXG4gICAqXG4gICAqIHdoZW4gcmVsZWFzZSgpIGlzIGNhbGxlZCwgdGhlIGJ1ZmZlciBpcyBub3QgcmVsZWFzZWQgaW1tZWRpYXRlbHkuIHRoaXMgaXMgYmVjYXVzZSB3ZSBuZWVkIHRvIHdhaXQgZm9yIHRoZSBjb21tYW5kc1xuICAgKiB0byBiZSBzdWJtaXR0ZWQgdG8gdGhlIEdQVS4gdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYWZ0ZXIgdGhlIGNvbW1hbmRzIGFyZSBzdWJtaXR0ZWQgc28gdGhhdCB0aGUgYnVmZmVycyBjYW4gYmVcbiAgICogYWN0dWFsbHkgcmVsZWFzZWQuXG4gICAqL1xuICByZWZyZXNoUGVuZGluZ0J1ZmZlcnMoKTogdm9pZDtcblxuICAvKipcbiAgICogcmVnaXN0ZXIgYW4gZXh0ZXJuYWwgYnVmZmVyIGZvciBJTyBCaW5kaW5nLiBJZiB0aGUgYnVmZmVyIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCwgcmV0dXJuIHRoZSBleGlzdGluZyBHUFUgZGF0YSBJRC5cbiAgICpcbiAgICogR1BVIGRhdGEgbWFuYWdlciBvbmx5IG1hbmFnZXMgYSBtYXBwaW5nIGJldHdlZW4gdGhlIGJ1ZmZlciBhbmQgdGhlIEdQVSBkYXRhIElELiBJdCB3aWxsIG5vdCBtYW5hZ2UgdGhlIGxpZmVjeWNsZSBvZlxuICAgKiB0aGUgZXh0ZXJuYWwgYnVmZmVyLlxuICAgKi9cbiAgcmVnaXN0ZXJFeHRlcm5hbEJ1ZmZlcihidWZmZXI6IEdQVUJ1ZmZlciwgb3JpZ2luYWxTaXplOiBudW1iZXIsIHByZXZpb3VzPzogW0dwdURhdGFJZCwgR1BVQnVmZmVyXSk6IG51bWJlcjtcblxuICAvKipcbiAgICogdW5yZWdpc3RlciBhbiBleHRlcm5hbCBidWZmZXIgZm9yIElPIEJpbmRpbmcuXG4gICAqL1xuICB1bnJlZ2lzdGVyRXh0ZXJuYWxCdWZmZXIoaWQ6IEdwdURhdGFJZCk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIGRlc3Ryb3kgYWxsIGdwdSBidWZmZXJzLlxuICAgKi9cbiAgZGlzcG9zZSgpOiB2b2lkO1xuXG4gIC8qKlxuICAgKiBjcmVhdGUgc2Vzc2lvbiByZWxhdGVkIGRhdGEuXG4gICAqL1xuICBvbkNyZWF0ZVNlc3Npb24oKTogdm9pZDtcblxuICAvKipcbiAgICogcmVsZWFzZSBzZXNzaW9uIHJlbGF0ZWQgZGF0YS5cbiAgICogQHBhcmFtIHNlc3Npb25JZCAtIHNwZWNpZnkgdGhlIHNlc3Npb24gSUQuXG4gICAqL1xuICBvblJlbGVhc2VTZXNzaW9uKHNlc3Npb25JZDogbnVtYmVyKTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIFN0b3JhZ2VDYWNoZVZhbHVlIHtcbiAgZ3B1RGF0YTogR3B1RGF0YTtcbiAgb3JpZ2luYWxTaXplOiBudW1iZXI7XG59XG5cbmNvbnN0IGJ1Y2tldEZyZWVsaXN0OiBNYXA8bnVtYmVyLCBudW1iZXI+ID0gbmV3IE1hcChbXG4gIFs2NCwgMjUwXSxcbiAgWzEyOCwgMjAwXSxcbiAgWzI1NiwgMjAwXSxcbiAgWzUxMiwgMjAwXSxcbiAgWzIwNDgsIDIzMF0sXG4gIFs0MDk2LCAyMDBdLFxuICBbODE5MiwgNTBdLFxuICBbMTYzODQsIDUwXSxcbiAgWzMyNzY4LCA1MF0sXG4gIFs2NTUzNiwgNTBdLFxuICBbMTMxMDcyLCA1MF0sXG4gIFsyNjIxNDQsIDUwXSxcbiAgWzUyNDI4OCwgNTBdLFxuICBbMTA0ODU3NiwgNTBdLFxuICBbMjA5NzE1MiwgMzBdLFxuICBbNDE5NDMwNCwgMjBdLFxuICBbODM4ODYwOCwgMTBdLFxuICBbMTI1ODI5MTIsIDEwXSxcbiAgWzE2Nzc3MjE2LCAxMF0sXG4gIFsyNjIxNDQwMCwgMTVdLFxuICBbMzM1NTQ0MzIsIDIyXSxcbiAgWzQ0MjM2ODAwLCAyXSxcbiAgWzU4OTgyNDAwLCA2XSxcbiAgLy8gd2UgZG9uJ3Qgd2FudCB0byBjYWNoZSB0aGUgYnVja2V0IHNpemVzIGJlbG93IGJ1dCBub3QgY2FjaGluZyB0aGVtXG4gIC8vIHJlc3VsdHMgaW4gc29tZSBtYWpvciBwZXJmb3JtYW5jZSBoaXRzIGZvciBtb2RlbHMgbGlrZSBzZC10dXJiby5cbiAgWzY3MTA4ODY0LCA2XSxcbiAgWzEzNDIxNzcyOCwgNl0sXG4gIFsxNjc3NzIxNjAsIDZdLFxuXSk7XG5cbmNvbnN0IGJ1Y2tldEFycjogbnVtYmVyW10gPSBbXTtcblxuLyoqXG4gKiBub3JtYWxpemUgdGhlIGJ1ZmZlciBzaXplIHNvIHRoYXQgaXQgZml0cyB0aGUgMTI4LWJpdHMgKDE2IGJ5dGVzKSBhbGlnbm1lbnQuXG4gKi9cbmNvbnN0IGNhbGNOb3JtYWxpemVkQnVmZmVyU2l6ZSA9IChzaXplOiBudW1iZXIpID0+IE1hdGguY2VpbChOdW1iZXIoc2l6ZSkgLyAxNikgKiAxNjtcblxuLyoqXG4gKiBjYWxjdWxhdGUgdGhlIGJ1ZmZlciBzaXplIHNvIHRoYXQgaXQgZml0cyBpbnRvIGJ1Y2tldHMuXG4gKi9cbmNvbnN0IGNhbGNCdWNrZXRCdWZmZXJTaXplID0gKHNpemU6IG51bWJlcikgPT4ge1xuICBmb3IgKGxldCBpZHggPSAwOyBpZHggPCBidWNrZXRBcnIubGVuZ3RoOyBpZHgrKykge1xuICAgIGNvbnN0IHNpemVGb3JCdWNrZXQgPSBidWNrZXRBcnJbaWR4XTtcbiAgICBpZiAoc2l6ZSA8PSBzaXplRm9yQnVja2V0KSB7XG4gICAgICByZXR1cm4gc2l6ZUZvckJ1Y2tldDtcbiAgICB9XG4gIH1cbiAgLy8gbm90IGluIGJ1Y2tldCBsaXN0IC0+IGNhbGxlciB3aWxsIG5vdCBjYWNoZSwgcm91bmQgdXAgdG8gMTYuXG4gIHJldHVybiBNYXRoLmNlaWwoc2l6ZSAvIDE2KSAqIDE2O1xufTtcblxubGV0IGd1aWQgPSAxO1xuY29uc3QgY3JlYXRlTmV3R3B1RGF0YUlkID0gKCkgPT4gZ3VpZCsrO1xuXG4vKipcbiAqIGV4cG9ydGVkIHN0YW5kYXJkIGRvd25sb2FkIGZ1bmN0aW9uLiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgYnkgdGhlIHNlc3Npb24gdG8gZG93bmxvYWQgdGhlIGRhdGEgZnJvbSBHUFUsIGFuZCBhbHNvIGJ5XG4gKiBmYWN0b3J5IHRvIGNyZWF0ZSBHUFUgdGVuc29ycyB3aXRoIHRoZSBjYXBhY2l0eSBvZiBkb3dubG9hZGluZyBkYXRhIGZyb20gR1BVLlxuICpcbiAqIEBwYXJhbSBiYWNrZW5kIC0gdGhlIFdlYkdQVSBiYWNrZW5kXG4gKiBAcGFyYW0gZ3B1QnVmZmVyIC0gdGhlIEdQVSBidWZmZXIgdG8gZG93bmxvYWRcbiAqIEBwYXJhbSBvcmlnaW5hbFNpemUgLSB0aGUgb3JpZ2luYWwgc2l6ZSBvZiB0aGUgZGF0YVxuICogQHBhcmFtIGdldFRhcmdldEJ1ZmZlciAtIG9wdGlvbmFsLiBJZiBwcm92aWRlZCwgdGhlIGRhdGEgd2lsbCBiZSBjb3BpZWQgdG8gdGhlIHRhcmdldCBidWZmZXIuIE90aGVyd2lzZSwgYSBuZXcgYnVmZmVyXG4gKiB3aWxsIGJlIGNyZWF0ZWQgYW5kIHJldHVybmVkLlxuICovXG5leHBvcnQgY29uc3QgZG93bmxvYWRHcHVEYXRhID0gYXN5bmMgKFxuICBiYWNrZW5kOiBXZWJHcHVCYWNrZW5kLFxuICBncHVCdWZmZXI6IEdQVUJ1ZmZlcixcbiAgb3JpZ2luYWxTaXplOiBudW1iZXIsXG4gIGdldFRhcmdldEJ1ZmZlcj86ICgpID0+IFVpbnQ4QXJyYXksXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXk+ID0+IHtcbiAgY29uc3QgYnVmZmVyU2l6ZSA9IGNhbGNOb3JtYWxpemVkQnVmZmVyU2l6ZShvcmlnaW5hbFNpemUpO1xuICBjb25zdCBncHVSZWFkQnVmZmVyID0gYmFja2VuZC5kZXZpY2UuY3JlYXRlQnVmZmVyKFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgeyBzaXplOiBidWZmZXJTaXplLCB1c2FnZTogR1BVQnVmZmVyVXNhZ2UuQ09QWV9EU1QgfCBHUFVCdWZmZXJVc2FnZS5NQVBfUkVBRCB9LFxuICApO1xuICB0cnkge1xuICAgIGNvbnN0IGNvbW1hbmRFbmNvZGVyID0gYmFja2VuZC5nZXRDb21tYW5kRW5jb2RlcigpO1xuICAgIGJhY2tlbmQuZW5kQ29tcHV0ZVBhc3MoKTtcbiAgICBjb21tYW5kRW5jb2Rlci5jb3B5QnVmZmVyVG9CdWZmZXIoXG4gICAgICBncHVCdWZmZXIgLyogc291cmNlIGJ1ZmZlciAqLyxcbiAgICAgIDAgLyogc291cmNlIG9mZnNldCAqLyxcbiAgICAgIGdwdVJlYWRCdWZmZXIgLyogZGVzdGluYXRpb24gYnVmZmVyICovLFxuICAgICAgMCAvKiBkZXN0aW5hdGlvbiBvZmZzZXQgKi8sXG4gICAgICBidWZmZXJTaXplIC8qIHNpemUgKi8sXG4gICAgKTtcbiAgICBiYWNrZW5kLmZsdXNoKCk7XG5cbiAgICBhd2FpdCBncHVSZWFkQnVmZmVyLm1hcEFzeW5jKEdQVU1hcE1vZGUuUkVBRCk7XG5cbiAgICBjb25zdCBhcnJheUJ1ZmZlciA9IGdwdVJlYWRCdWZmZXIuZ2V0TWFwcGVkUmFuZ2UoKTtcbiAgICBpZiAoZ2V0VGFyZ2V0QnVmZmVyKSB7XG4gICAgICAvLyBpZiB3ZSBhbHJlYWR5IGhhdmUgYSBDUFUgYnVmZmVyIHRvIGFjY2VwdCB0aGUgZGF0YSwgbm8gbmVlZCB0byBjbG9uZSB0aGUgQXJyYXlCdWZmZXIuXG4gICAgICBjb25zdCB0YXJnZXRCdWZmZXIgPSBnZXRUYXJnZXRCdWZmZXIoKTtcbiAgICAgIHRhcmdldEJ1ZmZlci5zZXQobmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIsIDAsIG9yaWdpbmFsU2l6ZSkpO1xuICAgICAgcmV0dXJuIHRhcmdldEJ1ZmZlcjtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gdGhlIG1hcHBlZCBBcnJheUJ1ZmZlciB3aWxsIGJlIHJlbGVhc2VkIHdoZW4gdGhlIEdQVSBidWZmZXIgaXMgZGVzdHJveWVkLiBOZWVkIHRvIGNsb25lIHRoZVxuICAgICAgLy8gQXJyYXlCdWZmZXIuXG4gICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIuc2xpY2UoMCwgb3JpZ2luYWxTaXplKSk7XG4gICAgfVxuICB9IGZpbmFsbHkge1xuICAgIGdwdVJlYWRCdWZmZXIuZGVzdHJveSgpO1xuICB9XG59O1xuXG5jbGFzcyBHcHVEYXRhTWFuYWdlckltcGwgaW1wbGVtZW50cyBHcHVEYXRhTWFuYWdlciB7XG4gIC8vIEdQVSBEYXRhIElEID0+IEdQVSBEYXRhICggc3RvcmFnZSBidWZmZXIgKVxuICBwcml2YXRlIHN0b3JhZ2VDYWNoZTogTWFwPEdwdURhdGFJZCwgU3RvcmFnZUNhY2hlVmFsdWU+O1xuXG4gIC8vIHBlbmRpbmcgYnVmZmVycyBmb3IgY29tcHV0aW5nXG4gIHByaXZhdGUgYnVmZmVyc1BlbmRpbmc6IEdQVUJ1ZmZlcltdO1xuXG4gIC8vIFRoZSByZXVzYWJsZSBzdG9yYWdlIGJ1ZmZlcnMgZm9yIGNvbXB1dGluZy5cbiAgcHJpdmF0ZSBmcmVlQnVmZmVyczogTWFwPG51bWJlciwgR1BVQnVmZmVyW10+O1xuICAvLyBUaGUgcmV1c2FibGUgdW5pZm9ybSBidWZmZXJzXG4gIHByaXZhdGUgZnJlZVVuaWZvcm1CdWZmZXJzOiBNYXA8bnVtYmVyLCBHUFVCdWZmZXJbXT47XG5cbiAgLy8gVGhlIHBlbmRpbmdCdWZmZXJzIGZvciBjYXB0dXJlIGdyYXBoLlxuICAvLyBhIFNlc3Npb25JRCAtPiBHUFVCdWZmZXJbXSBtYXBwaW5nLlxuICBwcml2YXRlIGNhcHR1cmVkUGVuZGluZ0J1ZmZlcnM6IE1hcDxudW1iZXIsIEdQVUJ1ZmZlcltdPjtcblxuICAvLyBUaGUgc2Vzc2lvbiBjb3VudC5cbiAgcHJpdmF0ZSBzZXNzaW9uQ291bnQ6IG51bWJlcjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGJhY2tlbmQ6IFdlYkdwdUJhY2tlbmQpIHtcbiAgICB0aGlzLnN0b3JhZ2VDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmZyZWVCdWZmZXJzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZnJlZVVuaWZvcm1CdWZmZXJzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuYnVmZmVyc1BlbmRpbmcgPSBbXTtcbiAgICB0aGlzLmNhcHR1cmVkUGVuZGluZ0J1ZmZlcnMgPSBuZXcgTWFwKCk7XG5cbiAgICBmb3IgKGNvbnN0IFtrZXldIG9mIGJ1Y2tldEZyZWVsaXN0KSB7XG4gICAgICBidWNrZXRBcnIucHVzaChrZXkpO1xuICAgICAgdGhpcy5mcmVlQnVmZmVycy5zZXQoa2V5LCBbXSk7XG4gICAgICB0aGlzLmZyZWVVbmlmb3JtQnVmZmVycy5zZXQoa2V5LCBbXSk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXNzaW9uQ291bnQgPSAwO1xuICB9XG5cbiAgdXBsb2FkKGlkOiBHcHVEYXRhSWQsIGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICBjb25zdCBzcmNBcnJheUJ1ZmZlciA9IGRhdGEuYnVmZmVyO1xuICAgIGNvbnN0IHNyY09mZnNldCA9IGRhdGEuYnl0ZU9mZnNldDtcbiAgICBjb25zdCBzcmNMZW5ndGggPSBkYXRhLmJ5dGVMZW5ndGg7XG4gICAgY29uc3Qgc2l6ZSA9IGNhbGNOb3JtYWxpemVkQnVmZmVyU2l6ZShzcmNMZW5ndGgpO1xuXG4gICAgLy8gZ2V0IGRlc3RpbmF0aW9uIGdwdSBidWZmZXJcbiAgICBjb25zdCBncHVEYXRhQ2FjaGUgPSB0aGlzLnN0b3JhZ2VDYWNoZS5nZXQoaWQpO1xuICAgIGlmICghZ3B1RGF0YUNhY2hlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dwdSBkYXRhIGZvciB1cGxvYWRpbmcgZG9lcyBub3QgZXhpc3QnKTtcbiAgICB9XG4gICAgaWYgKE51bWJlcihncHVEYXRhQ2FjaGUub3JpZ2luYWxTaXplKSAhPT0gc3JjTGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGluY29uc2lzdGVudCBkYXRhIHNpemUuIGdwdSBkYXRhIHNpemU9JHtncHVEYXRhQ2FjaGUub3JpZ2luYWxTaXplfSwgZGF0YSBzaXplPSR7c3JjTGVuZ3RofWApO1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSBncHUgYnVmZmVyXG4gICAgY29uc3QgZ3B1QnVmZmVyRm9yVXBsb2FkaW5nID0gdGhpcy5iYWNrZW5kLmRldmljZS5jcmVhdGVCdWZmZXIoXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgICAgeyBtYXBwZWRBdENyZWF0aW9uOiB0cnVlLCBzaXplLCB1c2FnZTogR1BVQnVmZmVyVXNhZ2UuTUFQX1dSSVRFIHwgR1BVQnVmZmVyVXNhZ2UuQ09QWV9TUkMgfSxcbiAgICApO1xuXG4gICAgLy8gY29weSAodXBsb2FkKSBkYXRhXG4gICAgY29uc3QgYXJyYXlCdWZmZXIgPSBncHVCdWZmZXJGb3JVcGxvYWRpbmcuZ2V0TWFwcGVkUmFuZ2UoKTtcbiAgICBuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcikuc2V0KG5ldyBVaW50OEFycmF5KHNyY0FycmF5QnVmZmVyLCBzcmNPZmZzZXQsIHNyY0xlbmd0aCkpO1xuICAgIGdwdUJ1ZmZlckZvclVwbG9hZGluZy51bm1hcCgpO1xuXG4gICAgLy8gR1BVIGNvcHlcbiAgICBjb25zdCBjb21tYW5kRW5jb2RlciA9IHRoaXMuYmFja2VuZC5kZXZpY2UuY3JlYXRlQ29tbWFuZEVuY29kZXIoKTtcbiAgICBjb21tYW5kRW5jb2Rlci5jb3B5QnVmZmVyVG9CdWZmZXIoZ3B1QnVmZmVyRm9yVXBsb2FkaW5nLCAwLCBncHVEYXRhQ2FjaGUuZ3B1RGF0YS5idWZmZXIsIDAsIHNpemUpO1xuICAgIHRoaXMuYmFja2VuZC5kZXZpY2UucXVldWUuc3VibWl0KFtjb21tYW5kRW5jb2Rlci5maW5pc2goKV0pO1xuICAgIGdwdUJ1ZmZlckZvclVwbG9hZGluZy5kZXN0cm95KCk7XG5cbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYkdQVV0gR3B1RGF0YU1hbmFnZXIudXBsb2FkKGlkPSR7aWR9KWApO1xuICB9XG5cbiAgbWVtY3B5KHNvdXJjZUlkOiBHcHVEYXRhSWQsIGRlc3RpbmF0aW9uSWQ6IEdwdURhdGFJZCk6IHZvaWQge1xuICAgIC8vIGdldCBzb3VyY2UgZ3B1IGJ1ZmZlclxuICAgIGNvbnN0IHNvdXJjZUdwdURhdGFDYWNoZSA9IHRoaXMuc3RvcmFnZUNhY2hlLmdldChzb3VyY2VJZCk7XG4gICAgaWYgKCFzb3VyY2VHcHVEYXRhQ2FjaGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc291cmNlIGdwdSBkYXRhIGZvciBtZW1jcHkgZG9lcyBub3QgZXhpc3QnKTtcbiAgICB9XG4gICAgLy8gZ2V0IGRlc3RpbmF0aW9uIGdwdSBidWZmZXJcbiAgICBjb25zdCBkZXN0aW5hdGlvbkdwdURhdGFDYWNoZSA9IHRoaXMuc3RvcmFnZUNhY2hlLmdldChkZXN0aW5hdGlvbklkKTtcbiAgICBpZiAoIWRlc3RpbmF0aW9uR3B1RGF0YUNhY2hlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Rlc3RpbmF0aW9uIGdwdSBkYXRhIGZvciBtZW1jcHkgZG9lcyBub3QgZXhpc3QnKTtcbiAgICB9XG4gICAgaWYgKHNvdXJjZUdwdURhdGFDYWNoZS5vcmlnaW5hbFNpemUgIT09IGRlc3RpbmF0aW9uR3B1RGF0YUNhY2hlLm9yaWdpbmFsU2l6ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbmNvbnNpc3RlbnQgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBncHUgZGF0YSBzaXplJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2l6ZSA9IGNhbGNOb3JtYWxpemVkQnVmZmVyU2l6ZShzb3VyY2VHcHVEYXRhQ2FjaGUub3JpZ2luYWxTaXplKTtcblxuICAgIC8vIEdQVSBjb3B5XG4gICAgY29uc3QgY29tbWFuZEVuY29kZXIgPSB0aGlzLmJhY2tlbmQuZ2V0Q29tbWFuZEVuY29kZXIoKTtcbiAgICB0aGlzLmJhY2tlbmQuZW5kQ29tcHV0ZVBhc3MoKTtcbiAgICBjb21tYW5kRW5jb2Rlci5jb3B5QnVmZmVyVG9CdWZmZXIoXG4gICAgICBzb3VyY2VHcHVEYXRhQ2FjaGUuZ3B1RGF0YS5idWZmZXIsXG4gICAgICAwLFxuICAgICAgZGVzdGluYXRpb25HcHVEYXRhQ2FjaGUuZ3B1RGF0YS5idWZmZXIsXG4gICAgICAwLFxuICAgICAgc2l6ZSxcbiAgICApO1xuICB9XG5cbiAgcmVnaXN0ZXJFeHRlcm5hbEJ1ZmZlcihidWZmZXI6IEdQVUJ1ZmZlciwgb3JpZ2luYWxTaXplOiBudW1iZXIsIHByZXZpb3VzPzogW0dwdURhdGFJZCwgR1BVQnVmZmVyXSk6IG51bWJlciB7XG4gICAgbGV0IGlkOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICBpZCA9IHByZXZpb3VzWzBdO1xuICAgICAgaWYgKGJ1ZmZlciA9PT0gcHJldmlvdXNbMV0pIHtcbiAgICAgICAgTE9HX0RFQlVHKFxuICAgICAgICAgICd2ZXJib3NlJyxcbiAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgYFtXZWJHUFVdIEdwdURhdGFNYW5hZ2VyLnJlZ2lzdGVyRXh0ZXJuYWxCdWZmZXIoc2l6ZT0ke29yaWdpbmFsU2l6ZX0pID0+IGlkPSR7aWR9LCBidWZmZXIgaXMgdGhlIHNhbWUsIHNraXAuYCxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIGlkO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLmJhY2tlbmQuY2FwdHVyZWRDb21tYW5kTGlzdC5oYXModGhpcy5iYWNrZW5kLmN1cnJlbnRTZXNzaW9uSWQhKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlZ2lzdGVyaW5nIGEgZGlmZmVyZW50IGV4dGVybmFsIGJ1ZmZlciB1bmRlciBncmFwaCBjYXB0dXJlIG1vZGUgaXMgbm90IHN1cHBvcnRlZCB5ZXQuXG4gICAgICAgICAgICAgUGxlYXNlIHVzZSB0aGUgcHJldmlvdXMgZXh0ZXJuYWwgYnVmZmVyIWApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZCA9IGNyZWF0ZU5ld0dwdURhdGFJZCgpO1xuICAgIH1cblxuICAgIHRoaXMuc3RvcmFnZUNhY2hlLnNldChpZCwgeyBncHVEYXRhOiB7IGlkLCB0eXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0LCBidWZmZXIgfSwgb3JpZ2luYWxTaXplIH0pO1xuICAgIExPR19ERUJVRyhcbiAgICAgICd2ZXJib3NlJyxcbiAgICAgICgpID0+IGBbV2ViR1BVXSBHcHVEYXRhTWFuYWdlci5yZWdpc3RlckV4dGVybmFsQnVmZmVyKHNpemU9JHtvcmlnaW5hbFNpemV9KSA9PiBpZD0ke2lkfSwgcmVnaXN0ZXJlZC5gLFxuICAgICk7XG4gICAgcmV0dXJuIGlkO1xuICB9XG5cbiAgdW5yZWdpc3RlckV4dGVybmFsQnVmZmVyKGlkOiBHcHVEYXRhSWQpOiB2b2lkIHtcbiAgICBpZiAoaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5zdG9yYWdlQ2FjaGUuZGVsZXRlKGlkKTtcbiAgICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViR1BVXSBHcHVEYXRhTWFuYWdlci51bnJlZ2lzdGVyRXh0ZXJuYWxCdWZmZXIoKSA9PiBpZD0ke2lkfWApO1xuICAgIH1cbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gIGNyZWF0ZShzaXplOiBudW1iZXIsIHVzYWdlID0gR1BVQnVmZmVyVXNhZ2UuU1RPUkFHRSB8IEdQVUJ1ZmZlclVzYWdlLkNPUFlfU1JDIHwgR1BVQnVmZmVyVXNhZ2UuQ09QWV9EU1QpOiBHcHVEYXRhIHtcbiAgICBjb25zdCBidWZmZXJTaXplID0gY2FsY0J1Y2tldEJ1ZmZlclNpemUoc2l6ZSk7XG5cbiAgICBsZXQgZ3B1QnVmZmVyO1xuICAgIC8vIEN1cnJlbnRseSwgb25seSBzdG9yYWdlIGJ1ZmZlcnMgYXJlIHJldXNlZC5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgIGNvbnN0IGlzU3RvcmFnZSA9ICh1c2FnZSAmIEdQVUJ1ZmZlclVzYWdlLlNUT1JBR0UpID09PSBHUFVCdWZmZXJVc2FnZS5TVE9SQUdFO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgY29uc3QgaXNVbmlmb3JtID0gKHVzYWdlICYgR1BVQnVmZmVyVXNhZ2UuVU5JRk9STSkgPT09IEdQVUJ1ZmZlclVzYWdlLlVOSUZPUk07XG4gICAgaWYgKGlzU3RvcmFnZSB8fCBpc1VuaWZvcm0pIHtcbiAgICAgIGNvbnN0IGZyZWVCdWZmZXJzID0gaXNTdG9yYWdlID8gdGhpcy5mcmVlQnVmZmVycyA6IHRoaXMuZnJlZVVuaWZvcm1CdWZmZXJzO1xuICAgICAgY29uc3QgYnVmZmVycyA9IGZyZWVCdWZmZXJzLmdldChidWZmZXJTaXplKTtcbiAgICAgIGlmICghYnVmZmVycykge1xuICAgICAgICAvLyBubyBzdWNoIGJ1Y2tldC9mcmVlbGlzdCAtIGNyZWF0ZSBncHUgYnVmZmVyXG4gICAgICAgIGdwdUJ1ZmZlciA9IHRoaXMuYmFja2VuZC5kZXZpY2UuY3JlYXRlQnVmZmVyKHsgc2l6ZTogYnVmZmVyU2l6ZSwgdXNhZ2UgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoYnVmZmVycy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgLy8gaW4gZnJlZWxpc3QsIHVzZSBpdFxuICAgICAgICAgIGdwdUJ1ZmZlciA9IGJ1ZmZlcnMucG9wKCkgYXMgR1BVQnVmZmVyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGJ1Y2tldCBlbXB0eSwgY3JlYXRlIGdwdSBidWZmZXJcbiAgICAgICAgICBncHVCdWZmZXIgPSB0aGlzLmJhY2tlbmQuZGV2aWNlLmNyZWF0ZUJ1ZmZlcih7IHNpemU6IGJ1ZmZlclNpemUsIHVzYWdlIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGNyZWF0ZSBncHUgYnVmZmVyXG4gICAgICBncHVCdWZmZXIgPSB0aGlzLmJhY2tlbmQuZGV2aWNlLmNyZWF0ZUJ1ZmZlcih7IHNpemU6IGJ1ZmZlclNpemUsIHVzYWdlIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGdwdURhdGEgPSB7IGlkOiBjcmVhdGVOZXdHcHVEYXRhSWQoKSwgdHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCwgYnVmZmVyOiBncHVCdWZmZXIgfTtcbiAgICB0aGlzLnN0b3JhZ2VDYWNoZS5zZXQoZ3B1RGF0YS5pZCwgeyBncHVEYXRhLCBvcmlnaW5hbFNpemU6IE51bWJlcihzaXplKSB9KTtcblxuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViR1BVXSBHcHVEYXRhTWFuYWdlci5jcmVhdGUoc2l6ZT0ke3NpemV9KSA9PiBpZD0ke2dwdURhdGEuaWR9YCk7XG4gICAgcmV0dXJuIGdwdURhdGE7XG4gIH1cblxuICBnZXQoaWQ6IEdwdURhdGFJZCk6IEdwdURhdGEgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnN0b3JhZ2VDYWNoZS5nZXQoaWQpPy5ncHVEYXRhO1xuICB9XG5cbiAgcmVsZWFzZShpZElucHV0OiBHcHVEYXRhSWQpOiBudW1iZXIge1xuICAgIGNvbnN0IGlkID0gdHlwZW9mIGlkSW5wdXQgPT09ICdiaWdpbnQnID8gTnVtYmVyKGlkSW5wdXQpIDogaWRJbnB1dDtcbiAgICBjb25zdCBjYWNoZWREYXRhID0gdGhpcy5zdG9yYWdlQ2FjaGUuZ2V0KGlkKTtcbiAgICBpZiAoIWNhY2hlZERhdGEpIHtcbiAgICAgIGlmICh0aGlzLnN0b3JhZ2VDYWNoZS5zaXplID09PSAwKSB7XG4gICAgICAgIC8vIGNhY2hlIHdhcyBwcmV2aW91c2x5IGNsZWFyZWQsIG5vIG5lZWQgdG8gcmVsZWFzZSBhbnl0aGluZy5cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3JlbGVhc2luZyBkYXRhIGRvZXMgbm90IGV4aXN0Jyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJHUFVdIEdwdURhdGFNYW5hZ2VyLnJlbGVhc2UoaWQ9JHtpZH0pLCBncHVEYXRhSWQ9JHtjYWNoZWREYXRhLmdwdURhdGEuaWR9YCk7XG5cbiAgICB0aGlzLnN0b3JhZ2VDYWNoZS5kZWxldGUoaWQpO1xuICAgIHRoaXMuYnVmZmVyc1BlbmRpbmcucHVzaChjYWNoZWREYXRhLmdwdURhdGEuYnVmZmVyKTtcbiAgICAvLyBjYWNoZWREYXRhLmdwdURhdGEuYnVmZmVyLmRlc3Ryb3koKTtcblxuICAgIHJldHVybiBjYWNoZWREYXRhLm9yaWdpbmFsU2l6ZTtcbiAgfVxuXG4gIGFzeW5jIGRvd25sb2FkKGlkOiBHcHVEYXRhSWQsIGdldFRhcmdldEJ1ZmZlcjogKCkgPT4gVWludDhBcnJheSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNhY2hlZERhdGEgPSB0aGlzLnN0b3JhZ2VDYWNoZS5nZXQoTnVtYmVyKGlkKSk7XG4gICAgaWYgKCFjYWNoZWREYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RhdGEgZG9lcyBub3QgZXhpc3QnKTtcbiAgICB9XG4gICAgYXdhaXQgZG93bmxvYWRHcHVEYXRhKHRoaXMuYmFja2VuZCwgY2FjaGVkRGF0YS5ncHVEYXRhLmJ1ZmZlciwgY2FjaGVkRGF0YS5vcmlnaW5hbFNpemUsIGdldFRhcmdldEJ1ZmZlcik7XG4gIH1cblxuICByZWZyZXNoUGVuZGluZ0J1ZmZlcnMoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYnVmZmVyc1BlbmRpbmcubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYmFja2VuZC5zZXNzaW9uU3RhdHVzID09PSAnZGVmYXVsdCcpIHtcbiAgICAgIGZvciAoY29uc3QgYnVmZmVyIG9mIHRoaXMuYnVmZmVyc1BlbmRpbmcpIHtcbiAgICAgICAgY29uc3QgbWF4SW5GcmVlTGlzdCA9IGJ1Y2tldEZyZWVsaXN0LmdldChidWZmZXIuc2l6ZSk7XG5cbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICAgICAgaWYgKChidWZmZXIudXNhZ2UgJiBHUFVCdWZmZXJVc2FnZS5TVE9SQUdFKSA9PT0gR1BVQnVmZmVyVXNhZ2UuU1RPUkFHRSkge1xuICAgICAgICAgIC8vIFB1dCB0aGUgcGVuZGluZyBidWZmZXIgdG8gZnJlZUJ1ZmZlcnMgbGlzdCBpbnN0ZWFkIG9mIHJlYWxseSBkZXN0cm95aW5nIGl0IGZvciBidWZmZXIgcmV1c2luZy5cbiAgICAgICAgICBjb25zdCBmcmVlbGlzdCA9IHRoaXMuZnJlZUJ1ZmZlcnMuZ2V0KGJ1ZmZlci5zaXplKSB8fCBbXTtcbiAgICAgICAgICBpZiAobWF4SW5GcmVlTGlzdCA9PT0gdW5kZWZpbmVkIHx8IGZyZWVsaXN0Lmxlbmd0aCA+PSBtYXhJbkZyZWVMaXN0KSB7XG4gICAgICAgICAgICBidWZmZXIuZGVzdHJveSgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmcmVlbGlzdC5wdXNoKGJ1ZmZlcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgICAgIH0gZWxzZSBpZiAoKGJ1ZmZlci51c2FnZSAmIEdQVUJ1ZmZlclVzYWdlLlVOSUZPUk0pID09PSBHUFVCdWZmZXJVc2FnZS5VTklGT1JNKSB7XG4gICAgICAgICAgLy8gUHV0IHRoZSBwZW5kaW5nIGJ1ZmZlciB0byBmcmVlVW5pZm9ybUJ1ZmZlcnMgbGlzdCBpbnN0ZWFkIG9mIHJlYWxseSBkZXN0cm95aW5nIGl0IGZvciBidWZmZXIgcmV1c2luZy5cbiAgICAgICAgICBjb25zdCBmcmVlbGlzdCA9IHRoaXMuZnJlZVVuaWZvcm1CdWZmZXJzLmdldChidWZmZXIuc2l6ZSkgfHwgW107XG4gICAgICAgICAgaWYgKG1heEluRnJlZUxpc3QgPT09IHVuZGVmaW5lZCB8fCBmcmVlbGlzdC5sZW5ndGggPj0gbWF4SW5GcmVlTGlzdCkge1xuICAgICAgICAgICAgYnVmZmVyLmRlc3Ryb3koKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZnJlZWxpc3QucHVzaChidWZmZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBidWZmZXIuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLmJ1ZmZlcnNQZW5kaW5nID0gW107XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIERvbid0IHJlbGVhc2UgaW50ZXJtZWRpYXRlIHRlbnNvcnMgaW4gbm9uLWRlZmF1bHQgbW9kZS5cbiAgICAgIC8vIFRPRE86IHJldXNlIHRoZSBzdG9yYWdlIGJ1ZmZlcnMgaW4gbm9uLWRlZmF1bHQgbW9kZS5cbiAgICAgIGxldCBjYXB0dXJlZEJ1ZmZlcnMgPSB0aGlzLmNhcHR1cmVkUGVuZGluZ0J1ZmZlcnMuZ2V0KHRoaXMuYmFja2VuZC5jdXJyZW50U2Vzc2lvbklkISk7XG4gICAgICBpZiAoIWNhcHR1cmVkQnVmZmVycykge1xuICAgICAgICBjYXB0dXJlZEJ1ZmZlcnMgPSBbXTtcbiAgICAgICAgdGhpcy5jYXB0dXJlZFBlbmRpbmdCdWZmZXJzLnNldCh0aGlzLmJhY2tlbmQuY3VycmVudFNlc3Npb25JZCEsIGNhcHR1cmVkQnVmZmVycyk7XG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IGJ1ZmZlciBvZiB0aGlzLmJ1ZmZlcnNQZW5kaW5nKSB7XG4gICAgICAgIGNhcHR1cmVkQnVmZmVycy5wdXNoKGJ1ZmZlcik7XG4gICAgICB9XG4gICAgICB0aGlzLmJ1ZmZlcnNQZW5kaW5nID0gW107XG4gICAgfVxuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICB0aGlzLmZyZWVCdWZmZXJzLmZvckVhY2goKGJ1ZmZlcnMpID0+IHtcbiAgICAgIGJ1ZmZlcnMuZm9yRWFjaCgoYnVmZmVyKSA9PiB7XG4gICAgICAgIGJ1ZmZlci5kZXN0cm95KCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICB0aGlzLmZyZWVVbmlmb3JtQnVmZmVycy5mb3JFYWNoKChidWZmZXJzKSA9PiB7XG4gICAgICBidWZmZXJzLmZvckVhY2goKGJ1ZmZlcikgPT4ge1xuICAgICAgICBidWZmZXIuZGVzdHJveSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnN0b3JhZ2VDYWNoZS5mb3JFYWNoKChzdG9yYWdlKSA9PiB7XG4gICAgICBzdG9yYWdlLmdwdURhdGEuYnVmZmVyLmRlc3Ryb3koKTtcbiAgICB9KTtcblxuICAgIHRoaXMuY2FwdHVyZWRQZW5kaW5nQnVmZmVycy5mb3JFYWNoKChidWZmZXJzKSA9PiB7XG4gICAgICBidWZmZXJzLmZvckVhY2goKGJ1ZmZlcikgPT4ge1xuICAgICAgICBidWZmZXIuZGVzdHJveSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgdGhpcy5zdG9yYWdlQ2FjaGUgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mcmVlQnVmZmVycyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmZyZWVVbmlmb3JtQnVmZmVycyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmNhcHR1cmVkUGVuZGluZ0J1ZmZlcnMgPSBuZXcgTWFwKCk7XG4gIH1cblxuICBvbkNyZWF0ZVNlc3Npb24oKSB7XG4gICAgdGhpcy5zZXNzaW9uQ291bnQgKz0gMTtcbiAgfVxuXG4gIG9uUmVsZWFzZVNlc3Npb24oc2Vzc2lvbklkOiBudW1iZXIpIHtcbiAgICAvLyByZWxlYXNlIHRoZSBjYXB0dXJlZCBwZW5kaW5nIGJ1ZmZlcnMuXG4gICAgY29uc3QgcGVuZGluZ0J1ZmZlcnMgPSB0aGlzLmNhcHR1cmVkUGVuZGluZ0J1ZmZlcnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKHBlbmRpbmdCdWZmZXJzKSB7XG4gICAgICBwZW5kaW5nQnVmZmVycy5mb3JFYWNoKChidWZmZXIpID0+IHtcbiAgICAgICAgYnVmZmVyLmRlc3Ryb3koKTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5jYXB0dXJlZFBlbmRpbmdCdWZmZXJzLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIH1cblxuICAgIC8vIHJlbGVhc2UgdGhlIHN0b3JhZ2UgY2FjaGUgaWYgbm8gYWN0aXZlIHNlc3Npb25zLlxuICAgIHRoaXMuc2Vzc2lvbkNvdW50IC09IDE7XG4gICAgaWYgKHRoaXMuc2Vzc2lvbkNvdW50ID09PSAwKSB7XG4gICAgICBMT0dfREVCVUcoJ3dhcm5pbmcnLCAoKSA9PiAnW1dlYkdQVV0gQ2xlYXJpbmcgd2ViZ3B1IGJ1ZmZlciBjYWNoZScpO1xuICAgICAgdGhpcy5zdG9yYWdlQ2FjaGUuZm9yRWFjaCgoc3RvcmFnZSkgPT4ge1xuICAgICAgICBzdG9yYWdlLmdwdURhdGEuYnVmZmVyLmRlc3Ryb3koKTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5zdG9yYWdlQ2FjaGUgPSBuZXcgTWFwKCk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVHcHVEYXRhTWFuYWdlciA9ICguLi5hcmdzOiBDb25zdHJ1Y3RvclBhcmFtZXRlcnM8dHlwZW9mIEdwdURhdGFNYW5hZ2VySW1wbD4pOiBHcHVEYXRhTWFuYWdlciA9PlxuICBuZXcgR3B1RGF0YU1hbmFnZXJJbXBsKC4uLmFyZ3MpO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5jbGFzcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXlJbXBsIHtcbiAgY29uc3RydWN0b3IoYXR0cmlidXRlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywgYXR0cmlidXRlKTtcbiAgfVxuXG4gIHByaXZhdGUga2V5OiBzdHJpbmc7XG4gIHB1YmxpYyBnZXQgY2FjaGVLZXkoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMua2V5KSB7XG4gICAgICB0aGlzLmtleSA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpXG4gICAgICAgIC5zb3J0KClcbiAgICAgICAgLm1hcCgobmFtZSkgPT4gYCR7KHRoaXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW25hbWVdfWApXG4gICAgICAgIC5qb2luKCc7Jyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmtleTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGNhY2hlS2V5OiBzdHJpbmc7XG59XG5cbi8qKlxuICogY3JlYXRlIGEgbmV3IG9iamVjdCBmcm9tIHRoZSBnaXZlbiBhdHRyaWJ1dGUsIGFuZCBhZGQgYSBjYWNoZUtleSBwcm9wZXJ0eSB0byBpdFxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5ID0gPFQgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gIGF0dHJpYnV0ZTogVCxcbik6IFQgJiBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgPT4gbmV3IEF0dHJpYnV0ZVdpdGhDYWNoZUtleUltcGwoYXR0cmlidXRlKSBhcyB1bmtub3duIGFzIFQgJiBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBQcm9ncmFtVW5pZm9ybSwgUHJvZ3JhbVVuaWZvcm1WYXJpYWJsZUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbi8qKlxuICogY29uc3RhbnQgdmFsdWUgZm9yIGEgd29ya2dyb3VwIHNpemUuXG4gKlxuICogV2UgZGVmaW5pdGVseSBjYW4gZG8gZnVydGhlciBvcHRpbWl6YXRpb24gaW4gZnV0dXJlLCBidXQgZm9yIG5vdyB3ZSB1c2UgNjQuXG4gKlxuICogcnVsZSBvZiB0aHVtYjogVXNlIFthIHdvcmtncm91cCBzaXplIG9mXSA2NCB1bmxlc3MgeW91IGtub3cgd2hhdCBHUFUgeW91IGFyZSB0YXJnZXRpbmcgb3IgdGhhdCB5b3VyIHdvcmtsb2FkXG4gKiAgICAgICAgICAgICAgICBuZWVkcyBzb21ldGhpbmcgZGlmZmVyZW50LlxuICpcbiAqIGZyb206IGh0dHBzOi8vc3VybWEuZGV2L3RoaW5ncy93ZWJncHUvXG4gKiovXG5leHBvcnQgY29uc3QgV09SS0dST1VQX1NJWkUgPSA2NDtcblxuaW50ZXJmYWNlIEluZGljZXNIZWxwZXJUeXBlcyB7XG4gIC8qKlxuICAgKiBXR1NMIHR5cGUgb2YgaW5kaWNlcyBleHByZXNzaW9uXG4gICAqL1xuICByZWFkb25seSBpbmRpY2VzOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdHU0wgdHlwZSBvZiBhIHZhbHVlXG4gICAqL1xuICByZWFkb25seSB2YWx1ZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXR1NMIHR5cGUgb2Ygc3RvcmFnZSB0eXBlIHJlcHJlc2VudGluZyBhIHZhbHVlXG4gICAqXG4gICAqIFRoaXMgaXMgdXN1YWxseSB0aGUgc2FtZSB0byBgdmFsdWVgLCBidXQgZm9yIHNvbWUgdHlwZSAoZWcuIGJvb2wpLCB3ZSBuZWVkIHRvIHVzZSBgdTMyYCBhcyBzdG9yYWdlIHR5cGUgZm9yXG4gICAqIHZhbHVlIHR5cGUgYHZlYzQ8Ym9vbD5gXG4gICAqL1xuICByZWFkb25seSBzdG9yYWdlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIHRlbnNvciB0eXBlIGFzIHJlcHJlc2VudGVkIGluIFRlbnNvclZpZXdcbiAgICovXG4gIHJlYWRvbmx5IHRlbnNvcjogbnVtYmVyO1xufVxuXG4vKipcbiAqIEEgaGVscGVyIGNsYXNzIGZvciBnZW5lcmF0aW5nIFdHU0wgY29kZSBmb3IgbWFuaXB1bGF0aW5nIGluZGljZXMgYW5kIGRhdGEgZm9yIGEgc2hhZGVyJ3MgaW5wdXQgb3Igb3V0cHV0LlxuICpcbiAqIFRoaXMgY2xhc3MgaXMgZGVzaWduZWQgdG8gb2ZmZXIgYSB1bmlmaWVkIHdheSB0byBnZW5lcmF0ZSBXR1NMIGNvZGUgZm9yIG1hbmlwdWxhdGluZyBpbmRpY2VzIGFuZCBkYXRhIGZvciBhIHNoYWRlcidzXG4gKiBpbnB1dCBvciBvdXRwdXQuXG4gKlxuICogVGhlIGZvbGxvd2luZyBpcyBhIGxpc3Qgb2YgdGVybWlub2xvZ2llcyB1c2VkIGluIHRoaXMgY2xhc3M6XG4gKiAtIGBvZmZzZXRgOiBhIHVpbnQzMiB2YWx1ZSByZXByZXNlbnRpbmcgdGhlIG9mZnNldCBvZiBhbiBlbGVtZW50IGluIHRoZSBkYXRhIGJ1ZmZlci5cbiAqIC0gYGluZGljZXNgOiBhbiBhYnN0cmFjdGlvbiBvZiBhIG11bHRpLWRpbWVuc2lvbmFsIGFycmF5J3MgaW5kaWNlcyByZXByZXNlbnRpbmcgdGhlIGRhdGEncyBpbmRleCBvbiBlYWNoIGRpbWVuc2lvbi5cbiAqIC0gYHZhbHVlYDogYSB2YWx1ZSBvZiBhIGRhdGEgZWxlbWVudC5cbiAqXG4gKiBVc2VycyBhcmUgZXhwZWN0ZWQgdG8gY3JlYXRlIGFuIGluc3RhbmNlIG9mIHRoaXMgY2xhc3MgZm9yIGVhY2ggc2hhZGVyJ3MgaW5wdXQgb3Igb3V0cHV0LCBhbmQgdXNlIHRoZSBpbnN0YW5jZSB0b1xuICogZ2VuZXJhdGUgV0dTTCBjb2RlIGZvciBtYW5pcHVsYXRpbmcgaW5kaWNlcyBhbmQgZGF0YS4gVGhlIGZvbGxvd2luZyAyIGV4cG9ydGVkIGZ1bmN0aW9ucyBhcmUgZm9yIHVzZXJzIHRvIGNhbGwgdG9cbiAqIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiBhbiBpbmRpY2VzIGhlbHBlcjpcbiAqIC0gYGlucHV0VmFyaWFibGUoKWA6IGNyZWF0ZSBhbiBpbmRpY2VzIGhlbHBlciBpbnN0YW5jZSBmb3IgYW4gaW5wdXQuXG4gKiAtIGBvdXRwdXRWYXJpYWJsZSgpYDogY3JlYXRlIGFuIGluZGljZXMgaGVscGVyIGluc3RhbmNlIGZvciBhbiBvdXRwdXQuXG4gKiAtIGBpbnRlcm5hbFZhcmlhYmxlKClgOiBjcmVhdGUgYW4gaW5kaWNlcyBoZWxwZXIgaW5zdGFuY2UgZm9yIGFuIGludGVybmFsIHZhcmlhYmxlLlxuICpcbiAqIEFuIGluZGljZXMgaGVscGVyIGluc3RhbmNlIGNvbnRhaW5zIGhlbHBlciBmdW5jdGlvbnMgZm9yIHRoZSBmb2xsb3dpbmcgb3BlcmF0aW9uczpcbiAqIC0gYWNjZXNzIHJlYWRvbmx5IGJhc2ljIGluZm9ybWF0aW9uLCBpbmNsdWRpbmc6IGBuYW1lYCh0aGUgbmFtZSBvZiB0aGUgaW5wdXQgb3Igb3V0cHV0KSwgYHVzYWdlYCh3aGV0aGVyIGl0J3MgYW5cbiAqIGlucHV0LCBhbiBvdXRwdXQgb3IgYW4gaW50ZXJuYWwgdmFyaWFibGUpIGFuZCBgc2hhcGVgKHRoZSBwYXNzZWQgaW4gc2hhcGUpLlxuICogLSBgdHlwZWA6IGFjY2VzcyByZWFkb25seSB0eXBlIGluZm9ybWF0aW9uLCBpbmNsdWRpbmc6IGBpbmRpY2VzYCh0aGUgdHlwZSBvZiBpbmRpY2VzKSwgYHZhbHVlYCh0aGUgdHlwZSBvZiB2YWx1ZSBhdFxuICogcnVudGltZSksIGBzdG9yYWdlYCh0aGUgdHlwZSBvZiB2YWx1ZSBhdCBzdG9yYWdlKSBhbmQgYHRlbnNvcmAodGhlIHRlbnNvciB0eXBlIGFzIHJlcHJlc2VudGVkIGluIFRlbnNvclZpZXcpLlxuICogLSBnZW5lcmF0ZSBXR1NMIGNvZGUgZm9yIGdldHRpbmcgaW5kaWNlcyBmcm9tIG9mZnNldC4gVXNlIGBvZmZzZXRUb0luZGljZXMoKWAgZm9yIFdHU0wgY29kZSBzbmlwcGV0IHRvIGNhbGN1bGF0ZVxuICogaW5kaWNlcyBmcm9tIG9mZnNldCwgYW5kIHVzZSBgaW5kaWNlc1RvT2Zmc2V0KClgIGZvciBXR1NMIGNvZGUgc25pcHBldCB0byBjYWxjdWxhdGUgb2Zmc2V0IGZyb20gaW5kaWNlcy5cbiAqIC0gdG8gbWFuaXB1bGF0ZSBhbiBpbnN0YW5jZSBvZiBpbmRpY2VzLCB1c2UgYHNldEluZGljZXMoKWAgYW5kIGBnZXRJbmRpY2VzKClgIHRvIHNldCBhbmQgZ2V0IHRoZSBpbmRpY2VzIG9uIGFuXG4gKiBpbmRpY2VzIHZhcmlhYmxlLlxuICogLSB0byBtYW5pcHVsYXRlIGRhdGEsIHVzZSBgc2V0KClgL2BnZXQoKWAgdG8gYWNjZXNzIGRhdGEgYXQgdGhlIGdpdmVuIGluZGljZXMgZnJvbSBwYXJhbWV0ZXIgbGlzdCwgdXNlXG4gKiBgc2V0QnlJbmRpY2VzKClgL2BnZXRCeUluZGljZXMoKWAgdG8gYWNjZXNzIGRhdGEgYXQgdGhlIGdpdmVuIGluZGljZXMgZnJvbSBhbiBpbmRpY2VzIHZhcmlhYmxlLCBhbmQgdXNlXG4gKiBgc2V0QnlPZmZzZXQoKWAvYGdldEJ5T2Zmc2V0KClgIHRvIGFjY2VzcyBkYXRhIGF0IHRoZSBnaXZlbiBvZmZzZXQuXG4gKiAtIGBpbXBsYDogZ2V0IFdHU0wgY29kZSBvZiBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbiBmb3IgdGhlIHV0aWwgZnVuY3Rpb25zIG1lbnRpb25lZCBhYm92ZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbmRpY2VzSGVscGVyIHtcbiAgLyoqXG4gICAqIGdldCBXR1NMIGNvZGUgb2YgZnVuY3Rpb24gaW1wbGVtZW50YXRpb24gZm9yIHRoZSB1dGlsIGZ1bmN0aW9ucy5cbiAgICpcbiAgICovXG4gIHJlYWRvbmx5IGltcGw6ICgpID0+IHN0cmluZztcblxuICAvKipcbiAgICogZ2V0IHR5cGUgaW5mb1xuICAgKi9cbiAgcmVhZG9ubHkgdHlwZTogSW5kaWNlc0hlbHBlclR5cGVzO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgb2YgYSBleHByZXNzaW9uIGZvciBnZXR0aW5nIGluZGljZXMgZnJvbSBvZmZzZXQuXG4gICAqXG4gICAqIEBwYXJhbSB2YXJPZmZzZXQgLSBhIHUzMiBleHByZXNzaW9uIHJlcHJlc2VudGluZyB0aGUgb2Zmc2V0LlxuICAgKlxuICAgKiBAcmV0dXJucyBhbiBgdHlwZS5pbmRpY2VzYCBleHByZXNzaW9uXG4gICAqL1xuICByZWFkb25seSBvZmZzZXRUb0luZGljZXM6ICh2YXJPZmZzZXQ6IHN0cmluZykgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgb2YgYW4gYHUzMmAgZXhwcmVzc2lvbiBmb3IgZ2V0dGluZyBvZmZzZXQgZnJvbSBpbmRpY2VzLlxuICAgKlxuICAgKiBAcGFyYW0gdmFySW5kaWNlcyAtIGEgYHR5cGUuaW5kaWNlc2AgZXhwcmVzc2lvbiByZXByZXNlbnRpbmcgdGhlIGluZGljZXMuXG4gICAqXG4gICAqIEByZXR1cm5zIGFuIGB1MzJgIGV4cHJlc3Npb25cbiAgICovXG4gIHJlYWRvbmx5IGluZGljZXNUb09mZnNldDogKHZhckluZGljZXM6IHN0cmluZykgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgb2YgYW4gYHUzMmAgZXhwcmVzc2lvbiBmb3IgZ2V0dGluZyBvcmlnaW5hbCBvZmZzZXQgZnJvbSBicm9hZGNhc3RlZCBpbmRpY2VzLlxuICAgKlxuICAgKiBAcGFyYW0gdmFySW5kaWNlcyAtIGEgYHR5cGUuaW5kaWNlc2AgZXhwcmVzc2lvbiByZXByZXNlbnRpbmcgdGhlIG91dHB1dCBpbmRpY2VzLlxuICAgKiBAcGFyYW0gb3V0cHV0IC0gb3V0cHV0IEluZGljZXNIZWxwZXIuXG4gICAqXG4gICAqIEByZXR1cm5zIGFuIGB1MzJgIGV4cHJlc3Npb25cbiAgICovXG4gIHJlYWRvbmx5IGJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0OiAodmFySW5kaWNlczogc3RyaW5nLCBvdXRwdXQ6IEluZGljZXNIZWxwZXIpID0+IHN0cmluZztcblxuICAvKipcbiAgICogV0dTTCBjb2RlIG9mIGdlbmVyYXRpbmcgYW4gaW5kaWNlcyBsaXRlcmFsXG4gICAqXG4gICAqIEBwYXJhbSBpbml0IC0gaW5pdGlhbCB2YWx1ZS5cbiAgICovXG4gIHJlYWRvbmx5IGluZGljZXM6ICguLi5pbml0OiBSZWFkb25seUFycmF5PG51bWJlciB8IHN0cmluZz4pID0+IHN0cmluZztcblxuICAvKipcbiAgICogV0dTTCBjb2RlIG9mIGEgc3RhdGVtZW50IGZvciBzZXR0aW5nIGluZGljZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YXJJbmRpY2VzIC0gYSB2YXJpYWJsZSBuYW1lIGZvciB0aGUgaW5kaWNlcy5cbiAgICogQHBhcmFtIGlkeCAtIHRoZSBpbmRleCBvZiB0aGUgaW5kaWNlcyB0byBzZXQuIGNhbiBiZSBhIG51bWJlciBvciBhIHN0cmluZyAoV0dTTCBgdTMyYCBleHByZXNzaW9uKS5cbiAgICogQHBhcmFtIHZhbHVlIC0gdGhlIHZhbHVlIHRvIHNldC4gY2FuIGJlIGEgbnVtYmVyIG9yIGEgc3RyaW5nIChXR1NMIGB1MzJgIGV4cHJlc3Npb24pLlxuICAgKlxuICAgKiBAcmV0dXJucyBhIFdHU0wgc3RhdGVtZW50XG4gICAqL1xuICByZWFkb25seSBpbmRpY2VzU2V0OiAodmFySW5kaWNlczogc3RyaW5nLCBpZHg6IG51bWJlciB8IHN0cmluZywgdmFsdWU6IG51bWJlciB8IHN0cmluZykgPT4gdm9pZDtcblxuICAvKipcbiAgICogV0dTTCBjb2RlIG9mIGFuIGB1MzJgIGV4cHJlc3Npb24gZm9yIGdldHRpbmcgaW5kaWNlcy5cbiAgICpcbiAgICogQHBhcmFtIHZhckluZGljZXMgLSBhIHZhcmlhYmxlIG5hbWUgZm9yIHRoZSBpbmRpY2VzLlxuICAgKiBAcGFyYW0gaWR4IC0gdGhlIGluZGV4IG9mIHRoZSBpbmRpY2VzIHRvIGdldC4gY2FuIGJlIGEgbnVtYmVyIG9yIGEgc3RyaW5nIChXR1NMIGB1MzJgIGV4cHJlc3Npb24pLlxuICAgKlxuICAgKiBAcmV0dXJucyBhbiBgdTMyYCBleHByZXNzaW9uXG4gICAqL1xuICByZWFkb25seSBpbmRpY2VzR2V0OiAodmFySW5kaWNlczogc3RyaW5nLCBpZHg6IG51bWJlciB8IHN0cmluZykgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgZm9yIGEgc3RhdGVtZW50IGZvciBzZXR0aW5nIGRhdGEgYXQgdGhlIGdpdmVuIGluZGljZXMuXG4gICAqXG4gICAqIEBwYXJhbSBpbmRpY2VzQW5kVmFsdWUgLSBhbiBhcnJheSBvZiBudW1iZXJzIG9yIHN0cmluZ3MgKFdHU0wgYHUzMmAgZXhwcmVzc2lvbikgcmVwcmVzZW50aW5nIHRoZSBpbmRpY2VzLCBmb2xsb3dlZFxuICAgKiAgICAgYnkgdGhlIHZhbHVlIHRvIHNldC4gVGhpcyBhcnJheSBzaG91bGQgaGF2ZSBleGFjdGx5IGBzaGFwZS5sZW5ndGggKyAxYCBlbGVtZW50cy5cbiAgICovXG4gIHJlYWRvbmx5IHNldDogKC4uLmluZGljZXNBbmRWYWx1ZTogUmVhZG9ubHlBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdHU0wgY29kZSBmb3IgYSBzdGF0ZW1lbnQgZm9yIHNldHRpbmcgZGF0YSBhdCB0aGUgZ2l2ZW4gaW5kaWNlcyB2YXJpYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHZhckluZGljZXMgLSBhIHZhcmlhYmxlIG5hbWUgZm9yIHRoZSBpbmRpY2VzLlxuICAgKiBAcGFyYW0gdmFsdWUgLSB0aGUgdmFsdWUgdG8gc2V0LiBzaG91bGQgYmUgYSBXR1NMIGV4cHJlc3Npb24uXG4gICAqL1xuICByZWFkb25seSBzZXRCeUluZGljZXM6ICh2YXJJbmRpY2VzOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpID0+IHN0cmluZztcblxuICAvKipcbiAgICogV0dTTCBjb2RlIGZvciBhIHN0YXRlbWVudCBmb3Igc2V0dGluZyBkYXRhIGF0IHRoZSBnaXZlbiBvZmZzZXQuXG4gICAqXG4gICAqIEBwYXJhbSBvZmZzZXQgLSBhIG51bWJlciBvciBhIHN0cmluZyAoV0dTTCBgdTMyYCBleHByZXNzaW9uKSByZXByZXNlbnRpbmcgdGhlIG9mZnNldC5cbiAgICogQHBhcmFtIHZhbHVlIC0gdGhlIHZhbHVlIHRvIHNldC4gc2hvdWxkIGJlIGEgV0dTTCBleHByZXNzaW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgc2V0QnlPZmZzZXQ6IChvZmZzZXQ6IG51bWJlciB8IHN0cmluZywgdmFsdWU6IHN0cmluZykgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgZm9yIGFuIGV4cHJlc3Npb24gZm9yIGdldHRpbmcgZGF0YSBhdCB0aGUgZ2l2ZW4gaW5kaWNlcy5cbiAgICpcbiAgICogQHBhcmFtIGluZGljZXMgLSBhbiBhcnJheSBvZiBudW1iZXJzIG9yIHN0cmluZ3MgKFdHU0wgYHUzMmAgZXhwcmVzc2lvbikgcmVwcmVzZW50aW5nIHRoZSBpbmRpY2VzLlxuICAgKi9cbiAgcmVhZG9ubHkgZ2V0OiAoLi4uaW5kaWNlczogUmVhZG9ubHlBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdHU0wgY29kZSBmb3IgYW4gZXhwcmVzc2lvbiBmb3IgZ2V0dGluZyBkYXRhIGF0IHRoZSBnaXZlbiBpbmRpY2VzIHZhcmlhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gdmFySW5kaWNlcyAtIGEgdmFyaWFibGUgbmFtZSBmb3IgdGhlIGluZGljZXMuXG4gICAqL1xuICByZWFkb25seSBnZXRCeUluZGljZXM6ICh2YXJJbmRpY2VzOiBzdHJpbmcpID0+IHN0cmluZztcblxuICAvKipcbiAgICogV0dTTCBjb2RlIGZvciBhbiBleHByZXNzaW9uIGZvciBnZXR0aW5nIGRhdGEgYXQgdGhlIGdpdmVuIG9mZnNldC5cbiAgICpcbiAgICogQHBhcmFtIG9mZnNldCAtIGEgbnVtYmVyIG9yIGEgc3RyaW5nIChXR1NMIGB1MzJgIGV4cHJlc3Npb24pIHJlcHJlc2VudGluZyB0aGUgb2Zmc2V0LlxuICAgKi9cbiAgcmVhZG9ubHkgZ2V0QnlPZmZzZXQ6IChvZmZzZXQ6IG51bWJlciB8IHN0cmluZykgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBuYW1lIG9mIHRoZSBkYXRhIHZhcmlhYmxlXG4gICAqL1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIHdoZXRoZXIgdGhlIGhlbHBlciBpcyBmb3IgYW4gaW5wdXQsIGFuIG91dHB1dCBvciBhbiBpbnRlcm5hbCB2YXJpYWJsZS5cbiAgICovXG4gIHJlYWRvbmx5IHVzYWdlOiAnaW5wdXQnIHwgJ291dHB1dCcgfCAnYXRvbWljT3V0cHV0JyB8ICdpbnRlcm5hbCc7XG5cbiAgLyoqXG4gICAqIHRoZSByYW5rIG9mIHRoZSBpbnB1dCBvciBvdXRwdXQuXG4gICAqL1xuICByZWFkb25seSByYW5rOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIGEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgdmFyaWFibGUgbmFtZSBmb3IgdGhlIHNoYXBlIG9mIHRoZSBpbnB1dCBvciBvdXRwdXQuXG4gICAqL1xuICByZWFkb25seSBzaGFwZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBhIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIHZhcmlhYmxlIG5hbWUgZm9yIHRoZSBzdHJpZGVzIG9mIHRoZSBpbnB1dCBvciBvdXRwdXQuXG4gICAqL1xuICByZWFkb25seSBzdHJpZGVzOiBzdHJpbmc7XG59XG5cbmNvbnN0IGdldFdnc2xNYXBwZWRUeXBlID0gKHR5cGU6IG51bWJlciwgY29tcG9uZW50czogMSB8IDIgfCAzIHwgNCk6IHN0cmluZyB8IFtzdHJpbmcsIHN0cmluZ10gPT4ge1xuICBpZiAoY29tcG9uZW50cyA9PT0gMykge1xuICAgIHRocm93IG5ldyBFcnJvcigndmVjMyBoYXMgc2FtZSBhbGlnbm1lbnQgYXMgdmVjNCwgdXNlIHZlYzQgaW5zdGVhZCcpO1xuICB9XG5cbiAgLy8gcmV0dXJuIHR5cGUgaXMgWyBzdG9yYWdlIHR5cGUsIHJ1bnRpbWUgdHlwZSBdIG9yIGEgc2luZ2xlIHN0cmluZyBmb3IgYm90aFxuICBzd2l0Y2ggKE51bWJlcih0eXBlKSkge1xuICAgIGNhc2UgRGF0YVR5cGUuZmxvYXQxNjpcbiAgICAgIHJldHVybiBjb21wb25lbnRzID4gMSA/IGB2ZWMke2NvbXBvbmVudHN9PGYxNj5gIDogJ2YxNic7XG4gICAgY2FzZSBEYXRhVHlwZS5mbG9hdDpcbiAgICAgIHJldHVybiBjb21wb25lbnRzID4gMSA/IGB2ZWMke2NvbXBvbmVudHN9PGYzMj5gIDogJ2YzMic7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQzMjpcbiAgICAgIHJldHVybiBjb21wb25lbnRzID4gMSA/IGB2ZWMke2NvbXBvbmVudHN9PGkzMj5gIDogJ2kzMic7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50MzI6XG4gICAgICByZXR1cm4gY29tcG9uZW50cyA+IDEgPyBgdmVjJHtjb21wb25lbnRzfTx1MzI+YCA6ICd1MzInO1xuICAgIGNhc2UgRGF0YVR5cGUuaW50NjQ6XG4gICAgICBpZiAoY29tcG9uZW50cyA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjdXJyZW50bHkgbm90IHN1cHBvcnRlZCB2ZWNYIG9mIHVpbnQ2NCB5ZXQnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBbJ3ZlYzI8dTMyPicsICdpMzInXTtcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQ2NDpcbiAgICAgIGlmIChjb21wb25lbnRzID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnRseSBub3Qgc3VwcG9ydGVkIHZlY1ggb2YgdWludDY0IHlldCcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFsndmVjMjx1MzI+JywgJ3UzMiddO1xuICAgIGNhc2UgRGF0YVR5cGUuYm9vbDpcbiAgICAgIGlmIChjb21wb25lbnRzICE9PSA0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYm9vbCBtdXN0IGJlIHZlYzQnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBbJ3UzMicsICd2ZWM0PGJvb2w+J107XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQ0OlxuICAgICAgcmV0dXJuICdpMzInO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDQ6XG4gICAgICByZXR1cm4gJ3UzMic7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBkYXRhIHR5cGU6ICR7dHlwZX1gKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSA9ICh0eXBlOiBEYXRhVHlwZSwgY29tcG9uZW50czogMSB8IDIgfCAzIHwgNCA9IDEpID0+IHtcbiAgY29uc3QgbWFwcGVkVHlwZSA9IGdldFdnc2xNYXBwZWRUeXBlKHR5cGUsIGNvbXBvbmVudHMpO1xuICByZXR1cm4gdHlwZW9mIG1hcHBlZFR5cGUgPT09ICdzdHJpbmcnID8gbWFwcGVkVHlwZSA6IG1hcHBlZFR5cGVbMF07XG59O1xuXG5leHBvcnQgY29uc3QgdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZSA9ICh0eXBlOiBEYXRhVHlwZSwgY29tcG9uZW50czogMSB8IDIgfCAzIHwgNCA9IDEpID0+IHtcbiAgY29uc3QgbWFwcGVkVHlwZSA9IGdldFdnc2xNYXBwZWRUeXBlKHR5cGUsIGNvbXBvbmVudHMpO1xuICByZXR1cm4gdHlwZW9mIG1hcHBlZFR5cGUgPT09ICdzdHJpbmcnID8gbWFwcGVkVHlwZSA6IG1hcHBlZFR5cGVbMV07XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMgPSAoLi4uZGltczogUmVhZG9ubHlBcnJheTxyZWFkb25seSBudW1iZXJbXT4pOiBQcm9ncmFtVW5pZm9ybVtdID0+IHtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW107XG4gIGRpbXMuZm9yRWFjaCgoZGltKSA9PiB7XG4gICAgaWYgKGRpbS5sZW5ndGggIT09IDApIHtcbiAgICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKFxuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZGltIH0sXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBTaGFwZVV0aWwuY29tcHV0ZVN0cmlkZXMoZGltKSB9LFxuICAgICAgKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gcHJvZ3JhbVVuaWZvcm1zO1xufTtcblxuLyoqXG4gKiBBIGhlbHBlciBmdW5jdGlvbiB0byBnZXQgbWF4aW11bSB2ZWN0b3Igc2l6ZSBmb3Igc3BlY2lmaWVkIGRhdGEgbGVuZ3RoXG4gKiBAcGFyYW0gc2l6ZVxuICovXG5leHBvcnQgY29uc3QgZ2V0TWF4Q29tcG9uZW50cyA9IChzaXplOiBudW1iZXIpID0+IHtcbiAgLy8gd2UgY2Fubm90IHVzZSB2ZWMzIHR5cGUgc2luY2UgaXQgaGFzIGFsaWdubWVudCBvZiAxNiBieXRlc1xuICBpZiAoc2l6ZSAlIDQgPT09IDApIHtcbiAgICByZXR1cm4gNDtcbiAgfSBlbHNlIGlmIChzaXplICUgMiA9PT0gMCkge1xuICAgIHJldHVybiAyO1xuICB9XG5cbiAgcmV0dXJuIDE7XG59O1xuXG4vKipcbiAqIEEgaGVscGVyIGZ1bmN0aW9uIHRoYXQgaW5pdGlhbGl6ZXMgdmFyaWFibGUgYXMgYSBzY2FsYXIgb3IgdmVjdG9yLiBlLmcuIGYzMigwKSBvciB2ZWM0ZigwLDAsMCwwKVxuICogQHBhcmFtIGRhdGFUeXBlXG4gKiBAcGFyYW0gY29tcG9uZW50c1xuICogQHBhcmFtIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCBmaWxsVmVjdG9yID0gKGRhdGFUeXBlID0gJ2YzMicsIGNvbXBvbmVudHM/OiBudW1iZXIsIHZhbHVlID0gJzAnKSA9PiB7XG4gIGlmICghY29tcG9uZW50cyB8fCBjb21wb25lbnRzID09PSAxKSB7XG4gICAgcmV0dXJuIGAke2RhdGFUeXBlfSgke3ZhbHVlfSlgO1xuICB9XG5cbiAgcmV0dXJuIGB2ZWMke2NvbXBvbmVudHN9PCR7ZGF0YVR5cGV9Pigke3ZhbHVlfSlgO1xufTtcblxuLyoqXG4gKiBBIGhlbHBlciBmdW5jdGlvbiB0aGF0IGNhc3RzIHZhbHVlIG9yIHZlY3RvciB0byBmMzJcbiAqIEBwYXJhbSBkYXRhVHlwZVxuICogQHBhcmFtIGNvbXBvbmVudHNcbiAqIEBwYXJhbSB2YWx1ZVxuICovXG5leHBvcnQgY29uc3QgY2FzdFRvRjMyID0gKGRhdGFUeXBlOiBzdHJpbmcsIGNvbXBvbmVudHM6IG51bWJlciwgdmFsdWU6IHN0cmluZykgPT4ge1xuICBpZiAoZGF0YVR5cGUgPT09ICdmMzInKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIGlmIChjb21wb25lbnRzID09PSAxKSB7XG4gICAgcmV0dXJuIGBmMzIoJHt2YWx1ZX0pYDtcbiAgfVxuXG4gIHJldHVybiBgdmVjJHtjb21wb25lbnRzfTxmMzI+KCR7dmFsdWV9KWA7XG59O1xuXG4vKipcbiAqIEEgaGVscGVyIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBzY2FsYXIgb3Igc3VtcyBhbGwgY29tcG9uZW50cyBvZiBhIHZlY3RvclxuICogQHBhcmFtIG5hbWVcbiAqIEBwYXJhbSBjb21wb25lbnRzXG4gKi9cbmV4cG9ydCBjb25zdCBzdW1WZWN0b3IgPSAobmFtZTogc3RyaW5nLCBjb21wb25lbnRzOiBudW1iZXIpID0+IHtcbiAgaWYgKGNvbXBvbmVudHMgPT09IDQpIHtcbiAgICByZXR1cm4gYCgke25hbWV9LnggKyAke25hbWV9LnkgKyAke25hbWV9LnogKyAke25hbWV9LncpYDtcbiAgfSBlbHNlIGlmIChjb21wb25lbnRzID09PSAyKSB7XG4gICAgcmV0dXJuIGAoJHtuYW1lfS54ICsgJHtuYW1lfS55KWA7XG4gIH0gZWxzZSBpZiAoY29tcG9uZW50cyA9PT0gMykge1xuICAgIHJldHVybiBgKCR7bmFtZX0ueCArICR7bmFtZX0ueSArICR7bmFtZX0ueilgO1xuICB9XG5cbiAgcmV0dXJuIG5hbWU7XG59O1xuXG4vKipcbiAqIEEgaGVscGVyIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB2YXJpYWJsZSBlbGVtZW50IGF0IGluZGV4LlxuICogQHBhcmFtIG5hbWUgLSB0aGUgbmFtZSBvZiB2YXJpYWJsZS5cbiAqIEBwYXJhbSBpbmRleCAtIHRoZSBpbmRleCBvZiB2YXJpYWJsZSBlbGVtZW50LlxuICogQHBhcmFtIGxlbmd0aCAtIHRoZSBsZW5ndGggb2YgdmFyaWFibGUuXG4gKiBAcGFyYW0gdHlwZSAtIHRoZSB0eXBlIG9mIHZhcmlhYmxlLCBvcHRpb25hbC5cbiAqL1xuZXhwb3J0IGNvbnN0IGdldEVsZW1lbnRBdCA9IChcbiAgbmFtZTogc3RyaW5nLFxuICBpbmRleDogbnVtYmVyIHwgc3RyaW5nLFxuICBsZW5ndGg6IG51bWJlcixcbiAgdHlwZT86IFVuaWZvcm1EYXRhRWxlbWVudFR5cGUsXG4pOiBzdHJpbmcgPT4ge1xuICBpZiAobmFtZS5zdGFydHNXaXRoKCd1bmlmb3Jtcy4nKSAmJiBsZW5ndGggPiA0KSB7XG4gICAgaWYgKHR5cGVvZiBpbmRleCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlmICh0eXBlID09PSAnZjE2Jykge1xuICAgICAgICByZXR1cm4gYCR7bmFtZX1bKCR7aW5kZXh9KSAvIDhdWygke2luZGV4fSkgJSA4IC8gNF1bKCR7aW5kZXh9KSAlIDggJSA0XWA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gYCR7bmFtZX1bKCR7aW5kZXh9KSAvIDRdWygke2luZGV4fSkgJSA0XWA7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0eXBlID09PSAnZjE2Jykge1xuICAgICAgICByZXR1cm4gYCR7bmFtZX1bJHtNYXRoLmZsb29yKGluZGV4IC8gOCl9XVske01hdGguZmxvb3IoKGluZGV4ICUgOCkgLyA0KX1dWyR7KGluZGV4ICUgOCkgJSA0fV1gO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGAke25hbWV9WyR7TWF0aC5mbG9vcihpbmRleCAvIDQpfV1bJHtpbmRleCAlIDR9XWA7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBsZW5ndGggPiAxID8gYCR7bmFtZX1bJHtpbmRleH1dYCA6IG5hbWU7XG4gIH1cbn07XG5cbi8qKlxuICogQSBoZWxwZXIgZnVuY3Rpb24gdG8gZ2V0IGEgSW5kaWNlc0hlbHBlciBmb3IgYSBnaXZlbiBpbnB1dCBvciBvdXRwdXQuXG4gKlxuICogQHBhcmFtIG5hbWUgLSB0aGUgbmFtZSBvZiB0aGUgaW5wdXQgb3Igb3V0cHV0LlxuICogQHBhcmFtIHRlbnNvclR5cGUgLSB0aGUgdGVuc29yIHR5cGUgb2YgdGhlIGlucHV0IG9yIG91dHB1dC5cbiAqIEBwYXJhbSBzaGFwZU9yUmFuayAtIHRoZSB0ZW5zb3Igc2hhcGUgb3IgdGhlIHJhbmsgb2YgdGhlIGlucHV0IG9yIG91dHB1dC5cbiAqIEBwYXJhbSB1c2FnZSAtIHRoZSB1c2FnZSBvZiB0aGUgaW5kaWNlcyBoZWxwZXIuXG4gKiBAcGFyYW0gY29tcG9uZW50cyAtIGluZGljYXRlcyB0aGUgbnVtYmVyIG9mIGNvbXBvbmVudHMgb2YgZWFjaCBlbGVtZW50LiAxIGZvciBzY2FsYXIsIDIgZm9yIHZlYzIsIDMgZm9yIHZlYzMsIDQgZm9yXG4gKiAgICB2ZWM0LlxuICovXG5jb25zdCBjcmVhdGVJbmRpY2VzSGVscGVyID0gKFxuICBuYW1lOiBzdHJpbmcsXG4gIHRlbnNvclR5cGU6IG51bWJlcixcbiAgc2hhcGVPclJhbms6IG51bWJlciB8IHJlYWRvbmx5IG51bWJlcltdLFxuICB1c2FnZTogSW5kaWNlc0hlbHBlclsndXNhZ2UnXSxcbiAgY29tcG9uZW50czogMSB8IDIgfCAzIHwgNCxcbik6IEluZGljZXNIZWxwZXIgPT4ge1xuICBjb25zdCB1c2VVbmlmb3JtID0gdHlwZW9mIHNoYXBlT3JSYW5rID09PSAnbnVtYmVyJztcbiAgY29uc3QgcmFuayA9IHVzZVVuaWZvcm0gPyBzaGFwZU9yUmFuayA6IHNoYXBlT3JSYW5rLmxlbmd0aDtcbiAgY29uc3QgcmFua0lkZW50aXR5ID0gWy4uLm5ldyBBcnJheShyYW5rKS5rZXlzKCldO1xuICBjb25zdCBpbmRpY2VzVHlwZSA9IHJhbmsgPCAyID8gJ3UzMicgOiByYW5rIDw9IDQgPyBgdmVjJHtyYW5rfTx1MzI+YCA6IGBhcnJheTx1MzIsICR7cmFua30+YDtcbiAgY29uc3QgbWFwcGVkVHlwZSA9IGdldFdnc2xNYXBwZWRUeXBlKHRlbnNvclR5cGUsIGNvbXBvbmVudHMpO1xuICBjb25zdCB2YWx1ZVR5cGUgPSB0eXBlb2YgbWFwcGVkVHlwZSA9PT0gJ3N0cmluZycgPyBtYXBwZWRUeXBlIDogbWFwcGVkVHlwZVsxXTtcbiAgY29uc3Qgc3RvcmFnZVR5cGUgPSB0eXBlb2YgbWFwcGVkVHlwZSA9PT0gJ3N0cmluZycgPyBtYXBwZWRUeXBlIDogbWFwcGVkVHlwZVswXTtcbiAgY29uc3QgdHlwZSA9IHsgaW5kaWNlczogaW5kaWNlc1R5cGUsIHZhbHVlOiB2YWx1ZVR5cGUsIHN0b3JhZ2U6IHN0b3JhZ2VUeXBlLCB0ZW5zb3I6IHRlbnNvclR5cGUgfTtcblxuICBjb25zdCBub3JtYWxpemVEaW0gPSAoZGltOiBudW1iZXIgfCBzdHJpbmcpOiBzdHJpbmcgPT4gKHR5cGVvZiBkaW0gPT09ICdzdHJpbmcnID8gZGltIDogYCR7ZGltfXVgKTtcblxuICBjb25zdCBpbXBsZW1lbnRhdGlvblVzZWQgPSB7XG4gICAgb2Zmc2V0VG9JbmRpY2VzOiBmYWxzZSxcbiAgICBpbmRpY2VzVG9PZmZzZXQ6IGZhbHNlLFxuICAgIGJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0OiBmYWxzZSxcbiAgICBzZXQ6IGZhbHNlLFxuICAgIHNldEJ5SW5kaWNlczogZmFsc2UsXG4gICAgZ2V0OiBmYWxzZSxcbiAgICBnZXRCeUluZGljZXM6IGZhbHNlLFxuICB9O1xuXG4gIGNvbnN0IHVuaWZvcm1QcmVmaXggPSB1c2VVbmlmb3JtID8gJ3VuaWZvcm1zLicgOiAnJztcbiAgY29uc3Qgc2hhcGUgPSBgJHt1bmlmb3JtUHJlZml4fSR7bmFtZX1fc2hhcGVgO1xuICBjb25zdCBzdHJpZGVzID0gYCR7dW5pZm9ybVByZWZpeH0ke25hbWV9X3N0cmlkZXNgO1xuXG4gIGxldCBvMmlTbmlwcGV0ID0gJyc7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuayAtIDE7IGkrKykge1xuICAgIG8yaVNuaXBwZXQgKz0gYFxuICAgIGxldCBkaW0ke2l9ID0gY3VycmVudCAvICR7Z2V0RWxlbWVudEF0KHN0cmlkZXMsIGksIHJhbmspfTtcbiAgICBsZXQgcmVzdCR7aX0gPSBjdXJyZW50ICUgJHtnZXRFbGVtZW50QXQoc3RyaWRlcywgaSwgcmFuayl9O1xuICAgIGluZGljZXNbJHtpfV0gPSBkaW0ke2l9O1xuICAgIGN1cnJlbnQgPSByZXN0JHtpfTtcbiAgICBgO1xuICB9XG4gIG8yaVNuaXBwZXQgKz0gYGluZGljZXNbJHtyYW5rIC0gMX1dID0gY3VycmVudDtgO1xuXG4gIGNvbnN0IG9mZnNldFRvSW5kaWNlc0ltcGxlbWVudGF0aW9uID1cbiAgICByYW5rIDwgMlxuICAgICAgPyAnJ1xuICAgICAgOiBgXG4gIGZuIG8yaV8ke25hbWV9KG9mZnNldDogdTMyKSAtPiAke3R5cGUuaW5kaWNlc30ge1xuICAgIHZhciBpbmRpY2VzOiAke3R5cGUuaW5kaWNlc307XG4gICAgdmFyIGN1cnJlbnQgPSBvZmZzZXQ7XG4gICAgJHtvMmlTbmlwcGV0fVxuICAgIHJldHVybiBpbmRpY2VzO1xuICB9YDtcblxuICBjb25zdCBvZmZzZXRUb0luZGljZXMgPSAodmFyT2Zmc2V0OiBzdHJpbmcpID0+IHtcbiAgICBpbXBsZW1lbnRhdGlvblVzZWQub2Zmc2V0VG9JbmRpY2VzID0gdHJ1ZTtcbiAgICByZXR1cm4gcmFuayA8IDIgPyB2YXJPZmZzZXQgOiBgbzJpXyR7bmFtZX0oJHt2YXJPZmZzZXR9KWA7XG4gIH07XG5cbiAgY29uc3Qgb2Zmc2V0czogc3RyaW5nW10gPSBbXTtcbiAgaWYgKHJhbmsgPj0gMikge1xuICAgIGZvciAobGV0IGkgPSByYW5rIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIG9mZnNldHMucHVzaChgJHtnZXRFbGVtZW50QXQoc3RyaWRlcywgaSwgcmFuayl9ICogKGluZGljZXNbJHtpfV0pYCk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgaW5kaWNlc1RvT2Zmc2V0SW1wbGVtZW50YXRpb24gPVxuICAgIHJhbmsgPCAyXG4gICAgICA/ICcnXG4gICAgICA6IGBcbiAgZm4gaTJvXyR7bmFtZX0oaW5kaWNlczogJHt0eXBlLmluZGljZXN9KSAtPiB1MzIge1xuICAgIHJldHVybiAke29mZnNldHMuam9pbignKycpfTtcbiAgfWA7XG5cbiAgY29uc3QgaW5kaWNlc1RvT2Zmc2V0ID0gKHZhckluZGljZXM6IHN0cmluZykgPT4ge1xuICAgIGltcGxlbWVudGF0aW9uVXNlZC5pbmRpY2VzVG9PZmZzZXQgPSB0cnVlO1xuICAgIHJldHVybiByYW5rIDwgMiA/IHZhckluZGljZXMgOiBgaTJvXyR7bmFtZX0oJHt2YXJJbmRpY2VzfSlgO1xuICB9O1xuXG4gIGNvbnN0IGluZGljZXMgPSAoLi4uaW5pdDogUmVhZG9ubHlBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PlxuICAgIHJhbmsgPT09IDAgPyAnMHUnIDogYCR7dHlwZS5pbmRpY2VzfSgke2luaXQubWFwKG5vcm1hbGl6ZURpbSkuam9pbignLCcpfSlgO1xuXG4gIGNvbnN0IGluZGljZXNHZXQgPSAodmFySW5kaWNlczogc3RyaW5nLCBpZHg6IG51bWJlciB8IHN0cmluZykgPT4ge1xuICAgIGlmIChyYW5rIDwgMikge1xuICAgICAgcmV0dXJuIGAke3ZhckluZGljZXN9YDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGAke2dldEVsZW1lbnRBdCh2YXJJbmRpY2VzLCBpZHgsIHJhbmspfWA7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGluZGljZXNTZXQgPSAodmFySW5kaWNlczogc3RyaW5nLCBpZHg6IG51bWJlciB8IHN0cmluZywgdmFsdWU6IHN0cmluZykgPT4ge1xuICAgIGlmIChyYW5rIDwgMikge1xuICAgICAgcmV0dXJuIGAke3ZhckluZGljZXN9PSR7dmFsdWV9O2A7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBgJHtnZXRFbGVtZW50QXQodmFySW5kaWNlcywgaWR4LCByYW5rKX09JHt2YWx1ZX07YDtcbiAgICB9XG4gIH07XG5cbiAgY29uc3QgYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXRJbXBsZW1lbnRhdGlvbjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICBjb25zdCBicm9hZGNhc3RlZEluZGljZXNUb09mZnNldCA9ICh2YXJJbmRpY2VzOiBzdHJpbmcsIG91dHB1dDogSW5kaWNlc0hlbHBlcikgPT4ge1xuICAgIGltcGxlbWVudGF0aW9uVXNlZC5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldCA9IHRydWU7XG4gICAgY29uc3QgaW1wbEtleSA9IGAke291dHB1dC5uYW1lfWJyb2FkY2FzdGVkSW5kaWNlc1RvJHtuYW1lfU9mZnNldGA7XG4gICAgaWYgKGltcGxLZXkgaW4gYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXRJbXBsZW1lbnRhdGlvbikge1xuICAgICAgcmV0dXJuIGAke2ltcGxLZXl9KCR7dmFySW5kaWNlc30pYDtcbiAgICB9XG4gICAgY29uc3Qgb2Zmc2V0cyA9IFtdO1xuICAgIGZvciAobGV0IGkgPSByYW5rIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGNvbnN0IGlkeCA9IG91dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRJbmRpY2VzJywgaSArIG91dHB1dC5yYW5rIC0gcmFuayk7XG4gICAgICBvZmZzZXRzLnB1c2goYCR7aW5kaWNlc0dldChzdHJpZGVzLCBpKX0gKiAoJHtpZHh9ICUgJHtpbmRpY2VzR2V0KHNoYXBlLCBpKX0pYCk7XG4gICAgfVxuICAgIGJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0SW1wbGVtZW50YXRpb25baW1wbEtleV0gPSBgZm4gJHtpbXBsS2V5fShvdXRwdXRJbmRpY2VzOiAke291dHB1dC50eXBlLmluZGljZXN9KSAtPiB1MzIge1xuICAgICAgICAgICAgIHJldHVybiAke29mZnNldHMubGVuZ3RoID4gMCA/IG9mZnNldHMuam9pbignKycpIDogJzB1J307XG4gICAgICAgICAgIH1gO1xuXG4gICAgcmV0dXJuIGAke2ltcGxLZXl9KCR7dmFySW5kaWNlc30pYDtcbiAgfTtcblxuICBjb25zdCBzZXRCeU9mZnNldCA9IChvZmZzZXQ6IG51bWJlciB8IHN0cmluZywgdmFsdWU6IHN0cmluZykgPT5cbiAgICAoKCkgPT4ge1xuICAgICAgaWYgKHR5cGUuc3RvcmFnZSA9PT0gdHlwZS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gYCR7bmFtZX1bJHtvZmZzZXR9XT0ke3ZhbHVlfTtgO1xuICAgICAgfSBlbHNlIGlmICh0eXBlLnN0b3JhZ2UgPT09ICd2ZWMyPHUzMj4nICYmIHR5cGUudmFsdWUgPT09ICdpMzInKSB7XG4gICAgICAgIC8vIGludDY0LCBjb21wb25lbnRzID09PSAxXG4gICAgICAgIHJldHVybiBgJHtuYW1lfVske29mZnNldH1dPXZlYzI8dTMyPih1MzIoJHt2YWx1ZX0pLCBzZWxlY3QoMHUsIDB4RkZGRkZGRkZ1LCAke3ZhbHVlfSA8IDApKTtgO1xuICAgICAgfSBlbHNlIGlmICh0eXBlLnN0b3JhZ2UgPT09ICd2ZWMyPHUzMj4nICYmIHR5cGUudmFsdWUgPT09ICd1MzInKSB7XG4gICAgICAgIC8vIHVpbnQ2NCwgY29tcG9uZW50cyA9PT0gMVxuICAgICAgICByZXR1cm4gYCR7bmFtZX1bJHtvZmZzZXR9XT12ZWMyPHUzMj4odTMyKCR7dmFsdWV9KSwgMHUpO2A7XG4gICAgICB9IGVsc2UgaWYgKHR5cGUuc3RvcmFnZSA9PT0gJ3UzMicgJiYgdHlwZS52YWx1ZSA9PT0gJ3ZlYzQ8Ym9vbD4nKSB7XG4gICAgICAgIC8vIGJvb2wsIGNvbXBvbmVudHMgPT09IDRcbiAgICAgICAgcmV0dXJuIGAke25hbWV9WyR7b2Zmc2V0fV09ZG90KHZlYzQ8dTMyPigweDEsIDB4MTAwLCAweDEwMDAwLCAweDEwMDAwMDApLCB2ZWM0PHUzMj4oJHt2YWx1ZX0pKTtgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGNvbWJpbmF0aW9uIG9mIHN0b3JhZ2UgdHlwZSAke3R5cGUuc3RvcmFnZX0gYW5kIHZhbHVlIHR5cGUgJHt0eXBlLnZhbHVlfSB5ZXRgKTtcbiAgICAgIH1cbiAgICB9KSgpO1xuXG4gIGNvbnN0IGdldEJ5T2Zmc2V0ID0gKG9mZnNldDogbnVtYmVyIHwgc3RyaW5nKSA9PlxuICAgICgoKSA9PiB7XG4gICAgICBpZiAodHlwZS5zdG9yYWdlID09PSB0eXBlLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiBgJHtuYW1lfVske29mZnNldH1dYDtcbiAgICAgIH0gZWxzZSBpZiAodHlwZS5zdG9yYWdlID09PSAndmVjMjx1MzI+JyAmJiB0eXBlLnZhbHVlID09PSAnaTMyJykge1xuICAgICAgICAvLyBpbnQ2NCwgY29tcG9uZW50cyA9PT0gMVxuICAgICAgICByZXR1cm4gYGkzMigke25hbWV9WyR7b2Zmc2V0fV0ueClgO1xuICAgICAgfSBlbHNlIGlmICh0eXBlLnN0b3JhZ2UgPT09ICd2ZWMyPHUzMj4nICYmIHR5cGUudmFsdWUgPT09ICd1MzInKSB7XG4gICAgICAgIC8vIHVpbnQ2NCwgY29tcG9uZW50cyA9PT0gMVxuICAgICAgICByZXR1cm4gYHUzMigke25hbWV9WyR7b2Zmc2V0fV0ueClgO1xuICAgICAgfSBlbHNlIGlmICh0eXBlLnN0b3JhZ2UgPT09ICd1MzInICYmIHR5cGUudmFsdWUgPT09ICd2ZWM0PGJvb2w+Jykge1xuICAgICAgICAvLyBib29sLCBjb21wb25lbnRzID09PSA0XG4gICAgICAgIHJldHVybiBgdmVjNDxib29sPihib29sKCR7bmFtZX1bJHtvZmZzZXR9XSAmIDB4RkZ1KSwgYm9vbCgke25hbWV9WyR7b2Zmc2V0fV0gJiAweEZGMDB1KSwgYm9vbCgke25hbWV9WyR7XG4gICAgICAgICAgb2Zmc2V0XG4gICAgICAgIH1dICYgMHhGRjAwMDB1KSwgYm9vbCgke25hbWV9WyR7b2Zmc2V0fV0gJiAweEZGMDAwMDAwdSkpYDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm90IHN1cHBvcnRlZCBjb21iaW5hdGlvbiBvZiBzdG9yYWdlIHR5cGUgJHt0eXBlLnN0b3JhZ2V9IGFuZCB2YWx1ZSB0eXBlICR7dHlwZS52YWx1ZX0geWV0YCk7XG4gICAgICB9XG4gICAgfSkoKTtcblxuICBjb25zdCBnZXRCeUluZGljZXNJbXBsZW1lbnRhdGlvbiA9XG4gICAgcmFuayA8IDJcbiAgICAgID8gJydcbiAgICAgIDogYFxuICBmbiBnZXRfJHtuYW1lfUJ5SW5kaWNlcyhpbmRpY2VzOiAke3R5cGUuaW5kaWNlc30pIC0+ICR7dmFsdWVUeXBlfSB7XG4gICAgcmV0dXJuICR7Z2V0QnlPZmZzZXQoYGkyb18ke25hbWV9KGluZGljZXMpYCl9O1xuICB9YDtcblxuICBjb25zdCBnZXRJbXBsZW1lbnRhdGlvbiA9XG4gICAgcmFuayA8IDJcbiAgICAgID8gJydcbiAgICAgIDogKCgpID0+IHtcbiAgICAgICAgICBjb25zdCBmdW5jdGlvblBhcmFtcyA9IHJhbmtJZGVudGl0eS5tYXAoKGkpID0+IGBkJHtpfTogdTMyYCkuam9pbignLCAnKTtcbiAgICAgICAgICBjb25zdCBkaW1zUGFyYW1zID0gcmFua0lkZW50aXR5Lm1hcCgoaSkgPT4gYGQke2l9YCkuam9pbignLCAnKTtcbiAgICAgICAgICByZXR1cm4gYFxuICBmbiBnZXRfJHtuYW1lfSgke2Z1bmN0aW9uUGFyYW1zfSkgLT4gJHt2YWx1ZVR5cGV9IHtcbiAgICByZXR1cm4gZ2V0XyR7bmFtZX1CeUluZGljZXMoJHtpbmRpY2VzKGRpbXNQYXJhbXMpfSk7XG4gIH1gO1xuICAgICAgICB9KSgpO1xuXG4gIGNvbnN0IGdldCA9ICguLi5pbmRpY2VzOiBSZWFkb25seUFycmF5PG51bWJlciB8IHN0cmluZz4pID0+IHtcbiAgICBpZiAoaW5kaWNlcy5sZW5ndGggIT09IHJhbmspIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW5kaWNlcyBsZW5ndGggbXVzdCBiZSAke3Jhbmt9YCk7XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZEluZGljZXMgPSBpbmRpY2VzLm1hcChub3JtYWxpemVEaW0pLmpvaW4oJywnKTtcblxuICAgIGlmIChyYW5rID09PSAwKSB7XG4gICAgICByZXR1cm4gZ2V0QnlPZmZzZXQoJzB1Jyk7XG4gICAgfSBlbHNlIGlmIChyYW5rID09PSAxKSB7XG4gICAgICByZXR1cm4gZ2V0QnlPZmZzZXQobm9ybWFsaXplZEluZGljZXNbMF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBpbXBsZW1lbnRhdGlvblVzZWQuZ2V0ID0gdHJ1ZTtcbiAgICAgIGltcGxlbWVudGF0aW9uVXNlZC5nZXRCeUluZGljZXMgPSB0cnVlO1xuICAgICAgaW1wbGVtZW50YXRpb25Vc2VkLmluZGljZXNUb09mZnNldCA9IHRydWU7XG4gICAgICByZXR1cm4gYGdldF8ke25hbWV9KCR7bm9ybWFsaXplZEluZGljZXN9KWA7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGdldEJ5SW5kaWNlcyA9ICh2YXJJbmRpY2VzOiBzdHJpbmcpID0+IHtcbiAgICBpZiAocmFuayA8IDIpIHtcbiAgICAgIHJldHVybiBnZXRCeU9mZnNldCh2YXJJbmRpY2VzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaW1wbGVtZW50YXRpb25Vc2VkLmdldEJ5SW5kaWNlcyA9IHRydWU7XG4gICAgICBpbXBsZW1lbnRhdGlvblVzZWQuaW5kaWNlc1RvT2Zmc2V0ID0gdHJ1ZTtcbiAgICAgIHJldHVybiBgZ2V0XyR7bmFtZX1CeUluZGljZXMoJHt2YXJJbmRpY2VzfSlgO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCBzZXRCeUluZGljZXNJbXBsZW1lbnRhdGlvbiA9XG4gICAgcmFuayA8IDJcbiAgICAgID8gJydcbiAgICAgIDogYFxuICBmbiBzZXRfJHtuYW1lfUJ5SW5kaWNlcyhpbmRpY2VzOiAke3R5cGUuaW5kaWNlc30sIHZhbHVlOiAke3ZhbHVlVHlwZX0pIHtcbiAgICAke3NldEJ5T2Zmc2V0KGBpMm9fJHtuYW1lfShpbmRpY2VzKWAsICd2YWx1ZScpfVxuICB9YDtcblxuICBjb25zdCBzZXRJbXBsZW1lbnRhdGlvbiA9XG4gICAgcmFuayA8IDJcbiAgICAgID8gJydcbiAgICAgIDogKCgpID0+IHtcbiAgICAgICAgICBjb25zdCBmdW5jdGlvblBhcmFtcyA9IHJhbmtJZGVudGl0eS5tYXAoKGkpID0+IGBkJHtpfTogdTMyYCkuam9pbignLCAnKTtcbiAgICAgICAgICBjb25zdCBkaW1zUGFyYW1zID0gcmFua0lkZW50aXR5Lm1hcCgoaSkgPT4gYGQke2l9YCkuam9pbignLCAnKTtcbiAgICAgICAgICByZXR1cm4gYFxuICBmbiBzZXRfJHtuYW1lfSgke2Z1bmN0aW9uUGFyYW1zfSwgdmFsdWU6ICR7dmFsdWVUeXBlfSkge1xuICAgIHNldF8ke25hbWV9QnlJbmRpY2VzKCR7aW5kaWNlcyhkaW1zUGFyYW1zKX0sIHZhbHVlKTtcbiAgfWA7XG4gICAgICAgIH0pKCk7XG5cbiAgY29uc3Qgc2V0ID0gKC4uLmluZGljZXNBbmRWYWx1ZTogUmVhZG9ubHlBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PiB7XG4gICAgaWYgKGluZGljZXNBbmRWYWx1ZS5sZW5ndGggIT09IHJhbmsgKyAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGluZGljZXMgbGVuZ3RoIG11c3QgYmUgJHtyYW5rfWApO1xuICAgIH1cbiAgICBjb25zdCB2YWx1ZSA9IGluZGljZXNBbmRWYWx1ZVtyYW5rXTtcbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd2YWx1ZSBtdXN0IGJlIHN0cmluZycpO1xuICAgIH1cblxuICAgIGNvbnN0IG5vcm1hbGl6ZWRJbmRpY2VzID0gaW5kaWNlc0FuZFZhbHVlLnNsaWNlKDAsIHJhbmspLm1hcChub3JtYWxpemVEaW0pLmpvaW4oJywnKTtcblxuICAgIGlmIChyYW5rID09PSAwKSB7XG4gICAgICByZXR1cm4gc2V0QnlPZmZzZXQoJzB1JywgdmFsdWUpO1xuICAgIH0gZWxzZSBpZiAocmFuayA9PT0gMSkge1xuICAgICAgcmV0dXJuIHNldEJ5T2Zmc2V0KG5vcm1hbGl6ZWRJbmRpY2VzWzBdLCB2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGltcGxlbWVudGF0aW9uVXNlZC5zZXQgPSB0cnVlO1xuICAgICAgaW1wbGVtZW50YXRpb25Vc2VkLnNldEJ5SW5kaWNlcyA9IHRydWU7XG4gICAgICBpbXBsZW1lbnRhdGlvblVzZWQuaW5kaWNlc1RvT2Zmc2V0ID0gdHJ1ZTtcbiAgICAgIHJldHVybiBgc2V0XyR7bmFtZX0oJHtub3JtYWxpemVkSW5kaWNlc30sICR7dmFsdWV9KWA7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IHNldEJ5SW5kaWNlcyA9ICh2YXJJbmRpY2VzOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICBpZiAocmFuayA8IDIpIHtcbiAgICAgIHJldHVybiBzZXRCeU9mZnNldCh2YXJJbmRpY2VzLCB2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGltcGxlbWVudGF0aW9uVXNlZC5zZXRCeUluZGljZXMgPSB0cnVlO1xuICAgICAgaW1wbGVtZW50YXRpb25Vc2VkLmluZGljZXNUb09mZnNldCA9IHRydWU7XG4gICAgICByZXR1cm4gYHNldF8ke25hbWV9QnlJbmRpY2VzKCR7dmFySW5kaWNlc30sICR7dmFsdWV9KTtgO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCBpbXBsID0gKCkgPT4ge1xuICAgIGNvbnN0IGltcGxzID0gW107XG4gICAgbGV0IG5lZWRTaGFwZVN0cmlkZXMgPSBmYWxzZTtcbiAgICBpZiAoaW1wbGVtZW50YXRpb25Vc2VkLm9mZnNldFRvSW5kaWNlcykge1xuICAgICAgaW1wbHMucHVzaChvZmZzZXRUb0luZGljZXNJbXBsZW1lbnRhdGlvbik7XG4gICAgICBuZWVkU2hhcGVTdHJpZGVzID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKGltcGxlbWVudGF0aW9uVXNlZC5pbmRpY2VzVG9PZmZzZXQpIHtcbiAgICAgIGltcGxzLnB1c2goaW5kaWNlc1RvT2Zmc2V0SW1wbGVtZW50YXRpb24pO1xuICAgICAgbmVlZFNoYXBlU3RyaWRlcyA9IHRydWU7XG4gICAgfVxuICAgIGlmIChpbXBsZW1lbnRhdGlvblVzZWQuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQpIHtcbiAgICAgIE9iamVjdC52YWx1ZXMoYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXRJbXBsZW1lbnRhdGlvbikuZm9yRWFjaCgoaW1wbCkgPT4gaW1wbHMucHVzaChpbXBsKSk7XG4gICAgICBuZWVkU2hhcGVTdHJpZGVzID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKGltcGxlbWVudGF0aW9uVXNlZC5zZXQpIHtcbiAgICAgIGltcGxzLnB1c2goc2V0SW1wbGVtZW50YXRpb24pO1xuICAgICAgbmVlZFNoYXBlU3RyaWRlcyA9IHRydWU7XG4gICAgfVxuICAgIGlmIChpbXBsZW1lbnRhdGlvblVzZWQuc2V0QnlJbmRpY2VzKSB7XG4gICAgICBpbXBscy5wdXNoKHNldEJ5SW5kaWNlc0ltcGxlbWVudGF0aW9uKTtcbiAgICAgIG5lZWRTaGFwZVN0cmlkZXMgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAoaW1wbGVtZW50YXRpb25Vc2VkLmdldCkge1xuICAgICAgaW1wbHMucHVzaChnZXRJbXBsZW1lbnRhdGlvbik7XG4gICAgICBuZWVkU2hhcGVTdHJpZGVzID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKGltcGxlbWVudGF0aW9uVXNlZC5nZXRCeUluZGljZXMpIHtcbiAgICAgIGltcGxzLnB1c2goZ2V0QnlJbmRpY2VzSW1wbGVtZW50YXRpb24pO1xuICAgICAgbmVlZFNoYXBlU3RyaWRlcyA9IHRydWU7XG4gICAgfVxuICAgIGlmICghdXNlVW5pZm9ybSAmJiBuZWVkU2hhcGVTdHJpZGVzKSB7XG4gICAgICBpbXBscy51bnNoaWZ0KFxuICAgICAgICBgY29uc3QgJHtzaGFwZX0gPSAke3R5cGUuaW5kaWNlc30oJHtzaGFwZU9yUmFuay5qb2luKCcsJyl9KTtgLFxuICAgICAgICBgY29uc3QgJHtzdHJpZGVzfSA9ICR7dHlwZS5pbmRpY2VzfSgke1NoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhzaGFwZU9yUmFuaykuam9pbignLCcpfSk7YCxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBpbXBscy5qb2luKCdcXG4nKTtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIGltcGwsXG4gICAgdHlwZSxcbiAgICBvZmZzZXRUb0luZGljZXMsXG4gICAgaW5kaWNlc1RvT2Zmc2V0LFxuICAgIGJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0LFxuICAgIGluZGljZXMsXG4gICAgaW5kaWNlc0dldCxcbiAgICBpbmRpY2VzU2V0LFxuICAgIHNldCxcbiAgICBzZXRCeU9mZnNldCxcbiAgICBzZXRCeUluZGljZXMsXG4gICAgZ2V0LFxuICAgIGdldEJ5T2Zmc2V0LFxuICAgIGdldEJ5SW5kaWNlcyxcbiAgICAvLyBpc1ZlYzQsXG4gICAgdXNhZ2UsXG4gICAgbmFtZSxcbiAgICBzdHJpZGVzLFxuICAgIHNoYXBlLFxuICAgIHJhbmssXG4gIH07XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIEluZGljZXNIZWxwZXIgZm9yIGFuIGlucHV0LlxuICpcbiAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgb2YgdGhlIGlucHV0LlxuICogQHBhcmFtIHR5cGUgLSB0aGUgdGVuc29yIHR5cGUgb2YgdGhlIGlucHV0LlxuICogQHBhcmFtIHNoYXBlT3JSYW5rIC0gdGhlIHRlbnNvciBzaGFwZSBvciB0aGUgcmFuayBvZiB0aGUgaW5wdXQuXG4gKiBAcGFyYW0gY29tcG9uZW50cyAtIHRoZSBudW1iZXIgb2YgY29tcG9uZW50cyBvZiB0aGUgaW5wdXQuIGF2YWlsYWJsZSB2YWx1ZXMgYXJlIDEsIDIsIDMsIDQuIGRlZmF1bHQgaXMgMS5cbiAqIEByZXR1cm5zIGFuIEluZGljZXNIZWxwZXIgZm9yIHRoZSBpbnB1dC5cbiAqL1xuZXhwb3J0IGNvbnN0IGlucHV0VmFyaWFibGUgPSAoXG4gIG5hbWU6IHN0cmluZyxcbiAgdHlwZTogbnVtYmVyLFxuICBzaGFwZU9yUmFuazogbnVtYmVyIHwgcmVhZG9ubHkgbnVtYmVyW10sXG4gIGNvbXBvbmVudHM6IDEgfCAyIHwgMyB8IDQgPSAxLFxuKTogSW5kaWNlc0hlbHBlciA9PiBjcmVhdGVJbmRpY2VzSGVscGVyKG5hbWUsIHR5cGUsIHNoYXBlT3JSYW5rLCAnaW5wdXQnLCBjb21wb25lbnRzKTtcblxuLyoqXG4gKiBDcmVhdGUgYSBJbmRpY2VzSGVscGVyIGZvciBhbiBvdXRwdXQuXG4gKlxuICogQHBhcmFtIG5hbWUgLSB0aGUgbmFtZSBvZiB0aGUgb3V0cHV0LlxuICogQHBhcmFtIHR5cGUgLSB0aGUgdGVuc29yIHR5cGUgb2YgdGhlIG91dHB1dC5cbiAqIEBwYXJhbSBzaGFwZU9yUmFuayAtIHRoZSB0ZW5zb3Igc2hhcGUgb3IgdGhlIHJhbmsgb2YgdGhlIG91dHB1dC5cbiAqIEBwYXJhbSBjb21wb25lbnRzIC0gdGhlIG51bWJlciBvZiBjb21wb25lbnRzIG9mIHRoZSBvdXRwdXQuIGF2YWlsYWJsZSB2YWx1ZXMgYXJlIDEsIDIsIDMsIDQuIGRlZmF1bHQgaXMgMS5cbiAqIEByZXR1cm5zIGFuIEluZGljZXNIZWxwZXIgZm9yIHRoZSBvdXRwdXQuXG4gKi9cbmV4cG9ydCBjb25zdCBvdXRwdXRWYXJpYWJsZSA9IChcbiAgbmFtZTogc3RyaW5nLFxuICB0eXBlOiBudW1iZXIsXG4gIHNoYXBlT3JSYW5rOiBudW1iZXIgfCByZWFkb25seSBudW1iZXJbXSxcbiAgY29tcG9uZW50czogMSB8IDIgfCAzIHwgNCA9IDEsXG4pOiBJbmRpY2VzSGVscGVyID0+IGNyZWF0ZUluZGljZXNIZWxwZXIobmFtZSwgdHlwZSwgc2hhcGVPclJhbmssICdvdXRwdXQnLCBjb21wb25lbnRzKTtcblxuLyoqXG4gKiBDcmVhdGUgYSBJbmRpY2VzSGVscGVyIGZvciBhbiBhdG9taWMgb3V0cHV0LlxuICpcbiAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgb2YgdGhlIG91dHB1dC5cbiAqIEBwYXJhbSB0eXBlIC0gdGhlIHRlbnNvciB0eXBlIG9mIHRoZSBvdXRwdXQuXG4gKiBAcGFyYW0gc2hhcGVPclJhbmsgLSB0aGUgdGVuc29yIHNoYXBlIG9yIHRoZSByYW5rIG9mIHRoZSBvdXRwdXQuXG4gKiBAcmV0dXJucyBhbiBJbmRpY2VzSGVscGVyIGZvciB0aGUgb3V0cHV0LlxuICovXG5leHBvcnQgY29uc3QgYXRvbWljT3V0cHV0VmFyaWFibGUgPSAoXG4gIG5hbWU6IHN0cmluZyxcbiAgdHlwZTogbnVtYmVyLFxuICBzaGFwZU9yUmFuazogbnVtYmVyIHwgcmVhZG9ubHkgbnVtYmVyW10sXG4pOiBJbmRpY2VzSGVscGVyID0+IGNyZWF0ZUluZGljZXNIZWxwZXIobmFtZSwgdHlwZSwgc2hhcGVPclJhbmssICdhdG9taWNPdXRwdXQnLCAxKTtcblxuLyoqXG4gKiBDcmVhdGUgYSBJbmRpY2VzSGVscGVyIGZvciBhbiBpbnRlcm5hbCB2YXJpYWJsZS5cbiAqXG4gKiBAcGFyYW0gbmFtZSAtIHRoZSBuYW1lIG9mIHRoZSB2YXJpYWJsZS5cbiAqIEBwYXJhbSB0eXBlIC0gdGhlIHRlbnNvciB0eXBlIG9mIHRoZSB2YXJpYWJsZS5cbiAqIEBwYXJhbSBzaGFwZU9yUmFuayAtIHRoZSB0ZW5zb3Igc2hhcGUgb3IgdGhlIHJhbmsgb2YgdGhlIHZhcmlhYmxlLlxuICogQHBhcmFtIGNvbXBvbmVudHMgLSB0aGUgbnVtYmVyIG9mIGNvbXBvbmVudHMgb2YgdGhlIHZhcmlhYmxlLiBhdmFpbGFibGUgdmFsdWVzIGFyZSAxLCAyLCAzLCA0LiBkZWZhdWx0IGlzIDEuXG4gKiBAcmV0dXJucyBhbiBJbmRpY2VzSGVscGVyIGZvciB0aGUgdmFyaWFibGUuXG4gKi9cbmV4cG9ydCBjb25zdCBpbnRlcm5hbFZhcmlhYmxlID0gKFxuICBuYW1lOiBzdHJpbmcsXG4gIHR5cGU6IG51bWJlcixcbiAgc2hhcGVPclJhbms6IG51bWJlciB8IHJlYWRvbmx5IG51bWJlcltdLFxuICBjb21wb25lbnRzOiAxIHwgMiB8IDMgfCA0ID0gMSxcbik6IEluZGljZXNIZWxwZXIgPT4gY3JlYXRlSW5kaWNlc0hlbHBlcihuYW1lLCB0eXBlLCBzaGFwZU9yUmFuaywgJ2ludGVybmFsJywgY29tcG9uZW50cyk7XG5cbmV4cG9ydCB0eXBlIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUgPSAndTMyJyB8ICdmMTYnIHwgJ2YzMicgfCAnaTMyJztcbmV4cG9ydCB0eXBlIFVuaWZvcm1zQXJyYXlUeXBlID0gQXJyYXk8eyBuYW1lOiBzdHJpbmc7IHR5cGU6IFVuaWZvcm1EYXRhRWxlbWVudFR5cGU7IGxlbmd0aD86IG51bWJlciB9PjtcblxuLyoqXG4gKiBBIFNoYWRlckhlbHBlciBpcyBhIGhlbHBlciBjbGFzcyBmb3IgZ2VuZXJhdGluZyBXR1NMIGNvZGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2hhZGVySGVscGVyIHtcbiAgLyoqXG4gICAqIEEgaGVscGVyIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIHRoZSBzdGFydCBvZiBtYWluIGZ1bmN0aW9uIGluIFdHU0wgc291cmNlIGNvZGUuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICAgKiAgLi4uXG4gICAqXG4gICAqICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICogICAgLy8geW91ciBjb2RlIGhlcmUgaW5zaWRlIG1haW4oKSBmdW5jdGlvblxuICAgKiAgICAuLi5cbiAgICogIH1cbiAgICogYDtcbiAgICpcbiAgICogQHBhcmFtIHdvcmtncm91cFNpemUgLSBhbiBvcHRpb25hbCB3b3JrZ3JvdXAgc2l6ZS4gZGVmYXVsdCBpcyBXT1JLR1JPVVBfU0laRS5cbiAgICovXG4gIG1haW5TdGFydCh3b3JrZ3JvdXBTaXplPzogbnVtYmVyIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXJdKTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIGhlbHBlciBmdW5jdGlvbiB0byBnZW5lcmF0ZSB0aGUgY29kZSBzbmlwcGV0IGZvciBndWFyZGluZyBhZ2FpbnN0IG91dC1vZi1ib3VuZHMgc2l6ZS5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICAqICAuLi5cbiAgICpcbiAgICogICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgKiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKG91dHB1dFNpemUpfVxuICAgKlxuICAgKiAgICAvLyB5b3VyIGNvZGUgaGVyZSBpbnNpZGUgbWFpbigpIGZ1bmN0aW9uXG4gICAqICAgIC4uLlxuICAgKiAgfVxuICAgKiBgO1xuICAgKlxuICAgKiBAcGFyYW0gc2l6ZSAtIHRoZSBzaXplIG9mIHRoZSBkYXRhIHRvIGd1YXJkIGFnYWluc3QuIGNhbiBiZSBhIG51bWJlciBvciBhIHN0cmluZyAoV0dTTCBgdTMyYCBleHByZXNzaW9uKS5cbiAgICovXG4gIGd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoc2l6ZTogdW5rbm93bik6IHN0cmluZztcblxuICAvKipcbiAgICogQSBoZWxwZXIgZnVuY3Rpb24gdG8gZ2VuZXJhdGUgdGhlIGNvZGUgc25pcHBldCBmb3IgZGVjbGFyaW5nIG11bHRpcGxlIGlucHV0cyBvciBvdXRwdXRzLlxuICAgKlxuICAgKiBAcGFyYW0gdmFyaWFibGVzIC0gYW4gYXJyYXkgb2YgSW5kaWNlc0hlbHBlciBmb3IgdGhlIHZhcmlhYmxlcy5cbiAgICovXG4gIGRlY2xhcmVWYXJpYWJsZXMoLi4udmFyaWFibGVzOiBJbmRpY2VzSGVscGVyW10pOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgaGVscGVyIGZ1bmN0aW9uIHRvIHJlZ2lzdGVyIG9uZSB1bmlmb3JtLiBDYW4gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIHRvIHJlZ2lzdGVyIG11bHRpcGxlIHVuaWZvcm1zLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSAtIHRoZSBuYW1lIG9mIHRoZSB1bmlmb3JtLlxuICAgKiBAcGFyYW0gdHlwZSAtIHRoZSB0eXBlIG9mIHRoZSB1bmlmb3JtLlxuICAgKiBAcGFyYW0gbGVuZ3RoIC0gdGhlIGxlbmd0aCBvZiB0aGUgdW5pZm9ybSwgZGVmYXVsdCB0byAxIHdoZW4gaXQgaXMgbm90IHByb3ZpZGVkLlxuICAgKi9cbiAgcmVnaXN0ZXJVbmlmb3JtKG5hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nLCBsZW5ndGg/OiBudW1iZXIpOiBTaGFkZXJIZWxwZXI7XG5cbiAgLyoqXG4gICAqIEEgaGVscGVyIGZ1bmN0aW9uIHRvIHJlZ2lzdGVyIG11bHRpcGxlIHVuaWZvcm1zLiBDYW4gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIHRvIHJlZ2lzdGVyIG11bHRpcGxlIHVuaWZvcm1zLlxuICAgKlxuICAgKiBAcGFyYW0gdW5pZm9ybXMgLSBhbiBhcnJheSBvZiB1bmlmb3Jtcy4gRWFjaCBlbGVtZW50IG9mIHRoZSBhcnJheSBpcyBhbiBvYmplY3Qgd2l0aCAyIHByb3BlcnRpZXM6IGBuYW1lYCBhbmRcbiAgICogICAgIGB0eXBlYC5cbiAgICovXG4gIHJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlKTogU2hhZGVySGVscGVyO1xuXG4gIC8qKlxuICAgKiBBIGhlbHBlciBmdW5jdGlvbiB0byByZWdpc3RlciBtdWx0aXBsZSBpbnRlcm5hbCB2YXJpYWJsZXMuIENhbiBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMgdG8gcmVnaXN0ZXIgbXVsdGlwbGVcbiAgICogaW50ZXJuYWwgdmFyaWFibGVzLlxuICAgKlxuICAgKiBAcGFyYW0gdmFyaWFibGVzIC0gYW4gYXJyYXkgb2YgSW5kaWNlc0hlbHBlciBmb3IgdGhlIHZhcmlhYmxlcy5cbiAgICovXG4gIHJlZ2lzdGVySW50ZXJuYWxWYXJpYWJsZXMoLi4udmFyaWFibGVzOiBJbmRpY2VzSGVscGVyW10pOiBTaGFkZXJIZWxwZXI7XG59XG5cbmNsYXNzIFNoYWRlckhlbHBlckltcGwgaW1wbGVtZW50cyBTaGFkZXJIZWxwZXIge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgcHJpdmF0ZSBsaW1pdHM6IEdQVVN1cHBvcnRlZExpbWl0cyxcbiAgKSB7fVxuXG4gIGd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoc2l6ZTogbnVtYmVyIHwgc3RyaW5nKTogc3RyaW5nIHtcbiAgICAvLyBHdWFyZCBhZ2FpbnN0IG91dC1vZi1ib3VuZHMgd29yayBncm91cCBzaXplc1xuICAgIGNvbnN0IHNpemVJbkNvZGUgPSB0eXBlb2Ygc2l6ZSA9PT0gJ251bWJlcicgPyBgJHtzaXplfXVgIDogc2l6ZTtcbiAgICByZXR1cm4gYGlmIChnbG9iYWxfaWR4ID49ICR7c2l6ZUluQ29kZX0pIHsgcmV0dXJuOyB9YDtcbiAgfVxuXG4gIG1haW5TdGFydCh3b3JrZ3JvdXBTaXplOiBudW1iZXIgfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPSBXT1JLR1JPVVBfU0laRSkge1xuICAgIGNvbnN0IHdvcmtncm91cFNpemVYID0gdHlwZW9mIHdvcmtncm91cFNpemUgPT09ICdudW1iZXInID8gd29ya2dyb3VwU2l6ZSA6IHdvcmtncm91cFNpemVbMF07XG4gICAgY29uc3Qgd29ya2dyb3VwU2l6ZVkgPSB0eXBlb2Ygd29ya2dyb3VwU2l6ZSA9PT0gJ251bWJlcicgPyAxIDogd29ya2dyb3VwU2l6ZVsxXTtcbiAgICBjb25zdCB3b3JrZ3JvdXBTaXplWiA9IHR5cGVvZiB3b3JrZ3JvdXBTaXplID09PSAnbnVtYmVyJyA/IDEgOiB3b3JrZ3JvdXBTaXplWzJdO1xuXG4gICAgaWYgKFxuICAgICAgd29ya2dyb3VwU2l6ZVggPiB0aGlzLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3VwU2l6ZVggfHxcbiAgICAgIHdvcmtncm91cFNpemVZID4gdGhpcy5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cFNpemVZIHx8XG4gICAgICB3b3JrZ3JvdXBTaXplWiA+IHRoaXMubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBTaXplWlxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgd29ya2dyb3VwIHNpemUgWyR7d29ya2dyb3VwU2l6ZVh9LCAke3dvcmtncm91cFNpemVZfSwgJHtcbiAgICAgICAgICB3b3JrZ3JvdXBTaXplWlxuICAgICAgICB9XSBleGNlZWRzIHRoZSBtYXhpbXVtIHdvcmtncm91cCBzaXplIFske3RoaXMubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBTaXplWH0sICR7XG4gICAgICAgICAgdGhpcy5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cFNpemVZXG4gICAgICAgIH0sICR7dGhpcy5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cFNpemVafV0uYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHdvcmtncm91cFNpemVYICogd29ya2dyb3VwU2l6ZVkgKiB3b3JrZ3JvdXBTaXplWiA+IHRoaXMubGltaXRzLm1heENvbXB1dGVJbnZvY2F0aW9uc1Blcldvcmtncm91cCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgd29ya2dyb3VwIHNpemUgWyR7d29ya2dyb3VwU2l6ZVh9LCAke3dvcmtncm91cFNpemVZfSwgJHtcbiAgICAgICAgICB3b3JrZ3JvdXBTaXplWlxuICAgICAgICB9XSBleGNlZWRzIHRoZSBtYXhpbXVtIHdvcmtncm91cCBpbnZvY2F0aW9ucyAke3RoaXMubGltaXRzLm1heENvbXB1dGVJbnZvY2F0aW9uc1Blcldvcmtncm91cH0uYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgaXMxRGltZW5zaW9uRGlzcGF0Y2ggPSB0aGlzLm5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwWzFdID09PSAxICYmIHRoaXMubm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMl0gPT09IDE7XG4gICAgY29uc3QgcGFyYW1MaXN0ID0gaXMxRGltZW5zaW9uRGlzcGF0Y2hcbiAgICAgID8gYEBidWlsdGluKGdsb2JhbF9pbnZvY2F0aW9uX2lkKSBnbG9iYWxfaWQgOiB2ZWMzPHUzMj4sXG4gICAgQGJ1aWx0aW4od29ya2dyb3VwX2lkKSB3b3JrZ3JvdXBfaWQgOiB2ZWMzPHUzMj4sXG4gICAgQGJ1aWx0aW4obG9jYWxfaW52b2NhdGlvbl9pbmRleCkgbG9jYWxfaWR4IDogdTMyLFxuICAgIEBidWlsdGluKGxvY2FsX2ludm9jYXRpb25faWQpIGxvY2FsX2lkIDogdmVjMzx1MzI+YFxuICAgICAgOiBgQGJ1aWx0aW4oZ2xvYmFsX2ludm9jYXRpb25faWQpIGdsb2JhbF9pZCA6IHZlYzM8dTMyPixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBidWlsdGluKGxvY2FsX2ludm9jYXRpb25faWQpIGxvY2FsX2lkIDogdmVjMzx1MzI+LFxuICAgIEBidWlsdGluKGxvY2FsX2ludm9jYXRpb25faW5kZXgpIGxvY2FsX2lkeCA6IHUzMixcbiAgICBAYnVpbHRpbih3b3JrZ3JvdXBfaWQpIHdvcmtncm91cF9pZCA6IHZlYzM8dTMyPixcbiAgICBAYnVpbHRpbihudW1fd29ya2dyb3VwcykgbnVtX3dvcmtncm91cHMgOiB2ZWMzPHUzMj5gO1xuICAgIGNvbnN0IGdsb2JhbElkeERlZmluaXRpb24gPSBpczFEaW1lbnNpb25EaXNwYXRjaFxuICAgICAgPyBgbGV0IGdsb2JhbF9pZHggPSBnbG9iYWxfaWQueDtcbiAgICAgICAgIGxldCB3b3JrZ3JvdXBfaW5kZXggPSB3b3JrZ3JvdXBfaWQueDtgXG4gICAgICA6IGBsZXQgd29ya2dyb3VwX2luZGV4ID0gd29ya2dyb3VwX2lkLnogKiBudW1fd29ya2dyb3Vwc1swXSAqIG51bV93b3JrZ3JvdXBzWzFdICtcbiAgICAgICAgICAgICB3b3JrZ3JvdXBfaWQueSAqIG51bV93b3JrZ3JvdXBzWzBdICsgd29ya2dyb3VwX2lkLng7XG4gICAgICAgICBsZXQgZ2xvYmFsX2lkeCA9IHdvcmtncm91cF9pbmRleCAqICR7d29ya2dyb3VwU2l6ZVggKiB3b3JrZ3JvdXBTaXplWSAqIHdvcmtncm91cFNpemVafXUgKyBsb2NhbF9pZHg7YDtcblxuICAgIHJldHVybiBgQGNvbXB1dGUgQHdvcmtncm91cF9zaXplKCR7d29ya2dyb3VwU2l6ZVh9LCAke3dvcmtncm91cFNpemVZfSwgJHt3b3JrZ3JvdXBTaXplWn0pXG4gIGZuIG1haW4oJHtwYXJhbUxpc3R9KSB7XG4gICAgJHtnbG9iYWxJZHhEZWZpbml0aW9ufVxuICBgO1xuICB9XG5cbiAgcHJpdmF0ZSBhcHBlbmRWYXJpYWJsZVVuaWZvcm1zKHZhcmlhYmxlOiBJbmRpY2VzSGVscGVyKTogdm9pZCB7XG4gICAgaWYgKHZhcmlhYmxlLnJhbmsgIT09IDApIHtcbiAgICAgIGlmICh2YXJpYWJsZS5zaGFwZS5zdGFydHNXaXRoKCd1bmlmb3Jtcy4nKSkge1xuICAgICAgICB0aGlzLnVuaWZvcm1zLnB1c2goeyBuYW1lOiB2YXJpYWJsZS5zaGFwZS5yZXBsYWNlKCd1bmlmb3Jtcy4nLCAnJyksIHR5cGU6ICd1MzInLCBsZW5ndGg6IHZhcmlhYmxlLnJhbmsgfSk7XG4gICAgICB9XG4gICAgICBpZiAodmFyaWFibGUuc3RyaWRlcy5zdGFydHNXaXRoKCd1bmlmb3Jtcy4nKSkge1xuICAgICAgICB0aGlzLnVuaWZvcm1zLnB1c2goeyBuYW1lOiB2YXJpYWJsZS5zdHJpZGVzLnJlcGxhY2UoJ3VuaWZvcm1zLicsICcnKSwgdHlwZTogJ3UzMicsIGxlbmd0aDogdmFyaWFibGUucmFuayB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGRlY2xhcmVWYXJpYWJsZSh2YXJpYWJsZTogSW5kaWNlc0hlbHBlciwgYmluZGluZ0luZGV4OiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGlmICh2YXJpYWJsZS51c2FnZSA9PT0gJ2ludGVybmFsJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3QgdXNlIGludGVybmFsIHZhcmlhYmxlIHdpdGggZGVjbGFyZVZhcmlhYmxlKCkuIHVzZSByZWdpc3RlckludGVybmFsVmFyaWFibGVzKCkgaW5zdGVhZC4nKTtcbiAgICB9XG4gICAgdGhpcy52YXJpYWJsZXMucHVzaCh2YXJpYWJsZSk7XG4gICAgdGhpcy5hcHBlbmRWYXJpYWJsZVVuaWZvcm1zKHZhcmlhYmxlKTtcbiAgICBjb25zdCBhY2Nlc3MgPSB2YXJpYWJsZS51c2FnZSA9PT0gJ2lucHV0JyA/ICdyZWFkJyA6ICdyZWFkX3dyaXRlJztcbiAgICBjb25zdCBzdG9yYWdlVHlwZSA9IHZhcmlhYmxlLnVzYWdlID09PSAnYXRvbWljT3V0cHV0JyA/IGBhdG9taWM8aTMyPmAgOiB2YXJpYWJsZS50eXBlLnN0b3JhZ2U7XG4gICAgcmV0dXJuIGBAZ3JvdXAoMCkgQGJpbmRpbmcoJHtiaW5kaW5nSW5kZXh9KSB2YXI8c3RvcmFnZSwgJHthY2Nlc3N9PiAke3ZhcmlhYmxlLm5hbWV9OiBhcnJheTwke3N0b3JhZ2VUeXBlfT47YDtcbiAgfVxuXG4gIGRlY2xhcmVWYXJpYWJsZXMoLi4udmFyaWFibGVzOiBJbmRpY2VzSGVscGVyW10pOiBzdHJpbmcge1xuICAgIHJldHVybiB2YXJpYWJsZXMubWFwKCh2KSA9PiB0aGlzLmRlY2xhcmVWYXJpYWJsZSh2LCB0aGlzLnZhcmlhYmxlSW5kZXgrKykpLmpvaW4oJ1xcbicpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWdpc3RlckludGVybmFsVmFyaWFibGUodmFyaWFibGU6IEluZGljZXNIZWxwZXIpOiB2b2lkIHtcbiAgICBpZiAodmFyaWFibGUudXNhZ2UgIT09ICdpbnRlcm5hbCcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ2Nhbm5vdCB1c2UgaW5wdXQgb3Igb3V0cHV0IHZhcmlhYmxlIHdpdGggcmVnaXN0ZXJJbnRlcm5hbFZhcmlhYmxlKCkuIHVzZSBkZWNsYXJlVmFyaWFibGVzKCkgaW5zdGVhZC4nLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmludGVybmFsVmFyaWFibGVzLnB1c2godmFyaWFibGUpO1xuICAgIHRoaXMuYXBwZW5kVmFyaWFibGVVbmlmb3Jtcyh2YXJpYWJsZSk7XG4gIH1cblxuICByZWdpc3RlckludGVybmFsVmFyaWFibGVzKC4uLnZhcmlhYmxlczogSW5kaWNlc0hlbHBlcltdKTogU2hhZGVySGVscGVyIHtcbiAgICB2YXJpYWJsZXMuZm9yRWFjaCgodikgPT4gdGhpcy5yZWdpc3RlckludGVybmFsVmFyaWFibGUodikpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcmVnaXN0ZXJVbmlmb3JtKG5hbWU6IHN0cmluZywgdHlwZTogVW5pZm9ybURhdGFFbGVtZW50VHlwZSwgbGVuZ3RoID0gMSk6IFNoYWRlckhlbHBlciB7XG4gICAgdGhpcy51bmlmb3Jtcy5wdXNoKHsgbmFtZSwgdHlwZSwgbGVuZ3RoIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcmVnaXN0ZXJVbmlmb3JtcyhhZGRpdGlvbmFsVW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlKTogU2hhZGVySGVscGVyIHtcbiAgICB0aGlzLnVuaWZvcm1zID0gdGhpcy51bmlmb3Jtcy5jb25jYXQoYWRkaXRpb25hbFVuaWZvcm1zKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxWYXJpYWJsZXM6IEluZGljZXNIZWxwZXJbXSA9IFtdO1xuICBwcml2YXRlIHZhcmlhYmxlczogSW5kaWNlc0hlbHBlcltdID0gW107XG4gIHByaXZhdGUgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW107XG4gIHByaXZhdGUgdW5pZm9ybURlY2xhcmF0aW9uKCk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMudW5pZm9ybXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgY29uc3QgdW5pZm9ybVNuaXBwZXRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgeyBuYW1lLCB0eXBlLCBsZW5ndGggfSBvZiB0aGlzLnVuaWZvcm1zKSB7XG4gICAgICBpZiAobGVuZ3RoICYmIGxlbmd0aCA+IDQpIHtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdmMTYnKSB7XG4gICAgICAgICAgdW5pZm9ybVNuaXBwZXRzLnB1c2goYEBhbGlnbigxNikgJHtuYW1lfTphcnJheTxtYXQyeDQ8JHt0eXBlfT4sICR7TWF0aC5jZWlsKGxlbmd0aCAvIDgpfT5gKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB1bmlmb3JtU25pcHBldHMucHVzaChgJHtuYW1lfTphcnJheTx2ZWM0PCR7dHlwZX0+LCAke01hdGguY2VpbChsZW5ndGggLyA0KX0+YCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHR5cGVUZW1wID0gbGVuZ3RoID09IG51bGwgfHwgbGVuZ3RoID09PSAxID8gdHlwZSA6IGB2ZWMke2xlbmd0aH08JHt0eXBlfT5gO1xuICAgICAgICB1bmlmb3JtU25pcHBldHMucHVzaChgJHtuYW1lfToke3R5cGVUZW1wfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBgXG4gICAgICBzdHJ1Y3QgVW5pZm9ybXMgeyAke3VuaWZvcm1TbmlwcGV0cy5qb2luKCcsICcpfSB9O1xuICAgICAgQGdyb3VwKDApIEBiaW5kaW5nKCR7dGhpcy52YXJpYWJsZUluZGV4fSkgdmFyPHVuaWZvcm0+IHVuaWZvcm1zOiBVbmlmb3JtcztgO1xuICB9XG4gIHByaXZhdGUgdmFyaWFibGVJbmRleCA9IDA7XG5cbiAgLyoqXG4gICAqIEdldCBhZGRpdGlvbmFsIGltcGxlbWVudGF0aW9uIHRoYXQgbmVlZHMgdG8gYmUgYWRkZWQgdG8gdGhlIHNoYWRlciBzb3VyY2UuXG4gICAqL1xuICBnZXQgYWRkaXRpb25hbEltcGxlbWVudGF0aW9ucygpOiBzdHJpbmcge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLnVuaWZvcm1EZWNsYXJhdGlvbigpICtcbiAgICAgIHRoaXMudmFyaWFibGVzLm1hcCgoaSkgPT4gaS5pbXBsKCkpLmpvaW4oJ1xcbicpICtcbiAgICAgIHRoaXMuaW50ZXJuYWxWYXJpYWJsZXMubWFwKChpKSA9PiBpLmltcGwoKSkuam9pbignXFxuJylcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgdmFyaWFibGUgaW5mbyBvZiB0aGUgc2hhZGVyIHByb2dyYW0uXG4gICAqL1xuICBnZXQgdmFyaWFibGVzSW5mbygpOiBQcm9ncmFtVW5pZm9ybVZhcmlhYmxlSW5mb1tdIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodGhpcy51bmlmb3Jtcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgdW5pZm9ybVdnc2xUeXBlVG9EYXRhVHlwZSA9ICh0eXBlOiBVbmlmb3JtRGF0YUVsZW1lbnRUeXBlKSA9PlxuICAgICAgW0RhdGFUeXBlLnVpbnQzMiwgRGF0YVR5cGUuZmxvYXQxNiwgRGF0YVR5cGUuZmxvYXQsIERhdGFUeXBlLmludDMyXVtbJ3UzMicsICdmMTYnLCAnZjMyJywgJ2kzMiddLmluZGV4T2YodHlwZSldO1xuICAgIHJldHVybiB0aGlzLnVuaWZvcm1zLm1hcCgodSkgPT4gW3VuaWZvcm1XZ3NsVHlwZVRvRGF0YVR5cGUodS50eXBlKSwgdS5sZW5ndGggPz8gMV0pO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVTaGFkZXJIZWxwZXIgPSAoZGlzcGF0Y2hHcm91cDogW251bWJlciwgbnVtYmVyLCBudW1iZXJdLCBsaW1pdHM6IEdQVVN1cHBvcnRlZExpbWl0cykgPT5cbiAgbmV3IFNoYWRlckhlbHBlckltcGwoZGlzcGF0Y2hHcm91cCwgbGltaXRzKTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBJbmRpY2VzSGVscGVyLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIFRyYW5zcG9zZUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBwZXJtOiBudW1iZXJbXTtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIHBlcm06IHJlYWRvbmx5IG51bWJlcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyYW5zcG9zZSByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG5cbiAgaWYgKHBlcm0ubGVuZ3RoICE9PSAwICYmIHBlcm0ubGVuZ3RoICE9PSBpbnB1dHNbMF0uZGltcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHBlcm0gc2l6ZSAke3Blcm0ubGVuZ3RofSBkb2VzIG5vdCBtYXRjaCBpbnB1dCByYW5rICR7aW5wdXRzWzBdLmRpbXMubGVuZ3RofWApO1xuICB9XG59O1xuXG5jb25zdCBnZXRBZGp1c3RlZFBlcm0gPSAoaW5wdXRSYW5rOiBudW1iZXIsIHBlcm06IG51bWJlcltdKTogbnVtYmVyW10gPT5cbiAgcGVybS5sZW5ndGggIT09IDAgPyBwZXJtIDogWy4uLm5ldyBBcnJheShpbnB1dFJhbmspLmtleXMoKV0ucmV2ZXJzZSgpO1xuXG5jb25zdCBnZXRPdXRwdXRTaGFwZSA9IChpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgcGVybTogbnVtYmVyW10pOiByZWFkb25seSBudW1iZXJbXSA9PlxuICBTaGFwZVV0aWwuc29ydEJhc2VkT25QZXJtKGlucHV0U2hhcGUsIGdldEFkanVzdGVkUGVybShpbnB1dFNoYXBlLmxlbmd0aCwgcGVybSkpO1xuXG5jb25zdCBwZXJtRnVuY3Rpb25Cb2R5ID0gKHBlcm06IG51bWJlcltdLCByYW5rOiBudW1iZXIsIGlucHV0OiBJbmRpY2VzSGVscGVyLCBvdXRwdXQ6IEluZGljZXNIZWxwZXIpOiBzdHJpbmcgPT4ge1xuICBsZXQgcmV2ZXJzZUZ1bmMgPSBgZm4gcGVybShpOiAke291dHB1dC50eXBlLmluZGljZXN9KSAtPiAke2lucHV0LnR5cGUuaW5kaWNlc30ge1xuICAgIHZhciBhOiAke2lucHV0LnR5cGUuaW5kaWNlc307YDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCByYW5rOyArK2kpIHtcbiAgICAvLyBpbnB1dCBpbmRpY2VzIGFuZCBvdXRwdXQgaW5kaWNlcyBzaG91bGQgYWx3YXlzIGJlIGxhcmdlciBvciBlcXVhbCB0byAyLFxuICAgIC8vIHNvIGluZGV4ZXIgaXMgYWx3YXlzIHZhbGlkIHRvIGJlIHVzZWQgb24gYGFgIGFuZCBgaWAuXG4gICAgcmV2ZXJzZUZ1bmMgKz0gYGFbJHtwZXJtW2ldfV09aVske2l9XTtgO1xuICB9XG4gIHJldHVybiAocmV2ZXJzZUZ1bmMgKz0gJ3JldHVybiBhO30nKTtcbn07XG5cbmNvbnN0IHNxdWVlemVTaGFwZSA9IChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGFkanVzdGVkUGVybTogbnVtYmVyW10pOiB7IG5ld1NoYXBlOiBudW1iZXJbXTsgbmV3UGVybTogbnVtYmVyW10gfSA9PiB7XG4gIGNvbnN0IG5ld1NoYXBlOiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCBuZXdQZXJtOiBudW1iZXJbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHNoYXBlLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKHNoYXBlW2ldICE9PSAxKSB7XG4gICAgICBuZXdTaGFwZS5wdXNoKHNoYXBlW2ldKTtcbiAgICB9XG4gICAgaWYgKHNoYXBlW2FkanVzdGVkUGVybVtpXV0gIT09IDEpIHtcbiAgICAgIG5ld1Blcm0ucHVzaChhZGp1c3RlZFBlcm1baV0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4geyBuZXdTaGFwZSwgbmV3UGVybSB9O1xufTtcblxuY29uc3QgaXNUcmFuc3Bvc2VSZXNoYXBlID0gKHBlcm06IG51bWJlcltdLCBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pID0+IHtcbiAgLy8gQXMgbG9uZyBhcyB0aGUgZGltcyB3aXRoIHZhbHVlcyA+IDEgc3RheSBpbiB0aGUgc2FtZSBvcmRlciwgaXQncyBhIHJlc2hhcGUuXG4gIC8vIEV4YW1wbGU6IFNoYXBlPSgxLDEsMTAyNCw0MDk2KSAtPiBwZXJtPSgyLDAsMywxKS5cbiAgbGV0IGxhc3RQZXJtdXRlZEF4aXMgPSAwO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHBlcm0ubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoc2hhcGVbcGVybVtpXV0gPT09IDEpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAocGVybVtpXSA8IGxhc3RQZXJtdXRlZEF4aXMpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgbGFzdFBlcm11dGVkQXhpcyA9IHBlcm1baV07XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8gPSAoaW5wdXRUZW5zb3I6IFRlbnNvclZpZXcsIHBlcm1BdHRyOiBudW1iZXJbXSk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXREYXRhVHlwZSA9IGlucHV0VGVuc29yLmRhdGFUeXBlO1xuICBjb25zdCBpbnB1dFJhbmsgPSBpbnB1dFRlbnNvci5kaW1zLmxlbmd0aDtcbiAgY29uc3QgcGVybSA9IGdldEFkanVzdGVkUGVybShpbnB1dFJhbmssIHBlcm1BdHRyKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBnZXRPdXRwdXRTaGFwZShpbnB1dFRlbnNvci5kaW1zLCBwZXJtKTtcbiAgbGV0IG5ld0lucHV0U2hhcGUgPSBpbnB1dFRlbnNvci5kaW1zO1xuICBsZXQgbmV3T3V0cHV0U2hhcGUgPSBvdXRwdXRTaGFwZTtcbiAgY29uc3QgdHJhbnNwb3NlQXNSZXNoYXBlID0gaW5wdXRSYW5rIDwgMiB8fCBpc1RyYW5zcG9zZVJlc2hhcGUocGVybSwgaW5wdXRUZW5zb3IuZGltcyk7XG4gIGxldCBnZXRTaGFkZXJTb3VyY2U7XG4gIGlmICh0cmFuc3Bvc2VBc1Jlc2hhcGUpIHtcbiAgICBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICAgIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBpbnB1dERhdGFUeXBlLCBuZXdJbnB1dFNoYXBlLCA0KTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dERhdGFUeXBlLCBuZXdPdXRwdXRTaGFwZSwgNCk7XG4gICAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dF9zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgb3V0cHV0W2dsb2JhbF9pZHhdID0gaW5wdXRbZ2xvYmFsX2lkeF07XG4gIH1gO1xuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ1RyYW5zcG9zZUNvcHknLFxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaW5wdXREZXBlbmRlbmNpZXM6IFsndHlwZSddIH0sXG4gICAgICBnZXRSdW5EYXRhOiAoKSA9PiB7XG4gICAgICAgIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dFRlbnNvci5kYXRhVHlwZSB9XSxcbiAgICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8gLyA0IC8qIGNvbXBvbmVudHMgKi8pIH0sXG4gICAgICAgICAgcHJvZ3JhbVVuaWZvcm1zOiBbeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNCkgfV0sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIH07XG4gIH1cbiAgY29uc3QgeyBuZXdTaGFwZSwgbmV3UGVybSB9ID0gc3F1ZWV6ZVNoYXBlKGlucHV0VGVuc29yLmRpbXMsIHBlcm0pO1xuICBjb25zdCBjaGFubmVsc0xhc3QgPSBTaGFwZVV0aWwuYXJlRXF1YWwobmV3UGVybSwgWzIsIDMsIDFdKTtcbiAgY29uc3QgY2hhbm5lbHNGaXJzdCA9IFNoYXBlVXRpbC5hcmVFcXVhbChuZXdQZXJtLCBbMywgMSwgMl0pO1xuICBjb25zdCB1c2VTaGFyZWQgPSBuZXdTaGFwZS5sZW5ndGggPT09IDIgfHwgY2hhbm5lbHNMYXN0IHx8IGNoYW5uZWxzRmlyc3Q7XG4gIGlmICh1c2VTaGFyZWQpIHtcbiAgICBuZXdJbnB1dFNoYXBlID0gY2hhbm5lbHNMYXN0XG4gICAgICA/IFtuZXdTaGFwZVswXSwgbmV3U2hhcGVbMV0gKiBuZXdTaGFwZVsyXV1cbiAgICAgIDogY2hhbm5lbHNGaXJzdFxuICAgICAgICA/IFtuZXdTaGFwZVswXSAqIG5ld1NoYXBlWzFdLCBuZXdTaGFwZVsyXV1cbiAgICAgICAgOiBuZXdTaGFwZTtcbiAgICBuZXdPdXRwdXRTaGFwZSA9IFtuZXdJbnB1dFNoYXBlWzFdLCBuZXdJbnB1dFNoYXBlWzBdXTtcbiAgICBjb25zdCB0aWxlU2l6ZSA9IDE2O1xuICAgIGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgICAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdhJywgaW5wdXREYXRhVHlwZSwgbmV3SW5wdXRTaGFwZS5sZW5ndGgpO1xuICAgICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0RGF0YVR5cGUsIG5ld091dHB1dFNoYXBlLmxlbmd0aCk7XG4gICAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dF9zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGUgOiBhcnJheTxhcnJheTwke291dHB1dC50eXBlLnZhbHVlfSwgJHt0aWxlU2l6ZSArIDF9PiwgJHt0aWxlU2l6ZX0+O1xuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoW3RpbGVTaXplLCB0aWxlU2l6ZSwgMV0pfVxuICAgIGxldCBzdHJpZGUgPSAodW5pZm9ybXMub3V0cHV0X3NoYXBlWzFdIC0gMSkgLyAke3RpbGVTaXplfSArIDE7XG4gICAgbGV0IHdvcmtncm91cF9pZF94ID0gd29ya2dyb3VwX2luZGV4ICUgc3RyaWRlO1xuICAgIGxldCB3b3JrZ3JvdXBfaWRfeSA9IHdvcmtncm91cF9pbmRleCAvIHN0cmlkZTtcbiAgICBsZXQgaW5wdXRfY29sID0gd29ya2dyb3VwX2lkX3kgKiAke3RpbGVTaXplfXUgKyBsb2NhbF9pZC54O1xuICAgIGxldCBpbnB1dF9yb3cgPSB3b3JrZ3JvdXBfaWRfeCAqICR7dGlsZVNpemV9dSArIGxvY2FsX2lkLnk7XG4gICAgaWYgKGlucHV0X3JvdyA8IHVuaWZvcm1zLmFfc2hhcGVbMF0gJiYgaW5wdXRfY29sIDwgdW5pZm9ybXMuYV9zaGFwZVsxXSkge1xuICAgICAgdGlsZVtsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9ICR7aW5wdXQuZ2V0QnlJbmRpY2VzKGAke2lucHV0LnR5cGUuaW5kaWNlc30oaW5wdXRfcm93LCBpbnB1dF9jb2wpYCl9O1xuICAgIH1cbiAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICBsZXQgb3V0cHV0X2NvbCA9IHdvcmtncm91cF9pZF94ICogJHt0aWxlU2l6ZX11ICsgbG9jYWxfaWQueDtcbiAgICBsZXQgb3V0cHV0X3JvdyA9IHdvcmtncm91cF9pZF95ICogJHt0aWxlU2l6ZX11ICsgbG9jYWxfaWQueTtcbiAgICBpZiAob3V0cHV0X3JvdyA8IHVuaWZvcm1zLm91dHB1dF9zaGFwZVswXSAmJiBvdXRwdXRfY29sIDwgdW5pZm9ybXMub3V0cHV0X3NoYXBlWzFdKSB7XG4gICAgICAke291dHB1dC5zZXRCeUluZGljZXMoYCR7b3V0cHV0LnR5cGUuaW5kaWNlc30ob3V0cHV0X3Jvdywgb3V0cHV0X2NvbClgLCAndGlsZVtsb2NhbF9pZC54XVtsb2NhbF9pZC55XScpfVxuICAgIH1cbiAgfWA7XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ1RyYW5zcG9zZVNoYXJlZCcsXG4gICAgICBzaGFkZXJDYWNoZTogeyBpbnB1dERlcGVuZGVuY2llczogWyd0eXBlJ10gfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+IHtcbiAgICAgICAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0VGVuc29yLmRhdGFUeXBlIH1dLFxuICAgICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG5ld091dHB1dFNoYXBlWzFdIC8gdGlsZVNpemUpLCB5OiBNYXRoLmNlaWwobmV3T3V0cHV0U2hhcGVbMF0gLyB0aWxlU2l6ZSkgfSxcbiAgICAgICAgICBwcm9ncmFtVW5pZm9ybXM6IFtcbiAgICAgICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhuZXdJbnB1dFNoYXBlLCBuZXdPdXRwdXRTaGFwZSksXG4gICAgICAgICAgXSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgfTtcbiAgfVxuXG4gIGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnYScsIGlucHV0RGF0YVR5cGUsIG5ld0lucHV0U2hhcGUubGVuZ3RoKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXREYXRhVHlwZSwgbmV3T3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dF9zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG5cbiAgJHtwZXJtRnVuY3Rpb25Cb2R5KHBlcm0sIGlucHV0UmFuaywgaW5wdXQsIG91dHB1dCl9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cblxuICAgIGxldCBpbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgIGxldCBhSW5kaWNlcyA9IHBlcm0oaW5kaWNlcyk7XG5cbiAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsIGlucHV0LmdldEJ5SW5kaWNlcygnYUluZGljZXMnKSl9XG4gIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdUcmFuc3Bvc2UnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke3Blcm1BdHRyfWAsIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+IHtcbiAgICAgIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0VGVuc29yLmRhdGFUeXBlIH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgICAgICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMobmV3SW5wdXRTaGFwZSwgbmV3T3V0cHV0U2hhcGUpLFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB0cmFuc3Bvc2UgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFRyYW5zcG9zZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMucGVybSk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgYXR0cmlidXRlcy5wZXJtKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VUcmFuc3Bvc2VBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogVHJhbnNwb3NlQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBwZXJtOiBhdHRyaWJ1dGVzLnBlcm0gYXMgbnVtYmVyW10gfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuaW1wb3J0IHsgY3JlYXRlUmVkdWNlQXR0cmlidXRlc0Zyb21JbnB1dHMsIFJlZHVjZUF0dHJpYnV0ZXMgfSBmcm9tICcuL3JlZHVjZSc7XG5pbXBvcnQgeyBjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyB9IGZyb20gJy4vdHJhbnNwb3NlJztcblxuY29uc3QgcmVkdWNlT3BzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICBtYXg6ICdzZWxlY3QoYmVzdFZhbHVlLCBjYW5kaWRhdGUsIGNhbmRpZGF0ZSA+IGJlc3RWYWx1ZSknLFxuICBtaW46ICdzZWxlY3QoYmVzdFZhbHVlLCBjYW5kaWRhdGUsIGNhbmRpZGF0ZSA8IGJlc3RWYWx1ZSknLFxuICBtZWFuOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlJyxcbiAgc3VtOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlJyxcbiAgcHJvZDogJ2Jlc3RWYWx1ZSAqIGNhbmRpZGF0ZScsXG4gIHN1bVNxdWFyZTogJ2Jlc3RWYWx1ZSArIGNhbmRpZGF0ZSAqIGNhbmRpZGF0ZScsXG4gIGxvZ1N1bUV4cDogJ2Jlc3RWYWx1ZSArIGV4cChjYW5kaWRhdGUpJyxcbiAgbDE6ICdiZXN0VmFsdWUgKyBhYnMoY2FuZGlkYXRlKScsXG4gIGwyOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlICogY2FuZGlkYXRlJyxcbiAgbG9nU3VtOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlJyxcbn07XG5cbmNvbnN0IHJlZHVjZVNoYXJlZE9wczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHtcbiAgbWF4OiAnc2VsZWN0KGJlc3RWYWx1ZSwgY2FuZGlkYXRlLCBjYW5kaWRhdGUgPiBiZXN0VmFsdWUpJyxcbiAgbWluOiAnc2VsZWN0KGJlc3RWYWx1ZSwgY2FuZGlkYXRlLCBjYW5kaWRhdGUgPCBiZXN0VmFsdWUpJyxcbiAgbWVhbjogJ2Jlc3RWYWx1ZSArIGNhbmRpZGF0ZScsXG4gIHN1bTogJ2Jlc3RWYWx1ZSArIGNhbmRpZGF0ZScsXG4gIHByb2Q6ICdiZXN0VmFsdWUgKiBjYW5kaWRhdGUnLFxuICBzdW1TcXVhcmU6ICdiZXN0VmFsdWUgKyBjYW5kaWRhdGUnLFxuICBsb2dTdW1FeHA6ICdiZXN0VmFsdWUgKyBjYW5kaWRhdGUnLFxuICBsMTogJ2Jlc3RWYWx1ZSArIGNhbmRpZGF0ZScsXG4gIGwyOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlJyxcbiAgbG9nU3VtOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlJyxcbn07XG5cbmNvbnN0IHJlZHVjZUluaXRWYWx1ZXM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gIG1heDogJ19BW29mZnNldF0nLFxuICBtaW46ICdfQVtvZmZzZXRdJyxcbiAgbWVhbjogJzAnLFxuICBzdW06ICcwJyxcbiAgcHJvZDogJzEnLFxuICBzdW1TcXVhcmU6ICcwJyxcbiAgbG9nU3VtRXhwOiAnMCcsXG4gIGwxOiAnMCcsXG4gIGwyOiAnMCcsXG4gIGxvZ1N1bTogJzAnLFxufTtcblxuY29uc3QgcmVkdWNlT3V0cHV0VmFsdWVzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICBtYXg6ICdiZXN0VmFsdWUnLFxuICBtaW46ICdiZXN0VmFsdWUnLFxuICBzdW06ICdiZXN0VmFsdWUnLFxuICBwcm9kOiAnYmVzdFZhbHVlJyxcbiAgc3VtU3F1YXJlOiAnYmVzdFZhbHVlJyxcbiAgbG9nU3VtRXhwOiAnbG9nKGJlc3RWYWx1ZSknLFxuICBsMTogJ2Jlc3RWYWx1ZScsXG4gIGwyOiAnc3FydChiZXN0VmFsdWUpJyxcbiAgbG9nU3VtOiAnbG9nKGJlc3RWYWx1ZSknLFxufTtcblxuY29uc3QgZ2V0SW5uZXJNb3N0QXhlcyA9IChudW1Jbm5lckF4ZXM6IG51bWJlciwgcmFuazogbnVtYmVyKTogbnVtYmVyW10gPT4ge1xuICBjb25zdCByZXMgPSBbXTtcbiAgZm9yIChsZXQgaSA9IHJhbmsgLSBudW1Jbm5lckF4ZXM7IGkgPCByYW5rOyArK2kpIHtcbiAgICByZXMucHVzaChpKTtcbiAgfVxuICByZXR1cm4gcmVzO1xufTtcblxuY29uc3QgY29tcHV0ZU91dEFuZFJlZHVjZVNoYXBlcyA9IChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGF4ZXM6IHJlYWRvbmx5IG51bWJlcltdKTogW251bWJlcltdLCBudW1iZXJbXV0gPT4ge1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IFtdO1xuICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCByYW5rOyBkaW0rKykge1xuICAgIGlmIChheGVzLmluZGV4T2YoZGltKSA9PT0gLTEpIHtcbiAgICAgIG91dHB1dFNoYXBlLnB1c2goc2hhcGVbZGltXSk7XG4gICAgfVxuICB9XG4gIGNvbnN0IHJlZHVjZVNoYXBlID0gYXhlcy5tYXAoKGRpbSkgPT4gc2hhcGVbZGltXSk7XG4gIHJldHVybiBbb3V0cHV0U2hhcGUsIHJlZHVjZVNoYXBlXTtcbn07XG5cbmNvbnN0IGV4cGFuZFNoYXBlVG9LZWVwRGltID0gKHNoYXBlOiBudW1iZXJbXSwgYXhlczogbnVtYmVyW10pOiBudW1iZXJbXSA9PiB7XG4gIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGggKyBheGVzLmxlbmd0aDtcbiAgY29uc3QgZXhwYW5kU2hhcGUgPSBbXTtcbiAgbGV0IHNoYXBlSWR4ID0gMDtcbiAgZm9yIChsZXQgZGltID0gMDsgZGltIDwgcmFuazsgZGltKyspIHtcbiAgICBpZiAoYXhlcy5pbmRleE9mKGRpbSkgPT09IC0xKSB7XG4gICAgICBleHBhbmRTaGFwZS5wdXNoKHNoYXBlW3NoYXBlSWR4KytdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZXhwYW5kU2hhcGUucHVzaCgxKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGV4cGFuZFNoYXBlO1xufTtcblxuY29uc3QgYXJlQXhlc0lubmVyTW9zdERpbXMgPSAoYXhlczogbnVtYmVyW10sIHJhbms6IG51bWJlcik6IGJvb2xlYW4gPT4ge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGF4ZXMubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoYXhlc1theGVzLmxlbmd0aCAtIGkgLSAxXSAhPT0gcmFuayAtIDEgLSBpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufTtcblxuY29uc3QgZ2V0QXhlc1Blcm11dGF0aW9uID0gKGF4ZXM6IG51bWJlcltdLCByYW5rOiBudW1iZXIpOiBudW1iZXJbXSA9PiB7XG4gIGNvbnN0IHJlcyA9IFtdO1xuICBpZiAoIWFyZUF4ZXNJbm5lck1vc3REaW1zKGF4ZXMsIHJhbmspKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByYW5rOyArK2kpIHtcbiAgICAgIGlmIChheGVzLmluZGV4T2YoaSkgPT09IC0xKSB7XG4gICAgICAgIHJlcy5wdXNoKGkpO1xuICAgICAgfVxuICAgIH1cbiAgICBheGVzLmZvckVhY2goKGF4aXMpID0+IHJlcy5wdXNoKGF4aXMpKTtcbiAgfVxuICByZXR1cm4gcmVzO1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVJlZHVjZVNoYXJlZFByb2dyYW1JbmZvID0gKFxuICBuYW1lOiBzdHJpbmcsXG4gIGNhY2hlS2V5OiBzdHJpbmcsXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICByZWR1Y2VUeXBlOiBzdHJpbmcsXG4gIG91dHB1dERhdGFUeXBlOiBEYXRhVHlwZSxcbiAgb3V0cHV0U2hhcGU6IG51bWJlcltdLFxuICByZWR1Y2VTaGFwZTogbnVtYmVyW10sXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcblxuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCByZWR1Y2VTaXplID0gU2hhcGVVdGlsLnNpemUocmVkdWNlU2hhcGUpO1xuXG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnX0EnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0U2hhcGUpO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0Jywgb3V0cHV0RGF0YVR5cGUsIG91dHB1dFNoYXBlKTtcblxuICBsZXQgd29ya2dyb3VwU2l6ZSA9IDY0O1xuICAvLyBJZiBvbmx5IG9uZSB3b3JrZ3JvdXAgaXMgZGlzcGF0Y2hlZCwgaW5jcmVhc2Ugd29ya2dyb3VwU2l6ZSB0byBpbXByb3ZlIHBhcmFsbGVsaXNtLlxuICBpZiAob3V0cHV0U2l6ZSA9PT0gMSkge1xuICAgIHdvcmtncm91cFNpemUgPSAyNTY7XG4gIH1cblxuICBjb25zdCBzaGFyZWRNZW1vcnlTbmlwcGV0ID0gYFxuICAgICAgICAgIHZhcjx3b3JrZ3JvdXA+IGFCZXN0VmFsdWVzIDogYXJyYXk8ZjMyLCAke3dvcmtncm91cFNpemV9PjtcbiAgICAgICBgO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ3JlZHVjZVNpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgb3V0cHV0KX1cbiAgICAgICAgJHtzaGFyZWRNZW1vcnlTbmlwcGV0fVxuICAgICAgICBmbiBESVZfQ0VJTChhIDogdTMyLCBiIDogdTMyKSAtPiB1MzIge1xuICAgICAgICAgIHJldHVybiAoKGEgLSAxdSkgLyBiICsgMXUpO1xuICAgICAgICAgfVxuICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KHdvcmtncm91cFNpemUpfVxuXG4gICAgICAgICAgbGV0IG91dHB1dEluZGV4ID0gZ2xvYmFsX2lkeCAvICR7d29ya2dyb3VwU2l6ZX07XG4gICAgICAgICAgbGV0IG9mZnNldCA9IG91dHB1dEluZGV4ICogdW5pZm9ybXMucmVkdWNlU2l6ZTtcblxuICAgICAgICAgIHZhciBiZXN0VmFsdWUgPSBmMzIoJHtyZWR1Y2VJbml0VmFsdWVzW3JlZHVjZVR5cGVdfSk7XG4gICAgICAgICAgbGV0IExlbmd0aCA9IHVuaWZvcm1zLnJlZHVjZVNpemU7XG4gICAgICAgICAgZm9yICh2YXIgayA9IGxvY2FsX2lkeDsgayA8IExlbmd0aDsgayA9IGsgKyAke3dvcmtncm91cFNpemV9KSB7XG4gICAgICAgICAgIGxldCBjYW5kaWRhdGUgPSBmMzIoJHtpbnB1dC5nZXRCeU9mZnNldCgnb2Zmc2V0ICsgaycpfSk7XG4gICAgICAgICAgIGJlc3RWYWx1ZSA9ICR7cmVkdWNlT3BzW3JlZHVjZVR5cGVdfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYUJlc3RWYWx1ZXNbbG9jYWxfaWR4XSA9IGJlc3RWYWx1ZTtcbiAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgICAgIHZhciByZWR1Y2VTaXplID0gbWluKExlbmd0aCwgJHt3b3JrZ3JvdXBTaXplfXUpO1xuICAgICAgICAgZm9yICh2YXIgY3VycmVudFNpemUgPSByZWR1Y2VTaXplIC8gMnU7IHJlZHVjZVNpemUgPiAxdTtcbiAgICAgICAgICAgICBjdXJyZW50U2l6ZSA9IHJlZHVjZVNpemUgLyAydSkge1xuICAgICAgICAgICBsZXQgaW50ZXJ2YWwgPSBESVZfQ0VJTChyZWR1Y2VTaXplLCAydSk7XG4gICAgICAgICAgIGlmIChsb2NhbF9pZHggPCBjdXJyZW50U2l6ZSkge1xuICAgICAgICAgICAgbGV0IGNhbmRpZGF0ZSA9IGFCZXN0VmFsdWVzW2xvY2FsX2lkeCArIGludGVydmFsXTtcbiAgICAgICAgICAgIGJlc3RWYWx1ZSA9ICR7cmVkdWNlU2hhcmVkT3BzW3JlZHVjZVR5cGVdfTtcbiAgICAgICAgICAgIGFCZXN0VmFsdWVzW2xvY2FsX2lkeF0gPSBiZXN0VmFsdWU7XG4gICAgICAgICAgIH1cbiAgICAgICAgICAgcmVkdWNlU2l6ZSA9IGludGVydmFsO1xuICAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgICAgICB9XG5cbiAgICAgICAgIGlmIChsb2NhbF9pZHggPT0gMHUpIHtcbiAgICAgICAgICAke291dHB1dC5zZXRCeU9mZnNldChcbiAgICAgICAgICAgICdvdXRwdXRJbmRleCcsXG4gICAgICAgICAgICBgJHtcbiAgICAgICAgICAgICAgcmVkdWNlVHlwZSA9PT0gJ21lYW4nXG4gICAgICAgICAgICAgICAgPyBgJHtvdXRwdXQudHlwZS5zdG9yYWdlfShiZXN0VmFsdWUgLyBmMzIodW5pZm9ybXMucmVkdWNlU2l6ZSkpYFxuICAgICAgICAgICAgICAgIDogYCR7b3V0cHV0LnR5cGUuc3RvcmFnZX0oJHtyZWR1Y2VPdXRwdXRWYWx1ZXNbcmVkdWNlVHlwZV19KWBcbiAgICAgICAgICAgIH1gLFxuICAgICAgICAgICl9O1xuICAgICAgICAgfVxuICAgICAgICB9YDtcblxuICAvLyBPbmUgd29yayBncm91cCBpcyByZXNwb25zaWJsZSBmb3Igb25seSBvbmUgZWxlbWVudCBvZiBvdXRwdXQuXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICAvLyBOb3RlIHRoYXQgaW4gSlNFUCwgV0cgc2l6ZSBpcyBub3QgaW5jbHVkZWQgaW4gY2FjaGUgYnkgZGVmYXVsdCwgYnV0IFdlYkdQVSBFUCBpdCBpcy5cbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtjYWNoZUtleX07JHt3b3JrZ3JvdXBTaXplfWAsIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3R5cGUnXSB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBvdXRwdXREYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogb3V0cHV0U2l6ZSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zOiBbeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHJlZHVjZVNpemUgfV0sXG4gICAgfSksXG4gIH07XG59O1xuXG5jb25zdCByZWR1Y2VDb21tb24gPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBuYW1lOiBzdHJpbmcsXG4gIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMsXG4gIHJlZHVjZVR5cGU6ICdzdW0nIHwgJ3N1bVNxdWFyZScgfCAncHJvZCcgfCAnbWluJyB8ICdtYXgnIHwgJ21lYW4nIHwgJ2xvZ1N1bUV4cCcgfCAnbDEnIHwgJ2wyJyB8ICdsb2dTdW0nLFxuKTogdm9pZCA9PiB7XG4gIGNvbnN0IHVwZGF0ZWRBdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzID1cbiAgICBjb250ZXh0LmlucHV0cy5sZW5ndGggPT09IDEgPyBhdHRyaWJ1dGVzIDogY3JlYXRlUmVkdWNlQXR0cmlidXRlc0Zyb21JbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuXG4gIGxldCB1cGRhdGVkQXhlcyA9IHVwZGF0ZWRBdHRyaWJ1dGVzLmF4ZXM7XG4gIGlmICh1cGRhdGVkQXhlcy5sZW5ndGggPT09IDAgJiYgIXVwZGF0ZWRBdHRyaWJ1dGVzLm5vb3BXaXRoRW1wdHlBeGVzKSB7XG4gICAgdXBkYXRlZEF4ZXMgPSBjb250ZXh0LmlucHV0c1swXS5kaW1zLm1hcCgoX2RpbSwgaSkgPT4gaSk7XG4gIH1cbiAgY29uc3Qgbm9ybWFsaXplQXhlcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGVzKHVwZGF0ZWRBeGVzLCBjb250ZXh0LmlucHV0c1swXS5kaW1zLmxlbmd0aCk7XG5cbiAgbGV0IGF4ZXMgPSBub3JtYWxpemVBeGVzO1xuICBsZXQgaW5wdXQgPSBjb250ZXh0LmlucHV0c1swXTtcbiAgY29uc3QgcGVybXV0ZWRBeGVzID0gZ2V0QXhlc1Blcm11dGF0aW9uKGF4ZXMsIGNvbnRleHQuaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcbiAgaWYgKHBlcm11dGVkQXhlcy5sZW5ndGggPiAwKSB7XG4gICAgaW5wdXQgPSBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sIHBlcm11dGVkQXhlcyksIHtcbiAgICAgIGlucHV0czogWzBdLFxuICAgICAgb3V0cHV0czogWy0xXSxcbiAgICB9KVswXTtcbiAgICBheGVzID0gZ2V0SW5uZXJNb3N0QXhlcyhheGVzLmxlbmd0aCwgaW5wdXQuZGltcy5sZW5ndGgpO1xuICB9XG5cbiAgY29uc3QgW291dHB1dFNoYXBlLCByZWR1Y2VTaGFwZV0gPSBjb21wdXRlT3V0QW5kUmVkdWNlU2hhcGVzKGlucHV0LmRpbXMsIGF4ZXMpO1xuICBsZXQgZmluYWxPdXRwdXRTaGFwZSA9IG91dHB1dFNoYXBlO1xuICBpZiAodXBkYXRlZEF0dHJpYnV0ZXMua2VlcERpbXMpIHtcbiAgICBmaW5hbE91dHB1dFNoYXBlID0gZXhwYW5kU2hhcGVUb0tlZXBEaW0ob3V0cHV0U2hhcGUsIG5vcm1hbGl6ZUF4ZXMpO1xuICB9XG5cbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZVJlZHVjZVNoYXJlZFByb2dyYW1JbmZvKFxuICAgICAgbmFtZSxcbiAgICAgIHVwZGF0ZWRBdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICAgW2lucHV0XSxcbiAgICAgIHJlZHVjZVR5cGUsXG4gICAgICBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgIGZpbmFsT3V0cHV0U2hhcGUsXG4gICAgICByZWR1Y2VTaGFwZSxcbiAgICApLFxuICAgIHsgaW5wdXRzOiBbaW5wdXRdIH0sXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTWVhblNoYXJlZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICByZWR1Y2VDb21tb24oY29udGV4dCwgJ1JlZHVjZU1lYW5TaGFyZWQnLCBhdHRyaWJ1dGVzLCAnbWVhbicpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZUwxU2hhcmVkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHJlZHVjZUNvbW1vbihjb250ZXh0LCAnUmVkdWNlTDFTaGFyZWQnLCBhdHRyaWJ1dGVzLCAnbDEnKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VMMlNoYXJlZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICByZWR1Y2VDb21tb24oY29udGV4dCwgJ1JlZHVjZUwyU2hhcmVkJywgYXR0cmlidXRlcywgJ2wyJyk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTG9nU3VtRXhwU2hhcmVkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHJlZHVjZUNvbW1vbihjb250ZXh0LCAnUmVkdWNlTG9nU3VtRXhwU2hhcmVkJywgYXR0cmlidXRlcywgJ2xvZ1N1bUV4cCcpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZU1heFNoYXJlZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICByZWR1Y2VDb21tb24oY29udGV4dCwgJ1JlZHVjZU1heFNoYXJlZCcsIGF0dHJpYnV0ZXMsICdtYXgnKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VNaW5TaGFyZWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgcmVkdWNlQ29tbW9uKGNvbnRleHQsICdSZWR1Y2VNaW5TaGFyZWQnLCBhdHRyaWJ1dGVzLCAnbWluJyk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlUHJvZFNoYXJlZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICByZWR1Y2VDb21tb24oY29udGV4dCwgJ1JlZHVjZVByb2RTaGFyZWQnLCBhdHRyaWJ1dGVzLCAncHJvZCcpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZVN1bVNoYXJlZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICByZWR1Y2VDb21tb24oY29udGV4dCwgJ1JlZHVjZVN1bVNoYXJlZCcsIGF0dHJpYnV0ZXMsICdzdW0nKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VTdW1TcXVhcmVTaGFyZWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgcmVkdWNlQ29tbW9uKGNvbnRleHQsICdSZWR1Y2VTdW1TcXVhcmVTaGFyZWQnLCBhdHRyaWJ1dGVzLCAnc3VtU3F1YXJlJyk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTG9nU3VtU2hhcmVkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHJlZHVjZUNvbW1vbihjb250ZXh0LCAnUmVkdWNlTG9nU3VtU2hhcmVkJywgYXR0cmlidXRlcywgJ2xvZ1N1bScpO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1TaGFkZXJDYWNoZUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBJbmRpY2VzSGVscGVyLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuaW1wb3J0IHtcbiAgcmVkdWNlTDFTaGFyZWQsXG4gIHJlZHVjZUwyU2hhcmVkLFxuICByZWR1Y2VMb2dTdW1FeHBTaGFyZWQsXG4gIHJlZHVjZUxvZ1N1bVNoYXJlZCxcbiAgcmVkdWNlTWF4U2hhcmVkLFxuICByZWR1Y2VNZWFuU2hhcmVkLFxuICByZWR1Y2VNaW5TaGFyZWQsXG4gIHJlZHVjZVByb2RTaGFyZWQsXG4gIHJlZHVjZVN1bVNoYXJlZCxcbiAgcmVkdWNlU3VtU3F1YXJlU2hhcmVkLFxufSBmcm9tICcuL3JlZHVjZS1zaGFyZWQnO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoID09PSAwIHx8IGlucHV0cy5sZW5ndGggPiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdSZWR1Y2Ugb3AgcmVxdWlyZXMgMSBvciAyIGlucHV0cy4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAyICYmIGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBheGVzIGlucHV0IGRpbXMuJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVkdWNlQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIGtlZXBEaW1zOiBib29sZWFuO1xuICBub29wV2l0aEVtcHR5QXhlczogYm9vbGVhbjtcbiAgYXhlczogbnVtYmVyW107XG59XG5cbmV4cG9ydCB0eXBlIFJlZHVjZU9wID0gKFxuICBpbnB1dDogSW5kaWNlc0hlbHBlcixcbiAgb3V0cHV0OiBJbmRpY2VzSGVscGVyLFxuICBheGVzOiByZWFkb25seSBudW1iZXJbXSxcbikgPT4gW3N0cmluZywgc3RyaW5nLCBzdHJpbmcsIHN0cmluZywgLi4uc3RyaW5nW11dO1xuXG5jb25zdCBub09wOiBSZWR1Y2VPcCA9IChpbnB1dCkgPT4gWycnLCAnJywgYHZhciB2YWx1ZSA9ICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9O2AsICcnXTtcbmV4cG9ydCBjb25zdCBjcmVhdGVSZWR1Y2VQcm9ncmFtSW5mbyA9IChcbiAgbmFtZTogc3RyaW5nLFxuICBzaGFkZXJDYWNoZTogUHJvZ3JhbVNoYWRlckNhY2hlSW5mbyxcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIHJlZHVjZU9wOiBSZWR1Y2VPcCxcbiAgYXhlc0lucHV0OiBudW1iZXJbXSxcbiAgb3V0cHV0RGF0YVR5cGU6IERhdGFUeXBlLFxuICBrZWVwRGltcyA9IGZhbHNlLFxuICBub29wV2l0aEVtcHR5QXhlcyA9IGZhbHNlLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBvdXRwdXRTaGFwZTogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBpbnB1dFJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcbiAgY29uc3QgYXhlcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGVzKGF4ZXNJbnB1dCwgaW5wdXRSYW5rKTtcbiAgY29uc3QgcmVkdWNlT25BbGxBeGVzID0gIW5vb3BXaXRoRW1wdHlBeGVzICYmIGF4ZXMubGVuZ3RoID09PSAwO1xuICBpbnB1dFNoYXBlLmZvckVhY2goKGQsIGkpID0+IHtcbiAgICBpZiAocmVkdWNlT25BbGxBeGVzIHx8IGF4ZXMuaW5kZXhPZihpKSA+PSAwKSB7XG4gICAgICBpZiAoa2VlcERpbXMpIHtcbiAgICAgICAgb3V0cHV0U2hhcGUucHVzaCgxKTtcbiAgICAgIH0gLy8gZWxzZSB7IC8vIHNraXAgdGhpcyBheGlzfVxuICAgIH0gZWxzZSB7XG4gICAgICBvdXRwdXRTaGFwZS5wdXNoKGQpO1xuICAgIH1cbiAgfSk7XG4gIGNvbnN0IG91dHB1dFJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlkeENvcHk6IHN0cmluZ1tdID0gW107IC8vIGNvcHkgb3V0cHV0IGluZGV4ZXMgdG8gaW5wdXQgaW5kZXhlc1xuXG4gICAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdfQScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRSYW5rKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0Jywgb3V0cHV0RGF0YVR5cGUsIG91dHB1dFJhbmspO1xuICAgIGNvbnN0IG9wcyA9IHJlZHVjZU9wKGlucHV0LCBvdXRwdXQsIGF4ZXMpO1xuICAgIGxldCByZWR1Y2VPcHMgPSBvcHNbMl07XG5cbiAgICBmb3IgKGxldCBrID0gMCwgbCA9IDA7IGsgPCBpbnB1dFJhbms7IGsrKykge1xuICAgICAgLy8gaWYgdGhpcyBheGlzIGlzIHJlZHVjZWRcbiAgICAgIGlmIChyZWR1Y2VPbkFsbEF4ZXMgfHwgYXhlcy5pbmRleE9mKGspID49IDApIHtcbiAgICAgICAgaWYgKGtlZXBEaW1zKSB7XG4gICAgICAgICAgbCsrO1xuICAgICAgICB9XG4gICAgICAgIC8vIGxvb3Agb3ZlciB0aGUgZC10aCBheGlzXG4gICAgICAgIHJlZHVjZU9wcyA9IGBmb3IodmFyIGoke2t9OiB1MzIgPSAwOyBqJHtrfSA8ICR7aW5wdXRTaGFwZVtrXX07IGoke2t9KyspIHtcbiAgICAgICAgICAgICAgICAgICR7b3BzWzJdLmluY2x1ZGVzKCdsYXN0X2luZGV4JykgPyBgbGV0IGxhc3RfaW5kZXggPSBqJHtrfTtgIDogJyd9XG4gICAgICAgICAgICAgICAgICAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0X2luZGljZXMnLCBrLCBgaiR7a31gKX1cbiAgICAgICAgICAgICAgICAgICR7cmVkdWNlT3BzfVxuICAgICAgICAgICAgICAgIH1gO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWR4Q29weS5wdXNoKGAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0X2luZGljZXMnLCBrLCBvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCBsKSl9O2ApO1xuICAgICAgICBsKys7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBgXG5cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRfc2l6ZScsICd1MzInKS5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBvdXRwdXQpfVxuXG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgICAgICAgdmFyIGlucHV0X2luZGljZXM6ICR7aW5wdXQudHlwZS5pbmRpY2VzfTtcbiAgICAgICAgICBsZXQgb3V0cHV0X2luZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG5cbiAgICAgICAgICAke2lkeENvcHkuam9pbignXFxuJyl9XG4gICAgICAgICAgJHtvcHNbMF19ICAgICAgIC8vIGluaXQgb3BzIGZvciByZWR1Y2UgbWF4L21pblxuICAgICAgICAgICR7b3BzWzFdfVxuICAgICAgICAgICR7cmVkdWNlT3BzfVxuICAgICAgICAgICR7b3BzWzNdfVxuICAgICAgICAgICR7b3BzLmxlbmd0aCA9PT0gNCA/IG91dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZScpIDogb3BzLnNsaWNlKDQpLmpvaW4oJ1xcbicpfVxuICAgICAgICB9YDtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIG5hbWUsXG4gICAgc2hhZGVyQ2FjaGUsXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IG91dHB1dERhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zOiBbXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0U2hhcGUsIG91dHB1dFNoYXBlKSxcbiAgICAgIF0sXG4gICAgfSksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlUmVkdWNlQXR0cmlidXRlc0Zyb21JbnB1dHMgPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzLFxuKTogUmVkdWNlQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGF4ZXM6IG51bWJlcltdID0gW107XG4gIGlmIChpbnB1dHNbMV0uZGltc1swXSA+IDApIHtcbiAgICBpbnB1dHNbMV0uZ2V0QmlnSW50NjRBcnJheSgpLmZvckVhY2goKHYpID0+IGF4ZXMucHVzaChOdW1iZXIodikpKTtcbiAgfVxuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtcbiAgICBheGVzLFxuICAgIGtlZXBEaW1zOiBhdHRyaWJ1dGVzLmtlZXBEaW1zLFxuICAgIG5vb3BXaXRoRW1wdHlBeGVzOiBhdHRyaWJ1dGVzLm5vb3BXaXRoRW1wdHlBeGVzLFxuICB9KTtcbn07XG5cbmNvbnN0IHJ1blJlZHVjZVByb2dyYW0gPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBuYW1lOiBzdHJpbmcsXG4gIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMsXG4gIHJlZHVjZU9wOiBSZWR1Y2VPcCxcbik6IHZvaWQgPT4ge1xuICBjb25zdCBpbnB1dHMgPSBjb250ZXh0LmlucHV0cztcbiAgY29uc3QgdXBkYXRlZEF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMgPVxuICAgIGlucHV0cy5sZW5ndGggPT09IDEgPyBhdHRyaWJ1dGVzIDogY3JlYXRlUmVkdWNlQXR0cmlidXRlc0Zyb21JbnB1dHMoaW5wdXRzLCBhdHRyaWJ1dGVzKTtcblxuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlUmVkdWNlUHJvZ3JhbUluZm8oXG4gICAgICBuYW1lLFxuICAgICAgeyBoaW50OiB1cGRhdGVkQXR0cmlidXRlcy5jYWNoZUtleSwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddIH0sXG4gICAgICBbaW5wdXRzWzBdXSxcbiAgICAgIHVwZGF0ZWRBdHRyaWJ1dGVzLm5vb3BXaXRoRW1wdHlBeGVzICYmIHVwZGF0ZWRBdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoID09PSAwID8gbm9PcCA6IHJlZHVjZU9wLFxuICAgICAgdXBkYXRlZEF0dHJpYnV0ZXMuYXhlcyxcbiAgICAgIGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgIHVwZGF0ZWRBdHRyaWJ1dGVzLmtlZXBEaW1zLFxuICAgICAgdXBkYXRlZEF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMsXG4gICAgKSxcbiAgICB7IGlucHV0czogWzBdIH0sXG4gICk7XG59O1xuXG5jb25zdCByZWR1Y2VMb2dTdW1OYWl2ZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9IChpbnB1dCwgb3V0cHV0KSA9PiBbXG4gICAgYHZhciB2YWx1ZSA9ICR7b3V0cHV0LnR5cGUuc3RvcmFnZX0oMCk7YCxcbiAgICAnJyxcbiAgICBgdmFsdWUgKz0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07YCxcbiAgICAndmFsdWUgPSBsb2codmFsdWUpOycsXG4gIF07XG4gIHJ1blJlZHVjZVByb2dyYW0oY29udGV4dCwgJ1JlZHVjZUxvZ1N1bScsIGF0dHJpYnV0ZXMsIHJlZHVjZU9wKTtcbn07XG5cbmNvbnN0IHJlZHVjZUwxTmFpdmUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoaW5wdXQsIG91dHB1dCkgPT4gW1xuICAgIGB2YXIgdmFsdWUgPSAke291dHB1dC50eXBlLnN0b3JhZ2V9KDApO2AsXG4gICAgJycsXG4gICAgYHZhbHVlICs9IGFicygke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfSk7YCxcbiAgICAnJyxcbiAgXTtcbiAgcnVuUmVkdWNlUHJvZ3JhbShjb250ZXh0LCAnUmVkdWNlTDEnLCBhdHRyaWJ1dGVzLCByZWR1Y2VPcCk7XG59O1xuXG5jb25zdCByZWR1Y2VMMk5haXZlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0LCBvdXRwdXQpID0+IFtcbiAgICBgdmFyIHQgPSAke291dHB1dC50eXBlLnZhbHVlfSgwKTsgdmFyIHZhbHVlID0gJHtvdXRwdXQudHlwZS52YWx1ZX0oMCk7YCxcbiAgICAnJyxcbiAgICBgdCA9ICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9OyB2YWx1ZSArPSAodCAqIHQpO2AsXG4gICAgJ3ZhbHVlID0gc3FydCh2YWx1ZSk7JyxcbiAgXTtcbiAgcnVuUmVkdWNlUHJvZ3JhbShjb250ZXh0LCAnUmVkdWNlTDInLCBhdHRyaWJ1dGVzLCByZWR1Y2VPcCk7XG59O1xuXG5jb25zdCByZWR1Y2VMb2dTdW1FeHBOYWl2ZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9IChpbnB1dCwgb3V0cHV0KSA9PiBbXG4gICAgYHZhciB2YWx1ZSA9ICR7b3V0cHV0LnR5cGUuc3RvcmFnZX0oMCk7YCxcbiAgICAnJyxcbiAgICBgdmFsdWUgKz0gZXhwKCR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9KTtgLFxuICAgICd2YWx1ZSA9IGxvZyh2YWx1ZSk7JyxcbiAgXTtcbiAgcnVuUmVkdWNlUHJvZ3JhbShjb250ZXh0LCAnUmVkdWNlTG9nU3VtRXhwJywgYXR0cmlidXRlcywgcmVkdWNlT3ApO1xufTtcblxuY29uc3QgcmVkdWNlTWF4TmFpdmUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoaW5wdXQsIF9vdXRwdXQsIGF4ZXMpID0+IHtcbiAgICBjb25zdCBpZHhaZXJvID0gW107XG4gICAgZm9yIChsZXQgayA9IDA7IGsgPCBpbnB1dC5yYW5rOyBrKyspIHtcbiAgICAgIGlmIChheGVzLmluZGV4T2YoaykgPj0gMCB8fCBheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBpZHhaZXJvLnB1c2goaW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsIGssIDApKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gW1xuICAgICAgYCR7aWR4WmVyby5qb2luKCdcXG4nKX1gLFxuICAgICAgYHZhciB2YWx1ZSA9ICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9O2AsXG4gICAgICBgdmFsdWUgPSBtYXgodmFsdWUsICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9KTtgLFxuICAgICAgJycsXG4gICAgXTtcbiAgfTtcbiAgcnVuUmVkdWNlUHJvZ3JhbShjb250ZXh0LCAnUmVkdWNlTWF4JywgYXR0cmlidXRlcywgcmVkdWNlT3ApO1xufTtcblxuY29uc3QgcmVkdWNlTWVhbk5haXZlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0LCBvdXRwdXQsIGF4ZXMpID0+IHtcbiAgICBsZXQgc2l6ZSA9IDEuMDtcbiAgICBmb3IgKGxldCBrID0gMDsgayA8IGlucHV0LnJhbms7IGsrKykge1xuICAgICAgaWYgKGF4ZXMuaW5kZXhPZihrKSA+PSAwIHx8IGF4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIC8vIFRPRE86IHRoaXMgZGVwZW5kcyBvbiB0aGUgaW5wdXQgZGltcy4gSWYgd2Ugd2FudCB0byB1c2UgdW5pZm9ybSwgdGhpcyBuZWVkIHRvIGJlIHVwZGF0ZWQuXG4gICAgICAgIHNpemUgKj0gY29udGV4dC5pbnB1dHNbMF0uZGltc1trXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gW1xuICAgICAgJ3ZhciBzdW0gPSBmMzIoMCk7JyxcbiAgICAgICcnLFxuICAgICAgYHN1bSArPSBmMzIoJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX0pO2AsXG4gICAgICBgbGV0IHZhbHVlID0gJHtvdXRwdXQudHlwZS52YWx1ZX0oc3VtIC8gJHtzaXplfSk7YCxcbiAgICBdO1xuICB9O1xuICBydW5SZWR1Y2VQcm9ncmFtKGNvbnRleHQsICdSZWR1Y2VNZWFuJywgYXR0cmlidXRlcywgcmVkdWNlT3ApO1xufTtcblxuY29uc3QgcmVkdWNlTWluTmFpdmUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoaW5wdXQsIF9vdXRwdXQsIGF4ZXMpID0+IHtcbiAgICBjb25zdCBpZHhaZXJvID0gW107XG4gICAgZm9yIChsZXQgayA9IDA7IGsgPCBpbnB1dC5yYW5rOyBrKyspIHtcbiAgICAgIGlmIChheGVzLmluZGV4T2YoaykgPj0gMCB8fCBheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBpZHhaZXJvLnB1c2goYGlucHV0X2luZGljZXNbJHtrfV0gPSAwO2ApOyAvLyBmaXJzdCBlbGVtZW50XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFtcbiAgICAgIGAke2lkeFplcm8uam9pbignXFxuJyl9YCxcbiAgICAgIGB2YXIgdmFsdWUgPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTtgLFxuICAgICAgYHZhbHVlID0gbWluKHZhbHVlLCAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfSk7YCxcbiAgICAgICcnLFxuICAgIF07XG4gIH07XG4gIHJ1blJlZHVjZVByb2dyYW0oY29udGV4dCwgJ1JlZHVjZU1pbicsIGF0dHJpYnV0ZXMsIHJlZHVjZU9wKTtcbn07XG5cbmNvbnN0IHJlZHVjZVByb2ROYWl2ZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9IChpbnB1dCwgb3V0cHV0KSA9PiBbXG4gICAgYHZhciB2YWx1ZSA9ICR7b3V0cHV0LnR5cGUuc3RvcmFnZX0oMSk7YCxcbiAgICAnJyxcbiAgICBgdmFsdWUgKj0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07YCxcbiAgICAnJyxcbiAgXTtcbiAgcnVuUmVkdWNlUHJvZ3JhbShjb250ZXh0LCAnUmVkdWNlUHJvZCcsIGF0dHJpYnV0ZXMsIHJlZHVjZU9wKTtcbn07XG5cbmNvbnN0IHJlZHVjZVN1bU5haXZlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0LCBvdXRwdXQpID0+IFtcbiAgICBgdmFyIHZhbHVlID0gJHtvdXRwdXQudHlwZS5zdG9yYWdlfSgwKTtgLFxuICAgICcnLFxuICAgIGB2YWx1ZSArPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTtgLFxuICAgICcnLFxuICBdO1xuICBydW5SZWR1Y2VQcm9ncmFtKGNvbnRleHQsICdSZWR1Y2VTdW0nLCBhdHRyaWJ1dGVzLCByZWR1Y2VPcCk7XG59O1xuXG5jb25zdCByZWR1Y2VTdW1TcXVhcmVOYWl2ZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9IChpbnB1dCwgb3V0cHV0KSA9PiBbXG4gICAgYHZhciB0ID0gJHtvdXRwdXQudHlwZS52YWx1ZX0oMCk7IHZhciB2YWx1ZSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KDApO2AsXG4gICAgJycsXG4gICAgYHQgPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTsgdmFsdWUgKz0gdCAqIHQ7YCxcbiAgICAnJyxcbiAgXTtcbiAgcnVuUmVkdWNlUHJvZ3JhbShjb250ZXh0LCAnUmVkdWNlU3VtU3F1YXJlJywgYXR0cmlidXRlcywgcmVkdWNlT3ApO1xufTtcblxuY29uc3QgdXNlTmFpdmVSZWR1Y2VNZXRob2QgPSAoXG4gIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgYXhlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIG5vb3BXaXRoRW1wdHlBeGVzOiBib29sZWFuLFxuKTogYm9vbGVhbiA9PiB7XG4gIGlmIChheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBub29wV2l0aEVtcHR5QXhlcztcbiAgfVxuXG4gIGxldCBvdXRwdXRTaXplID0gMTtcbiAgbGV0IHJlZHVjZVNpemUgPSAxO1xuICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBheGVzLmxlbmd0aDsgZGltKyspIHtcbiAgICBpZiAoYXhlcy5pbmRleE9mKGRpbSkgPT09IC0xKSB7XG4gICAgICBvdXRwdXRTaXplICo9IHNoYXBlW2RpbV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlZHVjZVNpemUgKj0gc2hhcGVbZGltXTtcbiAgICB9XG4gIH1cblxuICAvLyBUaGUgY29uZGl0aW9uIGRhdGEgaXMgdmVyeSByb3VnaCwgYWx0aG91Z2ggY29uc2lkZXJpbmcgdGhlIGNvdW50IG9mIEV4ZWN1dGlvbiBVbml0IChFVSksIHRoZSBwb3RlbnRpYWxcbiAgLy8gd29yayBncm91cHMgaW4gYSBFVSBhbmQgdGhlIGNvdW50cyBvZiBsb29wcyBpbiB0aGUgbmFpdmUgYW5kIHNoYXJlZCBtZXRob2RzLCBhbHNvIGRvaW5nIGV4cGVyaW1lbnRzXG4gIC8vIG9uIHNvbWUgbWFjaGluZXMuXG4gIHJldHVybiByZWR1Y2VTaXplIDwgMzIgJiYgb3V0cHV0U2l6ZSA+IDEwMjQ7XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTWVhbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBpZiAodXNlTmFpdmVSZWR1Y2VNZXRob2QoY29udGV4dC5pbnB1dHNbMF0uZGltcywgYXR0cmlidXRlcy5heGVzLCBhdHRyaWJ1dGVzLm5vb3BXaXRoRW1wdHlBeGVzKSkge1xuICAgIHJlZHVjZU1lYW5OYWl2ZShjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICByZWR1Y2VNZWFuU2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTDEgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKHVzZU5haXZlUmVkdWNlTWV0aG9kKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMsIGF0dHJpYnV0ZXMuYXhlcywgYXR0cmlidXRlcy5ub29wV2l0aEVtcHR5QXhlcykpIHtcbiAgICByZWR1Y2VMMU5haXZlKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9IGVsc2Uge1xuICAgIHJlZHVjZUwxU2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTDIgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKHVzZU5haXZlUmVkdWNlTWV0aG9kKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMsIGF0dHJpYnV0ZXMuYXhlcywgYXR0cmlidXRlcy5ub29wV2l0aEVtcHR5QXhlcykpIHtcbiAgICByZWR1Y2VMMk5haXZlKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9IGVsc2Uge1xuICAgIHJlZHVjZUwyU2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTG9nU3VtRXhwID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICh1c2VOYWl2ZVJlZHVjZU1ldGhvZChjb250ZXh0LmlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLmF4ZXMsIGF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMpKSB7XG4gICAgcmVkdWNlTG9nU3VtRXhwTmFpdmUoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgcmVkdWNlTG9nU3VtRXhwU2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTWF4ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICh1c2VOYWl2ZVJlZHVjZU1ldGhvZChjb250ZXh0LmlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLmF4ZXMsIGF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMpKSB7XG4gICAgcmVkdWNlTWF4TmFpdmUoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgcmVkdWNlTWF4U2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTWluID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICh1c2VOYWl2ZVJlZHVjZU1ldGhvZChjb250ZXh0LmlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLmF4ZXMsIGF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMpKSB7XG4gICAgcmVkdWNlTWluTmFpdmUoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgcmVkdWNlTWluU2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlUHJvZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBpZiAodXNlTmFpdmVSZWR1Y2VNZXRob2QoY29udGV4dC5pbnB1dHNbMF0uZGltcywgYXR0cmlidXRlcy5heGVzLCBhdHRyaWJ1dGVzLm5vb3BXaXRoRW1wdHlBeGVzKSkge1xuICAgIHJlZHVjZVByb2ROYWl2ZShjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICByZWR1Y2VQcm9kU2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlU3VtID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICh1c2VOYWl2ZVJlZHVjZU1ldGhvZChjb250ZXh0LmlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLmF4ZXMsIGF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMpKSB7XG4gICAgcmVkdWNlU3VtTmFpdmUoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgcmVkdWNlU3VtU2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlU3VtU3F1YXJlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICh1c2VOYWl2ZVJlZHVjZU1ldGhvZChjb250ZXh0LmlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLmF4ZXMsIGF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMpKSB7XG4gICAgcmVkdWNlU3VtU3F1YXJlTmFpdmUoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgcmVkdWNlU3VtU3F1YXJlU2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTG9nU3VtID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICh1c2VOYWl2ZVJlZHVjZU1ldGhvZChjb250ZXh0LmlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLmF4ZXMsIGF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMpKSB7XG4gICAgcmVkdWNlTG9nU3VtTmFpdmUoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgcmVkdWNlTG9nU3VtU2hhcmVkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vLyBUT0RPOiB0aGlzIGlzIHRoZSBzYW1lIG5haXZlIGltcGxlbWVudGF0aW9uIHdlIHVzZSBmb3IgcmVkdWNlIHRoYXQgaGFzXG4vLyBwZXJmb3JtYW5jZSBsaW1pdGF0aW9ucyB3aGVuIHRoZSByZWR1Y2VkIGF4aXMgaXMgbG9uZy4gTmVlZCB0byBhZGRcbi8vIGEgb3B0aW1pemVkIGNvZGVwYXRoIGZvciB0aGlzLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlUmVkdWNlUHJvZ3JhbUluZm8sIFJlZHVjZU9wIH0gZnJvbSAnLi9yZWR1Y2UnO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoID09PSAwIHx8IGlucHV0cy5sZW5ndGggPiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdBcmdNaW5NYXhPcCBvcCByZXF1aXJlcyAxIG9yIDIgaW5wdXRzLicpO1xuICB9XG4gIGlmIChpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXJnTWluTWF4QXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIGtlZXBEaW1zOiBib29sZWFuO1xuICBheGlzOiBudW1iZXI7XG4gIHNlbGVjdExhc3RJbmRleDogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgYXJnTWluID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBcmdNaW5NYXhBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgYXJnTWluTWF4T3A6IFJlZHVjZU9wID0gKGlucHV0LCBvdXRwdXQsIGF4ZXMpID0+IHtcbiAgICBjb25zdCBpZHhaZXJvID0gW107XG4gICAgZm9yIChsZXQgayA9IDA7IGsgPCBpbnB1dC5yYW5rOyBrKyspIHtcbiAgICAgIGlmIChheGVzLmluZGV4T2YoaykgPj0gMCB8fCBheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBpZHhaZXJvLnB1c2goYGlucHV0X2luZGljZXNbJHtrfV0gPSAwO2ApOyAvLyBmaXJzdCBlbGVtZW50XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBbXG4gICAgICBgJHtpZHhaZXJvLmpvaW4oJ1xcbicpfWAsXG4gICAgICBgdmFyIHZhbHVlID0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07XFxudmFyIGJlc3RfaW5kZXggOiBpMzIgPSAwO2AsXG4gICAgICBgaWYgKCR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9ICR7YXR0cmlidXRlcy5zZWxlY3RMYXN0SW5kZXggPiAwID8gJzw9JyA6ICc8J30gdmFsdWUpIHtcbiAgICAgICAgIHZhbHVlID0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07XG4gICAgICAgICBiZXN0X2luZGV4ID0gaTMyKGxhc3RfaW5kZXgpO1xuICAgICAgIH1gLFxuICAgICAgJycsXG4gICAgICBvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAnYmVzdF9pbmRleCcpLFxuICAgIF07XG4gIH07XG5cbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZVJlZHVjZVByb2dyYW1JbmZvKFxuICAgICAgJ0FyZ01pbicsXG4gICAgICB7IGhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSB9LFxuICAgICAgW2NvbnRleHQuaW5wdXRzWzBdXSxcbiAgICAgIGFyZ01pbk1heE9wLFxuICAgICAgW2F0dHJpYnV0ZXMuYXhpc10sXG4gICAgICBEYXRhVHlwZS5pbnQ2NCxcbiAgICAgIGF0dHJpYnV0ZXMua2VlcERpbXMsXG4gICAgKSxcbiAgICB7IGlucHV0czogWzBdIH0sXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgYXJnTWF4ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBcmdNaW5NYXhBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgYXJnTWluTWF4T3A6IFJlZHVjZU9wID0gKGlucHV0LCBvdXRwdXQsIGF4ZXMpID0+IHtcbiAgICBjb25zdCBpZHhaZXJvID0gW107XG4gICAgZm9yIChsZXQgayA9IDA7IGsgPCBpbnB1dC5yYW5rOyBrKyspIHtcbiAgICAgIGlmIChheGVzLmluZGV4T2YoaykgPj0gMCB8fCBheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBpZHhaZXJvLnB1c2goYGlucHV0X2luZGljZXNbJHtrfV0gPSAwO2ApOyAvLyBmaXJzdCBlbGVtZW50XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBbXG4gICAgICBgJHtpZHhaZXJvLmpvaW4oJ1xcbicpfWAsXG4gICAgICBgdmFyIHZhbHVlID0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07XFxudmFyIGJlc3RfaW5kZXggOiBpMzIgPSAwO2AsXG4gICAgICBgaWYgKCR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9ICR7YXR0cmlidXRlcy5zZWxlY3RMYXN0SW5kZXggPiAwID8gJz49JyA6ICc+J30gdmFsdWUpIHtcbiAgICAgICAgIHZhbHVlID0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07XG4gICAgICAgICBiZXN0X2luZGV4ID0gaTMyKGxhc3RfaW5kZXgpO1xuICAgICAgIH1gLFxuICAgICAgJycsXG4gICAgICBvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAnYmVzdF9pbmRleCcpLFxuICAgIF07XG4gIH07XG5cbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZVJlZHVjZVByb2dyYW1JbmZvKFxuICAgICAgJ2FyZ01heCcsXG4gICAgICB7IGhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSB9LFxuICAgICAgW2NvbnRleHQuaW5wdXRzWzBdXSxcbiAgICAgIGFyZ01pbk1heE9wLFxuICAgICAgW2F0dHJpYnV0ZXMuYXhpc10sXG4gICAgICBEYXRhVHlwZS5pbnQ2NCxcbiAgICAgIGF0dHJpYnV0ZXMua2VlcERpbXMsXG4gICAgKSxcbiAgICB7IGlucHV0czogWzBdIH0sXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VBcmdNaW5NYXhBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQXJnTWluTWF4QXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoYXR0cmlidXRlcyBhcyBPbWl0PEFyZ01pbk1heEF0dHJpYnV0ZXMsIGtleW9mIEF0dHJpYnV0ZVdpdGhDYWNoZUtleT4pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBHcHVEYXRhVHlwZSwgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBnZXRNYXhDb21wb25lbnRzLFxuICBJbmRpY2VzSGVscGVyLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG4gIHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUsXG4gIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBjb25zdCBlbnVtIEF0dGVudGlvblFrdkZvcm1hdCB7XG4gIHVua25vd24sIC8vIGVudW0gdmFsdWUgbm90IHNldCwgb3IgZGVwZW5kcyBvbiBxa3YgcHJvamVjdGlvbiBpbXBsZW1lbnRhdGlvbiBkZXRhaWxzXG4gIHFrdkJOU0gsIC8vIGZvciBub24tcGFja2VkIHFrdiwgcGVybXV0ZWRcbiAgcWt2QlNOSCwgLy8gZm9yIG5vbi1wYWNrZWQgcWt2LCBub3QgcGVybXV0ZWQsIHVzZWQgYnkgbWVtb3J5IGVmZmljaWVudCBhdHRlbnRpb24gb3IgTXVsdGlIZWFkQXR0ZW50aW9uXG4gIHFrdkJTTjNILCAvLyBmb3IgVFJUIGZ1c2VkIGF0dGVudGlvbiwgcWt2IGFyZSBwYWNrZWRcbiAgcWt2Qk5TSHFrdkJTM05ILCAvLyBmb3IgVFJUIGZ1c2VkIGNhdXNhbCBhdHRlbnRpb24sIGRhdGEgaGFzIHR3byBmb3JtYXRzIChxa3YgaXMgM0JOU0gsIGdlbW1fYnVmZmVyIGlzIEJTM05IKVxuICBxS3ZCU05IeEJTTjJILCAvLyBmb3IgVFJUIGZ1c2VkIGNyb3NzIGF0dGVudGlvbiwga3YgYXJlIHBhY2tlZFxuICBxa3ZUTkgsIC8vIGZvciBtZW1vcnkgZWZmaWNpZW50IGF0dGVudGlvbiwgcWt2IGFyZSBub3QgcGFja2VkLCBhbmQgcGFkZGluZ3MgYXJlIHJlbW92ZWQuXG4gIHFrdlROM0gsIC8vIGZvciBUUlQgZnVzZWQgYXR0ZW50aW9uLCBxa3YgYXJlIHBhY2tlZCBhbmQgcGFkZGluZ3MgYXJlIHJlbW92ZWRcbn1cblxuZXhwb3J0IGNvbnN0IGVudW0gQXR0ZW50aW9uTWFza1R5cGUge1xuICBub25lLCAvLyBObyBtYXNrXG4gIG1hc2sxZEtleVNlcUxlbiwgLy8gW2JhdGNoX3NpemVdLCBrZXkgc2VxdWVuY2UgbGVuZ3RoXG4gIG1hc2sxZEVuZFN0YXJ0LCAvLyBbMiAqIGJhdGNoX3NpemVdIHdpdGggZW5kIHBvc2l0aW9ucyBhbmQgc3RhcnQgcG9zaXRpb25zXG4gIG1hc2sxREtleVNlcUxlblN0YXJ0LCAvLyBbMyAqIGJhdGNoX3NpemUgKyAyXSB3aXRoIFtrZXlfbGVuWzBdLCAuLi4sIGtleV9sZW5bYmF0Y2hfc2l6ZSAtIDFdLCBxdWVyeV9zdGFydFswXSxcbiAgLy8gLi4uLCBxdWVyeV9zdGFydFtiYXRjaF9zaXplIC0gMV0sIHF1ZXJ5X2VuZFtiYXRjaF9zaXplIC0gMV0sIGtleV9zdGFydFswXSwgLi4uLFxuICAvLyBrZXlfc3RhcnRbYmF0Y2hfc2l6ZSAtIDFdLCBrZXlfZW5kW2JhdGNoX3NpemUgLSAxXV1cbiAgbWFzazJkRHVtbXksIC8vIGR1bW15IG1hc2sgd2l0aCBzaGFwZSBbMSwgMV0gb3IgW2JhdGNoX3NpemUsIDFdLiBJdCBoYXMgc2FtZSBlZmZlY3QgYXMgbm8gbWFzay5cbiAgbWFzazJkS2V5UGFkZGluZywgLy8gW2JhdGNoX3NpemUsIHRvdGFsX3NlcXVlbmNlX2xlbmd0aF1cbiAgbWFzazNkQXR0ZW50aW9uLCAvLyBbYmF0Y2hfc2l6ZSwgc2VxdWVuY2VfbGVuZ3RoLCB0b3RhbF9zZXF1ZW5jZV9sZW5ndGhdXG4gIG1hc2s0ZE1lZ2F0cm9uLCAvLyBNZWdhdHJvbiBjYXVzYWwgbWFzayB3aXRoIHNoYXBlIFtiYXRjaF9zaXplLCAxLCBtYXhfc2VxdWVuY2VfbGVuZ3RoLCBtYXhfc2VxdWVuY2VfbGVuZ3RoXVxuICBtYXNrVW5rbm93bixcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBdHRlbnRpb25QYXJhbWV0ZXJzIHtcbiAgYmF0Y2hTaXplOiBudW1iZXI7XG4gIHNlcXVlbmNlTGVuZ3RoOiBudW1iZXI7XG4gIHBhc3RTZXF1ZW5jZUxlbmd0aDogbnVtYmVyO1xuICBrdlNlcXVlbmNlTGVuZ3RoOiBudW1iZXI7XG4gIHRvdGFsU2VxdWVuY2VMZW5ndGg6IG51bWJlcjtcbiAgbWF4U2VxdWVuY2VMZW5ndGg6IG51bWJlcjtcbiAgaW5wdXRIaWRkZW5TaXplOiBudW1iZXI7XG4gIGhpZGRlblNpemU6IG51bWJlcjtcbiAgdkhpZGRlblNpemU6IG51bWJlcjtcbiAgaGVhZFNpemU6IG51bWJlcjtcbiAgdkhlYWRTaXplOiBudW1iZXI7XG4gIG51bUhlYWRzOiBudW1iZXI7XG4gIGt2TnVtSGVhZHM/OiBudW1iZXI7XG4gIG5SZXBzPzogbnVtYmVyO1xuICBpc1VuaWRpcmVjdGlvbmFsPzogYm9vbGVhbjtcbiAgcGFzdFByZXNlbnRTaGFyZUJ1ZmZlcjogYm9vbGVhbjtcbiAgbWFza0ZpbHRlclZhbHVlPzogbnVtYmVyO1xuICBtYXNrVHlwZTogQXR0ZW50aW9uTWFza1R5cGU7XG4gIHNjYWxlOiBudW1iZXI7XG4gIGJyb2FkY2FzdFJlc1Bvc0JpYXM6IGJvb2xlYW47XG4gIHBhc3NQYXN0SW5LdjogYm9vbGVhbjtcbiAgcWt2Rm9ybWF0OiBBdHRlbnRpb25Ra3ZGb3JtYXQ7XG4gIHNvZnRjYXA/OiBudW1iZXI7XG4gIGRvUm90YXJ5PzogbnVtYmVyO1xuICByb3RhcnlJbnRlckxlYXZlZD86IG51bWJlcjtcbiAgc29tbW9vdGhTb2Z0bWF4PzogbnVtYmVyO1xuICBsb2NhbFdpbmRvd3NTaXplPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF0dGVudGlvbkF0dHJzIHtcbiAgbnVtSGVhZHM6IG51bWJlcjtcbiAgaXNVbmlkaXJlY3Rpb25hbDogbnVtYmVyO1xuICBtYXNrRmlsdGVyVmFsdWU6IG51bWJlcjtcbiAgc2NhbGU6IG51bWJlcjtcbiAgZG9Sb3Rhcnk6IG51bWJlcjtcbiAgcWt2SGlkZGVuU2l6ZXM6IG51bWJlcltdO1xuICBwYXN0UHJlc2VudFNoYXJlQnVmZmVyOiBib29sZWFuO1xufVxuXG5jb25zdCB2YWxpZGF0ZUF0dGVudGlvbklucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogQXR0ZW50aW9uQXR0cnMpOiBBdHRlbnRpb25QYXJhbWV0ZXJzID0+IHtcbiAgLy8gQWJicmV2aWF0aW9uIGFuZCBNZWFuaW5nczpcbiAgLy8gICBCOiAgICBiYXRjaF9zaXplXG4gIC8vICAgUzogICAgc2VxdWVuY2VfbGVuZ3RoIChpbnB1dCBzZXF1ZW5jZSBsZW5ndGggb2YgcXVlcnkpXG4gIC8vICAgUDogICAgcGFzdF9zZXF1ZW5jZV9sZW5ndGggKHBhc3Qgc2VxdWVuY2UgbGVuZ3RoIG9mIGtleSBvciB2YWx1ZSlcbiAgLy8gICBMOiAgICBrdl9zZXF1ZW5jZV9sZW5ndGggKGlucHV0IHNlcXVlbmNlIGxlbmd0aCBvZiBrZXkgb3IgdmFsdWUpXG4gIC8vICAgTTogICAgbWF4X3NlcXVlbmNlX2xlbmd0aFxuICAvLyAgIFQ6ICAgIHRvdGFsX3NlcXVlbmNlX2xlbmd0aCA9IHBhc3Rfc2VxdWVuY2VfbGVuZ3RoICsga3Zfc2VxdWVuY2VfbGVuZ3RoXG4gIC8vICAgTjogICAgbnVtX2hlYWRzXG4gIC8vICAgSDogICAgaGVhZCBzaXplIGZvciBRIGFuZCBLLCBha2EgcV9oZWFkX3NpemUgb3Iga19oZWFkX3NpemUgb3IgcWtfaGVhZF9zaXplXG4gIC8vICAgSF92OiAgdl9oZWFkX3NpemVcbiAgLy8gICBEX2k6ICBpbnB1dCBoaWRkZW4gc2l6ZVxuICAvLyAgIEQ6ICAgIGhpZGRlbiBzaXplIGZvciBRIGFuZCBLIChEID0gTiAqIEgpLCBha2EgcV9oaWRkZW5fc2l6ZSBvciBrX2hpZGRlbl9zaXplIG9yIHFrX2hpZGRlbl9zaXplXG4gIC8vICAgRF92OiAgdl9oaWRkZW5fc2l6ZSA9IG51bV9oZWFkcyAqIHZfaGVhZF9zaXplXG5cbiAgLy8gV2hlbiBwYXN0IHN0YXRlIGlzIHVzZWQsIFEsIEsgYW5kIFYgc2hvdWxkIGhhdmUgc2FtZSBoaWRkZW4gc2l6ZSAodW5sZXNzIHdlIHNwbGl0IGl0IGludG8gcGFzdF9rZXkgYW5kIHBhc3RfdmFsdWUpLlxuXG4gIC8vIElucHV0IHNoYXBlczpcbiAgLy8gICBpbnB1dCAgICAgICAgKFEvSy9WKSAgICA6IChCLCBTLCBEX2kpXG4gIC8vICAgd2VpZ2h0cyAgICAgIChRL0svVikgICAgOiAoRF9pLCBEICsgRCArIERfdilcbiAgLy8gICBiaWFzICAgICAgICAgKFEvSy9WKSAgICA6IChEICsgRCArIERfdilcbiAgLy8gICBtYXNrX2luZGV4ICAgICAgICAgICAgICA6IHNlZSBiZWxvd1xuICAvLyAgIHBhc3QgICAgICAgICAoSy9WKSAgICAgIDogKDIsIEIsIE4sIFAsIEgpIG9yIE5VTExcbiAgLy8gICBhdHRlbnRpb25fYmlhcyAgICAgICAgICA6IChCLCBOLCBTLCBUKSBvciBOVUxMXG5cbiAgLy8gRm9yIG1hc2tfaW5kZXgsIHRoZSBmb2xsb3dpbmcgc2hhcGVzIGFyZSBzdXBwb3J0ZWQ6XG4gIC8vICAgICBOVUxMLCAoQiwgMSksICgxLCAxKVxuICAvLyAgICAgKEIpLCAoMiAqIEIpLCAoMyAqIEIgKyAyKVxuICAvLyAgICAgKEIsIFQpXG4gIC8vICAgICAoQiwgUywgVClcbiAgLy8gICAgIChCLCAxLCBNLCBNKVxuICAvL1xuICAvLyBXaGVuIGEgbW9kZWwgaXMgcHJ1bmVkIChsaWtlIHNvbWUgYXR0ZW50aW9uIGhlYWRzIGFyZSByZW1vdmVkIGluIFEvSy9WKSwgaW5wdXRfaGlkZGVuX3NpemUgY291bGQgYmUgbGFyZ2VyXG4gIC8vIHRoYW4gaGlkZGVuIGRpbWVuc2lvbiBvZiBRLCBLIGFuZCBWLlxuXG4gIGNvbnN0IGlucHV0ID0gaW5wdXRzWzBdO1xuICBjb25zdCB3ZWlnaHRzID0gaW5wdXRzWzFdO1xuICBjb25zdCBiaWFzID0gaW5wdXRzWzJdO1xuICBjb25zdCBtYXNrSW5kZXggPSBpbnB1dHNbM107XG4gIGNvbnN0IHBhc3QgPSBpbnB1dHNbNF07XG4gIGNvbnN0IGF0dGVudGlvbkJpYXMgPSBpbnB1dHNbNV07XG5cbiAgaWYgKHBhc3QgJiYgYXR0ZW50aW9uQmlhcykge1xuICAgIHRocm93IG5ldyBFcnJvcignQXR0ZW50aW9uIGNhbm5vdCBoYXZlIGJvdGggcGFzdCBhbmQgYXR0ZW50aW9uX2JpYXMnKTtcbiAgfVxuXG4gIGlmIChpbnB1dC5kaW1zLmxlbmd0aCAhPT0gMykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJpbnB1dFwiIG11c3QgaGF2ZSAzIGRpbWVuc2lvbnMnKTtcbiAgfVxuXG4gIGNvbnN0IGJhdGNoU2l6ZSA9IGlucHV0LmRpbXNbMF07XG4gIGNvbnN0IHNlcXVlbmNlTGVuZ3RoID0gaW5wdXQuZGltc1sxXTtcbiAgY29uc3QgaW5wdXRIaWRkZW5TaXplID0gaW5wdXQuZGltc1syXTtcblxuICBpZiAoYmlhcy5kaW1zLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJiaWFzXCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAxIGRpbWVuc2lvbnMnKTtcbiAgfVxuXG4gIGlmICh3ZWlnaHRzLmRpbXMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcIndlaWdodHNcIiBpcyBleHBlY3RlZCB0byBoYXZlIDIgZGltZW5zaW9ucycpO1xuICB9XG5cbiAgaWYgKHdlaWdodHMuZGltc1swXSAhPT0gaW5wdXRIaWRkZW5TaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCAxIGRpbWVuc2lvbiAwIHNob3VsZCBoYXZlIHNhbWUgbGVuZ3RoIGFzIGRpbWVuc2lvbiAyIG9mIGlucHV0IDAnKTtcbiAgfVxuXG4gIGlmIChiaWFzLmRpbXNbMF0gIT09IHdlaWdodHMuZGltc1sxXSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJiaWFzXCIgZGltZW5zaW9uIDAgc2hvdWxkIGhhdmUgc2FtZSBsZW5ndGggYXMgZGltZW5zaW9uIDEgb2YgaW5wdXQgXCJ3ZWlnaHRzXCInKTtcbiAgfVxuXG4gIGxldCBxSGlkZGVuU2l6ZSA9IGJpYXMuZGltc1swXSAvIDM7XG4gIGxldCBrSGlkZGVuU2l6ZSA9IHFIaWRkZW5TaXplO1xuICBsZXQgdkhpZGRlblNpemUgPSBrSGlkZGVuU2l6ZTtcbiAgaWYgKGF0dHJpYnV0ZXMucWt2SGlkZGVuU2l6ZXMubGVuZ3RoID4gMCkge1xuICAgIGlmIChhdHRyaWJ1dGVzLnFrdkhpZGRlblNpemVzLmxlbmd0aCAhPT0gMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdxa3ZfaGlkZGVuX3NpemVzIGF0dHJpYnV0ZSBzaG91bGQgaGF2ZSAzIGVsZW1lbnRzJyk7XG4gICAgfVxuICAgIGZvciAoY29uc3Qgc3ogb2YgYXR0cmlidXRlcy5xa3ZIaWRkZW5TaXplcykge1xuICAgICAgaWYgKHN6ICUgYXR0cmlidXRlcy5udW1IZWFkcyAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Frdl9oaWRkZW5fc2l6ZXMgc2hvdWxkIGJlIGRpdmlzaWJsZSBieSBudW1faGVhZHMnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBxSGlkZGVuU2l6ZSA9IGF0dHJpYnV0ZXMucWt2SGlkZGVuU2l6ZXNbMF07XG4gICAga0hpZGRlblNpemUgPSBhdHRyaWJ1dGVzLnFrdkhpZGRlblNpemVzWzFdO1xuICAgIHZIaWRkZW5TaXplID0gYXR0cmlidXRlcy5xa3ZIaWRkZW5TaXplc1syXTtcbiAgfVxuXG4gIGNvbnN0IGt2U2VxdWVuY2VMZW5ndGggPSBzZXF1ZW5jZUxlbmd0aDtcblxuICBpZiAocUhpZGRlblNpemUgIT09IGtIaWRkZW5TaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdxa3ZfaGlkZGVuX3NpemVzIGZpcnN0IGVsZW1lbnQgc2hvdWxkIGJlIHNhbWUgYXMgdGhlIHNlY29uZCcpO1xuICB9XG5cbiAgaWYgKGJpYXMuZGltc1swXSAhPT0gcUhpZGRlblNpemUgKyBrSGlkZGVuU2l6ZSArIHZIaWRkZW5TaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImJpYXNcIiBkaW1lbnNpb24gMCBzaG91bGQgaGF2ZSBzYW1lIGxlbmd0aCBhcyBzdW0gb2YgUS9LL1YgaGlkZGVuIHNpemVzJyk7XG4gIH1cblxuICBsZXQgcGFzdFNlcXVlbmNlTGVuZ3RoID0gMDtcbiAgaWYgKHBhc3QpIHtcbiAgICBpZiAoa0hpZGRlblNpemUgIT09IHZIaWRkZW5TaXplKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdFwiIGV4cGVjdCBrX2hpZGRlbl9zaXplID09IHZfaGlkZGVuX3NpemUnKTtcbiAgICB9XG4gICAgaWYgKHBhc3QuZGltcy5sZW5ndGggIT09IDUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0XCIgbXVzdCBoYXZlIDUgZGltZW5zaW9ucycpO1xuICAgIH1cbiAgICBpZiAocGFzdC5kaW1zWzBdICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdFwiIGZpcnN0IGRpbWVuc2lvbiBtdXN0IGJlIDInKTtcbiAgICB9XG4gICAgaWYgKHBhc3QuZGltc1sxXSAhPT0gYmF0Y2hTaXplKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdFwiIHNlY29uZCBkaW1lbnNpb24gbXVzdCBiZSBiYXRjaF9zaXplJyk7XG4gICAgfVxuICAgIGlmIChwYXN0LmRpbXNbMl0gIT09IGF0dHJpYnV0ZXMubnVtSGVhZHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0XCIgdGhpcmQgZGltZW5zaW9uIG11c3QgYmUgbnVtX2hlYWRzJyk7XG4gICAgfVxuICAgIGlmIChwYXN0LmRpbXNbNF0gIT09IGtIaWRkZW5TaXplIC8gYXR0cmlidXRlcy5udW1IZWFkcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3RcIiBmaWZ0aCBkaW1lbnNpb24gbXVzdCBiZSBrX2hpZGRlbl9zaXplIC8gbnVtX2hlYWRzJyk7XG4gICAgfVxuXG4gICAgaWYgKCFhdHRyaWJ1dGVzLnBhc3RQcmVzZW50U2hhcmVCdWZmZXIpIHtcbiAgICAgIHBhc3RTZXF1ZW5jZUxlbmd0aCA9IHBhc3QuZGltc1szXTtcbiAgICB9XG4gICAgLy8gVE9ETzogaGFuZGxlIHBhc3Rfc2VxX2xlblxuICB9XG5cbiAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aCA9IGt2U2VxdWVuY2VMZW5ndGggKyBwYXN0U2VxdWVuY2VMZW5ndGg7XG4gIGNvbnN0IG1heFNlcXVlbmNlTGVuZ3RoID0gLTE7XG5cbiAgY29uc3QgbWFza1R5cGUgPSBBdHRlbnRpb25NYXNrVHlwZS5ub25lO1xuICBpZiAobWFza0luZGV4KSB7XG4gICAgLy8gbWFza1R5cGUgPSBBdHRlbnRpb25NYXNrVHlwZS5NQVNLX1VOS05PV047XG4gICAgLy8gVE9ETzogaGFuZGxlIG1hc2tcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01hc2sgbm90IHN1cHBvcnRlZCcpO1xuICB9XG5cbiAgaWYgKHBhc3QpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Bhc3QgaXMgbm90IHN1cHBvcnRlZCcpO1xuICB9XG5cbiAgaWYgKGF0dGVudGlvbkJpYXMpIHtcbiAgICBpZiAoYXR0ZW50aW9uQmlhcy5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImF0dGVudGlvbl9iaWFzXCIgbXVzdCBoYXZlIDQgZGltZW5zaW9ucycpO1xuICAgIH1cblxuICAgIC8vIFRPRE86IHN1cHBvcnQgYnJvYWRjYXN0aW5nIHRoZSBmaXJzdCBhbmQgc2Vjb25kIGRpbWVuc2lvbnMgb2YgYXR0ZW50aW9uX2JpYXNcbiAgICBpZiAoXG4gICAgICBhdHRlbnRpb25CaWFzLmRpbXNbMF0gIT09IGJhdGNoU2l6ZSB8fFxuICAgICAgYXR0ZW50aW9uQmlhcy5kaW1zWzFdICE9PSBhdHRyaWJ1dGVzLm51bUhlYWRzIHx8XG4gICAgICBhdHRlbnRpb25CaWFzLmRpbXNbMl0gIT09IHNlcXVlbmNlTGVuZ3RoIHx8XG4gICAgICBhdHRlbnRpb25CaWFzLmRpbXNbM10gIT09IHRvdGFsU2VxdWVuY2VMZW5ndGhcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0IFwiYXR0ZW50aW9uX2JpYXNcIiBzaGFwZSAoYmF0Y2hfc2l6ZSwgbnVtX2hlYWRzLCBzZXF1ZW5jZV9sZW5ndGgsIHRvdGFsX3NlcXVlbmNlX2xlbmd0aCknKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGJhdGNoU2l6ZSxcbiAgICBzZXF1ZW5jZUxlbmd0aCxcbiAgICBwYXN0U2VxdWVuY2VMZW5ndGgsXG4gICAga3ZTZXF1ZW5jZUxlbmd0aCxcbiAgICB0b3RhbFNlcXVlbmNlTGVuZ3RoLFxuICAgIG1heFNlcXVlbmNlTGVuZ3RoLFxuICAgIGlucHV0SGlkZGVuU2l6ZSxcbiAgICBoaWRkZW5TaXplOiBxSGlkZGVuU2l6ZSxcbiAgICB2SGlkZGVuU2l6ZSxcbiAgICBoZWFkU2l6ZTogTWF0aC5mbG9vcihxSGlkZGVuU2l6ZSAvIGF0dHJpYnV0ZXMubnVtSGVhZHMpLFxuICAgIHZIZWFkU2l6ZTogTWF0aC5mbG9vcih2SGlkZGVuU2l6ZSAvIGF0dHJpYnV0ZXMubnVtSGVhZHMpLFxuICAgIG51bUhlYWRzOiBhdHRyaWJ1dGVzLm51bUhlYWRzLFxuICAgIGlzVW5pZGlyZWN0aW9uYWw6IGZhbHNlLFxuICAgIHBhc3RQcmVzZW50U2hhcmVCdWZmZXI6IGZhbHNlLFxuICAgIG1hc2tGaWx0ZXJWYWx1ZTogYXR0cmlidXRlcy5tYXNrRmlsdGVyVmFsdWUsXG4gICAgbWFza1R5cGUsXG4gICAgc2NhbGU6IGF0dHJpYnV0ZXMuc2NhbGUsXG4gICAgYnJvYWRjYXN0UmVzUG9zQmlhczogZmFsc2UsXG4gICAgcGFzc1Bhc3RJbkt2OiBmYWxzZSxcbiAgICBxa3ZGb3JtYXQ6IEF0dGVudGlvblFrdkZvcm1hdC5xa3ZCTlNILFxuICB9O1xufTtcblxuY29uc3QgaW5pdFZhclN0dWIgPSAoXG4gIHNlcUxlbnNJbnB1dDogSW5kaWNlc0hlbHBlciB8IHVuZGVmaW5lZCxcbiAgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0OiBJbmRpY2VzSGVscGVyIHwgdW5kZWZpbmVkLFxuICBpbml0UGFzdFNlcXVlbmNlTGVuZ3RoOiBib29sZWFuLFxuKSA9PiB7XG4gIC8vIEluIHRoZSBjYXNlIG9mIEdRQSwgcmVkZWZpbmUgdG90YWxfc2VxdWVuY2VfbGVuZ3RoLCBwcmVzZW50X3NlcXVlbmNlX2xlbmd0aCBhbmQgcGFzdF9zZXF1ZW5jZV9sZW5ndGggYmFzZWQgb24gc2VxbGVuX2sgaW5wdXRcbiAgaWYgKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCAmJiBzZXFMZW5zSW5wdXQpIHtcbiAgICByZXR1cm4gYFxuICAgICAgbGV0IHRvdGFsX3NlcXVlbmNlX2xlbmd0aF9pbnB1dCA9IHUzMigke3RvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dC5nZXRCeU9mZnNldCgnMCcpfSk7XG4gICAgICBsZXQgcHJlc2VudF9zZXF1ZW5jZV9sZW5ndGggPSBtYXgodG90YWxfc2VxdWVuY2VfbGVuZ3RoX2lucHV0LCB1bmlmb3Jtcy5wYXN0X3NlcXVlbmNlX2xlbmd0aCk7XG4gICAgICBsZXQgaXNfc3Vic2VxdWVudF9wcm9tcHQ6IGJvb2wgPSBzZXF1ZW5jZV9sZW5ndGggPiAxICYmIHNlcXVlbmNlX2xlbmd0aCAhPSB0b3RhbF9zZXF1ZW5jZV9sZW5ndGhfaW5wdXQ7XG4gICAgICBsZXQgaXNfZmlyc3RfcHJvbXB0OiBib29sID0gaXNfc3Vic2VxdWVudF9wcm9tcHQgPT0gZmFsc2UgJiYgc2VxdWVuY2VfbGVuZ3RoID09IHRvdGFsX3NlcXVlbmNlX2xlbmd0aF9pbnB1dDtcbiAgICAgIHRvdGFsX3NlcXVlbmNlX2xlbmd0aCA9IHUzMigke3NlcUxlbnNJbnB1dD8uZ2V0QnlPZmZzZXQoJ2JhdGNoSWR4Jyl9KSArIDE7XG4gICAgICB2YXIgcGFzdF9zZXF1ZW5jZV9sZW5ndGg6IHUzMiA9IDA7XG4gICAgICBpZiAoaXNfZmlyc3RfcHJvbXB0ID09IGZhbHNlKSB7XG4gICAgICAgIHBhc3Rfc2VxdWVuY2VfbGVuZ3RoID0gdG90YWxfc2VxdWVuY2VfbGVuZ3RoIC0gc2VxdWVuY2VfbGVuZ3RoO1xuICAgICAgfVxuICAgICAgIGA7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGBcbiAgICAke2luaXRQYXN0U2VxdWVuY2VMZW5ndGggPyAnbGV0IHBhc3Rfc2VxdWVuY2VfbGVuZ3RoID0gdW5pZm9ybXMucGFzdF9zZXF1ZW5jZV9sZW5ndGgnIDogJyd9O1xuICAgIGxldCBwcmVzZW50X3NlcXVlbmNlX2xlbmd0aCA9IHRvdGFsX3NlcXVlbmNlX2xlbmd0aDtcbiAgICBgO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVJblBsYWNlU29mdG1heFByb2dyYW1JbmZvID0gKFxuICBpbnB1dDogVGVuc29yVmlldyxcbiAgYmF0Y2hTaXplOiBudW1iZXIsXG4gIG51bUhlYWRzOiBudW1iZXIsXG4gIHBhc3RTZXF1ZW5jZUxlbmd0aDogbnVtYmVyLFxuICBzZXF1ZW5jZUxlbmd0aDogbnVtYmVyLFxuICB0b3RhbFNlcXVlbmNlTGVuZ3RoOiBudW1iZXIsXG4gIHNlcUxlbnM6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4gIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dDogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbikgPT4ge1xuICAvLyBTZXQgY29tcG9uZW50cyB0byAxIGlmIHNlcUxlbnMgaXMgc3BlY2lmaWVkLCBpLmUuIEdyb3VwUXVlcnlBdHRlbnRpb24uXG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKHNlcUxlbnMgPyAxIDogdG90YWxTZXF1ZW5jZUxlbmd0aCk7XG4gIGxldCBXRyA9IDY0O1xuICBjb25zdCB0b3RhbFNlcXVlbmNlTGVuZ3RoQ29tcCA9IHRvdGFsU2VxdWVuY2VMZW5ndGggLyBjb21wb25lbnRzO1xuICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aENvbXAgPCBXRykge1xuICAgIFdHID0gMzI7XG4gIH1cbiAgY29uc3QgZWxlbWVudHNQZXJUaHJlYWQgPSBNYXRoLmNlaWwodG90YWxTZXF1ZW5jZUxlbmd0aCAvIGNvbXBvbmVudHMgLyBXRyk7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYmF0Y2hTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG51bUhlYWRzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhc3RTZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiB0b3RhbFNlcXVlbmNlTGVuZ3RoQ29tcCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBlbGVtZW50c1BlclRocmVhZCB9LFxuICBdO1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dC5kYXRhVHlwZSwgY29tcG9uZW50cyk7XG4gIGNvbnN0IGYzMlR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKERhdGFUeXBlLmZsb2F0LCBjb21wb25lbnRzKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnXTtcbiAgaWYgKHNlcUxlbnMpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgaWYgKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCkge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBpbnB1dEhlbHBlciA9IG91dHB1dFZhcmlhYmxlKCd4JywgaW5wdXQuZGF0YVR5cGUsIGlucHV0LmRpbXMsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGlucHV0SGVscGVycyA9IFtpbnB1dEhlbHBlcl07XG4gICAgY29uc3Qgc2VxTGVuc0lucHV0SGVscGVyID0gc2VxTGVucyA/IGlucHV0VmFyaWFibGUoJ3NlcV9sZW5zJywgc2VxTGVucy5kYXRhVHlwZSwgc2VxTGVucy5kaW1zKSA6IHVuZGVmaW5lZDtcbiAgICBpZiAoc2VxTGVuc0lucHV0SGVscGVyKSB7XG4gICAgICBpbnB1dEhlbHBlcnMucHVzaChzZXFMZW5zSW5wdXRIZWxwZXIpO1xuICAgIH1cblxuICAgIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dEhlbHBlciA9IHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFxuICAgICAgPyBpbnB1dFZhcmlhYmxlKCd0b3RhbF9zZXF1ZW5jZV9sZW5ndGhfaW5wdXQnLCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQuZGF0YVR5cGUsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dC5kaW1zKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgaWYgKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dEhlbHBlcikge1xuICAgICAgaW5wdXRIZWxwZXJzLnB1c2godG90YWxTZXF1ZW5jZUxlbmd0aElucHV0SGVscGVyKTtcbiAgICB9XG4gICAgY29uc3QgZWxlbVZhbHVlVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoaW5wdXQuZGF0YVR5cGUpO1xuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ2JhdGNoX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnbnVtX2hlYWRzJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3Bhc3Rfc2VxdWVuY2VfbGVuZ3RoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3NlcXVlbmNlX2xlbmd0aCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICd0b3RhbF9zZXF1ZW5jZV9sZW5ndGgnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnZWxlbWVudHNfcGVyX3RocmVhZCcsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcblxuICAgIHJldHVybiBgXG4gIHZhcjx3b3JrZ3JvdXA+IHRocmVhZF9tYXg6IGFycmF5PGYzMiwgJHtXR30+O1xuICB2YXI8d29ya2dyb3VwPiB0aHJlYWRfc3VtOiBhcnJheTxmMzIsICR7V0d9PjtcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dEhlbHBlcnMpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoW1dHLCAxLCAxXSl9XG4gICAgbGV0IGJhdGNoSWR4ID0gd29ya2dyb3VwX2lkLnogLyB1bmlmb3Jtcy5udW1faGVhZHM7XG4gICAgbGV0IGhlYWRJZHggPSB3b3JrZ3JvdXBfaWQueiAlIHVuaWZvcm1zLm51bV9oZWFkcztcbiAgICBsZXQgc2VxdWVuY2VfbGVuZ3RoID0gdW5pZm9ybXMuc2VxdWVuY2VfbGVuZ3RoO1xuICAgIHZhciB0b3RhbF9zZXF1ZW5jZV9sZW5ndGggPSB1bmlmb3Jtcy50b3RhbF9zZXF1ZW5jZV9sZW5ndGg7XG4gICAgJHtpbml0VmFyU3R1YihzZXFMZW5zSW5wdXRIZWxwZXIsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dEhlbHBlciwgZmFsc2UpfVxuICAgIGxldCBsb2NhbF9vZmZzZXQgPSBsb2NhbF9pZHggKiB1bmlmb3Jtcy5lbGVtZW50c19wZXJfdGhyZWFkO1xuICAgIGxldCBvZmZzZXQgPSAoZ2xvYmFsX2lkeCAvICR7V0d9KSAqIHVuaWZvcm1zLnRvdGFsX3NlcXVlbmNlX2xlbmd0aCArIGxvY2FsX29mZnNldDtcbiAgICBsZXQgc2VxX2NhdXNhbF9sZW5ndGggPSAke3NlcUxlbnMgPyAndTMyKHBhc3Rfc2VxdWVuY2VfbGVuZ3RoICsgd29ya2dyb3VwX2lkLnkgKyAxKScgOiAndG90YWxfc2VxdWVuY2VfbGVuZ3RoJ307XG4gICAgdmFyIHRocmVhZF9tYXhfdmVjdG9yID0gJHtmMzJUeXBlfSgtMy40MDI4MjM0NjYzODUyODg2ZSszOGYpO1xuICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCB1bmlmb3Jtcy5lbGVtZW50c19wZXJfdGhyZWFkICYmIGkgKyBsb2NhbF9vZmZzZXQgPCBzZXFfY2F1c2FsX2xlbmd0aDsgaSsrKSB7XG4gICAgICB0aHJlYWRfbWF4X3ZlY3RvciA9IG1heCgke2YzMlR5cGV9KHhbb2Zmc2V0ICsgaV0pLCB0aHJlYWRfbWF4X3ZlY3Rvcik7XG4gICAgfVxuICAgIHRocmVhZF9tYXhbbG9jYWxfaWR4XSA9ICR7KCgpID0+IHtcbiAgICAgIHN3aXRjaCAoY29tcG9uZW50cykge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgcmV0dXJuICd0aHJlYWRfbWF4X3ZlY3Rvcic7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICByZXR1cm4gJ21heCh0aHJlYWRfbWF4X3ZlY3Rvci54LCB0aHJlYWRfbWF4X3ZlY3Rvci55KSc7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICByZXR1cm4gJ21heChtYXgodGhyZWFkX21heF92ZWN0b3IueCwgdGhyZWFkX21heF92ZWN0b3IueSksIG1heCh0aHJlYWRfbWF4X3ZlY3Rvci56LCB0aHJlYWRfbWF4X3ZlY3Rvci53KSknO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgY29tcG9uZW50czogJHtjb21wb25lbnRzfWApO1xuICAgICAgfVxuICAgIH0pKCl9O1xuICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgIHZhciBtYXhfdmFsdWUgPSAgZjMyKC0zLjQwMjgyMzQ2NjM4NTI4ODZlKzM4Zik7XG4gICAgZm9yICh2YXIgaSA9IDB1OyBpIDwgJHtXR307IGkrKykge1xuICAgICAgbWF4X3ZhbHVlID0gbWF4KHRocmVhZF9tYXhbaV0sIG1heF92YWx1ZSk7XG4gICAgfVxuXG4gICAgdmFyIHN1bV92ZWN0b3IgPSAke2YzMlR5cGV9KDApO1xuICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCB1bmlmb3Jtcy5lbGVtZW50c19wZXJfdGhyZWFkICYmIGkgKyBsb2NhbF9vZmZzZXQgPCBzZXFfY2F1c2FsX2xlbmd0aDsgaSsrKSB7XG4gICAgICBzdW1fdmVjdG9yICs9IGV4cCgke2YzMlR5cGV9KHhbb2Zmc2V0ICsgaV0pIC0gbWF4X3ZhbHVlKTtcbiAgICB9XG4gICAgdGhyZWFkX3N1bVtsb2NhbF9pZHhdID0gJHsoKCkgPT4ge1xuICAgICAgc3dpdGNoIChjb21wb25lbnRzKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICByZXR1cm4gJ3N1bV92ZWN0b3InO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgcmV0dXJuICdzdW1fdmVjdG9yLnggKyBzdW1fdmVjdG9yLnknO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgcmV0dXJuICdzdW1fdmVjdG9yLnggKyBzdW1fdmVjdG9yLnkgKyBzdW1fdmVjdG9yLnogKyBzdW1fdmVjdG9yLncnO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgY29tcG9uZW50czogJHtjb21wb25lbnRzfWApO1xuICAgICAgfVxuICAgIH0pKCl9O1xuICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgIHZhciBzdW06IGYzMiA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDB1OyBpIDwgJHtXR307IGkrKykge1xuICAgICAgc3VtICs9IHRocmVhZF9zdW1baV07XG4gICAgfVxuXG4gICAgaWYgKHN1bSA9PSAwKSB7XG4gICAgICBmb3IgKHZhciBpOiB1MzIgPSAwOyBpIDwgdW5pZm9ybXMuZWxlbWVudHNfcGVyX3RocmVhZCAmJiBpICsgbG9jYWxfb2Zmc2V0IDwgc2VxX2NhdXNhbF9sZW5ndGg7IGkrKykge1xuICAgICAgICB4W29mZnNldCArIGldID0gJHtpbnB1dEhlbHBlci50eXBlLnZhbHVlfSgke2VsZW1WYWx1ZVR5cGV9KDEuMCkgLyAke2VsZW1WYWx1ZVR5cGV9KHNlcV9jYXVzYWxfbGVuZ3RoKSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCB1bmlmb3Jtcy5lbGVtZW50c19wZXJfdGhyZWFkICYmIGkgKyBsb2NhbF9vZmZzZXQgPCBzZXFfY2F1c2FsX2xlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmMzJpbnB1dCA9ICR7ZjMyVHlwZX0oeFtvZmZzZXQgKyBpXSk7XG4gICAgICAgIHhbb2Zmc2V0ICsgaV0gPSAke2lucHV0SGVscGVyLnR5cGUudmFsdWV9KGV4cChmMzJpbnB1dCAtIG1heF92YWx1ZSkgLyBzdW0pO1xuICAgICAgfVxuICAgIH1cbiAgICAgICR7XG4gICAgICAgIHNlcUxlbnNcbiAgICAgICAgICA/IGBcbiAgICAgICAgZm9yICh2YXIgdG90YWxfc2VxX2lkOiB1MzIgPSBzZXFfY2F1c2FsX2xlbmd0aDsgdG90YWxfc2VxX2lkICsgbG9jYWxfb2Zmc2V0IDwgdW5pZm9ybXMudG90YWxfc2VxdWVuY2VfbGVuZ3RoOyB0b3RhbF9zZXFfaWQrKykge1xuICAgICAgICAgIHhbb2Zmc2V0ICsgdG90YWxfc2VxX2lkXSA9ICR7aW5wdXRIZWxwZXIudHlwZS52YWx1ZX0oJHtlbGVtVmFsdWVUeXBlfSgwKSk7XG4gICAgICAgIH1gXG4gICAgICAgICAgOiAnJ1xuICAgICAgfTtcbiAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQXR0ZW50aW9uUHJvYnNTb2Z0bWF4JyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtXR307JHtkYXRhVHlwZX07JHtjb21wb25lbnRzfWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbXSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogMSwgeTogc2VxdWVuY2VMZW5ndGgsIHo6IGJhdGNoU2l6ZSAqIG51bUhlYWRzIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gIH07XG59O1xuXG5jb25zdCBjcmVhdGVBdHRlbnRpb25Qcm9ic1Byb2dyYW1JbmZvID0gKFxuICBvdXRwdXRDb3VudDogbnVtYmVyLFxuICBxOiBUZW5zb3JWaWV3LFxuICBrZXk6IFRlbnNvclZpZXcsXG4gIHBhc3RLZXk6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4gIGF0dGVudGlvbkJpYXM6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4gIHBhcmFtZXRlcnM6IEF0dGVudGlvblBhcmFtZXRlcnMsXG4gIHBhc3RTZXF1ZW5jZUxlbmd0aDogbnVtYmVyLFxuICBzZXFMZW5zOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQ6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4pID0+IHtcbiAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aCA9IHBhc3RTZXF1ZW5jZUxlbmd0aCArIHBhcmFtZXRlcnMua3ZTZXF1ZW5jZUxlbmd0aDtcbiAgY29uc3QgcHJvYnNTaGFwZSA9IFtwYXJhbWV0ZXJzLmJhdGNoU2l6ZSwgcGFyYW1ldGVycy5udW1IZWFkcywgcGFyYW1ldGVycy5zZXF1ZW5jZUxlbmd0aCwgdG90YWxTZXF1ZW5jZUxlbmd0aF07XG4gIGNvbnN0IHByZXNlbnRLZXkgPSBvdXRwdXRDb3VudCA+IDEgJiYgcGFzdEtleTtcbiAgY29uc3Qga3ZOdW1IZWFkcyA9IHBhcmFtZXRlcnMua3ZOdW1IZWFkcyA/IHBhcmFtZXRlcnMua3ZOdW1IZWFkcyA6IHBhcmFtZXRlcnMubnVtSGVhZHM7XG4gIGNvbnN0IHByZXNlbnRLZXlTaGFwZSA9IHByZXNlbnRLZXlcbiAgICA/IFtwYXJhbWV0ZXJzLmJhdGNoU2l6ZSwga3ZOdW1IZWFkcywgdG90YWxTZXF1ZW5jZUxlbmd0aCwgcGFyYW1ldGVycy5oZWFkU2l6ZV1cbiAgICA6IHVuZGVmaW5lZDtcbiAgY29uc3QgblJlcHMgPSBwYXJhbWV0ZXJzLm5SZXBzID8gcGFyYW1ldGVycy5uUmVwcyA6IDE7XG4gIC8vIFRPRE86IGhhbmRsZSBtYXNrXG5cbiAgY29uc3QgYWxwaGEgPSBwYXJhbWV0ZXJzLnNjYWxlID09PSAwID8gMS4wIC8gTWF0aC5zcXJ0KHBhcmFtZXRlcnMuaGVhZFNpemUpIDogcGFyYW1ldGVycy5zY2FsZTtcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMocGFyYW1ldGVycy5oZWFkU2l6ZSk7XG4gIGNvbnN0IHZlY3Rvcml6ZWRIZWFkU2l6ZSA9IHBhcmFtZXRlcnMuaGVhZFNpemUgLyBjb21wb25lbnRzO1xuICBjb25zdCBUSUxFX1NJWkUgPSAxMjtcbiAgY29uc3QgZGlzcGF0Y2ggPSB7XG4gICAgeDogTWF0aC5jZWlsKHRvdGFsU2VxdWVuY2VMZW5ndGggLyBUSUxFX1NJWkUpLFxuICAgIHk6IE1hdGguY2VpbChwYXJhbWV0ZXJzLnNlcXVlbmNlTGVuZ3RoIC8gVElMRV9TSVpFKSxcbiAgICB6OiBwYXJhbWV0ZXJzLmJhdGNoU2l6ZSAqIHBhcmFtZXRlcnMubnVtSGVhZHMsXG4gIH07XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1ldGVycy5zZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiB2ZWN0b3JpemVkSGVhZFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogdG90YWxTZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbWV0ZXJzLm51bUhlYWRzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtZXRlcnMuaGVhZFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhbHBoYSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXN0U2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1ldGVycy5rdlNlcXVlbmNlTGVuZ3RoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG5SZXBzIH0sXG4gIF07XG4gIC8vIEZlZWQgcGFzdEtleSB0byB0aGUgc2hhZGVyLWNvZGUgb25seSBpZiBpdCBpcyBub24temVybyBhbmQgcHJlc2VudEtleSBpcyBiZWluZyBwcm9kdWNlZFxuICBjb25zdCBmZWVkUGFzdEtleSA9IHByZXNlbnRLZXkgJiYgcGFzdEtleSAmJiBTaGFwZVV0aWwuc2l6ZShwYXN0S2V5LmRpbXMpID4gMDtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnLCAndHlwZSddO1xuICBpZiAoZmVlZFBhc3RLZXkpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgaWYgKGF0dGVudGlvbkJpYXMpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgaWYgKHNlcUxlbnMpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgaWYgKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCkge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBjb25zdCBvdXRwdXRzID0gW3sgZGltczogcHJvYnNTaGFwZSwgZGF0YVR5cGU6IHEuZGF0YVR5cGUsIGdwdURhdGFUeXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0IH1dO1xuICBpZiAocHJlc2VudEtleSkge1xuICAgIG91dHB1dHMucHVzaCh7IGRpbXM6IHByZXNlbnRLZXlTaGFwZSEsIGRhdGFUeXBlOiBxLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9KTtcbiAgfVxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBxSW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdxJywgcS5kYXRhVHlwZSwgcS5kaW1zLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBrSW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdrZXknLCBrZXkuZGF0YVR5cGUsIGtleS5kaW1zLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBpbnB1dFZhcnMgPSBbcUlucHV0LCBrSW5wdXRdO1xuICAgIGlmIChmZWVkUGFzdEtleSkge1xuICAgICAgY29uc3QgcGFzdEtleUlucHV0ID0gaW5wdXRWYXJpYWJsZSgncGFzdF9rZXknLCBwYXN0S2V5LmRhdGFUeXBlLCBwYXN0S2V5LmRpbXMsIGNvbXBvbmVudHMpO1xuICAgICAgaW5wdXRWYXJzLnB1c2gocGFzdEtleUlucHV0KTtcbiAgICB9XG4gICAgaWYgKGF0dGVudGlvbkJpYXMpIHtcbiAgICAgIGlucHV0VmFycy5wdXNoKGlucHV0VmFyaWFibGUoJ2F0dGVudGlvbl9iaWFzJywgYXR0ZW50aW9uQmlhcy5kYXRhVHlwZSwgYXR0ZW50aW9uQmlhcy5kaW1zKSk7XG4gICAgfVxuICAgIGNvbnN0IHNlcUxlbnNJbnB1dFZhcmlhYmxlID0gc2VxTGVucyA/IGlucHV0VmFyaWFibGUoJ3NlcV9sZW5zJywgc2VxTGVucy5kYXRhVHlwZSwgc2VxTGVucy5kaW1zKSA6IHVuZGVmaW5lZDtcbiAgICBpZiAoc2VxTGVuc0lucHV0VmFyaWFibGUpIHtcbiAgICAgIGlucHV0VmFycy5wdXNoKHNlcUxlbnNJbnB1dFZhcmlhYmxlKTtcbiAgICB9XG4gICAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0VmFyaWFibGUgPSB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRcbiAgICAgID8gaW5wdXRWYXJpYWJsZSgndG90YWxfc2VxdWVuY2VfbGVuZ3RoX2lucHV0JywgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LmRhdGFUeXBlLCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQuZGltcylcbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIGlmICh0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRWYXJpYWJsZSkge1xuICAgICAgaW5wdXRWYXJzLnB1c2godG90YWxTZXF1ZW5jZUxlbmd0aElucHV0VmFyaWFibGUpO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgcS5kYXRhVHlwZSwgcHJvYnNTaGFwZSk7XG4gICAgY29uc3Qgb3V0cHV0VmFycyA9IFtvdXRwdXRdO1xuICAgIGlmIChwcmVzZW50S2V5KSB7XG4gICAgICBvdXRwdXRWYXJzLnB1c2gob3V0cHV0VmFyaWFibGUoJ3ByZXNlbnRfa2V5JywgcS5kYXRhVHlwZSwgcHJlc2VudEtleVNoYXBlISwgY29tcG9uZW50cykpO1xuICAgIH1cbiAgICBjb25zdCBmMzJUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShEYXRhVHlwZS5mbG9hdCwgY29tcG9uZW50cyk7XG5cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdNJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ0snLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnTicsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdudW1faGVhZHMnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnaGVhZF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2FscGhhJywgdHlwZTogJ2YzMicgYXMgVW5pZm9ybURhdGFFbGVtZW50VHlwZSB9LFxuICAgICAgeyBuYW1lOiAncGFzdF9zZXF1ZW5jZV9sZW5ndGgnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAna3Zfc2VxdWVuY2VfbGVuZ3RoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ25fcmVwcycsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICBjb25zdCBUSUxFX1NJWkUgPSAke1RJTEVfU0laRX11O1xuXG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGVROiBhcnJheTwke3FJbnB1dC50eXBlLnN0b3JhZ2V9LCAke1RJTEVfU0laRSAqIFRJTEVfU0laRX0+O1xuICB2YXI8d29ya2dyb3VwPiB0aWxlSzogYXJyYXk8JHtxSW5wdXQudHlwZS5zdG9yYWdlfSwgJHtUSUxFX1NJWkUgKiBUSUxFX1NJWkV9PjtcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcnMsIC4uLm91dHB1dFZhcnMpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoW1RJTEVfU0laRSwgVElMRV9TSVpFLCAxXSl9XG4gICAgLy8geCBob2xkcyB0aGUgTiBhbmQgeSBob2xkcyB0aGUgTVxuICAgIGxldCBoZWFkSWR4ID0gd29ya2dyb3VwX2lkLnogJSB1bmlmb3Jtcy5udW1faGVhZHM7XG4gICAgbGV0IGt2SGVhZElkeCA9ICR7blJlcHMgPT09IDEgPyAnaGVhZElkeCcgOiAnaGVhZElkeCAvIHVuaWZvcm1zLm5fcmVwcyd9O1xuICAgIGxldCBrdl9udW1faGVhZHMgPSAke25SZXBzID09PSAxID8gJ3VuaWZvcm1zLm51bV9oZWFkcycgOiAndW5pZm9ybXMubnVtX2hlYWRzIC8gdW5pZm9ybXMubl9yZXBzJ307XG4gICAgbGV0IGJhdGNoSWR4ID0gd29ya2dyb3VwX2lkLnogLyB1bmlmb3Jtcy5udW1faGVhZHM7XG4gICAgbGV0IG0gPSB3b3JrZ3JvdXBfaWQueSAqIFRJTEVfU0laRTtcbiAgICBsZXQgbiA9IHdvcmtncm91cF9pZC54ICogVElMRV9TSVpFO1xuICAgIGxldCBzZXF1ZW5jZV9sZW5ndGggPSB1bmlmb3Jtcy5NO1xuICAgIHZhciB0b3RhbF9zZXF1ZW5jZV9sZW5ndGggPSB1bmlmb3Jtcy5OO1xuICAgICR7aW5pdFZhclN0dWIoc2VxTGVuc0lucHV0VmFyaWFibGUsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFZhcmlhYmxlLCB0cnVlKX1cbiAgICBsZXQgYWJzS3ZIZWFkSWR4ID0gYmF0Y2hJZHggKiBrdl9udW1faGVhZHMgKyBrdkhlYWRJZHg7XG4gICAgbGV0IHFPZmZzZXQgPSB3b3JrZ3JvdXBfaWQueiAqIHVuaWZvcm1zLk0gKiB1bmlmb3Jtcy5LICsgbSAqIHVuaWZvcm1zLks7XG4gICAgJHtmZWVkUGFzdEtleSAmJiBwcmVzZW50S2V5ID8gJ2xldCBwYXN0S2V5T2Zmc2V0ID0gYWJzS3ZIZWFkSWR4ICogdW5pZm9ybXMucGFzdF9zZXF1ZW5jZV9sZW5ndGggKiB1bmlmb3Jtcy5LOycgOiAnJ307XG4gICAgbGV0IGtPZmZzZXQgPSBhYnNLdkhlYWRJZHggKiB1bmlmb3Jtcy5rdl9zZXF1ZW5jZV9sZW5ndGggKiB1bmlmb3Jtcy5LO1xuICAgICR7cHJlc2VudEtleSA/ICdsZXQgcHJlc2VudEtleU9mZnNldCA9IGFic0t2SGVhZElkeCAqIHVuaWZvcm1zLk4gKiB1bmlmb3Jtcy5LOycgOiAnJ31cbiAgICB2YXIgdmFsdWUgPSAke2YzMlR5cGV9KDApO1xuICAgIGZvciAodmFyIHc6IHUzMiA9IDB1OyB3IDwgdW5pZm9ybXMuSzsgdyArPSBUSUxFX1NJWkUpIHtcbiAgICAgIGlmIChnbG9iYWxfaWQueSA8IHVuaWZvcm1zLk0gJiYgdyArIGxvY2FsX2lkLnggPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHRpbGVRW1RJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54XSA9IHFbcU9mZnNldCArIGxvY2FsX2lkLnkgKiB1bmlmb3Jtcy5LICsgdyArIGxvY2FsX2lkLnhdO1xuICAgICAgfVxuICAgICAgaWYgKG4gKyBsb2NhbF9pZC55IDwgdW5pZm9ybXMuTiAmJiB3ICsgbG9jYWxfaWQueCA8IHVuaWZvcm1zLkspIHtcbiAgICAgICAgdmFyIGlkeCA9IFRJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54O1xuICAgICAgJHsoKCkgPT4ge1xuICAgICAgICBpZiAoZmVlZFBhc3RLZXkgJiYgcHJlc2VudEtleSkge1xuICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICAgIGlmIChuICsgbG9jYWxfaWQueSA8IHBhc3Rfc2VxdWVuY2VfbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGlsZUtbaWR4XSA9IHBhc3Rfa2V5W3Bhc3RLZXlPZmZzZXQgKyAobiArIGxvY2FsX2lkLnkpICogdW5pZm9ybXMuSyArIHcgKyBsb2NhbF9pZC54XTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChuICsgbG9jYWxfaWQueSAtIHBhc3Rfc2VxdWVuY2VfbGVuZ3RoIDwgdW5pZm9ybXMua3Zfc2VxdWVuY2VfbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGlsZUtbaWR4XSA9IGtleVtrT2Zmc2V0ICsgKG4gKyBsb2NhbF9pZC55IC0gcGFzdF9zZXF1ZW5jZV9sZW5ndGgpICogdW5pZm9ybXMuSyArIHcgKyBsb2NhbF9pZC54XTtcbiAgICAgICAgICAgICAgfWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBpZiAobiArIGxvY2FsX2lkLnkgPCB1bmlmb3Jtcy5rdl9zZXF1ZW5jZV9sZW5ndGgpIHtcbiAgICAgICAgICAgIHRpbGVLW2lkeF0gPSBrZXlba09mZnNldCArIChuICsgbG9jYWxfaWQueSkgKiB1bmlmb3Jtcy5LICsgdyArIGxvY2FsX2lkLnhdO1xuICAgICAgICAgIH1gO1xuICAgICAgICB9XG4gICAgICB9KSgpfVxuICAgICAgJHtcbiAgICAgICAgcHJlc2VudEtleVxuICAgICAgICAgID8gYGlmIChuICsgbG9jYWxfaWQueSA8IHByZXNlbnRfc2VxdWVuY2VfbGVuZ3RoKSB7XG4gICAgICAgIHByZXNlbnRfa2V5W3ByZXNlbnRLZXlPZmZzZXQgKyAobiArIGxvY2FsX2lkLnkpICogdW5pZm9ybXMuSyArIHcgKyBsb2NhbF9pZC54XSA9IHRpbGVLW2lkeF07XG4gICAgICB9YFxuICAgICAgICAgIDogJydcbiAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgZm9yICh2YXIgazogdTMyID0gMHU7IGsgPCBUSUxFX1NJWkUgJiYgdytrIDwgdW5pZm9ybXMuSzsgaysrKSB7XG4gICAgICAgICAgdmFsdWUgKz0gJHtmMzJUeXBlfSh0aWxlUVtUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsga10gKiB0aWxlS1tUSUxFX1NJWkUgKiBsb2NhbF9pZC54ICsga10pO1xuICAgICAgfVxuXG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgfVxuXG4gICAgaWYgKGdsb2JhbF9pZC55IDwgdW5pZm9ybXMuTSAmJiBnbG9iYWxfaWQueCA8IHRvdGFsX3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgbGV0IGhlYWRPZmZzZXQgPSB3b3JrZ3JvdXBfaWQueiAqIHVuaWZvcm1zLk0gKiB1bmlmb3Jtcy5OO1xuICAgICAgbGV0IG91dHB1dElkeCA9IGhlYWRPZmZzZXQgKyBnbG9iYWxfaWQueSAqIHVuaWZvcm1zLk4gKyBnbG9iYWxfaWQueDtcbiAgICAgIHZhciBzdW06IGYzMiA9ICR7KCgpID0+IHtcbiAgICAgICAgc3dpdGNoIChjb21wb25lbnRzKSB7XG4gICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgcmV0dXJuICd2YWx1ZSc7XG4gICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgcmV0dXJuICd2YWx1ZS54ICsgdmFsdWUueSc7XG4gICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgcmV0dXJuICd2YWx1ZS54ICsgdmFsdWUueSArIHZhbHVlLnogKyB2YWx1ZS53JztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBjb21wb25lbnRzOiAke2NvbXBvbmVudHN9YCk7XG4gICAgICAgIH1cbiAgICAgIH0pKCl9O1xuICAgICAgICBvdXRwdXRbb3V0cHV0SWR4XSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9IChzdW0gKiB1bmlmb3Jtcy5hbHBoYSkgKyAke1xuICAgICAgICAgIGF0dGVudGlvbkJpYXMgPyAnYXR0ZW50aW9uX2JpYXNbb3V0cHV0SWR4XScgOiAnMC4wJ1xuICAgICAgICB9O1xuICAgIH1cbiAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0F0dGVudGlvblByb2JzJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7Y29tcG9uZW50c307JHthdHRlbnRpb25CaWFzICE9PSB1bmRlZmluZWR9OyR7cGFzdEtleSAhPT0gdW5kZWZpbmVkfTske291dHB1dENvdW50fWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llcyxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7IG91dHB1dHMsIGRpc3BhdGNoR3JvdXA6IGRpc3BhdGNoLCBwcm9ncmFtVW5pZm9ybXMgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuY29uc3QgY3JlYXRlVnhBdHRlbnRpb25TY29yZVByb2dyYW1JbmZvID0gKFxuICBvdXRwdXRDb3VudDogbnVtYmVyLFxuICBwcm9iczogVGVuc29yVmlldyxcbiAgdjogVGVuc29yVmlldyxcbiAgcGFzdFZhbHVlOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICBwYXJhbXM6IEF0dGVudGlvblBhcmFtZXRlcnMsXG4gIHBhc3RTZXF1ZW5jZUxlbmd0aDogbnVtYmVyLFxuICBzZXFMZW5zOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQ6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4pID0+IHtcbiAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aCA9IHBhc3RTZXF1ZW5jZUxlbmd0aCArIHBhcmFtcy5rdlNlcXVlbmNlTGVuZ3RoO1xuICBjb25zdCBuUmVwcyA9IHBhcmFtcy5uUmVwcyA/IHBhcmFtcy5uUmVwcyA6IDE7XG4gIGNvbnN0IHJlcGVhdGVkVkhpZGRlblNpemUgPSBwYXJhbXMudkhpZGRlblNpemUgKiBuUmVwcztcbiAgY29uc3QgcHJlc2VudFZhbHVlID0gb3V0cHV0Q291bnQgPiAxICYmIHBhc3RWYWx1ZTtcbiAgY29uc3Qga3ZOdW1IZWFkcyA9IHBhcmFtcy5rdk51bUhlYWRzID8gcGFyYW1zLmt2TnVtSGVhZHMgOiBwYXJhbXMubnVtSGVhZHM7XG4gIGNvbnN0IHByZXNlbnRWYWx1ZVNoYXBlID0gcHJlc2VudFZhbHVlXG4gICAgPyBbcGFyYW1zLmJhdGNoU2l6ZSwga3ZOdW1IZWFkcywgdG90YWxTZXF1ZW5jZUxlbmd0aCwgcGFyYW1zLmhlYWRTaXplXVxuICAgIDogdW5kZWZpbmVkO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IFtwYXJhbXMuYmF0Y2hTaXplLCBwYXJhbXMuc2VxdWVuY2VMZW5ndGgsIHJlcGVhdGVkVkhpZGRlblNpemVdO1xuICBjb25zdCBUSUxFX1NJWkUgPSAxMjtcbiAgY29uc3QgZGlzcGF0Y2ggPSB7XG4gICAgeDogTWF0aC5jZWlsKHBhcmFtcy52SGVhZFNpemUgLyBUSUxFX1NJWkUpLFxuICAgIHk6IE1hdGguY2VpbChwYXJhbXMuc2VxdWVuY2VMZW5ndGggLyBUSUxFX1NJWkUpLFxuICAgIHo6IHBhcmFtcy5iYXRjaFNpemUgKiBwYXJhbXMubnVtSGVhZHMsXG4gIH07XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbXMuc2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogdG90YWxTZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbXMudkhlYWRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtcy5udW1IZWFkcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbXMuaGVhZFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcmVwZWF0ZWRWSGlkZGVuU2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXN0U2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1zLmt2U2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogblJlcHMgfSxcbiAgXTtcbiAgLy8gRmVlZCBwYXN0VmFsdWUgdG8gdGhlIHNoYWRlci1jb2RlIG9ubHkgaWYgaXQgaXMgbm9uLWVtcHR5IGFuZCBwcmVzZW50VmFsdWUgaXMgYmVpbmcgcHJvZHVjZWRcbiAgY29uc3QgZmVlZFBhc3RWYWx1ZSA9IHByZXNlbnRWYWx1ZSAmJiBwYXN0VmFsdWUgJiYgU2hhcGVVdGlsLnNpemUocGFzdFZhbHVlLmRpbXMpID4gMDtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnLCAndHlwZSddO1xuICBpZiAoZmVlZFBhc3RWYWx1ZSkge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBpZiAoc2VxTGVucykge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0KSB7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgndHlwZScpO1xuICB9XG4gIGNvbnN0IG91dHB1dHMgPSBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IHByb2JzLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9XTtcbiAgaWYgKHByZXNlbnRWYWx1ZSkge1xuICAgIG91dHB1dHMucHVzaCh7IGRpbXM6IHByZXNlbnRWYWx1ZVNoYXBlISwgZGF0YVR5cGU6IHByb2JzLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9KTtcbiAgfVxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBwcm9ic0hlbHBlciA9IGlucHV0VmFyaWFibGUoJ3Byb2JzJywgcHJvYnMuZGF0YVR5cGUsIHByb2JzLmRpbXMpO1xuICAgIGNvbnN0IHZIZWxwZXIgPSBpbnB1dFZhcmlhYmxlKCd2Jywgdi5kYXRhVHlwZSwgdi5kaW1zKTtcbiAgICBjb25zdCBpbnB1dFZhcnMgPSBbcHJvYnNIZWxwZXIsIHZIZWxwZXJdO1xuICAgIGlmIChmZWVkUGFzdFZhbHVlKSB7XG4gICAgICBpbnB1dFZhcnMucHVzaChpbnB1dFZhcmlhYmxlKCdwYXN0X3ZhbHVlJywgcGFzdFZhbHVlLmRhdGFUeXBlLCBwYXN0VmFsdWUuZGltcykpO1xuICAgIH1cbiAgICBjb25zdCBzZXFMZW5zSW5wdXRWYXJpYWJsZSA9IHNlcUxlbnMgPyBpbnB1dFZhcmlhYmxlKCdzZXFfbGVucycsIHNlcUxlbnMuZGF0YVR5cGUsIHNlcUxlbnMuZGltcykgOiB1bmRlZmluZWQ7XG4gICAgaWYgKHNlcUxlbnMpIHtcbiAgICAgIGlucHV0VmFycy5wdXNoKHNlcUxlbnNJbnB1dFZhcmlhYmxlISk7XG4gICAgfVxuICAgIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFZhcmlhYmxlID0gdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0XG4gICAgICA/IGlucHV0VmFyaWFibGUoJ3RvdGFsX3NlcXVlbmNlX2xlbmd0aF9pbnB1dCcsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dC5kYXRhVHlwZSwgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LmRpbXMpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0KSB7XG4gICAgICBpbnB1dFZhcnMucHVzaCh0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRWYXJpYWJsZSEpO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgcHJvYnMuZGF0YVR5cGUsIG91dHB1dFNoYXBlKTtcbiAgICBjb25zdCBvdXRwdXRWYXJzID0gW291dHB1dF07XG4gICAgaWYgKHByZXNlbnRWYWx1ZSkge1xuICAgICAgb3V0cHV0VmFycy5wdXNoKG91dHB1dFZhcmlhYmxlKCdwcmVzZW50X3ZhbHVlJywgcHJvYnMuZGF0YVR5cGUsIHByZXNlbnRWYWx1ZVNoYXBlISkpO1xuICAgIH1cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdNJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ0snLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnTicsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdudW1faGVhZHMnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnaGVhZF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3ZfaGlkZGVuX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAncGFzdF9zZXF1ZW5jZV9sZW5ndGgnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAna3Zfc2VxdWVuY2VfbGVuZ3RoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ25fcmVwcycsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICBjb25zdCBUSUxFX1NJWkUgPSAke1RJTEVfU0laRX11O1xuICB2YXI8d29ya2dyb3VwPiB0aWxlUTogYXJyYXk8JHtwcm9ic0hlbHBlci50eXBlLnZhbHVlfSwgJHtUSUxFX1NJWkUgKiBUSUxFX1NJWkV9PjtcbiAgdmFyPHdvcmtncm91cD4gdGlsZVY6IGFycmF5PCR7cHJvYnNIZWxwZXIudHlwZS52YWx1ZX0sICR7VElMRV9TSVpFICogVElMRV9TSVpFfT47XG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJzLCAuLi5vdXRwdXRWYXJzKX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFtUSUxFX1NJWkUsIFRJTEVfU0laRSwgMV0pfVxuICAgbGV0IGhlYWRJZHggPSB3b3JrZ3JvdXBfaWQueiAlIHVuaWZvcm1zLm51bV9oZWFkcztcbiAgIGxldCBiYXRjaElkeCA9IHdvcmtncm91cF9pZC56IC8gdW5pZm9ybXMubnVtX2hlYWRzO1xuICAgbGV0IGt2SGVhZElkeCA9ICR7blJlcHMgPT09IDEgPyAnaGVhZElkeCcgOiAnaGVhZElkeCAvIHVuaWZvcm1zLm5fcmVwcyd9O1xuICAgbGV0IGt2X251bV9oZWFkcyA9ICR7blJlcHMgPT09IDEgPyAndW5pZm9ybXMubnVtX2hlYWRzJyA6ICd1bmlmb3Jtcy5udW1faGVhZHMgLyB1bmlmb3Jtcy5uX3JlcHMnfTtcbiAgIGxldCBtID0gZ2xvYmFsX2lkLnk7XG4gICBsZXQgbiA9IGdsb2JhbF9pZC54O1xuICAgbGV0IHNlcXVlbmNlX2xlbmd0aCA9IHVuaWZvcm1zLk07XG4gICB2YXIgdG90YWxfc2VxdWVuY2VfbGVuZ3RoID0gdW5pZm9ybXMuSztcbiAgICR7aW5pdFZhclN0dWIoc2VxTGVuc0lucHV0VmFyaWFibGUsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFZhcmlhYmxlLCB0cnVlKX1cbiAgIGxldCBvZmZzZXRBID0gd29ya2dyb3VwX2lkLnogKiB1bmlmb3Jtcy5NICogdW5pZm9ybXMuSyArIG0gKiB1bmlmb3Jtcy5LO1xuICAgbGV0IGFic0t2SGVhZElkeCA9IGJhdGNoSWR4ICoga3ZfbnVtX2hlYWRzICsga3ZIZWFkSWR4OyAvLyBrdkhlYWRJZHggaXMgcmVsYXRpdmUgdG8gdGhlIGJhdGNoXG4gICAke2ZlZWRQYXN0VmFsdWUgJiYgcHJlc2VudFZhbHVlID8gJ2xldCBwYXN0VmFsdWVPZmZzZXQgPSBhYnNLdkhlYWRJZHggKiB1bmlmb3Jtcy5OICogdW5pZm9ybXMucGFzdF9zZXF1ZW5jZV9sZW5ndGggKyBuOycgOiAnJ307XG4gICBsZXQgdk9mZnNldCA9IGFic0t2SGVhZElkeCAqIHVuaWZvcm1zLk4gKiB1bmlmb3Jtcy5rdl9zZXF1ZW5jZV9sZW5ndGggKyBuO1xuICAgJHtwcmVzZW50VmFsdWUgPyAnbGV0IHByZXNlbnRWYWx1ZU9mZnNldCA9IGFic0t2SGVhZElkeCAqIHVuaWZvcm1zLk4gKiB1bmlmb3Jtcy5LICsgbjsnIDogJyd9XG4gICB2YXIgdmFsdWUgPSAke3Byb2JzSGVscGVyLnR5cGUuc3RvcmFnZX0oMCk7XG4gICBmb3IgKHZhciB3OiB1MzIgPSAwdTsgdyA8IHVuaWZvcm1zLks7IHcgKz0gVElMRV9TSVpFKSB7XG4gICAgICBpZiAobSA8IHVuaWZvcm1zLk0gJiYgdyArIGxvY2FsX2lkLnggPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHRpbGVRW1RJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54XSA9IHByb2JzW29mZnNldEEgKyB3ICsgbG9jYWxfaWQueF07XG4gICAgICB9XG4gICAgICBpZiAobiA8IHVuaWZvcm1zLk4gJiYgdyArIGxvY2FsX2lkLnkgPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHZhciBpZHggPSBUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgbG9jYWxfaWQueDtcbiAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgIGlmIChmZWVkUGFzdFZhbHVlICYmIHByZXNlbnRWYWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgaWYgKHcgKyBsb2NhbF9pZC55IDwgcGFzdF9zZXF1ZW5jZV9sZW5ndGgpIHtcbiAgICAgICAgICB0aWxlVltpZHhdID0gcGFzdF92YWx1ZVtwYXN0VmFsdWVPZmZzZXQgKyAodyArIGxvY2FsX2lkLnkpICogdW5pZm9ybXMuTl07XG4gICAgICAgIH0gZWxzZSBpZiAodyArIGxvY2FsX2lkLnkgLSBwYXN0X3NlcXVlbmNlX2xlbmd0aCA8IHVuaWZvcm1zLmt2X3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgICAgIHRpbGVWW2lkeF0gPSB2W3ZPZmZzZXQgKyAodyArIGxvY2FsX2lkLnkgLSBwYXN0X3NlcXVlbmNlX2xlbmd0aCkgKiB1bmlmb3Jtcy5OXTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgIGlmICh3ICsgbG9jYWxfaWQueSA8IHVuaWZvcm1zLmt2X3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgICAgICAgICB0aWxlVltpZHhdID0gdlt2T2Zmc2V0ICsgKHcgKyBsb2NhbF9pZC55KSAqIHVuaWZvcm1zLk5dO1xuICAgICAgICAgICAgfWA7XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpfVxuICAgICAgICAke1xuICAgICAgICAgIHByZXNlbnRWYWx1ZVxuICAgICAgICAgICAgPyBgXG4gICAgICAgICAgICBpZiAodyArIGxvY2FsX2lkLnkgPCBwcmVzZW50X3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgICAgIHByZXNlbnRfdmFsdWVbcHJlc2VudFZhbHVlT2Zmc2V0ICsgKHcgKyBsb2NhbF9pZC55KSAqIHVuaWZvcm1zLk5dID0gdGlsZVZbaWR4XTtcbiAgICAgICAgfWBcbiAgICAgICAgICAgIDogJydcbiAgICAgICAgfVxuICAgICAgfVxuICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgIGZvciAodmFyIGs6IHUzMiA9IDB1OyBrIDwgVElMRV9TSVpFICYmIHcrayA8IHRvdGFsX3NlcXVlbmNlX2xlbmd0aDsgaysrKSB7XG4gICAgICAgdmFsdWUgKz0gdGlsZVFbVElMRV9TSVpFICogbG9jYWxfaWQueSArIGtdICogdGlsZVZbVElMRV9TSVpFICogayArIGxvY2FsX2lkLnhdO1xuICAgICB9XG4gICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgIH1cblxuICAgLy8gd2UgbmVlZCB0byB0cmFuc3Bvc2Ugb3V0cHV0IGZyb20gQk5TSF92IHRvIEJTTkRfdlxuICAgaWYgKG0gPCB1bmlmb3Jtcy5NICYmIG4gPCB1bmlmb3Jtcy5OKSB7XG4gICAgIGxldCBvdXRwdXRJZHggPSBiYXRjaElkeCAqIHVuaWZvcm1zLk0gKiB1bmlmb3Jtcy52X2hpZGRlbl9zaXplICsgbSAqIHVuaWZvcm1zLnZfaGlkZGVuX3NpemVcbiAgICAgICArIGhlYWRJZHggKiB1bmlmb3Jtcy5OICsgbjtcbiAgICAgb3V0cHV0W291dHB1dElkeF0gPSB2YWx1ZTtcbiAgIH1cbiAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQXR0ZW50aW9uU2NvcmUnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke3Bhc3RWYWx1ZSAhPT0gdW5kZWZpbmVkfTske291dHB1dENvdW50fWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHsgb3V0cHV0cywgZGlzcGF0Y2hHcm91cDogZGlzcGF0Y2gsIHByb2dyYW1Vbmlmb3JtcyB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgYXBwbHlBdHRlbnRpb24gPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBxOiBUZW5zb3JWaWV3LFxuICBrOiBUZW5zb3JWaWV3LFxuICB2OiBUZW5zb3JWaWV3LFxuICBfbWFza0luZGV4OiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICBfcGFzdDogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbiAgcGFzdEtleTogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbiAgcGFzdFZhbHVlOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICBhdHRlbnRpb25CaWFzSW5wdXQ6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4gIHBhcmFtZXRlcnM6IEF0dGVudGlvblBhcmFtZXRlcnMsXG4gIHNlcUxlbnM6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4gIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dDogVGVuc29yVmlldyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbikgPT4ge1xuICAvLyBBc3N1bXB0aW9uIGlzIHRoYXQgcHJlc2VudEtleS9wcmVzZW50VmFsdWUgZXhpc3RzIG9ubHkgaWYgcGFzdEtleS9wYXN0VmFsdWUgZXhpc3RzLlxuICBjb25zdCBvdXRwdXRDb3VudCA9IE1hdGgubWluKGNvbnRleHQub3V0cHV0Q291bnQsIDEgKyAocGFzdEtleSA/IDEgOiAwKSArIChwYXN0VmFsdWUgPyAxIDogMCkpO1xuICAvLyBXaGVuIHRoZXJlIGFyZSBubyBwcmVzZW50IGtleS92YWx1ZSBvdXRwdXRzIChvdXRwdXRDb3VudCA8PSAxKSwgaWdub3JlIHBhc3QgdG8gbWF0Y2ggQ1BVIEVQIHNlbWFudGljcy5cbiAgY29uc3QgZWZmZWN0aXZlUGFzdEtleSA9IG91dHB1dENvdW50ID4gMSA/IHBhc3RLZXkgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IGVmZmVjdGl2ZVBhc3RWYWx1ZSA9IG91dHB1dENvdW50ID4gMSA/IHBhc3RWYWx1ZSA6IHVuZGVmaW5lZDtcbiAgY29uc3QgcGFzdFNlcXVlbmNlTGVuZ3RoID0gb3V0cHV0Q291bnQgPiAxID8gcGFyYW1ldGVycy5wYXN0U2VxdWVuY2VMZW5ndGggOiAwO1xuICBjb25zdCB0b3RhbFNlcXVlbmNlTGVuZ3RoID0gcGFzdFNlcXVlbmNlTGVuZ3RoICsgcGFyYW1ldGVycy5rdlNlcXVlbmNlTGVuZ3RoO1xuICBjb25zdCBhdHRlbnRpb25CaWFzID1cbiAgICBhdHRlbnRpb25CaWFzSW5wdXQgJiYgU2hhcGVVdGlsLnNpemUoYXR0ZW50aW9uQmlhc0lucHV0LmRpbXMpID4gMCA/IGF0dGVudGlvbkJpYXNJbnB1dCA6IHVuZGVmaW5lZDtcblxuICBjb25zdCBpbnB1dHNLID0gW3EsIGtdO1xuICBpZiAoZWZmZWN0aXZlUGFzdEtleSAmJiBTaGFwZVV0aWwuc2l6ZShlZmZlY3RpdmVQYXN0S2V5LmRpbXMpID4gMCkge1xuICAgIGlucHV0c0sucHVzaChlZmZlY3RpdmVQYXN0S2V5KTtcbiAgfVxuICBpZiAoYXR0ZW50aW9uQmlhcykge1xuICAgIGlucHV0c0sucHVzaChhdHRlbnRpb25CaWFzKTtcbiAgfVxuICBpZiAoc2VxTGVucykge1xuICAgIGlucHV0c0sucHVzaChzZXFMZW5zKTtcbiAgfVxuICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0KSB7XG4gICAgaW5wdXRzSy5wdXNoKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCk7XG4gIH1cbiAgLy8gUnVuIEF0dGVudGlvblByb2JzXG4gIGNvbnN0IHByb2JzID0gY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUF0dGVudGlvblByb2JzUHJvZ3JhbUluZm8oXG4gICAgICBvdXRwdXRDb3VudCxcbiAgICAgIHEsXG4gICAgICBrLFxuICAgICAgZWZmZWN0aXZlUGFzdEtleSxcbiAgICAgIGF0dGVudGlvbkJpYXMsXG4gICAgICBwYXJhbWV0ZXJzLFxuICAgICAgcGFzdFNlcXVlbmNlTGVuZ3RoLFxuICAgICAgc2VxTGVucyxcbiAgICAgIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCxcbiAgICApLFxuICAgIHsgaW5wdXRzOiBpbnB1dHNLLCBvdXRwdXRzOiBvdXRwdXRDb3VudCA+IDEgPyBbLTEsIDFdIDogWy0xXSB9LFxuICApWzBdO1xuXG4gIC8vIFJ1biBTb2Z0bWF4XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVJblBsYWNlU29mdG1heFByb2dyYW1JbmZvKFxuICAgICAgcHJvYnMsXG4gICAgICBwYXJhbWV0ZXJzLmJhdGNoU2l6ZSxcbiAgICAgIHBhcmFtZXRlcnMubnVtSGVhZHMsXG4gICAgICBwYXN0U2VxdWVuY2VMZW5ndGgsXG4gICAgICBwYXJhbWV0ZXJzLnNlcXVlbmNlTGVuZ3RoLFxuICAgICAgdG90YWxTZXF1ZW5jZUxlbmd0aCxcbiAgICAgIHNlcUxlbnMsXG4gICAgICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQsXG4gICAgKSxcbiAgICB7IGlucHV0czogc2VxTGVucyAmJiB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQgPyBbcHJvYnMsIHNlcUxlbnMsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dF0gOiBbcHJvYnNdLCBvdXRwdXRzOiBbXSB9LFxuICApO1xuXG4gIC8vIFJ1biBBdHRlbnRpb25TY29yZVxuICBjb25zdCBpbnB1dHNWID0gW3Byb2JzLCB2XTtcbiAgaWYgKGVmZmVjdGl2ZVBhc3RWYWx1ZSAmJiBTaGFwZVV0aWwuc2l6ZShlZmZlY3RpdmVQYXN0VmFsdWUuZGltcykgPiAwKSB7XG4gICAgaW5wdXRzVi5wdXNoKGVmZmVjdGl2ZVBhc3RWYWx1ZSk7XG4gIH1cbiAgaWYgKHNlcUxlbnMpIHtcbiAgICBpbnB1dHNWLnB1c2goc2VxTGVucyk7XG4gIH1cbiAgaWYgKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCkge1xuICAgIGlucHV0c1YucHVzaCh0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQpO1xuICB9XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVWeEF0dGVudGlvblNjb3JlUHJvZ3JhbUluZm8oXG4gICAgICBvdXRwdXRDb3VudCxcbiAgICAgIHByb2JzLFxuICAgICAgdixcbiAgICAgIGVmZmVjdGl2ZVBhc3RWYWx1ZSxcbiAgICAgIHBhcmFtZXRlcnMsXG4gICAgICBwYXN0U2VxdWVuY2VMZW5ndGgsXG4gICAgICBzZXFMZW5zLFxuICAgICAgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LFxuICAgICksXG4gICAge1xuICAgICAgaW5wdXRzOiBpbnB1dHNWLFxuICAgICAgb3V0cHV0czogb3V0cHV0Q291bnQgPiAxID8gWzAsIDJdIDogWzBdLFxuICAgIH0sXG4gICk7XG59O1xuXG5jb25zdCBwcmVwYXJlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBwYXJhbWV0ZXJzOiBBdHRlbnRpb25QYXJhbWV0ZXJzKSA9PiB7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gW3BhcmFtZXRlcnMuYmF0Y2hTaXplLCBwYXJhbWV0ZXJzLm51bUhlYWRzLCBwYXJhbWV0ZXJzLnNlcXVlbmNlTGVuZ3RoLCBwYXJhbWV0ZXJzLmhlYWRTaXplXTtcbiAgY29uc3QgTSA9IHBhcmFtZXRlcnMuc2VxdWVuY2VMZW5ndGg7XG4gIGNvbnN0IEsgPSBwYXJhbWV0ZXJzLmlucHV0SGlkZGVuU2l6ZTtcbiAgY29uc3QgTiA9IHBhcmFtZXRlcnMuaGVhZFNpemU7XG4gIGNvbnN0IFRJTEVfU0laRSA9IDEyO1xuICBjb25zdCBkaXNwYXRjaCA9IHtcbiAgICB4OiBNYXRoLmNlaWwocGFyYW1ldGVycy5oZWFkU2l6ZSAvIFRJTEVfU0laRSksXG4gICAgeTogTWF0aC5jZWlsKHBhcmFtZXRlcnMuc2VxdWVuY2VMZW5ndGggLyBUSUxFX1NJWkUpLFxuICAgIHo6IHBhcmFtZXRlcnMuYmF0Y2hTaXplICogcGFyYW1ldGVycy5udW1IZWFkcyxcbiAgfTtcbiAgY29uc3QgaW5wdXRzID0gW2NvbnRleHQuaW5wdXRzWzBdLCBjb250ZXh0LmlucHV0c1sxXSwgY29udGV4dC5pbnB1dHNbMl1dO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE0gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogSyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBOIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtZXRlcnMubnVtSGVhZHMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1ldGVycy5oZWFkU2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbWV0ZXJzLmhpZGRlblNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1ldGVycy5oaWRkZW5TaXplICsgcGFyYW1ldGVycy5oaWRkZW5TaXplICsgcGFyYW1ldGVycy52SGlkZGVuU2l6ZSB9LFxuICBdO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IG91dHB1dFEgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0X3EnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlKTtcbiAgICBjb25zdCBvdXRwdXRLID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dF9rJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZSk7XG4gICAgY29uc3Qgb3V0cHV0ViA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXRfdicsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUpO1xuICAgIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zKTtcbiAgICBjb25zdCB3ZWlnaHQgPSBpbnB1dFZhcmlhYmxlKCd3ZWlnaHQnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zKTtcbiAgICBjb25zdCBiaWFzID0gaW5wdXRWYXJpYWJsZSgnYmlhcycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMpO1xuICAgIGNvbnN0IGRhdGFUeXBlID0gaW5wdXQudHlwZS5zdG9yYWdlO1xuXG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnTScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdLJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ04nLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnbnVtX2hlYWRzJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2hlYWRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdoaWRkZW5fc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdsZGInLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG4gICAgcmV0dXJuIGBcbiAgY29uc3QgVElMRV9TSVpFID0gJHtUSUxFX1NJWkV9dTtcbiAgdmFyPHdvcmtncm91cD4gdGlsZUlucHV0OiBhcnJheTwke2RhdGFUeXBlfSwgJHtUSUxFX1NJWkUgKiBUSUxFX1NJWkV9PjtcbiAgdmFyPHdvcmtncm91cD4gdGlsZVdlaWdodFE6IGFycmF5PCR7ZGF0YVR5cGV9LCAke1RJTEVfU0laRSAqIFRJTEVfU0laRX0+O1xuICB2YXI8d29ya2dyb3VwPiB0aWxlV2VpZ2h0SzogYXJyYXk8JHtkYXRhVHlwZX0sICR7VElMRV9TSVpFICogVElMRV9TSVpFfT47XG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGVXZWlnaHRWOiBhcnJheTwke2RhdGFUeXBlfSwgJHtUSUxFX1NJWkUgKiBUSUxFX1NJWkV9PjtcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgd2VpZ2h0LCBiaWFzLCBvdXRwdXRRLCBvdXRwdXRLLCBvdXRwdXRWKX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFtUSUxFX1NJWkUsIFRJTEVfU0laRSwgMV0pfVxuICAgIGxldCBiYXRjaEluZGV4ID0gd29ya2dyb3VwX2lkLnogLyB1bmlmb3Jtcy5udW1faGVhZHM7XG4gICAgbGV0IGhlYWROdW1iZXIgPSB3b3JrZ3JvdXBfaWQueiAlIHVuaWZvcm1zLm51bV9oZWFkcztcbiAgICBsZXQgbSA9IGdsb2JhbF9pZC55O1xuICAgIGxldCBuID0gZ2xvYmFsX2lkLng7XG5cbiAgICBsZXQgaW5wdXRPZmZzZXQgPSBiYXRjaEluZGV4ICogKHVuaWZvcm1zLk0gKiB1bmlmb3Jtcy5LKSArIG0gKiB1bmlmb3Jtcy5LO1xuICAgIGxldCBiaWFzT2Zmc2V0USA9IGhlYWROdW1iZXIgKiB1bmlmb3Jtcy5oZWFkX3NpemU7XG4gICAgbGV0IGJpYXNPZmZzZXRLID0gdW5pZm9ybXMuaGlkZGVuX3NpemUgKyBiaWFzT2Zmc2V0UTtcbiAgICBsZXQgYmlhc09mZnNldFYgPSB1bmlmb3Jtcy5oaWRkZW5fc2l6ZSArIGJpYXNPZmZzZXRLO1xuXG4gICAgdmFyIHZhbHVlUSA9ICR7ZGF0YVR5cGV9KDApO1xuICAgIHZhciB2YWx1ZUsgPSAke2RhdGFUeXBlfSgwKTtcbiAgICB2YXIgdmFsdWVWID0gJHtkYXRhVHlwZX0oMCk7XG4gICAgZm9yICh2YXIgdzogdTMyID0gMHU7IHcgPCB1bmlmb3Jtcy5LOyB3ICs9IFRJTEVfU0laRSkge1xuICAgICAgaWYgKG0gPCB1bmlmb3Jtcy5NICYmIHcgKyBsb2NhbF9pZC54IDwgdW5pZm9ybXMuSykge1xuICAgICAgICB0aWxlSW5wdXRbVElMRV9TSVpFICogbG9jYWxfaWQueSArIGxvY2FsX2lkLnhdID0gaW5wdXRbaW5wdXRPZmZzZXQgKyB3ICsgbG9jYWxfaWQueF07XG4gICAgICB9XG4gICAgICBpZiAobiA8IHVuaWZvcm1zLk4gJiYgdyArIGxvY2FsX2lkLnkgPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIGxldCBvZmZzZXQgPSBuICsgKHcgKyBsb2NhbF9pZC55KSAqIHVuaWZvcm1zLmxkYjtcbiAgICAgICAgdGlsZVdlaWdodFFbVElMRV9TSVpFICogbG9jYWxfaWQueSArIGxvY2FsX2lkLnhdID0gd2VpZ2h0W2JpYXNPZmZzZXRRICsgb2Zmc2V0XTtcbiAgICAgICAgdGlsZVdlaWdodEtbVElMRV9TSVpFICogbG9jYWxfaWQueSArIGxvY2FsX2lkLnhdID0gd2VpZ2h0W2JpYXNPZmZzZXRLICsgb2Zmc2V0XTtcbiAgICAgICAgdGlsZVdlaWdodFZbVElMRV9TSVpFICogbG9jYWxfaWQueSArIGxvY2FsX2lkLnhdID0gd2VpZ2h0W2JpYXNPZmZzZXRWICsgb2Zmc2V0XTtcbiAgICAgIH1cbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgICAgIGZvciAodmFyIGs6IHUzMiA9IDB1OyBrPFRJTEVfU0laRSAmJiB3K2sgPCB1bmlmb3Jtcy5LOyBrKyspIHtcbiAgICAgICAgbGV0IGlucHV0VGlsZU9mZnNldCA9IFRJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBrO1xuICAgICAgICBsZXQgd2VpZ2h0VGlsZU9mZnNldCA9IFRJTEVfU0laRSAqIGsgKyBsb2NhbF9pZC54O1xuICAgICAgICB2YWx1ZVEgKz0gdGlsZUlucHV0W2lucHV0VGlsZU9mZnNldF0gKiB0aWxlV2VpZ2h0UVt3ZWlnaHRUaWxlT2Zmc2V0XTtcbiAgICAgICAgdmFsdWVLICs9IHRpbGVJbnB1dFtpbnB1dFRpbGVPZmZzZXRdICogdGlsZVdlaWdodEtbd2VpZ2h0VGlsZU9mZnNldF07XG4gICAgICAgIHZhbHVlViArPSB0aWxlSW5wdXRbaW5wdXRUaWxlT2Zmc2V0XSAqIHRpbGVXZWlnaHRWW3dlaWdodFRpbGVPZmZzZXRdO1xuICAgICAgfVxuXG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgfVxuXG4gICAgbGV0IGhlYWRPZmZzZXQgPSAobSAqIHVuaWZvcm1zLk4gKyBuKSAlIHVuaWZvcm1zLmhlYWRfc2l6ZTtcbiAgICB2YWx1ZVEgKz0gYmlhc1toZWFkT2Zmc2V0ICsgYmlhc09mZnNldFFdO1xuICAgIHZhbHVlSyArPSBiaWFzW2hlYWRPZmZzZXQgKyBiaWFzT2Zmc2V0S107XG4gICAgdmFsdWVWICs9IGJpYXNbaGVhZE9mZnNldCArIGJpYXNPZmZzZXRWXTtcblxuICAgIGxldCBvZmZzZXQgPSB3b3JrZ3JvdXBfaWQueiAqIHVuaWZvcm1zLk0gKiB1bmlmb3Jtcy5OO1xuICAgIGlmIChtIDwgdW5pZm9ybXMuTSAmJiBuIDwgdW5pZm9ybXMuTikge1xuICAgICAgbGV0IG91dHB1dElkeCA9IG9mZnNldCArIG0gKiB1bmlmb3Jtcy5OICsgbjtcbiAgICAgIG91dHB1dF9xW291dHB1dElkeF0gPSB2YWx1ZVE7XG4gICAgICBvdXRwdXRfa1tvdXRwdXRJZHhdID0gdmFsdWVLO1xuICAgICAgb3V0cHV0X3Zbb3V0cHV0SWR4XSA9IHZhbHVlVjtcbiAgICB9XG4gIH1gO1xuICB9O1xuXG4gIHJldHVybiBjb250ZXh0LmNvbXB1dGUoXG4gICAge1xuICAgICAgbmFtZTogJ0F0dGVudGlvblByZXBhcmUnLFxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaW5wdXREZXBlbmRlbmNpZXM6IFsndHlwZScsICd0eXBlJywgJ3R5cGUnXSB9LFxuICAgICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgIHsgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHQgfSxcbiAgICAgICAgICB7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUsIGdwdURhdGFUeXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0IH0sXG4gICAgICAgICAgeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9LFxuICAgICAgICBdLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiBkaXNwYXRjaCxcbiAgICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgICAgfSksXG4gICAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgfSxcbiAgICB7IGlucHV0cywgb3V0cHV0czogWy0xLCAtMSwgLTFdIH0sXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgYXR0ZW50aW9uID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBdHRlbnRpb25BdHRycyk6IHZvaWQgPT4ge1xuICBjb25zdCBwYXJhbXMgPSB2YWxpZGF0ZUF0dGVudGlvbklucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG5cbiAgY29uc3QgW3EsIGssIHZdID0gcHJlcGFyZShjb250ZXh0LCBwYXJhbXMpO1xuXG4gIHJldHVybiBhcHBseUF0dGVudGlvbihcbiAgICBjb250ZXh0LFxuICAgIHEsXG4gICAgayxcbiAgICB2LFxuICAgIGNvbnRleHQuaW5wdXRzWzRdLFxuICAgIHVuZGVmaW5lZCxcbiAgICB1bmRlZmluZWQsXG4gICAgdW5kZWZpbmVkLFxuICAgIGNvbnRleHQuaW5wdXRzWzVdLFxuICAgIHBhcmFtcyxcbiAgKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGVudiB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgZ2V0TWF4Q29tcG9uZW50cywgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBCYXRjaE5vcm1BdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgZXBzaWxvbjogbnVtYmVyO1xuICByZWFkb25seSBtb21lbnR1bTogbnVtYmVyO1xuICByZWFkb25seSBzcGF0aWFsOiBib29sZWFuO1xuICByZWFkb25seSB0cmFpbmluZ01vZGU6IGJvb2xlYW47XG4gIHJlYWRvbmx5IGZvcm1hdDogJ05IV0MnIHwgJ05DSFcnO1xuICByZWFkb25seSBvdXRwdXRDb3VudDogbnVtYmVyO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogQmF0Y2hOb3JtQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSA1KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdCYXRjaE5vcm1hbGl6YXRpb24gcmVxdWlyZXMgNSBpbnB1dHMnKTtcbiAgfVxuXG4gIGNvbnN0IGNoZWNrU2hhcGVFcXVhbCA9IChhY3R1YWw6IHJlYWRvbmx5IG51bWJlcltdLCBleHBlY3RlZDogcmVhZG9ubHkgbnVtYmVyW10sIG1lc3NhZ2U6IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IHIgPSBleHBlY3RlZC5sZW5ndGg7XG4gICAgaWYgKHIgIT09IGFjdHVhbC5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHttZXNzYWdlfTogbnVtIGRpbWVuc2lvbnMgIT0gJHtyfWApO1xuICAgIH1cbiAgICBleHBlY3RlZC5mb3JFYWNoKCh2LCBpKSA9PiB7XG4gICAgICBpZiAodiAhPT0gYWN0dWFsW2ldKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHttZXNzYWdlfTogZGltWyR7aX1dIGRvIG5vdCBtYXRjaGApO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggPiAxKSB7XG4gICAgY29uc3Qgc2hhcGUgPVxuICAgICAgYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJ1xuICAgICAgICA/IGF0dHJpYnV0ZXMuc3BhdGlhbFxuICAgICAgICAgID8gaW5wdXRzWzBdLmRpbXMuc2xpY2UoLTEpXG4gICAgICAgICAgOiBpbnB1dHNbMF0uZGltcy5zbGljZSgtMSkuY29uY2F0KGlucHV0c1swXS5kaW1zLnNsaWNlKDEsIGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDEpKVxuICAgICAgICA6IGlucHV0c1swXS5kaW1zLnNsaWNlKDEsIGF0dHJpYnV0ZXMuc3BhdGlhbCA/IDIgOiB1bmRlZmluZWQpO1xuICAgIGNoZWNrU2hhcGVFcXVhbChpbnB1dHNbMV0uZGltcywgc2hhcGUsICdJbnZhbGlkIGlucHV0IHNjYWxlJyk7XG4gICAgY2hlY2tTaGFwZUVxdWFsKGlucHV0c1syXS5kaW1zLCBzaGFwZSwgJ0ludmFsaWQgaW5wdXQgQicpO1xuICAgIGNoZWNrU2hhcGVFcXVhbChpbnB1dHNbM10uZGltcywgc2hhcGUsICdJbnZhbGlkIGlucHV0IG1lYW4nKTtcbiAgICBjaGVja1NoYXBlRXF1YWwoaW5wdXRzWzRdLmRpbXMsIHNoYXBlLCAnSW52YWxpZCBpbnB1dCB2YXInKTtcbiAgfSBlbHNlIHtcbiAgICBjaGVja1NoYXBlRXF1YWwoaW5wdXRzWzFdLmRpbXMsIFsxXSwgJ0ludmFsaWQgaW5wdXQgc2NhbGUnKTtcbiAgICBjaGVja1NoYXBlRXF1YWwoaW5wdXRzWzJdLmRpbXMsIFsxXSwgJ0ludmFsaWQgaW5wdXQgQicpO1xuICAgIGNoZWNrU2hhcGVFcXVhbChpbnB1dHNbM10uZGltcywgWzFdLCAnSW52YWxpZCBpbnB1dCBtZWFuJyk7XG4gICAgY2hlY2tTaGFwZUVxdWFsKGlucHV0c1s0XS5kaW1zLCBbMV0sICdJbnZhbGlkIGlucHV0IHZhcicpO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVCYXRjaE5vcm1JbmZlcmVuY2VQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IEJhdGNoTm9ybUF0dHJpYnV0ZXMsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IHsgZXBzaWxvbiwgc3BhdGlhbCwgZm9ybWF0IH0gPSBhdHRyaWJ1dGVzO1xuICBjb25zdCB5U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgY29tcG9uZW50cyA9IHNwYXRpYWwgPyBnZXRNYXhDb21wb25lbnRzKHlTaGFwZVt5U2hhcGUubGVuZ3RoIC0gMV0pIDogMTtcbiAgY29uc3QgY0NvbXBvbmVudHMgPSBmb3JtYXQgPT09ICdOSFdDJyAmJiB5U2hhcGUubGVuZ3RoID4gMSA/IGNvbXBvbmVudHMgOiAxO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUoeVNoYXBlKSAvIGNvbXBvbmVudHM7XG4gIC8vIE9ubHkgc3VwcG9ydCB1bmlmb3JtcyBmb3Igb3BzZXQgdmVyc2lvbiA+PSA5IChzcGF0aWFsID0gdHJ1ZSkuXG4gIGNvbnN0IHVzZVNoYXBlc1VuaWZvcm1zID0gc3BhdGlhbDtcbiAgY29uc3Qgc2hhcGVPclJhbmsgPSB1c2VTaGFwZXNVbmlmb3JtcyA/IHlTaGFwZS5sZW5ndGggOiB5U2hhcGU7XG4gIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcywgY29tcG9uZW50cyk7XG4gIGNvbnN0IHNjYWxlID0gaW5wdXRWYXJpYWJsZSgnc2NhbGUnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLCBjQ29tcG9uZW50cyk7XG4gIGNvbnN0IGJpYXMgPSBpbnB1dFZhcmlhYmxlKCdiaWFzJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcywgY0NvbXBvbmVudHMpO1xuICBjb25zdCBpbnB1dE1lYW4gPSBpbnB1dFZhcmlhYmxlKCdpbnB1dE1lYW4nLCBpbnB1dHNbM10uZGF0YVR5cGUsIGlucHV0c1szXS5kaW1zLCBjQ29tcG9uZW50cyk7XG4gIGNvbnN0IGlucHV0VmFyID0gaW5wdXRWYXJpYWJsZSgnaW5wdXRWYXInLCBpbnB1dHNbNF0uZGF0YVR5cGUsIGlucHV0c1s0XS5kaW1zLCBjQ29tcG9uZW50cyk7XG4gIGNvbnN0IHkgPSBvdXRwdXRWYXJpYWJsZSgneScsIGlucHV0c1swXS5kYXRhVHlwZSwgc2hhcGVPclJhbmssIGNvbXBvbmVudHMpO1xuICAvLyBUT0RPOiBzdXBwb3J0IGlucHV0cyB3aXRoIGRpZmZlcmVudCBkYXRhIHR5cGUuIEN1cnJlbnQgd2UgbmVlZCB0byBtYWtlIHN1cmUgYWxsIGlucHV0cyBoYXZlIHRoZSBzYW1lIGRhdGEgdHlwZS5cbiAgLy8gT3RoZXJ3aXNlLCB0aGUgc2hhZGVyIGNvbXBpbGF0aW9uIHdpbGwgZmFpbC5cbiAgY29uc3QgY2FsY0NPZmZzZXQgPSAoKTogc3RyaW5nID0+IHtcbiAgICBsZXQgY09mZnNldCA9ICcnO1xuICAgIGlmIChzcGF0aWFsKSB7XG4gICAgICBjT2Zmc2V0ID0gYGxldCBjT2Zmc2V0ID0gJHtcbiAgICAgICAgeVNoYXBlLmxlbmd0aCA9PT0gMVxuICAgICAgICAgID8gJzB1J1xuICAgICAgICAgIDogZm9ybWF0ID09PSAnTkhXQydcbiAgICAgICAgICAgID8gYG91dHB1dEluZGljZXNbJHt5U2hhcGUubGVuZ3RoIC0gMX1dIC8gJHtjb21wb25lbnRzfWBcbiAgICAgICAgICAgIDogJ291dHB1dEluZGljZXNbMV0nXG4gICAgICB9O2A7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChmb3JtYXQgPT09ICdOQ0hXJykge1xuICAgICAgICBjT2Zmc2V0ID0gYFxuICAgICAgICAgICAgJHt5LmluZGljZXNTZXQoJ291dHB1dEluZGljZXMnLCAnMCcsICcwJyl9XG4gICAgICAgICAgICBsZXQgY09mZnNldCA9ICR7eS5pbmRpY2VzVG9PZmZzZXQoJ291dHB1dEluZGljZXMnKX07YDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHVwZGF0ZSBDIGNoYW5uZWwuXG4gICAgICAgIGNPZmZzZXQgPSBgdmFyIGNJbmRpY2VzID0gJHtzY2FsZS50eXBlLmluZGljZXN9KDApO1xuICAgICAgICAgICAgICAgICAgICAgICBjSW5kaWNlc1swXSA9IG91dHB1dEluZGljZXNbJHt5U2hhcGUubGVuZ3RoIC0gMX1dO2A7XG4gICAgICAgIC8vIHVwZGF0ZSBEMSB4IC4uLiB4IERuIGNoYW5uZWxzLlxuICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHNjYWxlLnJhbms7IGkrKykge1xuICAgICAgICAgIGNPZmZzZXQgKz0gYGNJbmRpY2VzWyR7aX1dID0gb3V0cHV0SW5kaWNlc1ske2l9XTtgO1xuICAgICAgICB9XG4gICAgICAgIGNPZmZzZXQgKz0gYGxldCBjT2Zmc2V0ID0gJHtzY2FsZS5pbmRpY2VzVG9PZmZzZXQoJ2NJbmRpY2VzJyl9O2A7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjT2Zmc2V0O1xuICB9O1xuICBjb25zdCBnZXRJbmZlcmVuY2VNb2RlU2hhZGVyU291cmNlID0gKGhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gIGNvbnN0IGVwc2lsb24gPSAke2Vwc2lsb259O1xuICAke2hlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dFNpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyh4LCBzY2FsZSwgYmlhcywgaW5wdXRNZWFuLCBpbnB1dFZhciwgeSl9XG4gICR7aGVscGVyLm1haW5TdGFydCgpfVxuICAke2hlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG4gICAgdmFyIG91dHB1dEluZGljZXMgPSAke3kub2Zmc2V0VG9JbmRpY2VzKGBnbG9iYWxfaWR4ICogJHtjb21wb25lbnRzfWApfTtcbiAgICAke2NhbGNDT2Zmc2V0KCl9XG4gICAgbGV0IHNjYWxlID0gJHtzY2FsZS5nZXRCeU9mZnNldCgnY09mZnNldCcpfTtcbiAgICBsZXQgYmlhcyA9ICR7Ymlhcy5nZXRCeU9mZnNldCgnY09mZnNldCcpfTtcbiAgICBsZXQgaW5wdXRNZWFuID0gJHtpbnB1dE1lYW4uZ2V0QnlPZmZzZXQoJ2NPZmZzZXQnKX07XG4gICAgbGV0IGlucHV0VmFyID0gJHtpbnB1dFZhci5nZXRCeU9mZnNldCgnY09mZnNldCcpfTtcbiAgICBsZXQgeCA9ICR7eC5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpfTtcbiAgICBsZXQgdmFsdWUgPSAoeCAtIGlucHV0TWVhbikgKiBpbnZlcnNlU3FydChpbnB1dFZhciArIGVwc2lsb24pICogc2NhbGUgKyBiaWFzO1xuICAgICR7eS5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZScpfVxuICB9YDtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQmF0Y2hOb3JtYWxpemF0aW9uJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YXR0cmlidXRlcy5lcHNpbG9ufV8ke2F0dHJpYnV0ZXMuZm9ybWF0fV8ke3NwYXRpYWx9XyR7Y29tcG9uZW50c31gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IHVzZVNoYXBlc1VuaWZvcm1zID8gWydyYW5rJywgJ3R5cGUnLCAndHlwZScsICd0eXBlJywgJ3R5cGUnXSA6IHVuZGVmaW5lZCxcbiAgICB9LFxuICAgIGdldFNoYWRlclNvdXJjZTogZ2V0SW5mZXJlbmNlTW9kZVNoYWRlclNvdXJjZSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogaW5wdXRzWzBdLmRpbXMsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXM6IHVzZVNoYXBlc1VuaWZvcm1zXG4gICAgICAgID8gW3sgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKHlTaGFwZSldXG4gICAgICAgIDogW3sgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH1dLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQmF0Y2hOb3JtQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEJhdGNoTm9ybUF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KGF0dHJpYnV0ZXMgYXMgT21pdDxCYXRjaE5vcm1BdHRyaWJ1dGVzLCBrZXlvZiBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXk+KTtcblxuZXhwb3J0IGNvbnN0IGJhdGNoTm9ybSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiB2b2lkID0+IHtcbiAgY29uc3QgeyBpbnB1dHMsIG91dHB1dENvdW50IH0gPSBjb250ZXh0O1xuICBjb25zdCB1cGRhdGVkQXR0cmlidXRlcyA9IHBhcnNlQmF0Y2hOb3JtQXR0cmlidXRlcyh7IC4uLmF0dHJpYnV0ZXMsIG91dHB1dENvdW50IH0pO1xuICBpZiAoZW52LndlYmdwdS52YWxpZGF0ZUlucHV0Q29udGVudCkge1xuICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cywgdXBkYXRlZEF0dHJpYnV0ZXMpO1xuICB9XG4gIGlmIChhdHRyaWJ1dGVzLnRyYWluaW5nTW9kZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQmF0Y2hOb3JtYWxpemF0aW9uIHRyYWluaW5nTW9kZSBpcyBub3Qgc3VwcG9ydGVkIHlldC4nKTtcbiAgfSBlbHNlIHtcbiAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlQmF0Y2hOb3JtSW5mZXJlbmNlUHJvZ3JhbUluZm8oaW5wdXRzLCB1cGRhdGVkQXR0cmlidXRlcykpO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IHNob3VsZCBoYXZlIDMgZGltZW5zaW9ucycpO1xuICB9XG5cbiAgaWYgKCFbMzIwLCA2NDAsIDEyODBdLmluY2x1ZGVzKGlucHV0c1swXS5kaW1zWzJdKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbnVtYmVyIG9mIGNoYW5uZWxzIHNob3VsZCBiZSAzMjAsIDY0MCBvciAxMjgwJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdiaWFzIGlzIGV4cGVjdGVkIHRvIGhhdmUgMSBkaW1lbnNpb25zJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXNbMl0gIT09IGlucHV0c1sxXS5kaW1zWzBdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdsYXN0IGRpbWVuc2lvbiBvZiBpbnB1dCBhbmQgYmlhcyBhcmUgbm90IHRoZSBzYW1lJyk7XG4gIH1cbn07XG5cbmNvbnN0IGNyZWF0ZUJpYXNBZGRQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcblxuICBjb25zdCBjaGFubmVscyA9IGlucHV0c1swXS5kaW1zWzJdO1xuICAvLyBzaW5jZSBjaGFubmVsIG51bWJlciBjYW4gYmUgb25seSAzMjAvNjQwLzEyODAsIGl0J3MgYWx3YXlzIGRpdmlzaWJsZSBieSA0XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyA0O1xuXG4gIGNvbnN0IGRhdGFUeXBlID0gaW5wdXRzWzBdLmRhdGFUeXBlO1xuICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgZGF0YVR5cGUsIG91dHB1dFNoYXBlLCA0KTtcbiAgY29uc3QgYmlhcyA9IGlucHV0VmFyaWFibGUoJ2JpYXMnLCBkYXRhVHlwZSwgW2NoYW5uZWxzXSwgNCk7XG4gIGNvbnN0IHJlc2lkdWFsID0gaW5wdXRWYXJpYWJsZSgncmVzaWR1YWwnLCBkYXRhVHlwZSwgb3V0cHV0U2hhcGUsIDQpO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgZGF0YVR5cGUsIG91dHB1dFNoYXBlLCA0KTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgY29uc3QgY2hhbm5lbHMgPSAke2NoYW5uZWxzfXUgLyA0O1xuICAke3NoYWRlckhlbHBlci5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBiaWFzLCByZXNpZHVhbCwgb3V0cHV0KX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKG91dHB1dFNpemUpfVxuICAgIGxldCB2YWx1ZSA9ICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKX1cbiAgICAgICsgJHtiaWFzLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4ICUgY2hhbm5lbHMnKX0gKyAke3Jlc2lkdWFsLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4Jyl9O1xuICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3ZhbHVlJyl9XG4gIH1gO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0JpYXNBZGQnLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgYmlhc0FkZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVCaWFzQWRkUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZSxcbiAgVW5pZm9ybURhdGFFbGVtZW50VHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxudHlwZSBCdWlsdGluRnVuY3Rpb25OYW1lID0gc3RyaW5nO1xudHlwZSBFbGVtZW50d2lzZUN1c3RvbUV4cHJlc3Npb24gPSAoZXhwcmVzc2lvbjogc3RyaW5nKSA9PiBzdHJpbmc7XG50eXBlIEVsZW1lbnR3aXNlRnVuY3Rpb25DYWxsID0gQnVpbHRpbkZ1bmN0aW9uTmFtZSB8IEVsZW1lbnR3aXNlQ3VzdG9tRXhwcmVzc2lvbjtcblxuY29uc3QgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtU2hhZGVyID0gKFxuICBzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcixcbiAgZGF0YXNpemU6IG51bWJlcixcbiAgaW5wdXREYXRhVHlwZTogbnVtYmVyLFxuICBvdXRwdXREYXRhVHlwZTogbnVtYmVyLFxuICBmdW5jQ2FsbDogRWxlbWVudHdpc2VGdW5jdGlvbkNhbGwsXG4gIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbj86IHN0cmluZyxcbiAgYWRkaXRpb25hbFVuaWZvcm1zVHlwZT86IFVuaWZvcm1zQXJyYXlUeXBlLFxuKTogc3RyaW5nID0+IHtcbiAgY29uc3QgdmVjU2l6ZSA9IE1hdGguY2VpbChkYXRhc2l6ZSAvIDQpO1xuXG4gIGxldCBleHByZXNzaW9uID0gJyc7XG4gIGlmICh0eXBlb2YgZnVuY0NhbGwgPT09ICdzdHJpbmcnKSB7XG4gICAgZXhwcmVzc2lvbiA9IGAke2Z1bmNDYWxsfShhKWA7XG4gIH0gZWxzZSB7XG4gICAgZXhwcmVzc2lvbiA9IGZ1bmNDYWxsKCdhJyk7XG4gIH1cblxuICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0RGF0YScsIGlucHV0RGF0YVR5cGUsIFt2ZWNTaXplXSwgNCk7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXREYXRhJywgb3V0cHV0RGF0YVR5cGUsIFt2ZWNTaXplXSwgNCk7XG4gIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFt7IG5hbWU6ICd2ZWNfc2l6ZScsIHR5cGU6ICd1MzInIH1dO1xuICBpZiAoYWRkaXRpb25hbFVuaWZvcm1zVHlwZSkge1xuICAgIHVuaWZvcm1zLnB1c2goLi4uYWRkaXRpb25hbFVuaWZvcm1zVHlwZSk7XG4gIH1cblxuICByZXR1cm4gYFxuICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgb3V0cHV0KX1cblxuICAke2FkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbiA/PyAnJ31cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy52ZWNfc2l6ZScpfVxuXG4gICAgbGV0IGEgPSAke2lucHV0LmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4Jyl9O1xuICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgZXhwcmVzc2lvbil9XG4gIH1gO1xufTtcblxuY29uc3QgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXQ6IFRlbnNvclZpZXcsXG4gIG5hbWU6IHN0cmluZyxcbiAgZnVuY0NhbGw6IEVsZW1lbnR3aXNlRnVuY3Rpb25DYWxsLFxuICBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24/OiBzdHJpbmcsXG4gIGNhY2hlS2V5Pzogc3RyaW5nLFxuICBvdXRwdXREYXRhVHlwZTogbnVtYmVyID0gaW5wdXQuZGF0YVR5cGUsXG4gIGFkZGl0aW9uYWxVbmlmb3Jtcz86IFByb2dyYW1Vbmlmb3JtW10sXG4gIGFkZGl0aW9uYWxVbmlmb3Jtc1R5cGU/OiBVbmlmb3Jtc0FycmF5VHlwZSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBNYXRoLmNlaWwoU2hhcGVVdGlsLnNpemUoaW5wdXQuZGltcykgLyA0KSB9LFxuICBdO1xuICBpZiAoYWRkaXRpb25hbFVuaWZvcm1zKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uYWRkaXRpb25hbFVuaWZvcm1zKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBjYWNoZUtleSwgaW5wdXREZXBlbmRlbmNpZXM6IFsndHlwZSddIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlOiAoc2hhZGVySGVscGVyKSA9PlxuICAgICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtU2hhZGVyKFxuICAgICAgICBzaGFkZXJIZWxwZXIsXG4gICAgICAgIFNoYXBlVXRpbC5zaXplKGlucHV0LmRpbXMpLFxuICAgICAgICBpbnB1dC5kYXRhVHlwZSxcbiAgICAgICAgb3V0cHV0RGF0YVR5cGUsXG4gICAgICAgIGZ1bmNDYWxsLFxuICAgICAgICBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24sXG4gICAgICAgIGFkZGl0aW9uYWxVbmlmb3Jtc1R5cGUsXG4gICAgICApLFxuICAgIGdldFJ1bkRhdGE6IChpbnB1dFRlbnNvcnMpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBpbnB1dC5kaW1zLCBkYXRhVHlwZTogb3V0cHV0RGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7XG4gICAgICAgIHg6IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShpbnB1dFRlbnNvcnNbMF0uZGltcykgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLyAvIDQgLyogdmVjIHNpemUgKi8pLFxuICAgICAgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBhYnMgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdBYnMnLCAnYWJzJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGFjb3MgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdBY29zJywgJ2Fjb3MnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgYWNvc2ggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdBY29zaCcsICdhY29zaCcpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhc2luID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQXNpbicsICdhc2luJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGFzaW5oID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQXNpbmgnLCAnYXNpbmgnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgYXRhbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0F0YW4nLCAnYXRhbicpKTtcbn07XG5leHBvcnQgY29uc3QgYXRhbmggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdBdGFuaCcsICdhdGFuaCcpKTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2FzdEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSB0bzogbnVtYmVyO1xuICByZWFkb25seSBzYXR1cmF0ZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjb25zdCBwYXJzZUNhc3RBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQ2FzdEF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KGF0dHJpYnV0ZXMgYXMgeyB0bzogbnVtYmVyIH0pO1xuXG5leHBvcnQgY29uc3QgY2FzdCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQ2FzdEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgbGV0IGZ1bmM6IEVsZW1lbnR3aXNlRnVuY3Rpb25DYWxsO1xuICBzd2l0Y2ggKGF0dHJpYnV0ZXMudG8pIHtcbiAgICBjYXNlIERhdGFUeXBlLmZsb2F0MTY6XG4gICAgICBmdW5jID0gJ3ZlYzQ8ZjE2Pic7XG4gICAgICBicmVhaztcbiAgICBjYXNlIERhdGFUeXBlLmZsb2F0OlxuICAgICAgZnVuYyA9ICd2ZWM0PGYzMj4nO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50MzI6XG4gICAgICBmdW5jID0gJ3ZlYzQ8dTMyPic7XG4gICAgICBicmVhaztcbiAgICBjYXNlIERhdGFUeXBlLmludDMyOlxuICAgICAgZnVuYyA9ICd2ZWM0PGkzMj4nO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBEYXRhVHlwZS5ib29sOlxuICAgICAgZnVuYyA9ICd2ZWM0PGJvb2w+JztcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgbm90IHN1cHBvcnRlZCB0eXBlIChzcGVjaWZpZWQgaW4gYXR0cmlidXRlICd0bycgZnJvbSAnQ2FzdCcgb3BlcmF0b3IpOiAke2F0dHJpYnV0ZXMudG99YCk7XG4gIH1cbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdDYXN0JywgZnVuYywgdW5kZWZpbmVkLCBhdHRyaWJ1dGVzLmNhY2hlS2V5LCBhdHRyaWJ1dGVzLnRvKSxcbiAgKTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpcEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBtaW46IG51bWJlcjtcbiAgcmVhZG9ubHkgbWF4OiBudW1iZXI7XG59XG5cbmNvbnN0IGdlbmVyYXRlQ2xpcEF0dHJpYnV0ZXNGcm9tSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogQ2xpcEF0dHJpYnV0ZXMgPT4ge1xuICBsZXQgbWluOiBudW1iZXI7XG4gIGxldCBtYXg6IG51bWJlcjtcbiAgY29uc3QgaGFzTWluID0gaW5wdXRzLmxlbmd0aCA+PSAyICYmIGlucHV0c1sxXS5kYXRhICE9PSAwO1xuICBjb25zdCBoYXNNYXggPSBpbnB1dHMubGVuZ3RoID49IDMgJiYgaW5wdXRzWzJdLmRhdGEgIT09IDA7XG5cbiAgc3dpdGNoIChpbnB1dHNbMF0uZGF0YVR5cGUpIHtcbiAgICBjYXNlIERhdGFUeXBlLmZsb2F0OlxuICAgICAgbWluID0gaGFzTWluID8gaW5wdXRzWzFdLmdldEZsb2F0MzJBcnJheSgpWzBdIDogLTMuNDAyODIzNDY2Mzg1Mjg4NmUzODtcbiAgICAgIG1heCA9IGhhc01heCA/IGlucHV0c1syXS5nZXRGbG9hdDMyQXJyYXkoKVswXSA6IDMuNDAyODIzNDY2Mzg1Mjg4NmUzODtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgRGF0YVR5cGUuZmxvYXQxNjpcbiAgICAgIG1pbiA9IGhhc01pbiA/IGlucHV0c1sxXS5nZXRVaW50MTZBcnJheSgpWzBdIDogNjQ1MTE7IC8vIHVpbnQxNig2NDUxMSkgPC0+IGZsb2F0MTYoLTY1NTA0LjApXG4gICAgICBtYXggPSBoYXNNYXggPyBpbnB1dHNbMl0uZ2V0VWludDE2QXJyYXkoKVswXSA6IDMxNzQzOyAvLyB1aW50MTYoMzE3NDMpIDwtPiBmbG9hdDE2KDY1NTA0LjApXG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnQgZGF0YSB0eXBlJyk7XG4gIH1cblxuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgbWluLCBtYXggfSk7XG59O1xuXG5leHBvcnQgY29uc3QgY2xpcCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgY2xpcEF0dHJpYnV0ZXM6IENsaXBBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGF0dHJpYnV0ZXMgPSBjbGlwQXR0cmlidXRlcyA/IGNsaXBBdHRyaWJ1dGVzIDogZ2VuZXJhdGVDbGlwQXR0cmlidXRlc0Zyb21JbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgJ0NsaXAnLFxuICAgICAgKGEpID0+IGBjbGFtcCgke2F9LCB2ZWM0PCR7ZGF0YVR5cGV9Pih1bmlmb3Jtcy5taW4pLCB2ZWM0PCR7ZGF0YVR5cGV9Pih1bmlmb3Jtcy5tYXgpKWAsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgW1xuICAgICAgICB7IHR5cGU6IGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLCBkYXRhOiBhdHRyaWJ1dGVzLm1pbiB9LFxuICAgICAgICB7IHR5cGU6IGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLCBkYXRhOiBhdHRyaWJ1dGVzLm1heCB9LFxuICAgICAgXSxcbiAgICAgIFtcbiAgICAgICAgeyBuYW1lOiAnbWluJywgdHlwZTogZGF0YVR5cGUgYXMgVW5pZm9ybURhdGFFbGVtZW50VHlwZSB9LFxuICAgICAgICB7IG5hbWU6ICdtYXgnLCB0eXBlOiBkYXRhVHlwZSBhcyBVbmlmb3JtRGF0YUVsZW1lbnRUeXBlIH0sXG4gICAgICBdLFxuICAgICksXG4gICAgeyBpbnB1dHM6IFswXSB9LFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGNlaWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdDZWlsJywgJ2NlaWwnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgY29zID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQ29zJywgJ2NvcycpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBjb3NoID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQ29zaCcsICdjb3NoJykpO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBBbHBoYUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBhbHBoYTogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgcGFyc2VBbHBoYUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBBbHBoYUF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KGF0dHJpYnV0ZXMgYXMgeyBhbHBoYTogbnVtYmVyIH0pO1xuXG5leHBvcnQgY29uc3QgZWx1ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBbHBoYUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgICdFbHUnLFxuICAgICAgKGEpID0+IGBlbHVfdmYzMigke2F9KWAsXG4gICAgICBgXG4gIGNvbnN0IGVsdV9hbHBoYV8gPSAke2RhdGFUeXBlfSgke2F0dHJpYnV0ZXMuYWxwaGF9KTtcblxuICBmbiBlbHVfZjMyKGE6ICR7ZGF0YVR5cGV9KSAtPiAke2RhdGFUeXBlfSB7XG4gIHJldHVybiBzZWxlY3QoKGV4cChhKSAtIDEuMCkgKiBlbHVfYWxwaGFfLCBhLCBhID49IDAuMCk7XG4gIH1cblxuICBmbiBlbHVfdmYzMih2OiB2ZWM0PCR7ZGF0YVR5cGV9PikgLT4gdmVjNDwke2RhdGFUeXBlfT4ge1xuICByZXR1cm4gdmVjNChlbHVfZjMyKHYueCksIGVsdV9mMzIodi55KSwgZWx1X2YzMih2LnopLCBlbHVfZjMyKHYudykpO1xuICB9YCxcbiAgICAgIGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgKSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBlcmZJbXBsID0gKHZhclR5cGUgPSAnZjMyJykgPT4gYFxuY29uc3QgcjA6ICR7dmFyVHlwZX0gPSAwLjMyNzU5MTE7XG5jb25zdCByMTogJHt2YXJUeXBlfSA9IDAuMjU0ODI5NTkyO1xuY29uc3QgcjI6ICR7dmFyVHlwZX0gPSAtMC4yODQ0OTY3MzY7XG5jb25zdCByMzogJHt2YXJUeXBlfSA9IDEuNDIxNDEzNzQxO1xuY29uc3QgcjQ6ICR7dmFyVHlwZX0gPSAtMS40NTMxNTIwMjc7XG5jb25zdCByNTogJHt2YXJUeXBlfSA9IDEuMDYxNDA1NDI5O1xuXG5mbiBlcmZfdmYzMih2OiB2ZWM0PCR7dmFyVHlwZX0+KSAtPiB2ZWM0PCR7dmFyVHlwZX0+IHtcbiAgbGV0IGFic3YgPSBhYnModik7XG4gIGxldCB4ID0gMS4wIC8gKDEuMCArIHIwICogYWJzdik7XG4gIHJldHVybiBzaWduKHYpICogKDEuMCAtICgoKChyNSAqIHggKyByNCkgKiB4ICsgcjMpICogeCArIHIyKSAqIHggKyByMSkgKiB4ICogZXhwKC1hYnN2ICogYWJzdikpO1xufWA7XG5cbmV4cG9ydCBjb25zdCBlcmYgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdFcmYnLCAoYSkgPT4gYGVyZl92ZjMyKCR7YX0pYCwgZXJmSW1wbChkYXRhVHlwZSkpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBleHAgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdFeHAnLCAnZXhwJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGZsb29yID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnRmxvb3InLCAnZmxvb3InKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2VsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgJ0dlbHUnLFxuICAgICAgKGEpID0+IGAwLjUgKiAke2F9ICogKDEuMCArIGVyZl92ZjMyKCR7YX0gKiAwLjcwNzEwNjc4MTE4NjU0NzUpKWAsXG4gICAgICBlcmZJbXBsKGRhdGFUeXBlKSxcbiAgICApLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGxlYWt5UmVsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQWxwaGFBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICAnTGVha3lSZWx1JyxcbiAgICAgIChhKSA9PiBgc2VsZWN0KGxlYWt5X3JlbHVfYWxwaGFfICogJHthfSwgJHthfSwgJHthfSA+PSB2ZWM0PCR7ZGF0YVR5cGV9PigwLjApKWAsXG4gICAgICBgY29uc3QgbGVha3lfcmVsdV9hbHBoYV8gPSAke2RhdGFUeXBlfSgke2F0dHJpYnV0ZXMuYWxwaGF9KTtgLFxuICAgICAgYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICApLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IG5vdCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ05vdCcsIChhKSA9PiBgISR7YX1gKSk7XG59O1xuXG5leHBvcnQgY29uc3QgbmVnID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnTmVnJywgKGEpID0+IGAtJHthfWApKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWNpcHJvY2FsID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnUmVjaXByb2NhbCcsIChhKSA9PiBgMS4wLyR7YX1gKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgJ1JlbHUnLFxuICAgICAgKGEpID0+IGBzZWxlY3QodmVjNDwke2RhdGFUeXBlfT4oMC4wKSwgJHthfSwgJHthfSA+IHZlYzQ8JHtkYXRhVHlwZX0+KDAuMCkpYCxcbiAgICApLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHNpZ21vaWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdTaWdtb2lkJywgKGEpID0+IGAoMS4wIC8gKDEuMCArIGV4cCgtJHthfSkpKWApKTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgSGFyZFNpZ21vaWRBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYWxwaGE6IG51bWJlcjtcbiAgcmVhZG9ubHkgYmV0YTogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgcGFyc2VIYXJkU2lnbW9pZEF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBIYXJkU2lnbW9pZEF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KFxuICAgIGF0dHJpYnV0ZXMgYXMge1xuICAgICAgYWxwaGE6IG51bWJlcjtcbiAgICAgIGJldGE6IG51bWJlcjtcbiAgICB9LFxuICApO1xuXG5leHBvcnQgY29uc3QgaGFyZFNpZ21vaWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEhhcmRTaWdtb2lkQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgJ0hhcmRTaWdtb2lkJyxcbiAgICAgIChhKSA9PlxuICAgICAgICBgbWF4KHZlYzQ8JHtkYXRhVHlwZX0+KDAuMCksIG1pbih2ZWM0PCR7ZGF0YVR5cGV9PigxLjApLCAke2F0dHJpYnV0ZXMuYWxwaGF9ICogJHthfSArIHZlYzQ8JHtkYXRhVHlwZX0+KCR7YXR0cmlidXRlcy5iZXRhfSkpKWAsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICksXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3Qgc2luID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnU2luJywgJ3NpbicpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBzaW5oID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnU2luaCcsICdzaW5oJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHNxcnQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdTcXJ0JywgJ3NxcnQnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgdGFuID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnVGFuJywgJ3RhbicpKTtcbn07XG5cbmV4cG9ydCBjb25zdCB0YW5oRXhwcmVzc2lvbiA9IChhOiBzdHJpbmcpID0+IGBzaWduKCR7YX0pICogKDEgLSBleHAoLTIgKiBhYnMoJHthfSkpKSAvICgxICsgZXhwKC0yICogYWJzKCR7YX0pKSlgO1xuXG5leHBvcnQgY29uc3QgdGFuaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICAvLyBUT0RPOiByZXZpc2l0IGFmdGVyIGh0dHBzOi8vZ2l0aHViLmNvbS9ncHV3ZWIvZ3B1d2ViL2lzc3Vlcy80NDU4IGlzIHJlc29sdmVkXG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnVGFuaCcsIHRhbmhFeHByZXNzaW9uKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZmFzdEdlbHVJbXBsID0gKHZhclR5cGUgPSAnZjMyJykgPT4gYFxuY29uc3QgZmFzdF9nZWx1X2E6ICR7dmFyVHlwZX0gPSAwLjU7XG5jb25zdCBmYXN0X2dlbHVfYjogJHt2YXJUeXBlfSA9IDAuNzk3ODg0NTYwODAyODY1NDtcbmNvbnN0IGZhc3RfZ2VsdV9jOiAke3ZhclR5cGV9ID0gMC4wMzU2Nzc0MDgxMzYzMDAxMjU7XG5cbmZuIHRhbmhfdih2OiB2ZWM0PCR7dmFyVHlwZX0+KSAtPiB2ZWM0PCR7dmFyVHlwZX0+IHtcbiAgcmV0dXJuICR7dGFuaEV4cHJlc3Npb24oJ3YnKX07XG59XG5gO1xuXG5leHBvcnQgY29uc3QgZmFzdEdlbHVFeHByZXNzaW9uID0gKHg6IHN0cmluZykgPT5cbiAgYChmYXN0X2dlbHVfYSArIGZhc3RfZ2VsdV9hICogdGFuaF92KCR7eH0gKiAoZmFzdF9nZWx1X2MgKiAke3h9ICogJHt4fSArIGZhc3RfZ2VsdV9iKSkpICogJHt4fWA7XG5cbmV4cG9ydCBjb25zdCBmYXN0R2VsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgJ0Zhc3RHZWx1JyxcbiAgICAgIGZhc3RHZWx1RXhwcmVzc2lvbixcbiAgICAgIGZhc3RHZWx1SW1wbChkYXRhVHlwZSksXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSxcbiAgICApLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHRocmVzaG9sZGVkUmVsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQWxwaGFBdHRyaWJ1dGVzKTogbnVtYmVyID0+IHtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgICdUaHJlc2hvbGRlZFJlbHUnLFxuICAgICAgKGEpID0+IGBzZWxlY3QodmVjNDwke2RhdGFUeXBlfT4oMC4wKSwgJHthfSwgJHthfSA+IHRocmVzaG9sZGVkX3JlbHVfYWxwaGFfKWAsXG4gICAgICBgY29uc3QgdGhyZXNob2xkZWRfcmVsdV9hbHBoYV8gPSB2ZWM0PCR7ZGF0YVR5cGV9Pigke2F0dHJpYnV0ZXMuYWxwaGF9KTtgLFxuICAgICAgYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICApLFxuICApO1xuICByZXR1cm4gMDtcbn07XG5cbmV4cG9ydCBjb25zdCBsb2cgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdMb2cnLCAnbG9nJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHF1aWNrR2VsdUltcGwgPSAodmFyVHlwZTogc3RyaW5nLCBhbHBoYTogbnVtYmVyKSA9PiBgXG5jb25zdCBhbHBoYSA9IHZlYzQ8JHt2YXJUeXBlfT4oJHthbHBoYX0pO1xuY29uc3Qgb25lID0gJHt2YXJUeXBlfSgxLjApO1xuY29uc3QgemVybyA9ICR7dmFyVHlwZX0oMC4wKTtcblxuZm4gcXVpY2tfZ2VsdV9pbXBsKHg6IHZlYzQ8JHt2YXJUeXBlfT4pIC0+IHZlYzQ8JHt2YXJUeXBlfT4ge1xuICBsZXQgdiA9IHggKmFscGhhO1xuICB2YXIgeDEgOiB2ZWM0PCR7dmFyVHlwZX0+O1xuICBmb3IgKHZhciBpID0gMDsgaSA8IDQ7IGkgPSBpICsgMSkge1xuICAgIGlmICh2W2ldID49IHplcm8pIHtcbiAgICAgIHgxW2ldID0gb25lIC8gKG9uZSArIGV4cCgtdltpXSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB4MVtpXSA9IG9uZSAtIG9uZSAvIChvbmUgKyBleHAodltpXSkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4geCAqIHgxO1xufVxuYDtcblxuZXhwb3J0IGNvbnN0IHF1aWNrR2VsdUV4cHJlc3Npb24gPSAoeDogc3RyaW5nKSA9PiBgcXVpY2tfZ2VsdV9pbXBsKCR7eH0pYDtcblxuZXhwb3J0IGNvbnN0IHF1aWNrZ2VsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQWxwaGFBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGRUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICAnUXVpY2tHZWx1JyxcbiAgICAgIHF1aWNrR2VsdUV4cHJlc3Npb24sXG4gICAgICBxdWlja0dlbHVJbXBsKGRUeXBlLCBhdHRyaWJ1dGVzLmFscGhhKSxcbiAgICAgIGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSxcbiAgICApLFxuICApO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyLCB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUgfSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQgeyBlcmZJbXBsIH0gZnJvbSAnLi91bmFyeS1vcCc7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IHNob3VsZCBoYXZlIDMgZGltZW5zaW9ucycpO1xuICB9XG5cbiAgaWYgKCFbMjU2MCwgNTEyMCwgMTAyNDBdLmluY2x1ZGVzKGlucHV0c1swXS5kaW1zWzJdKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaGlkZGVuIHN0YXRlIHNob3VsZCBiZSAyNTYwLCA1MTIwIG9yIDEwMjQwJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdiaWFzIGlzIGV4cGVjdGVkIHRvIGhhdmUgMSBkaW1lbnNpb25zJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXNbMl0gIT09IGlucHV0c1sxXS5kaW1zWzBdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdsYXN0IGRpbWVuc2lvbiBvZiBpbnB1dCBhbmQgYmlhcyBhcmUgbm90IHRoZSBzYW1lJyk7XG4gIH1cbn07XG5cbmNvbnN0IGNyZWF0ZUJpYXNTcGxpdEdlbHVQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICBvdXRwdXRTaGFwZVsyXSA9IG91dHB1dFNoYXBlWzJdIC8gMjtcblxuICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcywgNCk7XG4gIGNvbnN0IGJpYXMgPSBpbnB1dFZhcmlhYmxlKCdiaWFzJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBbaW5wdXRzWzBdLmRpbXNbMl1dLCA0KTtcbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUsIDQpO1xuXG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyA0O1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICBjb25zdCBNX1NRUlQyID0gc3FydCgyLjApO1xuICBjb25zdCBoYWxmQ2hhbm5lbHMgPSAke2lucHV0c1swXS5kaW1zWzJdIC8gNCAvIDJ9dTtcblxuICAke3NoYWRlckhlbHBlci5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBiaWFzLCBvdXRwdXQpfVxuXG4gICR7ZXJmSW1wbChkYXRhVHlwZSl9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcyhvdXRwdXRTaXplKX1cbiAgICBsZXQgYmlhc0lkeCA9IGdsb2JhbF9pZHggJSBoYWxmQ2hhbm5lbHM7XG4gICAgbGV0IGJhdGNoSW5kZXggPSBnbG9iYWxfaWR4IC8gaGFsZkNoYW5uZWxzO1xuICAgIGxldCBpbnB1dE9mZnNldCA9IGJpYXNJZHggKyBiYXRjaEluZGV4ICogaGFsZkNoYW5uZWxzICogMjtcbiAgICBsZXQgdmFsdWVMZWZ0ID0gaW5wdXRbaW5wdXRPZmZzZXRdICsgYmlhc1tiaWFzSWR4XTtcbiAgICBsZXQgdmFsdWVSaWdodCA9IGlucHV0W2lucHV0T2Zmc2V0ICsgaGFsZkNoYW5uZWxzXSArIGJpYXNbYmlhc0lkeCArIGhhbGZDaGFubmVsc107XG4gICAgbGV0IGdlbHVSaWdodCA9IHZhbHVlUmlnaHQgKiAwLjUgKiAoZXJmX3ZmMzIodmFsdWVSaWdodCAvIE1fU1FSVDIpICsgMSk7XG5cbiAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZUxlZnQgKiBnZWx1UmlnaHQnKX1cbiAgfWA7XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQmlhc1NwbGl0R2VsdScsXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBiaWFzU3BsaXRHZWx1ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUJpYXNTcGxpdEdlbHVQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cykpO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgQnJvYWRjYXN0VXRpbCwgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG50eXBlIEJ1aWx0aW5GdW5jdGlvbk5hbWUgPSBzdHJpbmc7XG50eXBlIEJpbmFyeUN1c3RvbUV4cHJlc3Npb24gPSAoZXhwcmVzc2lvbkE6IHN0cmluZywgZXhwcmVzc2lvbkI6IHN0cmluZykgPT4gc3RyaW5nO1xudHlwZSBCaW5hcnlGdW5jdGlvbkNhbGwgPVxuICB8IEJ1aWx0aW5GdW5jdGlvbk5hbWVcbiAgfCBCaW5hcnlDdXN0b21FeHByZXNzaW9uXG4gIHwge1xuICAgICAgc2NhbGFyOiBCaW5hcnlDdXN0b21FeHByZXNzaW9uO1xuICAgICAgdmVjdG9yOiBCaW5hcnlDdXN0b21FeHByZXNzaW9uO1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbVNoYWRlciA9IChcbiAgc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIsXG4gIGRpbXNBOiByZWFkb25seSBudW1iZXJbXSxcbiAgZGltc0I6IHJlYWRvbmx5IG51bWJlcltdLFxuICBkaW1zT3V0cHV0OiByZWFkb25seSBudW1iZXJbXSxcbiAgdmVjdG9yaXplOiBib29sZWFuLFxuICBkb0Jyb2FkY2FzdDogYm9vbGVhbixcbiAgc2hhcmVkRGltZW5zaW9uRGl2aXNpYmxlQnk0OiBib29sZWFuLFxuICBmdW5jQ2FsbDogQmluYXJ5RnVuY3Rpb25DYWxsLFxuICB0eXBlQTogbnVtYmVyLFxuICB0eXBlQjogbnVtYmVyLFxuICB0eXBlT3V0cHV0OiBudW1iZXIsXG4gIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbj86IHN0cmluZyxcbikgPT4ge1xuICBsZXQgZXhwcmVzc2lvblNjYWxhcjogQmluYXJ5Q3VzdG9tRXhwcmVzc2lvbjtcbiAgbGV0IGV4cHJlc3Npb25WZWN0b3I6IEJpbmFyeUN1c3RvbUV4cHJlc3Npb247XG4gIGlmICh0eXBlb2YgZnVuY0NhbGwgPT09ICdzdHJpbmcnKSB7XG4gICAgZXhwcmVzc2lvblNjYWxhciA9IGV4cHJlc3Npb25WZWN0b3IgPSAoYSwgYikgPT4gYCR7ZnVuY0NhbGx9KCgke2F9KSwoJHtifSkpYDtcbiAgfSBlbHNlIGlmICh0eXBlb2YgZnVuY0NhbGwgPT09ICdmdW5jdGlvbicpIHtcbiAgICBleHByZXNzaW9uU2NhbGFyID0gZXhwcmVzc2lvblZlY3RvciA9IGZ1bmNDYWxsO1xuICB9IGVsc2Uge1xuICAgIGV4cHJlc3Npb25TY2FsYXIgPSBmdW5jQ2FsbC5zY2FsYXI7XG4gICAgZXhwcmVzc2lvblZlY3RvciA9IGZ1bmNDYWxsLnZlY3RvcjtcbiAgfVxuXG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXREYXRhJywgdHlwZU91dHB1dCwgZGltc091dHB1dC5sZW5ndGgsIDQpO1xuICBjb25zdCBhID0gaW5wdXRWYXJpYWJsZSgnYURhdGEnLCB0eXBlQSwgZGltc0EubGVuZ3RoLCA0KTtcbiAgY29uc3QgYiA9IGlucHV0VmFyaWFibGUoJ2JEYXRhJywgdHlwZUIsIGRpbXNCLmxlbmd0aCwgNCk7XG5cbiAgbGV0IGFzc2lnbm1lbnQ6IHN0cmluZztcbiAgaWYgKHZlY3Rvcml6ZSkge1xuICAgIGlmIChkb0Jyb2FkY2FzdCkge1xuICAgICAgY29uc3QgaXNBT25lRWxlbWVudCA9IFNoYXBlVXRpbC5zaXplKGRpbXNBKSA9PT0gMTtcbiAgICAgIGNvbnN0IGlzQk9uZUVsZW1lbnQgPSBTaGFwZVV0aWwuc2l6ZShkaW1zQikgPT09IDE7XG4gICAgICBjb25zdCBhTGFzdERpbURpdmlzaWJsZUJ5NCA9IGRpbXNBLmxlbmd0aCA+IDAgJiYgZGltc0FbZGltc0EubGVuZ3RoIC0gMV0gJSA0ID09PSAwO1xuICAgICAgY29uc3QgYkxhc3REaW1EaXZpc2libGVCeTQgPSBkaW1zQi5sZW5ndGggPiAwICYmIGRpbXNCW2RpbXNCLmxlbmd0aCAtIDFdICUgNCA9PT0gMDtcbiAgICAgIGlmIChpc0FPbmVFbGVtZW50IHx8IGlzQk9uZUVsZW1lbnQpIHtcbiAgICAgICAgYXNzaWdubWVudCA9IG91dHB1dC5zZXRCeU9mZnNldChcbiAgICAgICAgICAnZ2xvYmFsX2lkeCcsXG4gICAgICAgICAgZXhwcmVzc2lvblZlY3RvcihcbiAgICAgICAgICAgIGlzQU9uZUVsZW1lbnQgPyBgJHthLnR5cGUudmFsdWV9KCR7YS5nZXRCeU9mZnNldCgnMCcpfS54KWAgOiBhLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JyksXG4gICAgICAgICAgICBpc0JPbmVFbGVtZW50ID8gYCR7Yi50eXBlLnZhbHVlfSgke2IuZ2V0QnlPZmZzZXQoJzAnKX0ueClgIDogYi5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpLFxuICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhc3NpZ25tZW50ID0gYFxuICAgICAgICAgICAgbGV0IG91dHB1dEluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHggKiA0dScpfTtcbiAgICAgICAgICAgIGxldCBvZmZzZXRBID0gJHthLmJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0KCdvdXRwdXRJbmRpY2VzJywgb3V0cHV0KX07XG4gICAgICAgICAgICBsZXQgb2Zmc2V0QiA9ICR7Yi5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldCgnb3V0cHV0SW5kaWNlcycsIG91dHB1dCl9O1xuICAgICAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoXG4gICAgICAgICAgICAgICdnbG9iYWxfaWR4JyxcbiAgICAgICAgICAgICAgZXhwcmVzc2lvblZlY3RvcihcbiAgICAgICAgICAgICAgICBzaGFyZWREaW1lbnNpb25EaXZpc2libGVCeTQgfHwgYUxhc3REaW1EaXZpc2libGVCeTRcbiAgICAgICAgICAgICAgICAgID8gYS5nZXRCeU9mZnNldCgnb2Zmc2V0QSAvIDR1JylcbiAgICAgICAgICAgICAgICAgIDogYCR7YS50eXBlLnZhbHVlfSgke2EuZ2V0QnlPZmZzZXQoJ29mZnNldEEgLyA0dScpfVtvZmZzZXRBICUgNHVdKWAsXG4gICAgICAgICAgICAgICAgc2hhcmVkRGltZW5zaW9uRGl2aXNpYmxlQnk0IHx8IGJMYXN0RGltRGl2aXNpYmxlQnk0XG4gICAgICAgICAgICAgICAgICA/IGIuZ2V0QnlPZmZzZXQoJ29mZnNldEIgLyA0dScpXG4gICAgICAgICAgICAgICAgICA6IGAke2IudHlwZS52YWx1ZX0oJHtiLmdldEJ5T2Zmc2V0KCdvZmZzZXRCIC8gNHUnKX1bb2Zmc2V0QiAlIDR1XSlgLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKX1cbiAgICAgICAgICBgO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBhc3NpZ25tZW50ID0gb3V0cHV0LnNldEJ5T2Zmc2V0KFxuICAgICAgICAnZ2xvYmFsX2lkeCcsXG4gICAgICAgIGV4cHJlc3Npb25WZWN0b3IoYS5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpLCBiLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JykpLFxuICAgICAgKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFkb0Jyb2FkY2FzdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBuZWNlc3NhcnkgdG8gdXNlIHNjYWxhciBpbXBsZW1lbnRhdGlvbiBmb3IgZWxlbWVudC13aXNlIGJpbmFyeSBvcCBpbXBsZW1lbnRhdGlvbi4nKTtcbiAgICB9XG5cbiAgICBjb25zdCBzaW5nbGVBc3NpZ25tZW50ID0gKHJlc1N0cjogc3RyaW5nLCB4OiBudW1iZXIsIHR5cGVDYXN0ID0gJycpID0+IHtcbiAgICAgIGNvbnN0IGV4cHJlc3Npb25BID0gYGFEYXRhW2luZGV4QSR7eH1dW2NvbXBvbmVudEEke3h9XWA7XG4gICAgICBjb25zdCBleHByZXNzaW9uQiA9IGBiRGF0YVtpbmRleEIke3h9XVtjb21wb25lbnRCJHt4fV1gO1xuICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgIGxldCBvdXRwdXRJbmRpY2VzJHt4fSA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgZ2xvYmFsX2lkeCAqIDR1ICsgJHt4fXVgKX07XG4gICAgICAgICAgICBsZXQgb2Zmc2V0QSR7eH0gPSAke2EuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoYG91dHB1dEluZGljZXMke3h9YCwgb3V0cHV0KX07XG4gICAgICAgICAgICBsZXQgb2Zmc2V0QiR7eH0gPSAke2IuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoYG91dHB1dEluZGljZXMke3h9YCwgb3V0cHV0KX07XG4gICAgICAgICAgICBsZXQgaW5kZXhBJHt4fSA9IG9mZnNldEEke3h9IC8gNHU7XG4gICAgICAgICAgICBsZXQgaW5kZXhCJHt4fSA9IG9mZnNldEIke3h9IC8gNHU7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50QSR7eH0gPSBvZmZzZXRBJHt4fSAlIDR1O1xuICAgICAgICAgICAgbGV0IGNvbXBvbmVudEIke3h9ID0gb2Zmc2V0QiR7eH0gJSA0dTtcbiAgICAgICAgICAgICR7cmVzU3RyfVske3h9XSA9ICR7dHlwZUNhc3R9KCR7ZXhwcmVzc2lvblNjYWxhcihleHByZXNzaW9uQSwgZXhwcmVzc2lvbkIpfSk7XG4gICAgICAgICAgYDtcbiAgICB9O1xuICAgIGlmICh0eXBlT3V0cHV0ID09PSBEYXRhVHlwZS5ib29sKSB7XG4gICAgICBhc3NpZ25tZW50ID0gYFxuICAgICAgICAgICAgdmFyIGRhdGEgPSB2ZWM0PHUzMj4oMCk7XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAwLCAndTMyJyl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAxLCAndTMyJyl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAyLCAndTMyJyl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAzLCAndTMyJyl9XG4gICAgICAgICAgICBvdXRwdXREYXRhW2dsb2JhbF9pZHhdID0gZG90KHZlYzQ8dTMyPigweDEsIDB4MTAwLCAweDEwMDAwLCAweDEwMDAwMDApLCB2ZWM0PHUzMj4oZGF0YSkpO2A7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dERhdGFbZ2xvYmFsX2lkeF0nLCAwKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnb3V0cHV0RGF0YVtnbG9iYWxfaWR4XScsIDEpfVxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdvdXRwdXREYXRhW2dsb2JhbF9pZHhdJywgMil9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dERhdGFbZ2xvYmFsX2lkeF0nLCAzKX1cbiAgICAgICAgICBgO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBgXG4gICAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgndmVjX3NpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyhhLCBiLCBvdXRwdXQpfVxuXG4gICAgICAgICR7YWRkaXRpb25hbEltcGxlbWVudGF0aW9uID8/ICcnfVxuXG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy52ZWNfc2l6ZScpfVxuICAgICAgICAke2Fzc2lnbm1lbnR9XG4gICAgICB9YDtcbn07XG5cbmNvbnN0IGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbUluZm8gPSAoXG4gIG5hbWU6IHN0cmluZyxcbiAgY2FjaGVLZXk6IHN0cmluZyxcbiAgYTogVGVuc29yVmlldyxcbiAgYjogVGVuc29yVmlldyxcbiAgZnVuY0NhbGw6IEJpbmFyeUZ1bmN0aW9uQ2FsbCxcbiAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uPzogc3RyaW5nLFxuICBvdXRwdXREYXRhVHlwZTogbnVtYmVyID0gYS5kYXRhVHlwZSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgYURpbXMgPSBhLmRpbXMubWFwKE51bWJlcik7XG4gIGNvbnN0IGJEaW1zID0gYi5kaW1zLm1hcChOdW1iZXIpO1xuICBjb25zdCBpc0Jyb2FkY2FzdCA9ICFTaGFwZVV0aWwuYXJlRXF1YWwoYURpbXMsIGJEaW1zKTtcbiAgbGV0IG91dHB1dFNoYXBlID0gYURpbXM7XG4gIGxldCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUoYURpbXMpO1xuXG4gIGxldCB2ZWN0b3JpemUgPSBmYWxzZTtcbiAgbGV0IHNoYXJlZERpbWVuc2lvbkRpdmlzaWJsZUJ5NCA9IGZhbHNlO1xuXG4gIC8vIFRPRE86IGRlYWwgd2l0aCB6ZXJvLXNpemVkIHRlbnNvcnMgKGVnLiBkaW1zPVsxLDBdKVxuICBjb25zdCBjYWNoZUtleUF1eCA9IFtpc0Jyb2FkY2FzdF07XG4gIGlmIChpc0Jyb2FkY2FzdCkge1xuICAgIGNvbnN0IGNhbGN1bGF0ZWRTaGFwZSA9IEJyb2FkY2FzdFV0aWwuY2FsY1NoYXBlKGFEaW1zLCBiRGltcywgZmFsc2UpO1xuICAgIGlmICghY2FsY3VsYXRlZFNoYXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4ndCBwZXJmb3JtIGJpbmFyeSBvcCBvbiB0aGUgZ2l2ZW4gdGVuc29yc1wiKTtcbiAgICB9XG4gICAgb3V0cHV0U2hhcGUgPSBjYWxjdWxhdGVkU2hhcGUuc2xpY2UoKTtcbiAgICBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICAgIGNvbnN0IGlzQU9uZUVsZW1lbnQgPSBTaGFwZVV0aWwuc2l6ZShhRGltcykgPT09IDE7XG4gICAgY29uc3QgaXNCT25lRWxlbWVudCA9IFNoYXBlVXRpbC5zaXplKGJEaW1zKSA9PT0gMTtcbiAgICBjb25zdCBhTGFzdERpbURpdmlzaWJsZUJ5NCA9IGFEaW1zLmxlbmd0aCA+IDAgJiYgYURpbXNbYURpbXMubGVuZ3RoIC0gMV0gJSA0ID09PSAwO1xuICAgIGNvbnN0IGJMYXN0RGltRGl2aXNpYmxlQnk0ID0gYkRpbXMubGVuZ3RoID4gMCAmJiBiRGltc1tiRGltcy5sZW5ndGggLSAxXSAlIDQgPT09IDA7XG4gICAgY2FjaGVLZXlBdXgucHVzaChpc0FPbmVFbGVtZW50KTtcbiAgICBjYWNoZUtleUF1eC5wdXNoKGlzQk9uZUVsZW1lbnQpO1xuICAgIGNhY2hlS2V5QXV4LnB1c2goYUxhc3REaW1EaXZpc2libGVCeTQpO1xuICAgIGNhY2hlS2V5QXV4LnB1c2goYkxhc3REaW1EaXZpc2libGVCeTQpO1xuICAgIC8vIGNoZWNrIHdoZXRoZXIgdmVjdG9yaXplIGNhbiBiZSBlbmFibGVkXG4gICAgbGV0IHNoYXJlZERpbWVuc2lvbiA9IDE7XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCBvdXRwdXRTaGFwZS5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgZGltQSA9IGFEaW1zW2FEaW1zLmxlbmd0aCAtIGldO1xuICAgICAgY29uc3QgZGltQiA9IGJEaW1zW2JEaW1zLmxlbmd0aCAtIGldO1xuICAgICAgaWYgKGRpbUEgPT09IGRpbUIpIHtcbiAgICAgICAgc2hhcmVkRGltZW5zaW9uICo9IGRpbUE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHNoYXJlZERpbWVuc2lvbiAlIDQgPT09IDApIHtcbiAgICAgIHNoYXJlZERpbWVuc2lvbkRpdmlzaWJsZUJ5NCA9IHRydWU7XG4gICAgICB2ZWN0b3JpemUgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAoaXNBT25lRWxlbWVudCB8fCBpc0JPbmVFbGVtZW50IHx8IGFMYXN0RGltRGl2aXNpYmxlQnk0IHx8IGJMYXN0RGltRGl2aXNpYmxlQnk0KSB7XG4gICAgICB2ZWN0b3JpemUgPSB0cnVlO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBlbGVtZW50LXdpc2VcbiAgICB2ZWN0b3JpemUgPSB0cnVlO1xuICB9XG4gIGNhY2hlS2V5QXV4LnB1c2godmVjdG9yaXplKTtcblxuICByZXR1cm4ge1xuICAgIG5hbWUsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGNhY2hlS2V5ICsgY2FjaGVLZXlBdXgubWFwKCh4KSA9PiB4LnRvU3RyaW5nKCkpLmpvaW4oJ18nKSxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnLCAncmFuayddLFxuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlOiAoc2hhZGVySGVscGVyKSA9PlxuICAgICAgY3JlYXRlQmluYXJ5T3BQcm9ncmFtU2hhZGVyKFxuICAgICAgICBzaGFkZXJIZWxwZXIsXG4gICAgICAgIGFEaW1zLFxuICAgICAgICBiRGltcyxcbiAgICAgICAgb3V0cHV0U2hhcGUsXG4gICAgICAgIHZlY3Rvcml6ZSxcbiAgICAgICAgaXNCcm9hZGNhc3QsXG4gICAgICAgIHNoYXJlZERpbWVuc2lvbkRpdmlzaWJsZUJ5NCxcbiAgICAgICAgZnVuY0NhbGwsXG4gICAgICAgIGEuZGF0YVR5cGUsXG4gICAgICAgIGIuZGF0YVR5cGUsXG4gICAgICAgIG91dHB1dERhdGFUeXBlLFxuICAgICAgICBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24sXG4gICAgICApLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IG91dHB1dERhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovIC8gNCAvKiBjb21wb25lbnQgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIDQpIH0sXG4gICAgICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGFEaW1zLCBiRGltcywgb3V0cHV0U2hhcGUpLFxuICAgICAgXSxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmNvbnN0IHJ1bkJpbmFyeU9wID0gKFxuICBjb250ZXh0OiBDb21wdXRlQ29udGV4dCxcbiAgbmFtZTogc3RyaW5nLFxuICBmdW5jQ2FsbDogQmluYXJ5RnVuY3Rpb25DYWxsLFxuICBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24/OiBzdHJpbmcsXG4gIGNhY2hlS2V5Pzogc3RyaW5nLFxuICBvdXRwdXREYXRhVHlwZT86IG51bWJlcixcbik6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlQmluYXJ5T3BQcm9ncmFtSW5mbyhcbiAgICAgIG5hbWUsXG4gICAgICBjYWNoZUtleSA/PyAnJyxcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgY29udGV4dC5pbnB1dHNbMV0sXG4gICAgICBmdW5jQ2FsbCxcbiAgICAgIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbixcbiAgICAgIG91dHB1dERhdGFUeXBlLFxuICAgICksXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgYWRkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHJ1bkJpbmFyeU9wKGNvbnRleHQsICdBZGQnLCAoYSwgYikgPT4gYCR7YX0rJHtifWApO1xufTtcblxuZXhwb3J0IGNvbnN0IGRpdiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBydW5CaW5hcnlPcChjb250ZXh0LCAnRGl2JywgKGEsIGIpID0+IGAke2F9LyR7Yn1gKTtcbn07XG5cbmV4cG9ydCBjb25zdCBlcXVhbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBydW5CaW5hcnlPcChcbiAgICBjb250ZXh0LFxuICAgICdFcXVhbCcsXG4gICAgeyBzY2FsYXI6IChhLCBiKSA9PiBgdTMyKCR7YX09PSR7Yn0pYCwgdmVjdG9yOiAoYSwgYikgPT4gYHZlYzQ8dTMyPigke2F9PT0ke2J9KWAgfSxcbiAgICB1bmRlZmluZWQsXG4gICAgdW5kZWZpbmVkLFxuICAgIERhdGFUeXBlLmJvb2wsXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgbXVsID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHJ1bkJpbmFyeU9wKGNvbnRleHQsICdNdWwnLCAoYSwgYikgPT4gYCR7YX0qJHtifWApO1xufTtcblxuZXhwb3J0IGNvbnN0IHBvdyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb25zdCB0eXBlID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSwgY29udGV4dC5pbnB1dHNbMF0uZGltcykudHlwZS52YWx1ZTtcbiAgY29uc3Qgcm91bmRTdHIgPSB0eXBlID09PSAnaTMyJyA/ICdyb3VuZCcgOiAnJztcbiAgcnVuQmluYXJ5T3AoXG4gICAgY29udGV4dCxcbiAgICAnUG93JyxcbiAgICB7IHNjYWxhcjogKGEsIGIpID0+IGBwb3dfY3VzdG9tKCR7YX0sJHtifSlgLCB2ZWN0b3I6IChhLCBiKSA9PiBgcG93X3ZlY3Rvcl9jdXN0b20oJHthfSwke2J9KWAgfSxcbiAgICBgXG4gICAgZm4gcG93X2N1c3RvbShhIDogJHt0eXBlfSwgYiA6ICR7dHlwZX0pIC0+ICR7dHlwZX0ge1xuICAgICAgaWYgKGIgPT0gJHt0eXBlfSgwLjApKSB7XG4gICAgICAgIHJldHVybiAke3R5cGV9KDEuMCk7XG4gICAgICB9IGVsc2UgaWYgKGEgPCAke3R5cGV9KDAuMCkgJiYgZjMyKGIpICE9IGZsb29yKGYzMihiKSkpIHtcbiAgICAgICAgcmV0dXJuICR7dHlwZX0ocG93KGYzMihhKSwgZjMyKGIpKSk7IC8vIE5hTlxuICAgICAgfVxuICAgICAgcmV0dXJuIHNlbGVjdChzaWduKGEpLCAke3R5cGV9KDEuMCksIHJvdW5kKGYzMihhYnMoYikgJSAke3R5cGV9KDIuMCkpKSAhPSAxLjApICogJHt0eXBlfSgke3JvdW5kU3RyfShwb3coZjMyKGFicyhhKSksIGYzMihiKSkpKTtcbiAgICB9XG4gICAgZm4gcG93X3ZlY3Rvcl9jdXN0b20oYSA6IHZlYzQ8JHt0eXBlfT4sIGIgOiB2ZWM0PCR7dHlwZX0+KSAtPiB2ZWM0PCR7dHlwZX0+IHtcbiAgICAgIC8vIFRPRE86IGltcGxlbWVudCB2ZWN0b3JpemVkIHBvd1xuICAgICAgcmV0dXJuIHZlYzQ8JHt0eXBlfT4ocG93X2N1c3RvbShhLngsIGIueCksIHBvd19jdXN0b20oYS55LCBiLnkpLCBwb3dfY3VzdG9tKGEueiwgYi56KSwgcG93X2N1c3RvbShhLncsIGIudykpO1xuICAgIH1cbiAgICAgIGAsXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3Qgc3ViID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHJ1bkJpbmFyeU9wKGNvbnRleHQsICdTdWInLCAoYSwgYikgPT4gYCR7YX0tJHtifWApO1xufTtcblxuZXhwb3J0IGNvbnN0IGdyZWF0ZXIgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgcnVuQmluYXJ5T3AoXG4gICAgY29udGV4dCxcbiAgICAnR3JlYXRlcicsXG4gICAgeyBzY2FsYXI6IChhLCBiKSA9PiBgdTMyKCR7YX0+JHtifSlgLCB2ZWN0b3I6IChhLCBiKSA9PiBgdmVjNDx1MzI+KCR7YX0+JHtifSlgIH0sXG4gICAgdW5kZWZpbmVkLFxuICAgIHVuZGVmaW5lZCxcbiAgICBEYXRhVHlwZS5ib29sLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGxlc3MgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgcnVuQmluYXJ5T3AoXG4gICAgY29udGV4dCxcbiAgICAnTGVzcycsXG4gICAgeyBzY2FsYXI6IChhLCBiKSA9PiBgdTMyKCR7YX08JHtifSlgLCB2ZWN0b3I6IChhLCBiKSA9PiBgdmVjNDx1MzI+KCR7YX08JHtifSlgIH0sXG4gICAgdW5kZWZpbmVkLFxuICAgIHVuZGVmaW5lZCxcbiAgICBEYXRhVHlwZS5ib29sLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGdyZWF0ZXJPckVxdWFsID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHJ1bkJpbmFyeU9wKFxuICAgIGNvbnRleHQsXG4gICAgJ0dyZWF0ZXJPckVxdWFsJyxcbiAgICB7IHNjYWxhcjogKGEsIGIpID0+IGB1MzIoJHthfT49JHtifSlgLCB2ZWN0b3I6IChhLCBiKSA9PiBgdmVjNDx1MzI+KCR7YX0+PSR7Yn0pYCB9LFxuICAgIHVuZGVmaW5lZCxcbiAgICB1bmRlZmluZWQsXG4gICAgRGF0YVR5cGUuYm9vbCxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBsZXNzT3JFcXVhbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBydW5CaW5hcnlPcChcbiAgICBjb250ZXh0LFxuICAgICdMZXNzT3JFcXVhbCcsXG4gICAgeyBzY2FsYXI6IChhLCBiKSA9PiBgdTMyKCR7YX08PSR7Yn0pYCwgdmVjdG9yOiAoYSwgYikgPT4gYHZlYzQ8dTMyPigke2F9PD0ke2J9KWAgfSxcbiAgICB1bmRlZmluZWQsXG4gICAgdW5kZWZpbmVkLFxuICAgIERhdGFUeXBlLmJvb2wsXG4gICk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgSW5kaWNlc0hlbHBlciwgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBDb25jYXRBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXhpczogbnVtYmVyO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXhpczogbnVtYmVyKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd0b28gZmV3IGlucHV0cycpO1xuICB9XG4gIGNvbnN0IHJlZmVyZW5jZUluZGV4ID0gMDtcbiAgY29uc3QgcmVmZXJlbmNlSW5wdXQgPSBpbnB1dHNbcmVmZXJlbmNlSW5kZXhdO1xuICBjb25zdCBpbnB1dFR5cGUgPSByZWZlcmVuY2VJbnB1dC5kYXRhVHlwZTtcbiAgY29uc3QgaW5wdXRSYW5rID0gcmVmZXJlbmNlSW5wdXQuZGltcy5sZW5ndGg7XG4gIGlucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4ge1xuICAgIGlmIChpID09PSByZWZlcmVuY2VJbmRleCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBtYWtlIHN1cmUgdHlwZXMgb2YgYWxsIGlucHV0cyBtYXRjaFxuICAgIGlmIChpbnB1dC5kYXRhVHlwZSAhPT0gaW5wdXRUeXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IHRlbnNvcnMgc2hvdWxkIGJlIG9uZSB0eXBlJyk7XG4gICAgfVxuICAgIC8vIG1ha2Ugc3VyZSB0aGUgZGltZW5zaW9uYWxpdHkgb2YgYWxsIGlucHV0cyBhcmUgdGhlIHNhbWVcbiAgICBpZiAoaW5wdXQuZGltcy5sZW5ndGggIT09IGlucHV0UmFuaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCB0ZW5zb3JzIHNob3VsZCBoYXZlIHRoZSBzYW1lIHNoYXBlJyk7XG4gICAgfVxuICAgIGlucHV0LmRpbXMuZm9yRWFjaCgoZGltLCBpKSA9PiB7XG4gICAgICBpZiAoaSAhPT0gYXhpcyAmJiBkaW0gIT09IHJlZmVyZW5jZUlucHV0LmRpbXNbaV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdub24gY29uY2F0IGRpbWVuc2lvbnMgbXVzdCBtYXRjaCcpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn07XG5cbmNvbnN0IGNhbGN1bGF0ZUlucHV0SW5kZXhJbXBsID0gKG51bWJlck9mVGVuc29yczogbnVtYmVyLCBzaXplSW5Db25jYXRBeGlzU3RyOiBzdHJpbmcpOiBzdHJpbmcgPT4gYFxuICBmbiBjYWxjdWxhdGVJbnB1dEluZGV4KGluZGV4OiB1MzIpIC0+IHUzMiB7XG4gICAgbGV0IHNpemVJbkNvbmNhdEF4aXMgPSBhcnJheTx1MzIsICR7bnVtYmVyT2ZUZW5zb3JzfXU+KCR7c2l6ZUluQ29uY2F0QXhpc1N0cn0pO1xuICAgIGZvciAodmFyIGk6IHUzMiA9IDB1OyBpIDwgJHtudW1iZXJPZlRlbnNvcnN9OyBpICs9IDF1ICkge1xuICAgICAgaWYgKGluZGV4IDwgc2l6ZUluQ29uY2F0QXhpc1tpXSkge1xuICAgICAgICByZXR1cm4gaTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICR7bnVtYmVyT2ZUZW5zb3JzfXU7XG4gIH1gO1xuXG5jb25zdCBhc3NpZ25PdXRwdXREYXRhID0gKGlucHV0czogcmVhZG9ubHkgSW5kaWNlc0hlbHBlcltdLCBvdXRwdXQ6IEluZGljZXNIZWxwZXIpID0+IHtcbiAgY29uc3QgbnVtYmVyT2ZUZW5zb3JzID0gaW5wdXRzLmxlbmd0aDtcblxuICBjb25zdCBjb2RlTGluZXM6IHN0cmluZ1tdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZUZW5zb3JzOyArK2kpIHtcbiAgICBjb25zdCByZXR1cm5TbmlwcGV0ID0gb3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgaW5wdXRzW2ldLmdldEJ5SW5kaWNlcygnaW5kaWNlcycpKTtcbiAgICBpZiAobnVtYmVyT2ZUZW5zb3JzID09PSAxKSB7XG4gICAgICBjb2RlTGluZXMucHVzaChyZXR1cm5TbmlwcGV0KTtcbiAgICB9IGVsc2UgaWYgKGkgPT09IDApIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKGBpZiAoaW5wdXRJbmRleCA9PSAke2l9dSkgeyAke3JldHVyblNuaXBwZXR9IH1gKTtcbiAgICB9IGVsc2UgaWYgKGkgPT09IG51bWJlck9mVGVuc29ycyAtIDEpIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKGBlbHNlIHsgJHtyZXR1cm5TbmlwcGV0fSB9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKGBlbHNlIGlmIChpbnB1dEluZGV4ID09ICR7aX0pIHsgJHtyZXR1cm5TbmlwcGV0fSB9YCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBjb2RlTGluZXMuam9pbignXFxuJyk7XG59O1xuXG5jb25zdCBjcmVhdGVDb25jYXRQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGFkanVzdGVkQXhpczogbnVtYmVyLFxuICBvdXRwdXRTaGFwZTogbnVtYmVyW10sXG4gIGRhdGFUeXBlOiBEYXRhVHlwZSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcblxuICBjb25zdCBzaXplSW5Db25jYXRBeGlzID0gbmV3IEFycmF5PG51bWJlcj4oaW5wdXRzLmxlbmd0aCk7XG4gIGNvbnN0IGlucHV0VmFycyA9IG5ldyBBcnJheTxJbmRpY2VzSGVscGVyPihpbnB1dHMubGVuZ3RoKTtcblxuICBsZXQgcHJldmlvdXNTdW0gPSAwO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFtdO1xuICBjb25zdCBpbnB1dFJhbmtzID0gW107XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFt7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9XTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dHMubGVuZ3RoOyArK2kpIHtcbiAgICBwcmV2aW91c1N1bSArPSBpbnB1dHNbaV0uZGltc1thZGp1c3RlZEF4aXNdO1xuICAgIHNpemVJbkNvbmNhdEF4aXNbaV0gPSBwcmV2aW91c1N1bTtcbiAgICBpbnB1dFJhbmtzLnB1c2goaW5wdXRzW2ldLmRpbXMubGVuZ3RoKTtcbiAgICBpbnB1dFZhcnNbaV0gPSBpbnB1dFZhcmlhYmxlKGBpbnB1dCR7aX1gLCBkYXRhVHlwZSwgaW5wdXRSYW5rc1tpXSk7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgncmFuaycpO1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzaXplSW5Db25jYXRBeGlzW2ldIH0pO1xuICB9XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRzLmxlbmd0aDsgKytpKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzW2ldLmRpbXMpKTtcbiAgfVxuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRwdXRTaGFwZSkpO1xuXG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBkYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgY29uc3QgaW5kaWNlc0F4aXMgPSBvdXRwdXQuaW5kaWNlc0dldCgnaW5kaWNlcycsIGFkanVzdGVkQXhpcyk7XG4gIGNvbnN0IHNpemVJbkNvbmNhdEF4aXNTdHIgPSBBcnJheS5mcm9tKEFycmF5KHNpemVJbkNvbmNhdEF4aXMubGVuZ3RoKS5rZXlzKCkpXG4gICAgLm1hcCgoaSkgPT4gYHVuaWZvcm1zLnNpemVJbkNvbmNhdEF4aXMke2l9YClcbiAgICAuam9pbignLCcpO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcblxuICAkeygoKSA9PiB7XG4gICAgc2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0U2l6ZScsICd1MzInKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0cy5sZW5ndGg7IGkrKykge1xuICAgICAgc2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybShgc2l6ZUluQ29uY2F0QXhpcyR7aX1gLCAndTMyJyk7XG4gICAgfVxuICAgIHJldHVybiBzaGFkZXJIZWxwZXIuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcnMsIG91dHB1dCk7XG4gIH0pKCl9XG5cbiAgJHtjYWxjdWxhdGVJbnB1dEluZGV4SW1wbChzaXplSW5Db25jYXRBeGlzLmxlbmd0aCwgc2l6ZUluQ29uY2F0QXhpc1N0cil9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0U2l6ZScpfVxuXG4gICAgdmFyIGluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG5cbiAgICBsZXQgaW5wdXRJbmRleCA9IGNhbGN1bGF0ZUlucHV0SW5kZXgoJHtpbmRpY2VzQXhpc30pO1xuICAgIGlmIChpbnB1dEluZGV4ICE9IDB1KSB7XG4gICAgICBsZXQgc2l6ZUluQ29uY2F0QXhpcyA9IGFycmF5PHUzMiwgJHtzaXplSW5Db25jYXRBeGlzLmxlbmd0aH11Pigke3NpemVJbkNvbmNhdEF4aXNTdHJ9KTtcbiAgICAgICR7aW5kaWNlc0F4aXN9IC09IHNpemVJbkNvbmNhdEF4aXNbaW5wdXRJbmRleCAtIDF1XTtcbiAgICB9XG5cbiAgICAke2Fzc2lnbk91dHB1dERhdGEoaW5wdXRWYXJzLCBvdXRwdXQpfVxuICB9YDtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdDb25jYXQnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2FkanVzdGVkQXhpc31gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGNvbmNhdCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQ29uY2F0QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBpbnB1dHMgPSBjb250ZXh0LmlucHV0cztcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBhZGp1c3RlZEF4aXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhpcyhhdHRyaWJ1dGVzLmF4aXMsIGlucHV0U2hhcGUubGVuZ3RoKTtcbiAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzLCBhZGp1c3RlZEF4aXMpO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoKTtcbiAgb3V0cHV0U2hhcGVbYWRqdXN0ZWRBeGlzXSA9IGlucHV0cy5yZWR1Y2UoXG4gICAgKHN1bSwgaW5wdXQpID0+IHN1bSArIChpbnB1dC5kaW1zLmxlbmd0aCA+IGFkanVzdGVkQXhpcyA/IGlucHV0LmRpbXNbYWRqdXN0ZWRBeGlzXSA6IDApLFxuICAgIDAsXG4gICk7XG4gIC8vIDAgbGVuZ3RoIHRlbnNvcnMgYXJlIHZhbGlkIGZvciBjb25jYXQsIHJlbW92ZSB0aGVtXG4gIGNvbnN0IG5vbkVtcHR5SW5wdXRzID0gaW5wdXRzLmZpbHRlcigoaW5wdXQpID0+IFNoYXBlVXRpbC5zaXplKGlucHV0LmRpbXMpID4gMCk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVDb25jYXRQcm9ncmFtSW5mbyhub25FbXB0eUlucHV0cywgYWRqdXN0ZWRBeGlzLCBvdXRwdXRTaGFwZSwgaW5wdXRzWzBdLmRhdGFUeXBlKSwge1xuICAgIGlucHV0czogbm9uRW1wdHlJbnB1dHMsXG4gIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQ29uY2F0QXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IENvbmNhdEF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgYXhpczogYXR0cmlidXRlcy5heGlzIGFzIG51bWJlciB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBNQVhfQ0xJUCwgTUlOX0NMSVAgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBVbmlmb3Jtc0FycmF5VHlwZSB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzIHtcbiAgcmVhZG9ubHkgYWN0aXZhdGlvbjogc3RyaW5nO1xuICByZWFkb25seSBjbGlwTWluPzogbnVtYmVyO1xuICByZWFkb25seSBjbGlwTWF4PzogbnVtYmVyO1xuICByZWFkb25seSBhbHBoYT86IG51bWJlcjtcbiAgcmVhZG9ubHkgYmV0YT86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGdldEFjdGl2YXRpb25TbmlwcGV0ID0gKFxuICBhdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLFxuICB2YWx1ZVR5cGU6IHN0cmluZyxcbiAgYmFzZVR5cGUgPSAnZjMyJyxcbik6IHN0cmluZyA9PiB7XG4gIHN3aXRjaCAoYXR0cmlidXRlcy5hY3RpdmF0aW9uKSB7XG4gICAgY2FzZSAnUmVsdSc6XG4gICAgICByZXR1cm4gYHZhbHVlID0gbWF4KHZhbHVlLCAke3ZhbHVlVHlwZX0oMC4wKSk7YDtcbiAgICBjYXNlICdTaWdtb2lkJzpcbiAgICAgIHJldHVybiBgdmFsdWUgPSAoJHt2YWx1ZVR5cGV9KDEuMCkgLyAoJHt2YWx1ZVR5cGV9KDEuMCkgKyBleHAoLXZhbHVlKSkpO2A7XG4gICAgY2FzZSAnQ2xpcCc6XG4gICAgICByZXR1cm4gYHZhbHVlID0gY2xhbXAodmFsdWUsICR7dmFsdWVUeXBlfSgke2Jhc2VUeXBlfSh1bmlmb3Jtcy5jbGlwX21pbikpLCAke3ZhbHVlVHlwZX0oJHtcbiAgICAgICAgYmFzZVR5cGVcbiAgICAgIH0odW5pZm9ybXMuY2xpcF9tYXgpKSk7YDtcbiAgICBjYXNlICdIYXJkU2lnbW9pZCc6XG4gICAgICByZXR1cm4gYHZhbHVlID0gbWF4KCR7dmFsdWVUeXBlfSgwLjApLCBtaW4oJHt2YWx1ZVR5cGV9KDEuMCksICR7YmFzZVR5cGV9KHVuaWZvcm1zLmFscGhhKSAqIHZhbHVlICsgJHtcbiAgICAgICAgYmFzZVR5cGVcbiAgICAgIH0odW5pZm9ybXMuYmV0YSkpKTtgO1xuICAgIGNhc2UgJ0xlYWt5UmVsdSc6XG4gICAgICByZXR1cm4gYHZhbHVlID0gc2VsZWN0KCR7YmFzZVR5cGV9KHVuaWZvcm1zLmFscGhhKSAqIHZhbHVlLCB2YWx1ZSwgdmFsdWUgPj0gJHt2YWx1ZVR5cGV9KDAuMCkpO2A7XG4gICAgY2FzZSAnVGFuaCc6XG4gICAgICByZXR1cm4gYGxldCBlMnggPSBleHAoLTIuMCAqIGFicyh2YWx1ZSkpO1xuICAgICAgICAgICAgICB2YWx1ZSA9IHNpZ24odmFsdWUpICogKDEuMCAtIGUyeCkgLyAoMS4wICsgZTJ4KTtcbiAgICAgICAgYDtcbiAgICBjYXNlICcnOlxuICAgICAgcmV0dXJuICcnO1xuICAgIC8vIFRPRE86IGFkZGluZyBvdGhlciBhY3RpdmF0aW9ucyB0aGF0IGNhbiBiZSBmdXNlZC5cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBhY3RpdmF0aW9uICR7YXR0cmlidXRlcy5hY3RpdmF0aW9ufWApO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YSA9IChcbiAgYXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyxcbiAgcHJvZ3JhbVVuaWZvcm06IFByb2dyYW1Vbmlmb3JtW10sXG4pID0+IHtcbiAgaWYgKGF0dHJpYnV0ZXMuYWN0aXZhdGlvbiA9PT0gJ0NsaXAnKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm0ucHVzaChcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMuY2xpcE1heCEgfSxcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMuY2xpcE1pbiEgfSxcbiAgICApO1xuICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMuYWN0aXZhdGlvbiA9PT0gJ0hhcmRTaWdtb2lkJykge1xuICAgIHByb2dyYW1Vbmlmb3JtLnB1c2goXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhdHRyaWJ1dGVzLmFscGhhISB9LFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogYXR0cmlidXRlcy5iZXRhISB9LFxuICAgICk7XG4gIH0gZWxzZSBpZiAoYXR0cmlidXRlcy5hY3RpdmF0aW9uID09PSAnTGVha3lSZWx1Jykge1xuICAgIHByb2dyYW1Vbmlmb3JtLnB1c2goeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogYXR0cmlidXRlcy5hbHBoYSEgfSk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMgPSAoYXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcywgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlKSA9PiB7XG4gIGlmIChhdHRyaWJ1dGVzLmFjdGl2YXRpb24gPT09ICdDbGlwJykge1xuICAgIHVuaWZvcm1zLnB1c2goeyBuYW1lOiAnY2xpcF9tYXgnLCB0eXBlOiAnZjMyJyB9LCB7IG5hbWU6ICdjbGlwX21pbicsIHR5cGU6ICdmMzInIH0pO1xuICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMuYWN0aXZhdGlvbiA9PT0gJ0hhcmRTaWdtb2lkJykge1xuICAgIHVuaWZvcm1zLnB1c2goeyBuYW1lOiAnYWxwaGEnLCB0eXBlOiAnZjMyJyB9LCB7IG5hbWU6ICdiZXRhJywgdHlwZTogJ2YzMicgfSk7XG4gIH0gZWxzZSBpZiAoYXR0cmlidXRlcy5hY3RpdmF0aW9uID09PSAnTGVha3lSZWx1Jykge1xuICAgIHVuaWZvcm1zLnB1c2goeyBuYW1lOiAnYWxwaGEnLCB0eXBlOiAnZjMyJyB9KTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyA9IChcbiAgYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQsXG4pOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgYWN0aXZhdGlvbiA9IChhdHRyaWJ1dGVzPy5hY3RpdmF0aW9uIGFzIHN0cmluZykgfHwgJyc7XG4gIGlmIChhY3RpdmF0aW9uID09PSAnSGFyZFNpZ21vaWQnKSB7XG4gICAgY29uc3QgW2FscGhhLCBiZXRhXSA9IChhdHRyaWJ1dGVzPy5hY3RpdmF0aW9uX3BhcmFtcyBhcyBbbnVtYmVyLCBudW1iZXJdKSB8fCBbMC4yLCAwLjVdO1xuICAgIHJldHVybiB7IGFjdGl2YXRpb24sIGFscGhhLCBiZXRhIH07XG4gIH0gZWxzZSBpZiAoYWN0aXZhdGlvbiA9PT0gJ0NsaXAnKSB7XG4gICAgY29uc3QgW2NsaXBNaW4sIGNsaXBNYXhdID0gKGF0dHJpYnV0ZXM/LmFjdGl2YXRpb25fcGFyYW1zIGFzIFtudW1iZXIsIG51bWJlcl0pIHx8IFtNSU5fQ0xJUCwgTUFYX0NMSVBdO1xuICAgIHJldHVybiB7IGFjdGl2YXRpb24sIGNsaXBNYXgsIGNsaXBNaW4gfTtcbiAgfSBlbHNlIGlmIChhY3RpdmF0aW9uID09PSAnTGVha3lSZWx1Jykge1xuICAgIGNvbnN0IFthbHBoYV0gPSAoYXR0cmlidXRlcz8uYWN0aXZhdGlvbl9wYXJhbXMgYXMgW251bWJlcl0pIHx8IFswLjAxXTtcbiAgICByZXR1cm4geyBhY3RpdmF0aW9uLCBhbHBoYSB9O1xuICB9XG4gIHJldHVybiB7IGFjdGl2YXRpb24gfTtcbn07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG4vLyBzYW1wbGVkIGZyb20gW0B0ZW5zb3JmbG93L3RmanNdIHRmanMtYmFja2VuZC13ZWJncHUvc3JjL2FjdGl2YXRpb25fdXRpbC50c1xuLy9cbi8vIG1vZGlmaWVkIHRvIGZpdCB0aGUgbmVlZHMgb2YgdGhlIHByb2plY3RcblxuZXhwb3J0IGNvbnN0IHR5cGVTbmlwcGV0ID0gKGNvbXBvbmVudDogbnVtYmVyLCBkYXRhVHlwZTogc3RyaW5nKSA9PiB7XG4gIHN3aXRjaCAoY29tcG9uZW50KSB7XG4gICAgY2FzZSAxOlxuICAgICAgcmV0dXJuIGRhdGFUeXBlO1xuICAgIGNhc2UgMjpcbiAgICAgIHJldHVybiBgdmVjMjwke2RhdGFUeXBlfT5gO1xuICAgIGNhc2UgMzpcbiAgICAgIHJldHVybiBgdmVjMzwke2RhdGFUeXBlfT5gO1xuICAgIGNhc2UgNDpcbiAgICAgIHJldHVybiBgdmVjNDwke2RhdGFUeXBlfT5gO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29tcG9uZW50fS1jb21wb25lbnQgaXMgbm90IHN1cHBvcnRlZC5gKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGJpYXNTbmlwcGV0ID0gKGhhc0JpYXM6IGJvb2xlYW4pOiBzdHJpbmcgPT4gYFxuICAgICAgJHtoYXNCaWFzID8gJ3ZhbHVlID0gdmFsdWUgKyBnZXRCaWFzQnlPdXRwdXRDb29yZHMoY29vcmRzKTsnIDogJyd9XG4gICAgICBgO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuLy8gc2FtcGxlZCBmcm9tIFtAdGVuc29yZmxvdy90ZmpzXSB0ZmpzLWNvcmUvc3JjL29wcy9jb252X3V0aWwudHNcbi8vXG4vLyBtb2RpZmllZCB0byBmaXQgdGhlIG5lZWRzIG9mIHRoZSBwcm9qZWN0XG5cbmV4cG9ydCBjb25zdCB1dGlsRnVuY3Rpb25zID0gKHN0cmlkZVN0cjogc3RyaW5nKSA9PiBgXG5mbiBnZXRJbmRleEZyb21Db29yZHM0RChjb29yZHMgOiB2ZWM0PGkzMj4sIHNoYXBlIDogdmVjNDxpMzI+KSAtPiBpMzIge1xuICByZXR1cm4gZG90KGNvb3JkcywgdmVjNDxpMzI+KFxuICAgICAgc2hhcGUueSAqIHNoYXBlLnogKiBzaGFwZS53LCBzaGFwZS56ICogc2hhcGUudywgc2hhcGUudywgMSkpO1xufVxuZm4gZ2V0T3V0cHV0SW5kZXhGcm9tQ29vcmRzKGNvb3JkcyA6IHZlYzQ8aTMyPikgLT4gaTMyIHtcbiAgcmV0dXJuIGRvdChjb29yZHMsIHZlYzQ8aTMyPihcbiAgICBpMzIoJHtzdHJpZGVTdHJ9LngpLCBpMzIoJHtzdHJpZGVTdHJ9LnkpLCBpMzIoJHtzdHJpZGVTdHJ9LnopLCAxKSk7XG59XG5gO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldEVsZW1lbnRBdCxcbiAgZ2V0TWF4Q29tcG9uZW50cyxcbiAgSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRWYXJpYWJsZSxcbiAgaW50ZXJuYWxWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuaW1wb3J0IHtcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zLFxuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhLFxuICBnZXRBY3RpdmF0aW9uU25pcHBldCxcbiAgSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyxcbn0gZnJvbSAnLi9mdXNlLXV0aWxzJztcblxuLy8gSGVscGVyIHRoYXQgY29udmVydCBvdXRwdXQgYmF0Y2ggaW5kaWNlcyB0byBpbnB1dCBiYXRjaCBpbmRpY2VzIHVzaW5nIG9ubHkgdGhlIHJhbmsgYW5kXG4vLyB0aGUgc2hhcGUgaW5mb3JtYXRpb24gaW4gdW5pZm9ybVxuZXhwb3J0IGNvbnN0IGNvbnZlcnRPdXRwdXRCYXRjaEluZGljZXNUb0lucHV0QmF0Y2hJbmRpY2VzID0gKFxuICB0YXJnZXRJbmRpY2VzTmFtZTogc3RyaW5nLFxuICBpbnB1dFZhcmlhYmxlOiBJbmRpY2VzSGVscGVyLFxuICBpbnB1dEJhdGNoUmFuazogbnVtYmVyLFxuICBvdXRwdXRCYXRjaFJhbms6IG51bWJlcixcbiAgYmF0Y2hJbmRpY2VzTmFtZTogc3RyaW5nLFxuKSA9PiB7XG4gIC8vIEFzc3VtZSBvdXRwdXRCYXRjaFJhbmsgPj0gaW5wdXRCYXRjaFJhbmssIHRoZSBmaXJzdCBvdXRwdXRCYXRjaFJhbmsgLSBpbnB1dEJhdGNoUmFuayBvZlxuICAvLyBvdXRwdXRCYXRjaFJhbmsgc2hvdWxkIGJlIGlnbm9yZWQuXG4gIGNvbnN0IGV4dGVuZGluZ0lucHV0UmFuayA9IG91dHB1dEJhdGNoUmFuayAtIGlucHV0QmF0Y2hSYW5rO1xuICByZXR1cm4gYFxuICAgICAgJHtBcnJheS5mcm9tKHsgbGVuZ3RoOiBpbnB1dEJhdGNoUmFuayB9KVxuICAgICAgICAubWFwKFxuICAgICAgICAgIChfLCBpKSA9PiBgXG4gICAgICBpZiAoJHtnZXRFbGVtZW50QXQoaW5wdXRWYXJpYWJsZS5zaGFwZSwgaSwgaW5wdXRWYXJpYWJsZS5yYW5rKX0gIT0gMSkge1xuICAgICAgICAke2lucHV0VmFyaWFibGUuaW5kaWNlc1NldCh0YXJnZXRJbmRpY2VzTmFtZSwgaSwgZ2V0RWxlbWVudEF0KGJhdGNoSW5kaWNlc05hbWUsIGkgKyBleHRlbmRpbmdJbnB1dFJhbmssIG91dHB1dEJhdGNoUmFuaykpfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHtpbnB1dFZhcmlhYmxlLmluZGljZXNTZXQodGFyZ2V0SW5kaWNlc05hbWUsIGksIDApfVxuICAgICAgfWAsXG4gICAgICAgIClcbiAgICAgICAgLmpvaW4oJycpfVxuYDtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVOYWl2ZU1hdG11bFByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYWN0aXZhdGlvbkF0dHJpYnV0ZXM6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgcmVzaGFwZWRPdXRwdXRTaGFwZT86IHJlYWRvbmx5IG51bWJlcltdLFxuICBpc0NoYW5uZWxzTGFzdCA9IGZhbHNlIC8qIG9ubHkgdXNlZCBmb3IgY29udjJkQnlNYXRNdWwqLyxcbiAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgYVNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGJTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuXG4gIGNvbnN0IE0gPSBhU2hhcGVbYVNoYXBlLmxlbmd0aCAtIDJdO1xuICBjb25zdCBOID0gYlNoYXBlW2JTaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3QgSyA9IGFTaGFwZVthU2hhcGUubGVuZ3RoIC0gMV07XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKE4pO1xuICBjb25zdCBhQ29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoSyk7XG4gIGNvbnN0IG91dHB1dE51bWJlciA9IGdldE1heENvbXBvbmVudHMoTSk7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyBjb21wb25lbnRzIC8gb3V0cHV0TnVtYmVyO1xuICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA+IDI7XG4gIGNvbnN0IG91dGVyRGltcyA9IHJlc2hhcGVkT3V0cHV0U2hhcGUgPyByZXNoYXBlZE91dHB1dFNoYXBlLnNsaWNlKDAsIC0yKSA6IG91dHB1dFNoYXBlLnNsaWNlKDAsIC0yKTtcbiAgY29uc3QgYmF0Y2hTaXplID0gU2hhcGVVdGlsLnNpemUob3V0ZXJEaW1zKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGVJblNoYWRlciA9IFtiYXRjaFNpemUsIE0sIE5dO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBNIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE4gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogSyB9LFxuICBdO1xuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhKGFjdGl2YXRpb25BdHRyaWJ1dGVzLCBwcm9ncmFtVW5pZm9ybXMpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRlckRpbXMsIGFTaGFwZSwgYlNoYXBlKSk7XG4gIGlmIChoYXNCaWFzKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzJdLmRpbXMpKTtcbiAgfVxuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRwdXRTaGFwZUluU2hhZGVyKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgYmF0Y2hEaW1zID0gaW50ZXJuYWxWYXJpYWJsZSgnYmF0Y2hfZGltcycsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0ZXJEaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgYSA9IGlucHV0VmFyaWFibGUoJ2EnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGFTaGFwZS5sZW5ndGgsIGFDb21wb25lbnRzKTtcbiAgICBjb25zdCBiID0gaW5wdXRWYXJpYWJsZSgnYicsIGlucHV0c1sxXS5kYXRhVHlwZSwgYlNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGVJblNoYWRlci5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGJhc2VUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKG91dHB1dC50eXBlLnRlbnNvcik7XG4gICAgY29uc3QgYXBwbHlBY3RpdmF0aW9uID0gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYWN0aXZhdGlvbkF0dHJpYnV0ZXMsIG91dHB1dC50eXBlLnZhbHVlLCBiYXNlVHlwZSk7XG4gICAgY29uc3QgaW5wdXRWYXJpYWJsZXMgPSBbYSwgYl07XG4gICAgbGV0IHByb2Nlc3NCaWFzID0gJyc7XG4gICAgaWYgKGhhc0JpYXMpIHtcbiAgICAgIGNvbnN0IGJpYXNDb21wb25lbnRzID0gaXNDaGFubmVsc0xhc3QgPyBjb21wb25lbnRzIDogMTtcbiAgICAgIGlucHV0VmFyaWFibGVzLnB1c2goaW5wdXRWYXJpYWJsZSgnYmlhcycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoLCBiaWFzQ29tcG9uZW50cykpO1xuICAgICAgcHJvY2Vzc0JpYXMgPSBgJHtcbiAgICAgICAgaXNDaGFubmVsc0xhc3QgPyBgdmFsdWUgKz0gYmlhc1tjb2wgLyAke2JpYXNDb21wb25lbnRzfV07YCA6IGB2YWx1ZSArPSAke291dHB1dC50eXBlLnZhbHVlfShiaWFzW3JvdyArIGldKTtgXG4gICAgICB9YDtcbiAgICB9XG5cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdNJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ04nLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnSycsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMoYWN0aXZhdGlvbkF0dHJpYnV0ZXMsIHVuaWZvcm1zKTtcblxuICAgIGNvbnN0IGNhbGNSZXN1bHQgPSAoKTogc3RyaW5nID0+IHtcbiAgICAgIGxldCBjYWxjU3RyID0gYHZhciBhX2RhdGE6ICR7YS50eXBlLnZhbHVlfTtgO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhQ29tcG9uZW50czsgaSsrKSB7XG4gICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgICAgICBsZXQgYl9kYXRhJHtpfSA9IGJbKGJfb2Zmc2V0ICsgKGsgKyAke2l9KSAqIHVuaWZvcm1zLk4gKyBjb2wpIC8gJHtjb21wb25lbnRzfV07YDtcbiAgICAgIH1cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0TnVtYmVyOyBpKyspIHtcbiAgICAgICAgY2FsY1N0ciArPSBgYV9kYXRhID0gYVsoYV9vZmZzZXQgKyAocm93ICsgJHtpfSkgKiB1bmlmb3Jtcy5LICsgaykgLyAke2FDb21wb25lbnRzfV07YDtcblxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGFDb21wb25lbnRzOyBqKyspIHtcbiAgICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICAgIHZhbHVlc1ske2l9XSA9IGZtYSgke2IudHlwZS52YWx1ZX0oYV9kYXRhJHthQ29tcG9uZW50cyA9PT0gMSA/ICcnIDogYFske2p9XWB9KSwgYl9kYXRhJHtqfSwgdmFsdWVzWyR7aX1dKTtcXG5gO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gY2FsY1N0cjtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGBcbiAgJHtzaGFkZXJIZWxwZXJcbiAgICAucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcylcbiAgICAucmVnaXN0ZXJJbnRlcm5hbFZhcmlhYmxlcyhiYXRjaERpbXMpXG4gICAgLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgbGV0IGNvbCA9IChnbG9iYWxfaWR4ICUgKHVuaWZvcm1zLk4gLyAke2NvbXBvbmVudHN9KSkgKiAke2NvbXBvbmVudHN9O1xuICAgIHZhciBpbmRleDEgPSBnbG9iYWxfaWR4IC8gKHVuaWZvcm1zLk4gLyAke2NvbXBvbmVudHN9KTtcbiAgICBsZXQgc3RyaWRlMSA9IHVuaWZvcm1zLk0gLyAke291dHB1dE51bWJlcn07XG4gICAgbGV0IHJvdyA9IChpbmRleDEgJSBzdHJpZGUxKSAqICR7b3V0cHV0TnVtYmVyfTtcbiAgICBsZXQgYmF0Y2ggPSBpbmRleDEgLyBzdHJpZGUxO1xuXG4gICAgJHtvdXRwdXRTaGFwZS5sZW5ndGggPT09IDIgPyAnJyA6IGBsZXQgYmF0Y2hfaW5kaWNlcyA9ICR7YmF0Y2hEaW1zLm9mZnNldFRvSW5kaWNlcygnYmF0Y2gnKX07YH1cblxuICAgIHZhciBhX2luZGljZXM6ICR7YS50eXBlLmluZGljZXN9O1xuICAgICR7Y29udmVydE91dHB1dEJhdGNoSW5kaWNlc1RvSW5wdXRCYXRjaEluZGljZXMoJ2FfaW5kaWNlcycsIGEsIGEucmFuayAtIDIsIGJhdGNoRGltcy5yYW5rLCAnYmF0Y2hfaW5kaWNlcycpfVxuICAgICR7YS5pbmRpY2VzU2V0KCdhX2luZGljZXMnLCBhLnJhbmsgLSAyLCAwKX1cbiAgICAke2EuaW5kaWNlc1NldCgnYV9pbmRpY2VzJywgYS5yYW5rIC0gMSwgMCl9XG4gICAgbGV0IGFfb2Zmc2V0ID0gJHthLmluZGljZXNUb09mZnNldCgnYV9pbmRpY2VzJyl9O1xuXG4gICAgdmFyIGJfaW5kaWNlczogJHtiLnR5cGUuaW5kaWNlc307XG4gICAgJHtjb252ZXJ0T3V0cHV0QmF0Y2hJbmRpY2VzVG9JbnB1dEJhdGNoSW5kaWNlcygnYl9pbmRpY2VzJywgYiwgYi5yYW5rIC0gMiwgYmF0Y2hEaW1zLnJhbmssICdiYXRjaF9pbmRpY2VzJyl9XG4gICAgJHtiLmluZGljZXNTZXQoJ2JfaW5kaWNlcycsIGIucmFuayAtIDIsIDApfVxuICAgICR7Yi5pbmRpY2VzU2V0KCdiX2luZGljZXMnLCBiLnJhbmsgLSAxLCAwKX1cbiAgICBsZXQgYl9vZmZzZXQgPSAke2IuaW5kaWNlc1RvT2Zmc2V0KCdiX2luZGljZXMnKX07XG4gICAgdmFyIHZhbHVlczogYXJyYXk8JHtvdXRwdXQudHlwZS52YWx1ZX0sICR7b3V0cHV0TnVtYmVyfT47XG4gICAgZm9yICh2YXIgazogdTMyID0gMHU7IGsgPCB1bmlmb3Jtcy5LOyBrID0gayArICR7YUNvbXBvbmVudHN9KSB7XG4gICAgICAke2NhbGNSZXN1bHQoKX1cbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IDB1OyBpIDwgJHtvdXRwdXROdW1iZXJ9dTsgaSsrKSB7XG4gICAgICB2YXIgdmFsdWUgPSB2YWx1ZXNbaV07XG4gICAgICAke3Byb2Nlc3NCaWFzfVxuICAgICAgJHthcHBseUFjdGl2YXRpb259XG4gICAgICBsZXQgY3VyX2luZGljZXMgPSAke291dHB1dC50eXBlLmluZGljZXN9KGJhdGNoLCByb3cgKyBpLCBjb2wpO1xuICAgICAgbGV0IG9mZnNldCA9ICR7b3V0cHV0LmluZGljZXNUb09mZnNldCgnY3VyX2luZGljZXMnKX07XG4gICAgICAke291dHB1dC5zZXRCeU9mZnNldChgb2Zmc2V0IC8gJHtjb21wb25lbnRzfWAsICd2YWx1ZScpfTtcbiAgICB9XG4gIH1cbiAgYDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnTWF0TXVsTmFpdmUnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthY3RpdmF0aW9uQXR0cmlidXRlcy5hY3RpdmF0aW9ufTske2NvbXBvbmVudHN9OyR7YUNvbXBvbmVudHN9OyR7b3V0cHV0TnVtYmVyfTske2lzQ2hhbm5lbHNMYXN0fWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llczogaGFzQmlhcyA/IFsncmFuaycsICdyYW5rJywgJ3JhbmsnXSA6IFsncmFuaycsICdyYW5rJ10sXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW1xuICAgICAgICB7XG4gICAgICAgICAgZGltczogc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24gPyBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbihvdXRwdXRTaGFwZSkgOiBvdXRwdXRTaGFwZSxcbiAgICAgICAgICBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuLy8gc2FtcGxlZCBmcm9tIFtAdGVuc29yZmxvdy90ZmpzXSB0ZmpzLWJhY2tlbmQtd2ViZ3B1L3NyYy9tYXRtdWxfcGFja2VkX3dlYmdwdS50c1xuLy9cbi8vIG1vZGlmaWVkIHRvIGZpdCB0aGUgbmVlZHMgb2YgdGhlIHByb2plY3RcblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIEluZGljZXNIZWxwZXIsXG4gIGlucHV0VmFyaWFibGUsXG4gIGludGVybmFsVmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4uL2NvbW1vbic7XG5pbXBvcnQge1xuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMsXG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEsXG4gIGdldEFjdGl2YXRpb25TbmlwcGV0LFxuICBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLFxufSBmcm9tICcuLi9mdXNlLXV0aWxzJztcbmltcG9ydCB7IGNvbnZlcnRPdXRwdXRCYXRjaEluZGljZXNUb0lucHV0QmF0Y2hJbmRpY2VzIH0gZnJvbSAnLi4vbWF0bXVsLXNoYWRlcnMnO1xuXG5pbXBvcnQgeyB0eXBlU25pcHBldCB9IGZyb20gJy4vYWN0aXZhdGlvbl91dGlsJztcblxuY29uc3Qgd3JpdGVEYXRhVG9TdWJBVmVjNFNuaXBwZXQgPSAodHJhbnNwb3NlOiBib29sZWFuLCBiYXRjaERpbXM/OiBJbmRpY2VzSGVscGVyKSA9PiB7XG4gIGlmICh0cmFuc3Bvc2UpIHtcbiAgICByZXR1cm4gYFxuICAgICAgICBtbV9Bc3ViW2lucHV0Um93XVtpbnB1dENvbF0gPSBtbV9yZWFkQShiYXRjaCxcbiAgICAgICAgICBrU3RhcnQgKyBpbnB1dFJvdyxcbiAgICAgICAgICBnbG9iYWxSb3dTdGFydCAvIGlubmVyRWxlbWVudFNpemUgKyBpbnB1dENvbCR7YmF0Y2hEaW1zID8gJywgYmF0Y2hJbmRpY2VzJyA6ICcnfSk7XG4gICAgICAgIGA7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgbW1fQXN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEEoYmF0Y2gsXG4gICAgICAgICAgZ2xvYmFsUm93ICsgaW5uZXJSb3csXG4gICAgICAgICAga1N0YXJ0IC8gaW5uZXJFbGVtZW50U2l6ZSArIGlucHV0Q29sJHtiYXRjaERpbXMgPyAnLCBiYXRjaEluZGljZXMnIDogJyd9KTtcbiAgICAgICAgYDtcbiAgfVxufTtcblxuY29uc3QgY2FsY3VsYXRlUmVzdWx0U25pcHBldCA9ICh0cmFuc3Bvc2VBOiBib29sZWFuLCBpbm5lckVsZW1lbnRTaXplOiBudW1iZXIpID0+IHtcbiAgaWYgKHRyYW5zcG9zZUEpIHtcbiAgICByZXR1cm4gYFxuICAgICAgICBsZXQgQUNhY2hlZDAgPSBtbV9Bc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplXVtsb2NhbFJvd107XG4gICAgICAgIGxldCBBQ2FjaGVkMSA9IG1tX0FzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAxXVtsb2NhbFJvd107XG4gICAgICAgIGxldCBBQ2FjaGVkMiA9IG1tX0FzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAyXVtsb2NhbFJvd107XG4gICAgICAgICR7aW5uZXJFbGVtZW50U2l6ZSA9PT0gMyA/ICcnIDogJ2xldCBBQ2FjaGVkMyA9IG1tX0FzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAzXVtsb2NhbFJvd107J31cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3dQZXJUaHJlYWQ7IGkgPSBpICsgMSkge1xuICAgICAgICAgIGFjY1tpXSA9IEJDYWNoZWQwICogQUNhY2hlZDBbaV0gKyBhY2NbaV07XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDEgKiBBQ2FjaGVkMVtpXSArIGFjY1tpXTtcbiAgICAgICAgICBhY2NbaV0gPSBCQ2FjaGVkMiAqIEFDYWNoZWQyW2ldICsgYWNjW2ldO1xuICAgICAgICAgICR7aW5uZXJFbGVtZW50U2l6ZSA9PT0gMyA/ICcnIDogJ2FjY1tpXSA9IEJDYWNoZWQzICogQUNhY2hlZDNbaV0gKyBhY2NbaV07J31cbiAgICAgICAgfWA7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3dQZXJUaHJlYWQ7IGkgPSBpICsgMSkge1xuICAgICAgICAgIGxldCBBQ2FjaGVkID0gbW1fQXN1Ylt0aWxlUm93ICsgaV1ba107XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDAgKiBBQ2FjaGVkLnggKyBhY2NbaV07XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDEgKiBBQ2FjaGVkLnkgKyBhY2NbaV07XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDIgKiBBQ2FjaGVkLnogKyBhY2NbaV07XG4gICAgICAgICAgJHtpbm5lckVsZW1lbnRTaXplID09PSAzID8gJycgOiAnYWNjW2ldID0gQkNhY2hlZDMgKiBBQ2FjaGVkLncgKyBhY2NbaV07J31cbiAgICAgICAgfWA7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBtYWtlTWF0TXVsUGFja2VkVmVjNFNvdXJjZSA9IChcbiAgd29ya1BlclRocmVhZDogbnVtYmVyW10sXG4gIHdvcmtncm91cFNpemU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgdHlwZSA9ICdmMzInLFxuICBiYXRjaERpbXM/OiBJbmRpY2VzSGVscGVyLFxuICB0cmFuc3Bvc2VBID0gZmFsc2UsXG4gIHRpbGVJbm5lciA9IDMyLFxuICBzcGxpdEsgPSBmYWxzZSxcbiAgc3BsaXRlZERpbUlubmVyID0gMzIsXG4pOiBzdHJpbmcgPT4ge1xuICBjb25zdCB0aWxlQU91dGVyID0gd29ya2dyb3VwU2l6ZVsxXSAqIHdvcmtQZXJUaHJlYWRbMV07XG4gIGNvbnN0IHRpbGVCT3V0ZXIgPSB3b3JrZ3JvdXBTaXplWzBdICogd29ya1BlclRocmVhZFswXTtcbiAgY29uc3QgdGlsZUFXaWR0aCA9IHRyYW5zcG9zZUEgPyB0aWxlQU91dGVyIDogdGlsZUlubmVyO1xuICBjb25zdCB0aWxlQUhpZ2h0ID0gdHJhbnNwb3NlQSA/IHRpbGVJbm5lciA6IHRpbGVBT3V0ZXI7XG4gIGNvbnN0IGlubmVyRWxlbWVudFNpemUgPSB0aWxlQVdpZHRoIC8gd29ya2dyb3VwU2l6ZVswXTtcbiAgY29uc3Qgcm93UGVyVGhyZWFkQiA9IHRpbGVJbm5lciAvIHdvcmtncm91cFNpemVbMV07XG5cbiAgaWYgKFxuICAgICEoXG4gICAgICAoKHRyYW5zcG9zZUEgJiYgaW5uZXJFbGVtZW50U2l6ZSA9PT0gNCAmJiB3b3JrUGVyVGhyZWFkWzFdID09PSA0KSB8fFxuICAgICAgICAoIXRyYW5zcG9zZUEgJiYgKGlubmVyRWxlbWVudFNpemUgPT09IDMgfHwgaW5uZXJFbGVtZW50U2l6ZSA9PT0gNCkpKSAmJlxuICAgICAgdGlsZUFXaWR0aCAlIHdvcmtncm91cFNpemVbMF0gPT09IDAgJiZcbiAgICAgIHRpbGVJbm5lciAlIHdvcmtncm91cFNpemVbMV0gPT09IDAgJiZcbiAgICAgIHdvcmtQZXJUaHJlYWRbMF0gPT09IDRcbiAgICApXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSWYgdHJhbnNwb3NlQSAke3RyYW5zcG9zZUF9IGlzIHRydWUsIGlubmVyRWxlbWVudFNpemUgJHtpbm5lckVsZW1lbnRTaXplfSBhbmQgd29ya1BlclRocmVhZFsxXSAke3dvcmtQZXJUaHJlYWRbMV19IG11c3QgYmUgNC5cbiAgICAgIE90aGVyd2lzZSwgaW5uZXJFbGVtZW50U2l6ZSAke2lubmVyRWxlbWVudFNpemV9IG11c3QgYmUgMyBvciA0LlxuICB0aWxlQVdpZHRoICR7dGlsZUFXaWR0aH0gbXVzdCBiZSBkaXZpc2libGUgYnkgd29ya2dyb3VwU2l6ZVswXSR7d29ya2dyb3VwU2l6ZVswXX0uIHRpbGVJbm5lciAke3RpbGVJbm5lcn0gbXVzdCBiZSBkaXZpc2libGUgYnkgd29ya2dyb3VwU2l6ZVsxXSAke3dvcmtncm91cFNpemVbMV19LiBjb2xQZXJUaHJlYWQgJHt3b3JrUGVyVGhyZWFkWzBdfSBtdXN0IGJlIDQuYCk7XG4gIH1cbiAgcmV0dXJuIGBcbnZhcjx3b3JrZ3JvdXA+IG1tX0FzdWI6IGFycmF5PGFycmF5PHZlYyR7aW5uZXJFbGVtZW50U2l6ZX08JHt0eXBlfT4sICR7dGlsZUFXaWR0aCAvIGlubmVyRWxlbWVudFNpemV9PiwgJHt0aWxlQUhpZ2h0fT47XG52YXI8d29ya2dyb3VwPiBtbV9Cc3ViOiBhcnJheTxhcnJheTx2ZWM0PCR7dHlwZX0+LCAke3RpbGVCT3V0ZXIgLyB3b3JrUGVyVGhyZWFkWzBdfT4sICR7dGlsZUlubmVyfT47XG5cbmNvbnN0IHJvd1BlclRocmVhZCA9ICR7d29ya1BlclRocmVhZFsxXX07XG5jb25zdCBjb2xQZXJUaHJlYWQgPSAke3dvcmtQZXJUaHJlYWRbMF19O1xuY29uc3QgaW5uZXJFbGVtZW50U2l6ZSA9ICR7aW5uZXJFbGVtZW50U2l6ZX07XG5jb25zdCB0aWxlSW5uZXIgPSAke3RpbGVJbm5lcn07XG5cbkBjb21wdXRlIEB3b3JrZ3JvdXBfc2l6ZSgke3dvcmtncm91cFNpemVbMF19LCAke3dvcmtncm91cFNpemVbMV19LCAke3dvcmtncm91cFNpemVbMl19KVxuZm4gbWFpbihAYnVpbHRpbihsb2NhbF9pbnZvY2F0aW9uX2lkKSBsb2NhbElkIDogdmVjMzx1MzI+LFxuICAgICAgICBAYnVpbHRpbihnbG9iYWxfaW52b2NhdGlvbl9pZCkgZ2xvYmFsSWQgOiB2ZWMzPHUzMj4sXG4gICAgICAgIEBidWlsdGluKHdvcmtncm91cF9pZCkgd29ya2dyb3VwSWQgOiB2ZWMzPHUzMj4pIHtcbiAgbGV0IGxvY2FsUm93ID0gaTMyKGxvY2FsSWQueSk7XG4gIGxldCB0aWxlUm93ID0gbG9jYWxSb3cgKiByb3dQZXJUaHJlYWQ7XG4gIGxldCB0aWxlQ29sID0gaTMyKGxvY2FsSWQueCk7XG5cbiAgbGV0IGdsb2JhbFJvdyA9aTMyKGdsb2JhbElkLnkpICogcm93UGVyVGhyZWFkO1xuICBsZXQgZ2xvYmFsQ29sID0gaTMyKGdsb2JhbElkLngpO1xuICBsZXQgYmF0Y2ggPSAke3NwbGl0SyA/ICcwJyA6ICdpMzIoZ2xvYmFsSWQueiknfTtcbiAgJHtiYXRjaERpbXMgPyBgbGV0IGJhdGNoSW5kaWNlcyA9ICR7YmF0Y2hEaW1zLm9mZnNldFRvSW5kaWNlcygndTMyKGJhdGNoKScpfTtgIDogJyd9XG4gIGxldCBnbG9iYWxSb3dTdGFydCA9IGkzMih3b3JrZ3JvdXBJZC55KSAqICR7dGlsZUFPdXRlcn07XG5cbiAgbGV0IG51bV90aWxlcyA9ICR7c3BsaXRLID8gYCR7TWF0aC5jZWlsKHNwbGl0ZWREaW1Jbm5lciAvIHRpbGVJbm5lcil9YCA6ICcodW5pZm9ybXMuZGltX2lubmVyIC0gMSkgLyB0aWxlSW5uZXIgKyAxJ307XG4gIHZhciBrU3RhcnQgPSAke3NwbGl0SyA/IGBpMzIoZ2xvYmFsSWQueikgKiAke3NwbGl0ZWREaW1Jbm5lcn1gIDogJzAnfTtcblxuICB2YXIgYWNjOiBhcnJheTx2ZWM0PCR7dHlwZX0+LCByb3dQZXJUaHJlYWQ+O1xuXG4gIC8vIExvb3Agb3ZlciBzaGFyZWQgZGltZW5zaW9uLlxuICBsZXQgdGlsZVJvd0IgPSBsb2NhbFJvdyAqICR7cm93UGVyVGhyZWFkQn07XG4gIGZvciAodmFyIHQgPSAwOyB0IDwgbnVtX3RpbGVzOyB0ID0gdCArIDEpIHtcbiAgICAgIC8vIExvYWQgb25lIHRpbGUgb2YgQSBpbnRvIGxvY2FsIG1lbW9yeS5cbiAgICAgIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCByb3dQZXJUaHJlYWQ7IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgICAgICAgbGV0IGlucHV0Um93ID0gdGlsZVJvdyArIGlubmVyUm93O1xuICAgICAgICAgIGxldCBpbnB1dENvbCA9IHRpbGVDb2w7XG4gICAgICAgICAgJHt3cml0ZURhdGFUb1N1YkFWZWM0U25pcHBldCh0cmFuc3Bvc2VBLCBiYXRjaERpbXMpfVxuICAgICAgfVxuXG4gICAgICAvLyBMb2FkIG9uZSB0aWxlIG9mIEIgaW50byBsb2NhbCBtZW1vcnkuXG4gICAgICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgJHtyb3dQZXJUaHJlYWRCfTsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgICAgICAgICBsZXQgaW5wdXRSb3cgPSB0aWxlUm93QiArIGlubmVyUm93O1xuICAgICAgICAgIGxldCBpbnB1dENvbCA9IHRpbGVDb2w7XG4gICAgICAgICAgbW1fQnN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEIoYmF0Y2gsIGtTdGFydCArIGlucHV0Um93LCBnbG9iYWxDb2wke1xuICAgICAgICAgICAgYmF0Y2hEaW1zID8gJywgYmF0Y2hJbmRpY2VzJyA6ICcnXG4gICAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBrU3RhcnQgPSBrU3RhcnQgKyB0aWxlSW5uZXI7XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgIC8vIENvbXB1dGUgYWNjIHZhbHVlcyBmb3IgYSBzaW5nbGUgdGhyZWFkLlxuICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aWxlSW5uZXIgLyBpbm5lckVsZW1lbnRTaXplOyBrID0gayArIDEpIHtcbiAgICAgICAgICBsZXQgQkNhY2hlZDAgPSBtbV9Cc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplXVt0aWxlQ29sXTtcbiAgICAgICAgICBsZXQgQkNhY2hlZDEgPSBtbV9Cc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplICsgMV1bdGlsZUNvbF07XG4gICAgICAgICAgbGV0IEJDYWNoZWQyID0gbW1fQnN1YltrICogaW5uZXJFbGVtZW50U2l6ZSArIDJdW3RpbGVDb2xdO1xuICAgICAgICAgICR7aW5uZXJFbGVtZW50U2l6ZSA9PT0gMyA/ICcnIDogJ2xldCBCQ2FjaGVkMyA9IG1tX0JzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAzXVt0aWxlQ29sXTsnfVxuXG4gICAgICAgICAgJHtjYWxjdWxhdGVSZXN1bHRTbmlwcGV0KHRyYW5zcG9zZUEsIGlubmVyRWxlbWVudFNpemUpfVxuICAgICAgfVxuXG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gIH1cblxuICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgbW1fd3JpdGUoYmF0Y2gsIGdsb2JhbFJvdyArIGlubmVyUm93LCBnbG9iYWxDb2wsIGFjY1tpbm5lclJvd10pO1xuICB9XG59YDtcbn07XG5cbmNvbnN0IHdyaXRlRGF0YVRvU3ViQVNuaXBwZXQgPSAodHJhbnNwb3NlOiBib29sZWFuLCBiYXRjaERpbXM/OiBJbmRpY2VzSGVscGVyKSA9PiB7XG4gIGlmICh0cmFuc3Bvc2UpIHtcbiAgICByZXR1cm4gYFxuICAgICAgICAgICAgbW1fQXN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEEoYmF0Y2gsXG4gICAgICAgICAgICAgIGtTdGFydCArIGlucHV0Um93LFxuICAgICAgICAgICAgICBnbG9iYWxSb3dTdGFydCArIGlucHV0Q29sJHtiYXRjaERpbXMgPyAnLCBiYXRjaEluZGljZXMnIDogJyd9KTtcbiAgICAgICAgICAgIGA7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgIG1tX0FzdWJbaW5wdXRSb3ddW2lucHV0Q29sXSA9IG1tX3JlYWRBKGJhdGNoLFxuICAgICAgICAgICAgICBnbG9iYWxSb3dTdGFydCArIGlucHV0Um93LFxuICAgICAgICAgICAgICBrU3RhcnQgKyBpbnB1dENvbCR7YmF0Y2hEaW1zID8gJywgYmF0Y2hJbmRpY2VzJyA6ICcnfSk7XG4gICAgICAgICAgICBgO1xuICB9XG59O1xuXG5jb25zdCByZWFkRGF0YUZyb21TdWJBU25pcHBldCA9ICh0cmFuc3Bvc2VBOiBib29sZWFuKSA9PlxuICB0cmFuc3Bvc2VBID8gJ2xldCBBQ2FjaGVkID0gbW1fQXN1YltrXVt0aWxlUm93ICsgaW5uZXJSb3ddOycgOiAnbGV0IEFDYWNoZWQgPSBtbV9Bc3ViW3RpbGVSb3cgKyBpbm5lclJvd11ba107JztcblxuLy8gc2VxdWVudGlhbEFjY2Vzc0J5VGhyZWFkcyBtZWFucyBzZXF1ZW50aWFsIGRhdGEgaW4gbWVtb3J5IGlzIGFjY2Vzc2VkIGJ5XG4vLyB0aHJlYWRzLCBpbnN0ZWFkIG9mIGEgc2luZ2xlIHRocmVhZCAoZGVmYXVsdCBiZWhhdmlvcikuXG5leHBvcnQgY29uc3QgbWFrZU1hdE11bFBhY2tlZFNvdXJjZSA9IChcbiAgd29ya1BlclRocmVhZDogbnVtYmVyW10sXG4gIHdvcmtncm91cFNpemU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgdHlwZSA9ICdmMzInLFxuICBiYXRjaERpbXM/OiBJbmRpY2VzSGVscGVyLFxuICB0cmFuc3Bvc2VBID0gZmFsc2UsXG4gIHRpbGVJbm5lciA9IDMyLFxuICBzcGxpdEsgPSBmYWxzZSxcbiAgc3BsaXRlZERpbUlubmVyID0gMzIsXG4gIHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHMgPSBmYWxzZSxcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IHRpbGVBT3V0ZXIgPSB3b3JrUGVyVGhyZWFkWzFdICogd29ya2dyb3VwU2l6ZVsxXTtcbiAgY29uc3QgdGlsZUJPdXRlciA9IHdvcmtQZXJUaHJlYWRbMF0gKiB3b3JrZ3JvdXBTaXplWzBdO1xuICBjb25zdCB0aWxlQVdpZHRoID0gdHJhbnNwb3NlQSA/IHRpbGVBT3V0ZXIgOiB0aWxlSW5uZXI7XG4gIGNvbnN0IHRpbGVBSGlnaHQgPSB0cmFuc3Bvc2VBID8gdGlsZUlubmVyIDogdGlsZUFPdXRlcjtcblxuICBpZiAoXG4gICAgISh0aWxlQUhpZ2h0ICUgd29ya2dyb3VwU2l6ZVsxXSA9PT0gMCAmJiB0aWxlQVdpZHRoICUgd29ya2dyb3VwU2l6ZVswXSA9PT0gMCAmJiB0aWxlSW5uZXIgJSB3b3JrZ3JvdXBTaXplWzFdID09PSAwKVxuICApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgdGlsZUFIaWdodCAke3RpbGVBSGlnaHR9IG11c3QgYmUgZGl2aXNpYmxlIGJ5IHdvcmtncm91cFNpemVbMV0ke3dvcmtncm91cFNpemVbMV19LCB0aWxlQVdpZHRoICR7dGlsZUFXaWR0aH0gbXVzdCBiZSBkaXZpc2libGUgYnkgd29ya2dyb3VwU2l6ZVswXSR7d29ya2dyb3VwU2l6ZVswXX0sIHRpbGVJbm5lciAke3RpbGVJbm5lcn0gbXVzdCBiZSBkaXZpc2libGUgYnkgd29ya2dyb3VwU2l6ZVsxXSR7d29ya2dyb3VwU2l6ZVsxXX1gLFxuICAgICk7XG4gIH1cbiAgY29uc3Qgcm93UGVyVGhyZWFkQSA9IHRpbGVBSGlnaHQgLyB3b3JrZ3JvdXBTaXplWzFdO1xuICBjb25zdCBjb2xQZXJUaHJlYWRBID0gdGlsZUFXaWR0aCAvIHdvcmtncm91cFNpemVbMF07XG4gIGNvbnN0IHJvd1BlclRocmVhZEIgPSB0aWxlSW5uZXIgLyB3b3JrZ3JvdXBTaXplWzFdO1xuICBjb25zdCBtYXRtdWxTbmlwcGV0ID0gc2VxdWVudGlhbEFjY2Vzc0J5VGhyZWFkc1xuICAgID8gYFxuICAgIGxldCBsb2NhbFJvdyA9IGkzMihsb2NhbElkLnkpO1xuICAgIGxldCBsb2NhbENvbCA9IGkzMihsb2NhbElkLngpO1xuICAgIGxldCBnbG9iYWxSb3dTdGFydCA9IGkzMih3b3JrZ3JvdXBJZC55KSAqICR7dGlsZUFPdXRlcn07XG4gICAgbGV0IGdsb2JhbENvbFN0YXJ0ID0gaTMyKHdvcmtncm91cElkLngpICogJHt0aWxlQk91dGVyfTtcblxuICAgIC8vIExvb3Agb3ZlciBzaGFyZWQgZGltZW5zaW9uLlxuICAgIGZvciAodmFyIHQgPSAwOyB0IDwgbnVtX3RpbGVzOyB0ID0gdCArIDEpIHtcbiAgICAgIC8vIExvYWQgb25lIHRpbGUgb2YgQSBpbnRvIGxvY2FsIG1lbW9yeS5cbiAgICAgIGZvciAodmFyIGlucHV0Um93ID0gbG9jYWxSb3c7IGlucHV0Um93IDwgJHt0aWxlQUhpZ2h0fTsgaW5wdXRSb3cgPSBpbnB1dFJvdyArICR7d29ya2dyb3VwU2l6ZVsxXX0pIHtcbiAgICAgICAgZm9yICh2YXIgaW5wdXRDb2wgPSBsb2NhbENvbDsgaW5wdXRDb2wgPCAke3RpbGVBV2lkdGh9OyBpbnB1dENvbCA9IGlucHV0Q29sICsgJHt3b3JrZ3JvdXBTaXplWzBdfSkge1xuICAgICAgICAgICR7d3JpdGVEYXRhVG9TdWJBU25pcHBldCh0cmFuc3Bvc2VBLCBiYXRjaERpbXMpfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBMb2FkIG9uZSB0aWxlIG9mIEIgaW50byBsb2NhbCBtZW1vcnkuXG4gICAgICBmb3IgKHZhciBpbnB1dFJvdyA9IGxvY2FsUm93OyBpbnB1dFJvdyA8ICR7dGlsZUlubmVyfTsgaW5wdXRSb3cgPSBpbnB1dFJvdyArICR7d29ya2dyb3VwU2l6ZVsxXX0pIHtcbiAgICAgICAgICAgIGZvciAodmFyIGlucHV0Q29sID0gbG9jYWxDb2w7IGlucHV0Q29sIDwgJHt0aWxlQk91dGVyfTsgaW5wdXRDb2wgPSBpbnB1dENvbCArICR7d29ya2dyb3VwU2l6ZVswXX0pIHtcbiAgICAgICAgICBtbV9Cc3ViW2lucHV0Um93XVtpbnB1dENvbF0gPSBtbV9yZWFkQihiYXRjaCxcbiAgICAgICAgICAgIGtTdGFydCArIGlucHV0Um93LFxuICAgICAgICAgICAgZ2xvYmFsQ29sU3RhcnQgKyBpbnB1dENvbCR7YmF0Y2hEaW1zID8gJywgYmF0Y2hJbmRpY2VzJyA6ICcnfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGtTdGFydCA9IGtTdGFydCArIHRpbGVJbm5lcjtcbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgLy8gQ29tcHV0ZSBhY2MgdmFsdWVzIGZvciBhIHNpbmdsZSB0aHJlYWQuXG4gICAgICB2YXIgQkNhY2hlZCA6IGFycmF5PCR7dHlwZX0sIGNvbFBlclRocmVhZD47XG4gICAgICBmb3IgKHZhciBrID0gMDsgayA8IHRpbGVJbm5lcjsgayA9IGsgKyAxKSB7XG4gICAgICAgIGZvciAodmFyIGlubmVyID0gMDsgaW5uZXIgPCBjb2xQZXJUaHJlYWQ7IGlubmVyID0gaW5uZXIgKyAxKSB7XG4gICAgICAgICAgQkNhY2hlZFtpbm5lcl0gPSBtbV9Cc3ViW2tdW2xvY2FsQ29sICsgaW5uZXIgKiAke3dvcmtncm91cFNpemVbMF19XTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgICAgIGxldCBBQ2FjaGVkID0gJHtcbiAgICAgICAgICAgIHRyYW5zcG9zZUFcbiAgICAgICAgICAgICAgPyBgbW1fQXN1YltrXVtsb2NhbFJvdyArIGlubmVyUm93ICogJHt3b3JrZ3JvdXBTaXplWzFdfV07YFxuICAgICAgICAgICAgICA6IGBtbV9Bc3ViW2xvY2FsUm93ICsgaW5uZXJSb3cgKiAke3dvcmtncm91cFNpemVbMV19XVtrXTtgXG4gICAgICAgICAgfVxuICAgICAgICAgIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCBjb2xQZXJUaHJlYWQ7IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICAgICAgICBhY2NbaW5uZXJSb3ddW2lubmVyQ29sXSA9IGFjY1tpbm5lclJvd11baW5uZXJDb2xdICtcbiAgICAgICAgICAgICAgICBBQ2FjaGVkICogQkNhY2hlZFtpbm5lckNvbF07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgfVxuICAgIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCByb3dQZXJUaHJlYWQ7IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgICBsZXQgZ1JvdyA9IGdsb2JhbFJvd1N0YXJ0ICsgbG9jYWxSb3cgKyBpbm5lclJvdyAqICR7d29ya2dyb3VwU2l6ZVsxXX07XG4gICAgICBmb3IgKHZhciBpbm5lckNvbCA9IDA7IGlubmVyQ29sIDwgY29sUGVyVGhyZWFkOyBpbm5lckNvbCA9IGlubmVyQ29sICsgMSkge1xuICAgICAgICBsZXQgZ0NvbCA9IGdsb2JhbENvbFN0YXJ0ICsgbG9jYWxDb2wgKyBpbm5lckNvbCAqICR7d29ya2dyb3VwU2l6ZVswXX07XG4gICAgICAgIG1tX3dyaXRlKGJhdGNoLCBnUm93LCBnQ29sLCBhY2NbaW5uZXJSb3ddW2lubmVyQ29sXSk7XG4gICAgICB9XG4gICAgfVxuICAgIGBcbiAgICA6IGBcbmxldCB0aWxlUm93ID0gaTMyKGxvY2FsSWQueSkgKiByb3dQZXJUaHJlYWQ7XG5sZXQgdGlsZUNvbCA9IGkzMihsb2NhbElkLngpICogY29sUGVyVGhyZWFkO1xuXG5sZXQgZ2xvYmFsUm93ID0gaTMyKGdsb2JhbElkLnkpICogcm93UGVyVGhyZWFkO1xubGV0IGdsb2JhbENvbCA9IGkzMihnbG9iYWxJZC54KSAqIGNvbFBlclRocmVhZDtcbmxldCBnbG9iYWxSb3dTdGFydCA9IGkzMih3b3JrZ3JvdXBJZC55KSAqICR7dGlsZUFPdXRlcn07XG5cbmxldCB0aWxlUm93QSA9IGkzMihsb2NhbElkLnkpICogJHtyb3dQZXJUaHJlYWRBfTtcbmxldCB0aWxlQ29sQSA9IGkzMihsb2NhbElkLngpICogJHtjb2xQZXJUaHJlYWRBfTtcbmxldCB0aWxlUm93QiA9IGkzMihsb2NhbElkLnkpICogJHtyb3dQZXJUaHJlYWRCfTtcbi8vIExvb3Agb3ZlciBzaGFyZWQgZGltZW5zaW9uLlxuZm9yICh2YXIgdCA9IDA7IHQgPCBudW1fdGlsZXM7IHQgPSB0ICsgMSkge1xuICAvLyBMb2FkIG9uZSB0aWxlIG9mIEEgaW50byBsb2NhbCBtZW1vcnkuXG4gIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCAke3Jvd1BlclRocmVhZEF9OyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCAke2NvbFBlclRocmVhZEF9OyBpbm5lckNvbCA9IGlubmVyQ29sICsgMSkge1xuICAgICAgbGV0IGlucHV0Um93ID0gdGlsZVJvd0EgKyBpbm5lclJvdztcbiAgICAgIGxldCBpbnB1dENvbCA9IHRpbGVDb2xBICsgaW5uZXJDb2w7XG4gICAgICAke3dyaXRlRGF0YVRvU3ViQVNuaXBwZXQodHJhbnNwb3NlQSwgYmF0Y2hEaW1zKX1cbiAgICB9XG4gIH1cblxuICAvLyBMb2FkIG9uZSB0aWxlIG9mIEIgaW50byBsb2NhbCBtZW1vcnkuXG4gIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCAke3Jvd1BlclRocmVhZEJ9OyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCBjb2xQZXJUaHJlYWQ7IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICBsZXQgaW5wdXRSb3cgPSB0aWxlUm93QiArIGlubmVyUm93O1xuICAgICAgbGV0IGlucHV0Q29sID0gdGlsZUNvbCArIGlubmVyQ29sO1xuICAgICAgbW1fQnN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEIoYmF0Y2gsXG4gICAgICAgIGtTdGFydCArIGlucHV0Um93LFxuICAgICAgICBnbG9iYWxDb2wgKyBpbm5lckNvbCR7YmF0Y2hEaW1zID8gJywgYmF0Y2hJbmRpY2VzJyA6ICcnfSk7XG4gICAgfVxuICB9XG4gIGtTdGFydCA9IGtTdGFydCArIHRpbGVJbm5lcjtcbiAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gIC8vIENvbXB1dGUgYWNjIHZhbHVlcyBmb3IgYSBzaW5nbGUgdGhyZWFkLlxuICB2YXIgQkNhY2hlZCA6IGFycmF5PCR7dHlwZX0sIGNvbFBlclRocmVhZD47XG4gIGZvciAodmFyIGsgPSAwOyBrIDwgdGlsZUlubmVyOyBrID0gayArIDEpIHtcbiAgICBmb3IgKHZhciBpbm5lciA9IDA7IGlubmVyIDwgY29sUGVyVGhyZWFkOyBpbm5lciA9IGlubmVyICsgMSkge1xuICAgICAgQkNhY2hlZFtpbm5lcl0gPSBtbV9Cc3ViW2tdW3RpbGVDb2wgKyBpbm5lcl07XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8IHJvd1BlclRocmVhZDsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgICAgICR7cmVhZERhdGFGcm9tU3ViQVNuaXBwZXQodHJhbnNwb3NlQSl9XG4gICAgICBmb3IgKHZhciBpbm5lckNvbCA9IDA7IGlubmVyQ29sIDwgY29sUGVyVGhyZWFkOyBpbm5lckNvbCA9IGlubmVyQ29sICsgMSkge1xuICAgICAgICBhY2NbaW5uZXJSb3ddW2lubmVyQ29sXSA9IGFjY1tpbm5lclJvd11baW5uZXJDb2xdICsgQUNhY2hlZCAqIEJDYWNoZWRbaW5uZXJDb2xdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHdvcmtncm91cEJhcnJpZXIoKTtcbn1cblxuZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8IHJvd1BlclRocmVhZDsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgZm9yICh2YXIgaW5uZXJDb2wgPSAwOyBpbm5lckNvbCA8IGNvbFBlclRocmVhZDsgaW5uZXJDb2wgPSBpbm5lckNvbCArIDEpIHtcbiAgICBtbV93cml0ZShiYXRjaCwgZ2xvYmFsUm93ICsgaW5uZXJSb3csIGdsb2JhbENvbCArIGlubmVyQ29sLFxuICAgICAgICBhY2NbaW5uZXJSb3ddW2lubmVyQ29sXSk7XG4gIH1cbn1cbmA7XG5cbiAgcmV0dXJuIGBcbiAgdmFyPHdvcmtncm91cD4gbW1fQXN1YiA6IGFycmF5PGFycmF5PCR7dHlwZX0sICR7dGlsZUFXaWR0aH0+LCAke3RpbGVBSGlnaHR9PjtcbiAgdmFyPHdvcmtncm91cD4gbW1fQnN1YiA6IGFycmF5PGFycmF5PCR7dHlwZX0sICR7dGlsZUJPdXRlcn0+LCAke3RpbGVJbm5lcn0+O1xuICBjb25zdCByb3dQZXJUaHJlYWQgPSAke3dvcmtQZXJUaHJlYWRbMV19O1xuICBjb25zdCBjb2xQZXJUaHJlYWQgPSAke3dvcmtQZXJUaHJlYWRbMF19O1xuICBjb25zdCB0aWxlSW5uZXIgPSAke3RpbGVJbm5lcn07XG5cbkBjb21wdXRlIEB3b3JrZ3JvdXBfc2l6ZSgke3dvcmtncm91cFNpemVbMF19LCAke3dvcmtncm91cFNpemVbMV19LCAke3dvcmtncm91cFNpemVbMl19KVxuZm4gbWFpbihAYnVpbHRpbihsb2NhbF9pbnZvY2F0aW9uX2lkKSBsb2NhbElkIDogdmVjMzx1MzI+LFxuICAgICAgICBAYnVpbHRpbihnbG9iYWxfaW52b2NhdGlvbl9pZCkgZ2xvYmFsSWQgOiB2ZWMzPHUzMj4sXG4gICAgICAgIEBidWlsdGluKHdvcmtncm91cF9pZCkgd29ya2dyb3VwSWQgOiB2ZWMzPHUzMj4pIHtcbiAgICBsZXQgYmF0Y2ggPSAke3NwbGl0SyA/ICcwJyA6ICdpMzIoZ2xvYmFsSWQueiknfTtcbiAgICAke2JhdGNoRGltcyA/IGBsZXQgYmF0Y2hJbmRpY2VzID0gJHtiYXRjaERpbXMub2Zmc2V0VG9JbmRpY2VzKCd1MzIoYmF0Y2gpJyl9O2AgOiAnJ31cbiAgICBsZXQgbnVtX3RpbGVzID0gJHtcbiAgICAgIHNwbGl0SyA/IGAke01hdGguY2VpbChzcGxpdGVkRGltSW5uZXIgLyB0aWxlSW5uZXIpfWAgOiAnKHVuaWZvcm1zLmRpbV9pbm5lciAtIDEpIC8gdGlsZUlubmVyICsgMSdcbiAgICB9O1xuICAgIHZhciBrU3RhcnQgPSAke3NwbGl0SyA/IGBpMzIoZ2xvYmFsSWQueikgKiAke3NwbGl0ZWREaW1Jbm5lcn1gIDogJzAnfTtcblxuICAgIHZhciBhY2MgOiBhcnJheTxhcnJheTwke3R5cGV9LCBjb2xQZXJUaHJlYWQ+LCByb3dQZXJUaHJlYWQ+O1xuICAgICR7bWF0bXVsU25pcHBldH1cbiAgfVxuYDtcbn07XG5cbmNvbnN0IG1hdE11bFJlYWRXcml0ZUZuU291cmNlID0gKFxuICBjb21wb25lbnQ6IG51bWJlcixcbiAgaGFzQmlhczogYm9vbGVhbixcbiAgYXBwbHlBY3RpdmF0aW9uOiBzdHJpbmcsXG4gIHZhcmlhYmxlczogSW5kaWNlc0hlbHBlcltdLFxuICBpc0NoYW5uZWxzTGFzdCA9IGZhbHNlLFxuKTogc3RyaW5nID0+IHtcbiAgY29uc3QgW2JhdGNoVmFyaWFibGUsIGFWYXJpYWJsZSwgYlZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZV0gPSB2YXJpYWJsZXM7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKHZhcmlhYmxlc1swXS50eXBlLnRlbnNvcik7XG5cbiAgY29uc3Qgc291cmNlID0gYFxuICAgIGZuIG1tX3JlYWRBKGJhdGNoOiBpMzIsIHJvdzogaTMyLCBjb2xJbjogaTMyLCBiYXRjaEluZGljZXM6ICR7YmF0Y2hWYXJpYWJsZS50eXBlLmluZGljZXN9KSAtPiAke3R5cGVTbmlwcGV0KFxuICAgICAgY29tcG9uZW50LFxuICAgICAgZGF0YVR5cGUsXG4gICAgKX0ge1xuICAgICAgdmFyIHZhbHVlID0gJHt0eXBlU25pcHBldChjb21wb25lbnQsIGRhdGFUeXBlKX0oMC4wKTtcbiAgICAgIGxldCBjb2wgPSBjb2xJbiAqICR7Y29tcG9uZW50fTtcbiAgICAgIGlmKHJvdyA8IHVuaWZvcm1zLmRpbV9hX291dGVyICYmIGNvbCA8IHVuaWZvcm1zLmRpbV9pbm5lcilcbiAgICAgIHtcbiAgICAgICAgdmFyIGFJbmRpY2VzOiAke2FWYXJpYWJsZS50eXBlLmluZGljZXN9O1xuICAgICAgICAke2NvbnZlcnRPdXRwdXRCYXRjaEluZGljZXNUb0lucHV0QmF0Y2hJbmRpY2VzKFxuICAgICAgICAgICdhSW5kaWNlcycsXG4gICAgICAgICAgYVZhcmlhYmxlLFxuICAgICAgICAgIGFWYXJpYWJsZS5yYW5rIC0gMixcbiAgICAgICAgICBiYXRjaFZhcmlhYmxlLnJhbmssXG4gICAgICAgICAgJ2JhdGNoSW5kaWNlcycsXG4gICAgICAgICl9XG4gICAgICAgICR7YVZhcmlhYmxlLmluZGljZXNTZXQoJ2FJbmRpY2VzJywgYVZhcmlhYmxlLnJhbmsgLSAyLCAndTMyKHJvdyknKX1cbiAgICAgICAgJHthVmFyaWFibGUuaW5kaWNlc1NldCgnYUluZGljZXMnLCBhVmFyaWFibGUucmFuayAtIDEsICd1MzIoY29sSW4pJyl9XG4gICAgICAgIHZhbHVlID0gJHthVmFyaWFibGUuZ2V0QnlJbmRpY2VzKCdhSW5kaWNlcycpfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICBmbiBtbV9yZWFkQihiYXRjaDogaTMyLCByb3c6IGkzMiwgY29sSW46IGkzMiwgYmF0Y2hJbmRpY2VzOiAke2JhdGNoVmFyaWFibGUudHlwZS5pbmRpY2VzfSkgLT4gJHt0eXBlU25pcHBldChcbiAgICAgIGNvbXBvbmVudCxcbiAgICAgIGRhdGFUeXBlLFxuICAgICl9IHtcbiAgICAgIHZhciB2YWx1ZSA9ICR7dHlwZVNuaXBwZXQoY29tcG9uZW50LCBkYXRhVHlwZSl9KDAuMCk7XG4gICAgICBsZXQgY29sID0gY29sSW4gKiAke2NvbXBvbmVudH07XG4gICAgICBpZihyb3cgPCB1bmlmb3Jtcy5kaW1faW5uZXIgJiYgY29sIDwgdW5pZm9ybXMuZGltX2Jfb3V0ZXIpXG4gICAgICB7XG4gICAgICAgIHZhciBiSW5kaWNlczogJHtiVmFyaWFibGUudHlwZS5pbmRpY2VzfTtcbiAgICAgICAgJHtjb252ZXJ0T3V0cHV0QmF0Y2hJbmRpY2VzVG9JbnB1dEJhdGNoSW5kaWNlcyhcbiAgICAgICAgICAnYkluZGljZXMnLFxuICAgICAgICAgIGJWYXJpYWJsZSxcbiAgICAgICAgICBiVmFyaWFibGUucmFuayAtIDIsXG4gICAgICAgICAgYmF0Y2hWYXJpYWJsZS5yYW5rLFxuICAgICAgICAgICdiYXRjaEluZGljZXMnLFxuICAgICAgICApfVxuICAgICAgICAke2JWYXJpYWJsZS5pbmRpY2VzU2V0KCdiSW5kaWNlcycsIGJWYXJpYWJsZS5yYW5rIC0gMiwgJ3UzMihyb3cpJyl9XG4gICAgICAgICR7YlZhcmlhYmxlLmluZGljZXNTZXQoJ2JJbmRpY2VzJywgYlZhcmlhYmxlLnJhbmsgLSAxLCAndTMyKGNvbEluKScpfVxuICAgICAgICB2YWx1ZSA9ICR7YlZhcmlhYmxlLmdldEJ5SW5kaWNlcygnYkluZGljZXMnKX07XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgZm4gbW1fd3JpdGUoYmF0Y2g6IGkzMiwgcm93OiBpMzIsIGNvbEluOiBpMzIsIHZhbHVlSW46ICR7dHlwZVNuaXBwZXQoY29tcG9uZW50LCBkYXRhVHlwZSl9KSB7XG4gICAgICBsZXQgY29sID0gY29sSW4gKiAke2NvbXBvbmVudH07XG4gICAgICBpZiAocm93IDwgdW5pZm9ybXMuZGltX2Ffb3V0ZXIgJiYgY29sIDwgdW5pZm9ybXMuZGltX2Jfb3V0ZXIpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdmFsdWVJbjtcbiAgICAgICAgbGV0IGNvb3JkcyA9IHZlYzM8aTMyPihiYXRjaCwgcm93LCBjb2xJbik7XG4gICAgICAgICR7XG4gICAgICAgICAgaGFzQmlhc1xuICAgICAgICAgICAgPyBgdmFsdWUgPSB2YWx1ZSArICR7aXNDaGFubmVsc0xhc3QgPyAnYmlhc1tjb2xJbl0nIDogYCR7dHlwZVNuaXBwZXQoY29tcG9uZW50LCBkYXRhVHlwZSl9KGJpYXNbcm93XSlgfTtgXG4gICAgICAgICAgICA6ICcnXG4gICAgICAgIH1cbiAgICAgICAgJHthcHBseUFjdGl2YXRpb259XG4gICAgICAgICR7b3V0cHV0VmFyaWFibGUuc2V0QnlJbmRpY2VzKCd2ZWMzPHUzMj4oY29vcmRzKScsICd2YWx1ZScpfVxuICAgICAgfVxuICAgIH1cbiAgICBgO1xuICByZXR1cm4gc291cmNlO1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYWN0aXZhdGlvbkF0dHJpYnV0ZXM6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgcmVzaGFwZWRPdXRwdXRTaGFwZT86IHJlYWRvbmx5IG51bWJlcltdLFxuICBpc0NoYW5uZWxzTGFzdCA9IGZhbHNlIC8qIG9ubHkgdXNlZCBmb3IgY29udjJkQnlNYXRNdWwqLyxcbiAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgYVNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGJTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICBjb25zdCBvdXRlckRpbXNBID0gYVNoYXBlLnNsaWNlKDAsIC0yKTtcbiAgY29uc3Qgb3V0ZXJEaW1zQiA9IGJTaGFwZS5zbGljZSgwLCAtMik7XG4gIGNvbnN0IG91dGVyRGltcyA9IHJlc2hhcGVkT3V0cHV0U2hhcGUgPyByZXNoYXBlZE91dHB1dFNoYXBlLnNsaWNlKDAsIC0yKSA6IG91dHB1dFNoYXBlLnNsaWNlKDAsIC0yKTtcbiAgY29uc3QgYmF0Y2hTaXplID0gU2hhcGVVdGlsLnNpemUob3V0ZXJEaW1zKTtcbiAgY29uc3QgZGltQU91dGVyID0gYVNoYXBlW2FTaGFwZS5sZW5ndGggLSAyXTtcbiAgY29uc3QgZGltSW5uZXIgPSBhU2hhcGVbYVNoYXBlLmxlbmd0aCAtIDFdO1xuICBjb25zdCBkaW1CT3V0ZXIgPSBiU2hhcGVbYlNoYXBlLmxlbmd0aCAtIDFdO1xuICBjb25zdCBpc1ZlYzQgPSBkaW1Jbm5lciAlIDQgPT09IDAgJiYgZGltQk91dGVyICUgNCA9PT0gMDtcblxuICAvLyBUT0RPOiBmaW5lIHR1bmUgc2l6ZVxuICBjb25zdCBlbGVtZW50c1BlclRocmVhZCA9IGRpbUFPdXRlciA8PSA4ID8gWzQsIDEsIDFdIDogWzQsIDQsIDFdO1xuICBjb25zdCB3b3JrZ3JvdXBTaXplOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPSBbOCwgOCwgMV07XG4gIGNvbnN0IGRpc3BhdGNoID0gW1xuICAgIE1hdGguY2VpbChkaW1CT3V0ZXIgLyB3b3JrZ3JvdXBTaXplWzBdIC8gZWxlbWVudHNQZXJUaHJlYWRbMF0pLFxuICAgIE1hdGguY2VpbChkaW1BT3V0ZXIgLyB3b3JrZ3JvdXBTaXplWzFdIC8gZWxlbWVudHNQZXJUaHJlYWRbMV0pLFxuICAgIE1hdGguY2VpbChiYXRjaFNpemUgLyB3b3JrZ3JvdXBTaXplWzJdIC8gZWxlbWVudHNQZXJUaHJlYWRbMl0pLFxuICBdO1xuXG4gIGNvbnN0IGNvbXBvbmVudHMgPSBpc1ZlYzQgPyA0IDogMTtcbiAgY29uc3QgYVNoYXBlVGVtcCA9IFsuLi5vdXRlckRpbXNBLCBkaW1BT3V0ZXIsIGRpbUlubmVyIC8gY29tcG9uZW50c107XG4gIGNvbnN0IGFSYW5rID0gYVNoYXBlVGVtcC5sZW5ndGg7XG4gIGNvbnN0IGJTaGFwZVRlbXAgPSBbLi4ub3V0ZXJEaW1zQiwgZGltSW5uZXIsIGRpbUJPdXRlciAvIGNvbXBvbmVudHNdO1xuICBjb25zdCBiUmFuayA9IGJTaGFwZVRlbXAubGVuZ3RoO1xuICBjb25zdCBvdXRwdXRTaGFwZVRlbXAgPSBbYmF0Y2hTaXplLCBkaW1BT3V0ZXIsIGRpbUJPdXRlciAvIGNvbXBvbmVudHNdO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogZGltQU91dGVyIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogZGltQk91dGVyIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogZGltSW5uZXIgfSxcbiAgXTtcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YShhY3RpdmF0aW9uQXR0cmlidXRlcywgcHJvZ3JhbVVuaWZvcm1zKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0ZXJEaW1zLCBhU2hhcGVUZW1wLCBiU2hhcGVUZW1wKSk7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWydyYW5rJywgJ3JhbmsnXTtcblxuICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA+IDI7XG4gIGlmIChoYXNCaWFzKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzJdLmRpbXMpKTtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCdyYW5rJyk7XG4gIH1cbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGVUZW1wKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgYmF0Y2hSYW5rID0gb3V0ZXJEaW1zLmxlbmd0aDtcbiAgICBjb25zdCBiYXRjaERpbXMgPSBpbnRlcm5hbFZhcmlhYmxlKCdiYXRjaERpbXMnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGJhdGNoUmFuaywgMSk7XG4gICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcblxuICAgIGNvbnN0IEEgPSBpbnB1dFZhcmlhYmxlKCdhJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBhUmFuaywgY29tcG9uZW50cyk7XG4gICAgY29uc3QgQiA9IGlucHV0VmFyaWFibGUoJ2InLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGJSYW5rLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgncmVzdWx0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZVRlbXAubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBpbnB1dFZhcmlhYmxlcyA9IFtBLCBCXTtcbiAgICBpZiAoaGFzQmlhcykge1xuICAgICAgY29uc3QgYmlhc0NvbXBvbmVudHMgPSBpc0NoYW5uZWxzTGFzdCA/IGNvbXBvbmVudHMgOiAxO1xuICAgICAgaW5wdXRWYXJpYWJsZXMucHVzaChpbnB1dFZhcmlhYmxlKCdiaWFzJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcy5sZW5ndGgsIGJpYXNDb21wb25lbnRzKSk7XG4gICAgfVxuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ2RpbV9hX291dGVyJywgdHlwZTogJ2kzMicgfSxcbiAgICAgIHsgbmFtZTogJ2RpbV9iX291dGVyJywgdHlwZTogJ2kzMicgfSxcbiAgICAgIHsgbmFtZTogJ2RpbV9pbm5lcicsIHR5cGU6ICdpMzInIH0sXG4gICAgXTtcbiAgICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMoYWN0aXZhdGlvbkF0dHJpYnV0ZXMsIHVuaWZvcm1zKTtcbiAgICBjb25zdCBiYXNlVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShvdXRwdXQudHlwZS50ZW5zb3IpO1xuICAgIGNvbnN0IGFwcGx5QWN0aXZhdGlvbiA9IGdldEFjdGl2YXRpb25TbmlwcGV0KGFjdGl2YXRpb25BdHRyaWJ1dGVzLCBvdXRwdXQudHlwZS52YWx1ZSwgYmFzZVR5cGUpO1xuICAgIGNvbnN0IGRlY2xhcmVGdW5jdGlvbnMgPSBtYXRNdWxSZWFkV3JpdGVGblNvdXJjZShcbiAgICAgIGNvbXBvbmVudHMsXG4gICAgICBoYXNCaWFzLFxuICAgICAgYXBwbHlBY3RpdmF0aW9uLFxuICAgICAgW2JhdGNoRGltcywgQSwgQiwgb3V0cHV0XSxcbiAgICAgIGlzQ2hhbm5lbHNMYXN0LFxuICAgICk7XG4gICAgcmV0dXJuIGBcbiAgJHtzaGFkZXJIZWxwZXJcbiAgICAucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcylcbiAgICAucmVnaXN0ZXJJbnRlcm5hbFZhcmlhYmxlcyhiYXRjaERpbXMpXG4gICAgLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICR7ZGVjbGFyZUZ1bmN0aW9uc31cbiAgJHtcbiAgICBpc1ZlYzRcbiAgICAgID8gbWFrZU1hdE11bFBhY2tlZFZlYzRTb3VyY2UoZWxlbWVudHNQZXJUaHJlYWQsIHdvcmtncm91cFNpemUsIGRhdGFUeXBlLCBiYXRjaERpbXMpXG4gICAgICA6IG1ha2VNYXRNdWxQYWNrZWRTb3VyY2UoZWxlbWVudHNQZXJUaHJlYWQsIHdvcmtncm91cFNpemUsIGRhdGFUeXBlLCBiYXRjaERpbXMpXG4gIH1cbiAgICAgICAgICAgICAgICAgICBgO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdNYXRNdWwnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHtlbGVtZW50c1BlclRocmVhZH07JHthY3RpdmF0aW9uQXR0cmlidXRlcy5hY3RpdmF0aW9ufTske2lzVmVjNH07JHtpc0NoYW5uZWxzTGFzdH1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXMsXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW1xuICAgICAgICB7XG4gICAgICAgICAgZGltczogc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24gPyBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbihvdXRwdXRTaGFwZSkgOiBvdXRwdXRTaGFwZSxcbiAgICAgICAgICBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogZGlzcGF0Y2hbMF0sIHk6IGRpc3BhdGNoWzFdLCB6OiBkaXNwYXRjaFsyXSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG4vLyBzYW1wbGVkIGZyb20gW0B0ZW5zb3JmbG93L3RmanNdIHRmanMtYmFja2VuZC13ZWJncHUvc3JjL2NvbnYyZF9tbV93ZWJncHUudHNcbi8vXG4vLyBtb2RpZmllZCB0byBmaXQgdGhlIG5lZWRzIG9mIHRoZSBwcm9qZWN0XG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgTE9HX0RFQlVHIH0gZnJvbSAnLi4vLi4vLi4vbG9nJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4uL2NvbW1vbic7XG5pbXBvcnQgeyBDb252QXR0cmlidXRlcyB9IGZyb20gJy4uL2NvbnYnO1xuaW1wb3J0IHsgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zLCBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhLCBnZXRBY3RpdmF0aW9uU25pcHBldCB9IGZyb20gJy4uL2Z1c2UtdXRpbHMnO1xuXG5pbXBvcnQgeyBiaWFzU25pcHBldCwgdHlwZVNuaXBwZXQgfSBmcm9tICcuL2FjdGl2YXRpb25fdXRpbCc7XG5pbXBvcnQgeyB1dGlsRnVuY3Rpb25zIH0gZnJvbSAnLi9jb252X3V0aWwnO1xuaW1wb3J0IHsgbWFrZU1hdE11bFBhY2tlZFNvdXJjZSwgbWFrZU1hdE11bFBhY2tlZFZlYzRTb3VyY2UgfSBmcm9tICcuL21hdG11bF9wYWNrZWRfd2ViZ3B1JztcblxuY29uc3QgY29udjJkQ29tbW9uU25pcHBldCA9IChcbiAgaXNDaGFubmVsc0xhc3Q6IGJvb2xlYW4sXG4gIGZpdEFPdXRlcjogYm9vbGVhbixcbiAgZml0Qk91dGVyOiBib29sZWFuLFxuICBmaXRJbm5lcjogYm9vbGVhbixcbiAgYWRkQmlhcyA9IGZhbHNlLFxuICBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyxcbiAgaW5uZXJFbGVtZW50U2l6ZVggPSA0LFxuICBpbm5lckVsZW1lbnRTaXplVyA9IDQsXG4gIGlubmVyRWxlbWVudFNpemUgPSA0LFxuICBkYXRhVHlwZSA9ICdmMzInLFxuKTogc3RyaW5nID0+IHtcbiAgY29uc3QgZ2V0WFNuaXBwZXQgPSAoaW5uZXJFbGVtZW50U2l6ZTogbnVtYmVyKSA9PiB7XG4gICAgc3dpdGNoIChpbm5lckVsZW1lbnRTaXplKSB7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIHJldHVybiAncmVzRGF0YSA9IHhbeEluZGV4XTsnO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXR1cm4gYHJlc0RhdGEgPSB2ZWMzPCR7ZGF0YVR5cGV9Pih4W3hJbmRleF0sIHhbeEluZGV4ICsgMV0sIHhbeEluZGV4ICsgMl0pO2A7XG4gICAgICBjYXNlIDQ6XG4gICAgICAgIHJldHVybiAncmVzRGF0YSA9IHhbeEluZGV4IC8gNF07JztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW5uZXJFbGVtZW50U2l6ZSAke2lubmVyRWxlbWVudFNpemV9IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gICAgfVxuICB9O1xuICBjb25zdCBnZXRXU25pcHBldCA9IChpbm5lckVsZW1lbnRTaXplOiBudW1iZXIpID0+IHtcbiAgICBzd2l0Y2ggKGlubmVyRWxlbWVudFNpemUpIHtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmV0dXJuICdyZXR1cm4gd1tyb3cgKiBpMzIodW5pZm9ybXMud19zaGFwZVszXSkgKyBjb2xJbl07JztcbiAgICAgIGNhc2UgNDpcbiAgICAgICAgcmV0dXJuICdyZXR1cm4gd1tyb3cgKiBpMzIodW5pZm9ybXMud19zaGFwZVszXSkgLyA0ICsgY29sSW5dOyc7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGlubmVyRWxlbWVudFNpemUgJHtpbm5lckVsZW1lbnRTaXplfSBpcyBub3Qgc3VwcG9ydGVkLmApO1xuICAgIH1cbiAgfTtcbiAgY29uc3QgY29vcmRBU25pcHBldCA9IGlzQ2hhbm5lbHNMYXN0XG4gICAgPyBgXG4gICAgbGV0IGNvb3JkID0gdmVjNDxpMzI+KGJhdGNoLCB4Um93LCB4Q29sLCB4Q2gpO1xuICAgIGBcbiAgICA6IGBcbiAgICBsZXQgY29vcmQgPSB2ZWM0PGkzMj4oYmF0Y2gsIHhDaCwgeFJvdywgeENvbCk7XG4gICAgYDtcblxuICBjb25zdCBjb29yZFJlc1NuaXBwZXQgPSBpc0NoYW5uZWxzTGFzdFxuICAgID8gYFxuICAgIGxldCBjb29yZHMgPSB2ZWM0PGkzMj4oXG4gICAgICBiYXRjaCxcbiAgICAgIHJvdyAvIG91dFdpZHRoLFxuICAgICAgcm93ICUgb3V0V2lkdGgsXG4gICAgICBjb2wpO1xuICAgIGBcbiAgICA6IGBcbiAgICBsZXQgY29vcmRzID0gdmVjNDxpMzI+KFxuICAgICAgYmF0Y2gsXG4gICAgICByb3csXG4gICAgICBjb2wgLyBvdXRXaWR0aCxcbiAgICAgIGNvbCAlIG91dFdpZHRoKTtcbiAgICBgO1xuXG4gIGNvbnN0IHhIZWlnaHQgPSBpc0NoYW5uZWxzTGFzdCA/ICdpMzIodW5pZm9ybXMueF9zaGFwZVsxXSknIDogJ2kzMih1bmlmb3Jtcy54X3NoYXBlWzJdKSc7XG4gIGNvbnN0IHhXaWR0aCA9IGlzQ2hhbm5lbHNMYXN0ID8gJ2kzMih1bmlmb3Jtcy54X3NoYXBlWzJdKScgOiAnaTMyKHVuaWZvcm1zLnhfc2hhcGVbM10pJztcbiAgY29uc3Qgcm93ID0gaXNDaGFubmVsc0xhc3QgPyAncm93JyA6ICdjb2wnO1xuICBjb25zdCBjb2wgPSBpc0NoYW5uZWxzTGFzdCA/ICdjb2wnIDogJ3Jvdyc7XG4gIGNvbnN0IHJlYWRYU25pcHBldCA9IGBcbiAgICBsZXQgaW5DaGFubmVscyA9IGkzMih1bmlmb3Jtcy53X3NoYXBlWzJdKTtcbiAgICBsZXQgb3V0V2lkdGggPSAke2lzQ2hhbm5lbHNMYXN0ID8gJ2kzMih1bmlmb3Jtcy5yZXN1bHRfc2hhcGVbMl0pJyA6ICdpMzIodW5pZm9ybXMucmVzdWx0X3NoYXBlWzNdKSd9O1xuICAgIGxldCBvdXRSb3cgPSAke3Jvd30gLyBvdXRXaWR0aDtcbiAgICBsZXQgb3V0Q29sID0gJHtyb3d9ICUgb3V0V2lkdGg7XG5cbiAgICBsZXQgV1JvdyA9ICR7Y29sfSAvIChpMzIodW5pZm9ybXMud19zaGFwZVsxXSkgKiBpbkNoYW5uZWxzKTtcbiAgICBsZXQgV0NvbCA9ICR7Y29sfSAvIGluQ2hhbm5lbHMgJSBpMzIodW5pZm9ybXMud19zaGFwZVsxXSk7XG4gICAgbGV0IHhSb3cgPSBvdXRSb3cgKiB1bmlmb3Jtcy5zdHJpZGVbMF0gKyB1bmlmb3Jtcy5kaWxhdGlvblswXSAqIFdSb3cgLSB1bmlmb3Jtcy5wYWRbMF07XG4gICAgbGV0IHhDb2wgPSBvdXRDb2wgKiB1bmlmb3Jtcy5zdHJpZGVbMV0gKyB1bmlmb3Jtcy5kaWxhdGlvblsxXSAqIFdDb2wgLSB1bmlmb3Jtcy5wYWRbMV07XG4gICAgbGV0IHhDaCA9ICR7Y29sfSAlIGluQ2hhbm5lbHM7XG4gICAgdmFyIHJlc0RhdGEgPSAke3R5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVYLCBkYXRhVHlwZSl9KDAuMCk7XG4gICAgLy8gVGhlIGJvdW5kcyBjaGVja2luZyBpcyBhbHdheXMgbmVlZGVkIHNpbmNlIHdlIHVzZSBpdCB0byBwYWQgemVybyBmb3JcbiAgICAvLyB0aGUgJ3NhbWUnIHBhZGRpbmcgdHlwZS5cbiAgICBpZiAoeFJvdyA+PSAwICYmIHhSb3cgPCAke3hIZWlnaHR9ICYmIHhDb2wgPj0gMCAmJiB4Q29sIDwgJHt4V2lkdGh9KSB7XG4gICAgICAke2Nvb3JkQVNuaXBwZXR9XG4gICAgICBsZXQgeEluZGV4ID0gZ2V0SW5kZXhGcm9tQ29vcmRzNEQoY29vcmQsIHZlYzQ8aTMyPih1bmlmb3Jtcy54X3NoYXBlKSk7XG4gICAgICAke2dldFhTbmlwcGV0KGlubmVyRWxlbWVudFNpemVYKX1cbiAgICB9XG4gICAgcmV0dXJuIHJlc0RhdGE7YDtcblxuICBjb25zdCBzYW1wbGVYID0gaXNDaGFubmVsc0xhc3RcbiAgICA/IGZpdEFPdXRlciAmJiBmaXRJbm5lclxuICAgICAgPyBgXG4gICAgbGV0IGNvbCA9IGNvbEluICogJHtpbm5lckVsZW1lbnRTaXplWH07XG4gICAgJHtyZWFkWFNuaXBwZXR9YFxuICAgICAgOiBgXG4gICAgbGV0IGNvbCA9IGNvbEluICogJHtpbm5lckVsZW1lbnRTaXplWH07XG4gICAgaWYgKHJvdyA8IHVuaWZvcm1zLmRpbV9hX291dGVyICYmIGNvbCA8IHVuaWZvcm1zLmRpbV9pbm5lcikge1xuICAgICAgJHtyZWFkWFNuaXBwZXR9XG4gICAgfVxuICAgIHJldHVybiAke3R5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVYLCBkYXRhVHlwZSl9KDAuMCk7YFxuICAgIDogZml0SW5uZXIgJiYgZml0Qk91dGVyXG4gICAgICA/IGBcbiAgICBsZXQgY29sID0gY29sSW4gKiAke2lubmVyRWxlbWVudFNpemVYfTtcbiAgICAke3JlYWRYU25pcHBldH1gXG4gICAgICA6IGBcbiAgICBsZXQgY29sID0gY29sSW4gKiAke2lubmVyRWxlbWVudFNpemVYfTtcbiAgICBpZiAocm93IDwgdW5pZm9ybXMuZGltX2lubmVyICYmIGNvbCA8IHVuaWZvcm1zLmRpbV9iX291dGVyKSB7XG4gICAgICAke3JlYWRYU25pcHBldH1cbiAgICB9XG4gICAgcmV0dXJuICR7dHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVgsIGRhdGFUeXBlKX0oMC4wKTtgO1xuXG4gIGNvbnN0IHNhbXBsZVcgPSBpc0NoYW5uZWxzTGFzdFxuICAgID8gZml0SW5uZXIgJiYgZml0Qk91dGVyXG4gICAgICA/IGdldFdTbmlwcGV0KGlubmVyRWxlbWVudFNpemVXKVxuICAgICAgOiBgXG4gICAgbGV0IGNvbCA9IGNvbEluICogJHtpbm5lckVsZW1lbnRTaXplV307XG4gICAgaWYgKHJvdyA8IHVuaWZvcm1zLmRpbV9pbm5lciAmJiBjb2wgPCB1bmlmb3Jtcy5kaW1fYl9vdXRlcikge1xuICAgICAgJHtnZXRXU25pcHBldChpbm5lckVsZW1lbnRTaXplVyl9XG4gICAgfVxuICAgIHJldHVybiAke3R5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVXLCBkYXRhVHlwZSl9KDAuMCk7YFxuICAgIDogYFxuICAgIGxldCBjb2wgPSBjb2xJbiAqICR7aW5uZXJFbGVtZW50U2l6ZVd9O1xuICAgIGlmIChyb3cgPCB1bmlmb3Jtcy5kaW1faW5uZXIgJiYgY29sIDwgdW5pZm9ybXMuZGltX2Ffb3V0ZXIpIHtcbiAgICAgICR7Z2V0V1NuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVcpfVxuICAgIH1cbiAgICByZXR1cm4gJHt0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplVywgZGF0YVR5cGUpfSgwLjApO2A7XG5cbiAgY29uc3QgcmVzVHlwZSA9IHR5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemUsIGRhdGFUeXBlKTtcbiAgY29uc3QgYVR5cGUgPSBpc0NoYW5uZWxzTGFzdCA/IHR5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVYLCBkYXRhVHlwZSkgOiB0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplVywgZGF0YVR5cGUpO1xuICBjb25zdCBiVHlwZSA9IGlzQ2hhbm5lbHNMYXN0ID8gdHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVcsIGRhdGFUeXBlKSA6IHR5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVYLCBkYXRhVHlwZSk7XG4gIGNvbnN0IGFwcGx5QWN0aXZhdGlvbiA9IGdldEFjdGl2YXRpb25TbmlwcGV0KGF0dHJpYnV0ZXMsIHJlc1R5cGUsIGRhdGFUeXBlKTtcbiAgY29uc3QgdXNlckNvZGUgPSBgXG4gICAgZm4gbW1fcmVhZEEoYmF0Y2g6IGkzMiwgcm93IDogaTMyLCBjb2xJbiA6IGkzMikgLT4gJHthVHlwZX0ge1xuICAgICAgJHtpc0NoYW5uZWxzTGFzdCA/IHNhbXBsZVggOiBzYW1wbGVXfVxuICAgIH1cblxuICAgIGZuIG1tX3JlYWRCKGJhdGNoOiBpMzIsIHJvdyA6IGkzMiwgY29sSW4gOiBpMzIpIC0+ICR7YlR5cGV9IHtcbiAgICAgICR7aXNDaGFubmVsc0xhc3QgPyBzYW1wbGVXIDogc2FtcGxlWH1cbiAgICB9XG5cbiAgICBmbiBtbV93cml0ZShiYXRjaDogaTMyLCByb3cgOiBpMzIsIGNvbEluIDogaTMyLCB2YWx1ZUluIDogJHtyZXNUeXBlfSkge1xuICAgICAgbGV0IGNvbCA9IGNvbEluICogJHtpbm5lckVsZW1lbnRTaXplfTtcbiAgICAgIGlmIChyb3cgPCB1bmlmb3Jtcy5kaW1fYV9vdXRlciAmJiBjb2wgPCB1bmlmb3Jtcy5kaW1fYl9vdXRlcilcbiAgICAgIHtcbiAgICAgIHZhciB2YWx1ZSA9IHZhbHVlSW47XG4gICAgICBsZXQgb3V0V2lkdGggPSAke2lzQ2hhbm5lbHNMYXN0ID8gJ2kzMih1bmlmb3Jtcy5yZXN1bHRfc2hhcGVbMl0pJyA6ICdpMzIodW5pZm9ybXMucmVzdWx0X3NoYXBlWzNdKSd9O1xuICAgICAgJHtjb29yZFJlc1NuaXBwZXR9XG4gICAgICAke2JpYXNTbmlwcGV0KGFkZEJpYXMpfVxuICAgICAgJHthcHBseUFjdGl2YXRpb259XG4gICAgICBzZXRPdXRwdXRBdENvb3Jkcyhjb29yZHNbMF0sIGNvb3Jkc1sxXSwgY29vcmRzWzJdLCBjb29yZHNbM10sIHZhbHVlKTtcbiAgICAgIH1cbiAgICB9YDtcbiAgcmV0dXJuIHVzZXJDb2RlO1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUNvbnYyRE1hdE11bFByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMsXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgZGltQU91dGVyOiBudW1iZXIsXG4gIGRpbUJPdXRlcjogbnVtYmVyLFxuICBkaW1Jbm5lcjogbnVtYmVyLFxuICBoYXNCaWFzOiBib29sZWFuLFxuICBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzOiBib29sZWFuLFxuICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbj86IChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pID0+IG51bWJlcltdLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpc0NoYW5uZWxzTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGNvbnN0IGluQ2hhbm5lbHMgPSBpc0NoYW5uZWxzTGFzdCA/IGlucHV0c1swXS5kaW1zWzNdIDogaW5wdXRzWzBdLmRpbXNbMV07XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IG91dHB1dFNoYXBlWzBdO1xuICBjb25zdCBvdXRXaWR0aCA9IGlzQ2hhbm5lbHNMYXN0ID8gb3V0cHV0U2hhcGVbMl0gOiBvdXRwdXRTaGFwZVszXTtcbiAgY29uc3Qgb3V0SGVpZ2h0ID0gaXNDaGFubmVsc0xhc3QgPyBvdXRwdXRTaGFwZVsxXSA6IG91dHB1dFNoYXBlWzJdO1xuICBjb25zdCBvdXRDaGFubmVscyA9IGlzQ2hhbm5lbHNMYXN0ID8gb3V0cHV0U2hhcGVbM10gOiBvdXRwdXRTaGFwZVsxXTtcbiAgLy8gVE9ETzogZW5hYmxlIHZlYzQgZm9yIE5DSFdcbiAgY29uc3QgaXNWZWM0ID0gaXNDaGFubmVsc0xhc3QgJiYgKGluQ2hhbm5lbHMgJSA0ID09PSAwIHx8IGluQ2hhbm5lbHMgJSAzID09PSAwKSAmJiBvdXRDaGFubmVscyAlIDQgPT09IDA7XG5cbiAgLy8gVE9ETzogZmluZSB0dW5lIHNpemVcbiAgY29uc3QgZGlzcGF0Y2hYID0gaXNDaGFubmVsc0xhc3QgPyBvdXRDaGFubmVscyA6IG91dFdpZHRoICogb3V0SGVpZ2h0O1xuICBjb25zdCBkaXNwYXRjaFkgPSBpc0NoYW5uZWxzTGFzdCA/IG91dFdpZHRoICogb3V0SGVpZ2h0IDogb3V0Q2hhbm5lbHM7XG4gIGNvbnN0IHdvcmtHcm91cFNpemU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9IFs4LCA4LCAxXTtcbiAgY29uc3QgZWxlbWVudHNQZXJUaHJlYWQgPSBkaW1BT3V0ZXIgPD0gOCA/IFs0LCAxLCAxXSA6IFs0LCA0LCAxXTtcbiAgY29uc3QgZGlzcGF0Y2ggPSBbXG4gICAgTWF0aC5jZWlsKGRpc3BhdGNoWCAvIHdvcmtHcm91cFNpemVbMF0gLyBlbGVtZW50c1BlclRocmVhZFswXSksXG4gICAgTWF0aC5jZWlsKGRpc3BhdGNoWSAvIHdvcmtHcm91cFNpemVbMV0gLyBlbGVtZW50c1BlclRocmVhZFsxXSksXG4gICAgTWF0aC5jZWlsKGJhdGNoU2l6ZSAvIHdvcmtHcm91cFNpemVbMl0gLyBlbGVtZW50c1BlclRocmVhZFsyXSksXG4gIF07XG5cbiAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtjb252MmRfbW1fd2ViZ3B1XSBkaXNwYXRjaCA9ICR7ZGlzcGF0Y2h9YCk7XG5cbiAgY29uc3QgaW5uZXJFbGVtZW50U2l6ZSA9IGlzVmVjNCA/IChpc0NoYW5uZWxzTGFzdCAmJiBpbkNoYW5uZWxzICUgNCAhPT0gMCA/IDMgOiA0KSA6IDE7XG4gIGNvbnN0IHRpbGVBT3V0ZXIgPSB3b3JrR3JvdXBTaXplWzFdICogZWxlbWVudHNQZXJUaHJlYWRbMV07XG4gIGNvbnN0IHRpbGVCT3V0ZXIgPSB3b3JrR3JvdXBTaXplWzBdICogZWxlbWVudHNQZXJUaHJlYWRbMF07XG4gIGNvbnN0IHRpbGVJbm5lciA9IE1hdGgubWF4KHdvcmtHcm91cFNpemVbMF0gKiBpbm5lckVsZW1lbnRTaXplLCB3b3JrR3JvdXBTaXplWzFdKTtcbiAgY29uc3QgZml0QU91dGVyID0gZGltQU91dGVyICUgdGlsZUFPdXRlciA9PT0gMDtcbiAgY29uc3QgZml0Qk91dGVyID0gZGltQk91dGVyICUgdGlsZUJPdXRlciA9PT0gMDtcbiAgY29uc3QgZml0SW5uZXIgPSBkaW1Jbm5lciAlIHRpbGVJbm5lciA9PT0gMDtcbiAgY29uc3QgZWxlbWVudHNTaXplID0gaXNWZWM0ID8gW2lubmVyRWxlbWVudFNpemUsIDQsIDRdIDogWzEsIDEsIDFdO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBkaW1BT3V0ZXIgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBkaW1CT3V0ZXIgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBkaW1Jbm5lciB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IFthdHRyaWJ1dGVzLnBhZHNbMF0sIGF0dHJpYnV0ZXMucGFkc1sxXV0gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLnN0cmlkZXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLmRpbGF0aW9ucyB9LFxuICBdO1xuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhKGF0dHJpYnV0ZXMsIHByb2dyYW1Vbmlmb3Jtcyk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBpbnB1dHNbMV0uZGltcykpO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsncmFuaycsICdyYW5rJ107XG4gIGlmIChoYXNCaWFzKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzJdLmRpbXMpKTtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCdyYW5rJyk7XG4gIH1cbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGUpKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdkaW1fYV9vdXRlcicsIHR5cGU6ICdpMzInIH0sXG4gICAgICB7IG5hbWU6ICdkaW1fYl9vdXRlcicsIHR5cGU6ICdpMzInIH0sXG4gICAgICB7IG5hbWU6ICdkaW1faW5uZXInLCB0eXBlOiAnaTMyJyB9LFxuICAgICAgeyBuYW1lOiAncGFkJywgdHlwZTogJ2kzMicsIGxlbmd0aDogMiB9LFxuICAgICAgeyBuYW1lOiAnc3RyaWRlJywgdHlwZTogJ2kzMicsIGxlbmd0aDogMiB9LFxuICAgICAgeyBuYW1lOiAnZGlsYXRpb24nLCB0eXBlOiAnaTMyJywgbGVuZ3RoOiAyIH0sXG4gICAgXTtcbiAgICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMoYXR0cmlidXRlcywgdW5pZm9ybXMpO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBjb21wb25lbnQgMiwgMy5cbiAgICBjb25zdCBjb21wb25lbnRzID0gaXNWZWM0ID8gNCA6IDE7XG4gICAgY29uc3QgdCA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuICAgIGxldCBkZWNsYXJlRnVuY3Rpb25zID0gYFxuICAgICAgZm4gc2V0T3V0cHV0QXRJbmRleChmbGF0SW5kZXggOiBpMzIsIHZhbHVlIDogJHtpc1ZlYzQgPyBgdmVjNDwke3R9PmAgOiB0fSkge1xuICAgICAgICByZXN1bHRbZmxhdEluZGV4XSA9ICR7aXNWZWM0ID8gYHZlYzQ8JHt0fT5gIDogdH0odmFsdWUpO1xuICAgICAgfVxuICAgICAgZm4gc2V0T3V0cHV0QXRDb29yZHMoZDAgOiBpMzIsIGQxIDogaTMyLCBkMiA6IGkzMiwgZDMgOiBpMzIsIHZhbHVlIDogJHtpc1ZlYzQgPyBgdmVjNDwke3R9PmAgOiB0fSkge1xuICAgICAgICBsZXQgZmxhdEluZGV4ID0gZ2V0T3V0cHV0SW5kZXhGcm9tQ29vcmRzKHZlYzQ8aTMyPihkMCwgZDEsIGQyLCBkMykpO1xuICAgICAgICBzZXRPdXRwdXRBdEluZGV4KGZsYXRJbmRleCAke2lzVmVjNCA/ICcvIDQnIDogJyd9LCB2YWx1ZSk7XG4gICAgICB9YDtcbiAgICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZShcbiAgICAgICd4JyxcbiAgICAgIGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgIGlucHV0c1swXS5kaW1zLmxlbmd0aCxcbiAgICAgIGlubmVyRWxlbWVudFNpemUgPT09IDMgPyAxIDogaW5uZXJFbGVtZW50U2l6ZSxcbiAgICApO1xuICAgIGNvbnN0IHcgPSBpbnB1dFZhcmlhYmxlKCd3JywgaW5wdXRzWzFdLmRhdGFUeXBlLCBpbnB1dHNbMV0uZGltcy5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGlucHV0VmFyaWFibGVzID0gW3gsIHddO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdyZXN1bHQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgaWYgKGhhc0JpYXMpIHtcbiAgICAgIGNvbnN0IGJpYXMgPSBpbnB1dFZhcmlhYmxlKCdiaWFzJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcy5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgICAgaW5wdXRWYXJpYWJsZXMucHVzaChiaWFzKTtcbiAgICAgIGRlY2xhcmVGdW5jdGlvbnMgKz0gYFxuICAgICAgICBmbiBnZXRCaWFzQnlPdXRwdXRDb29yZHMoY29vcmRzIDogdmVjNDxpMzI+KSAtPiAke2lzVmVjNCA/IGB2ZWM0PCR7dH0+YCA6IHR9IHtcbiAgICAgICAgICByZXR1cm4gYmlhc1tjb29yZHMuJHtpc0NoYW5uZWxzTGFzdCA/ICd3JyA6ICd5J30ke2lzVmVjNCA/ICcvIDQnIDogJyd9XTtcbiAgICAgICAgfWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGBcbiAgICAgICAgJHt1dGlsRnVuY3Rpb25zKCd1bmlmb3Jtcy5yZXN1bHRfc3RyaWRlcycpfVxuICAgICAgICAvL3N0cnVjdCBVbmlmb3JtcyB7IHhTaGFwZSA6IHZlYzQ8aTMyPiwgd1NoYXBlIDogdmVjNDxpMzI+LCBvdXRTaGFwZSA6IHZlYzQ8aTMyPixcbiAgICAgICAgLy8gIG91dFNoYXBlU3RyaWRlczogdmVjMzxpMzI+LCBmaWx0ZXJEaW1zIDogdmVjMjxpMzI+LCBwYWQgOiB2ZWMyPGkzMj4sIHN0cmlkZSA6IHZlYzI8aTMyPixcbiAgICAgICAgLy8gIGRpbGF0aW9uIDogdmVjMjxpMzI+LCBkaW1BT3V0ZXIgOiBpMzIsIGRpbUJPdXRlciA6IGkzMiwgZGltSW5uZXIgOiBpMzIgfTtcbiAgICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcmlhYmxlcywgb3V0cHV0KX1cbiAgICAgICAgJHtkZWNsYXJlRnVuY3Rpb25zfVxuICAgICAgICAke2NvbnYyZENvbW1vblNuaXBwZXQoXG4gICAgICAgICAgaXNDaGFubmVsc0xhc3QsXG4gICAgICAgICAgZml0QU91dGVyLFxuICAgICAgICAgIGZpdEJPdXRlcixcbiAgICAgICAgICBmaXRJbm5lcixcbiAgICAgICAgICBoYXNCaWFzLFxuICAgICAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICAgICAgZWxlbWVudHNTaXplWzBdLFxuICAgICAgICAgIGVsZW1lbnRzU2l6ZVsxXSxcbiAgICAgICAgICBlbGVtZW50c1NpemVbMl0sXG4gICAgICAgICAgdCxcbiAgICAgICAgKX1cbiAgICAgICAgJHtcbiAgICAgICAgICBpc1ZlYzRcbiAgICAgICAgICAgID8gbWFrZU1hdE11bFBhY2tlZFZlYzRTb3VyY2UoZWxlbWVudHNQZXJUaHJlYWQsIHdvcmtHcm91cFNpemUsIHQsIHVuZGVmaW5lZCwgIWlzQ2hhbm5lbHNMYXN0LCB0aWxlSW5uZXIpXG4gICAgICAgICAgICA6IG1ha2VNYXRNdWxQYWNrZWRTb3VyY2UoXG4gICAgICAgICAgICAgICAgZWxlbWVudHNQZXJUaHJlYWQsXG4gICAgICAgICAgICAgICAgd29ya0dyb3VwU2l6ZSxcbiAgICAgICAgICAgICAgICB0LFxuICAgICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAhaXNDaGFubmVsc0xhc3QsXG4gICAgICAgICAgICAgICAgdGlsZUlubmVyLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzLFxuICAgICAgICAgICAgICApXG4gICAgICAgIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdDb252MkRNYXRNdWwnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fTske2lubmVyRWxlbWVudFNpemV9OyR7aXNWZWM0fTske2ZpdEFPdXRlcn07JHtmaXRCT3V0ZXJ9OyR7Zml0SW5uZXJ9OyR7dGlsZUFPdXRlcn07JHt0aWxlQk91dGVyfTske3RpbGVJbm5lcn1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXMsXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW1xuICAgICAgICB7XG4gICAgICAgICAgZGltczogc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24gPyBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbihvdXRwdXRTaGFwZSkgOiBvdXRwdXRTaGFwZSxcbiAgICAgICAgICBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogZGlzcGF0Y2hbMF0sIHk6IGRpc3BhdGNoWzFdLCB6OiBkaXNwYXRjaFsyXSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG4vLyBzYW1wbGVkIGZyb20gW0B0ZW5zb3JmbG93L3RmanNdIHRmanMtYmFja2VuZC13ZWJncHUvc3JjL2NvbnYzZF9uYWl2ZV93ZWJncHUudHNcbi8vXG4vLyBtb2RpZmllZCB0byBmaXQgdGhlIG5lZWRzIG9mIHRoZSBwcm9qZWN0XG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgTE9HX0RFQlVHIH0gZnJvbSAnLi4vLi4vLi4vbG9nJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7IFByb2dyYW1JbmZvLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi8uLi90eXBlcyc7XG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgZ2V0RWxlbWVudEF0LFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuLi9jb21tb24nO1xuaW1wb3J0IHsgQ29udkF0dHJpYnV0ZXMgfSBmcm9tICcuLi9jb252JztcbmltcG9ydCB7IGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcywgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YSwgZ2V0QWN0aXZhdGlvblNuaXBwZXQgfSBmcm9tICcuLi9mdXNlLXV0aWxzJztcblxuaW1wb3J0IHsgdHlwZVNuaXBwZXQgfSBmcm9tICcuL2FjdGl2YXRpb25fdXRpbCc7XG5cbmNvbnN0IGFycmF5UHJvZHVjdCA9IChhcnI6IG51bWJlcltdKSA9PiB7XG4gIGxldCBwcm9kdWN0ID0gMTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICBwcm9kdWN0ICo9IGFycltpXTtcbiAgfVxuICByZXR1cm4gcHJvZHVjdDtcbn07XG5cbmNvbnN0IHBhcnNlM1R1cGxlUGFyYW0gPSAocGFyYW06IG51bWJlciB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSk6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9PlxuICB0eXBlb2YgcGFyYW0gPT09ICdudW1iZXInID8gW3BhcmFtLCBwYXJhbSwgcGFyYW1dIDogcGFyYW07XG5cbmNvbnN0IGdldEVmZmVjdGl2ZUZpbHRlclNpemUgPSAoZmlsdGVyU2l6ZTogbnVtYmVyLCBkaWxhdGlvbjogbnVtYmVyKTogbnVtYmVyID0+IHtcbiAgaWYgKGRpbGF0aW9uIDw9IDEpIHtcbiAgICByZXR1cm4gZmlsdGVyU2l6ZTtcbiAgfVxuXG4gIHJldHVybiBmaWx0ZXJTaXplICsgKGZpbHRlclNpemUgLSAxKSAqIChkaWxhdGlvbiAtIDEpO1xufTtcblxuY29uc3QgY29tcHV0ZURlZmF1bHRQYWQgPSAoXG4gIGlucHV0U2hhcGU6IFtudW1iZXIsIG51bWJlcl0gfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgZmllbGRTaXplOiBudW1iZXIsXG4gIHN0cmlkZTogbnVtYmVyLFxuICBkaWxhdGlvbiA9IDEsXG4pOiBudW1iZXIgPT4ge1xuICBjb25zdCBlZmZlY3RpdmVGaWVsZFNpemUgPSBnZXRFZmZlY3RpdmVGaWx0ZXJTaXplKGZpZWxkU2l6ZSwgZGlsYXRpb24pO1xuICByZXR1cm4gTWF0aC5mbG9vcigoaW5wdXRTaGFwZVswXSAqIChzdHJpZGUgLSAxKSAtIHN0cmlkZSArIGVmZmVjdGl2ZUZpZWxkU2l6ZSkgLyAyKTtcbn07XG5cbmNvbnN0IGNvbXB1dGVPdXRwdXRTaGFwZTREID0gKFxuICBpblNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgZmlsdGVyU2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgb3V0Q2hhbm5lbHM6IG51bWJlcixcbiAgc3RyaWRlczogW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICB6ZXJvUGFkPzogbnVtYmVyLFxuKTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPT4ge1xuICBpZiAoemVyb1BhZCA9PSBudWxsKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgemVyb1BhZCA9IGNvbXB1dGVEZWZhdWx0UGFkKGluU2hhcGUsIGZpbHRlclNoYXBlWzBdLCBzdHJpZGVzWzBdKTtcbiAgfVxuICBjb25zdCBvdXRTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPSBbMCwgMCwgMCwgb3V0Q2hhbm5lbHNdO1xuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgMzsgaW5kZXgrKykge1xuICAgIGlmIChpblNoYXBlW2luZGV4XSArIDIgKiB6ZXJvUGFkID49IGZpbHRlclNoYXBlW2luZGV4XSkge1xuICAgICAgb3V0U2hhcGVbaW5kZXhdID0gTWF0aC50cnVuYygoaW5TaGFwZVtpbmRleF0gLSBmaWx0ZXJTaGFwZVtpbmRleF0gKyAyICogemVyb1BhZCkgLyBzdHJpZGVzW2luZGV4XSArIDEpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3V0U2hhcGU7XG59O1xuXG5jb25zdCBnZXQzRFBhZEFuZE91dEluZm8gPSAoXG4gIHBhZDogbnVtYmVyIHwgc3RyaW5nIHwgbnVtYmVyW10sXG4gIGluRGVwdGg6IG51bWJlcixcbiAgaW5IZWlnaHQ6IG51bWJlcixcbiAgaW5XaWR0aDogbnVtYmVyLFxuICBzdHJpZGVEZXB0aDogbnVtYmVyLFxuICBzdHJpZGVIZWlnaHQ6IG51bWJlcixcbiAgc3RyaWRlV2lkdGg6IG51bWJlcixcbiAgZmlsdGVyRGVwdGg6IG51bWJlcixcbiAgZmlsdGVySGVpZ2h0OiBudW1iZXIsXG4gIGZpbHRlcldpZHRoOiBudW1iZXIsXG4pOiB7IHBhZEluZm86IFBhZEluZm8zRDsgb3V0RGVwdGg6IG51bWJlcjsgb3V0SGVpZ2h0OiBudW1iZXI7IG91dFdpZHRoOiBudW1iZXIgfSA9PiB7XG4gIGxldCBwYWRJbmZvOiBQYWRJbmZvM0Q7XG4gIGxldCBvdXREZXB0aDogbnVtYmVyO1xuICBsZXQgb3V0SGVpZ2h0OiBudW1iZXI7XG4gIGxldCBvdXRXaWR0aDogbnVtYmVyO1xuXG4gIGlmIChwYWQgPT09ICdWQUxJRCcpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICBwYWQgPSAwO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBwYWQgPT09ICdudW1iZXInKSB7XG4gICAgcGFkSW5mbyA9IHsgdG9wOiBwYWQsIGJvdHRvbTogcGFkLCBsZWZ0OiBwYWQsIHJpZ2h0OiBwYWQsIGZyb250OiBwYWQsIGJhY2s6IHBhZCB9O1xuICAgIGNvbnN0IG91dFNoYXBlID0gY29tcHV0ZU91dHB1dFNoYXBlNEQoXG4gICAgICBbaW5EZXB0aCwgaW5IZWlnaHQsIGluV2lkdGgsIDFdLFxuICAgICAgW2ZpbHRlckRlcHRoLCBmaWx0ZXJIZWlnaHQsIGZpbHRlcldpZHRoXSxcbiAgICAgIDEsXG4gICAgICBbc3RyaWRlRGVwdGgsIHN0cmlkZUhlaWdodCwgc3RyaWRlV2lkdGhdLFxuICAgICAgcGFkLFxuICAgICk7XG4gICAgb3V0RGVwdGggPSBvdXRTaGFwZVswXTtcbiAgICBvdXRIZWlnaHQgPSBvdXRTaGFwZVsxXTtcbiAgICBvdXRXaWR0aCA9IG91dFNoYXBlWzJdO1xuICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocGFkKSkge1xuICAgIGlmICghcGFkLmV2ZXJ5KCh2YWwsIF8sIGFycikgPT4gdmFsID09PSBhcnJbMF0pKSB7XG4gICAgICB0aHJvdyBFcnJvcihgVW5zdXBwb3J0ZWQgcGFkZGluZyBwYXJhbWV0ZXI6ICR7cGFkfWApO1xuICAgIH1cbiAgICBwYWRJbmZvID0geyB0b3A6IHBhZFswXSwgYm90dG9tOiBwYWRbMV0sIGxlZnQ6IHBhZFsyXSwgcmlnaHQ6IHBhZFszXSwgZnJvbnQ6IHBhZFs0XSwgYmFjazogcGFkWzVdIH07XG4gICAgY29uc3Qgb3V0U2hhcGUgPSBjb21wdXRlT3V0cHV0U2hhcGU0RChcbiAgICAgIFtpbkRlcHRoLCBpbkhlaWdodCwgaW5XaWR0aCwgMV0sXG4gICAgICBbZmlsdGVyRGVwdGgsIGZpbHRlckhlaWdodCwgZmlsdGVyV2lkdGhdLFxuICAgICAgMSxcbiAgICAgIFtzdHJpZGVEZXB0aCwgc3RyaWRlSGVpZ2h0LCBzdHJpZGVXaWR0aF0sXG4gICAgICBwYWRbMF0sXG4gICAgKTtcbiAgICBvdXREZXB0aCA9IG91dFNoYXBlWzBdO1xuICAgIG91dEhlaWdodCA9IG91dFNoYXBlWzFdO1xuICAgIG91dFdpZHRoID0gb3V0U2hhcGVbMl07XG4gIH0gZWxzZSBpZiAocGFkID09PSAnU0FNRV9VUFBFUicpIHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0ICdTQU1FX0xPV0VSJy5cbiAgICBvdXREZXB0aCA9IE1hdGguY2VpbChpbkRlcHRoIC8gc3RyaWRlRGVwdGgpO1xuICAgIG91dEhlaWdodCA9IE1hdGguY2VpbChpbkhlaWdodCAvIHN0cmlkZUhlaWdodCk7XG4gICAgb3V0V2lkdGggPSBNYXRoLmNlaWwoaW5XaWR0aCAvIHN0cmlkZVdpZHRoKTtcbiAgICBjb25zdCBwYWRBbG9uZ0RlcHRoID0gKG91dERlcHRoIC0gMSkgKiBzdHJpZGVEZXB0aCArIGZpbHRlckRlcHRoIC0gaW5EZXB0aDtcbiAgICBjb25zdCBwYWRBbG9uZ0hlaWdodCA9IChvdXRIZWlnaHQgLSAxKSAqIHN0cmlkZUhlaWdodCArIGZpbHRlckhlaWdodCAtIGluSGVpZ2h0O1xuICAgIGNvbnN0IHBhZEFsb25nV2lkdGggPSAob3V0V2lkdGggLSAxKSAqIHN0cmlkZVdpZHRoICsgZmlsdGVyV2lkdGggLSBpbldpZHRoO1xuICAgIGNvbnN0IGZyb250ID0gTWF0aC5mbG9vcihwYWRBbG9uZ0RlcHRoIC8gMik7XG4gICAgY29uc3QgYmFjayA9IHBhZEFsb25nRGVwdGggLSBmcm9udDtcbiAgICBjb25zdCB0b3AgPSBNYXRoLmZsb29yKHBhZEFsb25nSGVpZ2h0IC8gMik7XG4gICAgY29uc3QgYm90dG9tID0gcGFkQWxvbmdIZWlnaHQgLSB0b3A7XG4gICAgY29uc3QgbGVmdCA9IE1hdGguZmxvb3IocGFkQWxvbmdXaWR0aCAvIDIpO1xuICAgIGNvbnN0IHJpZ2h0ID0gcGFkQWxvbmdXaWR0aCAtIGxlZnQ7XG5cbiAgICBwYWRJbmZvID0geyB0b3AsIGJvdHRvbSwgbGVmdCwgcmlnaHQsIGZyb250LCBiYWNrIH07XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgRXJyb3IoYFVua25vd24gcGFkZGluZyBwYXJhbWV0ZXI6ICR7cGFkfWApO1xuICB9XG4gIHJldHVybiB7IHBhZEluZm8sIG91dERlcHRoLCBvdXRIZWlnaHQsIG91dFdpZHRoIH07XG59O1xuXG50eXBlIFBhZEluZm8zRCA9IHtcbiAgdG9wOiBudW1iZXI7XG4gIGxlZnQ6IG51bWJlcjtcbiAgcmlnaHQ6IG51bWJlcjtcbiAgYm90dG9tOiBudW1iZXI7XG4gIGZyb250OiBudW1iZXI7XG4gIGJhY2s6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIENvbnYzREluZm8gPSB7XG4gIGJhdGNoU2l6ZTogbnVtYmVyO1xuICBpbkRlcHRoOiBudW1iZXI7XG4gIGluSGVpZ2h0OiBudW1iZXI7XG4gIGluV2lkdGg6IG51bWJlcjtcbiAgaW5DaGFubmVsczogbnVtYmVyO1xuICBvdXREZXB0aDogbnVtYmVyO1xuICBvdXRIZWlnaHQ6IG51bWJlcjtcbiAgb3V0V2lkdGg6IG51bWJlcjtcbiAgb3V0Q2hhbm5lbHM6IG51bWJlcjtcbiAgZGF0YUZvcm1hdDogJ2NoYW5uZWxzRmlyc3QnIHwgJ2NoYW5uZWxzTGFzdCc7XG4gIHN0cmlkZURlcHRoOiBudW1iZXI7XG4gIHN0cmlkZUhlaWdodDogbnVtYmVyO1xuICBzdHJpZGVXaWR0aDogbnVtYmVyO1xuICBkaWxhdGlvbkRlcHRoOiBudW1iZXI7XG4gIGRpbGF0aW9uSGVpZ2h0OiBudW1iZXI7XG4gIGRpbGF0aW9uV2lkdGg6IG51bWJlcjtcbiAgZmlsdGVyRGVwdGg6IG51bWJlcjtcbiAgZmlsdGVySGVpZ2h0OiBudW1iZXI7XG4gIGZpbHRlcldpZHRoOiBudW1iZXI7XG4gIGVmZmVjdGl2ZUZpbHRlckRlcHRoOiBudW1iZXI7XG4gIGVmZmVjdGl2ZUZpbHRlckhlaWdodDogbnVtYmVyO1xuICBlZmZlY3RpdmVGaWx0ZXJXaWR0aDogbnVtYmVyO1xuICBwYWRJbmZvOiBQYWRJbmZvM0Q7XG4gIGluU2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gIG91dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICBmaWx0ZXJTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbn07XG5cbmV4cG9ydCBjb25zdCBjb21wdXRlQ29udjNESW5mbyA9IChcbiAgaW5TaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgZmlsdGVyU2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIHN0cmlkZXM6IG51bWJlciB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgZGlsYXRpb25zOiBudW1iZXIgfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIHBhZDogbnVtYmVyIHwgc3RyaW5nIHwgbnVtYmVyW10sXG4gIGRlcHRod2lzZSA9IGZhbHNlLFxuICBkYXRhRm9ybWF0OiAnY2hhbm5lbHNGaXJzdCcgfCAnY2hhbm5lbHNMYXN0JyA9ICdjaGFubmVsc0xhc3QnLFxuKTogQ29udjNESW5mbyA9PiB7XG4gIGxldCBiYXRjaFNpemUsIGluRGVwdGgsIGluSGVpZ2h0LCBpbldpZHRoLCBpbkNoYW5uZWxzO1xuICBpZiAoZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzTGFzdCcpIHtcbiAgICBbYmF0Y2hTaXplLCBpbkRlcHRoLCBpbkhlaWdodCwgaW5XaWR0aCwgaW5DaGFubmVsc10gPSBpblNoYXBlO1xuICB9IGVsc2UgaWYgKGRhdGFGb3JtYXQgPT09ICdjaGFubmVsc0ZpcnN0Jykge1xuICAgIFtiYXRjaFNpemUsIGluQ2hhbm5lbHMsIGluRGVwdGgsIGluSGVpZ2h0LCBpbldpZHRoXSA9IGluU2hhcGU7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGRhdGFGb3JtYXQgJHtkYXRhRm9ybWF0fWApO1xuICB9XG4gIGNvbnN0IFtmaWx0ZXJDaGFubmVscywgLCBmaWx0ZXJEZXB0aCwgZmlsdGVySGVpZ2h0LCBmaWx0ZXJXaWR0aF0gPSBmaWx0ZXJTaGFwZTtcblxuICBjb25zdCBbc3RyaWRlRGVwdGgsIHN0cmlkZUhlaWdodCwgc3RyaWRlV2lkdGhdID0gcGFyc2UzVHVwbGVQYXJhbShzdHJpZGVzKTtcbiAgY29uc3QgW2RpbGF0aW9uRGVwdGgsIGRpbGF0aW9uSGVpZ2h0LCBkaWxhdGlvbldpZHRoXSA9IHBhcnNlM1R1cGxlUGFyYW0oZGlsYXRpb25zKTtcblxuICBjb25zdCBlZmZlY3RpdmVGaWx0ZXJEZXB0aCA9IGdldEVmZmVjdGl2ZUZpbHRlclNpemUoZmlsdGVyRGVwdGgsIGRpbGF0aW9uRGVwdGgpO1xuICBjb25zdCBlZmZlY3RpdmVGaWx0ZXJIZWlnaHQgPSBnZXRFZmZlY3RpdmVGaWx0ZXJTaXplKGZpbHRlckhlaWdodCwgZGlsYXRpb25IZWlnaHQpO1xuICBjb25zdCBlZmZlY3RpdmVGaWx0ZXJXaWR0aCA9IGdldEVmZmVjdGl2ZUZpbHRlclNpemUoZmlsdGVyV2lkdGgsIGRpbGF0aW9uV2lkdGgpO1xuICBjb25zdCB7IHBhZEluZm8sIG91dERlcHRoLCBvdXRIZWlnaHQsIG91dFdpZHRoIH0gPSBnZXQzRFBhZEFuZE91dEluZm8oXG4gICAgcGFkLFxuICAgIGluRGVwdGgsXG4gICAgaW5IZWlnaHQsXG4gICAgaW5XaWR0aCxcbiAgICBzdHJpZGVEZXB0aCxcbiAgICBzdHJpZGVIZWlnaHQsXG4gICAgc3RyaWRlV2lkdGgsXG4gICAgZWZmZWN0aXZlRmlsdGVyRGVwdGgsXG4gICAgZWZmZWN0aXZlRmlsdGVySGVpZ2h0LFxuICAgIGVmZmVjdGl2ZUZpbHRlcldpZHRoLFxuICApO1xuXG4gIGNvbnN0IG91dENoYW5uZWxzID0gZGVwdGh3aXNlID8gZmlsdGVyQ2hhbm5lbHMgKiBpbkNoYW5uZWxzIDogZmlsdGVyQ2hhbm5lbHM7XG5cbiAgbGV0IG91dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzAsIDAsIDAsIDAsIDBdO1xuICBpZiAoZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzRmlyc3QnKSB7XG4gICAgb3V0U2hhcGUgPSBbYmF0Y2hTaXplLCBvdXRDaGFubmVscywgb3V0RGVwdGgsIG91dEhlaWdodCwgb3V0V2lkdGhdO1xuICB9IGVsc2UgaWYgKGRhdGFGb3JtYXQgPT09ICdjaGFubmVsc0xhc3QnKSB7XG4gICAgb3V0U2hhcGUgPSBbYmF0Y2hTaXplLCBvdXREZXB0aCwgb3V0SGVpZ2h0LCBvdXRXaWR0aCwgb3V0Q2hhbm5lbHNdO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBiYXRjaFNpemUsXG4gICAgZGF0YUZvcm1hdCxcbiAgICBpbkRlcHRoLFxuICAgIGluSGVpZ2h0LFxuICAgIGluV2lkdGgsXG4gICAgaW5DaGFubmVscyxcbiAgICBvdXREZXB0aCxcbiAgICBvdXRIZWlnaHQsXG4gICAgb3V0V2lkdGgsXG4gICAgb3V0Q2hhbm5lbHMsXG4gICAgcGFkSW5mbyxcbiAgICBzdHJpZGVEZXB0aCxcbiAgICBzdHJpZGVIZWlnaHQsXG4gICAgc3RyaWRlV2lkdGgsXG4gICAgZmlsdGVyRGVwdGgsXG4gICAgZmlsdGVySGVpZ2h0LFxuICAgIGZpbHRlcldpZHRoLFxuICAgIGVmZmVjdGl2ZUZpbHRlckRlcHRoLFxuICAgIGVmZmVjdGl2ZUZpbHRlckhlaWdodCxcbiAgICBlZmZlY3RpdmVGaWx0ZXJXaWR0aCxcbiAgICBkaWxhdGlvbkRlcHRoLFxuICAgIGRpbGF0aW9uSGVpZ2h0LFxuICAgIGRpbGF0aW9uV2lkdGgsXG4gICAgaW5TaGFwZSxcbiAgICBvdXRTaGFwZSxcbiAgICBmaWx0ZXJTaGFwZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVDb252M0ROYWl2ZVByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMsXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgZmlsdGVyRGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHBhZHM6IHJlYWRvbmx5IG51bWJlcltdLFxuICBkYXRhRm9ybWF0OiBzdHJpbmcsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlzQ2hhbm5lbExhc3QgPSBkYXRhRm9ybWF0ID09PSAnY2hhbm5lbHNMYXN0JztcbiAgY29uc3QgaW5DaGFubmVscyA9IGlzQ2hhbm5lbExhc3QgPyBpbnB1dHNbMF0uZGltc1szXSA6IGlucHV0c1swXS5kaW1zWzFdO1xuICAvLyBUT0RPOiBlbmFibGUgdmVjNC5cbiAgY29uc3QgaXNWZWM0ID0gZmFsc2U7XG4gIGNvbnN0IHdvcmtHcm91cFNpemU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9IFs2NCwgMSwgMV07XG4gIGNvbnN0IGRpc3BhdGNoTGF5b3V0ID0geyB4OiBvdXRwdXRTaGFwZS5tYXAoKF8sIGkpID0+IGkpIH07XG4gIGNvbnN0IGRpc3BhdGNoID0gW01hdGguY2VpbChhcnJheVByb2R1Y3QoZGlzcGF0Y2hMYXlvdXQueC5tYXAoKGQpID0+IG91dHB1dFNoYXBlW2RdKSkgLyB3b3JrR3JvdXBTaXplWzBdKSwgMSwgMV07XG5cbiAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtjb252M2RfbmFpdmVfd2ViZ3B1XSBkaXNwYXRjaCA9ICR7ZGlzcGF0Y2h9YCk7XG5cbiAgY29uc3QgaW5uZXJFbGVtZW50U2l6ZSA9IGlzVmVjNCA/IChpc0NoYW5uZWxMYXN0ICYmIGluQ2hhbm5lbHMgJSA0ICE9PSAwID8gMyA6IDQpIDogMTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGZpbHRlckRpbXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFkcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLnN0cmlkZXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXR0cmlidXRlcy5kaWxhdGlvbnMgfSxcbiAgXTtcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YShhdHRyaWJ1dGVzLCBwcm9ncmFtVW5pZm9ybXMpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgaW5wdXRzWzFdLmRpbXMpKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3JhbmsnLCAncmFuayddO1xuICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA9PT0gMztcbiAgaWYgKGhhc0JpYXMpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMl0uZGltcykpO1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3JhbmsnKTtcbiAgfVxuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRwdXRTaGFwZSkpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2ZpbHRlcl9kaW1zJywgdHlwZTogJ3UzMicsIGxlbmd0aDogZmlsdGVyRGltcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ3BhZHMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBwYWRzLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnc3RyaWRlcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGF0dHJpYnV0ZXMuc3RyaWRlcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ2RpbGF0aW9ucycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGF0dHJpYnV0ZXMuZGlsYXRpb25zLmxlbmd0aCB9LFxuICAgIF07XG4gICAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zKGF0dHJpYnV0ZXMsIHVuaWZvcm1zKTtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGNvbXBvbmVudCAyLCAzLlxuICAgIGNvbnN0IGNvbXBvbmVudHMgPSBpc1ZlYzQgPyA0IDogMTtcbiAgICBjb25zdCB0ID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKGlucHV0c1swXS5kYXRhVHlwZSk7XG5cbiAgICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZShcbiAgICAgICd4JyxcbiAgICAgIGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgIGlucHV0c1swXS5kaW1zLmxlbmd0aCxcbiAgICAgIGlubmVyRWxlbWVudFNpemUgPT09IDMgPyAxIDogaW5uZXJFbGVtZW50U2l6ZSxcbiAgICApO1xuICAgIGNvbnN0IHcgPSBpbnB1dFZhcmlhYmxlKCdXJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBpbnB1dHNbMV0uZGltcy5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGlucHV0VmFyaWFibGVzID0gW3gsIHddO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdyZXN1bHQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgbGV0IGRlY2xhcmVGdW5jdGlvbnMgPSAnJztcbiAgICBpZiAoaGFzQmlhcykge1xuICAgICAgY29uc3QgYmlhcyA9IGlucHV0VmFyaWFibGUoJ2JpYXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgICBpbnB1dFZhcmlhYmxlcy5wdXNoKGJpYXMpO1xuICAgICAgZGVjbGFyZUZ1bmN0aW9ucyArPSBgXG4gICAgICAgIGZuIGdldEJpYXNCeU91dHB1dENvb3Jkcyhjb29yZHMgOiBhcnJheTx1MzIsIDU+KSAtPiAke2lzVmVjNCA/IGB2ZWM0PCR7dH0+YCA6IHR9IHtcbiAgICAgICAgICByZXR1cm4gYmlhc1ske2lzQ2hhbm5lbExhc3QgPyBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDQsIDUpIDogZ2V0RWxlbWVudEF0KCdjb29yZHMnLCAxLCA1KX0ke1xuICAgICAgICAgICAgaXNWZWM0ID8gJy8gNCcgOiAnJ1xuICAgICAgICAgIH1dO1xuICAgICAgICB9YDtcbiAgICB9XG4gICAgY29uc3QgcmVzVHlwZSA9IHR5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemUsIHQpO1xuICAgIGNvbnN0IGFwcGx5QWN0aXZhdGlvbiA9IGdldEFjdGl2YXRpb25TbmlwcGV0KGF0dHJpYnV0ZXMsIHJlc1R5cGUsIHQpO1xuXG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgICR7ZGVjbGFyZUZ1bmN0aW9uc31cbiAgICAgICAgICAgIGZuIGdldFgoZDAgOiB1MzIsIGQxIDogdTMyLCBkMiA6IHUzMiwgZDMgOiB1MzIsIGQ0IDogdTMyKSAtPiBmMzIge1xuICAgICAgICAgICAgICBsZXQgYUluZGljZXMgPSBhcnJheTx1MzIsIDU+KGQwLCBkMSwgZDIsIGQzLCBkNCk7XG4gICAgICAgICAgICAgIHJldHVybiAke3guZ2V0QnlJbmRpY2VzKCdhSW5kaWNlcycpfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZuIGdldFcoZDAgOiB1MzIsIGQxIDogdTMyLCBkMiA6IHUzMiwgZDMgOiB1MzIsIGQ0IDogdTMyKSAtPiBmMzIge1xuICAgICAgICAgICAgICBsZXQgYUluZGljZXMgPSBhcnJheTx1MzIsIDU+KGQwLCBkMSwgZDIsIGQzLCBkNCk7XG4gICAgICAgICAgICAgIHJldHVybiAke3cuZ2V0QnlJbmRpY2VzKCdhSW5kaWNlcycpfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFyaWFibGVzLCBvdXRwdXQpfVxuICAgICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgICAgICAgICAgIGxldCBjb29yZHMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICAgICAgICAgIGxldCBiYXRjaCA9ICR7Z2V0RWxlbWVudEF0KCdjb29yZHMnLCAwLCB4LnJhbmspfTtcbiAgICAgICAgICAgICAgbGV0IGQyID0gJHtcbiAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0ID8gZ2V0RWxlbWVudEF0KCdjb29yZHMnLCB4LnJhbmsgLSAxLCB4LnJhbmspIDogZ2V0RWxlbWVudEF0KCdjb29yZHMnLCAxLCB4LnJhbmspXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGxldCB4RlJDQ29ybmVyID0gdmVjMzx1MzI+KCR7XG4gICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdCA/IGdldEVsZW1lbnRBdCgnY29vcmRzJywgMSwgeC5yYW5rKSA6IGdldEVsZW1lbnRBdCgnY29vcmRzJywgMiwgeC5yYW5rKVxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAke2lzQ2hhbm5lbExhc3QgPyBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDIsIHgucmFuaykgOiBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDMsIHgucmFuayl9LFxuICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3QgPyBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDMsIHgucmFuaykgOiBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDQsIHgucmFuaylcbiAgICAgICAgICAgICAgfSkgKiB1bmlmb3Jtcy5zdHJpZGVzIC0gdW5pZm9ybXMucGFkcztcbiAgICAgICAgICAgICAgbGV0IHhGQ29ybmVyID0geEZSQ0Nvcm5lci54O1xuICAgICAgICAgICAgICBsZXQgeFJDb3JuZXIgPSB4RlJDQ29ybmVyLnk7XG4gICAgICAgICAgICAgIGxldCB4Q0Nvcm5lciA9IHhGUkNDb3JuZXIuejtcbiAgICAgICAgICAgICAgbGV0IHhTaGFwZVkgPSAke1xuICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3RcbiAgICAgICAgICAgICAgICAgID8gZ2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgMSwgeC5yYW5rKVxuICAgICAgICAgICAgICAgICAgOiBnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCAyLCB4LnJhbmspXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGxldCB4U2hhcGVaID0gJHtcbiAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgICAgICAgICAgICA/IGdldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIDIsIHgucmFuaylcbiAgICAgICAgICAgICAgICAgIDogZ2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgMywgeC5yYW5rKVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBsZXQgeFNoYXBlVyA9ICR7XG4gICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICAgICAgICAgICAgPyBnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCAzLCB4LnJhbmspXG4gICAgICAgICAgICAgICAgICA6IGdldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIDQsIHgucmFuaylcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgbGV0IHhTaGFwZVUgPSAke1xuICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3RcbiAgICAgICAgICAgICAgICAgID8gZ2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgNCwgeC5yYW5rKVxuICAgICAgICAgICAgICAgICAgOiBnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCAxLCB4LnJhbmspXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGxldCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgPSAoeFNoYXBlVSAvIDQpICogNDtcbiAgICAgICAgICAgICAgbGV0IGlucHV0RGVwdGhWZWM0UmVtYWluZGVyID0geFNoYXBlVSAlIDQ7XG5cbiAgICAgICAgICAgICAgdmFyIHZhbHVlID0gMC4wO1xuICAgICAgICAgICAgICBmb3IgKHZhciB3RiA9IDB1OyB3RiA8IHVuaWZvcm1zLmZpbHRlcl9kaW1zWzBdOyB3RisrKSB7XG4gICAgICAgICAgICAgICAgbGV0IHhGID0geEZDb3JuZXIgKyB3RiAqIHVuaWZvcm1zLmRpbGF0aW9uc1swXTtcbiAgICAgICAgICAgICAgICBpZiAoeEYgPCAwIHx8IHhGID49IHhTaGFwZVkpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHdSID0gMHU7IHdSIDwgdW5pZm9ybXMuZmlsdGVyX2RpbXNbMV07IHdSKyspIHtcbiAgICAgICAgICAgICAgICAgIGxldCB4UiA9IHhSQ29ybmVyICsgd1IgKiB1bmlmb3Jtcy5kaWxhdGlvbnNbMV07XG4gICAgICAgICAgICAgICAgICBpZiAoeFIgPCAwIHx8IHhSID49IHhTaGFwZVopIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIGZvciAodmFyIHdDID0gMHU7IHdDIDwgdW5pZm9ybXMuZmlsdGVyX2RpbXNbMl07IHdDKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHhDID0geENDb3JuZXIgKyB3QyAqIHVuaWZvcm1zLmRpbGF0aW9uc1syXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHhDIDwgMCB8fCB4QyA+PSB4U2hhcGVXKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBkMSA9IDB1OyBkMSA8IGlucHV0RGVwdGhOZWFyZXN0VmVjNDsgZDEgKz0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICR7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgID8gYGxldCB4VmFsdWVzID0gdmVjNDxmMzI+KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGQxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBkMSArIDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGQxICsgMiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgZDEgKyAzKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICAgICAgICA6IGBsZXQgeFZhbHVlcyA9IHZlYzQ8ZjMyPihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCBkMSwgeEYsIHhSLCB4QyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgZDEgKyAxLCB4RiwgeFIsIHhDKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCBkMSArIDIsIHhGLCB4UiwgeEMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIGQxICsgMywgeEYsIHhSLCB4QykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHdWYWx1ZXMgPSB2ZWM0PGYzMj4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRXKGQyLCBkMSwgd0YsIHdSLCB3QyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRXKGQyLCBkMSArIDEsIHdGLCB3Uiwgd0MpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0VyhkMiwgZDEgKyAyLCB3Riwgd1IsIHdDKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFcoZDIsIGQxICsgMywgd0YsIHdSLCB3QykpO1xuICAgICAgICAgICAgICAgICAgICAgIHZhbHVlICs9IGRvdCh4VmFsdWVzLCB3VmFsdWVzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXREZXB0aFZlYzRSZW1haW5kZXIgPT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gYHZhbHVlICs9IGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGlucHV0RGVwdGhOZWFyZXN0VmVjNClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKiBnZXRXKGQyLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQsIHdGLCB3Uiwgd0MpO2BcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGB2YWx1ZSArPSBnZXRYKGJhdGNoLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQsIHhGLCB4UiwgeEMpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICogZ2V0VyhkMiwgaW5wdXREZXB0aE5lYXJlc3RWZWM0LCB3Riwgd1IsIHdDKTtgXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5wdXREZXB0aFZlYzRSZW1haW5kZXIgPT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICR7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgID8gYGxldCB4VmFsdWVzID0gdmVjMjxmMzI+KFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgaW5wdXREZXB0aE5lYXJlc3RWZWM0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCArIDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDogYGxldCB4VmFsdWVzID0gdmVjMjxmMzI+KFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgaW5wdXREZXB0aE5lYXJlc3RWZWM0LCB4RiwgeFIsIHhDKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCArIDEsIHhGLCB4UiwgeEMpKTtcbiAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGV0IHdWYWx1ZXMgPSB2ZWMyPGYzMj4oXG4gICAgICAgICAgICAgICAgICAgICAgZ2V0VyhkMiwgaW5wdXREZXB0aE5lYXJlc3RWZWM0LCB3Riwgd1IsIHdDKSxcbiAgICAgICAgICAgICAgICAgICAgICBnZXRXKGQyLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgKyAxLCB3Riwgd1IsIHdDKSk7XG4gICAgICAgICAgICAgICAgICAgICAgdmFsdWUgKz0gZG90KHhWYWx1ZXMsIHdWYWx1ZXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlucHV0RGVwdGhWZWM0UmVtYWluZGVyID09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICAgICAgICAgICAgICAgICAgICA/IGBsZXQgeFZhbHVlcyA9IHZlYzM8ZjMyPihcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCksXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgKyAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCArIDIpKTtcbiAgICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDogYGxldCB4VmFsdWVzID0gdmVjMzxmMzI+KFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgaW5wdXREZXB0aE5lYXJlc3RWZWM0LCB4RiwgeFIsIHhDKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCArIDEsIHhGLCB4UiwgeEMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgaW5wdXREZXB0aE5lYXJlc3RWZWM0ICsgMiwgeEYsIHhSLCB4QykpO1xuICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgd1ZhbHVlcyA9IHZlYzM8ZjMyPihcbiAgICAgICAgICAgICAgICAgICAgICBnZXRXKGQyLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQsIHdGLCB3Uiwgd0MpLFxuICAgICAgICAgICAgICAgICAgICAgIGdldFcoZDIsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCArIDEsIHdGLCB3Uiwgd0MpLFxuICAgICAgICAgICAgICAgICAgICAgIGdldFcoZDIsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCArIDIsIHdGLCB3Uiwgd0MpKTtcbiAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSArPSBkb3QoeFZhbHVlcywgd1ZhbHVlcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgJHtoYXNCaWFzID8gJ3ZhbHVlID0gdmFsdWUgKyBnZXRCaWFzQnlPdXRwdXRDb29yZHMoY29vcmRzKScgOiAnJ307XG4gICAgICAgICAgICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgICAgICAgICAgICByZXN1bHRbZ2xvYmFsX2lkeF0gPSBmMzIodmFsdWUpO1xuICAgICAgICAgIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdDb252M0ROYWl2ZScsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX07JHtpc0NoYW5uZWxMYXN0fTske2lubmVyRWxlbWVudFNpemV9OyR7aGFzQmlhc31gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogZGlzcGF0Y2hbMF0sIHk6IGRpc3BhdGNoWzFdLCB6OiBkaXNwYXRjaFsyXSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldE1heENvbXBvbmVudHMsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7IENvbnZBdHRyaWJ1dGVzIH0gZnJvbSAnLi9jb252JztcbmltcG9ydCB7IGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcywgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YSwgZ2V0QWN0aXZhdGlvblNuaXBwZXQgfSBmcm9tICcuL2Z1c2UtdXRpbHMnO1xuXG4vKipcbiAqIG5haXZlIGdyb3VwZWQgY29udiBpbXBsZW1lbnRhdGlvbiwgc3VwcG9ydHMgMWQvMmQgY29udlxuICogQHBhcmFtIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uIC0gYW4gb3B0aW9uYWwgZnVuY3Rpb24gdG8gc3F1ZWV6ZSB0aGUgb3V0cHV0IHNoYXBlLCBvbmx5IHVzZWQgaW4gY29udjFkXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVHcm91cGVkQ29udlByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMsXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPiAyO1xuICBjb25zdCBwcm9jZXNzQmlhcyA9IGhhc0JpYXMgPyAndmFsdWUgKz0gYltvdXRwdXRfY2hhbm5lbF07JyA6ICcnO1xuICBjb25zdCB4U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3Qgd1NoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG5cbiAgY29uc3QgaXNDaGFubmVsTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGNvbnN0IG91dHB1dENoYW5uZWxzID0gaXNDaGFubmVsTGFzdCA/IG91dHB1dFNoYXBlWzNdIDogb3V0cHV0U2hhcGVbMV07XG4gIGNvbnN0IG91dHB1dENoYW5uZWxzUGVyR3JvdXAgPSBvdXRwdXRDaGFubmVscyAvIGF0dHJpYnV0ZXMuZ3JvdXA7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBpc0NoYW5uZWxMYXN0ICYmIG91dHB1dENoYW5uZWxzUGVyR3JvdXAgPj0gNCA/IGdldE1heENvbXBvbmVudHMob3V0cHV0Q2hhbm5lbHMpIDogMTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIGNvbXBvbmVudHM7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF0dHJpYnV0ZXMuZGlsYXRpb25zIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IFthdHRyaWJ1dGVzLnN0cmlkZXNbMF0sIGF0dHJpYnV0ZXMuc3RyaWRlc1sxXV0gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogW2F0dHJpYnV0ZXMucGFkc1swXSwgYXR0cmlidXRlcy5wYWRzWzFdXSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRDaGFubmVsc1Blckdyb3VwIH0sXG4gIF07XG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEoYXR0cmlidXRlcywgcHJvZ3JhbVVuaWZvcm1zKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goXG4gICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoeFNoYXBlLCBbd1NoYXBlWzBdLCB3U2hhcGVbMV0sIHdTaGFwZVsyXSwgd1NoYXBlWzNdIC8gY29tcG9uZW50c10pLFxuICApO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IGhhc0JpYXMgPyBbJ3JhbmsnLCAncmFuaycsICdyYW5rJ10gOiBbJ3JhbmsnLCAncmFuayddO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaChcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhbb3V0cHV0U2hhcGVbMF0sIG91dHB1dFNoYXBlWzFdLCBvdXRwdXRTaGFwZVsyXSwgb3V0cHV0U2hhcGVbM10gLyBjb21wb25lbnRzXSksXG4gICk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBiYXNlVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShvdXRwdXQudHlwZS50ZW5zb3IpO1xuICAgIGNvbnN0IGFwcGx5QWN0aXZhdGlvbiA9IGdldEFjdGl2YXRpb25TbmlwcGV0KGF0dHJpYnV0ZXMsIG91dHB1dC50eXBlLnZhbHVlLCBiYXNlVHlwZSk7XG4gICAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIHhTaGFwZS5sZW5ndGgpO1xuICAgIGNvbnN0IHcgPSBpbnB1dFZhcmlhYmxlKCd3JywgaW5wdXRzWzFdLmRhdGFUeXBlLCB3U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBpbnB1dFZhcnMgPSBbeCwgd107XG4gICAgaWYgKGhhc0JpYXMpIHtcbiAgICAgIGlucHV0VmFycy5wdXNoKGlucHV0VmFyaWFibGUoJ2InLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLCBjb21wb25lbnRzKSk7XG4gICAgfVxuXG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnZGlsYXRpb25zJywgdHlwZTogJ3UzMicsIGxlbmd0aDogYXR0cmlidXRlcy5kaWxhdGlvbnMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdzdHJpZGVzJywgdHlwZTogJ3UzMicsIGxlbmd0aDogMiB9LFxuICAgICAgeyBuYW1lOiAncGFkcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IDIgfSxcbiAgICAgIHsgbmFtZTogJ291dHB1dF9jaGFubmVsc19wZXJfZ3JvdXAnLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG4gICAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zKGF0dHJpYnV0ZXMsIHVuaWZvcm1zKTtcblxuICAgIGNvbnN0IGNhbGN1bGF0ZVJlc3VsdCA9IGlzQ2hhbm5lbExhc3RcbiAgICAgID8gYFxuICAgICAgZm9yICh2YXIgd0hlaWdodDogdTMyID0gMHU7IHdIZWlnaHQgPCB1bmlmb3Jtcy53X3NoYXBlWzBdOyB3SGVpZ2h0KyspIHtcbiAgICAgICAgbGV0IHhIZWlnaHQgPSB4UkNDb3JuZXIueCArIHdIZWlnaHQgKiB1bmlmb3Jtcy5kaWxhdGlvbnNbMF07XG5cbiAgICAgICAgaWYgKHhIZWlnaHQgPCAwdSB8fCB4SGVpZ2h0ID49IHVuaWZvcm1zLnhfc2hhcGVbMV0pIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIHdXaWR0aDogdTMyID0gMHU7IHdXaWR0aCA8IHVuaWZvcm1zLndfc2hhcGVbMV07IHdXaWR0aCsrKSB7XG4gICAgICAgICAgbGV0IHhXaWR0aCA9IHhSQ0Nvcm5lci55ICsgd1dpZHRoICogdW5pZm9ybXMuZGlsYXRpb25zWzFdO1xuICAgICAgICAgIGlmICh4V2lkdGggPCAwdSB8fCB4V2lkdGggPj0gdW5pZm9ybXMueF9zaGFwZVsyXSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZm9yICh2YXIgd0luQ2hhbm5lbDogdTMyID0gMHU7IHdJbkNoYW5uZWwgPCB1bmlmb3Jtcy53X3NoYXBlWzJdOyB3SW5DaGFubmVsKyspIHtcbiAgICAgICAgICAgIGxldCBpbnB1dF9jaGFubmVsID0gaW5fY2hhbm5lbF9vZmZzZXQgKyB3SW5DaGFubmVsO1xuICAgICAgICAgICAgbGV0IHhWYWwgPSAke3guZ2V0KCdiYXRjaCcsICd4SGVpZ2h0JywgJ3hXaWR0aCcsICdpbnB1dF9jaGFubmVsJyl9O1xuICAgICAgICAgICAgbGV0IHdWYWwgPSAke3cuZ2V0KCd3SGVpZ2h0JywgJ3dXaWR0aCcsICd3SW5DaGFubmVsJywgJ291dHB1dF9jaGFubmVsJyl9O1xuICAgICAgICAgICAgdmFsdWUgKz0geFZhbCAqIHdWYWw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBgXG4gICAgICA6IGBcbiAgICAgIGZvciAodmFyIHdJbkNoYW5uZWw6IHUzMiA9IDB1OyB3SW5DaGFubmVsIDwgdW5pZm9ybXMud19zaGFwZVsxXTsgd0luQ2hhbm5lbCsrKSB7XG4gICAgICAgIGxldCBpbnB1dF9jaGFubmVsID0gaW5fY2hhbm5lbF9vZmZzZXQgKyB3SW5DaGFubmVsO1xuICAgICAgICBmb3IgKHZhciB3SGVpZ2h0OiB1MzIgPSAwdTsgd0hlaWdodCA8IHVuaWZvcm1zLndfc2hhcGVbMl07IHdIZWlnaHQrKykge1xuICAgICAgICAgIGxldCB4SGVpZ2h0ID0geFJDQ29ybmVyLnggKyB3SGVpZ2h0ICogdW5pZm9ybXMuZGlsYXRpb25zWzBdO1xuXG4gICAgICAgICAgaWYgKHhIZWlnaHQgPCAwdSB8fCB4SGVpZ2h0ID49IHVuaWZvcm1zLnhfc2hhcGVbMl0pIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGZvciAodmFyIHdXaWR0aDogdTMyID0gMHU7IHdXaWR0aCA8IHVuaWZvcm1zLndfc2hhcGVbM107IHdXaWR0aCsrKSB7XG4gICAgICAgICAgICBsZXQgeFdpZHRoID0geFJDQ29ybmVyLnkgKyB3V2lkdGggKiB1bmlmb3Jtcy5kaWxhdGlvbnNbMV07XG4gICAgICAgICAgICBpZiAoeFdpZHRoIDwgMHUgfHwgeFdpZHRoID49IHVuaWZvcm1zLnhfc2hhcGVbM10pIHtcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCB4VmFsID0gJHt4LmdldCgnYmF0Y2gnLCAnaW5wdXRfY2hhbm5lbCcsICd4SGVpZ2h0JywgJ3hXaWR0aCcpfTtcbiAgICAgICAgICAgIGxldCB3VmFsID0gJHt3LmdldCgnb3V0cHV0X2NoYW5uZWwnLCAnd0luQ2hhbm5lbCcsICd3SGVpZ2h0JywgJ3dXaWR0aCcpfTtcbiAgICAgICAgICAgIHZhbHVlICs9IHhWYWwgKiB3VmFsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFycywgb3V0cHV0KX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuXG4gICAgbGV0IG91dHB1dEluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgbGV0IGJhdGNoOiB1MzIgPSBvdXRwdXRJbmRpY2VzWzBdO1xuICAgIGxldCBvdXRwdXRfY2hhbm5lbDogdTMyID0gb3V0cHV0SW5kaWNlc1ske2lzQ2hhbm5lbExhc3QgPyAzIDogMX1dO1xuICAgIGxldCB4UkNDb3JuZXI6IHZlYzI8dTMyPiA9IHZlYzI8dTMyPihvdXRwdXRJbmRpY2VzWyR7aXNDaGFubmVsTGFzdCA/IDEgOiAyfV0sIG91dHB1dEluZGljZXNbJHtcbiAgICAgIGlzQ2hhbm5lbExhc3QgPyAyIDogM1xuICAgIH1dKSAqIHVuaWZvcm1zLnN0cmlkZXMgLSB1bmlmb3Jtcy5wYWRzO1xuICAgIGxldCBncm91cF9pZDogdTMyID0gb3V0cHV0X2NoYW5uZWwgKiAke2NvbXBvbmVudHN9IC8gdW5pZm9ybXMub3V0cHV0X2NoYW5uZWxzX3Blcl9ncm91cDtcbiAgICB2YXIgaW5fY2hhbm5lbF9vZmZzZXQgPSBncm91cF9pZCAqIHVuaWZvcm1zLndfc2hhcGVbJHtpc0NoYW5uZWxMYXN0ID8gMiA6IDF9XTtcblxuICAgIHZhciB2YWx1ZTogJHtvdXRwdXQudHlwZS52YWx1ZX0gPSAke291dHB1dC50eXBlLnZhbHVlfSgwKTtcbiAgICAke2NhbGN1bGF0ZVJlc3VsdH1cbiAgICAke3Byb2Nlc3NCaWFzfVxuICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3ZhbHVlJyl9XG4gIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdHcm91cGVkQ29udicsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX1fJHtjb21wb25lbnRzfWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGRpbXM6IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uID8gc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24ob3V0cHV0U2hhcGUpIDogb3V0cHV0U2hhcGUsXG4gICAgICAgICAgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUdyb3VwZWRDb252VmVjdG9yaXplUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyxcbiAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbj86IChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pID0+IG51bWJlcltdLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA+IDI7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKG91dHB1dFNoYXBlWzNdKTtcbiAgY29uc3Qgb3V0cHV0TnVtYmVyID0gZ2V0TWF4Q29tcG9uZW50cyhvdXRwdXRTaGFwZVsyXSk7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyBjb21wb25lbnRzIC8gb3V0cHV0TnVtYmVyO1xuICBjb25zdCB4U2hhcGUgPSBbaW5wdXRzWzBdLmRpbXNbMF0sIGlucHV0c1swXS5kaW1zWzFdLCBpbnB1dHNbMF0uZGltc1syXSwgaW5wdXRzWzBdLmRpbXNbM10gLyBjb21wb25lbnRzXTtcbiAgY29uc3Qgd1NoYXBlID0gW2lucHV0c1sxXS5kaW1zWzBdLCBpbnB1dHNbMV0uZGltc1sxXSwgaW5wdXRzWzFdLmRpbXNbMl0sIGlucHV0c1sxXS5kaW1zWzNdIC8gY29tcG9uZW50c107XG4gIGNvbnN0IG91dHB1dFNoYXBlSW5TaGFkZXIgPSBbb3V0cHV0U2hhcGVbMF0sIG91dHB1dFNoYXBlWzFdLCBvdXRwdXRTaGFwZVsyXSwgb3V0cHV0U2hhcGVbM10gLyBjb21wb25lbnRzXTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBbYXR0cmlidXRlcy5zdHJpZGVzWzBdLCBhdHRyaWJ1dGVzLnN0cmlkZXNbMV1dIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogW2F0dHJpYnV0ZXMucGFkc1swXSwgYXR0cmlidXRlcy5wYWRzWzFdXSB9LFxuICBdO1xuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhKGF0dHJpYnV0ZXMsIHByb2dyYW1Vbmlmb3Jtcyk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKHhTaGFwZSwgd1NoYXBlLCBvdXRwdXRTaGFwZUluU2hhZGVyKSk7XG4gIGNvbnN0IHhOdW1iZXIgPSAob3V0cHV0TnVtYmVyIC0gMSkgKiBhdHRyaWJ1dGVzLnN0cmlkZXNbMV0gKyB3U2hhcGVbMV07XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlSW5TaGFkZXIubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBiYXNlVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShvdXRwdXQudHlwZS50ZW5zb3IpO1xuICAgIGNvbnN0IGFwcGx5QWN0aXZhdGlvbiA9IGdldEFjdGl2YXRpb25TbmlwcGV0KGF0dHJpYnV0ZXMsIG91dHB1dC50eXBlLnZhbHVlLCBiYXNlVHlwZSk7XG4gICAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIHhTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IHcgPSBpbnB1dFZhcmlhYmxlKCd3JywgaW5wdXRzWzFdLmRhdGFUeXBlLCB3U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBpbnB1dFZhcnMgPSBbeCwgd107XG4gICAgaWYgKGhhc0JpYXMpIHtcbiAgICAgIGlucHV0VmFycy5wdXNoKGlucHV0VmFyaWFibGUoJ2InLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLCBjb21wb25lbnRzKSk7XG4gICAgfVxuICAgIGNvbnN0IHByb2Nlc3NCaWFzID0gaGFzQmlhcyA/ICd2YWx1ZSArPSBiW291dHB1dF9jaGFubmVsXTsnIDogJyc7XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnc3RyaWRlcycsIHR5cGU6ICdpMzInLCBsZW5ndGg6IDIgfSxcbiAgICAgIHsgbmFtZTogJ3BhZHMnLCB0eXBlOiAnaTMyJywgbGVuZ3RoOiAyIH0sXG4gICAgXTtcbiAgICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMoYXR0cmlidXRlcywgdW5pZm9ybXMpO1xuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJzLCBvdXRwdXQpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICAgIGxldCB3aWR0aDAgPSB1bmlmb3Jtcy5vdXRwdXRfc2hhcGVbM107XG4gICAgbGV0IG91dHB1dF9jaGFubmVsID0gZ2xvYmFsX2lkeCAlIHdpZHRoMDtcbiAgICB2YXIgaW5kZXgxID0gZ2xvYmFsX2lkeCAvIHdpZHRoMDtcbiAgICBsZXQgd2lkdGgxID0gdW5pZm9ybXMub3V0cHV0X3NoYXBlWzJdIC8gJHtvdXRwdXROdW1iZXJ9dTtcbiAgICBsZXQgY29sID0gKGluZGV4MSAlIHdpZHRoMSkgKiAke291dHB1dE51bWJlcn11O1xuICAgIGluZGV4MSA9IGluZGV4MSAvIHdpZHRoMTtcbiAgICBsZXQgcm93ID0gaW5kZXgxICUgdW5pZm9ybXMub3V0cHV0X3NoYXBlWzFdO1xuICAgIGxldCBiYXRjaCA9IGluZGV4MSAvIHVuaWZvcm1zLm91dHB1dF9zaGFwZVsxXTtcblxuICAgIGxldCB4X2Nvcm5lciA9IHZlYzI8aTMyPihpMzIocm93KSwgaTMyKGNvbCkpICogdW5pZm9ybXMuc3RyaWRlcyAtIHVuaWZvcm1zLnBhZHM7XG5cbiAgICB2YXIgeF92YWxzOiBhcnJheTwke3gudHlwZS52YWx1ZX0sICR7eE51bWJlcn0+O1xuICAgIHZhciB2YWx1ZXM6IGFycmF5PCR7b3V0cHV0LnR5cGUudmFsdWV9LCAke291dHB1dE51bWJlcn0+O1xuICAgIGxldCBpbnB1dF9jaGFubmVsID0gb3V0cHV0X2NoYW5uZWw7XG4gICAgLy8gVXNlIGNvbnN0YW50IGluc3RlYWQgb2YgdW5pZm9ybSBjYW4gZ2l2ZSBiZXR0ZXIgcGVyZm9ybWFuY2UgZm9yIHcncyBoZWlnaHQvd2lkdGguXG4gICAgZm9yICh2YXIgd19oZWlnaHQ6IHUzMiA9IDB1OyB3X2hlaWdodCA8ICR7d1NoYXBlWzBdfTsgd19oZWlnaHQrKykge1xuICAgICAgbGV0IHhfaGVpZ2h0ID0geF9jb3JuZXIueCArIGkzMih3X2hlaWdodCk7XG4gICAgICBpZiAoeF9oZWlnaHQgPj0gMCAmJiB1MzIoeF9oZWlnaHQpIDwgdW5pZm9ybXMueF9zaGFwZVsxXSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8ICR7eE51bWJlcn07IGkrKykge1xuICAgICAgICAgIGxldCB4X3dpZHRoID0geF9jb3JuZXIueSArIGk7XG4gICAgICAgICAgaWYgKHhfd2lkdGggPj0gMCAmJiB1MzIoeF93aWR0aCkgPCB1bmlmb3Jtcy54X3NoYXBlWzJdKSB7XG4gICAgICAgICAgICB4X3ZhbHNbaV0gPSAke3guZ2V0KCdiYXRjaCcsICd1MzIoeF9oZWlnaHQpJywgJ3UzMih4X3dpZHRoKScsICdpbnB1dF9jaGFubmVsJyl9O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB4X3ZhbHNbaV0gPSAke3gudHlwZS52YWx1ZX0oMCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIHdfd2lkdGg6IHUzMiA9IDB1OyB3X3dpZHRoIDwgJHt3U2hhcGVbMV19OyB3X3dpZHRoKyspIHtcbiAgICAgICAgICBsZXQgd192YWwgPSAke3cuZ2V0KCd3X2hlaWdodCcsICd3X3dpZHRoJywgJzAnLCAnb3V0cHV0X2NoYW5uZWwnKX07XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDB1OyBpIDwgJHtvdXRwdXROdW1iZXJ9dTsgaSsrKSB7XG4gICAgICAgICAgICB2YWx1ZXNbaV0gPSBmbWEoeF92YWxzW2kgKiB1MzIodW5pZm9ybXMuc3RyaWRlc1sxXSkgKyB3X3dpZHRoXSwgd192YWwsIHZhbHVlc1tpXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDB1OyBpIDwgJHtvdXRwdXROdW1iZXJ9dTsgaSsrKSB7XG4gICAgICB2YXIgdmFsdWUgPSB2YWx1ZXNbaV07XG4gICAgICAke3Byb2Nlc3NCaWFzfVxuICAgICAgJHthcHBseUFjdGl2YXRpb259XG4gICAgICAke291dHB1dC5zZXQoJ2JhdGNoJywgJ3JvdycsICdjb2wgKyBpJywgJ291dHB1dF9jaGFubmVsJywgJ3ZhbHVlJyl9O1xuICAgIH1cbiAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnR3JvdXBlZENvbnYtVmVjdG9yaXplJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX07JHtjb21wb25lbnRzfTske291dHB1dE51bWJlcn07JHt4TnVtYmVyfTske3dTaGFwZVswXX07JHt3U2hhcGVbMV19YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBoYXNCaWFzID8gWydyYW5rJywgJ3JhbmsnLCAndHlwZSddIDogWydyYW5rJywgJ3JhbmsnXSxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBkaW1zOiBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiA/IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uKG91dHB1dFNoYXBlKSA6IG91dHB1dFNoYXBlLFxuICAgICAgICAgIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBQb29sQ29udlV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlQ29udjJETWF0TXVsUHJvZ3JhbUluZm8gfSBmcm9tICcuLzNyZC1wYXJ0eS9jb252MmRfbW1fd2ViZ3B1JztcbmltcG9ydCB7IGNvbXB1dGVDb252M0RJbmZvLCBjcmVhdGVDb252M0ROYWl2ZVByb2dyYW1JbmZvIH0gZnJvbSAnLi8zcmQtcGFydHkvY29udjNkX25haXZlX3dlYmdwdSc7XG5pbXBvcnQgeyBjcmVhdGVNYXRtdWxQcm9ncmFtSW5mbyB9IGZyb20gJy4vM3JkLXBhcnR5L21hdG11bF9wYWNrZWRfd2ViZ3B1JztcbmltcG9ydCB7IGNyZWF0ZUdyb3VwZWRDb252UHJvZ3JhbUluZm8sIGNyZWF0ZUdyb3VwZWRDb252VmVjdG9yaXplUHJvZ3JhbUluZm8gfSBmcm9tICcuL2NvbnYtZ3JvdXBlZCc7XG5pbXBvcnQgeyBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLCBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMgfSBmcm9tICcuL2Z1c2UtdXRpbHMnO1xuaW1wb3J0IHsgY3JlYXRlTmFpdmVNYXRtdWxQcm9ncmFtSW5mbyB9IGZyb20gJy4vbWF0bXVsLXNoYWRlcnMnO1xuaW1wb3J0IHsgY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8gfSBmcm9tICcuL3RyYW5zcG9zZSc7XG5cbmV4cG9ydCBjb25zdCBjYWxjdWxhdGVPdXRwdXRTaGFwZSA9IChcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXSxcbiAgYWRqdXN0UGFkczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICBpc0NoYW5uZWxMYXN0OiBib29sZWFuLFxuKTogbnVtYmVyW10gPT4ge1xuICBjb25zdCBiYXRjaFNpemUgPSBpbnB1dFNoYXBlWzBdO1xuICBjb25zdCBpbnB1dFNwYXRpYWxTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoaXNDaGFubmVsTGFzdCA/IDEgOiAyLCBpc0NoYW5uZWxMYXN0ID8gMyA6IDQpO1xuICBjb25zdCBzcGF0aWFsUmFuayA9IGlucHV0U3BhdGlhbFNoYXBlLmxlbmd0aDtcbiAgY29uc3Qgb3V0Q2hhbm5lbHMgPSBrZXJuZWxTaGFwZVswXTtcbiAgY29uc3Qga2VybmVsU3BhdGlhbFNoYXBlID0ga2VybmVsU2hhcGUuc2xpY2UoMik7XG4gIGNvbnN0IGRpbGF0ZWRLZXJuZWxTaGFwZSA9IGtlcm5lbFNwYXRpYWxTaGFwZS5tYXAoKHYsIGkpID0+IHYgKyAodiAtIDEpICogKGRpbGF0aW9uc1tpXSAtIDEpKTtcbiAgY29uc3QgaW5wdXRTcGF0aWFsU2hhcGVXaXRoUGFkID0gaW5wdXRTcGF0aWFsU2hhcGUubWFwKCh2LCBpKSA9PiB2ICsgYWRqdXN0UGFkc1tpXSArIGFkanVzdFBhZHNbaSArIHNwYXRpYWxSYW5rXSk7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRTcGF0aWFsU2hhcGVXaXRoUGFkLm1hcCgodiwgaSkgPT5cbiAgICBNYXRoLmZsb29yKCh2IC0gZGlsYXRlZEtlcm5lbFNoYXBlW2ldICsgc3RyaWRlc1tpXSkgLyBzdHJpZGVzW2ldKSxcbiAgKTtcbiAgb3V0cHV0U2hhcGUuc3BsaWNlKDAsIDAsIGJhdGNoU2l6ZSk7XG4gIG91dHB1dFNoYXBlLnNwbGljZShpc0NoYW5uZWxMYXN0ID8gMyA6IDEsIDAsIG91dENoYW5uZWxzKTtcbiAgcmV0dXJuIG91dHB1dFNoYXBlO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBDb252QXR0cmlidXRlcyBleHRlbmRzIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGF1dG9QYWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgZm9ybWF0OiAnTkhXQycgfCAnTkNIVyc7XG4gIHJlYWRvbmx5IGdyb3VwOiBudW1iZXI7XG4gIHJlYWRvbmx5IGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgcGFkczogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSB3SXNDb25zdDogYm9vbGVhbjtcbn1cblxuLy8gZm9yIHRyYW5zcG9zaW5nIHdlaWdodCB0ZW5zb3IgZnJvbSBbTSwgQy9ncm91cCwgS0gsIEtXXSB0byBbS0gsIEtXLCBDL2dyb3VwLCBNXVxuY29uc3Qgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlID0gWzIsIDMsIDEsIDBdO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgLy8gUmVmZXIgdG8gdGhlIGJlbG93IGxpbmsgZm9yIGFsbCBpbnB1dCBjaGVja3NcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL29ubngvb25ueC9ibG9iL21hc3Rlci9kb2NzL09wZXJhdG9ycy5tZCNDb252XG4gIGlmICghaW5wdXRzIHx8IChpbnB1dHMubGVuZ3RoICE9PSAyICYmIGlucHV0cy5sZW5ndGggIT09IDMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb252IHJlcXVpcmVzIDIgb3IgMyBpbnB1dHMnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggPiA1KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdncmVhdGVyIHRoYW4gNUQgaXMgbm90IHN1cHBvcnRlZCcpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdmaWx0ZXIgZG9lcyBub3QgaGF2ZSBzYW1lIGRpbWVuc2lvbiBhcyBpbnB1dCcpO1xuICB9XG5cbiAgLy8gRklMVEVSX0lOX0NIQU5ORUwgc2hvdWxkIGJlIGVxdWFsIHRvIERBVEFfQ0hBTk5FTFxuICBjb25zdCBkYXRhQ2hhbm5lbCA9IGlucHV0c1swXS5kaW1zW2F0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQycgPyBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAxIDogMV07XG4gIGNvbnN0IGZpbHRlckluQ2hhbm5lbCA9IGlucHV0c1sxXS5kaW1zWzFdICogYXR0cmlidXRlcy5ncm91cDtcbiAgaWYgKGRhdGFDaGFubmVsICE9PSBmaWx0ZXJJbkNoYW5uZWwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZJTFRFUl9JTl9DSEFOTkVMIHNob3VsZCBiZSBlcXVhbCB0byBEQVRBX0NIQU5ORUwnKTtcbiAgfVxuXG4gIC8vIGlmIGJpYXMgaXMgcHJvdmlkZWQgaXQgc2hvdWxkIGJlIDFEIGFuZCB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIHNob3VsZCBiZSBlcXVhbCB0byB0aGUgbnVtYmVyIG9mIGZlYXR1cmUgbWFwc1xuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiAoaW5wdXRzWzJdLmRpbXMubGVuZ3RoICE9PSAxIHx8IGlucHV0c1sxXS5kaW1zWzBdICE9PSBpbnB1dHNbMl0uZGltc1swXSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYmlhcycpO1xuICB9XG5cbiAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAyO1xuICAvLyB3cm9uZyBkaWxhdGlvbnMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLmRpbGF0aW9ucy5sZW5ndGggIT09IHNwYXRpYWxSYW5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBkaWxhdGlvbnMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmt9RGApO1xuICB9XG5cbiAgLy8gV3Jvbmcgc3RyaWRlcyBkaW1lbnNpb25cbiAgaWYgKGF0dHJpYnV0ZXMuc3RyaWRlcy5sZW5ndGggIT09IHNwYXRpYWxSYW5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBzdHJpZGVzIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIFdyb25nIHBhZHMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoICE9PSBzcGF0aWFsUmFuayAqIDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHBhZHMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmsgKiAyfURgKTtcbiAgfVxuXG4gIC8vIGlmIGtlcm5lbFNoYXBlIGlzIHNwZWNpZmllZCwgaXQncyBkYXRhIGxlbmd0aCBtdXN0IGJlIDIgbGVzcyB0aGFuIGRpbXMgbGVuZ3RoIG9mIHRoZSB3ZWlnaHRzIHRlbnNvclxuICAvLyAodGhlIGZpcnN0IDIgZGltcyBhcmUgYmF0Y2hfc2l6ZSBhbmQgY2hhbm5lbHMpXG4gIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gMCAmJiBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoIC0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBrZXJuZWwgc2hhcGUnKTtcbiAgfVxufTtcblxuY29uc3QgZ2V0QWRqdXN0ZWRDb252QXR0cmlidXRlcyA9IDxUIGV4dGVuZHMgQ29udkF0dHJpYnV0ZXM+KGF0dHJpYnV0ZXM6IFQsIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogVCA9PiB7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5zbGljZSgpO1xuICAvLyBpZiBrZXJuZWxTaGFwZSBpcyBub3Qgd2VsbCBzcGVjaWZpZWQgaW4gdGhlIGF0dHJpYnV0ZXMsIGluZmVyIGl0IGZyb20gdGhlIHdlaWdodCB0ZW5zb3IgZGltc1xuICBpZiAoa2VybmVsU2hhcGUubGVuZ3RoIDwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoIC0gMikge1xuICAgIGtlcm5lbFNoYXBlLnB1c2goLi4uQXJyYXkoaW5wdXRzWzFdLmRpbXMubGVuZ3RoIC0gMiAtIGtlcm5lbFNoYXBlLmxlbmd0aCkuZmlsbCgwKSk7XG4gIH1cbiAgZm9yIChsZXQgaSA9IDI7IGkgPCBpbnB1dHNbMV0uZGltcy5sZW5ndGg7ICsraSkge1xuICAgIGlmIChrZXJuZWxTaGFwZVtpIC0gMl0gPT09IDApIHtcbiAgICAgIGtlcm5lbFNoYXBlW2kgLSAyXSA9IGlucHV0c1sxXS5kaW1zW2ldO1xuICAgIH1cbiAgfVxuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5wYWRzLnNsaWNlKCk7XG4gIFBvb2xDb252VXRpbC5hZGp1c3RQYWRzQmFzZWRPbkF1dG9QYWQoXG4gICAgaW5wdXRzWzBdLmRpbXMsXG4gICAgYXR0cmlidXRlcy5zdHJpZGVzLFxuICAgIGF0dHJpYnV0ZXMuZGlsYXRpb25zLFxuICAgIGtlcm5lbFNoYXBlLFxuICAgIHBhZHMsXG4gICAgYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJyxcbiAgICBhdHRyaWJ1dGVzLmF1dG9QYWQsXG4gICk7XG5cbiAgLy8gYWx3YXlzIHJldHVybiBhIG5ldyBvYmplY3Qgc28gZG9lcyBub3QgbW9kaWZ5IHRoZSBvcmlnaW5hbCBhdHRyaWJ1dGVzXG4gIGNvbnN0IG5ld0F0dHJpYnV0ZXM6IFQgPSBPYmplY3QuYXNzaWduKHt9LCBhdHRyaWJ1dGVzKTtcbiAgT2JqZWN0LmFzc2lnbihuZXdBdHRyaWJ1dGVzLCB7IGtlcm5lbFNoYXBlLCBwYWRzIH0pO1xuICByZXR1cm4gbmV3QXR0cmlidXRlcztcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUNvbnZBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQ29udkF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBhY3RpdmF0aW9uQXR0cmlidXRlcyA9IHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyhhdHRyaWJ1dGVzKTtcbiAgLy8gVE9ETyA6IE1ha2UgdGhpcyBnZW5lcmljIGVub3VnaCB0byBjb21wdXRlIGRlZmF1bHQgYXR0cmlidXRlcyBmb3IgbXVsdGktZGltZW5zaW9uYWwgY29udlxuICBjb25zdCBmb3JtYXQgPSBhdHRyaWJ1dGVzLmZvcm1hdCBhcyAnTkhXQycgfCAnTkNIVyc7XG4gIGNvbnN0IGF1dG9QYWQgPSBbJ05PVFNFVCcsICdWQUxJRCcsICdTQU1FX1VQUEVSJywgJ1NBTUVfTE9XRVInXVthdHRyaWJ1dGVzLmF1dG9fcGFkIGFzIG51bWJlcl07XG4gIGNvbnN0IGRpbGF0aW9ucyA9IGF0dHJpYnV0ZXMuZGlsYXRpb25zIGFzIG51bWJlcltdO1xuICBjb25zdCBncm91cCA9IGF0dHJpYnV0ZXMuZ3JvdXAgYXMgbnVtYmVyO1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMua2VybmVsX3NoYXBlIGFzIG51bWJlcltdO1xuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5wYWRzIGFzIG51bWJlcltdO1xuICBjb25zdCBzdHJpZGVzID0gYXR0cmlidXRlcy5zdHJpZGVzIGFzIG51bWJlcltdO1xuICBjb25zdCB3SXNDb25zdCA9IChhdHRyaWJ1dGVzLndfaXNfY29uc3QgYXMgKCkgPT4gYm9vbGVhbikoKTtcblxuICByZXR1cm4ge1xuICAgIGF1dG9QYWQsXG4gICAgZm9ybWF0LFxuICAgIGRpbGF0aW9ucyxcbiAgICBncm91cCxcbiAgICBrZXJuZWxTaGFwZSxcbiAgICBwYWRzLFxuICAgIHN0cmlkZXMsXG4gICAgd0lzQ29uc3QsXG4gICAgLi4uYWN0aXZhdGlvbkF0dHJpYnV0ZXMsXG4gICAgY2FjaGVLZXk6IGAke2F0dHJpYnV0ZXMuZm9ybWF0fTske2FjdGl2YXRpb25BdHRyaWJ1dGVzLmFjdGl2YXRpb259O2AsXG4gIH07XG59O1xuXG5jb25zdCBjb252MmQgPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMsXG4gIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uPzogKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4gbnVtYmVyW10sXG4pOiB2b2lkID0+IHtcbiAgLy8gY2hlY2sgYXR0cmlidXRlc1xuXG4gIC8vIGNvbnN0IGhhc1ByZWx1QWN0aXZhdGlvbldlaWdodHMgPSBmYWxzZTsgLyogVE9ETzogYWRkIHN1cHBvcnQgZm9yIHByZWx1IGFjdGl2YXRpb24gd2VpZ2h0cyAqL1xuICBjb25zdCBpc0NoYW5uZWxzTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gY2FsY3VsYXRlT3V0cHV0U2hhcGUoXG4gICAgaW5wdXRzWzBdLmRpbXMsXG4gICAgaW5wdXRzWzFdLmRpbXMsXG4gICAgYXR0cmlidXRlcy5kaWxhdGlvbnMsXG4gICAgYXR0cmlidXRlcy5wYWRzLFxuICAgIGF0dHJpYnV0ZXMuc3RyaWRlcyxcbiAgICBpc0NoYW5uZWxzTGFzdCxcbiAgKTtcbiAgaWYgKGF0dHJpYnV0ZXMuZ3JvdXAgIT09IDEpIHtcbiAgICBjb25zdCBjb252SW5wdXRzID0gW2lucHV0c1swXV07XG4gICAgaWYgKGlzQ2hhbm5lbHNMYXN0KSB7XG4gICAgICBjb25zdCB0cmFuc3Bvc2VkV2VpZ2h0ID1cbiAgICAgICAgKGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCBhcyBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkKSA/P1xuICAgICAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8oaW5wdXRzWzFdLCB3ZWlnaHRUcmFuc3Bvc2VBdHRyaWJ1dGUpLCB7XG4gICAgICAgICAgaW5wdXRzOiBbMV0sXG4gICAgICAgICAgb3V0cHV0czogW2F0dHJpYnV0ZXMud0lzQ29uc3QgPyAtMiA6IC0xXSxcbiAgICAgICAgfSlbMF07XG4gICAgICBpZiAoYXR0cmlidXRlcy53SXNDb25zdCAmJiAhY29udGV4dC5rZXJuZWxDdXN0b21EYXRhLndUKSB7XG4gICAgICAgIGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCA9IHRyYW5zcG9zZWRXZWlnaHQ7XG4gICAgICB9XG4gICAgICBjb252SW5wdXRzLnB1c2godHJhbnNwb3NlZFdlaWdodCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnZJbnB1dHMucHVzaChpbnB1dHNbMV0pO1xuICAgIH1cbiAgICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMykge1xuICAgICAgY29udklucHV0cy5wdXNoKGlucHV0c1syXSk7XG4gICAgfVxuICAgIC8vIE5WSURJQSBHUFUgd2l0aCBhbXBlcmUgYXJjaGl0ZWN0dXJlIGZhaWxzIHdpdGggYmVsb3cgMiBjYXNlcywgYnV0IHdlIGNvdWxkbid0IHJlcHJvIHRoZW0gd2l0aCBhbnkgb3RoZXJcbiAgICAvLyBHUFVzLiBTbyBqdXN0IGRpc2FibGUgdmVjdG9yaXplIG9uIE5WSURJQSBhbXBlcmUgdG8gZW5zdXJlIGFsd2F5cyBjb3JyZWN0IG91dHB1dHMuXG4gICAgLy8gW3dlYmdwdV1Db252IC0gY29udiAtIHZlY3Rvcml6ZSBncm91cCAtIEJcbiAgICAvLyBbd2ViZ3B1XUNvbnYgLSBjb252IC0gdmVjdG9yaXplIGdyb3VwIC0gRFxuICAgIGNvbnN0IGVuYWJsZUdyb3VwZWRDb252VmVjdG9yaXplID0gIWNvbnRleHQuYWRhcHRlckluZm8uaXNBcmNoaXRlY3R1cmUoJ2FtcGVyZScpO1xuICAgIGlmIChcbiAgICAgIGVuYWJsZUdyb3VwZWRDb252VmVjdG9yaXplICYmXG4gICAgICBpc0NoYW5uZWxzTGFzdCAmJlxuICAgICAgaW5wdXRzWzFdLmRpbXNbMF0gPT09IGF0dHJpYnV0ZXMuZ3JvdXAgJiZcbiAgICAgIGlucHV0c1sxXS5kaW1zWzFdID09PSAxICYmXG4gICAgICBhdHRyaWJ1dGVzLmRpbGF0aW9uc1swXSA9PT0gMSAmJlxuICAgICAgYXR0cmlidXRlcy5kaWxhdGlvbnNbMV0gPT09IDFcbiAgICApIHtcbiAgICAgIGNvbnRleHQuY29tcHV0ZShcbiAgICAgICAgY3JlYXRlR3JvdXBlZENvbnZWZWN0b3JpemVQcm9ncmFtSW5mbyhjb252SW5wdXRzLCBhdHRyaWJ1dGVzLCBvdXRwdXRTaGFwZSwgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24pLFxuICAgICAgICB7IGlucHV0czogY29udklucHV0cyB9LFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUdyb3VwZWRDb252UHJvZ3JhbUluZm8oY29udklucHV0cywgYXR0cmlidXRlcywgb3V0cHV0U2hhcGUsIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uKSwge1xuICAgICAgICBpbnB1dHM6IGNvbnZJbnB1dHMsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPT09IDM7XG4gIGNvbnN0IGlucHV0SGVpZ2h0ID0gaW5wdXRzWzBdLmRpbXNbaXNDaGFubmVsc0xhc3QgPyAxIDogMl07XG4gIGNvbnN0IGlucHV0V2lkdGggPSBpbnB1dHNbMF0uZGltc1tpc0NoYW5uZWxzTGFzdCA/IDIgOiAzXTtcbiAgY29uc3QgaW5wdXRDaGFubmVscyA9IGlucHV0c1swXS5kaW1zW2lzQ2hhbm5lbHNMYXN0ID8gMyA6IDFdO1xuICBjb25zdCB3ZWlnaHRIZWlnaHQgPSBpbnB1dHNbMV0uZGltc1syXTtcbiAgY29uc3Qgd2VpZ2h0V2lkdGggPSBpbnB1dHNbMV0uZGltc1szXTtcblxuICBjb25zdCBvdXRIZWlnaHQgPSBvdXRwdXRTaGFwZVtpc0NoYW5uZWxzTGFzdCA/IDEgOiAyXTtcbiAgY29uc3Qgb3V0V2lkdGggPSBvdXRwdXRTaGFwZVtpc0NoYW5uZWxzTGFzdCA/IDIgOiAzXTtcbiAgY29uc3Qgb3V0Q2hhbm5lbHMgPSBvdXRwdXRTaGFwZVtpc0NoYW5uZWxzTGFzdCA/IDMgOiAxXTtcblxuICBjb25zdCBzYW1lU2l6ZSA9XG4gICAgaXNDaGFubmVsc0xhc3QgJiZcbiAgICB3ZWlnaHRIZWlnaHQgPT09IGlucHV0SGVpZ2h0ICYmXG4gICAgd2VpZ2h0V2lkdGggPT09IGlucHV0V2lkdGggJiZcbiAgICBhdHRyaWJ1dGVzLnBhZHNbMF0gPT09IDAgJiZcbiAgICBhdHRyaWJ1dGVzLnBhZHNbMV0gPT09IDA7XG4gIGlmIChcbiAgICBzYW1lU2l6ZSB8fFxuICAgICh3ZWlnaHRIZWlnaHQgPT09IDEgJiZcbiAgICAgIHdlaWdodFdpZHRoID09PSAxICYmXG4gICAgICBhdHRyaWJ1dGVzLmRpbGF0aW9uc1swXSA9PT0gMSAmJlxuICAgICAgYXR0cmlidXRlcy5kaWxhdGlvbnNbMV0gPT09IDEgJiZcbiAgICAgIGF0dHJpYnV0ZXMuc3RyaWRlc1swXSA9PT0gMSAmJlxuICAgICAgYXR0cmlidXRlcy5zdHJpZGVzWzFdID09PSAxICYmXG4gICAgICBhdHRyaWJ1dGVzLnBhZHNbMF0gPT09IDAgJiZcbiAgICAgIGF0dHJpYnV0ZXMucGFkc1sxXSA9PT0gMClcbiAgKSB7XG4gICAgLy8gY29udjJkQnlNYXRNdWxcbiAgICBjb25zdCBiYXRjaCA9IG91dHB1dFNoYXBlWzBdO1xuICAgIGxldCB4UmVzaGFwZWQsIHdSZXNoYXBlZCwgbWF0bXVsT3V0cHV0U2hhcGU7XG4gICAgY29uc3QgbWF0bXVsSW5wdXRzID0gW107XG4gICAgaWYgKGlzQ2hhbm5lbHNMYXN0KSB7XG4gICAgICBjb25zdCB0cmFuc3Bvc2VkV2VpZ2h0ID1cbiAgICAgICAgKGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCBhcyBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkKSA/P1xuICAgICAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8oaW5wdXRzWzFdLCB3ZWlnaHRUcmFuc3Bvc2VBdHRyaWJ1dGUpLCB7XG4gICAgICAgICAgaW5wdXRzOiBbMV0sXG4gICAgICAgICAgb3V0cHV0czogW2F0dHJpYnV0ZXMud0lzQ29uc3QgPyAtMiA6IC0xXSxcbiAgICAgICAgfSlbMF07XG4gICAgICBpZiAoYXR0cmlidXRlcy53SXNDb25zdCAmJiAhY29udGV4dC5rZXJuZWxDdXN0b21EYXRhLndUKSB7XG4gICAgICAgIGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCA9IHRyYW5zcG9zZWRXZWlnaHQ7XG4gICAgICB9XG4gICAgICBpZiAoc2FtZVNpemUpIHtcbiAgICAgICAgY29uc3Qgc2hhcmVkRGltID0gaW5wdXRIZWlnaHQgKiBpbnB1dFdpZHRoICogaW5wdXRDaGFubmVscztcbiAgICAgICAgeFJlc2hhcGVkID0gaW5wdXRzWzBdLnJlc2hhcGUoWzEsIGJhdGNoLCBzaGFyZWREaW1dKTtcbiAgICAgICAgd1Jlc2hhcGVkID0gdHJhbnNwb3NlZFdlaWdodC5yZXNoYXBlKFsxLCBzaGFyZWREaW0sIG91dENoYW5uZWxzXSk7XG4gICAgICAgIG1hdG11bE91dHB1dFNoYXBlID0gWzEsIGJhdGNoLCBvdXRDaGFubmVsc107XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB4UmVzaGFwZWQgPSBpbnB1dHNbMF0ucmVzaGFwZShbYmF0Y2gsIGlucHV0SGVpZ2h0ICogaW5wdXRXaWR0aCwgaW5wdXRDaGFubmVsc10pO1xuICAgICAgICB3UmVzaGFwZWQgPSB0cmFuc3Bvc2VkV2VpZ2h0LnJlc2hhcGUoWzEsIGlucHV0Q2hhbm5lbHMsIG91dENoYW5uZWxzXSk7XG4gICAgICAgIG1hdG11bE91dHB1dFNoYXBlID0gW2JhdGNoLCBvdXRIZWlnaHQgKiBvdXRXaWR0aCwgb3V0Q2hhbm5lbHNdO1xuICAgICAgfVxuICAgICAgbWF0bXVsSW5wdXRzLnB1c2goeFJlc2hhcGVkKTtcbiAgICAgIG1hdG11bElucHV0cy5wdXNoKHdSZXNoYXBlZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHhSZXNoYXBlZCA9IGlucHV0c1swXS5yZXNoYXBlKFtiYXRjaCwgaW5wdXRDaGFubmVscywgaW5wdXRIZWlnaHQgKiBpbnB1dFdpZHRoXSk7XG4gICAgICB3UmVzaGFwZWQgPSBpbnB1dHNbMV0ucmVzaGFwZShbMSwgb3V0Q2hhbm5lbHMsIGlucHV0Q2hhbm5lbHNdKTtcbiAgICAgIG1hdG11bE91dHB1dFNoYXBlID0gW2JhdGNoLCBvdXRDaGFubmVscywgb3V0SGVpZ2h0ICogb3V0V2lkdGhdO1xuICAgICAgbWF0bXVsSW5wdXRzLnB1c2god1Jlc2hhcGVkKTtcbiAgICAgIG1hdG11bElucHV0cy5wdXNoKHhSZXNoYXBlZCk7XG4gICAgfVxuICAgIGlmIChoYXNCaWFzKSB7XG4gICAgICBtYXRtdWxJbnB1dHMucHVzaChpbnB1dHNbMl0pO1xuICAgIH1cbiAgICBjb25zdCBOID0gbWF0bXVsT3V0cHV0U2hhcGVbMl07XG4gICAgY29uc3QgSyA9IG1hdG11bElucHV0c1swXS5kaW1zW21hdG11bElucHV0c1swXS5kaW1zLmxlbmd0aCAtIDFdO1xuICAgIC8vIFR1bmUgdGhlIHRocmVzaG9sZC5cbiAgICBpZiAoTiA8IDggJiYgSyA8IDgpIHtcbiAgICAgIGNvbnRleHQuY29tcHV0ZShcbiAgICAgICAgY3JlYXRlTmFpdmVNYXRtdWxQcm9ncmFtSW5mbyhcbiAgICAgICAgICBtYXRtdWxJbnB1dHMsXG4gICAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICAgICBvdXRwdXRTaGFwZSxcbiAgICAgICAgICBtYXRtdWxPdXRwdXRTaGFwZSxcbiAgICAgICAgICBpc0NoYW5uZWxzTGFzdCxcbiAgICAgICAgICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbixcbiAgICAgICAgKSxcbiAgICAgICAgeyBpbnB1dHM6IG1hdG11bElucHV0cyB9LFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGV4dC5jb21wdXRlKFxuICAgICAgICBjcmVhdGVNYXRtdWxQcm9ncmFtSW5mbyhcbiAgICAgICAgICBtYXRtdWxJbnB1dHMsXG4gICAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICAgICBvdXRwdXRTaGFwZSxcbiAgICAgICAgICBtYXRtdWxPdXRwdXRTaGFwZSxcbiAgICAgICAgICBpc0NoYW5uZWxzTGFzdCxcbiAgICAgICAgICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbixcbiAgICAgICAgKSxcbiAgICAgICAgeyBpbnB1dHM6IG1hdG11bElucHV0cyB9LFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVE9ETzogaW1wbGVtZW50IGNvbnYyZFdpdGhJbTJDb2woKVxuXG4gIGNvbnN0IHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHMgPSAvKiBiYWNrZW5kLmFkYXB0ZXJJbmZvLmlzSW50ZWwoKSAqLyB0cnVlO1xuXG4gIC8vIFNURVAuMTogdHJhbnNwb3NlIHdlaWdodFxuICBjb25zdCB0cmFuc3Bvc2VkV2VpZ2h0ID1cbiAgICAoY29udGV4dC5rZXJuZWxDdXN0b21EYXRhLndUIGFzIFRlbnNvclZpZXcgfCB1bmRlZmluZWQpID8/XG4gICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKGlucHV0c1sxXSwgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlKSwge1xuICAgICAgaW5wdXRzOiBbMV0sXG4gICAgICBvdXRwdXRzOiBbYXR0cmlidXRlcy53SXNDb25zdCA/IC0yIDogLTFdLFxuICAgIH0pWzBdO1xuICBpZiAoYXR0cmlidXRlcy53SXNDb25zdCAmJiAhY29udGV4dC5rZXJuZWxDdXN0b21EYXRhLndUKSB7XG4gICAgY29udGV4dC5rZXJuZWxDdXN0b21EYXRhLndUID0gdHJhbnNwb3NlZFdlaWdodDtcbiAgfVxuXG4gIC8vIFNURVAuMjogcHJlcGFyZSByZXNoYXBlZCBpbnB1dHNcbiAgY29uc3QgY29udklucHV0cyA9IFtpbnB1dHNbMF0sIHRyYW5zcG9zZWRXZWlnaHRdO1xuICBpZiAoaGFzQmlhcykge1xuICAgIGNvbnZJbnB1dHMucHVzaChpbnB1dHNbMl0pO1xuICB9XG5cbiAgLy8gU1RFUC4zOiBjb21wdXRlIG1hdG11bFxuICBjb25zdCBkaW1BT3V0ZXIgPSBpc0NoYW5uZWxzTGFzdCA/IG91dEhlaWdodCAqIG91dFdpZHRoIDogb3V0Q2hhbm5lbHM7XG4gIGNvbnN0IGRpbUJPdXRlciA9IGlzQ2hhbm5lbHNMYXN0ID8gb3V0Q2hhbm5lbHMgOiBvdXRIZWlnaHQgKiBvdXRXaWR0aDtcbiAgY29uc3QgZGltSW5uZXIgPSB3ZWlnaHRIZWlnaHQgKiB3ZWlnaHRXaWR0aCAqIGlucHV0Q2hhbm5lbHM7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVDb252MkRNYXRNdWxQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnZJbnB1dHMsXG4gICAgICBhdHRyaWJ1dGVzLFxuICAgICAgb3V0cHV0U2hhcGUsXG4gICAgICBkaW1BT3V0ZXIsXG4gICAgICBkaW1CT3V0ZXIsXG4gICAgICBkaW1Jbm5lcixcbiAgICAgIGhhc0JpYXMsXG4gICAgICBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzLFxuICAgICAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24sXG4gICAgKSxcbiAgICB7IGlucHV0czogY29udklucHV0cyB9LFxuICApO1xufTtcblxuY29uc3QgY29udjFkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICAvLyBleHRlbmQgdGhlIGlucHV0IHRvIDJEIGJ5IGFkZGluZyBIIGRpbWVuc2lvblxuICBjb25zdCBpc0NoYW5uZWxMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3QgaW5wdXRzID0gW1xuICAgIGNvbnRleHQuaW5wdXRzWzBdLnJlc2hhcGUoXG4gICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgID8gLy8gW04sIFcsIENdIC0+IFtOLCBIPTEsIFcsIENdXG4gICAgICAgICAgW2NvbnRleHQuaW5wdXRzWzBdLmRpbXNbMF0sIDEsIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMV0sIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMl1dXG4gICAgICAgIDogLy8gW04sIEMsIFddIC0+IFtOLCBDLCBIPTEsIFddXG4gICAgICAgICAgW2NvbnRleHQuaW5wdXRzWzBdLmRpbXNbMF0sIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMV0sIDEsIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMl1dLFxuICAgICksXG4gICAgLy9bRklMVEVSX09VVF9DSEFOTkVMLCBGSUxURVJfSU5fQ0hBTk5FTCwga1ddIC0+IFtGSUxURVJfT1VUX0NIQU5ORUwsIEZJTFRFUl9JTl9DSEFOTkVMLCBrSD0xLCBrV11cbiAgICBjb250ZXh0LmlucHV0c1sxXS5yZXNoYXBlKFtjb250ZXh0LmlucHV0c1sxXS5kaW1zWzBdLCBjb250ZXh0LmlucHV0c1sxXS5kaW1zWzFdLCAxLCBjb250ZXh0LmlucHV0c1sxXS5kaW1zWzJdXSksXG4gIF07XG4gIGlmIChjb250ZXh0LmlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICBpbnB1dHMucHVzaChjb250ZXh0LmlucHV0c1syXSk7XG4gIH1cbiAgY29uc3QgcGFkcyA9IFswLCBhdHRyaWJ1dGVzLnBhZHNbMF0sIDAsIGF0dHJpYnV0ZXMucGFkc1sxXV07XG4gIGNvbnN0IHN0cmlkZXMgPSBbMV0uY29uY2F0KGF0dHJpYnV0ZXMuc3RyaWRlcyk7XG4gIGNvbnN0IGRpbGF0aW9ucyA9IFsxXS5jb25jYXQoYXR0cmlidXRlcy5kaWxhdGlvbnMpO1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IFsxXS5jb25jYXQoYXR0cmlidXRlcy5rZXJuZWxTaGFwZSk7XG4gIGNvbnN0IGFkanVzdGVkQXR0cmlidXRlcyA9IGdldEFkanVzdGVkQ29udkF0dHJpYnV0ZXMoXG4gICAgeyAuLi5hdHRyaWJ1dGVzLCBwYWRzLCBzdHJpZGVzLCBkaWxhdGlvbnMsIGtlcm5lbFNoYXBlIH0sXG4gICAgaW5wdXRzLFxuICApO1xuICBjb252MmQoY29udGV4dCwgaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMsIChvdXRwdXRTaGFwZSkgPT5cbiAgICBpc0NoYW5uZWxMYXN0ID8gW291dHB1dFNoYXBlWzBdLCBvdXRwdXRTaGFwZVsyXSwgb3V0cHV0U2hhcGVbM11dIDogW291dHB1dFNoYXBlWzBdLCBvdXRwdXRTaGFwZVsxXSwgb3V0cHV0U2hhcGVbM11dLFxuICApO1xufTtcblxuY29uc3QgY29udjNkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgZm9ybWF0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJyA/ICdjaGFubmVsc0xhc3QnIDogJ2NoYW5uZWxzRmlyc3QnO1xuICBjb25zdCBhZGp1c3RlZEF0dHJpYnV0ZXMgPSBnZXRBZGp1c3RlZENvbnZBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMsIGlucHV0cyk7XG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLmF1dG9QYWQgPT09ICdOT1RTRVQnID8gYXR0cmlidXRlcy5wYWRzIDogYXR0cmlidXRlcy5hdXRvUGFkO1xuICBjb25zdCBjb252SW5mbyA9IGNvbXB1dGVDb252M0RJbmZvKFxuICAgIGlucHV0c1swXS5kaW1zIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgaW5wdXRzWzFdLmRpbXMgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgICBhdHRyaWJ1dGVzLnN0cmlkZXMgYXMgbnVtYmVyIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICAgIGF0dHJpYnV0ZXMuZGlsYXRpb25zIGFzIG51bWJlciB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgICBwYWRzIGFzIHN0cmluZyB8IG51bWJlcltdLFxuICAgIGZhbHNlLFxuICAgIGZvcm1hdCxcbiAgKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUNvbnYzRE5haXZlUHJvZ3JhbUluZm8oXG4gICAgICBpbnB1dHMsXG4gICAgICBhZGp1c3RlZEF0dHJpYnV0ZXMsXG4gICAgICBjb252SW5mby5vdXRTaGFwZSxcbiAgICAgIFtjb252SW5mby5maWx0ZXJEZXB0aCwgY29udkluZm8uZmlsdGVySGVpZ2h0LCBjb252SW5mby5maWx0ZXJXaWR0aF0sXG4gICAgICBbY29udkluZm8ucGFkSW5mby5mcm9udCwgY29udkluZm8ucGFkSW5mby50b3AsIGNvbnZJbmZvLnBhZEluZm8ubGVmdF0sXG4gICAgICBmb3JtYXQsXG4gICAgKSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBjb252ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGlmIChjb250ZXh0LmlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gMykge1xuICAgIGNvbnYxZChjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIGlmIChjb250ZXh0LmlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gNSkge1xuICAgIGNvbnYzZChjb250ZXh0LCBjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgYWRqdXN0ZWRBdHRyaWJ1dGVzID0gZ2V0QWRqdXN0ZWRDb252QXR0cmlidXRlcyhhdHRyaWJ1dGVzLCBjb250ZXh0LmlucHV0cyk7XG4gICAgY29udjJkKGNvbnRleHQsIGNvbnRleHQuaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMpO1xuICB9XG59O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuLy8gc2FtcGxlZCBmcm9tIFtAdGVuc29yZmxvdy90ZmpzXSB0ZmpzLWJhY2tlbmQtd2ViZ3B1L3NyYy9jb252X2JhY2twcm9wX3dlYmdwdS50c1xuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IExPR19ERUJVRyB9IGZyb20gJy4uLy4uLy4uL2xvZyc7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG4gIGdldE1heENvbXBvbmVudHMsXG59IGZyb20gJy4uL2NvbW1vbic7XG5pbXBvcnQgeyBDb252VHJhbnNwb3NlQXR0cmlidXRlcyB9IGZyb20gJy4uL2NvbnYtdHJhbnNwb3NlJztcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUNvbnZUcmFuc3Bvc2UyRFByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMsXG4gIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uPzogKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4gbnVtYmVyW10sXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID4gMjtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBhdHRyaWJ1dGVzLm91dHB1dFNoYXBlO1xuICBjb25zdCBpc0NoYW5uZWxzTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGNvbnN0IGdyb3VwID0gYXR0cmlidXRlcy5ncm91cDtcbiAgY29uc3Qgd1NoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gIGNvbnN0IGlucHV0Q2hhbm5lbHNQZXJHcm91cCA9IHdTaGFwZVsyXSAvIGdyb3VwO1xuICBjb25zdCBvdXRwdXRDaGFubmVsc1Blckdyb3VwID0gd1NoYXBlWzNdO1xuICBjb25zdCBhQ29tcG9uZW50cyA9IGlzQ2hhbm5lbHNMYXN0ID8gZ2V0TWF4Q29tcG9uZW50cyhpbnB1dENoYW5uZWxzUGVyR3JvdXApIDogMTtcbiAgY29uc3QgcGFja0lucHV0QXM0ID0gaXNDaGFubmVsc0xhc3QgJiYgb3V0cHV0Q2hhbm5lbHNQZXJHcm91cCA9PT0gMSAmJiBpbnB1dENoYW5uZWxzUGVyR3JvdXAgPj0gNDtcbiAgY29uc3QgaW5wdXRDaGFubmVsc1Blckdyb3VwSW50ID0gcGFja0lucHV0QXM0XG4gICAgPyBNYXRoLmZsb29yKGlucHV0Q2hhbm5lbHNQZXJHcm91cCAvIDQpICogNFxuICAgIDogTWF0aC5mbG9vcihpbnB1dENoYW5uZWxzUGVyR3JvdXAgLyBhQ29tcG9uZW50cykgKiBhQ29tcG9uZW50cztcbiAgY29uc3QgaW5wdXRDaGFubmVsc1JlbWFpbmRlciA9IGlucHV0Q2hhbm5lbHNQZXJHcm91cCAtIGlucHV0Q2hhbm5lbHNQZXJHcm91cEludDtcbiAgY29uc3QgY29tcG9uZW50cyA9IGlzQ2hhbm5lbHNMYXN0ID8gZ2V0TWF4Q29tcG9uZW50cyhvdXRwdXRDaGFubmVsc1Blckdyb3VwKSA6IDE7XG4gIGNvbnN0IGJDb21wb25lbnRzID0gaXNDaGFubmVsc0xhc3QgPyAob3V0cHV0Q2hhbm5lbHNQZXJHcm91cCA9PT0gMSA/IGFDb21wb25lbnRzIDogY29tcG9uZW50cykgOiAxO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gY29tcG9uZW50cztcbiAgY29uc3QgZGlzcGF0Y2ggPSBbTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCksIDEsIDFdO1xuICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW2NvbnYyZF9iYWNrcHJvcF93ZWJncHVdIGRpc3BhdGNoID0gJHtkaXNwYXRjaH1gKTtcblxuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsncmFuaycsICdyYW5rJ107XG4gIGNvbnN0IHN0cmlkZXMgPSBbYXR0cmlidXRlcy5zdHJpZGVzWzBdLCBhdHRyaWJ1dGVzLnN0cmlkZXNbMV1dO1xuICBjb25zdCBmaWx0ZXJEaW1zID0gW2F0dHJpYnV0ZXMua2VybmVsU2hhcGVbaXNDaGFubmVsc0xhc3QgPyAxIDogMl0sIGF0dHJpYnV0ZXMua2VybmVsU2hhcGVbaXNDaGFubmVsc0xhc3QgPyAyIDogM11dO1xuICBjb25zdCBkaWxhdGlvbnMgPSBbYXR0cmlidXRlcy5kaWxhdGlvbnNbMF0sIGF0dHJpYnV0ZXMuZGlsYXRpb25zWzFdXTtcbiAgY29uc3QgZWZmZWN0aXZlRmlsdGVyRGltcyA9IFtcbiAgICBmaWx0ZXJEaW1zWzBdICtcbiAgICAgIChhdHRyaWJ1dGVzLmRpbGF0aW9uc1swXSA8PSAxXG4gICAgICAgID8gMFxuICAgICAgICA6IChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlW2lzQ2hhbm5lbHNMYXN0ID8gMSA6IDJdIC0gMSkgKiAoYXR0cmlidXRlcy5kaWxhdGlvbnNbMF0gLSAxKSksXG4gICAgZmlsdGVyRGltc1sxXSArXG4gICAgICAoYXR0cmlidXRlcy5kaWxhdGlvbnNbMV0gPD0gMVxuICAgICAgICA/IDBcbiAgICAgICAgOiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZVtpc0NoYW5uZWxzTGFzdCA/IDIgOiAzXSAtIDEpICogKGF0dHJpYnV0ZXMuZGlsYXRpb25zWzFdIC0gMSkpLFxuICBdO1xuICBjb25zdCBwYWRzID0gW1xuICAgIGVmZmVjdGl2ZUZpbHRlckRpbXNbMF0gLSAxIC0gTWF0aC5mbG9vcigoYXR0cmlidXRlcy5wYWRzWzBdICsgYXR0cmlidXRlcy5wYWRzWzJdKSAvIDIpLFxuICAgIGVmZmVjdGl2ZUZpbHRlckRpbXNbMV0gLSAxIC0gTWF0aC5mbG9vcigoYXR0cmlidXRlcy5wYWRzWzFdICsgYXR0cmlidXRlcy5wYWRzWzNdKSAvIDIpLFxuICBdO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzdHJpZGVzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGZpbHRlckRpbXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZGlsYXRpb25zIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGVmZmVjdGl2ZUZpbHRlckRpbXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBwYWRzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGlucHV0Q2hhbm5lbHNQZXJHcm91cEludCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBpbnB1dENoYW5uZWxzUGVyR3JvdXAgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0Q2hhbm5lbHNQZXJHcm91cCB9LFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBpbnB1dHNbMV0uZGltcyksXG4gIF07XG4gIGlmIChoYXNCaWFzKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzJdLmRpbXMpKTtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCdyYW5rJyk7XG4gIH1cbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGUpKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdzdHJpZGVzJywgdHlwZTogJ3UzMicsIGxlbmd0aDogc3RyaWRlcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ2ZpbHRlcl9kaW1zJywgdHlwZTogJ3UzMicsIGxlbmd0aDogZmlsdGVyRGltcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ2RpbGF0aW9ucycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGZpbHRlckRpbXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdlZmZlY3RpdmVfZmlsdGVyX2RpbXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBlZmZlY3RpdmVGaWx0ZXJEaW1zLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAncGFkcycsIHR5cGU6ICdpMzInLCBsZW5ndGg6IHBhZHMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdpbnB1dF9jaGFubmVsc19wZXJfZ3JvdXBfaW50JywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2lucHV0X2NoYW5uZWxzX3Blcl9ncm91cCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfY2hhbm5lbHNfcGVyX2dyb3VwJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuICAgIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKGlucHV0c1swXS5kYXRhVHlwZSk7XG4gICAgY29uc3Qgcm93RGltID0gaXNDaGFubmVsc0xhc3QgPyAxIDogMjtcbiAgICBjb25zdCBjb2xEaW0gPSBpc0NoYW5uZWxzTGFzdCA/IDIgOiAzO1xuICAgIGNvbnN0IGNoYW5uZWxEaW0gPSBpc0NoYW5uZWxzTGFzdCA/IDMgOiAxO1xuXG4gICAgY29uc3QgdyA9IGlucHV0VmFyaWFibGUoJ1cnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLmxlbmd0aCwgYkNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGR5ID0gaW5wdXRWYXJpYWJsZSgnRHknLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLmxlbmd0aCwgYUNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGlucHV0VmFyaWFibGVzID0gW2R5LCB3XTtcbiAgICBpZiAoaGFzQmlhcykge1xuICAgICAgaW5wdXRWYXJpYWJsZXMucHVzaChpbnB1dFZhcmlhYmxlKCdiaWFzJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBbb3V0cHV0U2hhcGVbY2hhbm5lbERpbV1dLmxlbmd0aCwgY29tcG9uZW50cykpO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgncmVzdWx0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuXG4gICAgY29uc3QgY2FsY3VsYXRlUmVzdWx0ID0gKCk6IHN0cmluZyA9PiB7XG4gICAgICBsZXQgY2FsY1N0ciA9ICcnO1xuICAgICAgaWYgKHBhY2tJbnB1dEFzNCkge1xuICAgICAgICBpZiAoYUNvbXBvbmVudHMgPT09IDQpIHtcbiAgICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgbGV0IHhWYWx1ZSA9ICR7ZHkuZ2V0QnlPZmZzZXQoJ3hfb2Zmc2V0Jyl9O1xuICAgICAgICBsZXQgd1ZhbHVlID0gJHt3LmdldEJ5T2Zmc2V0KCd3X29mZnNldCcpfTtcbiAgICAgICAgZG90UHJvZCA9IGRvdFByb2QgKyBkb3QoeFZhbHVlLCB3VmFsdWUpO1xuICAgICAgICB4X29mZnNldCArPSAxdTtcbiAgICAgICAgd19vZmZzZXQgKz0gMXU7YDtcbiAgICAgICAgfSBlbHNlIGlmIChhQ29tcG9uZW50cyA9PT0gMikge1xuICAgICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgIGRvdFByb2QgPSBkb3RQcm9kICsgZG90KHZlYzQ8JHtkYXRhVHlwZX0+KCR7ZHkuZ2V0QnlPZmZzZXQoJ3hfb2Zmc2V0Jyl9LCAke2R5LmdldEJ5T2Zmc2V0KCd4X29mZnNldCArIDF1Jyl9KSwgdmVjNDwke2RhdGFUeXBlfT4oJHt3LmdldEJ5T2Zmc2V0KCd3X29mZnNldCcpfSwgJHt3LmdldEJ5T2Zmc2V0KCd3X29mZnNldCArIDF1Jyl9KSk7XG4gICAgICAgICAgeF9vZmZzZXQgKz0gMnU7XG4gICAgICAgICAgd19vZmZzZXQgKz0gMnU7YDtcbiAgICAgICAgfSBlbHNlIGlmIChhQ29tcG9uZW50cyA9PT0gMSkge1xuICAgICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgIGRvdFByb2QgPSBkb3RQcm9kICsgZG90KHZlYzQ8JHtkYXRhVHlwZX0+KCR7ZHkuZ2V0QnlPZmZzZXQoJ3hfb2Zmc2V0Jyl9LCAke2R5LmdldEJ5T2Zmc2V0KCd4X29mZnNldCArIDF1Jyl9LCAke2R5LmdldEJ5T2Zmc2V0KCd4X29mZnNldCArIDJ1Jyl9LCAke2R5LmdldEJ5T2Zmc2V0KCd4X29mZnNldCArIDN1Jyl9KSwgdmVjNDwke2RhdGFUeXBlfT4oJHt3LmdldEJ5T2Zmc2V0KCd3X29mZnNldCcpfSwgJHt3LmdldEJ5T2Zmc2V0KCd3X29mZnNldCArIDF1Jyl9LCAke3cuZ2V0QnlPZmZzZXQoJ3dfb2Zmc2V0ICsgMnUnKX0sICR7dy5nZXRCeU9mZnNldCgnd19vZmZzZXQgKyAzdScpfSkpO1xuICAgICAgICAgIHhfb2Zmc2V0ICs9IDR1O1xuICAgICAgICAgIHdfb2Zmc2V0ICs9IDR1O2A7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgICAgICAgICAgbGV0IHhWYWx1ZSA9ICR7XG4gICAgICAgICAgICAgICAgICAgIGlzQ2hhbm5lbHNMYXN0XG4gICAgICAgICAgICAgICAgICAgICAgPyBkeS5nZXRCeU9mZnNldChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYCR7ZHkuaW5kaWNlc1RvT2Zmc2V0KGAke2R5LnR5cGUuaW5kaWNlc30oYmF0Y2gsIGlkeVIsIGlkeUMsIGlucHV0Q2hhbm5lbClgKX0gLyAke2FDb21wb25lbnRzfWAsXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgOiBkeS5nZXQoJ2JhdGNoJywgJ2lucHV0Q2hhbm5lbCcsICdpZHlSJywgJ2lkeUMnKVxuICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgYDtcbiAgICAgICAgaWYgKGFDb21wb25lbnRzID09PSAxKSB7XG4gICAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgbGV0IHdfb2Zmc2V0ID0gJHt3LmluZGljZXNUb09mZnNldChgJHt3LnR5cGUuaW5kaWNlc30odTMyKHdSUGVybSksIHUzMih3Q1Blcm0pLCBpbnB1dENoYW5uZWwsIHdPdXRDaGFubmVsKWApfTtcbiAgICAgICAgICBsZXQgd1ZhbHVlID0gJHt3LmdldEJ5T2Zmc2V0KGB3X29mZnNldCAvICR7YkNvbXBvbmVudHN9YCl9O1xuICAgICAgICAgIGRvdFByb2QgPSBkb3RQcm9kICsgeFZhbHVlICogd1ZhbHVlO2A7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCBhQ29tcG9uZW50czsgYysrKSB7XG4gICAgICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICAgIGxldCB3VmFsdWUke2N9ID0gJHt3LmdldEJ5T2Zmc2V0KGAke3cuaW5kaWNlc1RvT2Zmc2V0KGAke3cudHlwZS5pbmRpY2VzfSh1MzIod1JQZXJtKSwgdTMyKHdDUGVybSksIGlucHV0Q2hhbm5lbCArICR7Y30sIHdPdXRDaGFubmVsKWApfSAvICR7YkNvbXBvbmVudHN9YCl9O1xuICAgICAgICAgICAgZG90UHJvZCA9IGRvdFByb2QgKyB4VmFsdWVbJHtjfV0gKiB3VmFsdWUke2N9O2A7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gY2FsY1N0cjtcbiAgICB9O1xuICAgIGNvbnN0IGNhbGN1bGF0ZVJlbWFpbmRlciA9ICgpOiBzdHJpbmcgPT4ge1xuICAgICAgaWYgKGlucHV0Q2hhbm5lbHNSZW1haW5kZXIgPT09IDApIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgICAgfVxuICAgICAgaWYgKCFwYWNrSW5wdXRBczQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBwYWNrSW5wdXRBczQgJHtwYWNrSW5wdXRBczR9IGlzIG5vdCB0cnVlLmApO1xuICAgICAgfVxuICAgICAgbGV0IGNhbGNTdHIgPSAnJztcbiAgICAgIGlmIChhQ29tcG9uZW50cyA9PT0gMSkge1xuICAgICAgICBjYWxjU3RyICs9ICdkb3RQcm9kID0gZG90UHJvZCc7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDaGFubmVsc1JlbWFpbmRlcjsgaSsrKSB7XG4gICAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgICArICR7ZHkuZ2V0QnlPZmZzZXQoYHhfb2Zmc2V0ICsgJHtpfWApfSAqICR7dy5nZXRCeU9mZnNldChgd19vZmZzZXQgKyAke2l9YCl9YDtcbiAgICAgICAgfVxuICAgICAgICBjYWxjU3RyICs9ICc7JztcbiAgICAgIH0gZWxzZSBpZiAoYUNvbXBvbmVudHMgPT09IDIpIHtcbiAgICAgICAgaWYgKGlucHV0Q2hhbm5lbHNSZW1haW5kZXIgIT09IDIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgaW5wdXRDaGFubmVsc1JlbWFpbmRlciAke2lucHV0Q2hhbm5lbHNSZW1haW5kZXJ9LmApO1xuICAgICAgICB9XG4gICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgIGxldCB4VmFsdWUgPSAke2R5LmdldEJ5T2Zmc2V0KCd4X29mZnNldCcpfTtcbiAgICAgICAgICBsZXQgd1ZhbHVlID0gJHt3LmdldEJ5T2Zmc2V0KCd3X29mZnNldCcpfTtcbiAgICAgICAgICBkb3RQcm9kID0gZG90UHJvZCArIGRvdCh4VmFsdWUsIHdWYWx1ZSk7YDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjYWxjU3RyO1xuICAgIH07XG4gICAgY29uc3QgY29kZVNuaXBwZXQgPSBgXG4gICAgICAgICAgICBsZXQgb3V0cHV0SW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgZ2xvYmFsX2lkeCAqICR7Y29tcG9uZW50c31gKX07XG4gICAgICAgICAgICBsZXQgYmF0Y2ggPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRJbmRpY2VzJywgMCl9O1xuICAgICAgICAgICAgbGV0IGQxID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0SW5kaWNlcycsIGNoYW5uZWxEaW0pfTtcbiAgICAgICAgICAgIGxldCByID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0SW5kaWNlcycsIHJvd0RpbSl9O1xuICAgICAgICAgICAgbGV0IGMgPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRJbmRpY2VzJywgY29sRGltKX07XG4gICAgICAgICAgICBsZXQgZHlDb3JuZXIgPSB2ZWMyPGkzMj4oaTMyKHIpLCBpMzIoYykpIC0gdW5pZm9ybXMucGFkcztcbiAgICAgICAgICAgIGxldCBkeVJDb3JuZXIgPSBkeUNvcm5lci54O1xuICAgICAgICAgICAgbGV0IGR5Q0Nvcm5lciA9IGR5Q29ybmVyLnk7XG4gICAgICAgICAgICBsZXQgZ3JvdXBJZCA9IGQxIC8gdW5pZm9ybXMub3V0cHV0X2NoYW5uZWxzX3Blcl9ncm91cDtcbiAgICAgICAgICAgIGxldCB3T3V0Q2hhbm5lbCA9IGQxIC0gZ3JvdXBJZCAqIHVuaWZvcm1zLm91dHB1dF9jaGFubmVsc19wZXJfZ3JvdXA7XG4gICAgICAgICAgICAvLyBDb252b2x2ZSBkeSg/LCA/LCBkMikgd2l0aCB3KDosIDosIGQxLCBkMikgdG8gY29tcHV0ZSBkeCh4UiwgeEMsIGQxKS5cbiAgICAgICAgICAgIC8vID8gPSB0byBiZSBkZXRlcm1pbmVkLiA6ID0gYWNyb3NzIGFsbCB2YWx1ZXMgaW4gdGhhdCBheGlzLlxuICAgICAgICAgICAgdmFyIGRvdFByb2QgPSAke291dHB1dC50eXBlLnZhbHVlfSgwLjApO1xuICAgICAgICAgICAgdmFyIHdSOiB1MzIgPSAwO1xuICAgICAgICAgICAgaWYgKHVuaWZvcm1zLmRpbGF0aW9ucy54ID09IDEpIHtcbiAgICAgICAgICAgICAgLy8gTWluaW11bSB3UiA+PSAwIHRoYXQgc2F0aXNmaWVzIChkeVJDb3JuZXIgKyB3UikgJSAodW5pZm9ybXMuc3RyaWRlcy54KSA9PSAwXG4gICAgICAgICAgICAgIHdSID0gdTMyKCgoZHlSQ29ybmVyICsgaTMyKHVuaWZvcm1zLnN0cmlkZXMueCkgLSAxKSAvIGkzMih1bmlmb3Jtcy5zdHJpZGVzLngpKSAqIGkzMih1bmlmb3Jtcy5zdHJpZGVzLngpIC0gZHlSQ29ybmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoOyB3UiA8IHVuaWZvcm1zLmVmZmVjdGl2ZV9maWx0ZXJfZGltcy54OyB3UiA9IHdSICsgMSkge1xuICAgICAgICAgICAgICBpZiAod1IgJSB1bmlmb3Jtcy5kaWxhdGlvbnMueCAhPSAwKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgbGV0IGR5UiA9ICgke2RhdGFUeXBlfShkeVJDb3JuZXIpICsgJHtkYXRhVHlwZX0od1IpKSAvICR7ZGF0YVR5cGV9KHVuaWZvcm1zLnN0cmlkZXNbMF0pO1xuICAgICAgICAgICAgICBsZXQgd1JQZXJtID0gdW5pZm9ybXMuZmlsdGVyX2RpbXMueCAtIDEgLSB3UiAvIHVuaWZvcm1zLmRpbGF0aW9ucy54O1xuICAgICAgICAgICAgICBpZiAoZHlSIDwgMC4wIHx8IGR5UiA+PSAke2RhdGFUeXBlfSh1bmlmb3Jtcy5EeV9zaGFwZVske3Jvd0RpbX1dKSB8fCBmcmFjdChkeVIpID4gMC4wIHx8XG4gICAgICAgICAgICAgICAgICB3UlBlcm0gPCAwKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgbGV0IGlkeVI6IHUzMiA9IHUzMihkeVIpO1xuICAgICAgICAgICAgICB2YXIgd0M6IHUzMiA9IDA7XG4gICAgICAgICAgICAgIGlmICh1bmlmb3Jtcy5kaWxhdGlvbnMueSA9PSAxKSB7XG4gICAgICAgICAgICAgICAgLy8gTWluaW11bSB3QyA+PSAwIHRoYXQgc2F0aXNmaWVzIChkeUNDb3JuZXIgKyB3QykgJSAodW5pZm9ybXMuc3RyaWRlcy55KSA9PSAwXG4gICAgICAgICAgICAgICAgd0MgPSB1MzIoKChkeUNDb3JuZXIgKyBpMzIodW5pZm9ybXMuc3RyaWRlcy55KSAtIDEpIC8gaTMyKHVuaWZvcm1zLnN0cmlkZXMueSkpICogaTMyKHVuaWZvcm1zLnN0cmlkZXMueSkgLSBkeUNDb3JuZXIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGZvciAoOyB3QyA8IHVuaWZvcm1zLmVmZmVjdGl2ZV9maWx0ZXJfZGltcy55OyB3QyA9IHdDICsgMSkge1xuICAgICAgICAgICAgICAgIGlmICh3QyAlIHVuaWZvcm1zLmRpbGF0aW9ucy55ICE9IDApIHtcbiAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgZHlDID0gKCR7ZGF0YVR5cGV9KGR5Q0Nvcm5lcikgKyAke2RhdGFUeXBlfSh3QykpIC8gJHtkYXRhVHlwZX0odW5pZm9ybXMuc3RyaWRlcy55KTtcbiAgICAgICAgICAgICAgICBsZXQgd0NQZXJtID0gdW5pZm9ybXMuZmlsdGVyX2RpbXMueSAtIDEgLSB3QyAvIHVuaWZvcm1zLmRpbGF0aW9ucy55O1xuICAgICAgICAgICAgICAgIGlmIChkeUMgPCAwLjAgfHwgZHlDID49ICR7ZGF0YVR5cGV9KHVuaWZvcm1zLkR5X3NoYXBlWyR7Y29sRGltfV0pIHx8XG4gICAgICAgICAgICAgICAgICAgIGZyYWN0KGR5QykgPiAwLjAgfHwgd0NQZXJtIDwgMCkge1xuICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBpZHlDOiB1MzIgPSB1MzIoZHlDKTtcbiAgICAgICAgICAgICAgICB2YXIgaW5wdXRDaGFubmVsID0gZ3JvdXBJZCAqIHVuaWZvcm1zLmlucHV0X2NoYW5uZWxzX3Blcl9ncm91cDtcbiAgICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgICAgcGFja0lucHV0QXM0XG4gICAgICAgICAgICAgICAgICAgID8gYFxuICAgICAgICAgICAgICAgIHZhciB4X29mZnNldCA9ICR7ZHkuaW5kaWNlc1RvT2Zmc2V0KGAke2R5LnR5cGUuaW5kaWNlc30oYmF0Y2gsIGlkeVIsIGlkeUMsIGlucHV0Q2hhbm5lbClgKX0gLyAke2FDb21wb25lbnRzfTtcbiAgICAgICAgICAgICAgICB2YXIgd19vZmZzZXQgPSAke3cuaW5kaWNlc1RvT2Zmc2V0KGAke3cudHlwZS5pbmRpY2VzfSh3UlBlcm0sIHdDUGVybSwgaW5wdXRDaGFubmVsLCB3T3V0Q2hhbm5lbClgKX0gLyAke2JDb21wb25lbnRzfTtcbiAgICAgICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICAgICAgOiAnJ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBkMjogdTMyID0gMDsgZDIgPCB1bmlmb3Jtcy5pbnB1dF9jaGFubmVsc19wZXJfZ3JvdXBfaW50OyBkMiA9IGQyICsgJHtwYWNrSW5wdXRBczQgPyA0IDogYUNvbXBvbmVudHN9KSB7XG4gICAgICAgICAgICAgICAgICAke2NhbGN1bGF0ZVJlc3VsdCgpfVxuICAgICAgICAgICAgICAgICAgaW5wdXRDaGFubmVsID0gaW5wdXRDaGFubmVsICsgJHtwYWNrSW5wdXRBczQgPyA0IDogYUNvbXBvbmVudHN9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAke2NhbGN1bGF0ZVJlbWFpbmRlcigpfVxuICAgICAgICAgICAgICAgIHdDID0gd0MgKyB1bmlmb3Jtcy5zdHJpZGVzLnkgLSAxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHdSID0gd1IgKyB1bmlmb3Jtcy5zdHJpZGVzWzBdIC0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IGRvdFByb2Qke2hhc0JpYXMgPyBgICsgYmlhc1tkMSAvICR7Y29tcG9uZW50c31dYCA6ICcnfTtcbiAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3ZhbHVlJyl9O1xuICAgICAgICAgIGA7XG5cbiAgICByZXR1cm4gYFxuICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9O1xuICAgICR7Y29kZVNuaXBwZXR9fWA7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQ29udlRyYW5zcG9zZTJEJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX07JHthQ29tcG9uZW50c30ke2JDb21wb25lbnRzfSR7Y29tcG9uZW50c30ke3BhY2tJbnB1dEFzNH0ke2lucHV0Q2hhbm5lbHNSZW1haW5kZXJ9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogZGlzcGF0Y2hbMF0sIHk6IGRpc3BhdGNoWzFdLCB6OiBkaXNwYXRjaFsyXSB9LFxuICAgICAgb3V0cHV0czogW1xuICAgICAgICB7XG4gICAgICAgICAgZGltczogc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24gPyBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbihvdXRwdXRTaGFwZSkgOiBvdXRwdXRTaGFwZSxcbiAgICAgICAgICBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQgfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZUNvbnZUcmFuc3Bvc2UyRFByb2dyYW1JbmZvIH0gZnJvbSAnLi8zcmQtcGFydHkvY29udl9iYWNrcHJvcF93ZWJncHUnO1xuaW1wb3J0IHsgQ29udkF0dHJpYnV0ZXMgfSBmcm9tICcuL2NvbnYnO1xuaW1wb3J0IHsgcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzIH0gZnJvbSAnLi9mdXNlLXV0aWxzJztcbmltcG9ydCB7IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvIH0gZnJvbSAnLi90cmFuc3Bvc2UnO1xuXG5jb25zdCBjb21wdXRlVG90YWxQYWQgPSAoXG4gIGluRGltOiBudW1iZXIsXG4gIHN0cmlkZTogbnVtYmVyLFxuICBhZGo6IG51bWJlcixcbiAga2VybmVsOiBudW1iZXIsXG4gIGRpbGF0aW9uOiBudW1iZXIsXG4gIG91dFNpemU6IG51bWJlcixcbikgPT4gKGluRGltIC0gMSkgKiBzdHJpZGUgKyBhZGogKyAoa2VybmVsIC0gMSkgKiBkaWxhdGlvbiArIDEgLSBvdXRTaXplO1xuXG5jb25zdCBkaXN0cmlidXRlUGFkZGluZyA9ICh0b3RhbFBhZDogbnVtYmVyLCBhdXRvUGFkOiBzdHJpbmcsIHBhZHM6IG51bWJlcltdLCBoZWFkOiBudW1iZXIsIHRhaWw6IG51bWJlcikgPT4ge1xuICBjb25zdCBzbWFsbFBhZCA9IE1hdGguZmxvb3IodG90YWxQYWQgLyAyKTtcbiAgaWYgKGF1dG9QYWQgPT09ICdTQU1FX1VQUEVSJykge1xuICAgIHBhZHNbaGVhZF0gPSBzbWFsbFBhZDtcbiAgICBwYWRzW3RhaWxdID0gdG90YWxQYWQgLSBzbWFsbFBhZDtcbiAgfSBlbHNlIGlmIChhdXRvUGFkID09PSAnU0FNRV9MT1dFUicpIHtcbiAgICBwYWRzW2hlYWRdID0gdG90YWxQYWQgLSBzbWFsbFBhZDtcbiAgICBwYWRzW3RhaWxdID0gc21hbGxQYWQ7XG4gIH1cbn07XG5cbmNvbnN0IGNhbGN1bGF0ZU91dHB1dFNoYXBlQW5kUGFkcyA9IChcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXSxcbiAgYXV0b1BhZDogc3RyaW5nLFxuICBncm91cDogbnVtYmVyLFxuICBwYWRzOiBudW1iZXJbXSxcbiAgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGlzQ2hhbm5lbExhc3Q6IGJvb2xlYW4sXG4gIG91dHB1dFBhZGRpbmc6IG51bWJlcltdLFxuICBvdXRwdXRTaGFwZTogbnVtYmVyW10sXG4pID0+IHtcbiAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aCAtIDI7XG4gIGNvbnN0IHVwZGF0ZU91dHB1dFNoYXBlID0gb3V0cHV0U2hhcGUubGVuZ3RoID09PSAwO1xuICBpZiAob3V0cHV0UGFkZGluZy5sZW5ndGggPCBzcGF0aWFsUmFuaykge1xuICAgIG91dHB1dFBhZGRpbmcucHVzaCguLi5BcnJheShzcGF0aWFsUmFuayAtIG91dHB1dFBhZGRpbmcubGVuZ3RoKS5maWxsKDApKTtcbiAgfVxuICBjb25zdCBiYXRjaFNpemUgPSBpbnB1dFNoYXBlWzBdO1xuICBjb25zdCBvdXRDaGFubmVscyA9IGtlcm5lbFNoYXBlW2lzQ2hhbm5lbExhc3QgPyAzIDogMV0gKiBncm91cDtcbiAgZm9yIChsZXQgaSA9IDAsIGogPSBpbnB1dFNoYXBlLmxlbmd0aCAtIHNwYXRpYWxSYW5rIC0gKGlzQ2hhbm5lbExhc3QgPyAxIDogMCk7IGkgPCBzcGF0aWFsUmFuazsgKytpLCArK2opIHtcbiAgICBjb25zdCBpblNpemUgPSBpbnB1dFNoYXBlW2pdO1xuICAgIGNvbnN0IG91dFNpemUgPSB1cGRhdGVPdXRwdXRTaGFwZSA/IGluU2l6ZSAqIHN0cmlkZXNbaV0gOiBvdXRwdXRTaGFwZVtpXTtcbiAgICBjb25zdCB0b3RhbFBhZCA9IGNvbXB1dGVUb3RhbFBhZChpblNpemUsIHN0cmlkZXNbaV0sIHBhZHNbaV0sIGtlcm5lbFNoYXBlW2pdLCBkaWxhdGlvbnNbaV0sIG91dFNpemUpO1xuICAgIGRpc3RyaWJ1dGVQYWRkaW5nKHRvdGFsUGFkLCBhdXRvUGFkLCBwYWRzLCBpLCBpICsgc3BhdGlhbFJhbmspO1xuICAgIGlmICh1cGRhdGVPdXRwdXRTaGFwZSkge1xuICAgICAgb3V0cHV0U2hhcGUucHVzaChcbiAgICAgICAgc3RyaWRlc1tpXSAqIChpblNpemUgLSAxKSArXG4gICAgICAgICAgb3V0cHV0UGFkZGluZ1tpXSArXG4gICAgICAgICAgKGtlcm5lbFNoYXBlW2pdIC0gMSkgKiBkaWxhdGlvbnNbaV0gK1xuICAgICAgICAgIDEgLVxuICAgICAgICAgIHBhZHNbaV0gLVxuICAgICAgICAgIHBhZHNbaSArIHNwYXRpYWxSYW5rXSxcbiAgICAgICk7XG4gICAgfVxuICB9XG4gIG91dHB1dFNoYXBlLnNwbGljZSgwLCAwLCBiYXRjaFNpemUpO1xuICBvdXRwdXRTaGFwZS5zcGxpY2UoaXNDaGFubmVsTGFzdCA/IDMgOiAxLCAwLCBvdXRDaGFubmVscyk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzIGV4dGVuZHMgQ29udkF0dHJpYnV0ZXMge1xuICByZWFkb25seSBvdXRwdXRQYWRkaW5nOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdO1xufVxuXG5jb25zdCBnZXRBZGp1c3RlZENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzID0gPFQgZXh0ZW5kcyBDb252VHJhbnNwb3NlQXR0cmlidXRlcz4oXG4gIGF0dHJpYnV0ZXM6IFQsXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuKTogVCA9PiB7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5zbGljZSgpO1xuICAvLyBpZiBrZXJuZWxTaGFwZSBpcyBub3Qgc3BlY2lmaWVkIGluIHRoZSBhdHRyaWJ1dGVzIG9mIHRoaXMgb3AsIGluZmVyIGl0IGZyb20gdGhlIHdlaWdodCB0ZW5zb3IgZGltc1xuICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggPT09IDAgfHwgYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5yZWR1Y2UoKGEsIGIpID0+IGEgKiBiLCAxKSA9PT0gMCkge1xuICAgIGtlcm5lbFNoYXBlLmxlbmd0aCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDI7IGkgPCBpbnB1dHNbMV0uZGltcy5sZW5ndGg7ICsraSkge1xuICAgICAga2VybmVsU2hhcGUucHVzaChpbnB1dHNbMV0uZGltc1tpXSk7XG4gICAgfVxuICB9XG4gIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAga2VybmVsU2hhcGUuc3BsaWNlKDAsIDAsIGlucHV0c1sxXS5kaW1zWzBdKTtcbiAga2VybmVsU2hhcGUuc3BsaWNlKGlzQ2hhbm5lbHNMYXN0ID8gMyA6IDEsIDAsIGlucHV0c1sxXS5kaW1zWzFdKTtcblxuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5wYWRzLnNsaWNlKCk7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gYXR0cmlidXRlcy5vdXRwdXRTaGFwZS5zbGljZSgpO1xuICBjb25zdCBvdXRwdXRQYWRkaW5nID0gYXR0cmlidXRlcy5vdXRwdXRQYWRkaW5nLnNsaWNlKCk7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgbGV0IGRpbGF0aW9ucyA9IGF0dHJpYnV0ZXMuZGlsYXRpb25zLnNsaWNlKCk7XG4gIGlmIChkaWxhdGlvbnMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgPT09IDApIHtcbiAgICBjb25zdCBzcGF0aWFsUmFuayA9IGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDI7XG4gICAgZGlsYXRpb25zID0gbmV3IEFycmF5KHNwYXRpYWxSYW5rKS5maWxsKDEpO1xuICB9XG4gIGxldCBzdHJpZGVzID0gYXR0cmlidXRlcy5zdHJpZGVzLnNsaWNlKCk7XG4gIGlmIChzdHJpZGVzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApID09PSAwKSB7XG4gICAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAyO1xuICAgIHN0cmlkZXMgPSBuZXcgQXJyYXkoc3BhdGlhbFJhbmspLmZpbGwoMSk7XG4gIH1cbiAgLy8gSWYgb3V0cHV0U2hhcGUgaXMgbm90IHNwZWNpZmllZCBpbiB0aGUgYXR0cmlidXRlcyBvZiB0aGlzIG9wLCBpbmZlciBpdCBmcm9tIHRoZSBwYXJhbWV0ZXJzXG4gIC8vIFNpbWlsYXJseSwgYXV0b21hdGljYWxseSBpbmZlciBwYWRzIGlmIG5vdCBzcGVjaWZpZWRcbiAgY2FsY3VsYXRlT3V0cHV0U2hhcGVBbmRQYWRzKFxuICAgIGlucHV0U2hhcGUsXG4gICAga2VybmVsU2hhcGUsXG4gICAgZGlsYXRpb25zLFxuICAgIGF0dHJpYnV0ZXMuYXV0b1BhZCxcbiAgICBhdHRyaWJ1dGVzLmdyb3VwLFxuICAgIHBhZHMsXG4gICAgc3RyaWRlcyxcbiAgICBpc0NoYW5uZWxzTGFzdCxcbiAgICBvdXRwdXRQYWRkaW5nLFxuICAgIG91dHB1dFNoYXBlLFxuICApO1xuXG4gIC8vIGFsd2F5cyByZXR1cm4gYSBuZXcgb2JqZWN0IHNvIGRvZXMgbm90IG1vZGlmeSB0aGUgb3JpZ2luYWwgYXR0cmlidXRlc1xuICBjb25zdCBuZXdBdHRyaWJ1dGVzOiBUID0gT2JqZWN0LmFzc2lnbih7fSwgYXR0cmlidXRlcyk7XG4gIE9iamVjdC5hc3NpZ24obmV3QXR0cmlidXRlcywgeyBrZXJuZWxTaGFwZSwgcGFkcywgb3V0cHV0UGFkZGluZywgb3V0cHV0U2hhcGUsIGRpbGF0aW9ucywgc3RyaWRlcyB9KTtcbiAgcmV0dXJuIG5ld0F0dHJpYnV0ZXM7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VDb252VHJhbnNwb3NlQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgYWN0aXZhdGlvbkF0dHJpYnV0ZXMgPSBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMoYXR0cmlidXRlcyk7XG4gIC8vIFRPRE8gOiBNYWtlIHRoaXMgZ2VuZXJpYyBlbm91Z2ggdG8gY29tcHV0ZSBkZWZhdWx0IGF0dHJpYnV0ZXMgZm9yIG11bHRpLWRpbWVuc2lvbmFsIGNvbnZcbiAgY29uc3QgZm9ybWF0ID0gYXR0cmlidXRlcy5mb3JtYXQgYXMgJ05IV0MnIHwgJ05DSFcnO1xuICBjb25zdCBhdXRvUGFkID0gWydOT1RTRVQnLCAnVkFMSUQnLCAnU0FNRV9VUFBFUicsICdTQU1FX0xPV0VSJ11bXG4gICAgdHlwZW9mIGF0dHJpYnV0ZXMuYXV0b1BhZCA9PSAndW5kZWZpbmVkJyA/IDAgOiAoYXR0cmlidXRlcy5hdXRvUGFkIGFzIG51bWJlcilcbiAgXTtcbiAgY29uc3QgZGlsYXRpb25zID0gYXR0cmlidXRlcy5kaWxhdGlvbnMgYXMgW251bWJlciwgbnVtYmVyXTtcbiAgY29uc3QgZ3JvdXAgPSAoYXR0cmlidXRlcy5ncm91cCBhcyBudW1iZXIpID8/IDE7IC8vIGRlZmF1bHQgdG8gMSBwZXIgT05OWCBzcGVjXG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdO1xuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5wYWRzIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICBjb25zdCBzdHJpZGVzID0gYXR0cmlidXRlcy5zdHJpZGVzIGFzIFtudW1iZXIsIG51bWJlcl07XG4gIGNvbnN0IHdJc0NvbnN0ID0gKGF0dHJpYnV0ZXMud0lzQ29uc3QgYXMgKCkgPT4gYm9vbGVhbikoKTtcbiAgY29uc3Qgb3V0cHV0UGFkZGluZyA9IGF0dHJpYnV0ZXMub3V0cHV0UGFkZGluZyBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBhdHRyaWJ1dGVzLm91dHB1dFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl07XG4gIHJldHVybiB7XG4gICAgYXV0b1BhZCxcbiAgICBmb3JtYXQsXG4gICAgZGlsYXRpb25zLFxuICAgIGdyb3VwLFxuICAgIGtlcm5lbFNoYXBlLFxuICAgIG91dHB1dFBhZGRpbmcsXG4gICAgb3V0cHV0U2hhcGUsXG4gICAgcGFkcyxcbiAgICBzdHJpZGVzLFxuICAgIHdJc0NvbnN0LFxuICAgIC4uLmFjdGl2YXRpb25BdHRyaWJ1dGVzLFxuICAgIGNhY2hlS2V5OiBgJHthdHRyaWJ1dGVzLmZvcm1hdH07JHthY3RpdmF0aW9uQXR0cmlidXRlcy5hY3RpdmF0aW9ufTtgLFxuICB9O1xufTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIC8vIFJlZmVyIHRvIHRoZSBiZWxvdyBsaW5rIGZvciBhbGwgaW5wdXQgY2hlY2tzXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9vbm54L29ubngvYmxvYi9tYWluL2RvY3MvT3BlcmF0b3JzLm1kI0NvbnZUcmFuc3Bvc2VcbiAgaWYgKCFpbnB1dHMgfHwgKGlucHV0cy5sZW5ndGggIT09IDIgJiYgaW5wdXRzLmxlbmd0aCAhPT0gMykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnYgcmVxdWlyZXMgMiBvciAzIGlucHV0cycpO1xuICB9XG5cbiAgLy8gVE9ETyA6IE5lZWQgdG8gYWRkIHN1cHBvcnQgZm9yIG11bHRpLWRpbWVuc2lvbmFsIGNvbnZcbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gNCAmJiBpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnRseSBvbmx5IHN1cHBvcnQgMi1kaW1lbnNpb25hbCBjb252Jyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSBpbnB1dHNbMV0uZGltcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ZpbHRlciBkb2VzIG5vdCBoYXZlIHNhbWUgZGltZW5zaW9uIGFzIGlucHV0Jyk7XG4gIH1cblxuICAvLyBGSUxURVJfSU5fQ0hBTk5FTCBzaG91bGQgYmUgZXF1YWwgdG8gREFUQV9DSEFOTkVMXG4gIGNvbnN0IGRhdGFDaGFubmVsID0gaW5wdXRzWzBdLmRpbXNbYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJyA/IGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDEgOiAxXTtcbiAgY29uc3QgZmlsdGVySW5DaGFubmVsID0gaW5wdXRzWzFdLmRpbXNbMF07XG4gIGlmIChkYXRhQ2hhbm5lbCAhPT0gZmlsdGVySW5DaGFubmVsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGSUxURVJfSU5fQ0hBTk5FTCBzaG91bGQgYmUgZXF1YWwgdG8gREFUQV9DSEFOTkVMJyk7XG4gIH1cblxuICBjb25zdCBmZWF0dXJlTWFwcyA9IGlucHV0c1sxXS5kaW1zWzFdICogYXR0cmlidXRlcy5ncm91cDtcblxuICAvLyBpZiBiaWFzIGlzIHByb3ZpZGVkIGl0IHNob3VsZCBiZSAxRCBhbmQgdGhlIG51bWJlciBvZiBlbGVtZW50cyBzaG91bGQgYmUgZXF1YWwgdG8gdGhlIG51bWJlciBvZiBmZWF0dXJlIG1hcHNcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgKGlucHV0c1syXS5kaW1zLmxlbmd0aCAhPT0gMSB8fCBpbnB1dHNbMl0uZGltc1swXSAhPT0gZmVhdHVyZU1hcHMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJpYXMnKTtcbiAgfVxuXG4gIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMjtcbiAgY29uc3QgZGlsYXRpb25zU2V0ID0gYXR0cmlidXRlcy5kaWxhdGlvbnMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgPiAwO1xuICAvLyB3cm9uZyBkaWxhdGlvbnMgZGltZW5zaW9uXG4gIGlmIChkaWxhdGlvbnNTZXQgJiYgYXR0cmlidXRlcy5kaWxhdGlvbnMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgZGlsYXRpb25zIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIGNvbnN0IHN0cmlkZXNTZXQgPSBhdHRyaWJ1dGVzLnN0cmlkZXMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgPiAwO1xuICAvLyBXcm9uZyBzdHJpZGVzIGRpbWVuc2lvblxuICBpZiAoc3RyaWRlc1NldCAmJiBhdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgc3RyaWRlcyBzaG91bGQgYmUgJHtzcGF0aWFsUmFua31EYCk7XG4gIH1cblxuICAvLyBXcm9uZyBwYWRzIGRpbWVuc2lvblxuICBjb25zdCBwYWRzU2V0ID0gYXR0cmlidXRlcy5wYWRzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApID4gMDtcbiAgaWYgKHBhZHNTZXQgJiYgYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmsgKiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBwYWRzIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rICogMn1EYCk7XG4gIH1cblxuICAvLyBXcm9uZyBvdXRwdXQgcGFkZGluZyBkaW1lbnNpb25cbiAgaWYgKGF0dHJpYnV0ZXMub3V0cHV0UGFkZGluZy5sZW5ndGggIT09IHNwYXRpYWxSYW5rICYmIGF0dHJpYnV0ZXMub3V0cHV0UGFkZGluZy5sZW5ndGggIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYG91dHB1dF9wYWRkaW5nIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIGlmIGtlcm5lbFNoYXBlIGlzIHNwZWNpZmllZCwgaXQncyBkYXRhIGxlbmd0aCBtdXN0IGJlIDIgbGVzcyB0aGFuIGRpbXMgbGVuZ3RoIG9mIHRoZSB3ZWlnaHRzIHRlbnNvclxuICAvLyAodGhlIGZpcnN0IDIgZGltcyBhcmUgYmF0Y2hfc2l6ZSBhbmQgY2hhbm5lbHMpXG4gIGNvbnN0IGtlcm5lbFNoYXBlU2V0ID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKSA+IDA7XG4gIGlmIChcbiAgICBrZXJuZWxTaGFwZVNldCAmJlxuICAgIGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoICE9PSAwICYmXG4gICAgYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggIT09IGlucHV0c1sxXS5kaW1zLmxlbmd0aCAtIDJcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGtlcm5lbCBzaGFwZScpO1xuICB9XG5cbiAgLy8gYXMgd2l0aCBrZXJuZWxTaGFwZSwgbXVzdCBoYXZlIHNhbWUgbnVtYmVyIG9mIHNwYXRpYWwgZGltcyBhcyBpbnB1dFxuICBpZiAoYXR0cmlidXRlcy5vdXRwdXRTaGFwZS5sZW5ndGggIT09IDAgJiYgYXR0cmlidXRlcy5vdXRwdXRTaGFwZS5sZW5ndGggIT09IGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgb3V0cHV0IHNoYXBlJyk7XG4gIH1cbn07XG5cbmNvbnN0IGNvbnZUcmFuc3Bvc2UyZCA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyxcbiAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSxcbik6IHZvaWQgPT4ge1xuICAvLyBTVEVQLjE6IHRyYW5zcG9zZSB3ZWlnaHRcbiAgY29uc3QgdHJhbnNwb3NlZFdlaWdodCA9XG4gICAgKGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCBhcyBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkKSA/P1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhpbnB1dHNbMV0sIFsyLCAzLCAwLCAxXSksIHtcbiAgICAgIGlucHV0czogWzFdLFxuICAgICAgb3V0cHV0czogW2F0dHJpYnV0ZXMud0lzQ29uc3QgPyAtMiA6IC0xXSxcbiAgICB9KVswXTtcbiAgaWYgKGF0dHJpYnV0ZXMud0lzQ29uc3QgJiYgIWNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCkge1xuICAgIGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCA9IHRyYW5zcG9zZWRXZWlnaHQ7XG4gIH1cblxuICAvLyBTVEVQLjI6IHByZXBhcmUgcmVzaGFwZWQgaW5wdXRzXG4gIGNvbnN0IGNvbnZUcmFuc3Bvc2VJbnB1dHMgPSBbaW5wdXRzWzBdLCB0cmFuc3Bvc2VkV2VpZ2h0XTtcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICBjb252VHJhbnNwb3NlSW5wdXRzLnB1c2goaW5wdXRzWzJdKTtcbiAgfVxuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlQ29udlRyYW5zcG9zZTJEUHJvZ3JhbUluZm8oY29udlRyYW5zcG9zZUlucHV0cywgYXR0cmlidXRlcywgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24pLCB7XG4gICAgaW5wdXRzOiBjb252VHJhbnNwb3NlSW5wdXRzLFxuICB9KTtcbn07XG5cbmNvbnN0IGNvbnZUcmFuc3Bvc2UxZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgLy8gZXh0ZW5kIHRoZSBpbnB1dCB0byAyRCBieSBhZGRpbmcgSCBkaW1lbnNpb25cbiAgY29uc3QgaXNDaGFubmVsTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG5cbiAgY29uc3QgaW5wdXRzID0gW1xuICAgIGNvbnRleHQuaW5wdXRzWzBdLnJlc2hhcGUoXG4gICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgID8gLy8gW04sIFcsIENdIC0+IFtOLCBIPTEsIFcsIENdXG4gICAgICAgICAgW2NvbnRleHQuaW5wdXRzWzBdLmRpbXNbMF0sIDEsIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMV0sIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMl1dXG4gICAgICAgIDogLy8gW04sIEMsIFddIC0+IFtOLCBDLCBIPTEsIFddXG4gICAgICAgICAgW2NvbnRleHQuaW5wdXRzWzBdLmRpbXNbMF0sIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMV0sIDEsIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMl1dLFxuICAgICksXG4gICAgLy9bRklMVEVSX09VVF9DSEFOTkVMLCBGSUxURVJfSU5fQ0hBTk5FTCwga1ddIC0+IFtGSUxURVJfT1VUX0NIQU5ORUwsIEZJTFRFUl9JTl9DSEFOTkVMLCBrSD0xLCBrV11cbiAgICBjb250ZXh0LmlucHV0c1sxXS5yZXNoYXBlKFtjb250ZXh0LmlucHV0c1sxXS5kaW1zWzBdLCBjb250ZXh0LmlucHV0c1sxXS5kaW1zWzFdLCAxLCBjb250ZXh0LmlucHV0c1sxXS5kaW1zWzJdXSksXG4gIF07XG4gIGlmIChjb250ZXh0LmlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICBpbnB1dHMucHVzaChjb250ZXh0LmlucHV0c1syXSk7XG4gIH1cbiAgbGV0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZTtcbiAgaWYgKGtlcm5lbFNoYXBlLmxlbmd0aCA9PT0gMCB8fCBrZXJuZWxTaGFwZVswXSA9PT0gMCkge1xuICAgIGtlcm5lbFNoYXBlID0gW2NvbnRleHQuaW5wdXRzWzFdLmRpbXNbMl1dO1xuICB9XG4gIGxldCBkaWxhdGlvbnMgPSBhdHRyaWJ1dGVzLmRpbGF0aW9ucztcbiAgaWYgKGRpbGF0aW9ucy5sZW5ndGggPT09IDAgfHwgZGlsYXRpb25zWzBdID09PSAwKSB7XG4gICAgZGlsYXRpb25zID0gWzFdO1xuICB9XG4gIGxldCBzdHJpZGVzID0gYXR0cmlidXRlcy5zdHJpZGVzO1xuICBpZiAoc3RyaWRlcy5sZW5ndGggPT09IDAgfHwgc3RyaWRlc1swXSA9PT0gMCkge1xuICAgIHN0cmlkZXMgPSBbMV07XG4gIH1cbiAgbGV0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHM7XG4gIGlmIChwYWRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHBhZHMgPSBbMCwgMF07XG4gIH1cbiAgcGFkcyA9IFswLCBwYWRzWzBdLCAwLCBwYWRzWzFdXTtcbiAgc3RyaWRlcyA9IFsxXS5jb25jYXQoc3RyaWRlcyk7XG4gIGRpbGF0aW9ucyA9IFsxXS5jb25jYXQoZGlsYXRpb25zKTtcbiAga2VybmVsU2hhcGUgPSBbMV0uY29uY2F0KGtlcm5lbFNoYXBlKTtcbiAgbGV0IG91dHB1dFBhZGRpbmcgPSBhdHRyaWJ1dGVzLm91dHB1dFBhZGRpbmc7XG4gIG91dHB1dFBhZGRpbmcgPSBbMF0uY29uY2F0KG91dHB1dFBhZGRpbmcpO1xuICBjb25zdCBhZGp1c3RlZEF0dHJpYnV0ZXMgPSBnZXRBZGp1c3RlZENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKFxuICAgIHsgLi4uYXR0cmlidXRlcywgcGFkcywgc3RyaWRlcywgZGlsYXRpb25zLCBrZXJuZWxTaGFwZSwgb3V0cHV0UGFkZGluZyB9LFxuICAgIGlucHV0cyxcbiAgKTtcblxuICBjb252VHJhbnNwb3NlMmQoY29udGV4dCwgaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMsIChvdXRwdXRTaGFwZSkgPT5cbiAgICBpc0NoYW5uZWxMYXN0ID8gW291dHB1dFNoYXBlWzBdLCBvdXRwdXRTaGFwZVsyXSwgb3V0cHV0U2hhcGVbM11dIDogW291dHB1dFNoYXBlWzBdLCBvdXRwdXRTaGFwZVsxXSwgb3V0cHV0U2hhcGVbM11dLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvbnZUcmFuc3Bvc2UgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgaWYgKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMubGVuZ3RoID09PSAzKSB7XG4gICAgY29udlRyYW5zcG9zZTFkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IGFkanVzdGVkQXR0cmlidXRlcyA9IGdldEFkanVzdGVkQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMoYXR0cmlidXRlcywgY29udGV4dC5pbnB1dHMpO1xuICAgIGNvbnZUcmFuc3Bvc2UyZChjb250ZXh0LCBjb250ZXh0LmlucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBnZXRFbGVtZW50QXQsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3VtU3VtQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGV4Y2x1c2l2ZTogYm9vbGVhbjtcbiAgcmVhZG9ubHkgcmV2ZXJzZTogYm9vbGVhbjtcbn1cbmNvbnN0IGNyZWF0ZUN1bXN1bVByb2dyYW1JbmZvID0gKFxuICBpbnB1dFR5cGU6IG51bWJlcixcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGF4aXNJbnB1dDogVGVuc29yVmlldyxcbiAgYXR0cmlidXRlczogQ3VtU3VtQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKGlucHV0U2hhcGUpOyAvLyBvdXRwdXRTaGFwZSBpcyBzYW1lIGFzIGlucHV0U2hhcGUuXG4gIGNvbnN0IHJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDsgLy8gaW5wdXQvb3V0cHV0IHJhbmtcbiAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0VHlwZSwgcmFuayk7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dFR5cGUsIHJhbmspO1xuICBjb25zdCBheGlzVmFsdWUgPVxuICAgIGF4aXNJbnB1dC5kYXRhVHlwZSA9PT0gRGF0YVR5cGUuaW50MzIgPyBheGlzSW5wdXQuZ2V0SW50MzJBcnJheSgpWzBdIDogTnVtYmVyKGF4aXNJbnB1dC5nZXRCaWdJbnQ2NEFycmF5KClbMF0pO1xuICBjb25zdCBheGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXhpc1ZhbHVlLCByYW5rKTtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5kZXggPSBgIGkzMigke2lucHV0LmluZGljZXNHZXQoJ2lucHV0SW5kaWNlcycsICd1bmlmb3Jtcy5heGlzJyl9KSBgO1xuICAgIGNvbnN0IG1heCA9IGdldEVsZW1lbnRBdCgndW5pZm9ybXMuaW5wdXRfc2hhcGUnLCAndW5pZm9ybXMuYXhpcycsIHJhbmspO1xuICAgIGNvbnN0IGxvd2VyTGltaXQgPSBhdHRyaWJ1dGVzLnJldmVyc2UgPyBpbmRleCArIChhdHRyaWJ1dGVzLmV4Y2x1c2l2ZSA/ICcgKyAxJyA6ICcnKSA6ICcwJztcbiAgICBjb25zdCB1cHBlckxpbWl0ID0gYXR0cmlidXRlcy5yZXZlcnNlID8gbWF4IDogaW5kZXggKyAoYXR0cmlidXRlcy5leGNsdXNpdmUgPyAnJyA6ICcgKyAxJyk7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgICAke3NoYWRlckhlbHBlclxuICAgICAgICAgICAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0U2l6ZScsICd1MzInKVxuICAgICAgICAgICAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnYXhpcycsICd1MzInKVxuICAgICAgICAgICAgICAgICAgLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG4gICAgICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG4gICAgICAgICAgICAgICAgICB2YXIgaW5wdXRJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgICAgICAgICAgICAgdmFyIHN1bSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KDApO1xuICAgICAgICAgICAgICAgICAgbGV0IGZpcnN0IDogaTMyID0gJHtsb3dlckxpbWl0fTtcbiAgICAgICAgICAgICAgICAgIGxldCBsYXN0IDogaTMyID0gJHt1cHBlckxpbWl0fTtcbiAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgOiBpMzIgPSBmaXJzdDsgaSA8IGxhc3Q7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0SW5kaWNlcycsICd1bmlmb3Jtcy5heGlzJywgJ3UzMihpKScpfTtcbiAgICAgICAgICAgICAgICAgICAgc3VtID0gc3VtICsgJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0SW5kaWNlcycpfTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3N1bScpfTtcbiAgICAgICAgICAgICAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQ3VtU3VtJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5LCBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJ10gfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogaW5wdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0VHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXhpcyB9LFxuICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlLCBpbnB1dFNoYXBlKSxcbiAgICAgIF0sXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGN1bXN1bSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQ3VtU3VtQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBpbnB1dFNoYXBlID0gY29udGV4dC5pbnB1dHNbMF0uZGltcztcbiAgY29uc3QgaW5wdXRUeXBlID0gY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IGF4aXMgPSBjb250ZXh0LmlucHV0c1sxXTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUN1bXN1bVByb2dyYW1JbmZvKGlucHV0VHlwZSwgaW5wdXRTaGFwZSwgYXhpcywgYXR0cmlidXRlcyksIHsgaW5wdXRzOiBbMF0gfSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VDdW1TdW1BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQ3VtU3VtQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGV4Y2x1c2l2ZSA9IChhdHRyaWJ1dGVzLmV4Y2x1c2l2ZSBhcyBudW1iZXIpID09PSAxO1xuICBjb25zdCByZXZlcnNlID0gKGF0dHJpYnV0ZXMucmV2ZXJzZSBhcyBudW1iZXIpID09PSAxO1xuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgZXhjbHVzaXZlLCByZXZlcnNlIH0pO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBJbmRpY2VzSGVscGVyLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEZvcm1hdEF0dHJpYnV0ZXMge1xuICByZWFkb25seSBmb3JtYXQ6ICdOSFdDJyB8ICdOQ0hXJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZXB0aFRvU3BhY2VBdHRyaWJ1dGVzIGV4dGVuZHMgRm9ybWF0QXR0cmlidXRlcywgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYmxvY2tzaXplOiBudW1iZXI7XG4gIHJlYWRvbmx5IG1vZGU6IHN0cmluZztcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignRGVwdGhUb1NwYWNlIHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRGVwdGhUb1NwYWNlIHJlcXVpcmVzIDREIGlucHV0LicpO1xuICB9XG59O1xuXG5jb25zdCBwZXJtRnVuY3Rpb25Cb2R5ID0gKHBlcm06IG51bWJlcltdLCByYW5rOiBudW1iZXIsIGlucHV0OiBJbmRpY2VzSGVscGVyLCBvdXRwdXQ6IEluZGljZXNIZWxwZXIpOiBzdHJpbmcgPT4ge1xuICBjb25zdCByZXZlcnNlRnVuYyA9IFtdO1xuICByZXZlcnNlRnVuYy5wdXNoKGBmbiBwZXJtKGk6ICR7b3V0cHV0LnR5cGUuaW5kaWNlc30pIC0+ICR7aW5wdXQudHlwZS5pbmRpY2VzfSB7XG4gICAgdmFyIGE6ICR7aW5wdXQudHlwZS5pbmRpY2VzfTtgKTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCByYW5rOyArK2kpIHtcbiAgICByZXZlcnNlRnVuYy5wdXNoKGlucHV0LmluZGljZXNTZXQoJ2EnLCBwZXJtW2ldLCBgaVske2l9XWApKTtcbiAgfVxuICByZXZlcnNlRnVuYy5wdXNoKCdyZXR1cm4gYTt9Jyk7XG4gIHJldHVybiByZXZlcnNlRnVuYy5qb2luKCdcXG4nKTtcbn07XG5cbmNvbnN0IGNyZWF0ZURlcHRoVG9TcGFjZVByb2dyYW1JbmZvID0gKGlucHV0VGVuc29yOiBUZW5zb3JWaWV3LCBhdHRyaWJ1dGVzOiBEZXB0aFRvU3BhY2VBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICBsZXQgbjogbnVtYmVyLCBoOiBudW1iZXIsIHc6IG51bWJlciwgYzogbnVtYmVyO1xuICBsZXQgc2hhcGU6IG51bWJlcltdO1xuICBsZXQgcGVybTogbnVtYmVyW107XG4gIGNvbnN0IGlzQ2hhbm5lbExhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBibG9ja3NpemUgPSBhdHRyaWJ1dGVzLmJsb2Nrc2l6ZTtcbiAgY29uc3QgaXNEQ1Jtb2RlID0gYXR0cmlidXRlcy5tb2RlID09PSAnRENSJztcbiAgaWYgKGlzQ2hhbm5lbExhc3QpIHtcbiAgICBbbiwgaCwgdywgY10gPSBpbnB1dFRlbnNvci5kaW1zO1xuICAgIHNoYXBlID0gaXNEQ1Jtb2RlXG4gICAgICA/IFtuLCBoLCB3LCBibG9ja3NpemUsIGJsb2Nrc2l6ZSwgYyAvIGJsb2Nrc2l6ZSAqKiAyXVxuICAgICAgOiBbbiwgaCwgdywgYyAvIGJsb2Nrc2l6ZSAqKiAyLCBibG9ja3NpemUsIGJsb2Nrc2l6ZV07XG4gICAgcGVybSA9IGlzRENSbW9kZSA/IFswLCAxLCAzLCAyLCA0LCA1XSA6IFswLCAxLCA0LCAyLCA1LCAzXTtcbiAgfSBlbHNlIHtcbiAgICBbbiwgaCwgdywgY10gPSBbaW5wdXRUZW5zb3IuZGltc1swXSwgaW5wdXRUZW5zb3IuZGltc1syXSwgaW5wdXRUZW5zb3IuZGltc1szXSwgaW5wdXRUZW5zb3IuZGltc1sxXV07XG4gICAgc2hhcGUgPSBpc0RDUm1vZGVcbiAgICAgID8gW24sIGJsb2Nrc2l6ZSwgYmxvY2tzaXplLCBjIC8gYmxvY2tzaXplICoqIDIsIGgsIHddXG4gICAgICA6IFtuLCBjIC8gYmxvY2tzaXplICoqIDIsIGJsb2Nrc2l6ZSwgYmxvY2tzaXplLCBoLCB3XTtcbiAgICBwZXJtID0gaXNEQ1Jtb2RlID8gWzAsIDMsIDQsIDEsIDUsIDJdIDogWzAsIDEsIDQsIDIsIDUsIDNdO1xuICB9XG4gIGNvbnN0IHJlc2hhcGVkSW5wdXRUZW5zb3IgPSBpbnB1dFRlbnNvci5yZXNoYXBlKHNoYXBlKTtcbiAgY29uc3QgcmVzaGFwZWRJbnB1dFJhbmsgPSByZXNoYXBlZElucHV0VGVuc29yLmRpbXMubGVuZ3RoO1xuICBjb25zdCBpbnB1dERhdGFUeXBlID0gaW5wdXRUZW5zb3IuZGF0YVR5cGU7XG5cbiAgY29uc3QgcmVzaGFwZWRJbnB1dCA9IGlucHV0VmFyaWFibGUoJ2EnLCBpbnB1dERhdGFUeXBlLCByZXNoYXBlZElucHV0UmFuayk7XG4gIGNvbnN0IHBlcm1lZE91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dERhdGFUeXBlLCByZXNoYXBlZElucHV0UmFuayk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyhyZXNoYXBlZElucHV0LCBwZXJtZWRPdXRwdXQpfVxuXG4gICR7cGVybUZ1bmN0aW9uQm9keShwZXJtLCByZXNoYXBlZElucHV0UmFuaywgcmVzaGFwZWRJbnB1dCwgcGVybWVkT3V0cHV0KX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuXG4gICAgbGV0IGluZGljZXMgPSAke3Blcm1lZE91dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgbGV0IGFJbmRpY2VzID0gcGVybShpbmRpY2VzKTtcblxuICAgICR7cGVybWVkT3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgcmVzaGFwZWRJbnB1dC5nZXRCeUluZGljZXMoJ2FJbmRpY2VzJykpfVxuICB9YDtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdEZXB0aFRvU3BhY2UnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHtpbnB1dFRlbnNvci5kaW1zfTske2F0dHJpYnV0ZXMuYmxvY2tzaXplfTske2F0dHJpYnV0ZXMubW9kZX1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKGlucHV0cykgPT4ge1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpc0NoYW5uZWxMYXN0XG4gICAgICAgID8gW24sIGggKiBibG9ja3NpemUsIHcgKiBibG9ja3NpemUsIGMgLyBibG9ja3NpemUgKiogMl1cbiAgICAgICAgOiBbbiwgYyAvIGJsb2Nrc2l6ZSAqKiAyLCBoICogYmxvY2tzaXplLCB3ICogYmxvY2tzaXplXTtcbiAgICAgIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gICAgICBjb25zdCBzaGFwZUJlZm9yZVBlcm0gPSByZXNoYXBlZElucHV0VGVuc29yLmRpbXM7XG4gICAgICBjb25zdCBzaGFwZUFmdGVyUGVybSA9IFNoYXBlVXRpbC5zb3J0QmFzZWRPblBlcm0oc2hhcGVCZWZvcmVQZXJtLCBwZXJtKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgICAgICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoc2hhcGVCZWZvcmVQZXJtLCBzaGFwZUFmdGVyUGVybSksXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGRlcHRoVG9TcGFjZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogRGVwdGhUb1NwYWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVEZXB0aFRvU3BhY2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgYXR0cmlidXRlcykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlRGVwdGhUb1NwYWNlQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IERlcHRoVG9TcGFjZUF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtcbiAgICBibG9ja3NpemU6IGF0dHJpYnV0ZXMuYmxvY2tzaXplIGFzIG51bWJlcixcbiAgICBtb2RlOiBhdHRyaWJ1dGVzLm1vZGUgYXMgc3RyaW5nLFxuICAgIGZvcm1hdDogYXR0cmlidXRlcy5mb3JtYXQgYXMgJ05IV0MnIHwgJ05DSFcnLFxuICB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBFaW5zdW1BdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgZXF1YXRpb246IHN0cmluZztcbn1cbi8vIFRoZSBlcXVhdGlvbiBhdHRyaWJ1dGUgdmFsdWUgaXMgYSBzdHJpbmcgd2hpY2ggY29uc2lzdHMgb2YgbGVmdCBoYW5kIHNpZGUgKExIUykgYW5kIG9wdGlvbmFsbHkgcmlnaHQgaGFuZCBzaWRlIChSSFMpXG4vLyBzZXBhcmF0ZWQgYnkgJy0+Jy4gRXguIFwiaWosamsgLT4gaWtcIiBleHByZXNzZXMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4vLyAgICAgXCJpai0+amlcIiBleHByZXNzZXMgbWF0cml4IHRyYW5zcG9zZVxuLy8gICAgICBcImlpLT5pXCIgZGlhZ29uYWwgZWxlbWVudHMgb2YgYSBzcXVhcmUgbWF0cml4XG4vLyBMSFMgY29uc2lzdHMgb2YgYSBzZXF1ZW5jZSBvZiB0ZXJtcyBzZXBhcmF0ZWQgYnkgY29tbWFzLiBFYWNoIHRlcm0gY29ycmVzcG9uZHMgdG8gYW4gaW5wdXQgdmFyaWFibGUuXG4vLyBFYWNoIHN5bWJvbCBjb3JyZXNwb25kcyB0byBhIGRpbWVuc2lvbiBpbiB0aGUgaW5wdXQgdmFyaWFibGUuIFRoZSBzeW1ib2wgY2FuIGJlIGVpdGhlciBhIGxldHRlciwgJ2EnIHRvICd6JyBvciAnQScgdG9cbi8vICdaJyBvciAnLi4uJyB0byByZXByZXNlbnQgYXJiaXRyYXJ5IGRpbWVuc2lvbnMuXG5cbmNvbnN0IHN5bWJvbFBhdHRlcm4gPSAnW2EtekEtWl18XFxcXC5cXFxcLlxcXFwuJzsgLy8gVGhlIHBhdHRlcm4gZWFjaCBzeW1ib2wgaW4gZWFjaCB0ZXJtIGluIHRoZSBzeW1ib2xpYyBlcXVhdGlvbiBzaG91bGQgbWF0Y2hcbmNvbnN0IHRlcm1QYXR0ZXJuID0gJygnICsgc3ltYm9sUGF0dGVybiArICcpKyc7IC8vIFRoZSBwYXR0ZXJuIGVhY2ggdGVybSBpbiB0aGUgc3ltYm9saWMgZXF1YXRpb24gc2hvdWxkIG1hdGNoXG5jb25zdCB0ZXJtUGF0dGVybk9ubHkgPSAnXicgKyB0ZXJtUGF0dGVybiArICckJzsgLy8gVGhlIHBhdHRlcm5zIG9ubHkgbWF0Y2hlcyBhIHRlcm0gYmVnaW4gdG8gZW5kLlxuY29uc3QgbGhzUGF0dGVybiA9ICcoJyArIHRlcm1QYXR0ZXJuICsgJywpKicgKyB0ZXJtUGF0dGVybjsgLy8gVGhlIHBhdHRlcm4gdGhlIExIUyBzaG91bGQgbWF0Y2hcbmNvbnN0IGxoc1BhdHRlcm5Pbmx5ID0gJ14nICsgbGhzUGF0dGVybiArICckJzsgLy8gVGhlIHBhdHRlcm5zIG9ubHkgbWF0Y2hlcyBhIExIUyBiZWdpbiB0byBlbmQuXG5cbmludGVyZmFjZSBTeW1ib2xJbmZvIHtcbiAgY291bnQ6IG51bWJlcjsgLy8gU3ltYm9sIGNvcnJlc3BvbmRpbmcgdG8gYSBkaW1lbnNpb24gb2YgYW4gaW5wdXRcbiAgaW5wdXRJbmRpY2VzOiBudW1iZXJbXTsgLy8gTnVtYmVyIG9mIGlucHV0IHZhcmlhYmxlcyB0aGUgc3ltYm9sIGNvcnJlc3BvbmRzIHRvXG4gIGRpbVZhbHVlOiBudW1iZXI7IC8vIE51bWJlciBvZiBkaW1lbnNpb25zIHRoZSBzeW1ib2wgY29ycmVzcG9uZHMgdG9cbn1cblxuY2xhc3MgRWluc3VtVGVybSB7XG4gIGNvbnN0cnVjdG9yKGlucHV0SW5kZXggPSAtMSkge1xuICAgIHRoaXMuc3ltYm9sVG9JbmRpY2VzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcltdPigpO1xuICAgIHRoaXMuaW5wdXRJbmRleCA9IGlucHV0SW5kZXg7XG4gIH1cblxuICAvLyBBZGQgYSBzeW1ib2wgdG8gdGhlIHRlcm1cbiAgYWRkU3ltYm9sKHN5bWJvbDogc3RyaW5nLCBpbmRleDogbnVtYmVyKSB7XG4gICAgbGV0IHZhbHVlID0gdGhpcy5zeW1ib2xUb0luZGljZXMuZ2V0KHN5bWJvbCk7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhbHVlID0gW2luZGV4XTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUucHVzaChpbmRleCk7XG4gICAgfVxuICAgIHRoaXMuc3ltYm9sVG9JbmRpY2VzLnNldChzeW1ib2wsIHZhbHVlKTtcbiAgfVxuXG4gIHN5bWJvbFRvSW5kaWNlczogTWFwPHN0cmluZywgbnVtYmVyW10+OyAvLyBNYXAgZnJvbSBzeW1ib2wgdG8gZGltZW5zaW9ucyBvZiB0aGUgaW5wdXQgY29ycmVzcG9uZGluZyB0byB0aGUgdGVybVxuICBpbnB1dEluZGV4OiBudW1iZXI7IC8vIC0xIGZvciBvdXRwdXQgYW5kIDAsIDEsIDIsIC4uLiBmb3IgaW5wdXRzXG59XG5cbmNsYXNzIEVpbnN1bUVxdWF0aW9uIHtcbiAgY29uc3RydWN0b3IoXG4gICAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gICAgcHVibGljIHJlYWRvbmx5IGVxdWF0aW9uOiBzdHJpbmcsXG4gICkge1xuICAgIHRoaXMuaGFzRWxsaXBzaXMgPSBmYWxzZTtcbiAgICB0aGlzLnN5bWJvbFRvSW5mbyA9IG5ldyBNYXA8c3RyaW5nLCBTeW1ib2xJbmZvPigpO1xuICAgIHRoaXMubGhzID0gbmV3IEFycmF5PEVpbnN1bVRlcm0+KCk7XG4gICAgdGhpcy5vdXRwdXREaW1zID0gW107XG4gICAgLy8gQXMgcmhzIG5lZWRzIHRvIGJlIHVwZGF0ZWQgYWxsb3cgdXNpbmcgbGV0IGluc3RlYWQgb2YgY29uc3QgZm9yIGJvdGggbGhzIGFuZCByaHMuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHByZWZlci1jb25zdFxuICAgIGxldCBbbGhzLCByaHNdID0gZXF1YXRpb24uaW5jbHVkZXMoJy0+JykgPyBlcXVhdGlvbi5zcGxpdCgnLT4nLCAyKSA6IFtlcXVhdGlvbiwgJyddO1xuICAgIGlmICghbGhzLm1hdGNoKFJlZ0V4cChsaHNQYXR0ZXJuT25seSkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgTEhTIHRlcm0nKTtcbiAgICB9XG4gICAgY29uc3QgaW5wdXRUZXJtcyA9IGxocy5zcGxpdCgnLCcpO1xuICAgIGlucHV0VGVybXMuZm9yRWFjaCgoaW5wdXRUZXJtLCBpbmRleCkgPT4ge1xuICAgICAgY29uc3QgZGltcyA9IGlucHV0c1tpbmRleF0uZGltcy5zbGljZSgpO1xuICAgICAgaWYgKCFpbnB1dFRlcm0ubWF0Y2goUmVnRXhwKHRlcm1QYXR0ZXJuT25seSkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBMSFMgdGVybScpO1xuICAgICAgfVxuICAgICAgY29uc3QgZWluc3VtVGVybSA9IHRoaXMucHJvY2Vzc1Rlcm0oaW5wdXRUZXJtLCB0cnVlLCBkaW1zLCBpbmRleCk7XG4gICAgICB0aGlzLmxocy5wdXNoKGVpbnN1bVRlcm0pO1xuICAgIH0pO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgUkhTIGlmIG5vdCBzcGVjaWZpZWRcbiAgICBpZiAocmhzID09PSAnJykge1xuICAgICAgLy8gQ29uc3RydWN0IFJIUyBmcm9tIExIUyB0ZXJtcy9zeW1ib2xzXG4gICAgICByaHMgKz0gWy4uLnRoaXMuc3ltYm9sVG9JbmZvLmVudHJpZXMoKV1cbiAgICAgICAgLmZpbHRlcigoW3N5bSwgaW5mb10pID0+IGluZm8uY291bnQgPT09IDEgfHwgc3ltID09PSAnLi4uJylcbiAgICAgICAgLm1hcCgoW3N5bV0pID0+IHN5bSlcbiAgICAgICAgLmpvaW4oJycpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIXJocy5tYXRjaChSZWdFeHAodGVybVBhdHRlcm4pKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgUkhTJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ29tcHV0ZSBvdXRwdXQgZGltc1xuICAgIGNvbnN0IHJoc1N5bWJvbHMgPSByaHMubWF0Y2goUmVnRXhwKHN5bWJvbFBhdHRlcm4sICdnJykpO1xuICAgIHJoc1N5bWJvbHM/LmZvckVhY2goKHN5bWJvbCkgPT4ge1xuICAgICAgaWYgKHN5bWJvbCA9PT0gJy4uLicpIHtcbiAgICAgICAgdGhpcy5vdXRwdXREaW1zID0gdGhpcy5vdXRwdXREaW1zLmNvbmNhdCh0aGlzLmVsbGlwc2lzRGltcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBpbmZvID0gdGhpcy5zeW1ib2xUb0luZm8uZ2V0KHN5bWJvbCk7XG4gICAgICAgIGlmIChpbmZvID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgUkhTIHN5bWJvbCcpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub3V0cHV0RGltcy5wdXNoKGluZm8uZGltVmFsdWUpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMucmhzID0gdGhpcy5wcm9jZXNzVGVybShyaHMsIGZhbHNlLCB0aGlzLm91dHB1dERpbXMpO1xuICB9IC8vIEVuZCBvZiBFaW5zdW1FcWF0aW9uIGNvbnN0cnVjdG9yXG5cbiAgLy8gQWRkIGEgc3ltYm9sIHRvIHRoZSBlcXVhdGlvblxuICBhZGRTeW1ib2woc3ltYm9sOiBzdHJpbmcsIGRpbVZhbHVlOiBudW1iZXIsIGlucHV0SW5kZXg6IG51bWJlcikge1xuICAgIGxldCBpbmZvID0gdGhpcy5zeW1ib2xUb0luZm8uZ2V0KHN5bWJvbCk7XG4gICAgaWYgKGluZm8gIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGluZm8uZGltVmFsdWUgIT09IGRpbVZhbHVlICYmIGluZm8uY291bnQgIT09IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEaW1lbnNpb24gbWlzbWF0Y2gnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGluZm8uY291bnQrKztcbiAgICAgICAgaW5mby5pbnB1dEluZGljZXMucHVzaChpbnB1dEluZGV4KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaW5mbyA9IHsgY291bnQ6IDEsIGRpbVZhbHVlLCBpbnB1dEluZGljZXM6IFtpbnB1dEluZGV4XSB9O1xuICAgIH1cbiAgICB0aGlzLnN5bWJvbFRvSW5mby5zZXQoc3ltYm9sLCBpbmZvKTtcbiAgfVxuXG4gIC8vIFByb2Nlc3Mgb25lIGlucHV0L291dHB1dCB0ZXJtXG4gIHByb2Nlc3NUZXJtKHRlcm06IHN0cmluZywgaXNJbnB1dDogYm9vbGVhbiwgZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGluZGV4ID0gLTEpOiBFaW5zdW1UZXJtIHtcbiAgICBjb25zdCByYW5rID0gZGltcy5sZW5ndGg7XG4gICAgbGV0IGVsbGlwc2lzID0gZmFsc2U7XG4gICAgbGV0IGVsbGlwc2lzRGltcyA9IFtdO1xuICAgIGxldCBuZXh0RGltID0gMDtcbiAgICAvLyBGb3Igb3V0cHV0IGVtcHR5IHN0cmluZyBpcyBhbGxvd2VkIGJlY2F1c2UgdGhlIG91dHB1dCBtYXkgYmUgcmVkdWNlZCB0byBhIHNjYWxhciB2YWx1ZVxuICAgIGlmICghdGVybS5tYXRjaChSZWdFeHAodGVybVBhdHRlcm5Pbmx5KSkgJiYgIWlzSW5wdXQgJiYgdGVybSAhPT0gJycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBMSFMgdGVybScpO1xuICAgIH1cbiAgICBjb25zdCBpbmRleFN5bWJvbHMgPSB0ZXJtLm1hdGNoKFJlZ0V4cChzeW1ib2xQYXR0ZXJuLCAnZycpKTtcbiAgICBjb25zdCBlaW5zdW1UZXJtID0gbmV3IEVpbnN1bVRlcm0oaW5kZXgpO1xuICAgIC8vIHN5bWJvbCBjYW4gYmUgZWl0aGVyIGEgbGV0dHJlLCAnYScgdG8gJ3onIG9yICdBJyB0byAnWicsIG9yICcuLi4nXG4gICAgaW5kZXhTeW1ib2xzPy5mb3JFYWNoKChzeW1ib2w6IHN0cmluZywgaTogbnVtYmVyKSA9PiB7XG4gICAgICBpZiAoc3ltYm9sID09PSAnLi4uJykge1xuICAgICAgICBpZiAoZWxsaXBzaXMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgb25lIGVsbGlwc2lzIGlzIGFsbG93ZWQgcGVyIGlucHV0IHRlcm0nKTtcbiAgICAgICAgfVxuICAgICAgICBlbGxpcHNpcyA9IHRydWU7XG4gICAgICAgIGNvbnN0IGVsbGlwc2lzRGltTGVuZ3RoID0gcmFuayAtIGluZGV4U3ltYm9scy5sZW5ndGggKyAxO1xuICAgICAgICBpZiAoZWxsaXBzaXNEaW1MZW5ndGggPCAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFbGxpcHNpcyBvdXQgb2YgYm91bmRzJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxsaXBzaXNEaW1zID0gZGltcy5zbGljZShuZXh0RGltLCBuZXh0RGltICsgZWxsaXBzaXNEaW1MZW5ndGgpO1xuICAgICAgICBpZiAodGhpcy5oYXNFbGxpcHNpcykge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuZWxsaXBzaXNEaW1zLmxlbmd0aCAhPT0gZWxsaXBzaXNEaW1zLmxlbmd0aCB8fFxuICAgICAgICAgICAgdGhpcy5lbGxpcHNpc0RpbXMudG9TdHJpbmcoKSAhPT0gZWxsaXBzaXNEaW1zLnRvU3RyaW5nKClcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRWxsaXBzaXMgZGltZW5zaW9ucyBtaXNtYXRjaCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChpc0lucHV0KSB7XG4gICAgICAgICAgdGhpcy5oYXNFbGxpcHNpcyA9IHRydWU7XG4gICAgICAgICAgdGhpcy5lbGxpcHNpc0RpbXMgPSBlbGxpcHNpc0RpbXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFbGxpcHNpcyBtdXN0IGJlIHNwZWNpZmllZCBpbiB0aGUgTEhTJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQWRkICcwJywgJzEnLCAnMicsICczJywgJzQnLCBldGMgdG8gcmVwcmVzZW50IGVsbGlwc2lzIGRpbWVuc2lvbnMgdG8gYXZvaWQgc3BlY2lhbCBoYW5kbGluZ1xuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGVsbGlwc2lzRGltcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgIGNvbnN0IHN5bWJvbCA9IFN0cmluZy5mcm9tQ2hhckNvZGUoJzAnLmNoYXJDb2RlQXQoMCkgKyBqKTtcbiAgICAgICAgICBlaW5zdW1UZXJtLmFkZFN5bWJvbChzeW1ib2wsIGkgKyBqKTtcbiAgICAgICAgICB0aGlzLmFkZFN5bWJvbChzeW1ib2wsIGRpbXNbbmV4dERpbSsrXSwgaW5kZXgpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlaW5zdW1UZXJtLmFkZFN5bWJvbChzeW1ib2wsIGkgKyAodGhpcy5oYXNFbGxpcHNpcyA/IHRoaXMuZWxsaXBzaXNEaW1zLmxlbmd0aCAtIDEgOiAwKSk7XG4gICAgICAgIHRoaXMuYWRkU3ltYm9sKHN5bWJvbCwgZGltc1tuZXh0RGltKytdLCBpbmRleCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGVpbnN1bVRlcm07XG4gIH1cblxuICBzeW1ib2xUb0luZm86IE1hcDxzdHJpbmcsIFN5bWJvbEluZm8+OyAvLyBBbGwgc3ltYm9scyBpbiB0aGUgZXF1YXRpb25cbiAgaGFzRWxsaXBzaXM6IGJvb2xlYW47IC8vIFRoZSBlcXVhdGlvbiBoYXMgZWxsaXBzaXMgb3Igbm90XG4gIGVsbGlwc2lzRGltczogbnVtYmVyW107IC8vIFRoZSBkaW1lbnNpb25zIG9mIHRoZSBlcXVhdGlvbiBlbGxpcHNpcyBjb3JyZXNwb25kcyB0by5cbiAgbGhzOiBFaW5zdW1UZXJtW107IC8vIFRlcm1zIG9uIHRoZSBsZWZ0LWhhbmQgc2lkZSBvZiB0aGUgZXF1YXRpb25cbiAgcmhzOiBFaW5zdW1UZXJtOyAvLyBUZXJtIG9uIHRoZSByaWdodC1oYW5kIHNpZGUgb2YgdGhlIGVxdWF0aW9uXG4gIG91dHB1dERpbXM6IG51bWJlcltdOyAvLyBPdXRwdXQgZGltZW5zaW9ucyBvZiB0aGUgZXF1YXRpb25cbn0gLy8gRW5kIG9mIGNsYXNzIEVpbnN1bUVxdWF0aW9uXG5cbmNvbnN0IGFwcGVuZE1heCA9IChuYW1lOiBzdHJpbmcpOiBzdHJpbmcgPT4gbmFtZSArICdfbWF4JztcblxuY29uc3QgY3JlYXRlRWluc3VtUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0U2hhcGVzOiBBcnJheTxyZWFkb25seSBudW1iZXJbXT4sXG4gIGRhdGFUeXBlOiBudW1iZXIsXG4gIGVpbnN1bUVxdWF0aW9uOiBFaW5zdW1FcXVhdGlvbixcbiAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCByYW5rcyA9IGlucHV0U2hhcGVzLm1hcCgoZGltcykgPT4gZGltcy5sZW5ndGgpO1xuICBjb25zdCBpbnB1dFZhcnMgPSByYW5rcy5tYXAoKHJhbmssIGluZGV4KSA9PiBpbnB1dFZhcmlhYmxlKGBpbnB1dCR7aW5kZXh9YCwgZGF0YVR5cGUsIHJhbmspKTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICBjb25zdCB1bmlmb3Jtc1N5bWJvbHMgPSBbLi4uZWluc3VtRXF1YXRpb24uc3ltYm9sVG9JbmZvLmtleXMoKV0uZmlsdGVyKFxuICAgIChzeW1ib2wpID0+ICFlaW5zdW1FcXVhdGlvbi5yaHMuc3ltYm9sVG9JbmRpY2VzLmhhcyhzeW1ib2wpLFxuICApO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBpZHhDb3B5OiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IGluaXRQcm9kID0gJ3ZhciBwcm9kID0gMS4wOyc7XG4gICAgY29uc3QgaW5pdFN1bSA9ICd2YXIgc3VtID0gMC4wOyc7XG4gICAgY29uc3QgdXBkYXRlU3VtID0gJ3N1bSArPSBwcm9kOyc7XG4gICAgY29uc3QgcmVkdWNlT3BzU2V0SW5kaWNlczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCByZWR1Y2VPcHNMb29wSGVhZGVyczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCByZWR1Y2VPcHNMb29wRm9vdGVyczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCByZWR1Y2VPcENvbXB1dGU6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgaXNSZWR1Y2VPcHNXaXRob3V0TG9vcCA9IGVpbnN1bUVxdWF0aW9uLnN5bWJvbFRvSW5mby5zaXplID09PSBlaW5zdW1FcXVhdGlvbi5yaHMuc3ltYm9sVG9JbmRpY2VzLnNpemU7XG4gICAgZWluc3VtRXF1YXRpb24uc3ltYm9sVG9JbmZvLmZvckVhY2goKGluZm8sIHN5bWJvbCkgPT4ge1xuICAgICAgaWYgKGVpbnN1bUVxdWF0aW9uLnJocy5zeW1ib2xUb0luZGljZXMuaGFzKHN5bWJvbCkpIHtcbiAgICAgICAgY29uc3Qgb3V0cHV0SW5kZXggPSBlaW5zdW1FcXVhdGlvbi5yaHMuc3ltYm9sVG9JbmRpY2VzLmdldChzeW1ib2wpPy5bMF07XG4gICAgICAgIGlmIChvdXRwdXRJbmRleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgZWluc3VtRXF1YXRpb24ubGhzLmZvckVhY2goKHRlcm0sIGkpID0+IHtcbiAgICAgICAgICAgIGlmIChpbmZvLmlucHV0SW5kaWNlcy5pbmNsdWRlcyhpKSkge1xuICAgICAgICAgICAgICBjb25zdCBpbmRpY2VzID0gdGVybS5zeW1ib2xUb0luZGljZXMuZ2V0KHN5bWJvbCk7XG4gICAgICAgICAgICAgIGlmIChpbmRpY2VzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3ltYm9sIGVycm9yJyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaW5kaWNlcy5mb3JFYWNoKChpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgIGlkeENvcHkucHVzaChcbiAgICAgICAgICAgICAgICAgIGAke2lucHV0VmFyc1tpXS5pbmRpY2VzU2V0KFxuICAgICAgICAgICAgICAgICAgICBgaW5wdXQke2l9SW5kaWNlc2AsXG4gICAgICAgICAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0SW5kaWNlcycsIG91dHB1dEluZGV4KSxcbiAgICAgICAgICAgICAgICAgICl9YCxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWluc3VtRXF1YXRpb24ubGhzLmZvckVhY2goKHRlcm0sIGkpID0+IHtcbiAgICAgICAgICBpZiAoaW5mby5pbnB1dEluZGljZXMuaW5jbHVkZXMoaSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGluZGljZXMgPSB0ZXJtLnN5bWJvbFRvSW5kaWNlcy5nZXQoc3ltYm9sKTtcbiAgICAgICAgICAgIGlmIChpbmRpY2VzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN5bWJvbCBlcnJvcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5kaWNlcy5mb3JFYWNoKChpbmRleCkgPT4ge1xuICAgICAgICAgICAgICByZWR1Y2VPcHNTZXRJbmRpY2VzLnB1c2goYCR7aW5wdXRWYXJzW2ldLmluZGljZXNTZXQoYGlucHV0JHtpfUluZGljZXNgLCBpbmRleCwgYCR7c3ltYm9sfWApfWApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZWR1Y2VPcENvbXB1dGUucHVzaChgcHJvZCAqPSAke2lucHV0VmFyc1tpXS5nZXRCeUluZGljZXMoYGlucHV0JHtpfUluZGljZXNgKX07YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmVkdWNlT3BzTG9vcEhlYWRlcnMucHVzaChcbiAgICAgICAgICBgZm9yKHZhciAke3N5bWJvbH06IHUzMiA9IDA7ICR7c3ltYm9sfSA8IHVuaWZvcm1zLiR7YXBwZW5kTWF4KHN5bWJvbCl9OyAke3N5bWJvbH0rKykge2AsXG4gICAgICAgICk7XG4gICAgICAgIHJlZHVjZU9wc0xvb3BGb290ZXJzLnB1c2goJ30nKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjb25zdCByZWR1Y2VPcHMgPSBpc1JlZHVjZU9wc1dpdGhvdXRMb29wXG4gICAgICA/IFtcbiAgICAgICAgICAuLi5pZHhDb3B5LFxuICAgICAgICAgIGBsZXQgc3VtID0gJHtpbnB1dFZhcnMubWFwKChpbnB1dFZhciwgaSkgPT4gaW5wdXRWYXIuZ2V0QnlJbmRpY2VzKGBpbnB1dCR7aX1JbmRpY2VzYCkpLmpvaW4oJyAqICcpfTtgLFxuICAgICAgICBdXG4gICAgICA6IFtcbiAgICAgICAgICAuLi5pZHhDb3B5LFxuICAgICAgICAgIGluaXRTdW0sXG4gICAgICAgICAgLi4ucmVkdWNlT3BzTG9vcEhlYWRlcnMsXG4gICAgICAgICAgLi4ucmVkdWNlT3BzU2V0SW5kaWNlcyxcbiAgICAgICAgICBpbml0UHJvZCxcbiAgICAgICAgICAuLi5yZWR1Y2VPcENvbXB1dGUsXG4gICAgICAgICAgdXBkYXRlU3VtLFxuICAgICAgICAgIC4uLnJlZHVjZU9wc0xvb3BGb290ZXJzLFxuICAgICAgICBdO1xuICAgIHJldHVybiBgXG4gICAgICAgICAgICAke3NoYWRlckhlbHBlclxuICAgICAgICAgICAgICAucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3Jtc1N5bWJvbHMubWFwKChzeW1ib2wpID0+ICh7IG5hbWU6IGAke2FwcGVuZE1heChzeW1ib2wpfWAsIHR5cGU6ICd1MzInIH0pKSlcbiAgICAgICAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0U2l6ZScsICd1MzInKVxuICAgICAgICAgICAgICAuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcnMsIG91dHB1dCl9XG5cbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0U2l6ZScpfVxuICAgICAgICAgICAgdmFyIG91dHB1dEluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICAgICAgICAke2lucHV0VmFycy5tYXAoKF92YXIsIGkpID0+IGB2YXIgaW5wdXQke2l9SW5kaWNlczogJHtpbnB1dFZhcnNbaV0udHlwZS5pbmRpY2VzfTtgKS5qb2luKCdcXG4nKX1cbiAgICAgICAgICAgICR7cmVkdWNlT3BzLmpvaW4oJ1xcbicpfTtcbiAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3N1bScpfTtcbiAgICAgICAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnRWluc3VtJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBlaW5zdW1FcXVhdGlvbi5lcXVhdGlvbiwgaW5wdXREZXBlbmRlbmNpZXM6IGlucHV0U2hhcGVzLm1hcCgoKSA9PiAncmFuaycpIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4ge1xuICAgICAgLy8gVGhlIHN5bWJvbHMgZnJvbSB1bmlmb3JtU3ltYm9scyBhcnJheSBhcmUgZ3VhcmFudGVlZCB0byBleGlzdCBpbiBlaW5zdW1FcXVhdGlvbnMuc3ltYm9sVG9JbmZvIG1hcC4gVGhlXG4gICAgICAvLyBmaWx0ZXIgaXMgYWRkZWQgdG8gbWFrZSBzdXJlIHRoYXQgZGltVmFsdWUgaXMgbmV2ZXIgMC5cbiAgICAgIGNvbnN0IHByb2dyYW1Vbmlmb3Jtc0luaXQ6IFByb2dyYW1Vbmlmb3JtW10gPSB1bmlmb3Jtc1N5bWJvbHNcbiAgICAgICAgLmZpbHRlcigoc3ltYm9sKSA9PiBlaW5zdW1FcXVhdGlvbi5zeW1ib2xUb0luZm8uaGFzKHN5bWJvbCkpXG4gICAgICAgIC5tYXAoKHN5bWJvbCkgPT4gKHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBlaW5zdW1FcXVhdGlvbi5zeW1ib2xUb0luZm8uZ2V0KHN5bWJvbCk/LmRpbVZhbHVlIHx8IDAgfSkpO1xuICAgICAgcHJvZ3JhbVVuaWZvcm1zSW5pdC5wdXNoKHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0pO1xuICAgICAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gaW5wdXRTaGFwZXNcbiAgICAgICAgLm1hcCgoZGltcywgXykgPT4gWy4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGRpbXMpXSlcbiAgICAgICAgLnJlZHVjZSgoYWNjLCBpbnB1dFByb2dyYW1Vbmlmb3JtcykgPT4gYWNjLmNvbmNhdChpbnB1dFByb2dyYW1Vbmlmb3JtcyksIHByb2dyYW1Vbmlmb3Jtc0luaXQpO1xuICAgICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGUpKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZSB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgICB9O1xuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGVpbnN1bSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogRWluc3VtQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBlaW5zdW1FcXVhdGlvbiA9IG5ldyBFaW5zdW1FcXVhdGlvbihjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcy5lcXVhdGlvbik7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gZWluc3VtRXF1YXRpb24ub3V0cHV0RGltcztcbiAgY29uc3QgaW5wdXRTaGFwZXMgPSBjb250ZXh0LmlucHV0cy5tYXAoKGlucHV0LCBfKSA9PiBpbnB1dC5kaW1zKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVpbnN1bVByb2dyYW1JbmZvKGlucHV0U2hhcGVzLCBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSwgZWluc3VtRXF1YXRpb24sIG91dHB1dFNoYXBlKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VFaW5zdW1BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogRWluc3VtQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGVxdWF0aW9uID0gKGF0dHJpYnV0ZXMuZXF1YXRpb24gYXMgc3RyaW5nKS5yZXBsYWNlKC9cXHMrL2csICcnKTtcbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IGVxdWF0aW9uIH0pO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignRXhwYW5kIHJlcXVpcmVzIDIgaW5wdXQuJyk7XG4gIH1cbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBzaGFwZSA9IEFycmF5LmZyb20oaW5wdXRzWzFdLmdldEJpZ0ludDY0QXJyYXkoKSwgTnVtYmVyKTtcblxuICBsZXQgc2hhcGVJbmRleCA9IHNoYXBlLmxlbmd0aCA8IGlucHV0U2hhcGUubGVuZ3RoID8gMCA6IHNoYXBlLmxlbmd0aCAtIGlucHV0U2hhcGUubGVuZ3RoO1xuICBsZXQgaW5wdXRTaGFwZUluZGV4ID0gaW5wdXRTaGFwZS5sZW5ndGggPCBzaGFwZS5sZW5ndGggPyAwIDogaW5wdXRTaGFwZS5sZW5ndGggLSBzaGFwZS5sZW5ndGg7XG4gIGZvciAoOyBzaGFwZUluZGV4IDwgc2hhcGUubGVuZ3RoICYmIGlucHV0U2hhcGVJbmRleCA8IGlucHV0U2hhcGUubGVuZ3RoOyArK3NoYXBlSW5kZXgsICsraW5wdXRTaGFwZUluZGV4KSB7XG4gICAgaWYgKFxuICAgICAgc2hhcGVbc2hhcGVJbmRleF0gIT09IGlucHV0U2hhcGVbaW5wdXRTaGFwZUluZGV4XSAmJlxuICAgICAgc2hhcGVbc2hhcGVJbmRleF0gIT09IDEgJiZcbiAgICAgIGlucHV0U2hhcGVbaW5wdXRTaGFwZUluZGV4XSAhPT0gMVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBhbmQgcmVxdWlyZXMgc2hhcGUgdG8gYmUgYnJvYWRjYXN0YWJsZSB0byBpbnB1dCcpO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgZ2V0QWRqdXN0ZWRTaGFwZSA9IChzaGFwZTE6IHJlYWRvbmx5IG51bWJlcltdLCBzaGFwZTI6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyW10gPT4ge1xuICBjb25zdCBkaWZmID0gc2hhcGUxLmxlbmd0aCAtIHNoYXBlMi5sZW5ndGg7XG4gIGNvbnN0IHNoYXBlOiBudW1iZXJbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGRpZmY7ICsraSkge1xuICAgIHNoYXBlLnB1c2goc2hhcGUxW2ldKTtcbiAgfVxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNoYXBlMi5sZW5ndGg7ICsraSkge1xuICAgIHNoYXBlLnB1c2goc2hhcGUyW2ldID09PSAxID8gc2hhcGUxW2kgKyBkaWZmXSA6IHNoYXBlMltpXSk7XG4gIH1cbiAgcmV0dXJuIHNoYXBlO1xufTtcblxuY29uc3QgY2FsY3VsYXRlT3V0cHV0U2hhcGUgPSAoaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSk6IG51bWJlcltdID0+XG4gIGlucHV0U2hhcGUubGVuZ3RoID4gc2hhcGUubGVuZ3RoID8gZ2V0QWRqdXN0ZWRTaGFwZShpbnB1dFNoYXBlLCBzaGFwZSkgOiBnZXRBZGp1c3RlZFNoYXBlKHNoYXBlLCBpbnB1dFNoYXBlKTtcblxuY29uc3QgY3JlYXRlRXhwYW5kUHJvZ3JhbUluZm8gPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3Qgc2hhcGUgPSBBcnJheS5mcm9tKGlucHV0c1sxXS5nZXRCaWdJbnQ2NEFycmF5KCksIE51bWJlcik7XG4gIGNvbnN0IG91dHB1dFNoYXBlOiBudW1iZXJbXSA9IGNhbGN1bGF0ZU91dHB1dFNoYXBlKGlucHV0U2hhcGUsIHNoYXBlKTtcbiAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dHNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IGlzQm9vbE9yU2NhbGFyID0gZGF0YVR5cGUgPT09IERhdGFUeXBlLmJvb2wgfHwgU2hhcGVVdGlsLnNpemUoaW5wdXRTaGFwZSkgPT09IDE7XG4gIGNvbnN0IGlDb21wb25lbnRzID1cbiAgICBkYXRhVHlwZSA9PT0gRGF0YVR5cGUuYm9vbCA/IDQgOiBpbnB1dFNoYXBlLmxlbmd0aCA+IDAgJiYgaW5wdXRTaGFwZVtpbnB1dFNoYXBlLmxlbmd0aCAtIDFdICUgNCA9PT0gMCA/IDQgOiAxO1xuICBjb25zdCBjb21wb25lbnRzID0gaXNCb29sT3JTY2FsYXJcbiAgICA/IDRcbiAgICA6IG91dHB1dFNoYXBlLmxlbmd0aCA+IDAgJiYgb3V0cHV0U2hhcGVbb3V0cHV0U2hhcGUubGVuZ3RoIC0gMV0gJSA0ID09PSAwXG4gICAgICA/IDRcbiAgICAgIDogMTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyBjb21wb25lbnRzKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgZGF0YVR5cGUsIGlucHV0U2hhcGUubGVuZ3RoLCBpQ29tcG9uZW50cyk7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGxldCBhc3NpZ25tZW50OiBzdHJpbmc7XG4gICAgaWYgKGRhdGFUeXBlID09PSBEYXRhVHlwZS5ib29sKSB7XG4gICAgICBjb25zdCBzaW5nbGVBc3NpZ25tZW50ID0gKHJlc1N0cjogc3RyaW5nLCB4OiBudW1iZXIsIHR5cGVDYXN0ID0gJycpID0+IGBcbiAgICAgICAgICBsZXQgb3V0cHV0SW5kaWNlcyR7eH0gPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoYG91dHB1dE9mZnNldCArICR7eH11YCl9O1xuICAgICAgICAgIGxldCBvZmZzZXQke3h9ID0gJHtpbnB1dC5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldChgb3V0cHV0SW5kaWNlcyR7eH1gLCBvdXRwdXQpfTtcbiAgICAgICAgICBsZXQgaW5kZXgke3h9ID0gb2Zmc2V0JHt4fSAvIDR1O1xuICAgICAgICAgIGxldCBjb21wb25lbnQke3h9ID0gb2Zmc2V0JHt4fSAlIDR1O1xuICAgICAgICAgICR7cmVzU3RyfVske3h9XSA9ICR7dHlwZUNhc3R9KCR7aW5wdXQuZ2V0QnlPZmZzZXQoYGluZGV4JHt4fWApfVtjb21wb25lbnQke3h9XSk7XG4gICAgICAgIGA7XG4gICAgICBhc3NpZ25tZW50ID0gYFxuICAgICAgICBsZXQgb3V0cHV0T2Zmc2V0ID0gZ2xvYmFsX2lkeCAqICR7Y29tcG9uZW50c307XG4gICAgICAgIHZhciBkYXRhID0gdmVjNDx1MzI+KDApO1xuICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAwLCAndTMyJyl9XG4gICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDEsICd1MzInKX1cbiAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdkYXRhJywgMiwgJ3UzMicpfVxuICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAzLCAndTMyJyl9XG4gICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ2RhdGEnKX1cbiAgICAgIH1gO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3NpZ25tZW50ID0gYFxuICAgICAgICBsZXQgb3V0cHV0SW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgZ2xvYmFsX2lkeCAqICR7Y29tcG9uZW50c31gKX07XG4gICAgICAgIGxldCBpbnB1dE9mZnNldCA9ICR7aW5wdXQuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoJ291dHB1dEluZGljZXMnLCBvdXRwdXQpfTtcbiAgICAgICAgbGV0IGRhdGEgPSAke291dHB1dC50eXBlLnZhbHVlfSgke2lucHV0LmdldEJ5T2Zmc2V0KGBpbnB1dE9mZnNldCAvICR7aUNvbXBvbmVudHN9YCl9KTtcbiAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAnZGF0YScpfVxuICAgICAgfWA7XG4gICAgfVxuICAgIHJldHVybiBgXG4gICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3JtKCd2ZWNfc2l6ZScsICd1MzInKS5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBvdXRwdXQpfVxuICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLnZlY19zaXplJyl9XG4gICAgJHthc3NpZ25tZW50fWA7XG4gIH07XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRTaGFwZSwgb3V0cHV0U2hhcGUpLFxuICBdO1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdFeHBhbmQnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke291dHB1dFNoYXBlLmxlbmd0aH07JHtpQ29tcG9uZW50c30ke2NvbXBvbmVudHN9YCwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBleHBhbmQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRXhwYW5kUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMpLCB7IGlucHV0czogWzBdIH0pO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxuICBXT1JLR1JPVVBfU0laRSxcbn0gZnJvbSAnLi9jb21tb24nO1xuaW1wb3J0ICogYXMgdW5hcnkgZnJvbSAnLi91bmFyeS1vcCc7XG5cbi8vIEdFTFUgaXMgZGVmaW5lZCBhcyBZPTAuNSpYKigxK3RhbmgoMC43OTc4ODUqWCswLjAzNTY3NypYKlgqWCkpLCB3aGVyZSBYIG1heSBwcmUtYWRkIGEgYmlhcy5cblxuY29uc3QgY3JlYXRlRmFzdEdlbHVQcm9ncmFtSW5mbyA9IChpbnB1dFRlbnNvcnM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dFRlbnNvcnNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShpbnB1dFRlbnNvcnNbMF0uZGltcyk7XG4gIGNvbnN0IGJpYXNMZW5ndGggPSBTaGFwZVV0aWwuc2l6ZShpbnB1dFRlbnNvcnNbMV0uZGltcyk7XG4gIC8vIGNhbiBvbmx5IHVzZSB2ZWM0IHdoZW4gYmlhcyBsZW5ndGggaXMgbXVsdGlwbGUgb2YgNFxuICBjb25zdCB1c2VWZWM0ID0gYmlhc0xlbmd0aCAlIDQgPT09IDA7XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcik6IHN0cmluZyA9PiB7XG4gICAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCBkYXRhVHlwZSwgWzFdLCA0KTtcbiAgICBjb25zdCBiaWFzID0gaW5wdXRWYXJpYWJsZSgnYmlhcycsIGRhdGFUeXBlLCBbMV0sIDQpO1xuICAgIGNvbnN0IHkgPSBvdXRwdXRWYXJpYWJsZSgneScsIGRhdGFUeXBlLCBbMV0sIDQpO1xuXG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3ZlY19zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2JpYXNfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcblxuICAgIGNvbnN0IHNpbmdsZUVsZW1lbnRCaWFzID0gKGk6IDAgfCAxIHwgMiB8IDMpID0+IGBcbiAgICAgIGxldCBiaWFzJHtpfV9vZmZzZXQ6IHUzMiA9IChnbG9iYWxfaWR4ICogNCArICR7aX0pICUgdW5pZm9ybXMuYmlhc19zaXplO1xuICAgICAgbGV0IGJpYXMke2l9ID0gJHtiaWFzLmdldEJ5T2Zmc2V0KGBiaWFzJHtpfV9vZmZzZXQgLyA0YCl9W2JpYXMke2l9X29mZnNldCAlIDRdO2A7XG4gICAgY29uc3QgYmlhc0dldEV4cHJlc3Npb24gPSB1c2VWZWM0XG4gICAgICA/IGBcbiAgICAgIGxldCBiaWFzID0gJHtiaWFzLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4ICUgKHVuaWZvcm1zLmJpYXNfc2l6ZSAvIDQpJyl9O2BcbiAgICAgIDogYCR7c2luZ2xlRWxlbWVudEJpYXMoMCl9JHtzaW5nbGVFbGVtZW50QmlhcygxKX0ke3NpbmdsZUVsZW1lbnRCaWFzKDIpfSR7c2luZ2xlRWxlbWVudEJpYXMoMyl9XG4gICAgICBsZXQgYmlhcyA9ICR7eC50eXBlLnZhbHVlfShiaWFzMCwgYmlhczEsIGJpYXMyLCBiaWFzMyk7YDtcblxuICAgIHJldHVybiBgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyh4LCBiaWFzLCB5KX1cblxuICAgICR7dW5hcnkuZmFzdEdlbHVJbXBsKHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoZGF0YVR5cGUpKX1cblxuICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydChXT1JLR1JPVVBfU0laRSl9XG4gICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfdmVjX3NpemUnKX1cblxuICAgICAgbGV0IHggPSAke3guZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKX07XG4gICAgICAke2JpYXNHZXRFeHByZXNzaW9ufVxuICAgICAgbGV0IHhfaW4gPSB4ICsgYmlhcztcbiAgICAgICR7eS5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsIHVuYXJ5LmZhc3RHZWx1RXhwcmVzc2lvbigneF9pbicpKX1cbiAgICB9YDtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdGYXN0R2VsdVdpdGhCaWFzJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHt1c2VWZWM0fWAsIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3R5cGUnLCAndHlwZSddIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6IChpbnB1dHMpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBpbnB1dHNbMF0uZGltcywgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA0KSB9LFxuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYmlhc0xlbmd0aCB9LFxuICAgICAgXSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyBXT1JLR1JPVVBfU0laRSAvIDQpIH0sXG4gICAgfSksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgZmFzdEdlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgaWYgKGNvbnRleHQuaW5wdXRzLmxlbmd0aCA8IDIgfHwgU2hhcGVVdGlsLnNpemUoY29udGV4dC5pbnB1dHNbMV0uZGltcykgPT09IDApIHtcbiAgICB1bmFyeS5mYXN0R2VsdShjb250ZXh0KTtcbiAgfSBlbHNlIHtcbiAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRmFzdEdlbHVQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cykpO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdhdGhlckF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICBheGlzOiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0dhdGhlciByZXF1aXJlcyAyIGlucHV0cy4nKTtcbiAgfVxufTtcblxuY29uc3QgY3JlYXRlR2F0aGVyUHJvZ3JhbUluZm8gPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IEdhdGhlckF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgaW5kaWNlc1NoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG5cbiAgY29uc3QgaW5wdXRSYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG4gIGNvbnN0IGF4aXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhpcyhhdHRyaWJ1dGVzLmF4aXMsIGlucHV0UmFuayk7XG5cbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlLnNsaWNlKDApO1xuICBvdXRwdXRTaGFwZS5zcGxpY2UoYXhpcywgMSwgLi4uaW5kaWNlc1NoYXBlKTtcblxuICBjb25zdCBheGlzRGltTGltaXQgPSBpbnB1dFNoYXBlW2F4aXNdO1xuICBjb25zdCBjb21wb25lbnRzID0gaW5wdXRzWzBdLmRhdGFUeXBlID09PSBEYXRhVHlwZS5ib29sID8gNCA6IDE7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBNYXRoLmNlaWwoU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gY29tcG9uZW50cyk7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogYXhpc0RpbUxpbWl0IH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF4aXMgfSxcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgaW5wdXRzWzFdLmRpbXMsIG91dHB1dFNoYXBlKSxcbiAgXTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBkYXRhID0gaW5wdXRWYXJpYWJsZSgnZGF0YScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBpbmRpY2VzID0gaW5wdXRWYXJpYWJsZSgnaW5wdXRJbmRpY2VzJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBpbnB1dHNbMV0uZGltcy5sZW5ndGgpO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG5cbiAgICBjb25zdCBjYWxjRGF0YUluZGljZXMgPSAoeDogbnVtYmVyIHwgc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICAgIGNvbnN0IGluZGljZXNSYW5rID0gaW5kaWNlc1NoYXBlLmxlbmd0aDtcbiAgICAgIGxldCBjYWxjU3RyID0gYHZhciBpbmRpY2VzSW5kaWNlcyR7eH0gID0gJHtpbmRpY2VzLnR5cGUuaW5kaWNlc30oMCk7YDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5kaWNlc1Jhbms7IGkrKykge1xuICAgICAgICBjYWxjU3RyICs9IGAke2luZGljZXNSYW5rID4gMSA/IGBpbmRpY2VzSW5kaWNlcyR7eH1bJHtpfV1gIDogYGluZGljZXNJbmRpY2VzJHt4fWB9ID0gJHtcbiAgICAgICAgICBvdXRwdXRTaGFwZS5sZW5ndGggPiAxID8gYG91dHB1dEluZGljZXMke3h9W3VuaWZvcm1zLmF4aXMgKyAke2l9XWAgOiBgb3V0cHV0SW5kaWNlcyR7eH1gXG4gICAgICAgIH07YDtcbiAgICAgIH1cbiAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgIHZhciBpZHgke3h9ID0gJHtpbmRpY2VzLmdldEJ5SW5kaWNlcyhgaW5kaWNlc0luZGljZXMke3h9YCl9O1xuICAgICAgICAgIGlmIChpZHgke3h9IDwgMCkge1xuICAgICAgICAgICAgaWR4JHt4fSA9IGlkeCR7eH0gKyB1bmlmb3Jtcy5heGlzRGltTGltaXQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBkYXRhSW5kaWNlcyR7eH0gOiAke2RhdGEudHlwZS5pbmRpY2VzfTtcbiAgICAgICAgYDtcbiAgICAgIGZvciAobGV0IGkgPSAwLCBqID0gMDsgaSA8IGlucHV0UmFuazsgaSsrKSB7XG4gICAgICAgIGlmIChpID09PSBheGlzKSB7XG4gICAgICAgICAgY2FsY1N0ciArPSBgJHtpbnB1dFJhbmsgPiAxID8gYGRhdGFJbmRpY2VzJHt4fVske2l9XWAgOiBgZGF0YUluZGljZXMke3h9YH0gPSB1MzIoaWR4JHt4fSk7YDtcbiAgICAgICAgICBqICs9IGluZGljZXNSYW5rO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbGNTdHIgKz0gYCR7aW5wdXRSYW5rID4gMSA/IGBkYXRhSW5kaWNlcyR7eH1bJHtpfV1gIDogYGRhdGFJbmRpY2VzJHt4fWB9ID0gJHtcbiAgICAgICAgICAgIG91dHB1dFNoYXBlLmxlbmd0aCA+IDEgPyBgb3V0cHV0SW5kaWNlcyR7eH1bJHtqfV1gIDogYG91dHB1dEluZGljZXMke3h9YFxuICAgICAgICAgIH07YDtcbiAgICAgICAgICBqKys7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBjYWxjU3RyO1xuICAgIH07XG4gICAgbGV0IGFzc2lnbm1lbnQ6IHN0cmluZztcbiAgICBpZiAoaW5wdXRzWzBdLmRhdGFUeXBlID09PSBEYXRhVHlwZS5ib29sKSB7XG4gICAgICBjb25zdCBzaW5nbGVBc3NpZ25tZW50ID0gKHJlc1N0cjogc3RyaW5nLCB4OiBudW1iZXIsIHR5cGVDYXN0ID0gJycpID0+IGBcbiAgICAgICAgICBsZXQgb3V0cHV0SW5kaWNlcyR7eH0gPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoYG91dHB1dE9mZnNldCArICR7eH11YCl9O1xuICAgICAgICAgICR7Y2FsY0RhdGFJbmRpY2VzKHgpfTtcbiAgICAgICAgICBsZXQgb2Zmc2V0JHt4fSA9ICR7ZGF0YS5pbmRpY2VzVG9PZmZzZXQoYGRhdGFJbmRpY2VzJHt4fWApfTtcbiAgICAgICAgICBsZXQgaW5kZXgke3h9ID0gb2Zmc2V0JHt4fSAvIDR1O1xuICAgICAgICAgIGxldCBjb21wb25lbnQke3h9ID0gb2Zmc2V0JHt4fSAlIDR1O1xuICAgICAgICAgICR7cmVzU3RyfVske3h9XSA9ICR7dHlwZUNhc3R9KCR7ZGF0YS5nZXRCeU9mZnNldChgaW5kZXgke3h9YCl9W2NvbXBvbmVudCR7eH1dKTtcbiAgICAgICAgYDtcbiAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgIGxldCBvdXRwdXRPZmZzZXQgPSBnbG9iYWxfaWR4ICogJHtjb21wb25lbnRzfTtcbiAgICAgICAgdmFyIHZhbHVlID0gdmVjNDx1MzI+KDApO1xuICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ3ZhbHVlJywgMCwgJ3UzMicpfVxuICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ3ZhbHVlJywgMSwgJ3UzMicpfVxuICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ3ZhbHVlJywgMiwgJ3UzMicpfVxuICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ3ZhbHVlJywgMywgJ3UzMicpfVxuICAgICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZScpfVxuICAgICAgYDtcbiAgICB9IGVsc2Uge1xuICAgICAgYXNzaWdubWVudCA9IGBcbiAgICAgIGxldCBvdXRwdXRJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgJHtjYWxjRGF0YUluZGljZXMoJycpfTtcbiAgICAgIGxldCB2YWx1ZSA9ICR7ZGF0YS5nZXRCeUluZGljZXMoJ2RhdGFJbmRpY2VzJyl9O1xuICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAndmFsdWUnKX07XG4gICAgICBgO1xuICAgIH1cbiAgICByZXR1cm4gYFxuICAgICAgJHtzaGFkZXJIZWxwZXJcbiAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0U2l6ZScsICd1MzInKVxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdheGlzRGltTGltaXQnLCAnaTMyJylcbiAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnYXhpcycsICd1MzInKVxuICAgICAgICAuZGVjbGFyZVZhcmlhYmxlcyhkYXRhLCBpbmRpY2VzLCBvdXRwdXQpfVxuICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dFNpemUnKX1cbiAgICAgICAgJHthc3NpZ25tZW50fVxuICAgICAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0dhdGhlcicsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYXR0cmlidXRlcy5jYWNoZUtleSwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuaycsICdyYW5rJ10gfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR2F0aGVyQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEdhdGhlckF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgYXhpczogYXR0cmlidXRlcy5heGlzIGFzIG51bWJlciB9KTtcblxuZXhwb3J0IGNvbnN0IGdhdGhlciA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogR2F0aGVyQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBpbnB1dHMgPSBjb250ZXh0LmlucHV0cztcbiAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUdhdGhlclByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyLCBVbmlmb3Jtc0FycmF5VHlwZSB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBHYXRoZXJOREF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBiYXRjaERpbXM6IG51bWJlcjtcbn1cblxuY29uc3QgY29tcHV0ZVNsaWNlT2Zmc2V0cyA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIGluZGljZXNEYXRhOiBUZW5zb3JWaWV3LFxuICBzaXplc0Zyb21TbGljZURpbXNEYXRhOiBudW1iZXJbXSxcbiAgYmF0Y2hEaW1zOiBudW1iZXIsXG4gIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIG51bVNsaWNlczogbnVtYmVyLFxuICBudW1TbGljZXNQZXJCYXRjaDogbnVtYmVyLFxuICBpbnB1dEJhdGNoU3RyaWRlOiBudW1iZXIsXG4gIG51bVNsaWNlRGltczogbnVtYmVyLFxuKSA9PiB7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogbnVtU2xpY2VzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGJhdGNoRGltcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBpbnB1dERpbXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogc2l6ZXNGcm9tU2xpY2VEaW1zRGF0YSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBudW1TbGljZXNQZXJCYXRjaCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBpbnB1dEJhdGNoU3RyaWRlIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG51bVNsaWNlRGltcyB9LFxuICBdO1xuXG4gIGNvbnN0IG91dHB1dFNoYXBlID0gW251bVNsaWNlc107XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGluZGljZXNEYXRhLmRpbXMsIG91dHB1dFNoYXBlKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5kaWNlcyA9IGlucHV0VmFyaWFibGUoJ2luZGljZXNfZGF0YScsIGluZGljZXNEYXRhLmRhdGFUeXBlLCBpbmRpY2VzRGF0YS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ2lucHV0X3NsaWNlX29mZnNldHNfZGF0YScsIERhdGFUeXBlLnVpbnQzMiwgMSwgMSk7XG4gICAgY29uc3QgdmFyaWFibGVzID0gW2luZGljZXMsIG91dHB1dF07XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnYmF0Y2hfZGltcycsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdpbnB1dF9kaW1zJywgdHlwZTogJ3UzMicsIGxlbmd0aDogaW5wdXREaW1zLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnc2l6ZXNfZnJvbV9zbGljZV9kaW1zX2RhdGEnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBzaXplc0Zyb21TbGljZURpbXNEYXRhLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnbnVtX3NsaWNlc19wZXJfYmF0Y2gnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnaW5wdXRfYmF0Y2hfc3RyaWRlJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ251bV9zbGljZV9kaW1zJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4udmFyaWFibGVzKX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICBsZXQgYmF0Y2hfaWR4ID0gZ2xvYmFsX2lkeCAvIHVuaWZvcm1zLm51bV9zbGljZXNfcGVyX2JhdGNoO1xuICAgIGxldCBiYXNlX29mZnNldCA9IGJhdGNoX2lkeCAqIHVuaWZvcm1zLmlucHV0X2JhdGNoX3N0cmlkZTtcblxuICAgIGxldCBzbGljZV9pbmRpY2VzX2Jhc2Vfb2Zmc2V0ID0gZ2xvYmFsX2lkeCAqIHVuaWZvcm1zLm51bV9zbGljZV9kaW1zO1xuICAgIHZhciByZWxhdGl2ZV9zbGljZV9vZmZzZXQgPSAwO1xuICAgIGZvciAodmFyIGRpbV9pZHggPSAwdTsgZGltX2lkeCA8IHVuaWZvcm1zLm51bV9zbGljZV9kaW1zOyBkaW1faWR4ICsrKSB7XG4gICAgICB2YXIgaW5kZXggPSBpMzIoaW5kaWNlc19kYXRhW2RpbV9pZHggKyBzbGljZV9pbmRpY2VzX2Jhc2Vfb2Zmc2V0XS54KTtcbiAgICAgIGxldCBpbnB1dF9kaW1faWR4ID0gdW5pZm9ybXMuYmF0Y2hfZGltcyArIGRpbV9pZHg7XG4gICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgICR7XG4gICAgICAgICAgaW5wdXREaW1zLmxlbmd0aCA9PT0gMVxuICAgICAgICAgICAgPyAnaW5kZXggKz0gaTMyKHVuaWZvcm1zLmlucHV0X2RpbXMpOydcbiAgICAgICAgICAgIDogJ2luZGV4ICs9IGkzMih1bmlmb3Jtcy5pbnB1dF9kaW1zW2lucHV0X2RpbV9pZHhdKTsnXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgICR7XG4gICAgICAgIHNpemVzRnJvbVNsaWNlRGltc0RhdGEubGVuZ3RoID09PSAxXG4gICAgICAgICAgPyAncmVsYXRpdmVfc2xpY2Vfb2Zmc2V0ICs9IGluZGV4ICogaTMyKHVuaWZvcm1zLnNpemVzX2Zyb21fc2xpY2VfZGltc19kYXRhKTsnXG4gICAgICAgICAgOiAncmVsYXRpdmVfc2xpY2Vfb2Zmc2V0ICs9IGluZGV4ICogaTMyKHVuaWZvcm1zLnNpemVzX2Zyb21fc2xpY2VfZGltc19kYXRhW2RpbV9pZHhdKTsnXG4gICAgICB9XG4gICAgfVxuXG4gICAgaW5wdXRfc2xpY2Vfb2Zmc2V0c19kYXRhW2dsb2JhbF9pZHhdID0gIGJhc2Vfb2Zmc2V0ICsgdTMyKHJlbGF0aXZlX3NsaWNlX29mZnNldCk7XG4gIH1gO1xuICB9O1xuXG4gIHJldHVybiBjb250ZXh0LmNvbXB1dGUoXG4gICAge1xuICAgICAgbmFtZTogJ2NvbXB1dGVTbGljZU9mZnNldHMnLFxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7aW5wdXREaW1zLmxlbmd0aH1fJHtzaXplc0Zyb21TbGljZURpbXNEYXRhLmxlbmd0aH1gLCBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJ10gfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogY29udGV4dC5pbnB1dHNbMV0uZGF0YVR5cGUgfV0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG51bVNsaWNlcyAvIDY0KSB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9LFxuICAgIHsgaW5wdXRzOiBbaW5kaWNlc0RhdGFdLCBvdXRwdXRzOiBbLTFdIH0sXG4gIClbMF07XG59O1xuXG5leHBvcnQgY29uc3QgZ2F0aGVyTkQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEdhdGhlck5EQXR0cmlidXRlcykgPT4ge1xuICBjb25zdCBpbnB1dHMgPSBjb250ZXh0LmlucHV0cztcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBpbnB1dFR5cGUgPSBpbnB1dHNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IGluZGljZXNTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICBjb25zdCBudW1TbGljZURpbXMgPSBpbmRpY2VzU2hhcGVbaW5kaWNlc1NoYXBlLmxlbmd0aCAtIDFdO1xuICBjb25zdCBudW1TbGljZXMgPSBTaGFwZVV0aWwuc2l6ZVRvRGltZW5zaW9uKGluZGljZXNTaGFwZSwgaW5kaWNlc1NoYXBlLmxlbmd0aCAtIDEpO1xuICBjb25zdCBzbGljZVNpemUgPSBTaGFwZVV0aWwuc2l6ZUZyb21EaW1lbnNpb24oaW5wdXRTaGFwZSwgYXR0cmlidXRlcy5iYXRjaERpbXMgKyBudW1TbGljZURpbXMpO1xuICBjb25zdCBudW1CYXRjaGVzID0gU2hhcGVVdGlsLnNpemVUb0RpbWVuc2lvbihpbnB1dFNoYXBlLCBhdHRyaWJ1dGVzLmJhdGNoRGltcyk7XG4gIGNvbnN0IGlucHV0QmF0Y2hTdHJpZGUgPSBTaGFwZVV0aWwuc2l6ZUZyb21EaW1lbnNpb24oaW5wdXRTaGFwZSwgYXR0cmlidXRlcy5iYXRjaERpbXMpO1xuICBjb25zdCBudW1TbGljZXNQZXJCYXRjaCA9IG51bVNsaWNlcyAvIG51bUJhdGNoZXM7XG4gIGNvbnN0IHNpemVzRnJvbVNsaWNlRGltcyA9IG5ldyBBcnJheShudW1TbGljZURpbXMpO1xuICBsZXQgcnVubmluZ1Byb2R1Y3QgPSBzbGljZVNpemU7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtU2xpY2VEaW1zOyArK2kpIHtcbiAgICBzaXplc0Zyb21TbGljZURpbXNbbnVtU2xpY2VEaW1zIC0gMSAtIGldID0gcnVubmluZ1Byb2R1Y3Q7XG4gICAgcnVubmluZ1Byb2R1Y3QgKj0gaW5wdXRTaGFwZVthdHRyaWJ1dGVzLmJhdGNoRGltcyArIG51bVNsaWNlRGltcyAtIDEgLSBpXTtcbiAgfVxuXG4gIGNvbnN0IGlucHV0U2xpY2VPZmZzZXRzID0gY29tcHV0ZVNsaWNlT2Zmc2V0cyhcbiAgICBjb250ZXh0LFxuICAgIGlucHV0c1sxXSxcbiAgICBzaXplc0Zyb21TbGljZURpbXMsXG4gICAgYXR0cmlidXRlcy5iYXRjaERpbXMsXG4gICAgaW5wdXRTaGFwZSxcbiAgICBudW1TbGljZXMsXG4gICAgbnVtU2xpY2VzUGVyQmF0Y2gsXG4gICAgaW5wdXRCYXRjaFN0cmlkZSxcbiAgICBudW1TbGljZURpbXMsXG4gICk7XG5cbiAgY29uc3QgbGFzdEluZGljZXNEaW1lbnNpb24gPSBhdHRyaWJ1dGVzLmJhdGNoRGltcyArIG51bVNsaWNlRGltcztcbiAgaWYgKGxhc3RJbmRpY2VzRGltZW5zaW9uID4gaW5wdXRTaGFwZS5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2xhc3QgZGltZW5zaW9uIG9mIGluZGljZXMgbXVzdCBub3QgYmUgbGFyZ2VyIHRoYW4gcmFuayBvZiBpbnB1dCB0ZW5zb3InKTtcbiAgfVxuXG4gIGNvbnN0IG91dHB1dFNoYXBlID0gaW5kaWNlc1NoYXBlLnNsaWNlKDAsIC0xKS5jb25jYXQoaW5wdXRTaGFwZS5zbGljZShsYXN0SW5kaWNlc0RpbWVuc2lvbikpO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzbGljZVNpemUgfSxcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgaW5wdXRTbGljZU9mZnNldHMuZGltcywgb3V0cHV0U2hhcGUpLFxuICBdO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnZGF0YScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBpbmRpY2VzID0gaW5wdXRWYXJpYWJsZSgnc2xpY2Vfb2Zmc2V0cycsIERhdGFUeXBlLnVpbnQzMiwgaW5wdXRTbGljZU9mZnNldHMuZGltcy5sZW5ndGgpO1xuXG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgICByZXR1cm4gYFxuICAgICAgICAgICR7c2hhZGVySGVscGVyXG4gICAgICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRfc2l6ZScsICd1MzInKVxuICAgICAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnc2xpY2Vfc2l6ZScsICd1MzInKVxuICAgICAgICAgICAgLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIGluZGljZXMsIG91dHB1dCl9XG4gICAgICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgICAgICAgbGV0IHNsaWNlX29mZnNldCA9IHNsaWNlX29mZnNldHNbZ2xvYmFsX2lkeCAvIHVuaWZvcm1zLnNsaWNlX3NpemVdO1xuICAgICAgICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9IGRhdGFbdTMyKHNsaWNlX29mZnNldCkgKyBnbG9iYWxfaWR4ICUgdW5pZm9ybXMuc2xpY2Vfc2l6ZV07XG4gICAgICAgIH1gO1xuICB9O1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAge1xuICAgICAgbmFtZTogJ0dhdGhlck5EJyxcbiAgICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnLCAncmFuayddIH0sXG4gICAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0VHlwZSB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9LFxuICAgIHsgaW5wdXRzOiBbaW5wdXRzWzBdLCBpbnB1dFNsaWNlT2Zmc2V0c10gfSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdhdGhlck5EQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEdhdGhlck5EQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGJhdGNoRGltcyA9IGF0dHJpYnV0ZXMuYmF0Y2hfZGltcyBhcyBudW1iZXI7XG4gIHJldHVybiB7XG4gICAgYmF0Y2hEaW1zLFxuICAgIGNhY2hlS2V5OiAnJyxcbiAgfTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2F0aGVyQmxvY2tRdWFudGl6ZWRBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgZ2F0aGVyQXhpczogbnVtYmVyO1xuICBxdWFudGl6ZUF4aXM6IG51bWJlcjtcbiAgYmxvY2tTaXplOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogR2F0aGVyQmxvY2tRdWFudGl6ZWRBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmIChpbnB1dHMubGVuZ3RoIDwgMyB8fCBpbnB1dHMubGVuZ3RoID4gNCkge1xuICAgIHRocm93IG5ldyBFcnJvcignR2F0aGVyQmxvY2tRdWFudGl6ZWQgcmVxdWlyZXMgMyBvciA0IGlucHV0cy4nKTtcbiAgfVxuICBjb25zdCBxdWFudGl6ZUF4aXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhpcyhhdHRyaWJ1dGVzLnF1YW50aXplQXhpcywgaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcbiAgY29uc3QgYmxvY2tTaXplID0gYXR0cmlidXRlcy5ibG9ja1NpemU7XG4gIGNvbnN0IGRhdGEgPSBpbnB1dHNbMF07XG4gIGNvbnN0IHNjYWxlcyA9IGlucHV0c1syXTtcbiAgY29uc3QgemVyb1BvaW50ID0gaW5wdXRzLmxlbmd0aCA9PT0gNCA/IGlucHV0c1szXSA6IHVuZGVmaW5lZDtcbiAgaWYgKFxuICAgIHNjYWxlcy5kaW1zLmxlbmd0aCAhPT0gZGF0YS5kaW1zLmxlbmd0aCB8fFxuICAgICFkYXRhLmRpbXNcbiAgICAgIC5tYXAoKGQsIGkpID0+IChpID09PSBxdWFudGl6ZUF4aXMgPyBNYXRoLmNlaWwoZCAvIGJsb2NrU2l6ZSkgPT09IHNjYWxlcy5kaW1zW2ldIDogZCA9PT0gc2NhbGVzLmRpbXNbaV0pKVxuICAgICAgLnJlZHVjZSgoYSwgYikgPT4gYSAmJiBiLCB0cnVlKVxuICApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnU2NhbGVzIG11c3QgaGF2ZSB0aGUgc2FtZSByYW5rIGFzIHRoZSBpbnB1dCB0ZW5zb3IgYW5kIHRoZSBkaW1zIHNob3VsZCBtYXRjaCBleGNlcHQgb24gZ2F0aGVyQXhpcy4nLFxuICAgICk7XG4gIH1cbiAgLy8gVE9ETyBVbmNvbW1lbnQgdGhlIGZvbGxvd2luZyBjaGVjayBvbmNlIHRoZSB0ZXN0IGNhc2UgY3JlYXRpb24gY29kZSBpcyBmaXhlZCB0byBjcmVhdGUgZGF0YSBjb3JyZWN0bHkgYWxpZ25lZC5cbiAgLy8gY29uc3QgaW5kaWNlcyA9IGlucHV0c1sxXTtcbiAgLy8gY29uc3QgdmFsaWRJbmRleCA9IChpbmRleDogbnVtYmVyKSA9PiBpbmRleCA+PSAwICYmIGluZGV4IDwgZGF0YS5kaW1zW2F0dHJpYnV0ZXMuZ2F0aGVyQXhpc107XG4gIC8vIGlmIChpbmRpY2VzLmRhdGFUeXBlID09PSBEYXRhVHlwZS5pbnQzMiAmJiBpbmRpY2VzLmdldEludDMyQXJyYXkoKS5zb21lKCh2KSA9PiAhdmFsaWRJbmRleCh2KSkgfHxcbiAgLy8gICAgIGluZGljZXMuZGF0YVR5cGUgPT09IERhdGFUeXBlLmludDY0ICYmIGluZGljZXMuZ2V0QmlnSW50NjRBcnJheSgpLnNvbWUoKHYpID0+ICF2YWxpZEluZGV4KE51bWJlcih2KSkpKSB7XG4gIC8vICAgdGhyb3cgbmV3IEVycm9yKCdJbmRpY2VzIG11c3QgYmUgd2l0aGluIHRoZSBib3VuZHMgb2YgdGhlIGdhdGhlckF4aXMuJyk7XG4gIC8vIH1cbiAgaWYgKHplcm9Qb2ludCkge1xuICAgIGlmICh6ZXJvUG9pbnQuZGF0YVR5cGUgIT09IGRhdGEuZGF0YVR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignWmVybyBwb2ludCBtdXN0IGhhdmUgdGhlIHNhbWUgZGF0YSB0eXBlIGFzIHRoZSBpbnB1dCB0ZW5zb3IuJyk7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIHplcm9Qb2ludC5kaW1zLmxlbmd0aCAhPT0gc2NhbGVzLmRpbXMubGVuZ3RoIHx8XG4gICAgICAhemVyb1BvaW50LmRpbXMubWFwKChkLCBpKSA9PiBkID09PSBzY2FsZXMuZGltc1tpXSkucmVkdWNlKChhLCBiKSA9PiBhICYmIGIsIHRydWUpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdaZXJvIHBvaW50IG11c3QgaGF2ZSB0aGUgc2FtZSByYW5rIGFzIHRoZSBpbnB1dCB0ZW5zb3IgYW5kIHRoZSBkaW1zIHNob3VsZCBtYXRjaCBleGNlcHQgb24gcXVhbnRpemVBeGlzLicsXG4gICAgICApO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgY3JlYXRlR2F0aGVyQmxvY2tRdWFudGl6ZWRQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IEdhdGhlckJsb2NrUXVhbnRpemVkQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBpbmRpY2VzU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgY29uc3QgaW5wdXRSYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG4gIGNvbnN0IGdhdGhlckF4aXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhpcyhhdHRyaWJ1dGVzLmdhdGhlckF4aXMsIGlucHV0UmFuayk7XG4gIGNvbnN0IHF1YW50aXplQXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMucXVhbnRpemVBeGlzLCBpbnB1dFJhbmspO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoMCk7XG4gIG91dHB1dFNoYXBlLnNwbGljZShnYXRoZXJBeGlzLCAxLCAuLi5pbmRpY2VzU2hhcGUpO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCBvdXRwdXRUeXBlID0gaW5wdXRzWzJdLmRhdGFUeXBlO1xuICBjb25zdCBpbnB1dFR5cGUgPSBpbnB1dHNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IGlzU2lnbmVkID0gaW5wdXRUeXBlID09PSBEYXRhVHlwZS5pbnQ0OyAvLyBpbnB1dCBkYXRhIHR5cGUgaXMgZWl0aGVyIGludDQgb3IgdWludDQuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBxdWFudGl6ZUF4aXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZ2F0aGVyQXhpcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLmJsb2NrU2l6ZSB9LFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKC4uLmlucHV0cy5tYXAoKGlucHV0LCBfKSA9PiBpbnB1dC5kaW1zKSwgb3V0cHV0U2hhcGUpLFxuICBdO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGRhdGEgPSBpbnB1dFZhcmlhYmxlKCdkYXRhJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgpO1xuICAgIGNvbnN0IGluZGljZXMgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dEluZGljZXMnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3Qgc2NhbGVzID0gaW5wdXRWYXJpYWJsZSgnc2NhbGVzJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcy5sZW5ndGgpO1xuICAgIGNvbnN0IHplcm9Qb2ludCA9XG4gICAgICBpbnB1dHMubGVuZ3RoID4gMyA/IGlucHV0VmFyaWFibGUoJ3plcm9Qb2ludCcsIGlucHV0c1szXS5kYXRhVHlwZSwgaW5wdXRzWzNdLmRpbXMubGVuZ3RoKSA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0Jywgb3V0cHV0VHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgICBjb25zdCBpbnB1dFZhcmlhYmxlcyA9IFtkYXRhLCBpbmRpY2VzLCBzY2FsZXNdO1xuICAgIGlmICh6ZXJvUG9pbnQpIHtcbiAgICAgIGlucHV0VmFyaWFibGVzLnB1c2goemVyb1BvaW50KTtcbiAgICB9XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAncXVhbnRpemVfYXhpcycsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdnYXRoZXJfYXhpcycsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdibG9ja19zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuICAgIHJldHVybiBgXG4gICAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICBsZXQgb3V0cHV0X2luZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICAgIHZhciBpbmRpY2VzX2luZGljZXMgPSAke2luZGljZXMudHlwZS5pbmRpY2VzfSgwKTtcbiAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgIGlmIChpbmRpY2VzU2hhcGUubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBmb3IgKHZhciBpOiB1MzIgPSAwOyBpIDwgJHtpbmRpY2VzU2hhcGUubGVuZ3RofTsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsICd1bmlmb3Jtcy5nYXRoZXJfYXhpcyArIGknKX07XG4gICAgICAgICAgICAke2luZGljZXMuaW5kaWNlc1NldCgnaW5kaWNlc19pbmRpY2VzJywgJ2knLCAnaW5kZXgnKX07XG4gICAgICAgICAgfWA7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBgaW5kaWNlc19pbmRpY2VzID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCAndW5pZm9ybXMuZ2F0aGVyX2F4aXMnKX07YDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pKCl9O1xuICAgICAgICB2YXIgZGF0YV9pbmRpY2VzID0gJHtkYXRhLnR5cGUuaW5kaWNlc30oMCk7XG4gICAgICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCB1bmlmb3Jtcy5nYXRoZXJfYXhpczsgaSsrKSB7XG4gICAgICAgICAgbGV0IGluZGV4ID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCAnaScpfTtcbiAgICAgICAgICAke2RhdGEuaW5kaWNlc1NldCgnZGF0YV9pbmRpY2VzJywgJ2knLCAnaW5kZXgnKX07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGluZGV4X2Zyb21faW5kaWNlcyA9ICR7aW5kaWNlcy5nZXRCeUluZGljZXMoJ2luZGljZXNfaW5kaWNlcycpfTtcbiAgICAgICAgaWYgKGluZGV4X2Zyb21faW5kaWNlcyA8IDApIHtcbiAgICAgICAgICBpbmRleF9mcm9tX2luZGljZXMgKz0gJHtpbnB1dFNoYXBlW2dhdGhlckF4aXNdfTtcbiAgICAgICAgfVxuICAgICAgICAke2RhdGEuaW5kaWNlc1NldCgnZGF0YV9pbmRpY2VzJywgJ3VuaWZvcm1zLmdhdGhlcl9heGlzJywgJ3UzMihpbmRleF9mcm9tX2luZGljZXMpJyl9O1xuICAgICAgICBmb3IgKHZhciBpID0gdW5pZm9ybXMuZ2F0aGVyX2F4aXMgKyAxOyBpIDwgJHtvdXRwdXRTaGFwZS5sZW5ndGh9OyBpKyspIHtcbiAgICAgICAgICBsZXQgaW5kZXggPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsIGBpICsgJHtpbmRpY2VzU2hhcGUubGVuZ3RofSAtIDFgKX07XG4gICAgICAgICAgJHtkYXRhLmluZGljZXNTZXQoJ2RhdGFfaW5kaWNlcycsICdpJywgJ2luZGV4Jyl9O1xuICAgICAgICB9XG4gICAgICAgIGxldCBkYXRhX29mZnNldCA9ICR7ZGF0YS5pbmRpY2VzVG9PZmZzZXQoJ2RhdGFfaW5kaWNlcycpfTtcbiAgICAgICAgbGV0IGRhdGFfaW5kZXggPSBkYXRhX29mZnNldCAlIDg7XG4gICAgICAgIC8vIENvbnZlcnQgNC1iaXQgcGFja2VkIGRhdGEgdG8gOC1iaXQgcGFja2VkIGRhdGEuXG4gICAgICAgIGxldCBwYWNrZWRfNGJpdF9xdWFudGl6ZWRfZGF0YSA9ICR7ZGF0YS5nZXRCeU9mZnNldCgnZGF0YV9vZmZzZXQgLyA4Jyl9O1xuICAgICAgICBsZXQgcGFja2VkXzhiaXRfcXVhbnRpemVkX2RhdGEgPSAocGFja2VkXzRiaXRfcXVhbnRpemVkX2RhdGEgPj4gKDQgKiAoZGF0YV9pbmRleCAlIDIpKSkgJiAweDBmMGYwZjBmO1xuICAgICAgICBsZXQgcXVhbnRpemVkX2RhdGFfdmVjID0gJHtpc1NpZ25lZCA/ICd1bnBhY2s0eEk4JyA6ICd1bnBhY2s0eFU4J30odTMyKHBhY2tlZF84Yml0X3F1YW50aXplZF9kYXRhKSk7XG4gICAgICAgIGxldCBxdWFudGl6ZWRfZGF0YSA9IHF1YW50aXplZF9kYXRhX3ZlY1tkYXRhX2luZGV4IC8gMl07XG4gICAgICAgIHZhciBzY2FsZV9pbmRpY2VzID0gZGF0YV9pbmRpY2VzO1xuICAgICAgICBsZXQgcXVhbnRpemVfYXhpc19pbmRleCA9ICR7c2NhbGVzLmluZGljZXNHZXQoJ2RhdGFfaW5kaWNlcycsICd1bmlmb3Jtcy5xdWFudGl6ZV9heGlzJyl9IC8gdW5pZm9ybXMuYmxvY2tfc2l6ZTtcbiAgICAgICAgJHtzY2FsZXMuaW5kaWNlc1NldCgnc2NhbGVfaW5kaWNlcycsICd1bmlmb3Jtcy5xdWFudGl6ZV9heGlzJywgJ3F1YW50aXplX2F4aXNfaW5kZXgnKX07XG4gICAgICAgIHZhciBzY2FsZSA9ICR7c2NhbGVzLmdldEJ5SW5kaWNlcygnc2NhbGVfaW5kaWNlcycpfTtcbiAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgIGlmICghemVyb1BvaW50KSB7XG4gICAgICAgICAgICByZXR1cm4gJ3ZhciB6ZXJvX3BvaW50ID0gMCc7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2luZGljZXMgPSBzY2FsZV9pbmRpY2VzO1xuICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF9vZmZzZXQgPSAke3plcm9Qb2ludC5pbmRpY2VzVG9PZmZzZXQoJ3plcm9fcG9pbnRfaW5kaWNlcycpfTtcbiAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfaW5kZXggPSB6ZXJvX3BvaW50X29mZnNldCAlIDg7XG4gICAgICAgICAgICAgIGxldCBwYWNrZWRfNGJpdF96ZXJvX3BvaW50cyA9ICR7emVyb1BvaW50LmdldEJ5T2Zmc2V0KCd6ZXJvX3BvaW50X29mZnNldCAvIDgnKX07XG4gICAgICAgICAgICAgIGxldCBwYWNrZWRfOGJpdF96ZXJvX3BvaW50cyA9IChwYWNrZWRfNGJpdF96ZXJvX3BvaW50cyA+PiAoNCAqICh6ZXJvX3BvaW50X2luZGV4ICUgMikpKSAmIDB4MGYwZjBmMGY7XG4gICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X3ZlYyA9ICR7aXNTaWduZWQgPyAndW5wYWNrNHhJOCcgOiAndW5wYWNrNHhVOCd9KHUzMihwYWNrZWRfOGJpdF96ZXJvX3BvaW50cykpO1xuICAgICAgICAgICAgICBsZXQgemVyb19wb2ludCA9IHplcm9fcG9pbnRfdmVjW3plcm9fcG9pbnRfaW5kZXggLyAyXTtgO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKX07XG4gICAgICAgIGxldCBkZXF1YW50aXplZF9kYXRhID0gJHt0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKG91dHB1dFR5cGUpfShxdWFudGl6ZWRfZGF0YSAtIHplcm9fcG9pbnQpICogc2NhbGU7XG4gICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ2RlcXVhbnRpemVkX2RhdGEnKX07XG4gICAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0dhdGhlckJsb2NrUXVhbnRpemVkJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX07JHtpbnB1dHNcbiAgICAgICAgLmZpbHRlcigoXywgaSkgPT4gaSAhPT0gMSlcbiAgICAgICAgLm1hcCgoaW5wdXQpID0+IGlucHV0LmRpbXMuam9pbignXycpKVxuICAgICAgICAuam9pbignOycpfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llczogQXJyYXkuZnJvbSh7IGxlbmd0aDogaW5wdXRzLmxlbmd0aCB9LCAoX3YsIF9pKSA9PiAncmFuaycpLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogb3V0cHV0VHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgZ2F0aGVyQmxvY2tRdWFudGl6ZWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEdhdGhlckJsb2NrUXVhbnRpemVkQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBpbnB1dHMgPSBjb250ZXh0LmlucHV0cztcbiAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUdhdGhlckJsb2NrUXVhbnRpemVkUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdhdGhlckJsb2NrUXVhbnRpemVkQXR0cmlidXRlcyA9IChcbiAgYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4pOiBHYXRoZXJCbG9ja1F1YW50aXplZEF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtcbiAgICBibG9ja1NpemU6IGF0dHJpYnV0ZXMuYmxvY2tTaXplIGFzIG51bWJlcixcbiAgICBnYXRoZXJBeGlzOiBhdHRyaWJ1dGVzLmdhdGhlckF4aXMgYXMgbnVtYmVyLFxuICAgIHF1YW50aXplQXhpczogYXR0cmlidXRlcy5xdWFudGl6ZUF4aXMgYXMgbnVtYmVyLFxuICB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2F0aGVyRWxlbWVudHNBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgYXhpczogbnVtYmVyO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdHYXRoZXJFbGVtZW50cyByZXF1aXJlcyAyIGlucHV0cy4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdHYXRoZXJFbGVtZW50cyByZXF1aXJlcyB0aGF0IHRoZSBkYXRhIGlucHV0IGJlIHJhbmsgPj0gMS4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IGlucHV0c1sxXS5kaW1zLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgR2F0aGVyRWxlbWVudHMgcmVxdWlyZXMgdGhhdCB0aGUgZGF0YSBpbnB1dCBhbmRcbiAgICAgICAgICAgICAgICAgICAgIGluZGljZXMgaW5wdXQgdGVuc29ycyBiZSBvZiBzYW1lIHJhbmsuYCk7XG4gIH1cbn07XG5cbmNvbnN0IGNyZWF0ZUdhdGhlckVsZW1lbnRzUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBHYXRoZXJFbGVtZW50c0F0dHJpYnV0ZXMsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgaW5wdXRPdXRwdXREYXRhVHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgaW5wdXRSYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG5cbiAgY29uc3QgaW5kaWNlc1NoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gIGNvbnN0IGluZGljZXNEYXRhVHlwZSA9IGlucHV0c1sxXS5kYXRhVHlwZTtcbiAgY29uc3QgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMuYXhpcywgaW5wdXRSYW5rKTtcbiAgY29uc3QgYXhpc0RpbUxpbWl0ID0gaW5wdXRTaGFwZVtheGlzXTtcblxuICBjb25zdCBvdXRwdXRTaGFwZSA9IGluZGljZXNTaGFwZS5zbGljZSgwKTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcblxuICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgaW5wdXRPdXRwdXREYXRhVHlwZSwgaW5wdXRSYW5rKTtcbiAgY29uc3QgaW5kaWNlcyA9IGlucHV0VmFyaWFibGUoJ2luZGljZXNJbnB1dCcsIGluZGljZXNEYXRhVHlwZSwgaW5kaWNlc1NoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dE91dHB1dERhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGF4aXNEaW1MaW1pdCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBheGlzIH0sXG4gIF07XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0U2hhcGUsIGluZGljZXNTaGFwZSwgb3V0cHV0U2hhcGUpKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3JhbmsnLCAncmFuayddO1xuXG4gIC8vIGludDY0IGluZGljZXMgd291bGQgYmUgdHJlYXRlZCBhcyBsaXR0bGUgZW5kaWFuIGkzMiB3aXRoIGFzc3VtcHRpb24gdGhleSBmYWxsIGluIGkzMiBsaW1pdHNcbiAgLy8gVGhhdCBhc3N1bXB0aW9uIGlzIHNhZmUgYXMgaXQncyBub3QgcG9zc2libGUgdG8gYWxsb2NhdGUgPjJnYiBidWZmZXIgZm9yIGlucHV0IHRlbnNvclxuICAvLyBJbnB1dCBkYXRhIHdpbGwgYmUgdHJlYXRlZCBhcyB1MzIgb3IgdHdvIHUzMiBmb3IgOC1ieXRlIHRlbnNvcnNcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICAgICAke3NoYWRlckhlbHBlclxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRTaXplJywgJ3UzMicpXG4gICAgICAgIC5yZWdpc3RlclVuaWZvcm0oJ2F4aXNEaW1MaW1pdCcsICdpMzInKVxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdheGlzJywgJ3UzMicpXG4gICAgICAgIC5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBpbmRpY2VzLCBvdXRwdXQpfVxuICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG5cbiAgICAgIGxldCBvdXRwdXRJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuXG4gICAgICB2YXIgaWR4ID0gJHtpbmRpY2VzLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgaWYgKGlkeCA8IDApIHtcbiAgICAgICAgaWR4ID0gaWR4ICsgdW5pZm9ybXMuYXhpc0RpbUxpbWl0O1xuICAgICAgfVxuICAgICAgdmFyIGlucHV0SW5kaWNlcyA9ICR7aW5wdXQudHlwZS5pbmRpY2VzfShvdXRwdXRJbmRpY2VzKTtcbiAgICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRJbmRpY2VzJywgJ3VuaWZvcm1zLmF4aXMnLCAndTMyKGlkeCknKX07XG4gICAgICBsZXQgdmFsdWUgPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRJbmRpY2VzJyl9O1xuXG4gICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZScpfTtcbiAgfWA7XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnR2F0aGVyRWxlbWVudHMnLFxuICAgIHNoYWRlckNhY2hlOiB7IGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdhdGhlckVsZW1lbnRzQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEdhdGhlckVsZW1lbnRzQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBheGlzOiBhdHRyaWJ1dGVzLmF4aXMgYXMgbnVtYmVyIH0pO1xuXG5leHBvcnQgY29uc3QgZ2F0aGVyRWxlbWVudHMgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEdhdGhlckVsZW1lbnRzQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBpbnB1dHMgPSBjb250ZXh0LmlucHV0cztcbiAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUdhdGhlckVsZW1lbnRzUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IEdlbW1VdGlsLCBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIEluZGljZXNIZWxwZXIsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBpcyBtaXNzaW5nJyk7XG4gIH1cbiAgaWYgKGlucHV0cy5sZW5ndGggPCAyIHx8IGlucHV0cy5sZW5ndGggPiAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhaWQgaW5wdXQgbnVtYmVyLicpO1xuICB9XG5cbiAgLy8gJ0MnIGNhbiBiZSBvZiBkaW1lbnNpb25hbGl0eSAwLCAxIG9yIDIgb25seVxuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMl0uZGltcy5sZW5ndGggPiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHNoYXBlIG9mIEMnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGF0YVR5cGUgIT09IGlucHV0c1sxXS5kYXRhVHlwZSB8fCAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMF0uZGF0YVR5cGUgIT09IGlucHV0c1syXS5kYXRhVHlwZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IHR5cGVzIGFyZSBtaXNtYXRjaGVkJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2VtbUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICB0cmFuc0E6IGJvb2xlYW47XG4gIHRyYW5zQjogYm9vbGVhbjtcbiAgYWxwaGE6IG51bWJlcjtcbiAgYmV0YTogbnVtYmVyO1xufVxuXG5jb25zdCBjcmVhdGVHZW1tUHJvZ3JhbUluZm8gPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IEdlbW1BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBhU2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICBjb25zdCBiU2hhcGUgPSBpbnB1dHNbMV0uZGltcy5zbGljZSgpO1xuICBjb25zdCBbTSwgTiwgS10gPSBHZW1tVXRpbC5nZXRTaGFwZU9mR2VtbVJlc3VsdChcbiAgICBhU2hhcGUsXG4gICAgYXR0cmlidXRlcy50cmFuc0EsXG4gICAgYlNoYXBlLFxuICAgIGF0dHJpYnV0ZXMudHJhbnNCLFxuICAgIGlucHV0cy5sZW5ndGggPT09IDMgPyBpbnB1dHNbMl0uZGltcyA6IHVuZGVmaW5lZCxcbiAgKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbTSwgTl07XG4gIGlmICghb3V0cHV0U2hhcGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4ndCB1c2UgZ2VtbSBvbiB0aGUgZ2l2ZW4gdGVuc29yc1wiKTtcbiAgfVxuICBjb25zdCB0aWxlU2l6ZSA9IDE2O1xuICBjb25zdCBudW1UaWxlTiA9IE1hdGguY2VpbChOIC8gdGlsZVNpemUpO1xuICBjb25zdCBudW1UaWxlTSA9IE1hdGguY2VpbChNIC8gdGlsZVNpemUpO1xuICAvLyBUT0RPOiBGaW5kIHRoZSBjb25kaXRpb24gd2hlbiB0byB1c2UgdGhlIG5haXZlIG9uZS5cbiAgY29uc3QgdXNlU2hhcmVkID0gdHJ1ZTtcblxuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHVzZVNoYXJlZCA/IG51bVRpbGVOIDogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBNIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE4gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogSyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMuYWxwaGEgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhdHRyaWJ1dGVzLmJldGEgfSxcbiAgXTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnLCAndHlwZSddO1xuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMykge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1syXS5kaW1zKSk7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgncmFuaycpO1xuICB9XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgbGV0IGxpbmUgPSAnJztcbiAgICBpZiAoYXR0cmlidXRlcy50cmFuc0EgJiYgYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgIGxpbmUgPSAndmFsdWUgKz0gYVtrICogdW5pZm9ybXMuTSArIG1dICogYltuICogdW5pZm9ybXMuSyArIGtdOyc7XG4gICAgfSBlbHNlIGlmIChhdHRyaWJ1dGVzLnRyYW5zQSAmJiAhYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgIGxpbmUgPSAndmFsdWUgKz0gYVtrICogdW5pZm9ybXMuTSArIG1dICogYltrICogdW5pZm9ybXMuTiArIG5dOyc7XG4gICAgfSBlbHNlIGlmICghYXR0cmlidXRlcy50cmFuc0EgJiYgYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgIGxpbmUgPSAndmFsdWUgKz0gYVttICogdW5pZm9ybXMuSyArIGtdICogYltuICogdW5pZm9ybXMuSyArIGtdOyc7XG4gICAgfSBlbHNlIGlmICghYXR0cmlidXRlcy50cmFuc0EgJiYgIWF0dHJpYnV0ZXMudHJhbnNCKSB7XG4gICAgICBsaW5lID0gJ3ZhbHVlICs9IGFbbSAqIHVuaWZvcm1zLksgKyBrXSAqIGJbayAqIHVuaWZvcm1zLk4gKyBuXTsnO1xuICAgIH1cblxuICAgIGNvbnN0IGNhbGN1bGF0ZUFscGhhID0gYXR0cmlidXRlcy5hbHBoYSA9PT0gMSA/ICcnIDogJ3ZhbHVlICo9IHVuaWZvcm1zLmFscGhhOyc7XG4gICAgY29uc3QgYSA9IGlucHV0VmFyaWFibGUoJ2EnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zKTtcbiAgICBjb25zdCBiID0gaW5wdXRWYXJpYWJsZSgnYicsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMpO1xuICAgIGNvbnN0IGRhdGFUeXBlID0gYS50eXBlLnZhbHVlO1xuICAgIGxldCBjOiBJbmRpY2VzSGVscGVyIHwgbnVsbCA9IG51bGw7XG4gICAgY29uc3QgdmFyaWFibGVzID0gW2EsIGJdO1xuICAgIGlmIChpbnB1dHMubGVuZ3RoID09PSAzKSB7XG4gICAgICBjID0gaW5wdXRWYXJpYWJsZSgnYycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoKTtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKGMpO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICAgIHZhcmlhYmxlcy5wdXNoKG91dHB1dCk7XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnTScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdOJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ0snLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnYWxwaGEnLCB0eXBlOiAnZjMyJyB9LFxuICAgICAgeyBuYW1lOiAnYmV0YScsIHR5cGU6ICdmMzInIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLnZhcmlhYmxlcyl9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cblxuICAgIGxldCBtID0gZ2xvYmFsX2lkeCAvIHVuaWZvcm1zLk47XG4gICAgbGV0IG4gPSBnbG9iYWxfaWR4ICUgdW5pZm9ybXMuTjtcblxuICAgIHZhciB2YWx1ZSA9ICR7ZGF0YVR5cGV9KDApO1xuICAgIGZvciAodmFyIGs6IHUzMiA9IDB1OyBrIDwgdW5pZm9ybXMuSzsgaysrKSB7XG4gICAgICAke2xpbmV9XG4gICAgfVxuXG4gICAgJHtjYWxjdWxhdGVBbHBoYX1cbiAgICAkeygoKSA9PiB7XG4gICAgICBpZiAoYyAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBgbGV0IGNPZmZzZXQgPSAke2MuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoJ3ZlYzIobSwgbiknLCBvdXRwdXQpfTsgdmFsdWUgKz0gJHtcbiAgICAgICAgICBkYXRhVHlwZVxuICAgICAgICB9KHVuaWZvcm1zLmJldGEpICogJHtjLmdldEJ5T2Zmc2V0KCdjT2Zmc2V0Jyl9O2A7XG4gICAgICB9XG4gICAgICByZXR1cm4gJyc7XG4gICAgfSkoKX1cbiAgICBvdXRwdXRbZ2xvYmFsX2lkeF0gPSB2YWx1ZTtcbiAgfWA7XG4gIH07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlU2hhcmVkID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgYSA9IGlucHV0VmFyaWFibGUoJ2EnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zKTtcbiAgICBjb25zdCBiID0gaW5wdXRWYXJpYWJsZSgnYicsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMpO1xuICAgIGxldCBjOiBJbmRpY2VzSGVscGVyIHwgbnVsbCA9IG51bGw7XG4gICAgY29uc3QgdmFyaWFibGVzID0gW2EsIGJdO1xuICAgIGlmIChpbnB1dHMubGVuZ3RoID09PSAzKSB7XG4gICAgICBjID0gaW5wdXRWYXJpYWJsZSgnYycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoKTtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKGMpO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICAgIHZhcmlhYmxlcy5wdXNoKG91dHB1dCk7XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnbnVtX3RpbGVfbicsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdNJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ04nLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnSycsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdhbHBoYScsIHR5cGU6ICdmMzInIH0sXG4gICAgICB7IG5hbWU6ICdiZXRhJywgdHlwZTogJ2YzMicgfSxcbiAgICBdO1xuXG4gICAgbGV0IGNhbGNSZXN1bHQgPSAnJztcbiAgICBsZXQgZmlsbFdvcmtncm91cE1lbW9yeSA9ICcnO1xuICAgIGlmIChhdHRyaWJ1dGVzLnRyYW5zQSAmJiBhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgZmlsbFdvcmtncm91cE1lbW9yeSA9IGBcbiAgICAgIHZhciBjb2wgPSB0aWxlX3Jvd19zdGFydCArIGxvY2FsX2lkLng7XG4gICAgICB2YXIgcm93ID0ga19zdGFydCArIGxvY2FsX2lkLnk7XG4gICAgICBpZiAoY29sIDwgdW5pZm9ybXMuTSAmJiByb3cgPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHRpbGVfYVtsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9IGFbcm93ICogdW5pZm9ybXMuTSArIGNvbF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aWxlX2FbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSAke2EudHlwZS52YWx1ZX0oMCk7XG4gICAgICB9XG5cbiAgICAgIGNvbCA9IGtfc3RhcnQgKyBsb2NhbF9pZC54O1xuICAgICAgcm93ID0gdGlsZV9jb2xfc3RhcnQgKyBsb2NhbF9pZC55O1xuICAgICAgaWYgKGNvbCA8IHVuaWZvcm1zLksgJiYgcm93IDwgdW5pZm9ybXMuTikge1xuICAgICAgICB0aWxlX2JbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSBiW3JvdyAqIHVuaWZvcm1zLksgKyBjb2xdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGlsZV9iW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gJHtiLnR5cGUudmFsdWV9KDApO1xuICAgICAgfVxuICAgICAgYDtcbiAgICAgIGNhbGNSZXN1bHQgPSBgdmFsdWUgKz0gdGlsZV9hW2tdW2xvY2FsX2lkLnldICogdGlsZV9iW2xvY2FsX2lkLnhdW2tdO2A7XG4gICAgfSBlbHNlIGlmIChhdHRyaWJ1dGVzLnRyYW5zQSAmJiAhYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgIGZpbGxXb3JrZ3JvdXBNZW1vcnkgPSBgXG4gICAgICB2YXIgY29sID0gdGlsZV9yb3dfc3RhcnQgKyBsb2NhbF9pZC54O1xuICAgICAgdmFyIHJvdyA9IGtfc3RhcnQgKyBsb2NhbF9pZC55O1xuICAgICAgaWYgKGNvbCA8IHVuaWZvcm1zLk0gJiYgcm93IDwgdW5pZm9ybXMuSykge1xuICAgICAgICB0aWxlX2FbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSBhW3JvdyAqIHVuaWZvcm1zLk0gKyBjb2xdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGlsZV9hW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gJHthLnR5cGUudmFsdWV9KDApO1xuICAgICAgfVxuXG4gICAgICBjb2wgPSB0aWxlX2NvbF9zdGFydCArIGxvY2FsX2lkLng7XG4gICAgICByb3cgPSBrX3N0YXJ0ICsgbG9jYWxfaWQueTtcbiAgICAgIGlmIChjb2wgPCB1bmlmb3Jtcy5OICYmIHJvdyA8IHVuaWZvcm1zLkspIHtcbiAgICAgICAgdGlsZV9iW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gYltyb3cgKiB1bmlmb3Jtcy5OICsgY29sXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbGVfYltsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9ICR7Yi50eXBlLnZhbHVlfSgwKTtcbiAgICAgIH1cbiAgICAgIGA7XG4gICAgICBjYWxjUmVzdWx0ID0gYHZhbHVlICs9IHRpbGVfYVtrXVtsb2NhbF9pZC55XSAqIHRpbGVfYltrXVtsb2NhbF9pZC54XTtgO1xuICAgIH0gZWxzZSBpZiAoIWF0dHJpYnV0ZXMudHJhbnNBICYmIGF0dHJpYnV0ZXMudHJhbnNCKSB7XG4gICAgICBmaWxsV29ya2dyb3VwTWVtb3J5ID0gYFxuICAgICAgdmFyIGNvbCA9IGtfc3RhcnQgKyBsb2NhbF9pZC54O1xuICAgICAgdmFyIHJvdyA9IHRpbGVfcm93X3N0YXJ0ICsgbG9jYWxfaWQueTtcbiAgICAgIGlmIChjb2wgPCB1bmlmb3Jtcy5LICYmIHJvdyA8IHVuaWZvcm1zLk0pIHtcbiAgICAgICAgdGlsZV9hW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gYVtyb3cgKiB1bmlmb3Jtcy5LICsgY29sXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbGVfYVtsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9ICR7YS50eXBlLnZhbHVlfSgwKTtcbiAgICAgIH1cblxuICAgICAgY29sID0ga19zdGFydCArIGxvY2FsX2lkLng7XG4gICAgICByb3cgPSB0aWxlX2NvbF9zdGFydCArIGxvY2FsX2lkLnk7XG4gICAgICBpZiAoY29sIDwgdW5pZm9ybXMuSyAmJiByb3cgPCB1bmlmb3Jtcy5OKSB7XG4gICAgICAgIHRpbGVfYltsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9IGJbcm93ICogdW5pZm9ybXMuSyArIGNvbF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aWxlX2JbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSAke2IudHlwZS52YWx1ZX0oMCk7XG4gICAgICB9XG4gICAgICBgO1xuICAgICAgY2FsY1Jlc3VsdCA9IGB2YWx1ZSArPSB0aWxlX2FbbG9jYWxfaWQueV1ba10gKiB0aWxlX2JbbG9jYWxfaWQueF1ba107YDtcbiAgICB9IGVsc2UgaWYgKCFhdHRyaWJ1dGVzLnRyYW5zQSAmJiAhYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgIGZpbGxXb3JrZ3JvdXBNZW1vcnkgPSBgXG4gICAgICB2YXIgY29sID0ga19zdGFydCArIGxvY2FsX2lkLng7XG4gICAgICB2YXIgcm93ID0gdGlsZV9yb3dfc3RhcnQgKyBsb2NhbF9pZC55O1xuICAgICAgaWYgKGNvbCA8IHVuaWZvcm1zLksgJiYgcm93IDwgdW5pZm9ybXMuTSkge1xuICAgICAgICB0aWxlX2FbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSBhW3JvdyAqIHVuaWZvcm1zLksgKyBjb2xdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGlsZV9hW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gJHthLnR5cGUudmFsdWV9KDApO1xuICAgICAgfVxuXG4gICAgICBjb2wgPSB0aWxlX2NvbF9zdGFydCArIGxvY2FsX2lkLng7XG4gICAgICByb3cgPSBrX3N0YXJ0ICsgbG9jYWxfaWQueTtcbiAgICAgIGlmIChjb2wgPCB1bmlmb3Jtcy5OICYmIHJvdyA8IHVuaWZvcm1zLkspIHtcbiAgICAgICAgdGlsZV9iW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gYltyb3cgKiB1bmlmb3Jtcy5OICsgY29sXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbGVfYltsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9ICR7Yi50eXBlLnZhbHVlfSgwKTtcbiAgICAgIH1cbiAgICAgIGA7XG4gICAgICBjYWxjUmVzdWx0ID0gYHZhbHVlICs9IHRpbGVfYVtsb2NhbF9pZC55XVtrXSAqIHRpbGVfYltrXVtsb2NhbF9pZC54XTtgO1xuICAgIH1cblxuICAgIGNvbnN0IGNhbGN1bGF0ZUFscGhhID0gYXR0cmlidXRlcy5hbHBoYSA9PT0gMSA/ICcnIDogJ3ZhbHVlICo9IHVuaWZvcm1zLmFscGhhOyc7XG5cbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLnZhcmlhYmxlcyl9XG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGVfYTogYXJyYXk8YXJyYXk8JHthLnR5cGUuc3RvcmFnZX0sICR7dGlsZVNpemV9PiwgJHt0aWxlU2l6ZX0+O1xuICB2YXI8d29ya2dyb3VwPiB0aWxlX2I6IGFycmF5PGFycmF5PCR7Yi50eXBlLnN0b3JhZ2V9LCAke3RpbGVTaXplfT4sICR7dGlsZVNpemV9PjtcbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFt0aWxlU2l6ZSwgdGlsZVNpemUsIDFdKX1cbiAgICBsZXQgdGlsZV9jb2xfc3RhcnQgPSAod29ya2dyb3VwX2luZGV4ICUgdW5pZm9ybXMubnVtX3RpbGVfbikgKiAke3RpbGVTaXplfTtcbiAgICBsZXQgdGlsZV9yb3dfc3RhcnQgPSAod29ya2dyb3VwX2luZGV4IC8gdW5pZm9ybXMubnVtX3RpbGVfbikgKiAke3RpbGVTaXplfTtcbiAgICBsZXQgbnVtX3RpbGVzID0gKHVuaWZvcm1zLksgLSAxKSAvICR7dGlsZVNpemV9ICsgMTtcbiAgICB2YXIga19zdGFydCA9IDB1O1xuICAgIHZhciB2YWx1ZSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KDApO1xuICAgIGZvciAodmFyIHQ6IHUzMiA9IDB1OyB0IDwgbnVtX3RpbGVzOyB0KyspIHtcbiAgICAgICR7ZmlsbFdvcmtncm91cE1lbW9yeX1cbiAgICAgIGtfc3RhcnQgPSBrX3N0YXJ0ICsgJHt0aWxlU2l6ZX07XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgIGZvciAodmFyIGs6IHUzMiA9IDB1OyBrIDwgJHt0aWxlU2l6ZX07IGsrKykge1xuICAgICAgICAke2NhbGNSZXN1bHR9XG4gICAgICB9XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgfVxuXG4gICAgJHtjYWxjdWxhdGVBbHBoYX1cbiAgICBsZXQgbSA9IHRpbGVfcm93X3N0YXJ0ICsgbG9jYWxfaWQueTtcbiAgICBsZXQgbiA9IHRpbGVfY29sX3N0YXJ0ICsgbG9jYWxfaWQueDtcbiAgICAkeygoKSA9PiB7XG4gICAgICBpZiAoYyAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBgbGV0IGNPZmZzZXQgPSAke2MuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoJ3ZlYzIobSwgbiknLCBvdXRwdXQpfTsgdmFsdWUgKz0gJHtcbiAgICAgICAgICBvdXRwdXQudHlwZS52YWx1ZVxuICAgICAgICB9KHVuaWZvcm1zLmJldGEpICogJHtjLmdldEJ5T2Zmc2V0KCdjT2Zmc2V0Jyl9O2A7XG4gICAgICB9XG4gICAgICByZXR1cm4gJyc7XG4gICAgfSkoKX1cbiAgICBpZiAobSA8IHVuaWZvcm1zLk0gJiYgbiA8IHVuaWZvcm1zLk4pIHtcbiAgICAgIG91dHB1dFttICogdW5pZm9ybXMuTiArIG5dID0gdmFsdWU7XG4gICAgfVxuICB9YDtcbiAgfTtcblxuICBpZiAodXNlU2hhcmVkKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6ICdHZW1tU2hhcmVkJyxcbiAgICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IG51bVRpbGVOICogbnVtVGlsZU0gfSxcbiAgICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgICAgfSksXG4gICAgICBnZXRTaGFkZXJTb3VyY2U6IGdldFNoYWRlclNvdXJjZVNoYXJlZCxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnR2VtbScsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX1gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VHZW1tQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEdlbW1BdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgdHJhbnNBID0gYXR0cmlidXRlcy50cmFuc0EgYXMgYm9vbGVhbjtcbiAgY29uc3QgdHJhbnNCID0gYXR0cmlidXRlcy50cmFuc0IgYXMgYm9vbGVhbjtcbiAgY29uc3QgYWxwaGEgPSBhdHRyaWJ1dGVzLmFscGhhIGFzIG51bWJlcjtcbiAgY29uc3QgYmV0YSA9IGF0dHJpYnV0ZXMuYmV0YSBhcyBudW1iZXI7XG4gIHJldHVybiB7XG4gICAgdHJhbnNBLFxuICAgIHRyYW5zQixcbiAgICBhbHBoYSxcbiAgICBiZXRhLFxuICAgIGNhY2hlS2V5OiBgJHthdHRyaWJ1dGVzLnRyYW5zQX07JHthdHRyaWJ1dGVzLnRyYW5zQn07JHthdHRyaWJ1dGVzLmFscGhhID09PSAxfWAsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgZ2VtbSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogR2VtbUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlR2VtbVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBJbmRpY2VzSGVscGVyLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5sZXQgW2lkeE4sIGlkeEMsIGlkeEgsIGlkeFddID0gWzAsIDEsIDIsIDNdOyAvLyBOQ0hXXG50eXBlIE1vZGUgPSAnYmlsaW5lYXInIHwgJ25lYXJlc3QnIHwgJ2JpY3ViaWMnO1xudHlwZSBQYWRkaW5nTW9kZSA9ICd6ZXJvcycgfCAnYm9yZGVyJyB8ICdyZWZsZWN0aW9uJztcbnR5cGUgRm9ybWF0ID0gJ05IV0MnIHwgJ05DSFcnO1xuZXhwb3J0IGludGVyZmFjZSBHcmlkU2FtcGVBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgYWxpZ25Db3JuZXJzOiBudW1iZXI7XG4gIG1vZGU6IE1vZGU7XG4gIHBhZGRpbmdNb2RlOiBQYWRkaW5nTW9kZTtcbiAgZm9ybWF0OiBGb3JtYXQ7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ29ubHkgNC1EIHRlbnNvciBpcyBzdXBwb3J0ZWQuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCBkaW1lbnNpb25zIG11c3QgYmUgZXF1YWwgdG8gZ3JpZCBkaW1lbnNpb25zJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMiAhPT0gaW5wdXRzWzFdLmRpbXNbaW5wdXRzWzFdLmRpbXMubGVuZ3RoIC0gMV0pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYGxhc3QgZGltZW5zaW9uIG9mIGdyaWQgbXVzdCBiZSBlcXVhbCB0byAke2lucHV0c1swXS5kaW1zLmxlbmd0aCAtIDJ9YCk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXNbMF0gIT09IGlucHV0c1sxXS5kaW1zWzBdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdncmlkIGJhdGNoIHNpemUgbXVzdCBtYXRjaCBpbnB1dCBiYXRjaCBzaXplJyk7XG4gIH1cbn07XG5cbmNvbnN0IGdzR2V0Q3ViaWNDb2VmZnMgPSBgXG4gIGZuIGdzX2dldF9jdWJpY19jb2VmZnMoeDogZjMyKSAtPiB2ZWM0PGYzMj4ge1xuICAgIGxldCBjdWJpY19hbHBoYSA9IC0wLjc1ZjtcbiAgICBsZXQgeF9hYnMgPSBhYnMoeCk7XG4gICAgdmFyIGNvZWZmczogdmVjNDxmMzI+O1xuICAgIGNvZWZmc1swXSA9ICgoKGN1YmljX2FscGhhICogKHhfYWJzICsgMSkgLSA1ICogY3ViaWNfYWxwaGEpICogKHhfYWJzICsgMSkgKyA4ICogY3ViaWNfYWxwaGEpICogKHhfYWJzICsgMSkgLSA0ICogY3ViaWNfYWxwaGEpO1xuICAgIGNvZWZmc1sxXSA9ICgoKGN1YmljX2FscGhhICsgMikgKiB4X2FicyAtIChjdWJpY19hbHBoYSArIDMpKSAqIHhfYWJzICogeF9hYnMgKyAxKTtcbiAgICBjb2VmZnNbMl0gPSAoKChjdWJpY19hbHBoYSArIDIpICogKDEgLSB4X2FicykgLSAoY3ViaWNfYWxwaGEgKyAzKSkgKiAoMSAtIHhfYWJzKSAqICgxIC0geF9hYnMpICsgMSk7XG4gICAgY29lZmZzWzNdID0gKCgoY3ViaWNfYWxwaGEgKiAoMiAtIHhfYWJzKSAtIDUgKiBjdWJpY19hbHBoYSkgKiAoMiAtIHhfYWJzKSArIDggKiBjdWJpY19hbHBoYSkgKiAoMiAtIHhfYWJzKSAtIDQgKiBjdWJpY19hbHBoYSk7XG4gICAgcmV0dXJuIGNvZWZmcztcbiAgfVxuYDtcblxuY29uc3QgZ3NCaWN1YmljSW50ZXJwb2xhdGUgPSAoZGF0YVR5cGU6IHN0cmluZyk6IHN0cmluZyA9PiBgXG4gIGZuIGdzX2JpY3ViaWNfaW50ZXJwb2xhdGUocDogbWF0NHg0PCR7ZGF0YVR5cGV9PiwgeDogZjMyLCB5OiBmMzIpIC0+ICR7ZGF0YVR5cGV9IHtcbiAgICB2YXIgdjogdmVjNDxmMzI+O1xuICAgIHZhciBjb2VmZnMgPSBnc19nZXRfY3ViaWNfY29lZmZzKHgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNDsgaSsrKSB7XG4gICAgICB2W2ldID0gY29lZmZzWzBdICogcFtpXVswXSArIGNvZWZmc1sxXSAqIHBbaV1bMV0gKyBjb2VmZnNbMl0gKiBwW2ldWzJdICsgY29lZmZzWzNdICogcFtpXVszXTtcbiAgICB9XG4gICAgY29lZmZzID0gZ3NfZ2V0X2N1YmljX2NvZWZmcyh5KTtcbiAgICBsZXQgcGl4ZWwgPSAke2RhdGFUeXBlfShjb2VmZnNbMF0gKiB2WzBdICsgY29lZmZzWzFdICogdlsxXSArIGNvZWZmc1syXSAqIHZbMl0gKyBjb2VmZnNbM10gKiB2WzNdKTtcbiAgICByZXR1cm4gcGl4ZWw7XG4gIH1cbmA7XG5cbmNvbnN0IGdzRGVub3JtYWxpemUgPSAoYXR0cmlidXRlczogR3JpZFNhbXBlQXR0cmlidXRlcyk6IHN0cmluZyA9PiBgXG4gIGZuIGdzX2Rlbm9ybWFsaXplKG46IGYzMiwgbGVuZ3RoOiBpMzIpIC0+IGYzMiB7XG4gICAgJHtcbiAgICAgIGF0dHJpYnV0ZXMuYWxpZ25Db3JuZXJzID09PSAwXG4gICAgICAgID8gYFxuICAgIC8vIGFsaWduQ29ybmVyczogZmFsc2UgPT4gWy0xLCAxXSB0byBbLTAuNSwgbGVuZ3RoIC0gMC41XVxuICAgIHJldHVybiAoKG4gKyAxLjApICogZjMyKGxlbmd0aCkgLSAxLjApIC8gMi4wO1xuICAgIGBcbiAgICAgICAgOiBgXG4gICAgLy8gYWxpZ25Db3JuZXJzOiB0cnVlID0+IFstMSwgMV0gdG8gWzAsIGxlbmd0aCAtIDFdXG4gICAgcmV0dXJuIChuICsgMS4wKSAvIDIuMCAqIChmMzIobGVuZ3RoIC0gMSkpO1xuICAgIGBcbiAgICB9XG4gIH1cbmA7XG5cbmNvbnN0IGdzUmVmbGVjdCA9IChhdHRyaWJ1dGVzOiBHcmlkU2FtcGVBdHRyaWJ1dGVzKTogc3RyaW5nID0+IGBcbiAgJHtcbiAgICBhdHRyaWJ1dGVzLnBhZGRpbmdNb2RlID09PSAncmVmbGVjdGlvbidcbiAgICAgID8gYFxuICAgICAgZm4gZ3NfcmVmbGVjdCh4OiBpMzIsIHhfbWluOiBmMzIsIHhfbWF4OiBmMzIpIC0+IHUzMiB7XG4gICAgICAgIHZhciBkeCA9IDAuMDtcbiAgICAgICAgdmFyIGZ4ID0gZjMyKHgpO1xuICAgICAgICBsZXQgcmFuZ2UgPSB4X21heCAtIHhfbWluO1xuICAgICAgICBpZiAoZnggPCB4X21pbikge1xuICAgICAgICAgIGR4ID0geF9taW4gLSBmeDtcbiAgICAgICAgICBsZXQgbiA9IHUzMihkeCAvIHJhbmdlKTtcbiAgICAgICAgICBsZXQgciA9IGR4IC0gZjMyKG4pICogcmFuZ2U7XG4gICAgICAgICAgaWYgKG4gJSAyID09IDApIHtcbiAgICAgICAgICAgIGZ4ID0geF9taW4gKyByO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmeCA9IHhfbWF4IC0gcjtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZnggPiB4X21heCkge1xuICAgICAgICAgIGR4ID0gZnggLSB4X21heDtcbiAgICAgICAgICBsZXQgbiA9IHUzMihkeCAvIHJhbmdlKTtcbiAgICAgICAgICBsZXQgciA9IGR4IC0gZjMyKG4pICogcmFuZ2U7XG4gICAgICAgICAgaWYgKG4gJSAyID09IDApIHtcbiAgICAgICAgICAgIGZ4ID0geF9tYXggLSByO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmeCA9IHhfbWluICsgcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHUzMihmeCk7XG4gICAgICB9YFxuICAgICAgOiAnJ1xuICB9XG5gO1xuXG5jb25zdCBwaXhlbEF0R3JpZCA9IChpbnB1dDogSW5kaWNlc0hlbHBlciwgZGF0YVR5cGU6IHN0cmluZywgYXR0cmlidXRlczogR3JpZFNhbXBlQXR0cmlidXRlcyk6IHN0cmluZyA9PlxuICBgXG4gIGZuIHBpeGVsX2F0X2dyaWQocjogaTMyLCBjOiBpMzIsIEg6IGkzMiwgVzogaTMyLCBiYXRjaDogdTMyLCBjaGFubmVsOiB1MzIsIGJvcmRlcjogdmVjNDxmMzI+KSAtPiAke2RhdGFUeXBlfSB7XG4gICAgIHZhciBwaXhlbCA9ICR7ZGF0YVR5cGV9KDApO1xuICAgICB2YXIgaW5kaWNlcyA9IHZlYzQ8dTMyPigwKTtcbiAgICAgaW5kaWNlc1ske2lkeE59XSA9IGJhdGNoO1xuICAgICBpbmRpY2VzWyR7aWR4Q31dID0gY2hhbm5lbDtgICtcbiAgKCgpID0+IHtcbiAgICBzd2l0Y2ggKGF0dHJpYnV0ZXMucGFkZGluZ01vZGUpIHtcbiAgICAgIGNhc2UgJ3plcm9zJzpcbiAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBpZiAociA+PSAwICYmIHIgPCBIICYmIGMgPj0wICYmIGMgPCBXKSB7XG4gICAgICAgICAgICBpbmRpY2VzWyR7aWR4SH1dID0gdTMyKHIpO1xuICAgICAgICAgICAgaW5kaWNlc1ske2lkeFd9XSA9IHUzMihjKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICR7ZGF0YVR5cGV9KDApO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIGNhc2UgJ2JvcmRlcic6XG4gICAgICAgIHJldHVybiBgXG4gICAgICAgICAgaW5kaWNlc1ske2lkeEh9XSA9IHUzMihjbGFtcChyLCAwLCBIIC0gMSkpO1xuICAgICAgICAgIGluZGljZXNbJHtpZHhXfV0gPSB1MzIoY2xhbXAoYywgMCwgVyAtIDEpKTtcbiAgICAgICAgYDtcbiAgICAgIGNhc2UgJ3JlZmxlY3Rpb24nOlxuICAgICAgICByZXR1cm4gYFxuICAgICAgICAgIGluZGljZXNbJHtpZHhIfV0gPSBnc19yZWZsZWN0KHIsIGJvcmRlclsxXSwgYm9yZGVyWzNdKTtcbiAgICAgICAgICBpbmRpY2VzWyR7aWR4V31dID0gZ3NfcmVmbGVjdChjLCBib3JkZXJbMF0sIGJvcmRlclsyXSk7XG4gICAgICAgIGA7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHBhZGRpbmcgbW9kZSAke2F0dHJpYnV0ZXMucGFkZGluZ01vZGV9IGlzIG5vdCBzdXBwb3J0ZWRgKTtcbiAgICB9XG4gIH0pKCkgK1xuICBgXG4gICAgcmV0dXJuICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbmRpY2VzJyl9O1xuICB9XG5gO1xuXG5jb25zdCBjb21wdXRlUGl4ZWwgPSAob3V0cHV0OiBJbmRpY2VzSGVscGVyLCBkYXRhVHlwZTogc3RyaW5nLCBhdHRyaWJ1dGVzOiBHcmlkU2FtcGVBdHRyaWJ1dGVzKTogc3RyaW5nID0+XG4gICgoKSA9PiB7XG4gICAgc3dpdGNoIChhdHRyaWJ1dGVzLm1vZGUpIHtcbiAgICAgIGNhc2UgJ25lYXJlc3QnOlxuICAgICAgICByZXR1cm4gYFxuICAgICAgICAgIGxldCByZXN1bHQgPSBwaXhlbF9hdF9ncmlkKGkzMihyb3VuZCh5KSksIGkzMihyb3VuZCh4KSksIEhfaW4sIFdfaW4sIGluZGljZXNbJHtpZHhOfV0sIGluZGljZXNbJHtpZHhDfV0sIGJvcmRlcik7XG4gICAgICAgIGA7XG4gICAgICBjYXNlICdiaWxpbmVhcic6XG4gICAgICAgIHJldHVybiBgXG4gICAgICAgICAgbGV0IHgxID0gaTMyKGZsb29yKHgpKTtcbiAgICAgICAgICBsZXQgeTEgPSBpMzIoZmxvb3IoeSkpO1xuICAgICAgICAgIGxldCB4MiA9IHgxICsgMTtcbiAgICAgICAgICBsZXQgeTIgPSB5MSArIDE7XG5cbiAgICAgICAgICBsZXQgcDExID0gcGl4ZWxfYXRfZ3JpZCh5MSwgeDEsIEhfaW4sIFdfaW4sIGluZGljZXNbJHtpZHhOfV0sIGluZGljZXNbJHtpZHhDfV0sIGJvcmRlcik7XG4gICAgICAgICAgbGV0IHAxMiA9IHBpeGVsX2F0X2dyaWQoeTEsIHgyLCBIX2luLCBXX2luLCBpbmRpY2VzWyR7aWR4Tn1dLCBpbmRpY2VzWyR7aWR4Q31dLCBib3JkZXIpO1xuICAgICAgICAgIGxldCBwMjEgPSBwaXhlbF9hdF9ncmlkKHkyLCB4MSwgSF9pbiwgV19pbiwgaW5kaWNlc1ske2lkeE59XSwgaW5kaWNlc1ske2lkeEN9XSwgYm9yZGVyKTtcbiAgICAgICAgICBsZXQgcDIyID0gcGl4ZWxfYXRfZ3JpZCh5MiwgeDIsIEhfaW4sIFdfaW4sIGluZGljZXNbJHtpZHhOfV0sIGluZGljZXNbJHtpZHhDfV0sIGJvcmRlcik7XG5cbiAgICAgICAgICBsZXQgZHgyID0gJHtkYXRhVHlwZX0oZjMyKHgyKSAtIHgpO1xuICAgICAgICAgIGxldCBkeDEgPSAke2RhdGFUeXBlfSh4IC0gZjMyKHgxKSk7XG4gICAgICAgICAgbGV0IGR5MiA9ICR7ZGF0YVR5cGV9KGYzMih5MikgLSB5KTtcbiAgICAgICAgICBsZXQgZHkxID0gJHtkYXRhVHlwZX0oeSAtIGYzMih5MSkpO1xuICAgICAgICAgIGxldCByZXN1bHQgPSBkeTIgKiAoZHgyICogcDExICsgZHgxICogcDEyKSArIGR5MSAqIChkeDIgKiBwMjEgKyBkeDEgKiBwMjIpO1xuICAgICAgICBgO1xuICAgICAgY2FzZSAnYmljdWJpYyc6XG4gICAgICAgIHJldHVybiBgXG4gICAgICAgICAgbGV0IHgwID0gaTMyKGZsb29yKHgpKSAtIDE7XG4gICAgICAgICAgbGV0IHkwID0gaTMyKGZsb29yKHkpKSAtIDE7XG4gICAgICAgICAgdmFyIHA6IG1hdDR4NDwke2RhdGFUeXBlfT47XG4gICAgICAgICAgZm9yICh2YXIgaCA9IDA7IGggPCA0OyBoKyspIHtcbiAgICAgICAgICAgIGZvciAodmFyIHcgPSAwOyB3IDwgNDsgdysrKSB7XG4gICAgICAgICAgICAgIHBbaF1bd10gPSBwaXhlbF9hdF9ncmlkKGggKyB5MCwgdyArIHgwLCBIX2luLCBXX2luLCBpbmRpY2VzWyR7aWR4Tn1dLCBpbmRpY2VzWyR7aWR4Q31dLCBib3JkZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGxldCBkeCA9IHggLSBmMzIoeDAgKyAxKTtcbiAgICAgICAgICBsZXQgZHkgPSB5IC0gZjMyKHkwICsgMSk7XG4gICAgICAgICAgbGV0IHJlc3VsdCA9IGdzX2JpY3ViaWNfaW50ZXJwb2xhdGUocCwgZHgsIGR5KTtcbiAgICAgICAgYDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbW9kZSAke2F0dHJpYnV0ZXMubW9kZX0gaXMgbm90IHN1cHBvcnRlZGApO1xuICAgIH1cbiAgfSkoKSArIGAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICdyZXN1bHQnKX1gO1xuXG5jb25zdCBjcmVhdGVHcmlkU2FtcGxlUHJvZ3JhbUluZm8gPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IEdyaWRTYW1wZUF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgpO1xuICAvLyBkaXNjYXJkIGxhc3QgZGltZW5zaW9uIGZvciB1c2luZyB2ZWMyIHRvIGFjY2VzcyBncmlkIGRhdGFcbiAgY29uc3QgZ3JpZFNoYXBlID0gW2lucHV0c1sxXS5kaW1zWzBdLCBpbnB1dHNbMV0uZGltc1sxXSwgaW5wdXRzWzFdLmRpbXNbMl1dO1xuICBjb25zdCBncmlkID0gaW5wdXRWYXJpYWJsZSgnZ3JpZCcsIGlucHV0c1sxXS5kYXRhVHlwZSwgZ3JpZFNoYXBlLmxlbmd0aCwgMik7XG4gIGxldCBvdXRwdXRTaGFwZSA9IFtpbnB1dHNbMF0uZGltc1swXSwgaW5wdXRzWzBdLmRpbXNbMV0sIGlucHV0c1sxXS5kaW1zWzFdLCBpbnB1dHNbMV0uZGltc1syXV07XG4gIGlmIChhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnKSB7XG4gICAgb3V0cHV0U2hhcGUgPSBbaW5wdXRzWzBdLmRpbXNbMF0sIGlucHV0c1sxXS5kaW1zWzFdLCBpbnB1dHNbMV0uZGltc1syXSwgaW5wdXRzWzBdLmRpbXNbM11dO1xuICAgIFtpZHhOLCBpZHhDLCBpZHhILCBpZHhXXSA9IFswLCAzLCAxLCAyXTtcbiAgfVxuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICBjb25zdCBkYXRhVHlwZSA9IHgudHlwZS52YWx1ZTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgZ3JpZFNoYXBlLCBvdXRwdXRTaGFwZSksXG4gIF07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyh4LCBncmlkLCBvdXRwdXQpfVxuICAke2dzR2V0Q3ViaWNDb2VmZnN9XG4gICR7Z3NCaWN1YmljSW50ZXJwb2xhdGUoZGF0YVR5cGUpfVxuICAke2dzRGVub3JtYWxpemUoYXR0cmlidXRlcyl9XG4gICR7Z3NSZWZsZWN0KGF0dHJpYnV0ZXMpfVxuICAke3BpeGVsQXRHcmlkKHgsIGRhdGFUeXBlLCBhdHRyaWJ1dGVzKX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICAgICAgbGV0IEhfaW4gPSBpMzIodW5pZm9ybXMueF9zaGFwZVske2lkeEh9XSk7XG4gICAgICBsZXQgV19pbiA9IGkzMih1bmlmb3Jtcy54X3NoYXBlWyR7aWR4V31dKTtcblxuICAgICAgJHtcbiAgICAgICAgYXR0cmlidXRlcy5hbGlnbkNvcm5lcnMgPT09IDBcbiAgICAgICAgICA/IGBcbiAgICAgIGxldCB4X21pbiA9IC0wLjU7XG4gICAgICBsZXQgeF9tYXggPSBmMzIoV19pbikgLSAwLjU7XG4gICAgICBsZXQgeV9taW4gPSAtMC41O1xuICAgICAgbGV0IHlfbWF4ID0gZjMyKEhfaW4pIC0gMC41O1xuICAgICAgYFxuICAgICAgICAgIDogYFxuICAgICAgbGV0IHhfbWluID0gMC4wO1xuICAgICAgbGV0IHhfbWF4ID0gZjMyKFdfaW4pIC0gMS4wO1xuICAgICAgbGV0IHlfbWluID0gMC4wO1xuICAgICAgbGV0IHlfbWF4ID0gZjMyKEhfaW4pIC0gMS4wO1xuICAgICAgYFxuICAgICAgfTtcbiAgICAgIGxldCBib3JkZXIgPSB2ZWM0PGYzMj4oeF9taW4sIHlfbWluLCB4X21heCwgeV9tYXgpO1xuXG4gICAgICBsZXQgaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgIHZhciBncmlkX2luZGljZXMgPSB2ZWMzPHUzMj4oaW5kaWNlc1ske2lkeE59XSwgaW5kaWNlc1ske2lkeEh9XSwgaW5kaWNlc1ske2lkeFd9XSk7XG4gICAgICBsZXQgbnh5ID0gJHtncmlkLmdldEJ5SW5kaWNlcygnZ3JpZF9pbmRpY2VzJyl9O1xuICAgICAgdmFyIHggPSBnc19kZW5vcm1hbGl6ZShmMzIobnh5WzBdKSwgV19pbik7XG4gICAgICB2YXIgeSA9IGdzX2Rlbm9ybWFsaXplKGYzMihueHlbMV0pLCBIX2luKTtcblxuICAgICAgJHtjb21wdXRlUGl4ZWwob3V0cHV0LCBkYXRhVHlwZSwgYXR0cmlidXRlcyl9XG4gIH1gO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0dyaWRTYW1wbGUnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9YCwgaW5wdXREZXBlbmRlbmNpZXM6IFsndHlwZScsICd0eXBlJ10gfSxcbiAgICBnZXRSdW5EYXRhOiAoaW5wdXRzKSA9PiB7XG4gICAgICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgICAgfTtcbiAgICB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBncmlkU2FtcGxlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBHcmlkU2FtcGVBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUdyaWRTYW1wbGVQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR3JpZFNhbXBsZUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBHcmlkU2FtcGVBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7XG4gICAgYWxpZ25Db3JuZXJzOiBhdHRyaWJ1dGVzLmFsaWduX2Nvcm5lcnMgYXMgbnVtYmVyLFxuICAgIG1vZGU6IGF0dHJpYnV0ZXMubW9kZSBhcyBNb2RlLFxuICAgIHBhZGRpbmdNb2RlOiBhdHRyaWJ1dGVzLnBhZGRpbmdfbW9kZSBhcyBQYWRkaW5nTW9kZSxcbiAgICBmb3JtYXQ6IGF0dHJpYnV0ZXMuZm9ybWF0IGFzIEZvcm1hdCxcbiAgfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBHcHVEYXRhVHlwZSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGFwcGx5QXR0ZW50aW9uLFxuICBBdHRlbnRpb25BdHRycyxcbiAgQXR0ZW50aW9uTWFza1R5cGUsXG4gIEF0dGVudGlvblBhcmFtZXRlcnMsXG4gIEF0dGVudGlvblFrdkZvcm1hdCxcbn0gZnJvbSAnLi9hdHRlbnRpb24nO1xuaW1wb3J0IHsgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciwgVW5pZm9ybXNBcnJheVR5cGUgfSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQgeyBjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbywgVHJhbnNwb3NlQXR0cmlidXRlcyB9IGZyb20gJy4vdHJhbnNwb3NlJztcblxuY29uc3QgZ2V0SW5wdXQgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGk6IG51bWJlcikgPT5cbiAgaW5wdXRzLmxlbmd0aCA+IGkgJiYgaW5wdXRzW2ldLmRpbXMubGVuZ3RoID4gMCA/IGlucHV0c1tpXSA6IHVuZGVmaW5lZDtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IEF0dGVudGlvbkF0dHJzKTogQXR0ZW50aW9uUGFyYW1ldGVycyA9PiB7XG4gIGNvbnN0IHF1ZXJ5ID0gaW5wdXRzWzBdO1xuICBjb25zdCBrZXkgPSBnZXRJbnB1dChpbnB1dHMsIDEpO1xuICBjb25zdCB2YWx1ZSA9IGdldElucHV0KGlucHV0cywgMik7XG4gIGNvbnN0IGJpYXMgPSBnZXRJbnB1dChpbnB1dHMsIDMpO1xuICBjb25zdCBrZXlQYWRkaW5nTWFzayA9IGdldElucHV0KGlucHV0cywgNCk7XG4gIGNvbnN0IGF0dGVudGlvbkJpYXMgPSBnZXRJbnB1dChpbnB1dHMsIDUpO1xuICBjb25zdCBwYXN0S2V5ID0gZ2V0SW5wdXQoaW5wdXRzLCA2KTtcbiAgY29uc3QgcGFzdFZhbHVlID0gZ2V0SW5wdXQoaW5wdXRzLCA3KTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gTm90YXRpb25zOlxuICAvLyAgICBCOiBiYXRjaF9zaXplXG4gIC8vICAgIE46IG51bV9oZWFkc1xuICAvLyAgICBIOiBoZWFkX3NpemUgb2YgUSBhbmQgS1xuICAvLyAgICBIX3Y6IGhlYWRfc2l6ZSBvZiBWXG4gIC8vICAgIEQ6IGhpZGRlbl9zaXplIGZvciBRIGFuZCBLLCB3aGVyZSBEID0gTiAqIEhcbiAgLy8gICAgRF92OiBoaWRkZW5fc2l6ZSBvZiBWLCB3aGVyZSBEX3YgPSBOICogSF92XG4gIC8vICAgIFM6IHFfc2VxdWVuY2VfbGVuZ3RoXG4gIC8vICAgIFA6IHBhc3Rfc2VxdWVuY2VfbGVuZ3RoIG9mIGt2IGNhY2hlXG4gIC8vICAgIEw6IGt2X3NlcXVlbmNlX2xlbmd0aFxuICAvLyAgICBUOiB0b3RhbF9zZXF1ZW5jZV9sZW5ndGggPSBQICsgTFxuICAvLyAgICBNOiBtYXhfc2VxdWVuY2VfbGVuZ3RoIG9mIGt2IGNhY2hlIHdoZW4gcGFzdCBhbmQgcHJlc2VudCBzaGFyZSBidWZmZXJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIE11bHRpSGVhZEF0dGVudGlvbiBpbnB1dHM6XG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAgUV9LX1ZfQlNOSCAtIG5vIHBhY2tpbmc6XG4gIC8vICAgICBxdWVyeSAgICAgICAgICAgIChRKSAgICAgICA6IChCLCBTLCBEKVxuICAvLyAgICAga2V5ICAgICAgICAgICAgICAoSykgICAgICAgOiAoQiwgTCwgRClcbiAgLy8gICAgIHZhbHVlICAgICAgICAgICAgKFYpICAgICAgIDogKEIsIEwsIERfdilcbiAgLy8gIFFfS19WX0JTTkhfQk5TSF9CTlNIIC0gY3Jvc3MgYXR0ZW50aW9uIChrdiBjYWNoZSBpcyBub3QgdXNlZCwgTCA9PSBULCBEID09IERfdik6XG4gIC8vICAgICBxdWVyeSAgICAgICAgICAgIChRKSAgICAgICA6IChCLCBTLCBEKVxuICAvLyAgICAga2V5ICAgICAgICAgICAgICAoSykgICAgICAgOiAoQiwgTiwgTCwgSClcbiAgLy8gICAgIHZhbHVlICAgICAgICAgICAgKFYpICAgICAgIDogKEIsIE4sIEwsIEhfdilcbiAgLy8gIFFfS1ZfQlNOSF9CU04ySCAtIHBhY2tlZCBrdiAoa3YgY2FjaGUgaXMgbm90IHVzZWQsIGJpYXMgaXMgbm90IGFsbG93ZWQgZm9yIHBhY2tlZCBrdik6XG4gIC8vICAgICBxdWVyeSAgICAgICAgICAgIChRKSAgICAgICA6IChCLCBTLCBEKVxuICAvLyAgICAga2V5ICAgICAgICAgICAgICAoSy9WKSAgICAgOiAoQiwgTCwgTiwgMiwgSClcbiAgLy8gICAgIHZhbHVlICAgICAgICAgICAgICAgICAgICAgIDogTm9uZVxuICAvLyAgUUtWX0JTTjNIIC0gcGFja2VkIHFrdiAoa3YgY2FjaGUgaXMgbm90IHVzZWQsIFMgPT0gTCwgRCA9PSBEX3YpOlxuICAvLyAgICAgcXVlcnkgICAgICAgICAgICAoUS9LL1YpICAgOiAoQiwgUywgTiwgMywgSClcbiAgLy8gICAgIGtleSAgICAgICAgICAgICAgICAgICAgICAgIDogTm9uZVxuICAvLyAgICAgdmFsdWUgICAgICAgICAgICAgICAgICAgICAgOiBOb25lXG4gIC8vXG4gIC8vICBPdGhlciBpbnB1dHM6XG4gIC8vICAgICBiaWFzICAgICAgICAgICAgIChRL0svVikgICA6IE5vbmUgb3IgKEQgKyBEICsgRF92KVxuICAvLyAgICAga2V5X3BhZGRpbmdfbWFzayAoSy9WKSAgICAgOiAoQikgb3IgKDMgKiBCICsgMikgb3IgKEIsIFQpIG9yIChCLCBTLCBUKVxuICAvLyAgICAgYXR0ZW50aW9uX2JpYXMgICAgICAgICAgICAgOiBOb25lIG9yIChCLCBOLCBTLCBUKSwgKDEsIE4sIFMsIFQpLCAoQiwgMSwgUywgVCkgb3IgKDEsIDEsIFMsIFQpXG4gIC8vICAgICBwYXN0X2tleSAgICAgICAgICAgICAgICAgICA6IChCLCBOLCBQLCBIKSBvciBOb25lLiBQYXN0IHN0YXRlIGlzIG9ubHkgYWxsb3dlZCBmb3IgUV9LX1ZfQlNOSC5cbiAgLy8gICAgIHBhc3RfdmFsdWUgICAgICAgICAgICAgICAgIDogKEIsIE4sIFAsIEgpIG9yIE5vbmUuIFBhc3Qgc3RhdGUgaXMgb25seSBhbGxvd2VkIGZvciBRX0tfVl9CU05ILlxuICAvL1xuICAvLyAgTm90IFN1cHBvcnRlZDpcbiAgLy8gICAgIGtleV9wYWRkaW5nX21hc2ssIHBhY2tlZCBrdiwgcGFja2VkIHFrdiwgYW5kIGJyb2FkY2FzdCBmb3IgYXR0ZW50aW9uX2JpYXMuXG5cbiAgaWYgKHF1ZXJ5LmRpbXMubGVuZ3RoICE9PSAzICYmIHF1ZXJ5LmRpbXMubGVuZ3RoICE9PSA1KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBxdWVyeSBpcyBleHBlY3RlZCB0byBoYXZlIDMgb3IgNSBkaW1lbnNpb25zJyk7XG4gIH1cblxuICBjb25zdCBiYXRjaFNpemUgPSBxdWVyeS5kaW1zWzBdO1xuICBjb25zdCBzZXF1ZW5jZUxlbmd0aCA9IHF1ZXJ5LmRpbXNbMV07XG4gIGNvbnN0IGhpZGRlblNpemUgPSBxdWVyeS5kaW1zLmxlbmd0aCA9PT0gMyA/IHF1ZXJ5LmRpbXNbMl0gOiBhdHRyaWJ1dGVzLm51bUhlYWRzICogcXVlcnkuZGltc1s0XTtcbiAgbGV0IGt2U2VxdWVuY2VMZW5ndGggPSBzZXF1ZW5jZUxlbmd0aDtcblxuICBsZXQgcGFzdFNlcXVlbmNlTGVuZ3RoID0gMDtcbiAgbGV0IG1heFNlcXVlbmNlTGVuZ3RoID0gMDtcbiAgY29uc3QgaGVhZFNpemUgPSBNYXRoLmZsb29yKGhpZGRlblNpemUgLyBhdHRyaWJ1dGVzLm51bUhlYWRzKTtcbiAgaWYgKHBhc3RLZXkgJiYgcGFzdFZhbHVlICYmIFNoYXBlVXRpbC5zaXplKHBhc3RLZXkuZGltcykgJiYgU2hhcGVVdGlsLnNpemUocGFzdFZhbHVlLmRpbXMpKSB7XG4gICAgaWYgKHBhc3RLZXkuZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0X2tleVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgNCBkaW1lbnNpb25zJyk7XG4gICAgfVxuICAgIGlmIChwYXN0S2V5LmRpbXNbMF0gIT09IGJhdGNoU2l6ZSB8fCBwYXN0S2V5LmRpbXNbMV0gIT09IGF0dHJpYnV0ZXMubnVtSGVhZHMgfHwgcGFzdEtleS5kaW1zWzNdICE9PSBoZWFkU2l6ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3Rfa2V5XCIgc2hhcGUgKGJhdGNoX3NpemUsIG51bV9oZWFkcywgcGFzdF9zZXF1ZW5jZV9sZW5ndGgsIGhlYWRfc2l6ZSknKTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgcGFzdFZhbHVlLmRpbXNbMF0gIT09IGJhdGNoU2l6ZSB8fFxuICAgICAgcGFzdFZhbHVlLmRpbXNbMV0gIT09IGF0dHJpYnV0ZXMubnVtSGVhZHMgfHxcbiAgICAgIHBhc3RWYWx1ZS5kaW1zWzNdICE9PSBoZWFkU2l6ZVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3RfdmFsdWVcIiBzaGFwZSAoYmF0Y2hfc2l6ZSwgbnVtX2hlYWRzLCBwYXN0X3NlcXVlbmNlX2xlbmd0aCwgaGVhZF9zaXplKScpO1xuICAgIH1cbiAgICBpZiAocGFzdEtleS5kaW1zWzJdICE9PSBwYXN0VmFsdWUuZGltc1syXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3Rfa2V5XCIgYW5kIFwicGFzdF92YWx1ZVwiIHNoYWxsIGhhdmUgc2FtZSBkaW0gMiAocGFzdF9zZXF1ZW5jZV9sZW5ndGgpJyk7XG4gICAgfVxuICAgIGlmIChwYXN0VmFsdWUuZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0X3ZhbHVlXCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSA0IGRpbWVuc2lvbnMnKTtcbiAgICB9XG4gICAgcGFzdFNlcXVlbmNlTGVuZ3RoID0gcGFzdEtleS5kaW1zWzJdO1xuICAgIG1heFNlcXVlbmNlTGVuZ3RoID0gcGFzdEtleS5kaW1zWzJdO1xuICB9IGVsc2UgaWYgKChwYXN0S2V5ICYmIFNoYXBlVXRpbC5zaXplKHBhc3RLZXkuZGltcykpIHx8IChwYXN0VmFsdWUgJiYgU2hhcGVVdGlsLnNpemUocGFzdFZhbHVlLmRpbXMpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0X2tleVwiIGFuZCBcInBhc3RfdmFsdWVcIiBzaGFsbCBiZSBib3RoIHByZXNlbnQgb3IgYm90aCBhYnNlbnQnKTtcbiAgfVxuXG4gIGxldCBxa3ZGb3JtYXQ6IEF0dGVudGlvblFrdkZvcm1hdDtcbiAgaWYgKGtleSAmJiBTaGFwZVV0aWwuc2l6ZShrZXkuZGltcykgPiAwKSB7XG4gICAgaWYgKHF1ZXJ5LmRpbXMubGVuZ3RoICE9PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicXVlcnlcIiBpcyBleHBlY3RlZCB0byBoYXZlIDMgZGltZW5zaW9ucyB3aGVuIGtleSBpcyBnaXZlbicpO1xuICAgIH1cbiAgICBpZiAoa2V5LmRpbXMubGVuZ3RoIDwgMyB8fCBrZXkuZGltcy5sZW5ndGggPiA1KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwia2V5XCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAzLCA0LCBvciA1IGRpbWVuc2lvbnMnKTtcbiAgICB9XG4gICAgaWYgKHF1ZXJ5LmRpbXNbMF0gIT09IGtleS5kaW1zWzBdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicXVlcnlcIiBhbmQgXCJrZXlcIiBzaGFsbCBoYXZlIHNhbWUgZGltIDAgKGJhdGNoIHNpemUpJyk7XG4gICAgfVxuXG4gICAgaWYgKGtleS5kaW1zLmxlbmd0aCA9PT0gMykge1xuICAgICAgaWYgKGtleS5kaW1zWzJdICE9PSBxdWVyeS5kaW1zWzJdKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGFuZCBcImtleVwiIHNoYWxsIGhhdmUgc2FtZSBkaW0gMiAoaGlkZGVuX3NpemUpJyk7XG4gICAgICB9XG4gICAgICBxa3ZGb3JtYXQgPSBBdHRlbnRpb25Ra3ZGb3JtYXQucWt2QlNOSDtcbiAgICAgIGt2U2VxdWVuY2VMZW5ndGggPSBrZXkuZGltc1sxXTtcbiAgICB9IGVsc2UgaWYgKGtleS5kaW1zLmxlbmd0aCA9PT0gNSkge1xuICAgICAgaWYgKGtleS5kaW1zWzJdICE9PSBhdHRyaWJ1dGVzLm51bUhlYWRzIHx8IGtleS5kaW1zWzNdICE9PSAyIHx8IGtleS5kaW1zWzRdICE9PSBoZWFkU2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdCBcImtleVwiIHNoYXBlIChiYXRjaF9zaXplLCBrdl9zZXF1ZW5jZV9sZW5ndGgsIG51bV9oZWFkcywgMiwgaGVhZF9zaXplKSBmb3IgcGFja2VkIGt2Jyk7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3QgXCJ2YWx1ZVwiIGJlIG5vbmUgd2hlbiBcImtleVwiIGhhcyBwYWNrZWQga3YgZm9ybWF0LicpO1xuICAgICAgfVxuICAgICAgcWt2Rm9ybWF0ID0gQXR0ZW50aW9uUWt2Rm9ybWF0LnFLdkJTTkh4QlNOMkg7XG4gICAgICBrdlNlcXVlbmNlTGVuZ3RoID0ga2V5LmRpbXNbMV07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGtleV9kaW1zLnNpemUoKSA9PSA0IChjcm9zcy1hdHRlbnRpb24gd2l0aCBwYXN0X2tleSlcbiAgICAgIGlmIChrZXkuZGltc1sxXSAhPT0gYXR0cmlidXRlcy5udW1IZWFkcyB8fCBrZXkuZGltc1szXSAhPT0gaGVhZFNpemUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3QgXCJrZXlcIiBzaGFwZSAoYmF0Y2hfc2l6ZSwgbnVtX2hlYWRzLCBrdl9zZXF1ZW5jZV9sZW5ndGgsIGhlYWRfc2l6ZSkgZm9yIHBhc3Rfa2V5Jyk7XG4gICAgICB9XG5cbiAgICAgIHFrdkZvcm1hdCA9IEF0dGVudGlvblFrdkZvcm1hdC51bmtub3duOyAvLyBRX0tfVl9CU05IX0JOU0hfQk5TSFxuICAgICAga3ZTZXF1ZW5jZUxlbmd0aCA9IGtleS5kaW1zWzJdO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBwYWNrZWQgUUtWXG4gICAgaWYgKHF1ZXJ5LmRpbXMubGVuZ3RoICE9PSA1KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicXVlcnlcIiBpcyBleHBlY3RlZCB0byBoYXZlIDUgZGltZW5zaW9ucyB3aGVuIGtleSBpcyBlbXB0eScpO1xuICAgIH1cbiAgICBpZiAocXVlcnkuZGltc1syXSAhPT0gYXR0cmlidXRlcy5udW1IZWFkcyB8fCBxdWVyeS5kaW1zWzNdICE9PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdCBcInF1ZXJ5XCIgc2hhcGUgKGJhdGNoX3NpemUsIGt2X3NlcXVlbmNlX2xlbmd0aCwgbnVtX2hlYWRzLCAzLCBoZWFkX3NpemUpIGZvciBwYWNrZWQga3YnKTtcbiAgICB9XG5cbiAgICBxa3ZGb3JtYXQgPSBBdHRlbnRpb25Ra3ZGb3JtYXQucWt2QlNOM0g7XG4gIH1cblxuICBpZiAoYmlhcyAmJiBTaGFwZVV0aWwuc2l6ZShiaWFzLmRpbXMpID4gMCkge1xuICAgIGlmIChiaWFzLmRpbXMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwiYmlhc1wiIGlzIGV4cGVjdGVkIHRvIGhhdmUgMSBkaW1lbnNpb24nKTtcbiAgICB9XG5cbiAgICBpZiAoa2V5KSB7XG4gICAgICBpZiAoa2V5LmRpbXMubGVuZ3RoID09PSA1ICYmIGtleS5kaW1zWzNdID09PSAyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYmlhcyBpcyBub3QgYWxsb3dlZCBmb3IgcGFja2VkIGt2LicpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGggPSBwYXN0U2VxdWVuY2VMZW5ndGggKyBrdlNlcXVlbmNlTGVuZ3RoO1xuXG4gIGxldCBtYXNrVHlwZTogQXR0ZW50aW9uTWFza1R5cGUgPSBBdHRlbnRpb25NYXNrVHlwZS5ub25lO1xuICBpZiAoa2V5UGFkZGluZ01hc2sgJiYgU2hhcGVVdGlsLnNpemUoa2V5UGFkZGluZ01hc2suZGltcykgPiAwKSB7XG4gICAgbWFza1R5cGUgPSBBdHRlbnRpb25NYXNrVHlwZS5tYXNrVW5rbm93bjtcbiAgICBjb25zdCBtYXNrRGltcyA9IGtleVBhZGRpbmdNYXNrLmRpbXM7XG4gICAgaWYgKG1hc2tEaW1zLmxlbmd0aCA9PT0gMSkge1xuICAgICAgaWYgKG1hc2tEaW1zWzBdID09PSBiYXRjaFNpemUpIHtcbiAgICAgICAgbWFza1R5cGUgPSBBdHRlbnRpb25NYXNrVHlwZS5tYXNrMWRLZXlTZXFMZW47XG4gICAgICB9IGVsc2UgaWYgKG1hc2tEaW1zWzBdID09PSAzICogYmF0Y2hTaXplICsgMikge1xuICAgICAgICBtYXNrVHlwZSA9IEF0dGVudGlvbk1hc2tUeXBlLm1hc2sxREtleVNlcUxlblN0YXJ0O1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobWFza0RpbXMubGVuZ3RoID09PSAyICYmIG1hc2tEaW1zWzBdID09PSBiYXRjaFNpemUgJiYgbWFza0RpbXNbMV0gPT09IHRvdGFsU2VxdWVuY2VMZW5ndGgpIHtcbiAgICAgIG1hc2tUeXBlID0gQXR0ZW50aW9uTWFza1R5cGUubWFzazJkS2V5UGFkZGluZztcbiAgICB9XG4gICAgaWYgKG1hc2tUeXBlID09PSBBdHRlbnRpb25NYXNrVHlwZS5tYXNrVW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImtleV9wYWRkaW5nX21hc2tcIiBzaGFwZSBzaGFsbCBiZSAoYmF0Y2hfc2l6ZSkgb3IgKGJhdGNoX3NpemUsIHRvdGFsX3NlcXVlbmNlX2xlbmd0aCknKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNYXNrIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuXG4gIGxldCBwYXNzUGFzdEluS3YgPSBmYWxzZTtcbiAgbGV0IHZIaWRkZW5TaXplID0gaGlkZGVuU2l6ZTtcbiAgaWYgKHZhbHVlICYmIFNoYXBlVXRpbC5zaXplKHZhbHVlLmRpbXMpID4gMCkge1xuICAgIGlmICh2YWx1ZS5kaW1zLmxlbmd0aCAhPT0gMyAmJiB2YWx1ZS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInZhbHVlXCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAzIG9yIDQgZGltZW5zaW9ucycpO1xuICAgIH1cblxuICAgIGlmIChxdWVyeS5kaW1zWzBdICE9PSB2YWx1ZS5kaW1zWzBdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicXVlcnlcIiBhbmQgXCJ2YWx1ZVwiIHNoYWxsIGhhdmUgc2FtZSBkaW0gMCAoYmF0Y2hfc2l6ZSknKTtcbiAgICB9XG5cbiAgICBpZiAodmFsdWUuZGltcy5sZW5ndGggPT09IDMpIHtcbiAgICAgIGlmIChrdlNlcXVlbmNlTGVuZ3RoICE9PSB2YWx1ZS5kaW1zWzFdKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJrZXlcIiBhbmQgXCJ2YWx1ZVwiIHNoYWxsIGhhdmUgdGhlIHNhbWUgZGltIDEgKGt2X3NlcXVlbmNlX2xlbmd0aCknKTtcbiAgICAgIH1cbiAgICAgIHZIaWRkZW5TaXplID0gdmFsdWUuZGltc1syXTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gUV9LX1ZfQlNOSF9CTlNIX0JOU0hcbiAgICAgIGlmIChrdlNlcXVlbmNlTGVuZ3RoICE9PSB2YWx1ZS5kaW1zWzJdKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJrZXlcIiBhbmQgXCJ2YWx1ZVwiIHNoYWxsIGhhdmUgdGhlIHNhbWUgZGltIDIgKGt2X3NlcXVlbmNlX2xlbmd0aCknKTtcbiAgICAgIH1cbiAgICAgIHZIaWRkZW5TaXplID0gdmFsdWUuZGltc1sxXSAqIHZhbHVlLmRpbXNbM107XG4gICAgICBwYXNzUGFzdEluS3YgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGJyb2FkY2FzdFJlc1Bvc0JpYXMgPSBmYWxzZTtcblxuICBpZiAoa2V5UGFkZGluZ01hc2sgJiYgU2hhcGVVdGlsLnNpemUoa2V5UGFkZGluZ01hc2suZGltcykgPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdLZXkgcGFkZGluZyBtYXNrIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuXG4gIGlmIChhdHRlbnRpb25CaWFzICYmIFNoYXBlVXRpbC5zaXplKGF0dGVudGlvbkJpYXMuZGltcykgPiAwKSB7XG4gICAgaWYgKGF0dGVudGlvbkJpYXMuZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJhdHRlbnRpb25fYmlhc1wiIGlzIGV4cGVjdGVkIHRvIGhhdmUgNCBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBicm9hZGNhc3RpbmcgdGhlIGZpcnN0IGFuZCBzZWNvbmQgZGltZW5zaW9ucyBvZiBhdHRlbnRpb25fYmlhcy5cbiAgICBpZiAoXG4gICAgICBhdHRlbnRpb25CaWFzLmRpbXNbMF0gIT09IGJhdGNoU2l6ZSB8fFxuICAgICAgYXR0ZW50aW9uQmlhcy5kaW1zWzFdICE9PSBhdHRyaWJ1dGVzLm51bUhlYWRzIHx8XG4gICAgICBhdHRlbnRpb25CaWFzLmRpbXNbMl0gIT09IHNlcXVlbmNlTGVuZ3RoIHx8XG4gICAgICBhdHRlbnRpb25CaWFzLmRpbXNbM10gIT09IHRvdGFsU2VxdWVuY2VMZW5ndGhcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0IFwiYXR0ZW50aW9uX2JpYXNcIiBzaGFwZSAoYmF0Y2hfc2l6ZSwgbnVtX2hlYWRzLCBzZXF1ZW5jZV9sZW5ndGgsIHRvdGFsX3NlcXVlbmNlX2xlbmd0aCknKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGJhdGNoU2l6ZSxcbiAgICBzZXF1ZW5jZUxlbmd0aCxcbiAgICBwYXN0U2VxdWVuY2VMZW5ndGgsXG4gICAga3ZTZXF1ZW5jZUxlbmd0aCxcbiAgICB0b3RhbFNlcXVlbmNlTGVuZ3RoLFxuICAgIG1heFNlcXVlbmNlTGVuZ3RoLFxuICAgIGlucHV0SGlkZGVuU2l6ZTogMCxcbiAgICBoaWRkZW5TaXplLFxuICAgIHZIaWRkZW5TaXplLFxuICAgIGhlYWRTaXplLFxuICAgIHZIZWFkU2l6ZTogTWF0aC5mbG9vcih2SGlkZGVuU2l6ZSAvIGF0dHJpYnV0ZXMubnVtSGVhZHMpLFxuICAgIG51bUhlYWRzOiBhdHRyaWJ1dGVzLm51bUhlYWRzLFxuICAgIGlzVW5pZGlyZWN0aW9uYWw6IGZhbHNlLFxuICAgIHBhc3RQcmVzZW50U2hhcmVCdWZmZXI6IGZhbHNlLFxuICAgIG1hc2tGaWx0ZXJWYWx1ZTogYXR0cmlidXRlcy5tYXNrRmlsdGVyVmFsdWUsXG4gICAgbWFza1R5cGUsXG4gICAgc2NhbGU6IGF0dHJpYnV0ZXMuc2NhbGUsXG4gICAgYnJvYWRjYXN0UmVzUG9zQmlhcyxcbiAgICBwYXNzUGFzdEluS3YsXG4gICAgcWt2Rm9ybWF0LFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTXVsdGlIZWFkQXR0ZW50aW9uQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBBdHRlbnRpb25BdHRycyk6IEF0dGVudGlvbkF0dHJzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IC4uLmF0dHJpYnV0ZXMgfSk7XG5cbmNvbnN0IHdlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZTogVHJhbnNwb3NlQXR0cmlidXRlcyA9IGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IHBlcm06IFswLCAyLCAxLCAzXSB9KTtcblxuY29uc3QgYWRkQmlhc1RyYW5zcG9zZSA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIHFrdjogVGVuc29yVmlldyxcbiAgYmlhczogVGVuc29yVmlldyxcbiAgYmF0Y2hTaXplOiBudW1iZXIsXG4gIHNlcXVlbmNlTGVuZ3RoOiBudW1iZXIsXG4gIGhpZGRlblNpemU6IG51bWJlcixcbiAgYmlhc09mZnNldDogbnVtYmVyLFxuKSA9PiB7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gW2JhdGNoU2l6ZSwgc2VxdWVuY2VMZW5ndGgsIGhpZGRlblNpemVdO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYmlhc09mZnNldCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBoaWRkZW5TaXplIH0sXG4gIF07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ3Frdl93aXRoX2JpYXMnLCBxa3YuZGF0YVR5cGUsIG91dHB1dFNoYXBlKTtcbiAgICBjb25zdCBxa3ZJbnB1dCA9IGlucHV0VmFyaWFibGUoJ3FrdicsIHFrdi5kYXRhVHlwZSwgb3V0cHV0U2hhcGUpO1xuICAgIGNvbnN0IGJpYXNJbnB1dCA9IGlucHV0VmFyaWFibGUoJ2JpYXMnLCBiaWFzLmRhdGFUeXBlLCBvdXRwdXRTaGFwZSk7XG5cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdiaWFzX29mZnNldCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdoaWRkZW5fc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKHFrdklucHV0LCBiaWFzSW5wdXQsIG91dHB1dCl9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgbGV0IGJpYXNfb2Zmc2V0X2lkeCA9IChnbG9iYWxfaWR4ICUgdW5pZm9ybXMuaGlkZGVuX3NpemUpICsgdW5pZm9ybXMuYmlhc19vZmZzZXQ7XG5cbiAgICBxa3Zfd2l0aF9iaWFzW2dsb2JhbF9pZHhdID0gcWt2W2dsb2JhbF9pZHhdICsgYmlhc1tiaWFzX29mZnNldF9pZHhdO1xuICB9YDtcbiAgfTtcblxuICByZXR1cm4gY29udGV4dC5jb21wdXRlKFxuICAgIHtcbiAgICAgIG5hbWU6ICdNdWx0aUhlYWRBdHRlbnRpb25BZGRCaWFzJyxcbiAgICAgIHNoYWRlckNhY2hlOiB7IGlucHV0RGVwZW5kZW5jaWVzOiBbJ3R5cGUnLCAndHlwZSddIH0sXG4gICAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IHFrdi5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHQgfV0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgICAgfSksXG4gICAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgfSxcbiAgICB7IGlucHV0czogW3FrdiwgYmlhc10sIG91dHB1dHM6IFstMV0gfSxcbiAgKVswXTtcbn07XG5cbmV4cG9ydCBjb25zdCBtYXliZVRyYW5zcG9zZVRvQk5TSEFuZEFkZEJpYXMgPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBiYXRjaFNpemU6IG51bWJlcixcbiAgbnVtSGVhZHM6IG51bWJlcixcbiAgc2VxdWVuY2VMZW5ndGg6IG51bWJlcixcbiAgaGVhZFNpemU6IG51bWJlcixcbiAgaW5wdXQ6IFRlbnNvclZpZXcsXG4gIGJpYXM/OiBUZW5zb3JWaWV3LFxuICBiaWFzT2Zmc2V0PzogbnVtYmVyLFxuKSA9PiB7XG4gIC8vIGNvbnN0IG5ld0RpbXMgPSBbXTtcblxuICBsZXQgcmVzaGFwZWRJbnB1dCA9IGlucHV0O1xuICBpZiAoIShiaWFzICYmIFNoYXBlVXRpbC5zaXplKGJpYXMuZGltcykgPiAwKSkge1xuICAgIGlmIChpbnB1dC5kaW1zLmxlbmd0aCA9PT0gMykge1xuICAgICAgcmVzaGFwZWRJbnB1dCA9IGlucHV0LnJlc2hhcGUoW2JhdGNoU2l6ZSwgc2VxdWVuY2VMZW5ndGgsIG51bUhlYWRzLCBoZWFkU2l6ZV0pO1xuICAgIH1cbiAgICBpZiAobnVtSGVhZHMgPT09IDEgfHwgc2VxdWVuY2VMZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiByZXNoYXBlZElucHV0O1xuICAgIH1cbiAgICByZXR1cm4gY29udGV4dC5jb21wdXRlKGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKHJlc2hhcGVkSW5wdXQsIHdlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZS5wZXJtKSwge1xuICAgICAgaW5wdXRzOiBbcmVzaGFwZWRJbnB1dF0sXG4gICAgICBvdXRwdXRzOiBbLTFdLFxuICAgIH0pWzBdO1xuICB9IGVsc2Uge1xuICAgIGlmIChzZXF1ZW5jZUxlbmd0aCA9PT0gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBZGRCaWFzUmVzaGFwZSBpcyBub3QgaW1wbGVtZW50ZWQuIFBsZWFzZSBleHBvcnQgeW91ciBtb2RlbCB3aXRoIHBhY2tlZCBRS1Ygb3IgS1YnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzaGFwZWRJbnB1dCA9IGFkZEJpYXNUcmFuc3Bvc2UoXG4gICAgICAgIGNvbnRleHQsXG4gICAgICAgIGlucHV0LFxuICAgICAgICBiaWFzLFxuICAgICAgICBiYXRjaFNpemUsXG4gICAgICAgIHNlcXVlbmNlTGVuZ3RoLFxuICAgICAgICBudW1IZWFkcyAqIGhlYWRTaXplLFxuICAgICAgICBiaWFzT2Zmc2V0ISxcbiAgICAgICk7XG4gICAgICByZXNoYXBlZElucHV0ID0gcmVzaGFwZWRJbnB1dC5yZXNoYXBlKFtiYXRjaFNpemUsIHNlcXVlbmNlTGVuZ3RoLCBudW1IZWFkcywgaGVhZFNpemVdKTtcbiAgICAgIGlmIChudW1IZWFkcyA9PT0gMSB8fCBzZXF1ZW5jZUxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gcmVzaGFwZWRJbnB1dDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8ocmVzaGFwZWRJbnB1dCwgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlLnBlcm0pLCB7XG4gICAgICAgIGlucHV0czogW3Jlc2hhcGVkSW5wdXRdLFxuICAgICAgICBvdXRwdXRzOiBbLTFdLFxuICAgICAgfSlbMF07XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgY29uc3QgbXVsdGlIZWFkQXR0ZW50aW9uID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBdHRlbnRpb25BdHRycyk6IHZvaWQgPT4ge1xuICBjb25zdCBwYXJhbXMgPSB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGNvbnN0IHF1ZXJ5ID0gY29udGV4dC5pbnB1dHNbMF07XG4gIGNvbnN0IGtleSA9IGdldElucHV0KGNvbnRleHQuaW5wdXRzLCAxKTtcbiAgY29uc3QgdmFsdWUgPSBnZXRJbnB1dChjb250ZXh0LmlucHV0cywgMik7XG4gIGNvbnN0IGJpYXMgPSBnZXRJbnB1dChjb250ZXh0LmlucHV0cywgMyk7XG4gIGNvbnN0IGtleVBhZGRpbmdNYXNrID0gZ2V0SW5wdXQoY29udGV4dC5pbnB1dHMsIDQpO1xuICBjb25zdCBhdHRlbnRpb25CaWFzID0gZ2V0SW5wdXQoY29udGV4dC5pbnB1dHMsIDUpO1xuICBjb25zdCBwYXN0S2V5ID0gZ2V0SW5wdXQoY29udGV4dC5pbnB1dHMsIDYpO1xuICBjb25zdCBwYXN0VmFsdWUgPSBnZXRJbnB1dChjb250ZXh0LmlucHV0cywgNyk7XG4gIGlmIChxdWVyeS5kaW1zLmxlbmd0aCA9PT0gNSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUGFja2VkIFFLViBpcyBub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIGlmIChrZXk/LmRpbXMubGVuZ3RoID09PSA1KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQYWNrZWQgS1YgaXMgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICAvLyBhcHBseUF0dGVudGlvbiBleHBlY3RzIEJOU0ggaW5wdXRzXG4gIGNvbnN0IGt2Qk5TSCA9IGtleSAmJiB2YWx1ZSAmJiBrZXkuZGltcy5sZW5ndGggPT09IDQgJiYgdmFsdWUuZGltcy5sZW5ndGggPT09IDQ7XG5cbiAgY29uc3QgUSA9IG1heWJlVHJhbnNwb3NlVG9CTlNIQW5kQWRkQmlhcyhcbiAgICBjb250ZXh0LFxuICAgIHBhcmFtcy5iYXRjaFNpemUsXG4gICAgcGFyYW1zLm51bUhlYWRzLFxuICAgIHBhcmFtcy5zZXF1ZW5jZUxlbmd0aCxcbiAgICBwYXJhbXMuaGVhZFNpemUsXG4gICAgcXVlcnksXG4gICAgYmlhcyxcbiAgICAwLFxuICApO1xuXG4gIGlmIChrdkJOU0gpIHtcbiAgICByZXR1cm4gYXBwbHlBdHRlbnRpb24oY29udGV4dCwgUSwga2V5LCB2YWx1ZSwga2V5UGFkZGluZ01hc2ssIHVuZGVmaW5lZCwgcGFzdEtleSwgcGFzdFZhbHVlLCBhdHRlbnRpb25CaWFzLCBwYXJhbXMpO1xuICB9XG4gIGlmICgha2V5IHx8ICF2YWx1ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigna2V5IGFuZCB2YWx1ZSBtdXN0IGJlIHByb3ZpZGVkJyk7XG4gIH1cbiAgY29uc3QgSyA9IG1heWJlVHJhbnNwb3NlVG9CTlNIQW5kQWRkQmlhcyhcbiAgICBjb250ZXh0LFxuICAgIHBhcmFtcy5iYXRjaFNpemUsXG4gICAgcGFyYW1zLm51bUhlYWRzLFxuICAgIHBhcmFtcy5rdlNlcXVlbmNlTGVuZ3RoLFxuICAgIHBhcmFtcy5oZWFkU2l6ZSxcbiAgICBrZXksXG4gICAgYmlhcyxcbiAgICBwYXJhbXMuaGlkZGVuU2l6ZSxcbiAgKTtcblxuICBjb25zdCBWID0gbWF5YmVUcmFuc3Bvc2VUb0JOU0hBbmRBZGRCaWFzKFxuICAgIGNvbnRleHQsXG4gICAgcGFyYW1zLmJhdGNoU2l6ZSxcbiAgICBwYXJhbXMubnVtSGVhZHMsXG4gICAgcGFyYW1zLmt2U2VxdWVuY2VMZW5ndGgsXG4gICAgcGFyYW1zLnZIZWFkU2l6ZSxcbiAgICB2YWx1ZSxcbiAgICBiaWFzLFxuICAgIDIgKiBwYXJhbXMuaGlkZGVuU2l6ZSxcbiAgKTtcblxuICBhcHBseUF0dGVudGlvbihjb250ZXh0LCBRLCBLLCBWLCBrZXlQYWRkaW5nTWFzaywgdW5kZWZpbmVkLCBwYXN0S2V5LCBwYXN0VmFsdWUsIGF0dGVudGlvbkJpYXMsIHBhcmFtcyk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0sIFRlbnNvckluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRFbGVtZW50QXQsXG4gIEluZGljZXNIZWxwZXIsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG59IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBTcGxpdEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBheGlzOiBudW1iZXI7XG4gIHJlYWRvbmx5IG51bU91dHB1dHM6IG51bWJlcjtcbiAgcmVhZG9ubHkgc3BsaXRTaXplczogbnVtYmVyW107XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd0b28gZmV3IGlucHV0cycpO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVTcGxpdEF0dHJpYnV0ZXNGcm9tSW5wdXRzID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogU3BsaXRBdHRyaWJ1dGVzLFxuKTogU3BsaXRBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3Qgc3BsaXRTaXplczogbnVtYmVyW10gPSBbXTtcbiAgbGV0IG51bU91dHB1dHM6IG51bWJlciA9IGF0dHJpYnV0ZXMubnVtT3V0cHV0cztcbiAgaWYgKGlucHV0c1sxXS5kaW1zWzBdID4gMCkge1xuICAgIGlucHV0c1sxXS5nZXRCaWdJbnQ2NEFycmF5KCkuZm9yRWFjaCgodikgPT4gc3BsaXRTaXplcy5wdXNoKE51bWJlcih2KSkpO1xuICAgIG51bU91dHB1dHMgPSBzcGxpdFNpemVzLmxlbmd0aDtcbiAgfVxuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgbnVtT3V0cHV0cywgYXhpczogYXR0cmlidXRlcy5heGlzLCBzcGxpdFNpemVzIH0pO1xufTtcblxuY29uc3QgY2FsY3VsYXRlT3V0cHV0SW5kZXhJbXBsID0gKG51bWJlck9mVGVuc29yczogbnVtYmVyKTogc3RyaW5nID0+IGBcbmZuIGNhbGN1bGF0ZU91dHB1dEluZGV4KGluZGV4OiB1MzIpIC0+IHUzMiB7XG4gICAgZm9yICh2YXIgaTogdTMyID0gMHU7IGkgPCAke251bWJlck9mVGVuc29yc311OyBpICs9IDF1ICkge1xuICAgIGlmIChpbmRleCA8ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5zaXplX2luX3NwbGl0X2F4aXMnLCAnaScsIG51bWJlck9mVGVuc29ycyl9KSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICR7bnVtYmVyT2ZUZW5zb3JzfXU7XG59YDtcbmNvbnN0IHdyaXRlQnVmZmVyRGF0YUltcGwgPSAob3V0cHV0czogcmVhZG9ubHkgSW5kaWNlc0hlbHBlcltdKSA9PiB7XG4gIGNvbnN0IG51bWJlck9mVGVuc29ycyA9IG91dHB1dHMubGVuZ3RoO1xuICBjb25zdCBjb2RlTGluZXM6IHN0cmluZ1tdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZUZW5zb3JzOyArK2kpIHtcbiAgICBjb25zdCByZXR1cm5TbmlwcGV0ID0gb3V0cHV0c1tpXS5zZXRCeUluZGljZXMoJ2luZGljZXMnLCAnaW5wdXRbZ2xvYmFsX2lkeF0nKTtcbiAgICBpZiAobnVtYmVyT2ZUZW5zb3JzID09PSAxKSB7XG4gICAgICBjb2RlTGluZXMucHVzaChyZXR1cm5TbmlwcGV0KTtcbiAgICB9IGVsc2UgaWYgKGkgPT09IDApIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKGBpZiAob3V0cHV0X251bWJlciA9PSAke2l9dSkgeyAke3JldHVyblNuaXBwZXR9IH1gKTtcbiAgICB9IGVsc2UgaWYgKGkgPT09IG51bWJlck9mVGVuc29ycyAtIDEpIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKGBlbHNlIHsgJHtyZXR1cm5TbmlwcGV0fSB9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKGBlbHNlIGlmIChvdXRwdXRfbnVtYmVyID09ICR7aX0pIHsgJHtyZXR1cm5TbmlwcGV0fSB9YCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBgXG4gICAgICBmbiB3cml0ZUJ1ZmZlckRhdGEob3V0cHV0X251bWJlcjogdTMyLCBpbmRpY2VzOiAke291dHB1dHNbMF0udHlwZS5pbmRpY2VzfSwgZ2xvYmFsX2lkeDogdTMyKSB7XG4gICAgICAgICR7Y29kZUxpbmVzLmpvaW4oJ1xcbicpfVxuICAgICAgfWA7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlU3BsaXRQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogU3BsaXRBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGlucHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKGlucHV0U2hhcGUpO1xuICBjb25zdCBkYXRhVHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMuYXhpcywgaW5wdXRTaGFwZS5sZW5ndGgpO1xuICBjb25zdCBvdXRwdXRzID0gbmV3IEFycmF5PEluZGljZXNIZWxwZXI+KGF0dHJpYnV0ZXMubnVtT3V0cHV0cyk7XG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBkYXRhVHlwZSwgaW5wdXRTaGFwZS5sZW5ndGgpO1xuICBjb25zdCBzaXplSW5TcGxpdEF4aXMgPSBuZXcgQXJyYXk8bnVtYmVyPihhdHRyaWJ1dGVzLm51bU91dHB1dHMpO1xuICBjb25zdCBvdXRwdXRzVGVuc29ySW5mbzogVGVuc29ySW5mb1tdID0gW107XG4gIGNvbnN0IG91dHB1dFNoYXBlczogbnVtYmVyW11bXSA9IFtdO1xuICBsZXQgcHJldmlvdXNTdW0gPSAwO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGlucHV0U2l6ZSB9XTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhdHRyaWJ1dGVzLm51bU91dHB1dHM7IGkrKykge1xuICAgIHByZXZpb3VzU3VtICs9IGF0dHJpYnV0ZXMuc3BsaXRTaXplc1tpXTtcbiAgICBzaXplSW5TcGxpdEF4aXNbaV0gPSBwcmV2aW91c1N1bTtcbiAgICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoKTtcbiAgICBvdXRwdXRTaGFwZVtheGlzXSA9IGF0dHJpYnV0ZXMuc3BsaXRTaXplc1tpXTtcbiAgICBvdXRwdXRTaGFwZXMucHVzaChvdXRwdXRTaGFwZSk7XG4gICAgb3V0cHV0c1tpXSA9IG91dHB1dFZhcmlhYmxlKGBvdXRwdXQke2l9YCwgZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gICAgb3V0cHV0c1RlbnNvckluZm8ucHVzaCh7IGRpbXM6IG91dHB1dFNoYXBlc1tpXSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9KTtcbiAgfVxuICBwcm9ncmFtVW5pZm9ybXMucHVzaChcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogc2l6ZUluU3BsaXRBeGlzIH0sXG4gICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRTaGFwZSwgLi4ub3V0cHV0U2hhcGVzKSxcbiAgKTtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICR7c2hhZGVySGVscGVyXG4gICAgLnJlZ2lzdGVyVW5pZm9ybSgnaW5wdXRfc2l6ZScsICd1MzInKVxuICAgIC5yZWdpc3RlclVuaWZvcm0oJ3NpemVfaW5fc3BsaXRfYXhpcycsICd1MzInLCBzaXplSW5TcGxpdEF4aXMubGVuZ3RoKVxuICAgIC5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCAuLi5vdXRwdXRzKX1cbiAgJHtjYWxjdWxhdGVPdXRwdXRJbmRleEltcGwoc2l6ZUluU3BsaXRBeGlzLmxlbmd0aCl9XG4gICR7d3JpdGVCdWZmZXJEYXRhSW1wbChvdXRwdXRzKX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5pbnB1dF9zaXplJyl9XG5cbiAgICB2YXIgaW5kaWNlcyA9ICR7aW5wdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgIHZhciBpbmRleCA9ICR7aW5wdXQuaW5kaWNlc0dldCgnaW5kaWNlcycsIGF4aXMpfTtcbiAgICBsZXQgb3V0cHV0X251bWJlciA9IGNhbGN1bGF0ZU91dHB1dEluZGV4KGluZGV4KTtcbiAgICBpZiAob3V0cHV0X251bWJlciAhPSAwKSB7XG4gICAgICBpbmRleCAtPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMuc2l6ZV9pbl9zcGxpdF9heGlzJywgJ291dHB1dF9udW1iZXIgLSAxdScsIHNpemVJblNwbGl0QXhpcy5sZW5ndGgpfTtcbiAgICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5kaWNlcycsIGF4aXMsICdpbmRleCcpfTtcbiAgICB9XG4gICAgd3JpdGVCdWZmZXJEYXRhKG91dHB1dF9udW1iZXIsIGluZGljZXMsIGdsb2JhbF9pZHgpO1xuICB9YDtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnU3BsaXQnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogb3V0cHV0c1RlbnNvckluZm8sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChpbnB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBzcGxpdCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogU3BsaXRBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgdXBkYXRlZEF0dHJpYnV0ZXMgPVxuICAgIGNvbnRleHQuaW5wdXRzLmxlbmd0aCA9PT0gMSA/IGF0dHJpYnV0ZXMgOiBjcmVhdGVTcGxpdEF0dHJpYnV0ZXNGcm9tSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVNwbGl0UHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIHVwZGF0ZWRBdHRyaWJ1dGVzKSwgeyBpbnB1dHM6IFswXSB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZVNwbGl0QXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFNwbGl0QXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGF4aXMgPSBhdHRyaWJ1dGVzLmF4aXMgYXMgbnVtYmVyO1xuICBjb25zdCBzcGxpdFNpemVzOiBudW1iZXJbXSA9IGF0dHJpYnV0ZXMuc3BsaXRTaXplcyBhcyBudW1iZXJbXTtcbiAgY29uc3QgbnVtT3V0cHV0cyA9IChhdHRyaWJ1dGVzLm51bU91dHB1dHMgYXMgbnVtYmVyKSA8IDAgPyBzcGxpdFNpemVzLmxlbmd0aCA6IChhdHRyaWJ1dGVzLm51bU91dHB1dHMgYXMgbnVtYmVyKTtcbiAgaWYgKG51bU91dHB1dHMgIT09IHNwbGl0U2l6ZXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdudW1PdXRwdXRzIGFuZCBzcGxpdFNpemVzIGxlbmd0aCBtdXN0IGJlIGVxdWFsJyk7XG4gIH1cbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IGF4aXMsIG51bU91dHB1dHMsIHNwbGl0U2l6ZXMgfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciwgV09SS0dST1VQX1NJWkUgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyB7XG4gIHJlYWRvbmx5IGludGVybGVhdmVkOiBib29sZWFuO1xuICByZWFkb25seSBudW1IZWFkczogbnVtYmVyO1xuICByZWFkb25seSByb3RhcnlFbWJlZGRpbmdEaW06IG51bWJlcjtcbiAgcmVhZG9ubHkgc2NhbGU6IG51bWJlcjtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IFJvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgW2lucHV0LCBwb3NpdGlvbklkcywgY29zQ2FjaGUsIHNpbkNhY2hlXSA9IGlucHV0cztcbiAgY29uc3QgeyBudW1IZWFkcywgcm90YXJ5RW1iZWRkaW5nRGltIH0gPSBhdHRyaWJ1dGVzO1xuXG4gIGlmIChpbnB1dC5kaW1zLmxlbmd0aCAhPT0gMyAmJiBpbnB1dC5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgJ3gnIGlzIGV4cGVjdGVkIHRvIGhhdmUgMyBvciA0IGRpbWVuc2lvbnMsIGdvdCAke2lucHV0LmRpbXMubGVuZ3RofWApO1xuICB9XG4gIGlmIChcbiAgICAhU2hhcGVVdGlsLmFyZUVxdWFsKHBvc2l0aW9uSWRzLmRpbXMsIFtdKSAmJlxuICAgICFTaGFwZVV0aWwuYXJlRXF1YWwocG9zaXRpb25JZHMuZGltcywgWzFdKSAmJlxuICAgIHBvc2l0aW9uSWRzLmRpbXMubGVuZ3RoICE9PSAyXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgJ3Bvc2l0aW9uX2lkcycgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAwLCAxLCBvciAyIGRpbWVuc2lvbnMsIGdvdCAke3Bvc2l0aW9uSWRzLmRpbXMubGVuZ3RofWApO1xuICB9XG4gIGlmIChjb3NDYWNoZS5kaW1zLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgJ2Nvc19jYWNoZScgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAyIGRpbWVuc2lvbnMsIGdvdCAke2Nvc0NhY2hlLmRpbXMubGVuZ3RofWApO1xuICB9XG4gIGlmIChzaW5DYWNoZS5kaW1zLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgJ3Npbl9jYWNoZScgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAyIGRpbWVuc2lvbnMsIGdvdCAke3NpbkNhY2hlLmRpbXMubGVuZ3RofWApO1xuICB9XG4gIGlmICghU2hhcGVVdGlsLmFyZUVxdWFsKGNvc0NhY2hlLmRpbXMsIHNpbkNhY2hlLmRpbXMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW5wdXRzICdjb3NfY2FjaGUnIGFuZCAnc2luX2NhY2hlJyBhcmUgZXhwZWN0ZWQgdG8gaGF2ZSB0aGUgc2FtZSBzaGFwZVwiKTtcbiAgfVxuXG4gIGlmIChyb3RhcnlFbWJlZGRpbmdEaW0gPiAwICYmIG51bUhlYWRzID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdudW1faGVhZHMgbXVzdCBiZSBwcm92aWRlZCBpZiByb3RhcnlfZW1iZWRkaW5nX2RpbSBpcyBzcGVjaWZpZWQnKTtcbiAgfVxuXG4gIGNvbnN0IGJhdGNoU2l6ZSA9IGlucHV0LmRpbXNbMF07XG4gIGNvbnN0IHNlcXVlbmNlTGVuZ3RoID0gaW5wdXQuZGltc1tpbnB1dC5kaW1zLmxlbmd0aCAtIDJdO1xuICBjb25zdCBtYXhTZXF1ZW5jZUxlbmd0aCA9IGNvc0NhY2hlLmRpbXNbMF07XG4gIGNvbnN0IGhpZGRlblNpemUgPSBTaGFwZVV0aWwuc2l6ZUZyb21EaW1lbnNpb24oaW5wdXQuZGltcywgMSkgLyBzZXF1ZW5jZUxlbmd0aDtcbiAgY29uc3QgaGVhZFNpemUgPSByb3RhcnlFbWJlZGRpbmdEaW0gPT09IDAgPyBjb3NDYWNoZS5kaW1zWzFdICogMiA6IGhpZGRlblNpemUgLyBudW1IZWFkcztcbiAgaWYgKHJvdGFyeUVtYmVkZGluZ0RpbSA+IGhlYWRTaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdyb3RhcnlfZW1iZWRkaW5nX2RpbSBtdXN0IGJlIGxlc3MgdGhhbiBvciBlcXVhbCB0byBoZWFkX3NpemUnKTtcbiAgfVxuXG4gIGlmIChwb3NpdGlvbklkcy5kaW1zLmxlbmd0aCA9PT0gMikge1xuICAgIGlmIChiYXRjaFNpemUgIT09IHBvc2l0aW9uSWRzLmRpbXNbMF0pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgJ3Bvc2l0aW9uX2lkcycgZGltZW5zaW9uIDAgc2hvdWxkIGJlIG9mIHNpemUgYmF0Y2hfc2l6ZSwgZ290ICR7cG9zaXRpb25JZHMuZGltc1swXX1gKTtcbiAgICB9XG4gICAgaWYgKHNlcXVlbmNlTGVuZ3RoICE9PSBwb3NpdGlvbklkcy5kaW1zWzFdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYElucHV0ICdwb3NpdGlvbl9pZHMnIGRpbWVuc2lvbiAxIHNob3VsZCBiZSBvZiBzaXplIHNlcXVlbmNlX2xlbmd0aCwgZ290ICR7cG9zaXRpb25JZHMuZGltc1sxXX1gKTtcbiAgICB9XG4gIH1cblxuICBpZiAoc2VxdWVuY2VMZW5ndGggPiBtYXhTZXF1ZW5jZUxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignVXBkYXRpbmcgY29zX2NhY2hlIGFuZCBzaW5fY2FjaGUgaW4gUm90YXJ5RW1iZWRkaW5nIGlzIG5vdCBjdXJyZW50bHkgc3VwcG9ydGVkJyk7XG4gIH1cblxuICAvLyBOb3RlOiBwb3NpdGlvbl9pZHMgdmFsdWUgdmFsaWRhdGlvbiBpcyBoYW5kbGVkIGJ5IHNoYWRlci1zaWRlIGJvdW5kcyBjaGVja3MgKGRlZmVuc2UtaW4tZGVwdGgpLlxuICAvLyBXZSBjYW5ub3QgdmFsaWRhdGUgcG9zaXRpb25faWRzIHZhbHVlcyBoZXJlIGJlY2F1c2UgdGhlIHRlbnNvciBpcyBHUFUtcmVzaWRlbnQgXHUyMDE0IGl0cyBkYXRhIGZpZWxkXG4gIC8vIGlzIGEgR1BVIGJ1ZmZlciBJRCwgbm90IGEgV0FTTSBoZWFwIHBvaW50ZXIsIHNvIGdldEJpZ0ludDY0QXJyYXkoKSB3b3VsZCByZWFkIGdhcmJhZ2UuXG5cbiAgaWYgKGhlYWRTaXplIC8gMiAhPT0gY29zQ2FjaGUuZGltc1sxXSAmJiByb3RhcnlFbWJlZGRpbmdEaW0gLyAyICE9PSBjb3NDYWNoZS5kaW1zWzFdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYElucHV0ICdjb3NfY2FjaGUnIGRpbWVuc2lvbiAxIHNob3VsZCBiZSBzYW1lIGFzIGhlYWRfc2l6ZSAvIDIgb3Igcm90YXJ5X2VtYmVkZGluZ19kaW0gLyAyLCBnb3QgJHtcbiAgICAgICAgY29zQ2FjaGUuZGltc1sxXVxuICAgICAgfWAsXG4gICAgKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVJvdGFyeUVtYmVkZGluZ1Byb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgeyBpbnRlcmxlYXZlZCwgbnVtSGVhZHMsIHJvdGFyeUVtYmVkZGluZ0RpbSwgc2NhbGUgfSA9IGF0dHJpYnV0ZXM7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IGlucHV0c1swXS5kaW1zWzBdO1xuICBjb25zdCBiYXRjaFN0cmlkZSA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbihpbnB1dHNbMF0uZGltcywgMSk7XG4gIGNvbnN0IHNlcXVlbmNlTGVuZ3RoID0gaW5wdXRzWzBdLmRpbXNbaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMl07XG4gIGNvbnN0IGhpZGRlblNpemUgPSBiYXRjaFN0cmlkZSAvIHNlcXVlbmNlTGVuZ3RoO1xuICBjb25zdCBoYWxmUm90YXJ5RW1iZWRkaW5nRGltID0gaW5wdXRzWzJdLmRpbXNbMV07XG4gIGNvbnN0IGhlYWRTaXplID0gcm90YXJ5RW1iZWRkaW5nRGltID09PSAwID8gaGFsZlJvdGFyeUVtYmVkZGluZ0RpbSAqIDIgOiBoaWRkZW5TaXplIC8gbnVtSGVhZHM7XG5cbiAgLy8gUm90YXJ5IGVtYmVkZGluZ3Mgd2lsbCBiZSBjYWxjdWxhdGVkIGluIGEgcGFpci13aXNlIGZhc2hpb24uIEluIGFjY29yZGFuY2UsIHVzZSB0aGUgc2hhcGVcbiAgLy8gW2JhdGNoIHNpemUsIHNlcXVlbmNlIGxlbmd0aCwgbnVtIG9mIGhlYWRzLCBudW0gb2YgcGFpcnMgdG8gcm90YXRlICsgbnVtIG9mIGRpbXMgdG8gY29weV1cbiAgLy8gdG8gdW5mb2xkIHRoZSBnbG9iYWwgaW5kZXggaW4gc2hhZGVyLlxuICBjb25zdCBnbG9iYWxTaGFwZSA9IG5ldyBBcnJheTxudW1iZXI+KFxuICAgIGJhdGNoU2l6ZSxcbiAgICBzZXF1ZW5jZUxlbmd0aCxcbiAgICBoaWRkZW5TaXplIC8gaGVhZFNpemUsXG4gICAgaGVhZFNpemUgLSBoYWxmUm90YXJ5RW1iZWRkaW5nRGltLFxuICApO1xuICBjb25zdCBnbG9iYWxTdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKGdsb2JhbFNoYXBlKTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogc2NhbGUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZ2xvYmFsU2hhcGUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZ2xvYmFsU3RyaWRlcyB9LFxuXG4gICAgLy8gc3RyaWRlcyBmb3IgYWRkcmVzc2luZyB0aGUgaW5wdXQvb3V0cHV0IHRlbnNvciwgaW4gcGVybXV0YXRlZCBvcmRlciB0byBhbGlnbiB3aXRoIHRoZSB1bmZvbGRlZCBnbG9iYWwgaW5kZXgsXG4gICAgLy8gaS5lLiBCU05IXG4gICAgLi4uKGlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gM1xuICAgICAgPyBuZXcgQXJyYXk8UHJvZ3JhbVVuaWZvcm0+KHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBbYmF0Y2hTdHJpZGUsIGhpZGRlblNpemUsIGhlYWRTaXplLCAxXSB9KVxuICAgICAgOiBbXSksXG4gICAgLi4uKGlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gNFxuICAgICAgPyBuZXcgQXJyYXk8UHJvZ3JhbVVuaWZvcm0+KHtcbiAgICAgICAgICB0eXBlOiBEYXRhVHlwZS51aW50MzIsXG4gICAgICAgICAgZGF0YTogW2JhdGNoU3RyaWRlLCBoZWFkU2l6ZSwgc2VxdWVuY2VMZW5ndGggKiBoZWFkU2l6ZSwgMV0sXG4gICAgICAgIH0pXG4gICAgICA6IFtdKSxcblxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBpbnB1dHNbMV0uZGltcywgaW5wdXRzWzJdLmRpbXMsIGlucHV0c1szXS5kaW1zLCBpbnB1dHNbMF0uZGltcyksXG4gIF07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBwb3NpdGlvbklkcyA9IGlucHV0VmFyaWFibGUoJ3Bvc2l0aW9uX2lkcycsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBjb3NDYWNoZSA9IGlucHV0VmFyaWFibGUoJ2Nvc19jYWNoZScsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBzaW5DYWNoZSA9IGlucHV0VmFyaWFibGUoJ3Npbl9jYWNoZScsIGlucHV0c1szXS5kYXRhVHlwZSwgaW5wdXRzWzNdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgpO1xuXG4gICAgc2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXMoW1xuICAgICAgeyBuYW1lOiAnc2NhbGUnLCB0eXBlOiAnZjMyJyB9LFxuICAgICAgeyBuYW1lOiAnZ2xvYmFsX3NoYXBlJywgdHlwZTogJ3UzMicsIGxlbmd0aDogZ2xvYmFsU2hhcGUubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdnbG9iYWxfc3RyaWRlcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGdsb2JhbFN0cmlkZXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdpbnB1dF9vdXRwdXRfc3RyaWRlcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGdsb2JhbFN0cmlkZXMubGVuZ3RoIH0sXG4gICAgXSk7XG5cbiAgICByZXR1cm4gYFxuICAgICAgICAke3NoYWRlckhlbHBlci5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBwb3NpdGlvbklkcywgY29zQ2FjaGUsIHNpbkNhY2hlLCBvdXRwdXQpfVxuXG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydChXT1JLR1JPVVBfU0laRSl9XG4gICAgICAgICAgbGV0IGhhbGZfcm90YXJ5X2VtYl9kaW0gPSB1bmlmb3Jtcy4ke2Nvc0NhY2hlLm5hbWV9X3NoYXBlWzFdO1xuICAgICAgICAgIGxldCBic25oID0gZ2xvYmFsX2lkeCAvIHVuaWZvcm1zLmdsb2JhbF9zdHJpZGVzICUgdW5pZm9ybXMuZ2xvYmFsX3NoYXBlO1xuICAgICAgICAgIGxldCBzaXplID0gdW5pZm9ybXMuZ2xvYmFsX3NoYXBlWzBdICogdW5pZm9ybXMuZ2xvYmFsX3N0cmlkZXNbMF07XG4gICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygnc2l6ZScpfVxuXG4gICAgICAgICAgaWYgKGJzbmhbM10gPCBoYWxmX3JvdGFyeV9lbWJfZGltKSB7XG4gICAgICAgICAgICBsZXQgcG9zaXRpb25faWRzX2lkeCA9XG4gICAgICAgICAgICAgICAgJHtwb3NpdGlvbklkcy5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldCgnYnNuaC54eScsIG91dHB1dFZhcmlhYmxlKCcnLCBwb3NpdGlvbklkcy50eXBlLnRlbnNvciwgMikpfTtcbiAgICAgICAgICAgIGxldCBwb3NpdGlvbl9pZCA9XG4gICAgICAgICAgICAgICAgdTMyKCR7cG9zaXRpb25JZHMuZ2V0QnlPZmZzZXQoJ3Bvc2l0aW9uX2lkc19pZHgnKX0pICsgc2VsZWN0KDAsIGJzbmhbMV0sIHBvc2l0aW9uX2lkc19pZHggPT0gMCk7XG4gICAgICAgICAgICBsZXQgaSA9IGRvdChic25oLCB1bmlmb3Jtcy5pbnB1dF9vdXRwdXRfc3RyaWRlcykgKyBzZWxlY3QoMCwgYnNuaFszXSwgJHtpbnRlcmxlYXZlZH0pO1xuICAgICAgICAgICAgbGV0IGogPSBpICsgc2VsZWN0KGhhbGZfcm90YXJ5X2VtYl9kaW0sIDEsICR7aW50ZXJsZWF2ZWR9KTtcbiAgICAgICAgICAgIGxldCByZSA9ICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2knKX0gKiAke2Nvc0NhY2hlLmdldCgncG9zaXRpb25faWQnLCAnYnNuaFszXScpfSAtXG4gICAgICAgICAgICAgICAgJHtpbnB1dC5nZXRCeU9mZnNldCgnaicpfSAqICR7c2luQ2FjaGUuZ2V0KCdwb3NpdGlvbl9pZCcsICdic25oWzNdJyl9O1xuICAgICAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2knLCAncmUnKX1cbiAgICAgICAgICAgIGxldCBpbSA9ICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2knKX0gKiAke3NpbkNhY2hlLmdldCgncG9zaXRpb25faWQnLCAnYnNuaFszXScpfSArXG4gICAgICAgICAgICAgICAgJHtpbnB1dC5nZXRCeU9mZnNldCgnaicpfSAqICR7Y29zQ2FjaGUuZ2V0KCdwb3NpdGlvbl9pZCcsICdic25oWzNdJyl9O1xuICAgICAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2onLCAnaW0nKX1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IGsgPSBkb3QoYnNuaCwgdW5pZm9ybXMuaW5wdXRfb3V0cHV0X3N0cmlkZXMpICsgaGFsZl9yb3RhcnlfZW1iX2RpbTtcbiAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdrJywgaW5wdXQuZ2V0QnlPZmZzZXQoJ2snKSl9XG4gICAgICAgICAgfVxuICAgICAgICB9YDtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdSb3RhcnlFbWJlZGRpbmcnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe1xuICAgICAgICBpbnRlcmxlYXZlZCxcbiAgICAgIH0pLmNhY2hlS2V5LFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuaycsICdyYW5rJywgJ3JhbmsnLCAncmFuayddLFxuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBpbnB1dHNbMF0uZGltcywgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKGdsb2JhbFNoYXBlKSAvIFdPUktHUk9VUF9TSVpFKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHJvdGFyeUVtYmVkZGluZyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVSb3RhcnlFbWJlZGRpbmdQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcykpO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5cbmltcG9ydCB7IGFwcGx5QXR0ZW50aW9uLCBBdHRlbnRpb25NYXNrVHlwZSwgQXR0ZW50aW9uUGFyYW1ldGVycywgQXR0ZW50aW9uUWt2Rm9ybWF0IH0gZnJvbSAnLi9hdHRlbnRpb24nO1xuaW1wb3J0IHsgbWF5YmVUcmFuc3Bvc2VUb0JOU0hBbmRBZGRCaWFzIH0gZnJvbSAnLi9tdWx0aWhlYWQtYXR0ZW50aW9uJztcbmltcG9ydCB7IGNyZWF0ZVNwbGl0UHJvZ3JhbUluZm8sIFNwbGl0QXR0cmlidXRlcyB9IGZyb20gJy4vc3BsaXQnO1xuaW1wb3J0IHsgY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8sIFRyYW5zcG9zZUF0dHJpYnV0ZXMgfSBmcm9tICcuL3RyYW5zcG9zZSc7XG5pbXBvcnQgeyBSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzLCBjcmVhdGVSb3RhcnlFbWJlZGRpbmdQcm9ncmFtSW5mbyB9IGZyb20gJy4vcm90YXJ5LWVtYmVkZGluZyc7XG5pbXBvcnQgeyBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyLCBVbmlmb3Jtc0FycmF5VHlwZSB9IGZyb20gJy4vY29tbW9uJztcbmV4cG9ydCBpbnRlcmZhY2UgR3JvdXBRdWVyeUF0dGVudGlvbkF0dHJpYnV0ZXMge1xuICBudW1IZWFkczogbnVtYmVyO1xuICBrdk51bUhlYWRzOiBudW1iZXI7XG4gIHNjYWxlOiBudW1iZXI7XG4gIHNvZnRjYXA6IG51bWJlcjtcbiAgZG9Sb3Rhcnk6IG51bWJlcjtcbiAgcm90YXJ5SW50ZXJsZWF2ZWQ6IG51bWJlcjtcbiAgc21vb3RoU29mdG1heDogYm9vbGVhbjtcbiAgbG9jYWxXaW5kb3dTaXplOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCB2YWxpZGF0ZUlucHV0cyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IEdyb3VwUXVlcnlBdHRlbnRpb25BdHRyaWJ1dGVzLFxuKTogQXR0ZW50aW9uUGFyYW1ldGVycyA9PiB7XG4gIGlmIChhdHRyaWJ1dGVzLmRvUm90YXJ5ICYmIGlucHV0cy5sZW5ndGggPD0gNykge1xuICAgIHRocm93IG5ldyBFcnJvcignY29zX2NhY2hlIGFuZCBzaW5fY2FjaGUgaW5wdXRzIGFyZSByZXF1aXJlZCBpZiBkb19yb3RhcnkgaXMgc3BlY2lmaWVkJyk7XG4gIH1cbiAgY29uc3QgcXVlcnkgPSBpbnB1dHNbMF07XG4gIGNvbnN0IGtleSA9IGlucHV0c1sxXTtcbiAgY29uc3QgdmFsdWUgPSBpbnB1dHNbMl07XG4gIGNvbnN0IHBhc3RLZXkgPSBpbnB1dHNbM107XG4gIGNvbnN0IHBhc3RWYWx1ZSA9IGlucHV0c1s0XTtcbiAgaWYgKGF0dHJpYnV0ZXMuZG9Sb3RhcnkgIT09IDAgJiYgaW5wdXRzLmxlbmd0aCA8PSA3KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb3NfY2FzdCBhbmQgc2luX2NhY2hlIGFyZSBleHBlY3RlZCBpZiBkb19yb3RhcnkgYXR0cmlidXRlIGlzIG5vbi16ZXJvJyk7XG4gIH1cbiAgaWYgKGF0dHJpYnV0ZXMubG9jYWxXaW5kb3dTaXplICE9PSAtMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignTG9jYWwgYXR0ZW50aW9uIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuICBpZiAoYXR0cmlidXRlcy5zb2Z0Y2FwICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTb2Z0Y2FwIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuICBpZiAoYXR0cmlidXRlcy5yb3RhcnlJbnRlcmxlYXZlZCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignUm90YXJ5IGludGVybGVhdmVkIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuICBpZiAoYXR0cmlidXRlcy5zbW9vdGhTb2Z0bWF4KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTbW9vdGggc29mdG1heCBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbiAgLy8gQWJicmV2aWF0aW9uIGFuZCBNZWFuaW5nczpcbiAgLy8gICBCOiAgICBiYXRjaF9zaXplXG4gIC8vICAgUzogICAgc2VxdWVuY2VfbGVuZ3RoIChpbnB1dCBzZXF1ZW5jZSBsZW5ndGggb2YgcXVlcnkpXG4gIC8vICAgUDogICAgcGFzdF9zZXF1ZW5jZV9sZW5ndGggKHBhc3Qgc2VxdWVuY2UgbGVuZ3RoIG9mIGtleSBvciB2YWx1ZSlcbiAgLy8gICBMOiAgICBrdl9zZXF1ZW5jZV9sZW5ndGggKGlucHV0IHNlcXVlbmNlIGxlbmd0aCBvZiBrZXkgb3IgdmFsdWUpXG4gIC8vICAgTTogICAgbWF4X3NlcXVlbmNlX2xlbmd0aFxuICAvLyAgIFQ6ICAgIHRvdGFsX3NlcXVlbmNlX2xlbmd0aCA9IHBhc3Rfc2VxdWVuY2VfbGVuZ3RoICsga3Zfc2VxdWVuY2VfbGVuZ3RoXG4gIC8vICAgTjogICAgbnVtX2hlYWRzXG4gIC8vICAgSDogICAgaGVhZCBzaXplIGZvciBRIGFuZCBLLCBha2EgcV9oZWFkX3NpemUgb3Iga19oZWFkX3NpemUgb3IgcWtfaGVhZF9zaXplXG4gIC8vICAgSF92OiAgdl9oZWFkX3NpemVcbiAgLy8gICBEX2k6ICBpbnB1dCBoaWRkZW4gc2l6ZVxuICAvLyAgIEQ6ICAgIGhpZGRlbiBzaXplIGZvciBRIGFuZCBLIChEID0gTiAqIEgpLCBha2EgcV9oaWRkZW5fc2l6ZSBvciBrX2hpZGRlbl9zaXplIG9yIHFrX2hpZGRlbl9zaXplXG4gIC8vICAgRF92OiAgdl9oaWRkZW5fc2l6ZSA9IG51bV9oZWFkcyAqIHZfaGVhZF9zaXplXG5cbiAgLy8gICAgIHBhc3Rfa2V5ICAgICAgICAgICAgICAgICAgIDogKEIsIE4sIFMqLCBIKVxuICAvLyAgICAgcGFzdF92YWx1ZSAgICAgICAgICAgICAgICAgOiAoQiwgTiwgUyosIEgpXG4gIC8vIFdoZW4gbm8gcGFja2luZyBmb3IgcS9rL3Y6XG4gIC8vICAgICBxdWVyeSAgICAgICAgICAgIChRKSAgICAgICA6IChCLCBTLCBEKVxuICAvLyAgICAga2V5ICAgICAgICAgICAgICAoSykgICAgICAgOiAoQiwgTCwgRCkgb3IgKEIsIE4sIFMqLCBIKVxuICAvLyAgICAgdmFsdWUgICAgICAgICAgICAoVikgICAgICAgOiAoQiwgTCwgRF92KSBvciAoQiwgTiwgUyosIEgpXG4gIC8vIFdoZW4gcGFja2VkIGt2IGlzIHVzZWQ6XG4gIC8vICAgICBxdWVyeSAgICAgICAgICAgIChRKSAgICAgICA6IChCLCBTLCBEKVxuICAvLyAgICAga2V5ICAgICAgICAgICAgICAoSykgICAgICAgOiAoQiwgTCwgTiwgMiwgSClcbiAgLy8gICAgIHZhbHVlICAgICAgICAgICAgKFYpICAgICAgIDogTm9uZVxuICAvLyBXaGVuIHBhY2tlZCBxa3YgaXMgdXNlZDpcbiAgLy8gICAgIHF1ZXJ5ICAgICAgICAgICAgKFEpICAgICAgIDogKEIsIEwsIE4sIDMsIEgpIG9yIChCLCBTLCAzKkQpXG4gIC8vICAgICBrZXkgICAgICAgICAgICAgIChLKSAgICAgICA6IE5vbmVcbiAgLy8gICAgIHZhbHVlICAgICAgICAgICAgKFYpICAgICAgIDogTm9uZVxuXG4gIGlmIChxdWVyeS5kaW1zLmxlbmd0aCAhPT0gMyAmJiBxdWVyeS5kaW1zLmxlbmd0aCAhPT0gNSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgcXVlcnkgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAzIG9yIDUgZGltZW5zaW9ucycpO1xuICB9XG5cbiAgY29uc3QgZG1taGFQYWNraW5nID0gZmFsc2U7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IHF1ZXJ5LmRpbXNbMF07XG4gIGNvbnN0IHNlcXVlbmNlTGVuZ3RoID0gcXVlcnkuZGltc1sxXTtcbiAgbGV0IGhpZGRlblNpemUgPVxuICAgIHF1ZXJ5LmRpbXMubGVuZ3RoID09PSAzID8gKGRtbWhhUGFja2luZyA/IHF1ZXJ5LmRpbXNbMl0gLyAzIDogcXVlcnkuZGltc1syXSkgOiBhdHRyaWJ1dGVzLm51bUhlYWRzICogcXVlcnkuZGltc1s0XTtcbiAgbGV0IGt2U2VxdWVuY2VMZW5ndGggPSBzZXF1ZW5jZUxlbmd0aDtcblxuICBsZXQgcGFzdFNlcXVlbmNlTGVuZ3RoID0gMDtcbiAgY29uc3QgcGFja2VkUUtWID0gIWtleSB8fCBrZXkuZGltcy5sZW5ndGggPT09IDA7XG4gIGNvbnN0IGhlYWRTaXplID0gIXBhY2tlZFFLVlxuICAgID8gTWF0aC5mbG9vcihoaWRkZW5TaXplIC8gYXR0cmlidXRlcy5udW1IZWFkcylcbiAgICA6IE1hdGguZmxvb3IoaGlkZGVuU2l6ZSAvIChhdHRyaWJ1dGVzLm51bUhlYWRzICsgMiAqIGF0dHJpYnV0ZXMua3ZOdW1IZWFkcykpO1xuICBpZiAocGFja2VkUUtWKSB7XG4gICAgaGlkZGVuU2l6ZSA9IGhlYWRTaXplICogYXR0cmlidXRlcy5udW1IZWFkcztcbiAgfVxuICBjb25zdCBoYXNQYXN0S2V5ID0gcGFzdEtleSAmJiBwYXN0S2V5LmRpbXMubGVuZ3RoICE9PSAwO1xuICBjb25zdCBoYXNQYXN0VmFsdWUgPSBwYXN0VmFsdWUgJiYgcGFzdFZhbHVlLmRpbXMubGVuZ3RoICE9PSAwO1xuICAvLyBDdXJyZW50bHkgdGhlIG9ubnhydW50aW1lIEdRQSBzcGVjaWZpY2F0aW9uIG9ubHkgc3VwcG9ydCBrZXkvdmFsdWUgQk5TSCBmb3JtYXQuXG4gIGNvbnN0IGlzUGFzdGt2QlNOSCA9XG4gICAgaGFzUGFzdEtleSAmJlxuICAgIHBhc3RLZXkuZGltcy5sZW5ndGggPT09IDQgJiZcbiAgICBwYXN0S2V5LmRpbXNbMF0gPT09IGJhdGNoU2l6ZSAmJlxuICAgIHBhc3RLZXkuZGltc1sxXSAhPT0gYXR0cmlidXRlcy5rdk51bUhlYWRzICYmXG4gICAgcGFzdEtleS5kaW1zWzJdID09PSBhdHRyaWJ1dGVzLmt2TnVtSGVhZHMgJiZcbiAgICBwYXN0S2V5LmRpbXNbM10gPT09IGhlYWRTaXplO1xuXG4gIGlmIChpc1Bhc3RrdkJTTkgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0JTTkggcGFzdEtleS9wYXN0VmFsdWUgaXMgbm90IHN1cHBvcnRlZCcpO1xuICB9XG4gIGlmIChoYXNQYXN0S2V5ICYmIGhhc1Bhc3RWYWx1ZSkge1xuICAgIGlmIChwYXN0S2V5LmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdF9rZXlcIiBpcyBleHBlY3RlZCB0byBoYXZlIDQgZGltZW5zaW9ucycpO1xuICAgIH1cbiAgICBpZiAocGFzdFZhbHVlLmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdF92YWx1ZVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgNCBkaW1lbnNpb25zJyk7XG4gICAgfVxuICAgIHBhc3RTZXF1ZW5jZUxlbmd0aCA9IHBhc3RLZXkuZGltc1syXTtcbiAgfSBlbHNlIGlmIChoYXNQYXN0S2V5IHx8IGhhc1Bhc3RWYWx1ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0X2tleVwiIGFuZCBcInBhc3RfdmFsdWVcIiBzaGFsbCBiZSBib3RoIHByZXNlbnQgb3IgYm90aCBhYnNlbnQnKTtcbiAgfVxuXG4gIGxldCBxa3ZGb3JtYXQ6IEF0dGVudGlvblFrdkZvcm1hdCA9IEF0dGVudGlvblFrdkZvcm1hdC5xa3ZCTlNIO1xuICBpZiAoa2V5ICYmIGtleS5kaW1zLmxlbmd0aCA+IDApIHtcbiAgICBpZiAocXVlcnkuZGltcy5sZW5ndGggIT09IDMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgMyBkaW1lbnNpb25zIHdoZW4ga2V5IGlzIGdpdmVuJyk7XG4gICAgfVxuICAgIGlmIChrZXkuZGltcy5sZW5ndGggPCAzIHx8IGtleS5kaW1zLmxlbmd0aCA+IDUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJrZXlcIiBpcyBleHBlY3RlZCB0byBoYXZlIDMsIDQsIG9yIDUgZGltZW5zaW9ucycpO1xuICAgIH1cbiAgICBpZiAocXVlcnkuZGltc1swXSAhPT0ga2V5LmRpbXNbMF0pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGFuZCBcImtleVwiIHNoYWxsIGhhdmUgc2FtZSBkaW0gMCAoYmF0Y2ggc2l6ZSknKTtcbiAgICB9XG5cbiAgICBpZiAoa2V5LmRpbXMubGVuZ3RoID09PSAzKSB7XG4gICAgICBpZiAocXVlcnkuZGltc1syXSAlIGtleS5kaW1zWzJdICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRGltZW5zaW9uIDIgb2YgXCJxdWVyeVwiIHNob3VsZCBiZSBhIG11bHRpcGxlIG9mIFwia2V5XCInKTtcbiAgICAgIH1cbiAgICAgIGt2U2VxdWVuY2VMZW5ndGggPSBrZXkuZGltc1sxXTtcbiAgICB9IGVsc2UgaWYgKGtleS5kaW1zLmxlbmd0aCA9PT0gNSkge1xuICAgICAgaWYgKGtleS5kaW1zWzJdICE9PSBhdHRyaWJ1dGVzLm51bUhlYWRzIHx8IGtleS5kaW1zWzNdICE9PSAyIHx8IGtleS5kaW1zWzRdICE9PSBoZWFkU2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdCBcImtleVwiIHNoYXBlIChiYXRjaF9zaXplLCBrdl9zZXF1ZW5jZV9sZW5ndGgsIG51bV9oZWFkcywgMiwgaGVhZF9zaXplKSBmb3IgcGFja2VkIGt2Jyk7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3QgXCJ2YWx1ZVwiIGJlIG5vbmUgd2hlbiBcImtleVwiIGhhcyBwYWNrZWQga3YgZm9ybWF0LicpO1xuICAgICAgfVxuICAgICAga3ZTZXF1ZW5jZUxlbmd0aCA9IGtleS5kaW1zWzFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBrZXlfZGltcy5zaXplKCkgPT0gNCAoY3Jvc3MtYXR0ZW50aW9uIHdpdGggcGFzdF9rZXkpXG4gICAgICBpZiAoa2V5LmRpbXNbMV0gIT09IGF0dHJpYnV0ZXMubnVtSGVhZHMgfHwga2V5LmRpbXNbM10gIT09IGhlYWRTaXplKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0IFwia2V5XCIgc2hhcGUgKGJhdGNoX3NpemUsIG51bV9oZWFkcywga3Zfc2VxdWVuY2VfbGVuZ3RoLCBoZWFkX3NpemUpIGZvciBwYXN0X2tleScpO1xuICAgICAgfVxuICAgICAga3ZTZXF1ZW5jZUxlbmd0aCA9IGtleS5kaW1zWzJdO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBwYWNrZWQgUUtWXG4gICAgaWYgKHF1ZXJ5LmRpbXMubGVuZ3RoICE9PSAzICYmIHF1ZXJ5LmRpbXMubGVuZ3RoICE9PSA1KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicXVlcnlcIiBpcyBleHBlY3RlZCB0byBoYXZlIDMgb3IgNSBkaW1lbnNpb25zIHdoZW4ga2V5IGlzIGVtcHR5Jyk7XG4gICAgfVxuICAgIGlmIChxdWVyeS5kaW1zLmxlbmd0aCA9PT0gNSAmJiAocXVlcnkuZGltc1syXSAhPT0gYXR0cmlidXRlcy5udW1IZWFkcyB8fCBxdWVyeS5kaW1zWzNdICE9PSAzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3QgXCJxdWVyeVwiIHNoYXBlIChiYXRjaF9zaXplLCBrdl9zZXF1ZW5jZV9sZW5ndGgsIG51bV9oZWFkcywgMywgaGVhZF9zaXplKSBmb3IgcGFja2VkIGt2Jyk7XG4gICAgfVxuXG4gICAgcWt2Rm9ybWF0ID0gQXR0ZW50aW9uUWt2Rm9ybWF0LnFrdkJTTjNIO1xuICB9XG5cbiAgY29uc3QgbWFza1R5cGU6IEF0dGVudGlvbk1hc2tUeXBlID0gQXR0ZW50aW9uTWFza1R5cGUubm9uZTtcbiAgbGV0IHBhc3NQYXN0SW5LdiA9IGZhbHNlO1xuICBsZXQgdkhpZGRlblNpemUgPSBhdHRyaWJ1dGVzLmt2TnVtSGVhZHMgPyBoZWFkU2l6ZSAqIGF0dHJpYnV0ZXMua3ZOdW1IZWFkcyA6IGhpZGRlblNpemU7XG4gIGlmICh2YWx1ZSAmJiB2YWx1ZS5kaW1zLmxlbmd0aCA+IDApIHtcbiAgICBpZiAodmFsdWUuZGltcy5sZW5ndGggIT09IDMgJiYgdmFsdWUuZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJ2YWx1ZVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgMyBvciA0IGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBpZiAocXVlcnkuZGltc1swXSAhPT0gdmFsdWUuZGltc1swXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInF1ZXJ5XCIgYW5kIFwidmFsdWVcIiBzaGFsbCBoYXZlIHNhbWUgZGltIDAgKGJhdGNoX3NpemUpJyk7XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlLmRpbXMubGVuZ3RoID09PSAzKSB7XG4gICAgICBpZiAoa3ZTZXF1ZW5jZUxlbmd0aCAhPT0gdmFsdWUuZGltc1sxXSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwia2V5XCIgYW5kIFwidmFsdWVcIiBzaGFsbCBoYXZlIHRoZSBzYW1lIGRpbSAxIChrdl9zZXF1ZW5jZV9sZW5ndGgpJyk7XG4gICAgICB9XG4gICAgICB2SGlkZGVuU2l6ZSA9IHZhbHVlLmRpbXNbMl07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChrdlNlcXVlbmNlTGVuZ3RoICE9PSB2YWx1ZS5kaW1zWzJdKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0X2tleVwiIGFuZCBcInBhc3RfdmFsdWVcIiBzaGFsbCBoYXZlIHRoZSBzYW1lIGRpbSAyIChrdl9zZXF1ZW5jZV9sZW5ndGgpJyk7XG4gICAgICB9XG4gICAgICB2SGlkZGVuU2l6ZSA9IHZhbHVlLmRpbXNbMV0gKiB2YWx1ZS5kaW1zWzNdO1xuICAgICAgcGFzc1Bhc3RJbkt2ID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgLy8gU3BlYyByZXF1aXJlcyAxRCBzaGFwZSAoYmF0Y2hfc2l6ZSksIGJ1dCBvbGRlciBtb2RlbCBidWlsZGVycyBtYXkgYWRkIHVuaXRcbiAgLy8gZGltZW5zaW9ucyAoZS5nLiBbQiwgMV0gaW5zdGVhZCBvZiBbQl0pLiBBbGxvdyBzaGFwZXMgd2hlcmUgZWFjaCBkaW0gaXMgMSBvciBiYXRjaFNpemUuXG4gIGNvbnN0IHNlcWxMZW5zID0gaW5wdXRzLmxlbmd0aCA+IDQgPyBpbnB1dHNbNV0gOiB1bmRlZmluZWQ7XG4gIGlmIChzZXFsTGVucykge1xuICAgIGlmIChzZXFsTGVucy5kaW1zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzZXFsZW5zX2sgbXVzdCBiZSBhdCBsZWFzdCAxRCwgZ290IHNjYWxhci4nKTtcbiAgICB9XG4gICAgY29uc3Qgc2VxbExlblNpemUgPSBzZXFsTGVucy5kaW1zLnJlZHVjZSgoYSwgYikgPT4gYSAqIGIsIDEpO1xuICAgIGlmIChzZXFsTGVuU2l6ZSAhPT0gYmF0Y2hTaXplKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHNlcWxlbnNfayBtdXN0IGhhdmUgYmF0Y2hfc2l6ZSAoJHtiYXRjaFNpemV9KSBlbGVtZW50cywgZ290ICR7c2VxbExlblNpemV9LmApO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlcWxMZW5zLmRpbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChzZXFsTGVucy5kaW1zW2ldICE9PSAxICYmIHNlcWxMZW5zLmRpbXNbaV0gIT09IGJhdGNoU2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYHNlcWxlbnNfayBoYXMgdW5leHBlY3RlZCBzaGFwZS4gRWFjaCBkaW1lbnNpb24gbXVzdCBiZSAxIG9yIGJhdGNoX3NpemUgKCR7YmF0Y2hTaXplfSksIGdvdCBkaW1zWyR7aX1dID0gJHtzZXFsTGVucy5kaW1zW2ldfS5gLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBjb25zdCB0b3RhbFNlcXVlbmNlTGVuZ3RoID0gLTE7XG4gIGNvbnN0IG1heFNlcXVlbmNlTGVuZ3RoID0gLTE7XG4gIGNvbnN0IGJyb2FkY2FzdFJlc1Bvc0JpYXMgPSBmYWxzZTtcblxuICByZXR1cm4ge1xuICAgIGJhdGNoU2l6ZSxcbiAgICBzZXF1ZW5jZUxlbmd0aCxcbiAgICBwYXN0U2VxdWVuY2VMZW5ndGgsXG4gICAga3ZTZXF1ZW5jZUxlbmd0aCxcbiAgICB0b3RhbFNlcXVlbmNlTGVuZ3RoLFxuICAgIG1heFNlcXVlbmNlTGVuZ3RoLFxuICAgIGlucHV0SGlkZGVuU2l6ZTogMCxcbiAgICBoaWRkZW5TaXplLFxuICAgIHZIaWRkZW5TaXplLFxuICAgIGhlYWRTaXplLFxuICAgIHZIZWFkU2l6ZTogTWF0aC5mbG9vcih2SGlkZGVuU2l6ZSAvIGF0dHJpYnV0ZXMua3ZOdW1IZWFkcyksXG4gICAgbnVtSGVhZHM6IGF0dHJpYnV0ZXMubnVtSGVhZHMsXG4gICAga3ZOdW1IZWFkczogYXR0cmlidXRlcy5rdk51bUhlYWRzLFxuICAgIG5SZXBzOiBhdHRyaWJ1dGVzLm51bUhlYWRzIC8gYXR0cmlidXRlcy5rdk51bUhlYWRzLFxuICAgIHBhc3RQcmVzZW50U2hhcmVCdWZmZXI6IGZhbHNlLFxuICAgIG1hc2tUeXBlLFxuICAgIHNjYWxlOiBhdHRyaWJ1dGVzLnNjYWxlLFxuICAgIGJyb2FkY2FzdFJlc1Bvc0JpYXMsXG4gICAgcGFzc1Bhc3RJbkt2LFxuICAgIHFrdkZvcm1hdCxcbiAgfTtcbn07XG5cbmNvbnN0IHdlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZTogVHJhbnNwb3NlQXR0cmlidXRlcyA9IGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IHBlcm06IFswLCAyLCAxLCAzXSB9KTtcblxuY29uc3QgbWF5YmVUcmFuc3Bvc2VUb0JOU0ggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGlucHV0OiBUZW5zb3JWaWV3LCBwYXJhbXM6IEF0dGVudGlvblBhcmFtZXRlcnMpID0+IHtcbiAgbGV0IHJlc2hhcGVkSW5wdXQgPSBpbnB1dDtcbiAgY29uc3QgbnVtSGVhZHMgPSBwYXJhbXMua3ZOdW1IZWFkcyE7XG4gIGlmIChpbnB1dC5kaW1zLmxlbmd0aCA9PT0gMyAmJiBwYXJhbXMua3ZTZXF1ZW5jZUxlbmd0aCAhPT0gMCkge1xuICAgIHJlc2hhcGVkSW5wdXQgPSBpbnB1dC5yZXNoYXBlKFtwYXJhbXMuYmF0Y2hTaXplLCBwYXJhbXMua3ZTZXF1ZW5jZUxlbmd0aCwgbnVtSGVhZHMsIHBhcmFtcy5oZWFkU2l6ZV0pO1xuICAgIHJlc2hhcGVkSW5wdXQgPSBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8ocmVzaGFwZWRJbnB1dCwgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlLnBlcm0pLCB7XG4gICAgICBpbnB1dHM6IFtyZXNoYXBlZElucHV0XSxcbiAgICAgIG91dHB1dHM6IFstMV0sXG4gICAgfSlbMF07XG4gIH1cblxuICByZXR1cm4gcmVzaGFwZWRJbnB1dDtcbn07XG5cbmNvbnN0IGdlbmVyYXRlUG9zaXRpb25JZHNQcm9ncmFtSW5mbyA9IChcbiAgYmF0Y2hTaXplOiBudW1iZXIsXG4gIHNlcXVlbmNlTGVuZ3RoOiBudW1iZXIsXG4gIHNlcUxlbnM6IFRlbnNvclZpZXcsXG4gIHRvdGFsU2VxTGVuOiBUZW5zb3JWaWV3LFxuKSA9PiB7XG4gIGNvbnN0IG91dHB1dERhdGFUeXBlID0gRGF0YVR5cGUuaW50NjQ7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWyd0eXBlJywgJ3R5cGUnXTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbYmF0Y2hTaXplICogc2VxdWVuY2VMZW5ndGhdO1xuICBjb25zdCBvdXRwdXRTaXplID0gYmF0Y2hTaXplICogc2VxdWVuY2VMZW5ndGg7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBiYXRjaFNpemUgfSxcbiAgXTtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3Qgc2VxTGVuc0lucHV0SGVscGVyID0gaW5wdXRWYXJpYWJsZSgnc2VxX2xlbnMnLCBzZXFMZW5zLmRhdGFUeXBlLCBzZXFMZW5zLmRpbXMpO1xuICAgIGNvbnN0IHRvdGFsU2VxTGVuSW5wdXRIZWxwZXIgPSBpbnB1dFZhcmlhYmxlKCd0b3RhbF9zZXFfbGVucycsIHRvdGFsU2VxTGVuLmRhdGFUeXBlLCB0b3RhbFNlcUxlbi5kaW1zKTtcbiAgICBjb25zdCBwb3NpdGlvbklkc0hlbHBlciA9IG91dHB1dFZhcmlhYmxlKCdwb3NfaWRzJywgb3V0cHV0RGF0YVR5cGUsIG91dHB1dFNoYXBlKTtcblxuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3NlcXVlbmNlX2xlbmd0aCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdiYXRjaF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuXG4gICAgcmV0dXJuIGBcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyhzZXFMZW5zSW5wdXRIZWxwZXIsIHRvdGFsU2VxTGVuSW5wdXRIZWxwZXIsIHBvc2l0aW9uSWRzSGVscGVyKX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICBsZXQgdG90YWxfc2VxdWVuY2VfbGVuZ3RoID0gdTMyKCR7dG90YWxTZXFMZW5JbnB1dEhlbHBlci5nZXRCeU9mZnNldCgnMCcpfSk7XG4gICAgbGV0IGlzX3N1YnNlcXVlbnRfcHJvbXB0ID0gdW5pZm9ybXMuc2VxdWVuY2VfbGVuZ3RoID4gMSAmJiB1bmlmb3Jtcy5zZXF1ZW5jZV9sZW5ndGggIT0gdG90YWxfc2VxdWVuY2VfbGVuZ3RoO1xuICAgIGxldCBpc19maXJzdF9wcm9tcHQgPSAhaXNfc3Vic2VxdWVudF9wcm9tcHQgJiYgdW5pZm9ybXMuc2VxdWVuY2VfbGVuZ3RoID09IHRvdGFsX3NlcXVlbmNlX2xlbmd0aDtcbiAgICBsZXQgYmF0Y2hfaWR4ID0gZ2xvYmFsX2lkeCAvIHVuaWZvcm1zLnNlcXVlbmNlX2xlbmd0aDtcbiAgICBsZXQgc2VxdWVuY2VfaWR4ID0gaTMyKGdsb2JhbF9pZHggJSB1bmlmb3Jtcy5zZXF1ZW5jZV9sZW5ndGgpO1xuICAgIHZhciBwb3NfaWQ6IGkzMiA9IDA7XG4gICAgbGV0IHNlcWxlbiA9ICR7c2VxTGVuc0lucHV0SGVscGVyLmdldEJ5T2Zmc2V0KCdiYXRjaF9pZHgnKX07XG4gICAgbGV0IHRvdGFsX3NlcWxlbiA9IHNlcWxlbiArIDE7XG4gICAgaWYgKGlzX2ZpcnN0X3Byb21wdCkge1xuICAgICAgaWYgKHNlcXVlbmNlX2lkeCA8IHRvdGFsX3NlcWxlbikge1xuICAgICAgICBwb3NfaWQgPSBzZXF1ZW5jZV9pZHg7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwb3NfaWQgPSAxO1xuICAgICAgfVxuICAgICAgJHtwb3NpdGlvbklkc0hlbHBlci5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICdwb3NfaWQnKX1cbiAgICB9IGVsc2UgaWYgKGlzX3N1YnNlcXVlbnRfcHJvbXB0KSB7XG4gICAgICBsZXQgcGFzdF9zZXFsZW4gPSB0b3RhbF9zZXFsZW4gLSBpMzIodW5pZm9ybXMuc2VxdWVuY2VfbGVuZ3RoKTtcbiAgICAgIGlmIChwYXN0X3NlcWxlbiArIHNlcXVlbmNlX2lkeCA8IHRvdGFsX3NlcWxlbikge1xuICAgICAgICBwb3NfaWQgPSBwYXN0X3NlcWxlbiArIHNlcXVlbmNlX2lkeDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBvc19pZCA9IDE7XG4gICAgICB9XG4gICAgICAke3Bvc2l0aW9uSWRzSGVscGVyLnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3Bvc19pZCcpfVxuICAgIH0gZWxzZSBpZiAoZ2xvYmFsX2lkeCA8IHVuaWZvcm1zLmJhdGNoX3NpemUpIHtcbiAgICAgICR7cG9zaXRpb25JZHNIZWxwZXIuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAnc2VxbGVuJyl9XG4gICAgfTtcbiAgfVxuICBgO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdHZW5lcmF0ZVBvc2l0aW9uSWRzJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtiYXRjaFNpemV9OyR7c2VxdWVuY2VMZW5ndGh9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBvdXRwdXREYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgZ3JvdXBRdWVyeUF0dGVudGlvbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogR3JvdXBRdWVyeUF0dGVudGlvbkF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgcGFyYW1zID0gdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBpZiAoY29udGV4dC5pbnB1dHNbMF0uZGltcy5sZW5ndGggPT09IDUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1BhY2tlZCBRS1YgaXMgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICBpZiAoY29udGV4dC5pbnB1dHNbMV0/LmRpbXMubGVuZ3RoID09PSA1KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQYWNrZWQgS1YgaXMgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICBjb25zdCBxID0gY29udGV4dC5pbnB1dHNbMF07XG4gIGNvbnN0IGsgPSBjb250ZXh0LmlucHV0c1sxXSAmJiBjb250ZXh0LmlucHV0c1sxXS5kaW1zLmxlbmd0aCA+IDAgPyBjb250ZXh0LmlucHV0c1sxXSA6IHVuZGVmaW5lZDtcbiAgY29uc3QgdiA9IGNvbnRleHQuaW5wdXRzWzJdICYmIGNvbnRleHQuaW5wdXRzWzJdLmRpbXMubGVuZ3RoID4gMCA/IGNvbnRleHQuaW5wdXRzWzJdIDogdW5kZWZpbmVkO1xuICBjb25zdCBwYXN0S2V5ID0gY29udGV4dC5pbnB1dHNbM10gJiYgY29udGV4dC5pbnB1dHNbM10uZGltcy5sZW5ndGggIT09IDAgPyBjb250ZXh0LmlucHV0c1szXSA6IHVuZGVmaW5lZDtcbiAgY29uc3QgcGFzdFZhbHVlID0gY29udGV4dC5pbnB1dHNbNF0gJiYgY29udGV4dC5pbnB1dHNbNF0uZGltcy5sZW5ndGggIT09IDAgPyBjb250ZXh0LmlucHV0c1s0XSA6IHVuZGVmaW5lZDtcbiAgY29uc3Qgc2VxTGVucyA9IGNvbnRleHQuaW5wdXRzLmxlbmd0aCA+IDQgPyBjb250ZXh0LmlucHV0c1s1XSA6IHVuZGVmaW5lZDtcbiAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0ID0gY29udGV4dC5pbnB1dHMubGVuZ3RoID4gNSA/IGNvbnRleHQuaW5wdXRzWzZdIDogdW5kZWZpbmVkO1xuICBjb25zdCBrdk51bUhlYWRzID0gcGFyYW1zLmt2TnVtSGVhZHMgPyBwYXJhbXMua3ZOdW1IZWFkcyA6IHBhcmFtcy5udW1IZWFkcztcblxuICAvLyBUT0RPIFJlbW92ZSBleHBsaWNpdCBzcGxpdCBvcGVyYXRpb24gYW5kIHVzZSBpbmRleGluZyBpbiBBdHRlbnRpb24gaW1wbGVtZW50YXRpb24gdG8gYXZvaWQgb3ZlcmhlYWQuXG5cbiAgY29uc3Qgc3BsaXRBdHRyaWJ1dGVzOiBTcGxpdEF0dHJpYnV0ZXMgPSBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe1xuICAgIGF4aXM6IDIsXG4gICAgbnVtT3V0cHV0czogMyxcbiAgICBzcGxpdFNpemVzOiBbcGFyYW1zLm51bUhlYWRzICogcGFyYW1zLmhlYWRTaXplLCBrdk51bUhlYWRzICogcGFyYW1zLmhlYWRTaXplLCBrdk51bUhlYWRzICogcGFyYW1zLmhlYWRTaXplXSxcbiAgfSk7XG4gIGNvbnN0IFtxdWVyeSwga2V5LCB2YWx1ZV0gPVxuICAgICFrICYmICF2XG4gICAgICA/IGNvbnRleHQuY29tcHV0ZShjcmVhdGVTcGxpdFByb2dyYW1JbmZvKFtxXSwgc3BsaXRBdHRyaWJ1dGVzKSwgeyBpbnB1dHM6IFtxXSwgb3V0cHV0czogWy0xLCAtMSwgLTFdIH0pXG4gICAgICA6IFtxLCBrISwgdiFdO1xuICBsZXQgcVJvdGFyeTogVGVuc29yVmlldyB8IHVuZGVmaW5lZDtcbiAgbGV0IGtSb3Rhcnk6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQ7XG4gIGlmIChhdHRyaWJ1dGVzLmRvUm90YXJ5KSB7XG4gICAgY29uc3QgcG9zSWRzID0gY29udGV4dC5jb21wdXRlKFxuICAgICAgZ2VuZXJhdGVQb3NpdGlvbklkc1Byb2dyYW1JbmZvKHBhcmFtcy5iYXRjaFNpemUsIHBhcmFtcy5zZXF1ZW5jZUxlbmd0aCwgc2VxTGVucyEsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCEpLFxuICAgICAgeyBpbnB1dHM6IFtzZXFMZW5zISwgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0IV0sIG91dHB1dHM6IFstMV0gfSxcbiAgICApWzBdO1xuICAgIGNvbnN0IGNvc0NhY2hlID0gY29udGV4dC5pbnB1dHNbN107XG4gICAgY29uc3Qgc2luQ2FjaGUgPSBjb250ZXh0LmlucHV0c1s4XTtcbiAgICBjb25zdCBxUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlczogUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyA9IGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7XG4gICAgICBpbnRlcmxlYXZlZDogYXR0cmlidXRlcy5yb3RhcnlJbnRlcmxlYXZlZCAhPT0gMCxcbiAgICAgIG51bUhlYWRzOiBwYXJhbXMubnVtSGVhZHMsXG4gICAgICByb3RhcnlFbWJlZGRpbmdEaW06IDAsXG4gICAgICBzY2FsZTogYXR0cmlidXRlcy5zY2FsZSxcbiAgICB9KTtcbiAgICBjb25zdCBpbnB1dHMgPSBbcXVlcnksIHBvc0lkcywgY29zQ2FjaGUsIHNpbkNhY2hlXTtcbiAgICBjb25zdCBvdXRwdXRzID0gWy0xXTtcbiAgICBxUm90YXJ5ID0gY29udGV4dC5jb21wdXRlKGNyZWF0ZVJvdGFyeUVtYmVkZGluZ1Byb2dyYW1JbmZvKGlucHV0cywgcVJvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXMpLCB7XG4gICAgICBpbnB1dHMsXG4gICAgICBvdXRwdXRzLFxuICAgIH0pWzBdO1xuICAgIGlucHV0cy5zcGxpY2UoMCwgMSwga2V5KTtcbiAgICBjb25zdCBrUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlczogUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyA9IGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7XG4gICAgICBpbnRlcmxlYXZlZDogYXR0cmlidXRlcy5yb3RhcnlJbnRlcmxlYXZlZCAhPT0gMCxcbiAgICAgIG51bUhlYWRzOiBwYXJhbXMua3ZOdW1IZWFkcyEsXG4gICAgICByb3RhcnlFbWJlZGRpbmdEaW06IDAsXG4gICAgICBzY2FsZTogYXR0cmlidXRlcy5zY2FsZSxcbiAgICB9KTtcbiAgICBrUm90YXJ5ID0gY29udGV4dC5jb21wdXRlKGNyZWF0ZVJvdGFyeUVtYmVkZGluZ1Byb2dyYW1JbmZvKGlucHV0cywga1JvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXMpLCB7XG4gICAgICBpbnB1dHMsXG4gICAgICBvdXRwdXRzLFxuICAgIH0pWzBdO1xuICB9XG4gIGNvbnN0IFEgPSBtYXliZVRyYW5zcG9zZVRvQk5TSEFuZEFkZEJpYXMoXG4gICAgY29udGV4dCxcbiAgICBwYXJhbXMuYmF0Y2hTaXplLFxuICAgIHBhcmFtcy5udW1IZWFkcyxcbiAgICBwYXJhbXMuc2VxdWVuY2VMZW5ndGgsXG4gICAgcGFyYW1zLmhlYWRTaXplLFxuICAgIGF0dHJpYnV0ZXMuZG9Sb3RhcnkgPyBxUm90YXJ5ISA6IHF1ZXJ5LFxuICAgIHVuZGVmaW5lZCxcbiAgICAwLFxuICApO1xuICBjb25zdCBLID0gbWF5YmVUcmFuc3Bvc2VUb0JOU0goY29udGV4dCwgYXR0cmlidXRlcy5kb1JvdGFyeSA/IGtSb3RhcnkhIDoga2V5LCBwYXJhbXMpO1xuICBjb25zdCBWID0gbWF5YmVUcmFuc3Bvc2VUb0JOU0goY29udGV4dCwgdmFsdWUsIHBhcmFtcyk7XG5cbiAgYXBwbHlBdHRlbnRpb24oXG4gICAgY29udGV4dCxcbiAgICBRLFxuICAgIEssXG4gICAgVixcbiAgICB1bmRlZmluZWQsXG4gICAgdW5kZWZpbmVkLFxuICAgIHBhc3RLZXksXG4gICAgcGFzdFZhbHVlLFxuICAgIHVuZGVmaW5lZCxcbiAgICBwYXJhbXMsXG4gICAgc2VxTGVucyxcbiAgICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQsXG4gICk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQgeyBjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyB9IGZyb20gJy4vdHJhbnNwb3NlJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldE1heENvbXBvbmVudHMsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHN1bVZlY3RvcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5zdGFuY2VOb3JtQXR0cmlidXRlcyB7XG4gIGVwc2lsb246IG51bWJlcjtcbiAgZm9ybWF0OiAnTkhXQycgfCAnTkNIVyc7XG59XG5cbmNvbnN0IGNvbXB1dGVDaGFubmVsU2NhbGVTaGlmdCA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIGlucHV0OiBUZW5zb3JWaWV3LFxuICBzY2FsZTogVGVuc29yVmlldyxcbiAgYmlhczogVGVuc29yVmlldyxcbiAgbjogbnVtYmVyLFxuICBoOiBudW1iZXIsXG4gIGM6IG51bWJlcixcbiAgZXBzaWxvbjogbnVtYmVyLFxuKSA9PiB7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKGgpO1xuICBjb25zdCBmMzJUeXBlID0gY29tcG9uZW50cyA9PT0gMSA/ICdmMzInIDogYHZlYyR7Y29tcG9uZW50c31mYDtcbiAgY29uc3Qgd2dUeXBlID0gY29tcG9uZW50cyA9PT0gMSA/ICd2ZWMyZicgOiBgbWF0Mngke2NvbXBvbmVudHN9ZmA7XG4gIGNvbnN0IHVuaXRzT2ZXb3JrID0gbiAqIGM7XG4gIGxldCB3b3JrZ3JvdXBTaXplID0gNjQ7XG4gIGlmICh1bml0c09mV29yayA9PT0gMSkge1xuICAgIHdvcmtncm91cFNpemUgPSAyNTY7XG4gIH1cbiAgY29uc3QgaW5wdXRTaGFwZSA9IFtuLCBjLCBoIC8gY29tcG9uZW50c107XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gW24sIGMsIDJdO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsncmFuaycsICd0eXBlJywgJ3R5cGUnXTtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW107XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0U2hhcGUsIG91dHB1dFNoYXBlKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dC5kYXRhVHlwZSwgMywgY29tcG9uZW50cyk7XG4gICAgY29uc3QgcyA9IGlucHV0VmFyaWFibGUoJ3NjYWxlJywgc2NhbGUuZGF0YVR5cGUsIHNjYWxlLmRpbXMpO1xuICAgIGNvbnN0IGIgPSBpbnB1dFZhcmlhYmxlKCdiaWFzJywgYmlhcy5kYXRhVHlwZSwgYmlhcy5kaW1zKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgRGF0YVR5cGUuZmxvYXQsIDMsIDIpO1xuICAgIGNvbnN0IHZhcmlhYmxlcyA9IFt4LCBzLCBiLCBvdXRwdXRdO1xuICAgIHJldHVybiBgXG4gIHZhcjx3b3JrZ3JvdXA+IHdvcmtncm91cF9zaGFyZWQgOiBhcnJheTwke3dnVHlwZX0sICR7d29ya2dyb3VwU2l6ZX0+O1xuICBjb25zdCB3b3JrZ3JvdXBfc2l6ZSA9ICR7d29ya2dyb3VwU2l6ZX11O1xuICAke3NoYWRlckhlbHBlci5kZWNsYXJlVmFyaWFibGVzKC4uLnZhcmlhYmxlcyl9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCh3b3JrZ3JvdXBTaXplKX1cbiAgICBsZXQgYmF0Y2ggPSB3b3JrZ3JvdXBfaW5kZXggLyB1bmlmb3Jtcy54X3NoYXBlWzFdO1xuICAgIGxldCBjaGFubmVsID0gd29ya2dyb3VwX2luZGV4ICUgdW5pZm9ybXMueF9zaGFwZVsxXTtcbiAgICBsZXQgaGlnaHQgPSB1bmlmb3Jtcy54X3NoYXBlWzJdO1xuICAgIC8vIGluaXRpYWxpemUgd29ya2dyb3VwIG1lbW9yeVxuICAgIHZhciBzdW0gPSAke2YzMlR5cGV9KDApO1xuICAgIHZhciBzcXVhcmVkX3N1bSA9ICR7ZjMyVHlwZX0oMCk7XG4gICAgZm9yICh2YXIgaCA9IGxvY2FsX2lkeDsgaCA8IGhpZ2h0OyBoICs9IHdvcmtncm91cF9zaXplKSB7XG4gICAgICBsZXQgdmFsdWUgPSAke2YzMlR5cGV9KCR7eC5nZXQoJ2JhdGNoJywgJ2NoYW5uZWwnLCAnaCcpfSk7XG4gICAgICBzdW0gKz0gdmFsdWU7XG4gICAgICBzcXVhcmVkX3N1bSArPSB2YWx1ZSAqIHZhbHVlO1xuICAgIH1cbiAgICB3b3JrZ3JvdXBfc2hhcmVkW2xvY2FsX2lkeF0gPSAke3dnVHlwZX0oc3VtLCBzcXVhcmVkX3N1bSk7XG4gICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgZm9yICh2YXIgY3VyclNpemUgPSB3b3JrZ3JvdXBfc2l6ZSA+PiAxOyAgY3VyclNpemUgPiAwOyBjdXJyU2l6ZSA9IGN1cnJTaXplID4+IDEpIHtcbiAgICAgIGlmIChsb2NhbF9pZHggPCBjdXJyU2l6ZSkge1xuICAgICAgICB3b3JrZ3JvdXBfc2hhcmVkW2xvY2FsX2lkeF0gPSB3b3JrZ3JvdXBfc2hhcmVkW2xvY2FsX2lkeF0gKyB3b3JrZ3JvdXBfc2hhcmVkW2xvY2FsX2lkeCArIGN1cnJTaXplXTtcbiAgICAgIH1cbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgICB9XG4gICAgaWYgKGxvY2FsX2lkeCA9PSAwKSB7XG4gICAgICBsZXQgc3VtX2ZpbmFsID0gJHtzdW1WZWN0b3IoJ3dvcmtncm91cF9zaGFyZWRbMF1bMF0nLCBjb21wb25lbnRzKX0gLyBmMzIoaGlnaHQgKiAke2NvbXBvbmVudHN9KTtcbiAgICAgIGxldCBzcXVhcmVkX3N1bV9maW5hbCA9ICR7c3VtVmVjdG9yKCd3b3JrZ3JvdXBfc2hhcmVkWzBdWzFdJywgY29tcG9uZW50cyl9IC8gZjMyKGhpZ2h0ICogJHtjb21wb25lbnRzfSk7XG5cbiAgICAgIGxldCBpbnZfc3RkX2RldiA9IGludmVyc2VTcXJ0KHNxdWFyZWRfc3VtX2ZpbmFsIC0gc3VtX2ZpbmFsICogc3VtX2ZpbmFsICsgZjMyKCR7ZXBzaWxvbn0pKTtcbiAgICAgIGxldCBjaGFubmVsX3NjYWxlID0gaW52X3N0ZF9kZXYgKiBmMzIoc2NhbGVbY2hhbm5lbF0pO1xuICAgICAgbGV0IGNoYW5uZWxfc2hpZnQgPSBmMzIoYmlhc1tjaGFubmVsXSkgLSBzdW1fZmluYWwgKiBjaGFubmVsX3NjYWxlO1xuICAgICAgb3V0cHV0W3dvcmtncm91cF9pbmRleF0gPSB2ZWMyZihjaGFubmVsX3NjYWxlLCBjaGFubmVsX3NoaWZ0KTtcbiAgICB9XG4gIH1gO1xuICB9O1xuXG4gIHJldHVybiBjb250ZXh0LmNvbXB1dGUoXG4gICAge1xuICAgICAgbmFtZTogJ0luc3RhbmNlTm9ybUNvbXB1dGVDaGFubmVsU2NhbGVTaGlmdCcsXG4gICAgICAvLyBUT0RPOiB1c2UgZXBzaWxvbiBhcyB1bmlmb3JtLiBDdXJyZW50bHkgZXBzaWxvbiBhcyB1bmlmb3JtIGZhaWxzIHRlc3RfaW5zdGFuY2Vub3JtX2Vwc2lsb24uXG4gICAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtjb21wb25lbnRzfTske2Vwc2lsb259OyR7d29ya2dyb3VwU2l6ZX1gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBEYXRhVHlwZS5mbG9hdCB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiB1bml0c09mV29yayB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9LFxuICAgIHsgaW5wdXRzOiBbaW5wdXQsIHNjYWxlLCBiaWFzXSwgb3V0cHV0czogWy0xXSB9LFxuICApWzBdO1xufTtcblxuY29uc3QgY3JlYXRlSW5zdGFuY2VOb3JtUHJvZ3JhbUluZm8gPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogSW5zdGFuY2VOb3JtQXR0cmlidXRlcyxcbikgPT4ge1xuICBjb25zdCB4U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSB4U2hhcGU7XG4gIGNvbnN0IGF4aXMgPSAyO1xuICBjb25zdCBOID0geFNoYXBlWzBdO1xuICBjb25zdCBDID0geFNoYXBlWzFdO1xuICBjb25zdCBIID0gU2hhcGVVdGlsLnNpemVGcm9tRGltZW5zaW9uKHhTaGFwZSwgYXhpcyk7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKEgpO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gY29tcG9uZW50cztcbiAgLy8gY29tcHV0ZSBjaGFubmVsIHNjYWxlIGFuZCBjaGFubmVsIHNoaWZ0LlxuICBjb25zdCBjaGFubmVsU2NhbGVTaGlmdCA9IGNvbXB1dGVDaGFubmVsU2NhbGVTaGlmdChcbiAgICBjb250ZXh0LFxuICAgIGlucHV0c1swXSxcbiAgICBpbnB1dHNbMV0sXG4gICAgaW5wdXRzWzJdLFxuICAgIE4sXG4gICAgSCxcbiAgICBDLFxuICAgIGF0dHJpYnV0ZXMuZXBzaWxvbixcbiAgKTtcblxuICBjb25zdCBpbnB1dFNoYXBlID0gW04sIEMsIEggLyBjb21wb25lbnRzXTtcbiAgY29uc3Qgc2NhbGVTaGFwZSA9IFtOLCBDXTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnLCAnbm9uZSddO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3Qgc2NhbGUgPSBpbnB1dFZhcmlhYmxlKCdzY2FsZV9zaGlmdCcsIERhdGFUeXBlLmZsb2F0LCBzY2FsZVNoYXBlLmxlbmd0aCwgMik7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IHZhcmlhYmxlcyA9IFt4LCBzY2FsZSwgb3V0cHV0XTtcbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dF9zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoLi4udmFyaWFibGVzKX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgICBsZXQgb3V0cHV0SW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgIGxldCBiYXRjaCA9IG91dHB1dEluZGljZXNbMF07XG4gICAgICBsZXQgY2hhbm5lbCA9IG91dHB1dEluZGljZXNbMV07XG4gICAgICBsZXQgc2NhbGVfc2hpZnQgPSAke3NjYWxlLmdldEJ5SW5kaWNlcygndmVjMjx1MzI+KGJhdGNoLCBjaGFubmVsKScpfTtcbiAgICAgIGxldCB2YWx1ZSA9ICR7eC5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpfSAqICR7b3V0cHV0LnR5cGUudmFsdWV9KHNjYWxlX3NoaWZ0LngpICsgJHtvdXRwdXQudHlwZS52YWx1ZX0oc2NhbGVfc2hpZnQueSk7XG4gICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZScpfTtcbiAgfWA7XG4gIH07XG5cbiAgY29udGV4dC5jb21wdXRlKFxuICAgIHtcbiAgICAgIG5hbWU6ICdJbnN0YW5jZU5vcm1hbGl6YXRpb24nLFxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7Y29tcG9uZW50c31gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgICAgcHJvZ3JhbVVuaWZvcm1zOiBbXG4gICAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlLCBzY2FsZVNoYXBlLCBpbnB1dFNoYXBlKSxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIH0sXG4gICAgeyBpbnB1dHM6IFtpbnB1dHNbMF0sIGNoYW5uZWxTY2FsZVNoaWZ0XSB9LFxuICApO1xufTtcblxuY29uc3QgY3JlYXRlSW5zdGFuY2VOb3JtTkhXQ1Byb2dyYW1JbmZvID0gKFxuICBjb250ZXh0OiBDb21wdXRlQ29udGV4dCxcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IEluc3RhbmNlTm9ybUF0dHJpYnV0ZXMsXG4pID0+IHtcbiAgY29uc3QgeFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0geFNoYXBlO1xuICBjb25zdCBOID0geFNoYXBlWzBdO1xuICBjb25zdCBDID0geFNoYXBlW3hTaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3QgSCA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbih4U2hhcGUsIDEpIC8gQztcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoQyk7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyBjb21wb25lbnRzO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IEggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTWF0aC5mbG9vcihDIC8gY29tcG9uZW50cykgfSxcbiAgXTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnLCAndHlwZSddO1xuXG4gIC8vIDEuIHRyYW5zcG9zZSB4IGZyb20gTkhXQyB0byBOQ0hXXG4gIGxldCBuZWVkVHJhbnNwb3NlID0gZmFsc2U7XG4gIGNvbnN0IHRyYW5zcG9zZWRYUGVybSA9IFswLCB4U2hhcGUubGVuZ3RoIC0gMV07XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgeFNoYXBlLmxlbmd0aCAtIDI7IGkrKykge1xuICAgIG5lZWRUcmFuc3Bvc2UgPSBuZWVkVHJhbnNwb3NlIHx8IHhTaGFwZVtpICsgMV0gIT09IDE7XG4gICAgdHJhbnNwb3NlZFhQZXJtLnB1c2goaSArIDEpO1xuICB9XG5cbiAgbmVlZFRyYW5zcG9zZSA9IG5lZWRUcmFuc3Bvc2UgJiYgeFNoYXBlW3hTaGFwZS5sZW5ndGggLSAxXSAhPT0gMTtcblxuICBjb25zdCB0cmFuc3Bvc2VkWCA9IG5lZWRUcmFuc3Bvc2VcbiAgICA/IGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgdHJhbnNwb3NlZFhQZXJtKSwge1xuICAgICAgICBpbnB1dHM6IFtjb250ZXh0LmlucHV0c1swXV0sXG4gICAgICAgIG91dHB1dHM6IFstMV0sXG4gICAgICB9KVswXVxuICAgIDogY29udGV4dC5pbnB1dHNbMF0ucmVzaGFwZShBcnJheS5mcm9tKHsgbGVuZ3RoOiB4U2hhcGUubGVuZ3RoIH0sIChfLCBpKSA9PiB4U2hhcGVbdHJhbnNwb3NlZFhQZXJtW2ldXSkpO1xuICAvLyAyLiBjb21wdXRlIGNoYW5uZWwgc2NhbGUgYW5kIGNoYW5uZWwgc2hpZnQuXG4gIGNvbnN0IGNoYW5uZWxTY2FsZVNoaWZ0ID0gY29tcHV0ZUNoYW5uZWxTY2FsZVNoaWZ0KFxuICAgIGNvbnRleHQsXG4gICAgdHJhbnNwb3NlZFgsXG4gICAgaW5wdXRzWzFdLFxuICAgIGlucHV0c1syXSxcbiAgICBOLFxuICAgIEgsXG4gICAgQyxcbiAgICBhdHRyaWJ1dGVzLmVwc2lsb24sXG4gICk7XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKGlucHV0c1swXS5kYXRhVHlwZSk7XG4gICAgY29uc3Qgc2NhbGVUeXBlID0gY29tcG9uZW50cyA9PT0gMSA/ICd2ZWMyZicgOiBgbWF0JHtjb21wb25lbnRzfXgyZmA7XG4gICAgY29uc3Qgc2NhbGVEYXRhID0gKG51bTogbnVtYmVyKSA9PiB7XG4gICAgICBjb25zdCBpbmRleCA9IG51bSA9PT0gMCA/ICd4JyA6ICd5JztcbiAgICAgIGNvbnN0IGYzMlR5cGUgPSBjb21wb25lbnRzID09PSAxID8gJ2YzMicgOiBgdmVjJHtjb21wb25lbnRzfWZgO1xuICAgICAgc3dpdGNoIChjb21wb25lbnRzKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICByZXR1cm4gYCR7ZGF0YVR5cGV9KCR7ZjMyVHlwZX0oc2NhbGUuJHtpbmRleH0pKWA7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICByZXR1cm4gYHZlYzI8JHtkYXRhVHlwZX0+KCR7ZjMyVHlwZX0oc2NhbGVbMF0uJHtpbmRleH0sIHNjYWxlWzFdLiR7aW5kZXh9KSlgO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgcmV0dXJuIGB2ZWM0PCR7ZGF0YVR5cGV9Pigke2YzMlR5cGV9KHNjYWxlWzBdLiR7aW5kZXh9LCBzY2FsZVsxXS4ke2luZGV4fSwgc2NhbGVbMl0uJHtpbmRleH0sIHNjYWxlWzNdLiR7aW5kZXh9KSlgO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTm90IHN1cHBvcnRlZCBjb21wb2VudHMgJHtjb21wb25lbnRzfWApO1xuICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgaW5wdXRIZWxwZXIgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IG91dHB1dEhlbHBlciA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLCBjb21wb25lbnRzKTtcblxuICAgIHJldHVybiBgXG4gIEBncm91cCgwKSBAYmluZGluZygwKSB2YXI8c3RvcmFnZSwgcmVhZD4gaW5wdXQgOiBhcnJheTwke2lucHV0SGVscGVyLnR5cGUuc3RvcmFnZX0+O1xuICBAZ3JvdXAoMCkgQGJpbmRpbmcoMSkgdmFyPHN0b3JhZ2UsIHJlYWQ+IHNjYWxlX2lucHV0IDogYXJyYXk8JHtzY2FsZVR5cGV9PjtcbiAgQGdyb3VwKDApIEBiaW5kaW5nKDIpIHZhcjxzdG9yYWdlLCByZWFkX3dyaXRlPiBvdXRwdXQgOiBhcnJheTwke291dHB1dEhlbHBlci50eXBlLnN0b3JhZ2V9PjtcbiAgc3RydWN0IFVuaWZvcm1zIHtIOiB1MzIsIEMgOiB1MzJ9O1xuICBAZ3JvdXAoMCkgQGJpbmRpbmcoMykgdmFyPHVuaWZvcm0+IHVuaWZvcm1zOiBVbmlmb3JtcztcblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICBsZXQgY3VycmVudF9pbWFnZV9udW1iZXIgPSBnbG9iYWxfaWR4IC8gKHVuaWZvcm1zLkMgKiB1bmlmb3Jtcy5IKTtcbiAgICBsZXQgY3VycmVudF9jaGFubmVsX251bWJlciA9IGdsb2JhbF9pZHggJSB1bmlmb3Jtcy5DO1xuXG4gICAgbGV0IHNjYWxlX29mZnNldCA9IGN1cnJlbnRfaW1hZ2VfbnVtYmVyICogdW5pZm9ybXMuQyArIGN1cnJlbnRfY2hhbm5lbF9udW1iZXI7XG4gICAgbGV0IHNjYWxlID0gc2NhbGVfaW5wdXRbc2NhbGVfb2Zmc2V0XTtcbiAgICBvdXRwdXRbZ2xvYmFsX2lkeF0gPSBmbWEoaW5wdXRbZ2xvYmFsX2lkeF0sICR7c2NhbGVEYXRhKDApfSwgJHtzY2FsZURhdGEoMSl9KTtcbiAgfWA7XG4gIH07XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICB7XG4gICAgICBuYW1lOiAnSW5zdGFuY2VOb3JtYWxpemF0aW9uTkhXQycsXG4gICAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtjb21wb25lbnRzfWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9LFxuICAgIHsgaW5wdXRzOiBbaW5wdXRzWzBdLCBjaGFubmVsU2NhbGVTaGlmdF0gfSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBpbnN0YW5jZU5vcm0gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEluc3RhbmNlTm9ybUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQycpIHtcbiAgICBjcmVhdGVJbnN0YW5jZU5vcm1OSFdDUHJvZ3JhbUluZm8oY29udGV4dCwgY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICB9IGVsc2Uge1xuICAgIGNyZWF0ZUluc3RhbmNlTm9ybVByb2dyYW1JbmZvKGNvbnRleHQsIGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY2FzdFRvRjMyLFxuICBmaWxsVmVjdG9yLFxuICBnZXRNYXhDb21wb25lbnRzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICBzdW1WZWN0b3IsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuaW50ZXJmYWNlIExheWVyTm9ybUF0dHJpYnV0ZXMge1xuICBzaW1wbGlmaWVkOiBib29sZWFuO1xuICBheGlzOiBudW1iZXI7XG4gIGVwc2lsb246IG51bWJlcjtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCA8IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2xheWVyTm9ybSByZXF1aXJlcyBhdCBsZWFzdCAyIGlucHV0cy4nKTtcbiAgfVxufTtcblxuY29uc3QgY3JlYXRlTGF5ZXJOb3JtUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBMYXllck5vcm1BdHRyaWJ1dGVzLFxuICBvdXRwdXRDb3VudDogbnVtYmVyLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBzaW1wbGlmaWVkID0gYXR0cmlidXRlcy5zaW1wbGlmaWVkO1xuXG4gIGNvbnN0IHhTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBzY2FsZSA9IGlucHV0c1sxXTtcbiAgY29uc3QgYmlhcyA9ICFzaW1wbGlmaWVkICYmIGlucHV0c1syXTtcblxuICBjb25zdCBvdXRwdXRTaGFwZSA9IHhTaGFwZTtcbiAgY29uc3QgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMuYXhpcywgeFNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IG5vcm1Db3VudCA9IFNoYXBlVXRpbC5zaXplVG9EaW1lbnNpb24oeFNoYXBlLCBheGlzKTtcbiAgY29uc3Qgbm9ybVNpemUgPSBTaGFwZVV0aWwuc2l6ZUZyb21EaW1lbnNpb24oeFNoYXBlLCBheGlzKTtcblxuICBjb25zdCBzY2FsZVNpemUgPSBTaGFwZVV0aWwuc2l6ZShzY2FsZS5kaW1zKTtcbiAgY29uc3QgYmlhc1NpemUgPSBiaWFzID8gU2hhcGVVdGlsLnNpemUoYmlhcy5kaW1zKSA6IDA7XG4gIGlmIChzY2FsZVNpemUgIT09IG5vcm1TaXplIHx8IChiaWFzICYmIGJpYXNTaXplICE9PSBub3JtU2l6ZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFNpemUgb2YgWC5zaGFwZSgpW2F4aXM6XSA9PSAke25vcm1TaXplfS5cbiAgICAgICBTaXplIG9mIHNjYWxlIGFuZCBiaWFzIChpZiBwcm92aWRlZCkgbXVzdCBtYXRjaCB0aGlzLlxuICAgICAgIEdvdCBzY2FsZSBzaXplIG9mICR7c2NhbGVTaXplfSBhbmQgYmlhcyBzaXplIG9mICR7Ymlhc1NpemV9YCk7XG4gIH1cblxuICBjb25zdCBtZWFuSW52U3RkRGV2RGltOiBudW1iZXJbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHhTaGFwZS5sZW5ndGg7ICsraSkge1xuICAgIGlmIChpIDwgYXhpcykge1xuICAgICAgbWVhbkludlN0ZERldkRpbS5wdXNoKHhTaGFwZVtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1lYW5JbnZTdGREZXZEaW0ucHVzaCgxKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMobm9ybVNpemUpO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsndHlwZScsICd0eXBlJ107XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogbm9ybUNvdW50IH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogbm9ybVNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTWF0aC5mbG9vcihub3JtU2l6ZSAvIGNvbXBvbmVudHMpIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogYXR0cmlidXRlcy5lcHNpbG9uIH0sXG4gIF07XG4gIGlmIChiaWFzKSB7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgndHlwZScpO1xuICB9XG4gIGNvbnN0IGhhc01lYW5EYXRhT3V0cHV0ID0gb3V0cHV0Q291bnQgPiAxO1xuICBjb25zdCBoYXNJbnZTdGRPdXRwdXQgPSBvdXRwdXRDb3VudCA+IDI7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgICBjb25zdCB2YXJpYWJsZXMgPSBbXG4gICAgICBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcywgY29tcG9uZW50cyksXG4gICAgICBpbnB1dFZhcmlhYmxlKCdzY2FsZScsIHNjYWxlLmRhdGFUeXBlLCBzY2FsZS5kaW1zLCBjb21wb25lbnRzKSxcbiAgICBdO1xuICAgIGlmIChiaWFzKSB7XG4gICAgICB2YXJpYWJsZXMucHVzaChpbnB1dFZhcmlhYmxlKCdiaWFzJywgYmlhcy5kYXRhVHlwZSwgYmlhcy5kaW1zLCBjb21wb25lbnRzKSk7XG4gICAgfVxuICAgIHZhcmlhYmxlcy5wdXNoKG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLCBjb21wb25lbnRzKSk7XG4gICAgaWYgKGhhc01lYW5EYXRhT3V0cHV0KSB7XG4gICAgICB2YXJpYWJsZXMucHVzaChvdXRwdXRWYXJpYWJsZSgnbWVhbl9kYXRhX291dHB1dCcsIERhdGFUeXBlLmZsb2F0LCBtZWFuSW52U3RkRGV2RGltKSk7XG4gICAgfVxuICAgIGlmIChoYXNJbnZTdGRPdXRwdXQpIHtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKG91dHB1dFZhcmlhYmxlKCdpbnZfc3RkX291dHB1dCcsIERhdGFUeXBlLmZsb2F0LCBtZWFuSW52U3RkRGV2RGltKSk7XG4gICAgfVxuXG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnbm9ybV9jb3VudCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdub3JtX3NpemUnLCB0eXBlOiAnZjMyJyB9LFxuICAgICAgeyBuYW1lOiAnbm9ybV9zaXplX3ZlY3Rvcml6ZWQnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnZXBzaWxvbicsIHR5cGU6ICdmMzInIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLnZhcmlhYmxlcyl9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm5vcm1fY291bnQnKX1cbiAgICBsZXQgb2Zmc2V0ID0gZ2xvYmFsX2lkeCAqIHVuaWZvcm1zLm5vcm1fc2l6ZV92ZWN0b3JpemVkO1xuICAgIHZhciBtZWFuX3ZlY3RvciA9ICR7ZmlsbFZlY3RvcignZjMyJywgY29tcG9uZW50cyl9O1xuICAgIHZhciBtZWFuX3NxdWFyZV92ZWN0b3IgPSAke2ZpbGxWZWN0b3IoJ2YzMicsIGNvbXBvbmVudHMpfTtcblxuICAgIGZvciAodmFyIGg6IHUzMiA9IDB1OyBoIDwgdW5pZm9ybXMubm9ybV9zaXplX3ZlY3Rvcml6ZWQ7IGgrKykge1xuICAgICAgbGV0IHZhbHVlID0gJHtjYXN0VG9GMzIoZGF0YVR5cGUsIGNvbXBvbmVudHMsICd4W2ggKyBvZmZzZXRdJyl9O1xuICAgICAgbWVhbl92ZWN0b3IgKz0gdmFsdWU7XG4gICAgICBtZWFuX3NxdWFyZV92ZWN0b3IgKz0gdmFsdWUgKiB2YWx1ZTtcbiAgICB9XG4gICAgbGV0IG1lYW4gPSAke3N1bVZlY3RvcignbWVhbl92ZWN0b3InLCBjb21wb25lbnRzKX0gLyB1bmlmb3Jtcy5ub3JtX3NpemU7XG4gICAgbGV0IGludl9zdGRfZGV2ID0gaW52ZXJzZVNxcnQoJHtzdW1WZWN0b3IoJ21lYW5fc3F1YXJlX3ZlY3RvcicsIGNvbXBvbmVudHMpfSAvIHVuaWZvcm1zLm5vcm1fc2l6ZSAke1xuICAgICAgc2ltcGxpZmllZCA/ICcnIDogJy0gbWVhbiAqIG1lYW4nXG4gICAgfSArIHVuaWZvcm1zLmVwc2lsb24pO1xuXG4gICAgZm9yICh2YXIgajogdTMyID0gMDsgaiA8IHVuaWZvcm1zLm5vcm1fc2l6ZV92ZWN0b3JpemVkOyBqKyspIHtcbiAgICAgIGxldCBmMzJpbnB1dCA9ICR7Y2FzdFRvRjMyKGRhdGFUeXBlLCBjb21wb25lbnRzLCAneFtqICsgb2Zmc2V0XScpfTtcbiAgICAgIGxldCBmMzJzY2FsZSA9ICR7Y2FzdFRvRjMyKGRhdGFUeXBlLCBjb21wb25lbnRzLCAnc2NhbGVbal0nKX07XG4gICAgICBvdXRwdXRbaiArIG9mZnNldF0gPSAke3ZhcmlhYmxlc1swXS50eXBlLnZhbHVlfSgoZjMyaW5wdXQgJHtzaW1wbGlmaWVkID8gJycgOiAnLSBtZWFuJ30pICogaW52X3N0ZF9kZXYgKiBmMzJzY2FsZVxuICAgICAgICAke2JpYXMgPyBgKyAke2Nhc3RUb0YzMihkYXRhVHlwZSwgY29tcG9uZW50cywgJ2JpYXNbal0nKX1gIDogJyd9XG4gICAgICApO1xuICAgIH1cblxuICAgICR7aGFzTWVhbkRhdGFPdXRwdXQgPyAnbWVhbl9kYXRhX291dHB1dFtnbG9iYWxfaWR4XSA9IG1lYW4nIDogJyd9O1xuICAgICR7aGFzSW52U3RkT3V0cHV0ID8gJ2ludl9zdGRfb3V0cHV0W2dsb2JhbF9pZHhdID0gaW52X3N0ZF9kZXYnIDogJyd9O1xuICB9YDtcbiAgfTtcbiAgY29uc3Qgb3V0cHV0cyA9IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dO1xuICBpZiAoaGFzTWVhbkRhdGFPdXRwdXQpIHtcbiAgICBvdXRwdXRzLnB1c2goeyBkaW1zOiBtZWFuSW52U3RkRGV2RGltLCBkYXRhVHlwZTogRGF0YVR5cGUuZmxvYXQgfSk7XG4gIH1cbiAgaWYgKGhhc0ludlN0ZE91dHB1dCkge1xuICAgIG91dHB1dHMucHVzaCh7IGRpbXM6IG1lYW5JbnZTdGREZXZEaW0sIGRhdGFUeXBlOiBEYXRhVHlwZS5mbG9hdCB9KTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0xheWVyTm9ybWFsaXphdGlvbicsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7Y29tcG9uZW50c307JHtvdXRwdXRDb3VudH07JHtzaW1wbGlmaWVkfWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHMsXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChub3JtQ291bnQgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgbGF5ZXJOb3JtID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBMYXllck5vcm1BdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUxheWVyTm9ybVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzLCBjb250ZXh0Lm91dHB1dENvdW50KSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgQnJvYWRjYXN0VXRpbCwgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlTmFpdmVNYXRtdWxQcm9ncmFtSW5mbyB9IGZyb20gJy4vbWF0bXVsLXNoYWRlcnMnO1xuaW1wb3J0IHsgY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm8gfSBmcm9tICcuLzNyZC1wYXJ0eS9tYXRtdWxfcGFja2VkX3dlYmdwdSc7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01hdE11bCByZXF1aXJlcyAyIGlucHV0cy4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltc1tpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAxXSAhPT0gaW5wdXRzWzFdLmRpbXNbaW5wdXRzWzFdLmRpbXMubGVuZ3RoIC0gMl0pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NoYXJlZCBkaW1lbnNpb24gZG9lcyBub3QgbWF0Y2guJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBtYXRNdWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IEJyb2FkY2FzdFV0aWwuY2FsY1NoYXBlKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMsIGNvbnRleHQuaW5wdXRzWzFdLmRpbXMsIHRydWUpO1xuICBpZiAoIW91dHB1dFNoYXBlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgdXNlIG1hdG11bCBvbiB0aGUgZ2l2ZW4gdGVuc29yc1wiKTtcbiAgfVxuICBjb25zdCBOID0gb3V0cHV0U2hhcGVbb3V0cHV0U2hhcGUubGVuZ3RoIC0gMV07XG4gIGNvbnN0IEsgPSBjb250ZXh0LmlucHV0c1swXS5kaW1zW2NvbnRleHQuaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMV07XG4gIGlmIChOIDwgOCAmJiBLIDwgOCkge1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVOYWl2ZU1hdG11bFByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCB7IGFjdGl2YXRpb246ICcnIH0sIG91dHB1dFNoYXBlKSk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgTSA9IG91dHB1dFNoYXBlW291dHB1dFNoYXBlLmxlbmd0aCAtIDJdO1xuICAgIGNvbnN0IGJhdGNoQSA9IFNoYXBlVXRpbC5zaXplKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMuc2xpY2UoMCwgLTIpKTtcbiAgICBjb25zdCBiYXRjaEIgPSBTaGFwZVV0aWwuc2l6ZShjb250ZXh0LmlucHV0c1sxXS5kaW1zLnNsaWNlKDAsIC0yKSk7XG4gICAgaWYgKGJhdGNoQSAhPT0gMSAmJiBNID09PSAxICYmIGJhdGNoQiA9PT0gMSkge1xuICAgICAgLy8gT3B0aW1pemF0aW9uIGZvciBiYXRjaGVkIHZlYy1tYXQtbXVsXG4gICAgICBjb25zdCByZXNoYXBlZEEgPSBjb250ZXh0LmlucHV0c1swXS5yZXNoYXBlKFsxLCBiYXRjaEEsIEtdKTtcbiAgICAgIGNvbnN0IHJlc2hhcGVkQiA9IGNvbnRleHQuaW5wdXRzWzFdLnJlc2hhcGUoWzEsIEssIE5dKTtcbiAgICAgIGNvbnN0IG1hdG11bE91dHB1dFNoYXBlID0gWzEsIGJhdGNoQSwgTl07XG4gICAgICBjb25zdCBtYXRtdWxJbnB1dHMgPSBbcmVzaGFwZWRBLCByZXNoYXBlZEJdO1xuICAgICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvKG1hdG11bElucHV0cywgeyBhY3RpdmF0aW9uOiAnJyB9LCBvdXRwdXRTaGFwZSwgbWF0bXVsT3V0cHV0U2hhcGUpLCB7XG4gICAgICAgIGlucHV0czogbWF0bXVsSW5wdXRzLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVNYXRtdWxQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgeyBhY3RpdmF0aW9uOiAnJyB9LCBvdXRwdXRTaGFwZSkpO1xuICAgIH1cbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgZ2V0TWF4Q29tcG9uZW50cyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbi8vICBUT0RPIHN1cHBvcnQgcXVhbnRpemF0aW9uIGJpdHMgbm90IGVxdWFsIHRvIDRcbmV4cG9ydCBpbnRlcmZhY2UgTWF0TXVsTkJpdHNBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgazogbnVtYmVyO1xuICBuOiBudW1iZXI7XG4gIGFjY3VyYWN5TGV2ZWw6IG51bWJlcjtcbiAgYml0czogbnVtYmVyO1xuICBibG9ja1NpemU6IG51bWJlcjtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IE1hdE11bE5CaXRzQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBpZiAoaW5wdXRzLmxlbmd0aCA8IDMgfHwgaW5wdXRzLmxlbmd0aCA+IDQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01hdE11bE5CaXRzIHJlcXVpcmVzIDMgb3IgNCBpbnB1dHMnKTtcbiAgfVxuICBjb25zdCBhID0gaW5wdXRzWzBdO1xuICBjb25zdCBhUmFuayA9IGEuZGltcy5sZW5ndGg7XG4gIGlmIChhLmRpbXNbYVJhbmsgLSAxXSAhPT0gYXR0cmlidXRlcy5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgbGFzdCBkaW0gb2YgaW5wdXQgc2hhcGUgZG9lcyBub3QgbWF0Y2ggdGhlIGsgdmFsdWUnKTtcbiAgfVxuICBjb25zdCBuQmxvY2tzUGVyQ29sID0gTWF0aC5mbG9vcigoYXR0cmlidXRlcy5rICsgYXR0cmlidXRlcy5ibG9ja1NpemUgLSAxKSAvIGF0dHJpYnV0ZXMuYmxvY2tTaXplKTtcbiAgY29uc3QgYmxvYlNpemUgPSAoYXR0cmlidXRlcy5ibG9ja1NpemUgLyA4KSAqIGF0dHJpYnV0ZXMuYml0cztcbiAgY29uc3QgYiA9IGlucHV0c1sxXTtcbiAgaWYgKCFTaGFwZVV0aWwuYXJlRXF1YWwoYi5kaW1zLCBbYXR0cmlidXRlcy5uLCBuQmxvY2tzUGVyQ29sLCBibG9iU2l6ZV0pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgc2Vjb25kIGlucHV0cyBtdXN0IGJlIDNEIHRlbnNvciB3aXRoIHNoYXBlIE4gWCBuQmxvY2tzUGVyQ29sIFggYmxvYlNpemUnKTtcbiAgfVxuICBjb25zdCBzY2FsZXMgPSBpbnB1dHNbMl07XG4gIGNvbnN0IHNjYWxlc1NoYXBlID0gc2NhbGVzLmRpbXM7XG4gIGlmIChTaGFwZVV0aWwuc2l6ZShzY2FsZXNTaGFwZSkgIT09IGF0dHJpYnV0ZXMubiAqIG5CbG9ja3NQZXJDb2wpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NjYWxlcyBpbnB1dCBzaXplIGVycm9yLicpO1xuICB9XG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSA0KSB7XG4gICAgY29uc3QgemVyb1BvaW50cyA9IGlucHV0c1szXTtcbiAgICBjb25zdCB6ZXJvUG9pbnRzU2hhcGUgPSB6ZXJvUG9pbnRzLmRpbXM7XG5cbiAgICAvLyBUaGlzIGFzc3VtZXMgemVybyBwb2ludHMgYXJlIHBhY2tlZC5cbiAgICAvLyBVbnBhY2sgZm9ybWF0ICh6ZXJvIHBvaW50IGhhcyBzYW1lIGRhdGEgdHlwZSBhbmQgc2hhcGUgYXMgc2NhbGUpIGlzIG5vdCBzdXBwb3J0ZWQgYnkgd2ViZ3B1LlxuICAgIGNvbnN0IGV4cGVjdGVkWmVyb1BvaW50c1NpemUgPVxuICAgICAgYXR0cmlidXRlcy5uICogKGF0dHJpYnV0ZXMuYml0cyA9PT0gOCA/IG5CbG9ja3NQZXJDb2wgOiBNYXRoLmZsb29yKChuQmxvY2tzUGVyQ29sICogYXR0cmlidXRlcy5iaXRzICsgNykgLyA4KSk7XG4gICAgaWYgKFNoYXBlVXRpbC5zaXplKHplcm9Qb2ludHNTaGFwZSkgIT09IGV4cGVjdGVkWmVyb1BvaW50c1NpemUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignemVyb1BvaW50cyBpbnB1dCBzaXplIGVycm9yLicpO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZU1hdE11bE5CaXRzUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBNYXRNdWxOQml0c0F0dHJpYnV0ZXMsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgYVJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcbiAgY29uc3QgZGltQU91dGVyID0gaW5wdXRTaGFwZVthUmFuayAtIDJdO1xuICBjb25zdCBkaW1Jbm5lciA9IGF0dHJpYnV0ZXMuaztcbiAgY29uc3QgZGltQk91dGVyID0gYXR0cmlidXRlcy5uO1xuICBjb25zdCBiYXRjaERpbXMgPSBpbnB1dFNoYXBlLnNsaWNlKDAsIGFSYW5rIC0gMik7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IFNoYXBlVXRpbC5zaXplKGJhdGNoRGltcyk7XG4gIGNvbnN0IGJsb2JTaXplID0gaW5wdXRzWzFdLmRpbXNbMl07XG4gIGNvbnN0IGJsb2JTaXplSW5Xb3JkcyA9IGJsb2JTaXplIC8gNDtcbiAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dHNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IGFDb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhhdHRyaWJ1dGVzLmspO1xuICBjb25zdCBiQ29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoYmxvYlNpemVJbldvcmRzKTtcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoZGltQk91dGVyKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBiYXRjaERpbXMuY29uY2F0KFtkaW1BT3V0ZXIsIGRpbUJPdXRlcl0pO1xuICBjb25zdCBvdXRwdXROdW1iZXIgPSBkaW1BT3V0ZXIgPiAxICYmIChkaW1CT3V0ZXIgLyBjb21wb25lbnRzKSAlIDIgPT09IDAgPyAyIDogMTtcbiAgY29uc3QgZGlzcGF0Y2hTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gY29tcG9uZW50cyAvIG91dHB1dE51bWJlcjtcblxuICBjb25zdCB3b3JrZ3JvdXBTaXplID0gNjQ7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW107XG4gIGNvbnN0IGlucHV0U2hhcGVUZW1wID0gW2JhdGNoU2l6ZSwgZGltQU91dGVyLCBkaW1Jbm5lciAvIGFDb21wb25lbnRzXTtcbiAgY29uc3QgYlNoYXBlID0gU2hhcGVVdGlsLmNvbnZlcnRTaGFwZShpbnB1dHNbMV0uZGltcykuc2xpY2UoKTtcbiAgYlNoYXBlLnNwbGljZSgtMSwgMSwgYmxvYlNpemVJbldvcmRzIC8gYkNvbXBvbmVudHMpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlVGVtcCkpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhiU2hhcGUpKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzJdLmRpbXMpKTtcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDQpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhTaGFwZVV0aWwuY29udmVydFNoYXBlKGlucHV0c1szXS5kaW1zKSkpO1xuICB9XG4gIGNvbnN0IG91dHB1dFNoYXBlVGVtcCA9IFtiYXRjaFNpemUsIGRpbUFPdXRlciwgZGltQk91dGVyIC8gY29tcG9uZW50c107XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlVGVtcCkpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlucHV0UmFuayA9IGlucHV0U2hhcGVUZW1wLmxlbmd0aDtcbiAgICBjb25zdCBhID0gaW5wdXRWYXJpYWJsZSgnYScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRSYW5rLCBhQ29tcG9uZW50cyk7XG4gICAgY29uc3QgYiA9IGlucHV0VmFyaWFibGUoJ2InLCBEYXRhVHlwZS51aW50MzIsIGJTaGFwZS5sZW5ndGgsIGJDb21wb25lbnRzKTtcbiAgICBjb25zdCBzY2FsZXMgPSBpbnB1dFZhcmlhYmxlKCdzY2FsZXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgaW5wdXRWYXJpYWJsZXMgPSBbYSwgYiwgc2NhbGVzXTtcbiAgICBjb25zdCB6ZXJvUG9pbnRzID1cbiAgICAgIGlucHV0cy5sZW5ndGggPT09IDQgPyBpbnB1dFZhcmlhYmxlKCd6ZXJvX3BvaW50cycsIERhdGFUeXBlLnVpbnQzMiwgaW5wdXRzWzNdLmRpbXMubGVuZ3RoKSA6IHVuZGVmaW5lZDtcbiAgICBpZiAoemVyb1BvaW50cykge1xuICAgICAgaW5wdXRWYXJpYWJsZXMucHVzaCh6ZXJvUG9pbnRzKTtcbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0UmFuayA9IG91dHB1dFNoYXBlVGVtcC5sZW5ndGg7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0UmFuaywgY29tcG9uZW50cyk7XG4gICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcblxuICAgIGNvbnN0IHFEcURhdGFUeXBlID0gKCgpID0+IHtcbiAgICAgIHN3aXRjaCAoYUNvbXBvbmVudHMpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIHJldHVybiBgYXJyYXk8JHtkYXRhVHlwZX0sIDg+YDtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHJldHVybiBgbWF0NHgyPCR7ZGF0YVR5cGV9PmA7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICByZXR1cm4gYG1hdDJ4NDwke2RhdGFUeXBlfT5gO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHthQ29tcG9uZW50c30tY29tcG9uZW50IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gICAgICB9XG4gICAgfSkoKTtcblxuICAgIC8vIE51bWJlciBvZiBxdWFudGl6ZWQgdmFsdWVzIHBlciB1MzIgd29yZCBhbmQgcGFzc2VzIG5lZWRlZCAoZWFjaCBwYXNzIGV4dHJhY3RzIDggdmFsdWVzKS5cbiAgICBjb25zdCB2YWx1ZXNQZXJXb3JkID0gTWF0aC5mbG9vcigzMiAvIGF0dHJpYnV0ZXMuYml0cyk7IC8vIFE0PTgsIFEyPTE2XG4gICAgY29uc3QgcGFzc2VzUGVyV29yZCA9IE1hdGguZmxvb3IodmFsdWVzUGVyV29yZCAvIDgpOyAvLyBRND0xLCBRMj0yXG5cbiAgICBjb25zdCBwcm9jZXNzT25lV29yZCA9ICgpOiBzdHJpbmcgPT4ge1xuICAgICAgbGV0IGNhbGNTdHIgPSAnJztcbiAgICAgIGZvciAobGV0IHBhc3MgPSAwOyBwYXNzIDwgcGFzc2VzUGVyV29yZDsgcGFzcysrKSB7XG4gICAgICAgIC8vIEVhY2ggcGFzcyBwcm9jZXNzZXMgOCB2YWx1ZXMgZnJvbSB0aGUgY3VycmVudCB1MzIgd29yZC5cbiAgICAgICAgLy8gRm9yIFE0IChwYXNzPTApOiBzaGlmdCBieSAwIGFuZCA0LiBGb3IgUTIgKHBhc3MgMDogc2hpZnQgMCwyOyBwYXNzIDE6IHNoaWZ0IDQsNikuXG4gICAgICAgIGNvbnN0IGxvd2VyU2hpZnQgPSBwYXNzICogYXR0cmlidXRlcy5iaXRzICogNDsgLy8gYml0IG9mZnNldCBmb3IgbG93ZXIgZ3JvdXAgd2l0aGluIGVhY2ggYnl0ZVxuICAgICAgICBjb25zdCB1cHBlclNoaWZ0ID0gbG93ZXJTaGlmdCArIGF0dHJpYnV0ZXMuYml0cztcbiAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgLy8gcmV1c2UgYSBkYXRhIChwYXNzICR7cGFzc30pXG4gICAgICAgICAgICB2YXIgaW5wdXRfb2Zmc2V0JHtwYXNzID4gMCA/IHBhc3MgOiAnJ30gPSAke3Bhc3MgPT09IDAgPyBhLmluZGljZXNUb09mZnNldChgJHthLnR5cGUuaW5kaWNlc30oYmF0Y2gsIHJvdywgd29yZF9vZmZzZXQpYCkgOiBgaW5wdXRfb2Zmc2V0YH07XG4gICAgICAgICAgICB2YXIgYV9kYXRhJHtwYXNzID4gMCA/IHBhc3MgOiAnJ306ICR7cURxRGF0YVR5cGV9O1xuICAgICAgICAgICAgZm9yICh2YXIgaiR7cGFzcyA+IDAgPyBwYXNzIDogJyd9OiB1MzIgPSAwOyBqJHtwYXNzID4gMCA/IHBhc3MgOiAnJ30gPCAkezggLyBhQ29tcG9uZW50c307IGoke3Bhc3MgPiAwID8gcGFzcyA6ICcnfSsrKSB7XG4gICAgICAgICAgICAgIGFfZGF0YSR7cGFzcyA+IDAgPyBwYXNzIDogJyd9W2oke3Bhc3MgPiAwID8gcGFzcyA6ICcnfV0gPSAke2EuZ2V0QnlPZmZzZXQoYGlucHV0X29mZnNldCR7cGFzcyA+IDAgPyBwYXNzIDogJyd9YCl9O1xuICAgICAgICAgICAgICBpbnB1dF9vZmZzZXQke3Bhc3MgPiAwID8gcGFzcyA6ICcnfSsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIGA7XG4gICAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgY29tcG9uZW50cyAqIG91dHB1dE51bWJlcjsgYysrKSB7XG4gICAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgICBiX3ZhbHVlID0gJHtiQ29tcG9uZW50cyA9PT0gMSA/IGBiJHtjfV9kYXRhYCA6IGBiJHtjfV9kYXRhW2ldYH07XG4gICAgICAgICAgICAke1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVzLmJpdHMgPT09IDJcbiAgICAgICAgICAgICAgICA/IGB7XG4gICAgICAgICAgICAgIGxldCBoYWxmX3dvcmQgPSBiX3ZhbHVlID4+ICR7cGFzcyAqIDE2fXU7XG4gICAgICAgICAgICAgIGxldCBieXRlX2xvID0gaGFsZl93b3JkICYgMHhGRnU7XG4gICAgICAgICAgICAgIGxldCBieXRlX2hpID0gKGhhbGZfd29yZCA+PiA4dSkgJiAweEZGdTtcbiAgICAgICAgICAgICAgbGV0IHNwcmVhZF93b3JkID0gKGJ5dGVfbG8gJiAweEZ1KSB8ICgoYnl0ZV9sbyA+PiA0dSkgPDwgOHUpIHwgKChieXRlX2hpICYgMHhGdSkgPDwgMTZ1KSB8ICgoYnl0ZV9oaSA+PiA0dSkgPDwgMjR1KTtcbiAgICAgICAgICAgICAgYl92YWx1ZV9sb3dlciA9IHVucGFjazR4VTgoc3ByZWFkX3dvcmQgJiBiX21hc2spO1xuICAgICAgICAgICAgICBiX3ZhbHVlX3VwcGVyID0gdW5wYWNrNHhVOCgoc3ByZWFkX3dvcmQgPj4gMnUpICYgYl9tYXNrKTtcbiAgICAgICAgICAgIH1gXG4gICAgICAgICAgICAgICAgOiBgYl92YWx1ZV9sb3dlciA9IHVucGFjazR4VTgoKGJfdmFsdWUgPj4gJHtsb3dlclNoaWZ0fXUpICYgYl9tYXNrKTtcbiAgICAgICAgICAgIGJfdmFsdWVfdXBwZXIgPSB1bnBhY2s0eFU4KChiX3ZhbHVlID4+ICR7dXBwZXJTaGlmdH11KSAmIGJfbWFzayk7YFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYl9xdWFudGl6ZWRfdmFsdWVzID0gJHtxRHFEYXRhVHlwZX0oJHtBcnJheS5mcm9tKFxuICAgICAgICAgICAgICB7IGxlbmd0aDogNCB9LFxuICAgICAgICAgICAgICAoXywgaSkgPT4gYCR7ZGF0YVR5cGV9KGJfdmFsdWVfbG93ZXJbJHtpfV0pLCAke2RhdGFUeXBlfShiX3ZhbHVlX3VwcGVyWyR7aX1dKWAsXG4gICAgICAgICAgICApLmpvaW4oJywgJyl9KTtcbiAgICAgICAgICAgIGJfZGVxdWFudGl6ZWRfdmFsdWVzID0gJHsoKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoYUNvbXBvbmVudHMgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYCR7cURxRGF0YVR5cGV9KCR7QXJyYXkuZnJvbShcbiAgICAgICAgICAgICAgICAgIHsgbGVuZ3RoOiA4IH0sXG4gICAgICAgICAgICAgICAgICAoXywgaSkgPT4gYChiX3F1YW50aXplZF92YWx1ZXNbJHtpfV0gLSAke3plcm9Qb2ludHMgPyBgemVyb19wb2ludCR7Y31gIDogJ3plcm9fcG9pbnQnfSkgKiBzY2FsZSR7Y31gLFxuICAgICAgICAgICAgICAgICkuam9pbignLCAnKX0pO2A7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGAoYl9xdWFudGl6ZWRfdmFsdWVzIC0gJHtxRHFEYXRhVHlwZX0oJHtBcnJheSg4KVxuICAgICAgICAgICAgICAgICAgLmZpbGwoYCR7emVyb1BvaW50cyA/IGB6ZXJvX3BvaW50JHtjfWAgOiAnemVyb19wb2ludCd9YClcbiAgICAgICAgICAgICAgICAgIC5qb2luKCcsJyl9KSkgKiBzY2FsZSR7Y307YDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkoKX07XG4gICAgICAgICAgICB3b3JrZ3JvdXBfc2hhcmVkW2xvY2FsX2lkLnggKiAke291dHB1dE51bWJlcn0gKyAke01hdGguZmxvb3IoYyAvIGNvbXBvbmVudHMpfV0ke2NvbXBvbmVudHMgPiAxID8gYFske2MgJSBjb21wb25lbnRzfV1gIDogJyd9ICs9ICR7QXJyYXkuZnJvbShcbiAgICAgICAgICAgICAgeyBsZW5ndGg6IDggLyBhQ29tcG9uZW50cyB9LFxuICAgICAgICAgICAgICAoXywgaSkgPT5cbiAgICAgICAgICAgICAgICBgJHtcbiAgICAgICAgICAgICAgICAgIGFDb21wb25lbnRzID09PSAxXG4gICAgICAgICAgICAgICAgICAgID8gYGFfZGF0YSR7cGFzcyA+IDAgPyBwYXNzIDogJyd9WyR7aX1dICogYl9kZXF1YW50aXplZF92YWx1ZXNbJHtpfV1gXG4gICAgICAgICAgICAgICAgICAgIDogYGRvdChhX2RhdGEke3Bhc3MgPiAwID8gcGFzcyA6ICcnfVske2l9XSwgYl9kZXF1YW50aXplZF92YWx1ZXNbJHtpfV0pYFxuICAgICAgICAgICAgICAgIH1gLFxuICAgICAgICAgICAgKS5qb2luKCcgKyAnKX07XG4gICAgICAgICAgYDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGNhbGNTdHI7XG4gICAgfTtcbiAgICBjb25zdCBwcmVwYXJlU2NhbGVBbmRaZXJvUG9pbnQgPSAoKTogc3RyaW5nID0+IHtcbiAgICAgIGxldCBjYWxjU3RyID0gYFxuICAgICAgICAgICAgdmFyIGNvbF9pbmRleCA9IGNvbCAqICR7Y29tcG9uZW50c307XG4gICAgICAgICAgICAke1xuICAgICAgICAgICAgICB6ZXJvUG9pbnRzXG4gICAgICAgICAgICAgICAgPyBgXG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF92YWx1ZXNfcGVyX2J5dGU6IHUzMiA9ICR7TWF0aC5mbG9vcig4IC8gYXR0cmlidXRlcy5iaXRzKX11O1xuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfYnl0ZXNfcGVyX2NvbCA9IChuQmxvY2tzUGVyQ29sICsgemVyb19wb2ludF92YWx1ZXNfcGVyX2J5dGUgLSAxdSkgLyB6ZXJvX3BvaW50X3ZhbHVlc19wZXJfYnl0ZTtcbiAgICAgICAgICAgIHZhciB6ZXJvX3BvaW50X2J5dGVfY291bnQ6IHUzMjtcbiAgICAgICAgICAgIHZhciB6ZXJvX3BvaW50X3dvcmRfaW5kZXg6IHUzMjtcbiAgICAgICAgICAgIHZhciB6ZXJvX3BvaW50X2J5dGVfb2Zmc2V0OiB1MzI7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9zdWJfb2Zmc2V0OiB1MzIgPSBibG9jayAlIHplcm9fcG9pbnRfdmFsdWVzX3Blcl9ieXRlO1xuICAgICAgICAgICAgdmFyIHplcm9fcG9pbnRfYml0c19vZmZzZXQ6IHUzMjtcbiAgICAgICAgICAgIHZhciB6ZXJvX3BvaW50X3dvcmQ6IHUzMjtgXG4gICAgICAgICAgICAgICAgOiBgXG4gICAgICAgICAgICAvLyBUaGUgZGVmYXVsdCB6ZXJvIHBvaW50IGlzICR7TWF0aC5wb3coMiwgYXR0cmlidXRlcy5iaXRzIC0gMSl9IGZvciB1bnNpZ25lZCAke2F0dHJpYnV0ZXMuYml0c30tYml0IHF1YW50aXphdGlvbi5cbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50ID0gJHtkYXRhVHlwZX0oJHtNYXRoLnBvdygyLCBhdHRyaWJ1dGVzLmJpdHMgLSAxKS50b0ZpeGVkKDEpfSk7YFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYDtcbiAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgY29tcG9uZW50cyAqIG91dHB1dE51bWJlcjsgYysrKSB7XG4gICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgICAgbGV0IHNjYWxlJHtjfSA9ICR7c2NhbGVzLmdldEJ5T2Zmc2V0KGBjb2xfaW5kZXggKiBuQmxvY2tzUGVyQ29sICsgYmxvY2tgKX07XG4gICAgICAgICAgICAke1xuICAgICAgICAgICAgICB6ZXJvUG9pbnRzXG4gICAgICAgICAgICAgICAgPyBgXG4gICAgICAgICAgICB6ZXJvX3BvaW50X2J5dGVfY291bnQgPSBjb2xfaW5kZXggKiB6ZXJvX3BvaW50X2J5dGVzX3Blcl9jb2wgKyAoYmxvY2sgLyB6ZXJvX3BvaW50X3ZhbHVlc19wZXJfYnl0ZSk7XG4gICAgICAgICAgICB6ZXJvX3BvaW50X3dvcmRfaW5kZXggPSB6ZXJvX3BvaW50X2J5dGVfY291bnQgPj4gMHgydTtcbiAgICAgICAgICAgIHplcm9fcG9pbnRfYnl0ZV9vZmZzZXQgPSB6ZXJvX3BvaW50X2J5dGVfY291bnQgJiAweDN1O1xuICAgICAgICAgICAgemVyb19wb2ludF9iaXRzX29mZnNldCA9ICh6ZXJvX3BvaW50X2J5dGVfb2Zmc2V0IDw8IDMpICsgKHplcm9fcG9pbnRfc3ViX29mZnNldCAqICR7YXR0cmlidXRlcy5iaXRzfXUpO1xuICAgICAgICAgICAgemVyb19wb2ludF93b3JkID0gJHt6ZXJvUG9pbnRzLmdldEJ5T2Zmc2V0KCd6ZXJvX3BvaW50X3dvcmRfaW5kZXgnKX0gPj4gemVyb19wb2ludF9iaXRzX29mZnNldDtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50JHtjfSA9ICR7ZGF0YVR5cGV9KCh6ZXJvX3BvaW50X3dvcmQpICYgJHthdHRyaWJ1dGVzLmJpdHMgPT09IDIgPyAnMHgzdScgOiAnMHhGdSd9KTtgXG4gICAgICAgICAgICAgICAgOiAnJ1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29sX2luZGV4ICs9IDE7YDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjYWxjU3RyO1xuICAgIH07XG4gICAgY29uc3QgcHJlcGFyZUJEYXRhID0gKCk6IHN0cmluZyA9PiB7XG4gICAgICBsZXQgY2FsY1N0ciA9IGBjb2xfaW5kZXggPSBjb2wgKiAke2NvbXBvbmVudHN9O2A7XG4gICAgICBmb3IgKGxldCBjID0gMDsgYyA8IGNvbXBvbmVudHMgKiBvdXRwdXROdW1iZXI7IGMrKykge1xuICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICAgIGxldCBiJHtjfV9kYXRhID0gJHtiLmdldEJ5SW5kaWNlcyhgJHtiLnR5cGUuaW5kaWNlc30oY29sX2luZGV4LCBibG9jaywgd29yZClgKX07XG4gICAgICAgICAgICBjb2xfaW5kZXggKz0gMTtgO1xuICAgICAgfVxuICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgICB2YXIgYl92YWx1ZTogdTMyO1xuICAgICAgICAgICAgbGV0IGJfbWFzazogdTMyID0gJHthdHRyaWJ1dGVzLmJpdHMgPT09IDIgPyAnMHgwMzAzMDMwM3UnIDogJzB4MEYwRjBGMEZ1J307XG4gICAgICAgICAgICB2YXIgYl92YWx1ZV9sb3dlcjogdmVjNDx1MzI+O1xuICAgICAgICAgICAgdmFyIGJfdmFsdWVfdXBwZXI6IHZlYzQ8dTMyPjtcbiAgICAgICAgICAgIHZhciBiX3F1YW50aXplZF92YWx1ZXM6ICR7cURxRGF0YVR5cGV9O1xuICAgICAgICAgICAgdmFyIGJfZGVxdWFudGl6ZWRfdmFsdWVzOiAke3FEcURhdGFUeXBlfTtgO1xuICAgICAgcmV0dXJuIGNhbGNTdHI7XG4gICAgfTtcbiAgICByZXR1cm4gYFxuICAgICAgICB2YXI8d29ya2dyb3VwPiB3b3JrZ3JvdXBfc2hhcmVkOiBhcnJheTwke291dHB1dC50eXBlLnZhbHVlfSwgJHtvdXRwdXROdW1iZXIgKiB3b3JrZ3JvdXBTaXplfT47XG4gICAgICAgICR7c2hhZGVySGVscGVyLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydChbd29ya2dyb3VwU2l6ZSwgMSwgMV0pfVxuICAgICAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgKGdsb2JhbF9pZHggLyAke3dvcmtncm91cFNpemV9KSAqICR7b3V0cHV0TnVtYmVyfWApfTtcbiAgICAgICAgICBsZXQgY29sID0gb3V0cHV0X2luZGljZXNbMl07XG4gICAgICAgICAgbGV0IHJvdyA9IG91dHB1dF9pbmRpY2VzWzFdO1xuICAgICAgICAgIGxldCBiYXRjaCA9IG91dHB1dF9pbmRpY2VzWzBdO1xuICAgICAgICAgIGxldCBuQmxvY2tzUGVyQ29sID0gdW5pZm9ybXMuYl9zaGFwZVsxXTtcblxuICAgICAgICAgIGZvciAodmFyIGJsb2NrID0gbG9jYWxfaWQueDsgYmxvY2sgPCBuQmxvY2tzUGVyQ29sOyBibG9jayArPSAke3dvcmtncm91cFNpemV9KSB7XG4gICAgICAgICAgICAvL3Byb2Nlc3Mgb25lIGJsb2NrXG4gICAgICAgICAgICB2YXIgd29yZF9vZmZzZXQ6IHUzMiA9IGJsb2NrICogJHthdHRyaWJ1dGVzLmJsb2NrU2l6ZSAvIGFDb21wb25lbnRzfTtcbiAgICAgICAgICAgICR7cHJlcGFyZVNjYWxlQW5kWmVyb1BvaW50KCl9XG4gICAgICAgICAgICBmb3IgKHZhciB3b3JkOiB1MzIgPSAwOyB3b3JkIDwgJHtibG9iU2l6ZUluV29yZHN9OyB3b3JkICs9ICR7YkNvbXBvbmVudHN9KSB7XG4gICAgICAgICAgICAgICR7cHJlcGFyZUJEYXRhKCl9XG4gICAgICAgICAgICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCAke2JDb21wb25lbnRzfTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgJHtwcm9jZXNzT25lV29yZCgpfVxuICAgICAgICAgICAgICAgIHdvcmRfb2Zmc2V0ICs9ICR7dmFsdWVzUGVyV29yZCAvIGFDb21wb25lbnRzfTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgICAgICBpZiAobG9jYWxfaWQueCA8ICR7b3V0cHV0TnVtYmVyfSkge1xuICAgICAgICAgICAgdmFyIG91dHB1dF92YWx1ZTogJHtvdXRwdXQudHlwZS52YWx1ZX0gPSAke291dHB1dC50eXBlLnZhbHVlfSgwKTtcbiAgICAgICAgICAgIHZhciB3b3JrZ3JvdXBfc2hhcmVkX29mZnNldDogdTMyID0gbG9jYWxfaWQueDtcbiAgICAgICAgICAgIGZvciAodmFyIGI6IHUzMiA9IDB1OyBiIDwgJHt3b3JrZ3JvdXBTaXplfXU7IGIrKykge1xuICAgICAgICAgICAgICBvdXRwdXRfdmFsdWUgKz0gd29ya2dyb3VwX3NoYXJlZFt3b3JrZ3JvdXBfc2hhcmVkX29mZnNldF07XG4gICAgICAgICAgICAgIHdvcmtncm91cF9zaGFyZWRfb2Zmc2V0ICs9ICR7b3V0cHV0TnVtYmVyfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5SW5kaWNlcyhgJHtvdXRwdXQudHlwZS5pbmRpY2VzfShiYXRjaCwgcm93LCBjb2wgKyBsb2NhbF9pZC54KWAsICdvdXRwdXRfdmFsdWUnKX07XG4gICAgICAgICAgfVxuICAgICAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnTWF0TXVsTkJpdHMnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmJsb2NrU2l6ZX07JHthdHRyaWJ1dGVzLmJpdHN9OyR7YUNvbXBvbmVudHN9OyR7YkNvbXBvbmVudHN9OyR7Y29tcG9uZW50c307JHtvdXRwdXROdW1iZXJ9OyR7d29ya2dyb3VwU2l6ZX1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IEFycmF5KGlucHV0cy5sZW5ndGgpLmZpbGwoJ3JhbmsnKSxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IGRpc3BhdGNoU2l6ZSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbi8vIEN1cnJlbnRseSwgb25seSBzdXBwb3J0IGJsb2NrU2l6ZSA9IDMyLlxuZXhwb3J0IGNvbnN0IGNyZWF0ZU1hdE11bE5CaXRzQmxvY2tTaXplMzJQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IE1hdE11bE5CaXRzQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBhUmFuayA9IGlucHV0U2hhcGUubGVuZ3RoO1xuICBjb25zdCBkaW1BT3V0ZXIgPSBpbnB1dFNoYXBlW2FSYW5rIC0gMl07XG4gIGNvbnN0IGRpbUlubmVyID0gYXR0cmlidXRlcy5rO1xuICBjb25zdCBkaW1CT3V0ZXIgPSBhdHRyaWJ1dGVzLm47XG4gIGNvbnN0IGJhdGNoRGltcyA9IGlucHV0U2hhcGUuc2xpY2UoMCwgYVJhbmsgLSAyKTtcbiAgY29uc3QgYmF0Y2hTaXplID0gU2hhcGVVdGlsLnNpemUoYmF0Y2hEaW1zKTtcbiAgY29uc3QgYmxvYlNpemUgPSBpbnB1dHNbMV0uZGltc1syXTtcbiAgY29uc3QgYmxvYlNpemVJbldvcmRzID0gYmxvYlNpemUgLyA0O1xuICBjb25zdCBkYXRhVHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgYUNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKGF0dHJpYnV0ZXMuayk7XG4gIGNvbnN0IGJDb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhibG9iU2l6ZUluV29yZHMpO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGJhdGNoRGltcy5jb25jYXQoW2RpbUFPdXRlciwgZGltQk91dGVyXSk7XG5cbiAgY29uc3Qgd29ya2dyb3VwU2l6ZSA9IDEyODtcbiAgY29uc3Qgd29ya2dyb3VwWSA9IGRpbUJPdXRlciAlIDggPT09IDAgPyA4IDogZGltQk91dGVyICUgNCA9PT0gMCA/IDQgOiAxO1xuICBjb25zdCB3b3JrZ3JvdXBYID0gd29ya2dyb3VwU2l6ZSAvIHdvcmtncm91cFk7XG4gIGNvbnN0IHZhbHVlc1BlcldvcmRCczMyID0gTWF0aC5mbG9vcigzMiAvIGF0dHJpYnV0ZXMuYml0cyk7IC8vIFE0PTgsIFEyPTE2XG4gIGNvbnN0IHRpbGVTaXplID0gd29ya2dyb3VwWCAqIGJDb21wb25lbnRzICogdmFsdWVzUGVyV29yZEJzMzI7IC8vIGVhY2ggdWludDMyIGhhcyB2YWx1ZXNQZXJXb3JkIGRhdGEuXG4gIGNvbnN0IGFMZW5ndGhQZXJUaWxlID0gdGlsZVNpemUgLyBhQ29tcG9uZW50cztcbiAgY29uc3QgYmxvY2tzUGVyVGlsZSA9IHRpbGVTaXplIC8gYXR0cmlidXRlcy5ibG9ja1NpemU7XG4gIGNvbnN0IGRpc3BhdGNoU2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIHdvcmtncm91cFk7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW107XG4gIGNvbnN0IGlucHV0U2hhcGVUZW1wID0gW2JhdGNoU2l6ZSwgZGltQU91dGVyLCBkaW1Jbm5lciAvIGFDb21wb25lbnRzXTtcbiAgY29uc3QgYlNoYXBlID0gU2hhcGVVdGlsLmNvbnZlcnRTaGFwZShpbnB1dHNbMV0uZGltcykuc2xpY2UoKTtcbiAgYlNoYXBlLnNwbGljZSgtMSwgMSwgYmxvYlNpemVJbldvcmRzIC8gYkNvbXBvbmVudHMpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlVGVtcCkpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhiU2hhcGUpKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzJdLmRpbXMpKTtcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDQpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhTaGFwZVV0aWwuY29udmVydFNoYXBlKGlucHV0c1szXS5kaW1zKSkpO1xuICB9XG4gIGNvbnN0IG91dHB1dFNoYXBlVGVtcCA9IFtiYXRjaFNpemUsIGRpbUFPdXRlciwgZGltQk91dGVyXTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGVUZW1wKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5wdXRSYW5rID0gaW5wdXRTaGFwZVRlbXAubGVuZ3RoO1xuICAgIGNvbnN0IGEgPSBpbnB1dFZhcmlhYmxlKCdhJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dFJhbmssIGFDb21wb25lbnRzKTtcbiAgICBjb25zdCBiID0gaW5wdXRWYXJpYWJsZSgnYicsIERhdGFUeXBlLnVpbnQzMiwgYlNoYXBlLmxlbmd0aCwgYkNvbXBvbmVudHMpO1xuICAgIGNvbnN0IHNjYWxlcyA9IGlucHV0VmFyaWFibGUoJ3NjYWxlcycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBpbnB1dFZhcmlhYmxlcyA9IFthLCBiLCBzY2FsZXNdO1xuICAgIGNvbnN0IHplcm9Qb2ludHMgPVxuICAgICAgaW5wdXRzLmxlbmd0aCA9PT0gNCA/IGlucHV0VmFyaWFibGUoJ3plcm9fcG9pbnRzJywgRGF0YVR5cGUudWludDMyLCBpbnB1dHNbM10uZGltcy5sZW5ndGgpIDogdW5kZWZpbmVkO1xuICAgIGlmICh6ZXJvUG9pbnRzKSB7XG4gICAgICBpbnB1dFZhcmlhYmxlcy5wdXNoKHplcm9Qb2ludHMpO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXRSYW5rID0gb3V0cHV0U2hhcGVUZW1wLmxlbmd0aDtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRSYW5rKTtcbiAgICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuICAgIGNvbnN0IHJlYWRBID0gKCkgPT4ge1xuICAgICAgc3dpdGNoIChhQ29tcG9uZW50cykge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBsZXQgYV9kYXRhMCA9IHZlYzQ8JHtkYXRhVHlwZX0+KHN1Yl9hW3dvcmRfb2Zmc2V0XSwgc3ViX2Fbd29yZF9vZmZzZXQgKyAxXSwgc3ViX2Fbd29yZF9vZmZzZXQgKyAyXSwgc3ViX2Fbd29yZF9vZmZzZXQgKyAzXSk7XG4gICAgICAgICAgbGV0IGFfZGF0YTEgPSB2ZWM0PCR7ZGF0YVR5cGV9PihzdWJfYVt3b3JkX29mZnNldCArIDRdLCBzdWJfYVt3b3JkX29mZnNldCArIDVdLCBzdWJfYVt3b3JkX29mZnNldCArIDZdLCBzdWJfYVt3b3JkX29mZnNldCArIDddKTtgO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBsZXQgYV9kYXRhMCA9IHZlYzQ8JHtkYXRhVHlwZX0+KHN1Yl9hW3dvcmRfb2Zmc2V0XSwgc3ViX2Fbd29yZF9vZmZzZXQgKyAxXSk7XG4gICAgICAgICAgbGV0IGFfZGF0YTEgPSB2ZWM0PCR7ZGF0YVR5cGV9PihzdWJfYVt3b3JkX29mZnNldCArIDJdLCBzdWJfYVt3b3JkX29mZnNldCArIDNdKTtgO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBsZXQgYV9kYXRhMCA9IHN1Yl9hW3dvcmRfb2Zmc2V0XTtcbiAgICAgICAgICBsZXQgYV9kYXRhMSA9IHN1Yl9hW3dvcmRfb2Zmc2V0ICsgMV07YDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7YUNvbXBvbmVudHN9LWNvbXBvbmVudCBpcyBub3Qgc3VwcG9ydGVkLmApO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gYFxuICAgICAgICB2YXI8d29ya2dyb3VwPiBzdWJfYTogYXJyYXk8JHthLnR5cGUudmFsdWV9LCAke2FMZW5ndGhQZXJUaWxlfT47XG4gICAgICAgIHZhcjx3b3JrZ3JvdXA+IGludGVyX3Jlc3VsdHM6IGFycmF5PGFycmF5PCR7b3V0cHV0LnR5cGUudmFsdWV9LCAke3dvcmtncm91cFh9PiwgJHt3b3JrZ3JvdXBZfT47XG4gICAgICAgICR7c2hhZGVySGVscGVyLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydChbd29ya2dyb3VwWCwgd29ya2dyb3VwWSwgMV0pfVxuICAgICAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgd29ya2dyb3VwX2luZGV4ICogJHt3b3JrZ3JvdXBZfWApfTtcbiAgICAgICAgICBsZXQgY29sID0gb3V0cHV0X2luZGljZXNbMl07XG4gICAgICAgICAgbGV0IHJvdyA9IG91dHB1dF9pbmRpY2VzWzFdO1xuICAgICAgICAgIGxldCBiYXRjaCA9IG91dHB1dF9pbmRpY2VzWzBdO1xuICAgICAgICAgIGxldCBuX2Jsb2Nrc19wZXJfY29sID0gdW5pZm9ybXMuYl9zaGFwZVsxXTtcbiAgICAgICAgICBsZXQgbnVtX3RpbGVzID0gIChuX2Jsb2Nrc19wZXJfY29sIC0gMSkgLyAke2Jsb2Nrc1BlclRpbGV9ICsgMTtcblxuICAgICAgICAgIC8vIExvb3Agb3ZlciBzaGFyZWQgZGltZW5zaW9uLlxuICAgICAgICAgIGZvciAodmFyIHRpbGU6IHUzMiA9IDA7IHRpbGUgPCBudW1fdGlsZXM7IHRpbGUgKz0gMSkge1xuICAgICAgICAgICAgbGV0IGFfY29sX3N0YXJ0ID0gdGlsZSAqICR7YUxlbmd0aFBlclRpbGV9O1xuICAgICAgICAgICAgLy8gbG9hZCBvbmUgdGlsZSBBIGRhdGEgaW50byBzaGFyZWQgbWVtb3J5LlxuICAgICAgICAgICAgZm9yICh2YXIgYV9vZmZzZXQgPSBsb2NhbF9pZHg7IGFfb2Zmc2V0IDwgJHthTGVuZ3RoUGVyVGlsZX07IGFfb2Zmc2V0ICs9ICR7d29ya2dyb3VwU2l6ZX0pXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGxldCBhX2NvbCA9IGFfY29sX3N0YXJ0ICsgYV9vZmZzZXQ7XG4gICAgICAgICAgICAgIGlmIChhX2NvbCA8IHVuaWZvcm1zLmFfc2hhcGVbMl0pXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzdWJfYVthX29mZnNldF0gPSAke2EuZ2V0QnlJbmRpY2VzKGAke2EudHlwZS5pbmRpY2VzfShiYXRjaCwgcm93LCBhX2NvbClgKX07XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3ViX2FbYV9vZmZzZXRdID0gJHthLnR5cGUudmFsdWV9KDApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgICAgICAgIC8vIGVhY2ggdGhyZWFkIHByb2Nlc3Mgb25lIGJsb2NrXG4gICAgICAgICAgICBsZXQgYl9yb3cgPSBjb2wgKyBsb2NhbF9pZC55O1xuICAgICAgICAgICAgbGV0IGJsb2NrID0gdGlsZSAqICR7YmxvY2tzUGVyVGlsZX0gKyBsb2NhbF9pZC54O1xuICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgemVyb1BvaW50c1xuICAgICAgICAgICAgICAgID8gYFxuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfdmFsdWVzX3Blcl9ieXRlOiB1MzIgPSAke01hdGguZmxvb3IoOCAvIGF0dHJpYnV0ZXMuYml0cyl9dTtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2J5dGVzX3Blcl9jb2wgPSAobl9ibG9ja3NfcGVyX2NvbCArIHplcm9fcG9pbnRfdmFsdWVzX3Blcl9ieXRlIC0gMXUpIC8gemVyb19wb2ludF92YWx1ZXNfcGVyX2J5dGU7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9ieXRlX2NvdW50ID0gYl9yb3cgKiB6ZXJvX3BvaW50X2J5dGVzX3Blcl9jb2wgKyAoYmxvY2sgLyB6ZXJvX3BvaW50X3ZhbHVlc19wZXJfYnl0ZSk7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF93b3JkX2luZGV4ID0gemVyb19wb2ludF9ieXRlX2NvdW50ID4+IDB4MnU7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9ieXRlX29mZnNldCA9IHplcm9fcG9pbnRfYnl0ZV9jb3VudCAmIDB4M3U7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9zdWJfb2Zmc2V0OiB1MzIgPSBibG9jayAlIHplcm9fcG9pbnRfdmFsdWVzX3Blcl9ieXRlO1xuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfYml0c19vZmZzZXQgPSAoemVyb19wb2ludF9ieXRlX29mZnNldCA8PCAzKSArICh6ZXJvX3BvaW50X3N1Yl9vZmZzZXQgKiAke2F0dHJpYnV0ZXMuYml0c311KTtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X3dvcmQgPSAke3plcm9Qb2ludHMuZ2V0QnlPZmZzZXQoJ3plcm9fcG9pbnRfd29yZF9pbmRleCcpfSA+PiB6ZXJvX3BvaW50X2JpdHNfb2Zmc2V0O1xuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnQgPSAke2RhdGFUeXBlfSgoemVyb19wb2ludF93b3JkKSAmICR7YXR0cmlidXRlcy5iaXRzID09PSAyID8gJzB4M3UnIDogJzB4RnUnfSk7YFxuICAgICAgICAgICAgICAgIDogYFxuICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgemVybyBwb2ludCBpcyAke01hdGgucG93KDIsIGF0dHJpYnV0ZXMuYml0cyAtIDEpfSBmb3IgdW5zaWduZWQgJHthdHRyaWJ1dGVzLmJpdHN9LWJpdCBxdWFudGl6YXRpb24uXG4gICAgICAgICAgICBsZXQgemVyb19wb2ludCA9ICR7ZGF0YVR5cGV9KCR7TWF0aC5wb3coMiwgYXR0cmlidXRlcy5iaXRzIC0gMSkudG9GaXhlZCgxKX0pO2BcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzY2FsZSA9ICR7c2NhbGVzLmdldEJ5T2Zmc2V0KGBiX3JvdyAqIG5fYmxvY2tzX3Blcl9jb2wgKyBibG9ja2ApfTtcbiAgICAgICAgICAgIGxldCBiX2RhdGEgPSAke2IuZ2V0QnlJbmRpY2VzKGAke2IudHlwZS5pbmRpY2VzfShiX3JvdywgYmxvY2ssIDApYCl9O1xuICAgICAgICAgICAgdmFyIHdvcmRfb2Zmc2V0ID0gbG9jYWxfaWQueCAqICR7YXR0cmlidXRlcy5ibG9ja1NpemUgLyBhQ29tcG9uZW50c307XG4gICAgICAgICAgICBmb3IgKHZhciBpOiB1MzIgPSAwOyBpIDwgJHtiQ29tcG9uZW50c307IGkrKykge1xuICAgICAgICAgICAgICBsZXQgYl92YWx1ZSA9ICR7YkNvbXBvbmVudHMgPT09IDEgPyBgYl9kYXRhYCA6IGBiX2RhdGFbaV1gfTtcbiAgICAgICAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhc3Nlc1BlcldvcmRCczMyID0gTWF0aC5mbG9vcih2YWx1ZXNQZXJXb3JkQnMzMiAvIDgpO1xuICAgICAgICAgICAgICAgIGxldCBjb2RlID0gJyc7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgcGFzcyA9IDA7IHBhc3MgPCBwYXNzZXNQZXJXb3JkQnMzMjsgcGFzcysrKSB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBsb3dlclNoaWZ0ID0gcGFzcyAqIGF0dHJpYnV0ZXMuYml0cyAqIDQ7XG4gICAgICAgICAgICAgICAgICBjb25zdCB1cHBlclNoaWZ0ID0gbG93ZXJTaGlmdCArIGF0dHJpYnV0ZXMuYml0cztcbiAgICAgICAgICAgICAgICAgIGNvZGUgKz0gYFxuICAgICAgICAgICAgICAke3JlYWRBKCl9XG4gICAgICAgICAgICAgIHske1xuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXMuYml0cyA9PT0gMlxuICAgICAgICAgICAgICAgICAgPyBgXG4gICAgICAgICAgICAgICAgbGV0IGhhbGZfd29yZCA9IGJfdmFsdWUgPj4gJHtwYXNzICogMTZ9dTtcbiAgICAgICAgICAgICAgICBsZXQgYnl0ZV9sbyA9IGhhbGZfd29yZCAmIDB4RkZ1O1xuICAgICAgICAgICAgICAgIGxldCBieXRlX2hpID0gKGhhbGZfd29yZCA+PiA4dSkgJiAweEZGdTtcbiAgICAgICAgICAgICAgICBsZXQgc3ByZWFkX3dvcmQgPSAoYnl0ZV9sbyAmIDB4RnUpIHwgKChieXRlX2xvID4+IDR1KSA8PCA4dSkgfCAoKGJ5dGVfaGkgJiAweEZ1KSA8PCAxNnUpIHwgKChieXRlX2hpID4+IDR1KSA8PCAyNHUpO1xuICAgICAgICAgICAgICAgIGxldCBiX3ZhbHVlX2xvd2VyID0gdW5wYWNrNHhVOChzcHJlYWRfd29yZCAmIDB4MDMwMzAzMDN1KTtcbiAgICAgICAgICAgICAgICBsZXQgYl92YWx1ZV91cHBlciA9IHVucGFjazR4VTgoKHNwcmVhZF93b3JkID4+IDJ1KSAmIDB4MDMwMzAzMDN1KTtgXG4gICAgICAgICAgICAgICAgICA6IGBcbiAgICAgICAgICAgICAgICBsZXQgYl92YWx1ZV9sb3dlciA9IHVucGFjazR4VTgoKGJfdmFsdWUgPj4gJHtsb3dlclNoaWZ0fXUpICYgMHgwRjBGMEYwRnUpO1xuICAgICAgICAgICAgICAgIGxldCBiX3ZhbHVlX3VwcGVyID0gdW5wYWNrNHhVOCgoYl92YWx1ZSA+PiAke3VwcGVyU2hpZnR9dSkgJiAweDBGMEYwRjBGdSk7YFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGJfcXVhbnRpemVkX3ZhbHVlcyA9IG1hdDJ4NDwke2RhdGFUeXBlfT4oJHtBcnJheS5mcm9tKFxuICAgICAgICAgICAgICAgICAgeyBsZW5ndGg6IDQgfSxcbiAgICAgICAgICAgICAgICAgIChfLCBpKSA9PiBgJHtkYXRhVHlwZX0oYl92YWx1ZV9sb3dlclske2l9XSksICR7ZGF0YVR5cGV9KGJfdmFsdWVfdXBwZXJbJHtpfV0pYCxcbiAgICAgICAgICAgICAgICApLmpvaW4oJywgJyl9KTtcbiAgICAgICAgICAgICAgICBsZXQgYl9kZXF1YW50aXplZF92YWx1ZXMgPSAoYl9xdWFudGl6ZWRfdmFsdWVzIC0gbWF0Mng0PCR7ZGF0YVR5cGV9Pigke0FycmF5KDgpLmZpbGwoJ3plcm9fcG9pbnQnKS5qb2luKCcsJyl9KSkgKiBzY2FsZTtcbiAgICAgICAgICAgICAgICBpbnRlcl9yZXN1bHRzW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdICs9ICR7QXJyYXkuZnJvbShcbiAgICAgICAgICAgICAgICAgIHsgbGVuZ3RoOiAyIH0sXG4gICAgICAgICAgICAgICAgICAoXywgaSkgPT4gYCR7YGRvdChhX2RhdGEke2l9LCBiX2RlcXVhbnRpemVkX3ZhbHVlc1ske2l9XSlgfWAsXG4gICAgICAgICAgICAgICAgKS5qb2luKCcgKyAnKX07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgd29yZF9vZmZzZXQgKz0gJHs4IC8gYUNvbXBvbmVudHN9O2A7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBjb2RlO1xuICAgICAgICAgICAgICB9KSgpfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChsb2NhbF9pZHggPCAke3dvcmtncm91cFl9KSB7XG4gICAgICAgICAgICB2YXIgb3V0cHV0X3ZhbHVlOiAke291dHB1dC50eXBlLnZhbHVlfSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KDApO1xuICAgICAgICAgICAgZm9yICh2YXIgYiA9IDB1OyBiIDwgJHt3b3JrZ3JvdXBYfTsgYisrKSB7XG4gICAgICAgICAgICAgIG91dHB1dF92YWx1ZSArPSBpbnRlcl9yZXN1bHRzW2xvY2FsX2lkeF1bYl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29sICsgbG9jYWxfaWR4IDwgdW5pZm9ybXMub3V0cHV0X3NoYXBlWzJdKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAke291dHB1dC5zZXRCeUluZGljZXMoYCR7b3V0cHV0LnR5cGUuaW5kaWNlc30oYmF0Y2gsIHJvdywgY29sICsgbG9jYWxfaWR4KWAsICdvdXRwdXRfdmFsdWUnKX1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdCbG9ja3dpc2VNYXRNdWxOQml0czMyJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YXR0cmlidXRlcy5ibG9ja1NpemV9OyR7YUNvbXBvbmVudHN9OyR7YkNvbXBvbmVudHN9OyR7d29ya2dyb3VwWH07JHt3b3JrZ3JvdXBZfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llczogQXJyYXkoaW5wdXRzLmxlbmd0aCkuZmlsbCgncmFuaycpLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogZGlzcGF0Y2hTaXplIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IG1hdE11bE5CaXRzID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBNYXRNdWxOQml0c0F0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBpZiAoXG4gICAgYXR0cmlidXRlcy5ibG9ja1NpemUgPT09IDMyICYmXG4gICAgY29udGV4dC5hZGFwdGVySW5mby5pc1ZlbmRvcignaW50ZWwnKSAmJlxuICAgIGNvbnRleHQuYWRhcHRlckluZm8uaXNBcmNoaXRlY3R1cmUoJ2dlbi0xMmxwJylcbiAgKSB7XG4gICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZU1hdE11bE5CaXRzQmxvY2tTaXplMzJQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcykpO1xuICB9IGVsc2Uge1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVNYXRNdWxOQml0c1Byb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKSk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZU1hdE11bE5CaXRzQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IE1hdE11bE5CaXRzQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoYXR0cmlidXRlcyBhcyBPbWl0PE1hdE11bE5CaXRzQXR0cmlidXRlcywga2V5b2YgQXR0cmlidXRlV2l0aENhY2hlS2V5Pik7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRFbGVtZW50QXQsXG4gIEluZGljZXNIZWxwZXIsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmludGVyZmFjZSBQYWRBdHRyaWJ1dGVzIHtcbiAgLy8gMC1jb25zdGFudCwgMS1yZWZsZWN0LCAyLWVkZ2UsIDMtd3JhcFxuICByZWFkb25seSBtb2RlOiBudW1iZXI7XG4gIHJlYWRvbmx5IHZhbHVlOiBudW1iZXI7XG4gIHJlYWRvbmx5IHBhZHM6IG51bWJlcltdO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoIDwgMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignVG9vIGZldyBpbnB1dHMnKTtcbiAgfVxuICBpZiAoaW5wdXRzWzBdLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5mbG9hdCAmJiBpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0MTYpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IHR5cGUgbXVzdCBiZSBmbG9hdCBvciBmbG9hdDE2LicpO1xuICB9XG5cbiAgaWYgKGlucHV0cy5sZW5ndGggPj0gMikge1xuICAgIGxldCB2YWxpZFBhZHMgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggKiAyID09PSBpbnB1dHNbMV0uZGltc1swXTtcbiAgICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gNCkge1xuICAgICAgdmFsaWRQYWRzID0gaW5wdXRzWzNdLmRpbXNbMF0gKiAyID09PSBpbnB1dHNbMV0uZGltc1swXTtcbiAgICB9XG4gICAgaWYgKCF2YWxpZFBhZHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIHBhZHMgc2hvdWxkIGJlIGEgMUQgdGVuc29yIG9mIHNoYXBlIFsyICogaW5wdXRfcmFua10gb3IgWzIgKiBudW1fYXhlc10uJyk7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBnZXRQYWRDb25zdGFudCA9IChvdXRwdXQ6IEluZGljZXNIZWxwZXIsIGlucHV0UmFuazogbnVtYmVyLCBwYWRzTGVuZ3RoOiBudW1iZXIpOiBzdHJpbmcgPT4ge1xuICBsZXQgYmxvY2sgPSAnJztcbiAgZm9yIChsZXQgaSA9IGlucHV0UmFuayAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgYmxvY2sgKz0gYFxuICAgICAgICAgICAgayA9IGkzMigke291dHB1dC5pbmRpY2VzR2V0KCdpbmRpY2VzJywgaSl9KSAtICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5wYWRzJywgaSwgcGFkc0xlbmd0aCl9O1xuICAgICAgICAgICAgaWYgKGsgPCAwKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGsgPj0gaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgaSwgaW5wdXRSYW5rKX0pKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb2Zmc2V0ICs9IGsgKiBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc3RyaWRlcycsIGksIGlucHV0UmFuayl9KTtcbiAgICAgICAgYDtcbiAgfVxuXG4gIHJldHVybiBgXG4gICAgICAgICAgdmFsdWUgPSAke291dHB1dC50eXBlLnZhbHVlfSh1bmlmb3Jtcy5jb25zdGFudF92YWx1ZSk7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAxOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgdmFyIGsgPSAwO1xuICAgICAgICAgICAgJHtibG9ja31cbiAgICAgICAgICAgIHZhbHVlID0geFtvZmZzZXRdO1xuICAgICAgICAgIH1cbiAgICAgIGA7XG59O1xuXG5jb25zdCBnZXRQYWRSZWZsZWN0ID0gKG91dHB1dDogSW5kaWNlc0hlbHBlciwgaW5wdXRSYW5rOiBudW1iZXIsIHBhZHNMZW5ndGg6IG51bWJlcik6IHN0cmluZyA9PiB7XG4gIGxldCBibG9jayA9ICcnO1xuICBmb3IgKGxldCBpID0gaW5wdXRSYW5rIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICBibG9jayArPSBgXG4gICAgICAgICAgICAgICAgayA9IGkzMigke291dHB1dC5pbmRpY2VzR2V0KCdpbmRpY2VzJywgaSl9KSAtICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5wYWRzJywgaSwgcGFkc0xlbmd0aCl9O1xuICAgICAgICAgICAgICAgIGlmIChrIDwgMCkge1xuICAgICAgICAgICAgICAgICAgayA9IC1rO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBsZXQgXzJuXzEgPSAyICogKGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIGksIGlucHV0UmFuayl9KSAtIDEpO1xuICAgICAgICAgICAgICAgICAgayA9IGsgJSBfMm5fMTtcbiAgICAgICAgICAgICAgICAgIGlmKGsgPj0gaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgaSwgaW5wdXRSYW5rKX0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGsgPSBfMm5fMSAtIGs7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG9mZnNldCArPSBrICogaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3N0cmlkZXMnLCBpLCBpbnB1dFJhbmspfSk7XG4gICAgICAgICAgICBgO1xuICB9XG5cbiAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgdmFyIG9mZnNldCA9IDA7XG4gICAgICAgICAgICAgIHZhciBrID0gMDtcbiAgICAgICAgICAgICAgJHtibG9ja31cbiAgICAgICAgICAgICAgdmFsdWUgPSB4W29mZnNldF07XG4gICAgICAgICAgYDtcbn07XG5cbmNvbnN0IGdldFBhZEVkZ2UgPSAob3V0cHV0OiBJbmRpY2VzSGVscGVyLCBpbnB1dFJhbms6IG51bWJlciwgcGFkc0xlbmd0aDogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgbGV0IGJsb2NrID0gJyc7XG4gIGZvciAobGV0IGkgPSBpbnB1dFJhbmsgLSAxOyBpID49IDA7IC0taSkge1xuICAgIGJsb2NrICs9IGBcbiAgICAgICAgICAgICAgICBrID0gaTMyKCR7b3V0cHV0LmluZGljZXNHZXQoJ2luZGljZXMnLCBpKX0pIC0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnBhZHMnLCBpLCBwYWRzTGVuZ3RoKX07XG4gICAgICAgICAgICAgICAgaWYgKGsgPCAwKSB7XG4gICAgICAgICAgICAgICAgICBrID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGsgPj0gaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgaSwgaW5wdXRSYW5rKX0pKSB7XG4gICAgICAgICAgICAgICAgICBrID0gaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgaSwgaW5wdXRSYW5rKX0pIC0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb2Zmc2V0ICs9IGsgKiBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc3RyaWRlcycsIGksIGlucHV0UmFuayl9KTtcbiAgICAgICAgICAgIGA7XG4gIH1cblxuICByZXR1cm4gYFxuICAgICAgICAgICAgICB2YXIgb2Zmc2V0ID0gMDtcbiAgICAgICAgICAgICAgdmFyIGsgPSAwO1xuICAgICAgICAgICAgICAke2Jsb2NrfVxuICAgICAgICAgICAgICB2YWx1ZSA9IHhbb2Zmc2V0XTtcbiAgICAgICAgICBgO1xufTtcblxuY29uc3QgZ2V0UGFkV3JhcCA9IChvdXRwdXQ6IEluZGljZXNIZWxwZXIsIGlucHV0UmFuazogbnVtYmVyLCBwYWRzTGVuZ3RoOiBudW1iZXIpOiBzdHJpbmcgPT4ge1xuICBsZXQgYmxvY2sgPSAnJztcbiAgZm9yIChsZXQgaSA9IGlucHV0UmFuayAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgYmxvY2sgKz0gYFxuICAgICAgICAgICAgICAgIGsgPSBpMzIoJHtvdXRwdXQuaW5kaWNlc0dldCgnaW5kaWNlcycsIGkpfSkgLSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMucGFkcycsIGksIHBhZHNMZW5ndGgpfTtcbiAgICAgICAgICAgICAgICBpZiAoayA8IDApICB7XG4gICAgICAgICAgICAgICAgICBrICs9IGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIGksIGlucHV0UmFuayl9XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChrID49IGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIGksIGlucHV0UmFuayl9KSkge1xuICAgICAgICAgICAgICAgICAgayAtPSBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCBpLCBpbnB1dFJhbmspfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG9mZnNldCArPSBrICogaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3N0cmlkZXMnLCBpLCBpbnB1dFJhbmspfSk7XG4gICAgICAgICAgICBgO1xuICB9XG5cbiAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgdmFyIG9mZnNldCA9IDA7XG4gICAgICAgICAgICAgIHZhciBrID0gMDtcbiAgICAgICAgICAgICAgJHtibG9ja31cbiAgICAgICAgICAgICAgdmFsdWUgPSB4W29mZnNldF07XG4gICAgICAgICAgYDtcbn07XG5cbmNvbnN0IGdldFBhZFNuaXBwZXQgPSAob3V0cHV0OiBJbmRpY2VzSGVscGVyLCBpbnB1dFJhbms6IG51bWJlciwgYXR0cmlidXRlczogUGFkQXR0cmlidXRlcyk6IHN0cmluZyA9PiB7XG4gIHN3aXRjaCAoYXR0cmlidXRlcy5tb2RlKSB7XG4gICAgY2FzZSAwOlxuICAgICAgcmV0dXJuIGdldFBhZENvbnN0YW50KG91dHB1dCwgaW5wdXRSYW5rLCBhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoKTtcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gZ2V0UGFkUmVmbGVjdChvdXRwdXQsIGlucHV0UmFuaywgYXR0cmlidXRlcy5wYWRzLmxlbmd0aCk7XG4gICAgY2FzZSAyOlxuICAgICAgcmV0dXJuIGdldFBhZEVkZ2Uob3V0cHV0LCBpbnB1dFJhbmssIGF0dHJpYnV0ZXMucGFkcy5sZW5ndGgpO1xuICAgIGNhc2UgMzpcbiAgICAgIHJldHVybiBnZXRQYWRXcmFwKG91dHB1dCwgaW5wdXRSYW5rLCBhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoKTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1vZGUnKTtcbiAgfVxufTtcblxuY29uc3QgY3JlYXRlUGFkUHJvZ3JhbUluZm8gPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IFBhZEF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gU2hhcGVVdGlsLnBhZFNoYXBlKGlucHV0c1swXS5kaW1zLnNsaWNlKCksIGF0dHJpYnV0ZXMucGFkcyk7XG4gIGNvbnN0IGlucHV0RGltcyA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLnBhZHMgfSxcbiAgXTtcblxuICBjb25zdCBpc1ZhbHVlRnJvbUlucHV0ID0gaW5wdXRzLmxlbmd0aCA+PSAzICYmIGlucHV0c1syXS5kYXRhO1xuICBpZiAoYXR0cmlidXRlcy5tb2RlID09PSAwKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goeyB0eXBlOiBpc1ZhbHVlRnJvbUlucHV0ID8gaW5wdXRzWzJdLmRhdGFUeXBlIDogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMudmFsdWUgfSk7XG4gIH1cblxuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgb3V0cHV0U2hhcGUpKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3JhbmsnXTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICAgIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXREaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dC50eXBlLnZhbHVlO1xuICAgIGNvbnN0IHBhZFNuaXBwZXQgPSBnZXRQYWRTbmlwcGV0KG91dHB1dCwgaW5wdXREaW1zLmxlbmd0aCwgYXR0cmlidXRlcyk7XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAncGFkcycsIHR5cGU6ICdpMzInLCBsZW5ndGg6IGF0dHJpYnV0ZXMucGFkcy5sZW5ndGggfSxcbiAgICBdO1xuICAgIGlmIChhdHRyaWJ1dGVzLm1vZGUgPT09IDApIHtcbiAgICAgIHVuaWZvcm1zLnB1c2goeyBuYW1lOiAnY29uc3RhbnRfdmFsdWUnLCB0eXBlOiAoaXNWYWx1ZUZyb21JbnB1dCA/IGRhdGFUeXBlIDogJ2YzMicpIGFzIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG4gICAgICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG5cbiAgICAgICAgICAgIGxldCBpbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuXG4gICAgICAgICAgICB2YXIgdmFsdWUgPSAke2RhdGFUeXBlfSgwKTtcbiAgICAgICAgICAgICR7cGFkU25pcHBldH1cbiAgICAgICAgICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9IHZhbHVlO1xuICAgICAgICB9YDtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdQYWQnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2F0dHJpYnV0ZXMubW9kZX0ke2lzVmFsdWVGcm9tSW5wdXR9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5jb25zdCBjcmVhdGVQYWRBdHRyaWJ1dGVzRnJvbUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogUGFkQXR0cmlidXRlcyk6IFBhZEF0dHJpYnV0ZXMgPT4ge1xuICBpZiAoaW5wdXRzLmxlbmd0aCA+IDEpIHtcbiAgICBjb25zdCBiaWdJbnQ2NFBhZHMgPSBpbnB1dHNbMV0uZ2V0QmlnSW50NjRBcnJheSgpO1xuICAgIGNvbnN0IHZhbHVlID1cbiAgICAgIGlucHV0cy5sZW5ndGggPj0gMyAmJiBpbnB1dHNbMl0uZGF0YVxuICAgICAgICA/IGlucHV0c1syXS5kYXRhVHlwZSA9PT0gRGF0YVR5cGUuZmxvYXQxNlxuICAgICAgICAgID8gaW5wdXRzWzJdLmdldFVpbnQxNkFycmF5KClbMF1cbiAgICAgICAgICA6IGlucHV0c1syXS5nZXRGbG9hdDMyQXJyYXkoKVswXVxuICAgICAgICA6IDAuMDtcblxuICAgIGNvbnN0IGlucHV0UmFuayA9IGlucHV0c1swXS5kaW1zLmxlbmd0aDtcbiAgICBjb25zdCB1cGRhdGVQYWRzID0gbmV3IEludDMyQXJyYXkoMiAqIGlucHV0UmFuaykuZmlsbCgwKTtcbiAgICBpZiAoaW5wdXRzLmxlbmd0aCA+PSA0KSB7XG4gICAgICBjb25zdCBheGVzID0gaW5wdXRzWzNdLmdldEJpZ0ludDY0QXJyYXkoKTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB1cGRhdGVQYWRzW051bWJlcihheGVzW2ldKV0gPSBOdW1iZXIoYmlnSW50NjRQYWRzW2ldKTtcbiAgICAgICAgdXBkYXRlUGFkc1tOdW1iZXIoYXhlc1tpXSkgKyBpbnB1dFJhbmtdID0gTnVtYmVyKGJpZ0ludDY0UGFkc1tpICsgYXhlcy5sZW5ndGhdKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYmlnSW50NjRQYWRzLmZvckVhY2goKHYsIGkpID0+ICh1cGRhdGVQYWRzW051bWJlcihpKV0gPSBOdW1iZXIodikpKTtcbiAgICB9XG5cbiAgICBjb25zdCBwYWRzOiBudW1iZXJbXSA9IFtdO1xuICAgIHVwZGF0ZVBhZHMuZm9yRWFjaCgodikgPT4gcGFkcy5wdXNoKHYpKTtcblxuICAgIHJldHVybiB7IG1vZGU6IGF0dHJpYnV0ZXMubW9kZSwgdmFsdWUsIHBhZHMgfTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYXR0cmlidXRlcztcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHBhZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUGFkQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IHVwZGF0ZWRBdHRyaWJ1dGVzID0gY3JlYXRlUGFkQXR0cmlidXRlc0Zyb21JbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlUGFkUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIHVwZGF0ZWRBdHRyaWJ1dGVzKSwgeyBpbnB1dHM6IFswXSB9KTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGVudiB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFBvb2xDb252VXRpbCwgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRFbGVtZW50QXQsXG4gIEluZGljZXNIZWxwZXIsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbi8vIFRPRE86IHN1cHBvcnQ6XG4vLyAtIGNlaWxfbW9kZSAgICAgICAgICAgICAgICAgXCJ0ZXN0X21heHBvb2xfMmRfY2VpbFwiXG4vLyAtIHN0b3JhZ2Vfb3JkZXIgICAgICAgICAgICAgXCJ0ZXN0X21heHBvb2xfd2l0aF9hcmdtYXhfMmRfcHJlY29tcHV0ZWRfc3RyaWRlc1wiXG4vLyAtIFtNYXhQb29sXSBkaWxhdGlvbnMgICAgICAgXCJ0ZXN0X21heHBvb2xfMmRfZGlsYXRpb25zXCJcbi8vIC0gW01heFBvb2xdIG91dHB1dFsxXSAgICAgICBcInRlc3RfbWF4cG9vbF93aXRoX2FyZ21heF8yZF9wcmVjb21wdXRlZF9wYWRzXCJcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKGVudi53ZWJncHUudmFsaWRhdGVJbnB1dENvbnRlbnQgJiYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Bvb2wgb3BzIHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cbn07XG5cbmNvbnN0IGdldEFkanVzdGVkUG9vbEF0dHJpYnV0ZXNBbmRPdXRwdXRTaGFwZSA9IDxBdHRyaWJ1dGVUeXBlIGV4dGVuZHMgQXZlcmFnZVBvb2xBdHRyaWJ1dGVzIHwgTWF4UG9vbEF0dHJpYnV0ZXM+KFxuICBpbnB1dDogVGVuc29yVmlldyxcbiAgYXR0cmlidXRlczogQXR0cmlidXRlVHlwZSxcbiAgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbixcbik6IFtBdHRyaWJ1dGVUeXBlLCBudW1iZXJbXV0gPT4ge1xuICBjb25zdCBpc0NoYW5uZWxzTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGNvbnN0IGlucHV0U2hhcGVBc0NoYW5uZWxGaXJzdCA9IGlucHV0LmRpbXMuc2xpY2UoKTtcbiAgaWYgKGlzQ2hhbm5lbHNMYXN0KSB7XG4gICAgaW5wdXRTaGFwZUFzQ2hhbm5lbEZpcnN0LnNwbGljZSgxLCAwLCBpbnB1dFNoYXBlQXNDaGFubmVsRmlyc3QucG9wKCkhKTsgLy8gTW92ZSBjaGFubmVsIHRvIHRoZSBzZWNvbmQgcG9zaXRpb24uXG4gIH1cbiAgY29uc3QgaGFzRGlsYXRpb25zID0gT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwoYXR0cmlidXRlcywgJ2RpbGF0aW9ucycpO1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUuc2xpY2UoKTtcbiAgY29uc3Qgc3RyaWRlcyA9IGF0dHJpYnV0ZXMuc3RyaWRlcy5zbGljZSgpO1xuICBjb25zdCBkaWxhdGlvbnM6IG51bWJlcltdID0gaGFzRGlsYXRpb25zID8gKGF0dHJpYnV0ZXMgYXMgTWF4UG9vbEF0dHJpYnV0ZXMpLmRpbGF0aW9ucy5zbGljZSgpIDogW107XG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHMuc2xpY2UoKTtcbiAgUG9vbENvbnZVdGlsLmFkanVzdFBvb2xBdHRyaWJ1dGVzKGlzR2xvYmFsT3BlcmF0b3IsIGlucHV0U2hhcGVBc0NoYW5uZWxGaXJzdCwga2VybmVsU2hhcGUsIHN0cmlkZXMsIGRpbGF0aW9ucywgcGFkcyk7XG5cbiAgY29uc3Qgb3V0cHV0U2hhcGVBc0NoYW5uZWxGaXJzdCA9IFBvb2xDb252VXRpbC5jb21wdXRlUG9vbE91dHB1dFNoYXBlKFxuICAgIGlzR2xvYmFsT3BlcmF0b3IsXG4gICAgaW5wdXRTaGFwZUFzQ2hhbm5lbEZpcnN0LFxuICAgIHN0cmlkZXMsXG4gICAgZGlsYXRpb25zLFxuICAgIGtlcm5lbFNoYXBlLFxuICAgIHBhZHMsXG4gICAgYXR0cmlidXRlcy5hdXRvUGFkLFxuICApO1xuXG4gIGNvbnN0IG5ld0F0dHJpYnV0ZXMgPSBPYmplY3QuYXNzaWduKHt9LCBhdHRyaWJ1dGVzKTtcbiAgaWYgKGhhc0RpbGF0aW9ucykge1xuICAgIE9iamVjdC5hc3NpZ24obmV3QXR0cmlidXRlcywgeyBrZXJuZWxTaGFwZSwgc3RyaWRlcywgcGFkcywgZGlsYXRpb25zLCBjYWNoZUtleTogYXR0cmlidXRlcy5jYWNoZUtleSB9KTtcbiAgfSBlbHNlIHtcbiAgICBPYmplY3QuYXNzaWduKG5ld0F0dHJpYnV0ZXMsIHsga2VybmVsU2hhcGUsIHN0cmlkZXMsIHBhZHMsIGNhY2hlS2V5OiBhdHRyaWJ1dGVzLmNhY2hlS2V5IH0pO1xuICB9XG4gIGNvbnN0IG91dHB1dFNoYXBlQXNDaGFubmVsTGFzdCA9IG91dHB1dFNoYXBlQXNDaGFubmVsRmlyc3Quc2xpY2UoKTtcbiAgb3V0cHV0U2hhcGVBc0NoYW5uZWxMYXN0LnB1c2gob3V0cHV0U2hhcGVBc0NoYW5uZWxMYXN0LnNwbGljZSgxLCAxKVswXSk7XG4gIHJldHVybiBbbmV3QXR0cmlidXRlcywgaXNDaGFubmVsc0xhc3QgPyBvdXRwdXRTaGFwZUFzQ2hhbm5lbExhc3QgOiBvdXRwdXRTaGFwZUFzQ2hhbm5lbEZpcnN0XTtcbn07XG5cbmNvbnN0IGdldFVuaWZvcm1BbmRQYWRJbmZvID0gPEF0dHJpYnV0ZVR5cGUgZXh0ZW5kcyBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgfCBNYXhQb29sQXR0cmlidXRlcz4oXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgYXR0cmlidXRlczogQXR0cmlidXRlVHlwZSxcbik6IFtQcm9ncmFtVW5pZm9ybVtdLCBVbmlmb3Jtc0FycmF5VHlwZSwgYm9vbGVhbiwgYm9vbGVhbiwgYm9vbGVhbl0gPT4ge1xuICBjb25zdCBpc0NoYW5uZWxzTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IGtlcm5lbFNpemUgPSBTaGFwZVV0aWwuc2l6ZShhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlKTtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGtlcm5lbFNpemUgfSxcbiAgXTtcbiAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgIHsgbmFtZTogJ291dHB1dFNpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgIHsgbmFtZTogJ2tlcm5lbFNpemUnLCB0eXBlOiAndTMyJyB9LFxuICBdO1xuICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggPD0gMikge1xuICAgIGNvbnN0IGt3ID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZVthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAtIDFdO1xuICAgIGNvbnN0IHN3ID0gYXR0cmlidXRlcy5zdHJpZGVzW2F0dHJpYnV0ZXMuc3RyaWRlcy5sZW5ndGggLSAxXTtcbiAgICBjb25zdCBwd1N0YXJ0ID0gYXR0cmlidXRlcy5wYWRzW2F0dHJpYnV0ZXMucGFkcy5sZW5ndGggLyAyIC0gMV07XG4gICAgY29uc3QgcHdFbmQgPSBhdHRyaWJ1dGVzLnBhZHNbYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAtIDFdO1xuICAgIGNvbnN0IHB3U3RhcnRFbmROb3RaZXJvID0gISEocHdTdGFydCArIHB3RW5kKTtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaChcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBrdyB9LFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHN3IH0sXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcHdTdGFydCB9LFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHB3RW5kIH0sXG4gICAgKTtcbiAgICB1bmlmb3Jtcy5wdXNoKFxuICAgICAgeyBuYW1lOiAna3cnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnc3cnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAncHdTdGFydCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdwd0VuZCcsIHR5cGU6ICd1MzInIH0sXG4gICAgKTtcblxuICAgIGxldCBwaFN0YXJ0RW5kTm90WmVybyA9IGZhbHNlO1xuICAgIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCA9PT0gMikge1xuICAgICAgY29uc3Qga2ggPSBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlW2F0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoIC0gMl07XG4gICAgICBjb25zdCBzaCA9IGF0dHJpYnV0ZXMuc3RyaWRlc1thdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoIC0gMl07XG4gICAgICBjb25zdCBwaFN0YXJ0ID0gYXR0cmlidXRlcy5wYWRzW2F0dHJpYnV0ZXMucGFkcy5sZW5ndGggLyAyIC0gMl07XG4gICAgICBjb25zdCBwaEVuZCA9IGF0dHJpYnV0ZXMucGFkc1thdHRyaWJ1dGVzLnBhZHMubGVuZ3RoIC0gMl07XG4gICAgICBwaFN0YXJ0RW5kTm90WmVybyA9ICEhKHBoU3RhcnQgKyBwaEVuZCk7XG4gICAgICBwcm9ncmFtVW5pZm9ybXMucHVzaChcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGtoIH0sXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzaCB9LFxuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGhTdGFydCB9LFxuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGhFbmQgfSxcbiAgICAgICk7XG5cbiAgICAgIHVuaWZvcm1zLnB1c2goXG4gICAgICAgIHsgbmFtZTogJ2toJywgdHlwZTogJ3UzMicgfSxcbiAgICAgICAgeyBuYW1lOiAnc2gnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgICB7IG5hbWU6ICdwaFN0YXJ0JywgdHlwZTogJ3UzMicgfSxcbiAgICAgICAgeyBuYW1lOiAncGhFbmQnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIFtwcm9ncmFtVW5pZm9ybXMsIHVuaWZvcm1zLCB0cnVlLCBwd1N0YXJ0RW5kTm90WmVybywgcGhTdGFydEVuZE5vdFplcm9dO1xuICB9IGVsc2Uge1xuICAgIGlmIChpc0NoYW5uZWxzTGFzdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdQb29saW5nIHdpdGgga2VybmVsU2hhcGUubGVuZ3RoID4gMiBpcyBub3Qgc3VwcG9ydGVkIGZvciBOSFdDIGZvcm1hdC4nKTtcbiAgICB9XG4gICAgY29uc3Qga2VybmVsU3RyaWRlcyA9IFNoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlKTtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaChcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBrZXJuZWxTdHJpZGVzIH0sXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXR0cmlidXRlcy5wYWRzIH0sXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXR0cmlidXRlcy5zdHJpZGVzIH0sXG4gICAgKTtcbiAgICB1bmlmb3Jtcy5wdXNoKFxuICAgICAgeyBuYW1lOiAna2VybmVsU3RyaWRlcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGtlcm5lbFN0cmlkZXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdwYWRzJywgdHlwZTogJ3UzMicsIGxlbmd0aDogYXR0cmlidXRlcy5wYWRzLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnc3RyaWRlcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGF0dHJpYnV0ZXMuc3RyaWRlcy5sZW5ndGggfSxcbiAgICApO1xuXG4gICAgY29uc3QgaGFzUGFkcyA9IGF0dHJpYnV0ZXMucGFkcy5yZWR1Y2UoKHN1bSwgY3VyKSA9PiBzdW0gKyBjdXIpO1xuICAgIHJldHVybiBbcHJvZ3JhbVVuaWZvcm1zLCB1bmlmb3JtcywgISFoYXNQYWRzLCBmYWxzZSwgZmFsc2VdO1xuICB9XG59O1xuXG5jb25zdCBnZW5lcmF0ZVBvb2xpbmdDb2RlID0gPEF0dHJpYnV0ZVR5cGUgZXh0ZW5kcyBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgfCBNYXhQb29sQXR0cmlidXRlcz4oXG4gIHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyLFxuICB4OiBJbmRpY2VzSGVscGVyLFxuICByYW5rOiBudW1iZXIsXG4gIG91dHB1dFNoYXBlUmFuazogbnVtYmVyLFxuICBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGVUeXBlLFxuICBvcDE6IHN0cmluZyxcbiAgb3AyOiBzdHJpbmcsXG4gIHN0YXJ0OiBudW1iZXIsXG4gIHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSxcbiAgaGFzUGFkczogYm9vbGVhbixcbiAgcHdTdGFydEVuZE5vdFplcm86IGJvb2xlYW4sXG4gIHBoU3RhcnRFbmROb3RaZXJvOiBib29sZWFuLFxuKTogc3RyaW5nID0+IHtcbiAgY29uc3QgaXNDaGFubmVsc0xhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBkYXRhVHlwZSA9IHgudHlwZS52YWx1ZTtcbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIHgudHlwZS50ZW5zb3IsIG91dHB1dFNoYXBlUmFuayk7XG5cbiAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoIDw9IDIpIHtcbiAgICBsZXQgY29kZVcgPSAnJztcbiAgICBsZXQgY29kZUggPSAnJztcbiAgICBsZXQgY29kZUhFbmQgPSAnJztcbiAgICBjb25zdCBkaW1JZHhXID0gcmFuayAtIChpc0NoYW5uZWxzTGFzdCA/IDIgOiAxKTtcbiAgICBpZiAocHdTdGFydEVuZE5vdFplcm8pIHtcbiAgICAgIGNvZGVXID0gYFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGk6IHUzMiA9IDB1OyBpIDwgdW5pZm9ybXMua3c7IGkrKykge1xuICAgICAgICAgICAgICAgICAgeEluZGljZXNbJHtkaW1JZHhXfV0gPSBpbmRpY2VzWyR7ZGltSWR4V31dICogdW5pZm9ybXMuc3cgLSB1bmlmb3Jtcy5wd1N0YXJ0ICsgaTtcbiAgICAgICAgICAgICAgICAgIGlmICh4SW5kaWNlc1ske2RpbUlkeFd9XSA8IDAgfHwgeEluZGljZXNbJHtkaW1JZHhXfV1cbiAgICAgICAgICAgICAgICAgICAgICA+PSB1bmlmb3Jtcy54X3NoYXBlWyR7ZGltSWR4V31dKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhZCsrO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGxldCB4X3ZhbCA9IHhbJHt4LmluZGljZXNUb09mZnNldCgneEluZGljZXMnKX1dO1xuICAgICAgICAgICAgICAgICAgJHtvcDF9XG4gICAgICAgICAgICAgICAgfWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGVXID0gYFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGk6IHUzMiA9IDB1OyBpIDwgdW5pZm9ybXMua3c7IGkrKykge1xuICAgICAgICAgICAgICAgICAgeEluZGljZXNbJHtkaW1JZHhXfV0gPSBpbmRpY2VzWyR7ZGltSWR4V31dICogdW5pZm9ybXMuc3cgLSB1bmlmb3Jtcy5wd1N0YXJ0ICsgaTtcbiAgICAgICAgICAgICAgICAgIGxldCB4X3ZhbCA9IHhbJHt4LmluZGljZXNUb09mZnNldCgneEluZGljZXMnKX1dO1xuICAgICAgICAgICAgICAgICAgJHtvcDF9XG4gICAgICAgICAgICAgICAgfWA7XG4gICAgfVxuXG4gICAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoID09PSAyKSB7XG4gICAgICBjb25zdCBkaW1JZHhIID0gcmFuayAtIChpc0NoYW5uZWxzTGFzdCA/IDMgOiAyKTtcbiAgICAgIGlmIChwaFN0YXJ0RW5kTm90WmVybykge1xuICAgICAgICBjb2RlSCA9IGBcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqOiB1MzIgPSAwdTsgaiA8IHVuaWZvcm1zLmtoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgIHhJbmRpY2VzWyR7ZGltSWR4SH1dID0gaW5kaWNlc1ske2RpbUlkeEh9XSAqIHVuaWZvcm1zLnNoIC0gdW5pZm9ybXMucGhTdGFydCArIGo7XG4gICAgICAgICAgICAgICAgICBpZiAoeEluZGljZXNbJHtkaW1JZHhIfV0gPCAwIHx8IHhJbmRpY2VzWyR7ZGltSWR4SH1dID49IHVuaWZvcm1zLnhfc2hhcGVbJHtkaW1JZHhIfV0pIHtcbiAgICAgICAgICAgICAgICAgICAgcGFkICs9IGkzMih1bmlmb3Jtcy5rdyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29kZUggPSBgXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgajogdTMyID0gMHU7IGogPCB1bmlmb3Jtcy5raDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICB4SW5kaWNlc1ske2RpbUlkeEh9XSA9IGluZGljZXNbJHtkaW1JZHhIfV0gKiB1bmlmb3Jtcy5zaCAtIHVuaWZvcm1zLnBoU3RhcnQgKyBqO1xuICAgICAgICAgICAgICAgIGA7XG4gICAgICB9XG4gICAgICBjb2RlSEVuZCA9IGBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgYDtcbiAgICB9XG5cbiAgICBjb25zdCBwb29saW5nQ29kZSA9IGBcbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoeCwgb3V0cHV0KX1cblxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dFNpemUnKX1cblxuICAgICAgICAgICAgICBsZXQgaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgICAgICAgICAgdmFyIHhJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuXG4gICAgICAgICAgICAgIHZhciB2YWx1ZSA9ICR7ZGF0YVR5cGV9KCR7c3RhcnR9KTtcbiAgICAgICAgICAgICAgdmFyIHBhZCA9IDA7XG4gICAgICAgICAgICAgICR7Y29kZUh9XG4gICAgICAgICAgICAgICR7Y29kZVd9XG4gICAgICAgICAgICAgICR7Y29kZUhFbmR9XG4gICAgICAgICAgICAgICR7b3AyfVxuXG4gICAgICAgICAgICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9IHZhbHVlO1xuICAgICAgICAgICAgfWA7XG4gICAgcmV0dXJuIHBvb2xpbmdDb2RlO1xuICB9IGVsc2Uge1xuICAgIGlmIChpc0NoYW5uZWxzTGFzdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdQb29saW5nIHdpdGgga2VybmVsU2hhcGUubGVuZ3RoID4gMiBpcyBub3Qgc3VwcG9ydGVkIGZvciBOSFdDIGZvcm1hdC4nKTtcbiAgICB9XG4gICAgY29uc3Qgc3RyaWRlc1JhbmsgPSBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aDtcbiAgICBjb25zdCBwYWRzUmFuayA9IGF0dHJpYnV0ZXMucGFkcy5sZW5ndGg7XG4gICAgbGV0IHBhZENvZGUgPSAnJztcbiAgICBpZiAoaGFzUGFkcykge1xuICAgICAgcGFkQ29kZSA9IGBcbiAgICAgICAgICAgICAgICBpZiAoeEluZGljZXNbal0gPj0gdW5pZm9ybXMueF9zaGFwZVtqXSkge1xuICAgICAgICAgICAgICAgICAgcGFkKys7XG4gICAgICAgICAgICAgICAgICBpc1BhZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKCFpc1BhZCkge1xuICAgICAgICAgICAgICAgIGxldCB4X3ZhbCA9IHhbJHt4LmluZGljZXNUb09mZnNldCgneEluZGljZXMnKX1dO1xuICAgICAgICAgICAgICAgICR7b3AxfVxuICAgICAgICAgICAgICB9YDtcbiAgICB9IGVsc2Uge1xuICAgICAgcGFkQ29kZSA9IGBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBsZXQgeF92YWwgPSB4WyR7eC5pbmRpY2VzVG9PZmZzZXQoJ3hJbmRpY2VzJyl9XTtcbiAgICAgICAgICAgICAgJHtvcDF9XG4gICAgICAgICAgICBgO1xuICAgIH1cbiAgICBjb25zdCBwb29saW5nQ29kZSA9IGBcbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoeCwgb3V0cHV0KX1cblxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dFNpemUnKX1cbiAgICAgICAgICAgICAgbGV0IGluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICAgICAgICAgIHZhciB4SW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcblxuICAgICAgICAgICAgICB2YXIgb2Zmc2V0czogYXJyYXk8dTMyLCAke3N0cmlkZXNSYW5rfT47XG5cbiAgICAgICAgICAgICAgdmFyIHZhbHVlID0gJHtkYXRhVHlwZX0oJHtzdGFydH0pO1xuICAgICAgICAgICAgICB2YXIgcGFkID0gMDtcbiAgICAgICAgICAgICAgdmFyIGlzUGFkID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgZm9yICh2YXIgaTogdTMyID0gMHU7IGkgPCB1bmlmb3Jtcy5rZXJuZWxTaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgb2Zmc2V0ID0gaTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMHU7IGogPCAke3N0cmlkZXNSYW5rIC0gMX11OyBqKyspIHtcbiAgICAgICAgICAgICAgICAgIG9mZnNldHNbal0gPSBvZmZzZXQgLyAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMua2VybmVsU3RyaWRlcycsICdqJywgc3RyaWRlc1JhbmspfTtcbiAgICAgICAgICAgICAgICAgIG9mZnNldCAtPSBvZmZzZXRzW2pdICogJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLmtlcm5lbFN0cmlkZXMnLCAnaicsIHN0cmlkZXNSYW5rKX07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG9mZnNldHNbJHtzdHJpZGVzUmFuayAtIDF9XSA9IG9mZnNldDtcblxuICAgICAgICAgICAgICAgIGlzUGFkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9ICR7cmFuayAtIHN0cmlkZXNSYW5rfXU7IGogPCAke3Jhbmt9dTsgaisrKSB7XG4gICAgICAgICAgICAgICAgICB4SW5kaWNlc1tqXSA9IGluZGljZXNbal0gKiAke2dldEVsZW1lbnRBdChcbiAgICAgICAgICAgICAgICAgICAgJ3VuaWZvcm1zLnN0cmlkZXMnLFxuICAgICAgICAgICAgICAgICAgICBgaiAtICR7cmFuayAtIHN0cmlkZXNSYW5rfXVgLFxuICAgICAgICAgICAgICAgICAgICBzdHJpZGVzUmFuayxcbiAgICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgICAgICAgICsgb2Zmc2V0c1tqIC0gJHtyYW5rIC0gc3RyaWRlc1Jhbmt9dV0gLSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMucGFkcycsICdqIC0gMnUnLCBwYWRzUmFuayl9O1xuICAgICAgICAgICAgICAgICAgJHtwYWRDb2RlfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICR7b3AyfVxuXG4gICAgICAgICAgICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9IHZhbHVlO1xuICAgICAgICAgICAgfWA7XG4gICAgcmV0dXJuIHBvb2xpbmdDb2RlO1xuICB9XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIEZvcm1hdEF0dHJpYnV0ZXMge1xuICByZWFkb25seSBmb3JtYXQ6ICdOSFdDJyB8ICdOQ0hXJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQb29sQ29tbW9uQXR0cmlidXRlcyBleHRlbmRzIEZvcm1hdEF0dHJpYnV0ZXMge1xuICByZWFkb25seSBhdXRvUGFkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNlaWxNb2RlOiBudW1iZXI7XG4gIHJlYWRvbmx5IGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IHBhZHM6IHJlYWRvbmx5IG51bWJlcltdO1xufVxuXG5jb25zdCBjcmVhdGVTaGFkZXJLZXlGcm9tQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBQb29sQ29tbW9uQXR0cmlidXRlcyk6IHN0cmluZyA9PlxuICBgJHthdHRyaWJ1dGVzLmZvcm1hdH07JHthdHRyaWJ1dGVzLmNlaWxNb2RlfTske2F0dHJpYnV0ZXMuYXV0b1BhZH07JHthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aH1gO1xuXG5jb25zdCBjcmVhdGVBdmVyYWdlUG9vbFNoYWRlcktleUZyb21BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyk6IHN0cmluZyA9PlxuICBgJHtjcmVhdGVTaGFkZXJLZXlGcm9tQXR0cmlidXRlcyhhdHRyaWJ1dGVzKX07JHthdHRyaWJ1dGVzLmNvdW50SW5jbHVkZVBhZH1gO1xuXG5jb25zdCBjcmVhdGVNYXhQb29sU2hhZGVyS2V5RnJvbUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogTWF4UG9vbEF0dHJpYnV0ZXMpOiBzdHJpbmcgPT5cbiAgYCR7Y3JlYXRlU2hhZGVyS2V5RnJvbUF0dHJpYnV0ZXMoYXR0cmlidXRlcyl9OyR7YXR0cmlidXRlcy5zdG9yYWdlT3JkZXJ9OyR7YXR0cmlidXRlcy5kaWxhdGlvbnN9YDtcblxuY29uc3QgcGFyc2VQb29sQ29tbW9uQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFBvb2xDb21tb25BdHRyaWJ1dGVzID0+ICh7XG4gIGZvcm1hdDogYXR0cmlidXRlcy5mb3JtYXQgYXMgRm9ybWF0QXR0cmlidXRlc1snZm9ybWF0J10sXG4gIGF1dG9QYWQ6IFsnTk9UU0VUJywgJ1ZBTElEJywgJ1NBTUVfVVBQRVInLCAnU0FNRV9MT1dFUiddW2F0dHJpYnV0ZXMuYXV0b19wYWQgYXMgbnVtYmVyXSxcbiAgY2VpbE1vZGU6IGF0dHJpYnV0ZXMuY2VpbF9tb2RlIGFzIG51bWJlcixcbiAga2VybmVsU2hhcGU6IGF0dHJpYnV0ZXMua2VybmVsX3NoYXBlIGFzIFtudW1iZXIsIG51bWJlcl0sXG4gIHN0cmlkZXM6IGF0dHJpYnV0ZXMuc3RyaWRlcyBhcyBbbnVtYmVyLCBudW1iZXJdLFxuICBwYWRzOiBhdHRyaWJ1dGVzLnBhZHMgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG59KTtcblxuZXhwb3J0IGludGVyZmFjZSBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgZXh0ZW5kcyBQb29sQ29tbW9uQXR0cmlidXRlcywgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgY291bnRJbmNsdWRlUGFkOiBib29sZWFuO1xufVxuXG5jb25zdCBjcmVhdGVBdmVyYWdlUG9vbFByb2dyYW1JbmZvID0gKFxuICBuYW1lOiBzdHJpbmcsXG4gIGlucHV0OiBUZW5zb3JWaWV3LFxuICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLFxuICBhdHRyaWJ1dGVzOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IFthZGp1c3RlZEF0dHJpYnV0ZXMsIG91dHB1dFNoYXBlXSA9IGdldEFkanVzdGVkUG9vbEF0dHJpYnV0ZXNBbmRPdXRwdXRTaGFwZShcbiAgICBpbnB1dCxcbiAgICBhdHRyaWJ1dGVzLFxuICAgIGlzR2xvYmFsT3BlcmF0b3IsXG4gICk7XG4gIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXQuZGF0YVR5cGUsIGlucHV0LmRpbXMubGVuZ3RoKTtcbiAgY29uc3QgZGF0YVR5cGUgPSB4LnR5cGUudmFsdWU7XG5cbiAgY29uc3Qgb3AxID0gJ3ZhbHVlICs9IHhfdmFsOyc7XG4gIGxldCBvcDIgPSAnJztcbiAgaWYgKGFkanVzdGVkQXR0cmlidXRlcy5jb3VudEluY2x1ZGVQYWQpIHtcbiAgICBvcDIgKz0gYHZhbHVlIC89ICR7ZGF0YVR5cGV9KHVuaWZvcm1zLmtlcm5lbFNpemUpO2A7XG4gIH0gZWxzZSB7XG4gICAgb3AyICs9IGB2YWx1ZSAvPSAke2RhdGFUeXBlfShpMzIodW5pZm9ybXMua2VybmVsU2l6ZSkgLSBwYWQpO2A7XG4gIH1cbiAgY29uc3QgW3Byb2dyYW1Vbmlmb3JtcywgdW5pZm9ybXMsIGhhc1BhZHMsIHB3U3RhcnRFbmROb3RaZXJvLCBwaFN0YXJ0RW5kTm90WmVyb10gPSBnZXRVbmlmb3JtQW5kUGFkSW5mbyhcbiAgICBvdXRwdXRTaGFwZSxcbiAgICBhZGp1c3RlZEF0dHJpYnV0ZXMsXG4gICk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0LmRpbXMsIG91dHB1dFNoYXBlKSk7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWydyYW5rJ107XG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX07JHtoYXNQYWRzfTske3B3U3RhcnRFbmROb3RaZXJvfTske3BoU3RhcnRFbmROb3RaZXJvfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llcyxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0LmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwoU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlOiAoc2hhZGVySGVscGVyKSA9PlxuICAgICAgZ2VuZXJhdGVQb29saW5nQ29kZShcbiAgICAgICAgc2hhZGVySGVscGVyLFxuICAgICAgICB4LFxuICAgICAgICBpbnB1dC5kaW1zLmxlbmd0aCxcbiAgICAgICAgb3V0cHV0U2hhcGUubGVuZ3RoLFxuICAgICAgICBhZGp1c3RlZEF0dHJpYnV0ZXMsXG4gICAgICAgIG9wMSxcbiAgICAgICAgb3AyLFxuICAgICAgICAwLjAsXG4gICAgICAgIHVuaWZvcm1zLFxuICAgICAgICBoYXNQYWRzLFxuICAgICAgICBwd1N0YXJ0RW5kTm90WmVybyxcbiAgICAgICAgcGhTdGFydEVuZE5vdFplcm8sXG4gICAgICApLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQXZlcmFnZVBvb2xBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgY291bnRJbmNsdWRlUGFkID0gKGF0dHJpYnV0ZXMuY291bnRfaW5jbHVkZV9wYWQgYXMgbnVtYmVyKSA9PT0gMCA/IGZhbHNlIDogdHJ1ZTtcblxuICBjb25zdCBhdHRyID0gcGFyc2VQb29sQ29tbW9uQXR0cmlidXRlcyhhdHRyaWJ1dGVzKTtcbiAgLy8gVE9ETzogc3VwcG9ydCBhdHRyaWJ1dGUgJ2NlaWxfbW9kZSdcbiAgaWYgKGF0dHIuY2VpbE1vZGUgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3VzaW5nIGNlaWwoKSBpbiBzaGFwZSBjb21wdXRhdGlvbiBpcyBub3QgeWV0IHN1cHBvcnRlZCBmb3IgQXZlcmFnZVBvb2wnKTtcbiAgfVxuICBjb25zdCBhdmVyYWdlUG9vbEF0dHJpYnV0ZXMgPSB7IGNvdW50SW5jbHVkZVBhZCwgLi4uYXR0ciwgY2FjaGVLZXk6ICcnIH07XG4gIHJldHVybiB7IC4uLmF2ZXJhZ2VQb29sQXR0cmlidXRlcywgY2FjaGVLZXk6IGNyZWF0ZUF2ZXJhZ2VQb29sU2hhZGVyS2V5RnJvbUF0dHJpYnV0ZXMoYXZlcmFnZVBvb2xBdHRyaWJ1dGVzKSB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGF2ZXJhZ2VQb29sID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlQXZlcmFnZVBvb2xQcm9ncmFtSW5mbygnQXZlcmFnZVBvb2wnLCBjb250ZXh0LmlucHV0c1swXSwgZmFsc2UsIGF0dHJpYnV0ZXMpKTtcbn07XG5cbmNvbnN0IGdsb2JhbFBvb2xBdHRyaWJ1dGVzID0ge1xuICBhdXRvUGFkOiAnJyxcbiAgY2VpbE1vZGU6IDAsXG4gIGNvdW50SW5jbHVkZVBhZDogZmFsc2UsXG4gIGtlcm5lbFNoYXBlOiBbXSxcbiAgc3RyaWRlczogW10sXG4gIHBhZHM6IFtdLFxuICBzdG9yYWdlT3JkZXI6IDAsXG4gIGRpbGF0aW9uczogW10sXG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VHbG9iYWxBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBmb3JtYXQgPSBhdHRyaWJ1dGVzLmZvcm1hdCBhcyBGb3JtYXRBdHRyaWJ1dGVzWydmb3JtYXQnXTtcbiAgcmV0dXJuIHsgZm9ybWF0LCAuLi5nbG9iYWxQb29sQXR0cmlidXRlcywgY2FjaGVLZXk6IGZvcm1hdCB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGdsb2JhbEF2ZXJhZ2VQb29sID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlQXZlcmFnZVBvb2xQcm9ncmFtSW5mbygnR2xvYmFsQXZlcmFnZVBvb2wnLCBjb250ZXh0LmlucHV0c1swXSwgdHJ1ZSwgYXR0cmlidXRlcykpO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBNYXhQb29sQXR0cmlidXRlcyBleHRlbmRzIFBvb2xDb21tb25BdHRyaWJ1dGVzLCBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBzdG9yYWdlT3JkZXI6IG51bWJlcjtcbiAgcmVhZG9ubHkgZGlsYXRpb25zOiBudW1iZXJbXTtcbn1cblxuY29uc3QgY3JlYXRlTWF4UG9vbFByb2dyYW1JbmZvID0gKFxuICBuYW1lOiBzdHJpbmcsXG4gIGlucHV0OiBUZW5zb3JWaWV3LFxuICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLFxuICBhdHRyaWJ1dGVzOiBNYXhQb29sQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgW2FkanVzdGVkQXR0cmlidXRlcywgb3V0cHV0U2hhcGVdID0gZ2V0QWRqdXN0ZWRQb29sQXR0cmlidXRlc0FuZE91dHB1dFNoYXBlKFxuICAgIGlucHV0LFxuICAgIGF0dHJpYnV0ZXMsXG4gICAgaXNHbG9iYWxPcGVyYXRvcixcbiAgKTtcbiAgY29uc3Qgb3AxID0gYFxuICAgICAgdmFsdWUgPSBtYXgoeF92YWwsIHZhbHVlKTtcbiAgICBgO1xuICBjb25zdCBvcDIgPSAnJztcbiAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dC5kYXRhVHlwZSwgaW5wdXQuZGltcy5sZW5ndGgpO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsncmFuayddO1xuICBjb25zdCBbcHJvZ3JhbVVuaWZvcm1zLCB1bmlmb3JtcywgaGFzUGFkcywgcHdTdGFydEVuZE5vdFplcm8sIHBoU3RhcnRFbmROb3RaZXJvXSA9IGdldFVuaWZvcm1BbmRQYWRJbmZvKFxuICAgIG91dHB1dFNoYXBlLFxuICAgIGFkanVzdGVkQXR0cmlidXRlcyxcbiAgKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXQuZGltcywgb3V0cHV0U2hhcGUpKTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fTske2hhc1BhZHN9OyR7cHdTdGFydEVuZE5vdFplcm99OyR7cGhTdGFydEVuZE5vdFplcm99YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXQuZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2U6IChzaGFkZXJIZWxwZXIpID0+XG4gICAgICBnZW5lcmF0ZVBvb2xpbmdDb2RlKFxuICAgICAgICBzaGFkZXJIZWxwZXIsXG4gICAgICAgIHgsXG4gICAgICAgIGlucHV0LmRpbXMubGVuZ3RoLFxuICAgICAgICBvdXRwdXRTaGFwZS5sZW5ndGgsXG4gICAgICAgIGFkanVzdGVkQXR0cmlidXRlcyxcbiAgICAgICAgb3AxLFxuICAgICAgICBvcDIsXG4gICAgICAgIGlucHV0LmRhdGFUeXBlID09PSBEYXRhVHlwZS5mbG9hdDE2ID8gLTY1NTA0IDogLTFlNSxcbiAgICAgICAgdW5pZm9ybXMsXG4gICAgICAgIGhhc1BhZHMsXG4gICAgICAgIHB3U3RhcnRFbmROb3RaZXJvLFxuICAgICAgICBwaFN0YXJ0RW5kTm90WmVybyxcbiAgICAgICksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgbWF4UG9vbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogTWF4UG9vbEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlTWF4UG9vbFByb2dyYW1JbmZvKCdNYXhQb29sJywgY29udGV4dC5pbnB1dHNbMF0sIGZhbHNlLCBhdHRyaWJ1dGVzKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VNYXhQb29sQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IE1heFBvb2xBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3Qgc3RvcmFnZU9yZGVyID0gYXR0cmlidXRlcy5zdG9yYWdlX29yZGVyIGFzIG51bWJlcjtcbiAgY29uc3QgZGlsYXRpb25zID0gYXR0cmlidXRlcy5kaWxhdGlvbnMgYXMgW251bWJlciwgbnVtYmVyXTtcblxuICBjb25zdCBhdHRyID0gcGFyc2VQb29sQ29tbW9uQXR0cmlidXRlcyhhdHRyaWJ1dGVzKTtcbiAgLy8gVE9ETzogc3VwcG9ydCBhdHRyaWJ1dGUgJ2NlaWxfbW9kZScgYW5kICdzdG9yYWdlX29yZGVyJ1xuICBpZiAoc3RvcmFnZU9yZGVyICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb2x1bW4gbWFqb3Igc3RvcmFnZSBvcmRlciBpcyBub3QgeWV0IHN1cHBvcnRlZCBmb3IgTWF4UG9vbCcpO1xuICB9XG4gIGlmIChhdHRyLmNlaWxNb2RlICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd1c2luZyBjZWlsKCkgaW4gc2hhcGUgY29tcHV0YXRpb24gaXMgbm90IHlldCBzdXBwb3J0ZWQgZm9yIE1heFBvb2wnKTtcbiAgfVxuICBjb25zdCBtYXhQb29sQXR0cmlidXRlcyA9IHsgc3RvcmFnZU9yZGVyLCBkaWxhdGlvbnMsIC4uLmF0dHIsIGNhY2hlS2V5OiAnJyB9O1xuICByZXR1cm4geyAuLi5tYXhQb29sQXR0cmlidXRlcywgY2FjaGVLZXk6IGNyZWF0ZU1heFBvb2xTaGFkZXJLZXlGcm9tQXR0cmlidXRlcyhtYXhQb29sQXR0cmlidXRlcykgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdsb2JhbE1heFBvb2xBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogTWF4UG9vbEF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBmb3JtYXQgPSBhdHRyaWJ1dGVzLmZvcm1hdCBhcyBGb3JtYXRBdHRyaWJ1dGVzWydmb3JtYXQnXTtcbiAgcmV0dXJuIHsgZm9ybWF0LCAuLi5nbG9iYWxQb29sQXR0cmlidXRlcywgY2FjaGVLZXk6IGZvcm1hdCB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGdsb2JhbE1heFBvb2wgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IE1heFBvb2xBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZU1heFBvb2xQcm9ncmFtSW5mbygnR2xvYmFsTWF4UG9vbCcsIGNvbnRleHQuaW5wdXRzWzBdLCB0cnVlLCBhdHRyaWJ1dGVzKSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRNYXhDb21wb25lbnRzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIERlcXVhbnRpemVMaW5lckF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICBheGlzOiBudW1iZXI7XG4gIGJsb2NrU2l6ZTogbnVtYmVyO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogRGVxdWFudGl6ZUxpbmVyQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBpZiAoaW5wdXRzLmxlbmd0aCA8IDIgfHwgaW5wdXRzLmxlbmd0aCA+IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0RlcXVhbnRpemVMaW5lYXIgcmVxdWlyZXMgMiBvciAzIGlucHV0cy4nKTtcbiAgfVxuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMV0uZGltcyA9PT0gaW5wdXRzWzJdLmRpbXMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3gtc2NhbGUgYW5kIHgtemVyby1wb2ludCBtdXN0IGhhdmUgdGhlIHNhbWUgc2hhcGUuJyk7XG4gIH1cbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgaW5wdXRzWzBdLmRhdGFUeXBlICE9PSBpbnB1dHNbMl0uZGF0YVR5cGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3ggYW5kIHgtemVyby1wb2ludCBtdXN0IGhhdmUgdGhlIHNhbWUgZGF0YSB0eXBlLicpO1xuICB9XG4gIGlmIChpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDAgJiYgaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSAxICYmIGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzY2FsZSBpbnB1dCBtdXN0IGJlIGEgc2NhbGFyLCBhIDFEIHRlbnNvciwgb3IgaGF2ZSB0aGUgc2FtZSByYW5rIGFzIHRoZSBpbnB1dCB0ZW5zb3IuJyk7XG4gIH1cbiAgLy8gdmFsaWRhdGUgc2NhbGUgYW5kIHplcm8tcG9pbnQgaW5wdXQgc2hhcGVzXG4gIGlmIChpbnB1dHMubGVuZ3RoID4gMikge1xuICAgIC8vIHplcm8tcG9pbnQgaW5wdXQgdHlwZSBzaG91bGQgYmUgdGhlIHNhbWUgYXMgaW5wdXQgZGF0YSB0eXBlLlxuICAgIGlmIChpbnB1dHNbMF0uZGF0YVR5cGUgIT09IGlucHV0c1syXS5kYXRhVHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd4IGFuZCB4LXplcm8tcG9pbnQgbXVzdCBoYXZlIHRoZSBzYW1lIGRhdGEgdHlwZS4nKTtcbiAgICB9XG4gICAgLy8gU2NhbGUgYW5kIHplcm8tcG9pbnQgaW5wdXRzIG11c3QgaGF2ZSB0aGUgc2FtZSBzaGFwZVxuICAgIGlmIChpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IGlucHV0c1syXS5kaW1zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzY2FsZSBhbmQgemVyby1wb2ludCBpbnB1dHMgbXVzdCBoYXZlIHRoZSBzYW1lIHJhbmsuJyk7XG4gICAgfVxuICAgIGlmICghaW5wdXRzWzFdLmRpbXMubWFwKChkLCBpKSA9PiBkID09PSBpbnB1dHNbMl0uZGltc1tpXSkucmVkdWNlKChhLCBiKSA9PiBhICYmIGIsIHRydWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NjYWxlIGFuZCB6ZXJvLXBvaW50IGlucHV0cyBtdXN0IGhhdmUgdGhlIHNhbWUgc2hhcGUuJyk7XG4gICAgfVxuICB9XG4gIC8vIFZhbGlkYXRlIGJsb2NrU2l6ZVxuICBpZiAoYXR0cmlidXRlcy5ibG9ja1NpemUgPiAwKSB7XG4gICAgLy8gQmxvY2sgcXVuYXRpemF0aW9uXG4gICAgaWYgKGlucHV0c1sxXS5kaW1zLmxlbmd0aCA9PT0gMCB8fCAoaW5wdXRzWzFdLmRpbXMubGVuZ3RoID09PSAxICYmIGlucHV0c1sxXS5kaW1zWzBdID09PSAxKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdibG9ja1NpemUgbXVzdCBiZSBzZXQgb25seSBmb3IgYmxvY2sgcXVhbnRpemF0aW9uLicpO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICAhaW5wdXRzWzFdLmRpbXMubWFwKChkLCBpKSA9PiBpID09PSBhdHRyaWJ1dGVzLmF4aXMgfHwgZCA9PT0gaW5wdXRzWzBdLmRpbXNbaV0pLnJlZHVjZSgoYSwgYikgPT4gYSAmJiBiLCB0cnVlKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGb3IgYmxvY2sgcXVuYXRpemF0aW9uLCBzY2FsZSBpbnB1dCBzaGFwZSB0byBtYXRjaCB0aGUgaW5wdXQgc2hhcGUgZXhjZXB0IGZvciB0aGUgYXhpcycpO1xuICAgIH1cbiAgICAvLyBTY2FsZSBpbnB1dCByYW5rIHNob3VsZCBiZSBzYW1lIGFzIHRoZSBpbnB1dCByYW5rXG4gICAgaWYgKGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZvciBibG9jayBxdW5hdGl6YXRpb24gdGhlIHNjYWxlIGlucHV0IHJhbmsgbXVzdCBiZSB0aGUgc2FtZSBhcyB0aGUgeCByYW5rLicpO1xuICAgIH1cbiAgICBjb25zdCBkSSA9IGlucHV0c1swXS5kaW1zW2F0dHJpYnV0ZXMuYXhpc107XG4gICAgY29uc3Qgc2kgPSBpbnB1dHNbMV0uZGltc1thdHRyaWJ1dGVzLmF4aXNdO1xuICAgIGlmIChhdHRyaWJ1dGVzLmJsb2NrU2l6ZSA8IE1hdGguY2VpbChkSSAvIHNpKSB8fCBhdHRyaWJ1dGVzLmJsb2NrU2l6ZSA+IE1hdGguY2VpbChkSSAvIChzaSAtIDEpIC0gMSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignYmxvY2tTaXplIG11c3QgYmUgd2l0aCBpbiB0aGUgcmFuZ2UgW2NlaWwoZEkgLyBTaSksIGNlaWwoZEkgLyAoU2kgLSAxKSAtIDEpXS4nKTtcbiAgICB9XG4gIH1cbn07XG5cbmNvbnN0IGNyZWF0ZURlcXVhbnRpemVMaW5lYXJQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IERlcXVhbnRpemVMaW5lckF0dHJpYnV0ZXMsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGF4aXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhpcyhhdHRyaWJ1dGVzLmF4aXMsIGlucHV0c1swXS5kaW1zLmxlbmd0aCk7XG4gIGNvbnN0IGlucHV0VHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgaXNTaWduZWQgPSBpbnB1dFR5cGUgPT09IERhdGFUeXBlLmludDg7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7IC8vIG91dHB1dCBzaGFwZSBpcyBzYW1lIGFzIHRoZSBpbnB1dCBzaGFwZVxuICBjb25zdCBkYXRhVHlwZSA9IGlucHV0c1sxXS5kYXRhVHlwZTsgLy8gb3V0cHV0IHR5cGUgaXMgc2FtZSBhcyB0aGUgdGhlIHNjYWxlIGlucHV0IHR5cGVcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgY29uc3QgaXNQYWNrZWQgPSBpbnB1dFR5cGUgPT09IERhdGFUeXBlLmludDggfHwgaW5wdXRUeXBlID09PSBEYXRhVHlwZS51aW50ODtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlzUGFja2VkID8gW01hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShpbnB1dHNbMF0uZGltcykgLyA0KV0gOiBpbnB1dHNbMF0uZGltcztcbiAgY29uc3Qgc2NhbGVTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICBjb25zdCB6ZXJvUG9pbnRJbnB1dCA9IGlucHV0cy5sZW5ndGggPiAyID8gaW5wdXRzWzJdIDogdW5kZWZpbmVkO1xuICBjb25zdCB6ZXJvUG9pbnRTaGFwZSA9IHplcm9Qb2ludElucHV0XG4gICAgPyBpc1BhY2tlZFxuICAgICAgPyBbTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKHplcm9Qb2ludElucHV0LmRpbXMpIC8gNCldXG4gICAgICA6IHplcm9Qb2ludElucHV0LmRpbXNcbiAgICA6IHVuZGVmaW5lZDtcbiAgLy8gU2NhbGVzIGlucHV0IGlzIGEgc2NhbGVyIGZvciBwZXItdGVuc29yL3Blci1sYXllciBxdWFudGl6YXRpb24sIDEtRCB0ZW5zb3IgZm9yIHBlci1heGlzIHF1YW50aXphdGlvblxuICAvLyBvciB0ZW5zb3Igd2l0aCBzYW1lIHJhbmsgYXMgaW5wdXQgZm9yIGJsb2NrZWQgcXVhbnRpemF0aW9uLlxuICBjb25zdCBwZXJMYXllclF1YW50aXphdGlvbiA9IHNjYWxlU2hhcGUubGVuZ3RoID09PSAwIHx8IChzY2FsZVNoYXBlLmxlbmd0aCA9PT0gMSAmJiBzY2FsZVNoYXBlWzBdID09PSAxKTtcbiAgY29uc3QgcGVyQXhpc1F1YW50aXphdGlvbiA9IHBlckxheWVyUXVhbnRpemF0aW9uID09PSBmYWxzZSAmJiBzY2FsZVNoYXBlLmxlbmd0aCA9PT0gMTtcbiAgLy8gTGVmdCB1bm5lY2Vzc2FyeSBjb21tZW50ZWQtb3V0IGFzc2lnbm1lbnQgZm9yIGRvY3VtZW50YXRpb25cbiAgLy8gY29uc3QgYmxvY2tRdWFudGl6YXRpb24gPSBwZXJMYXllclF1YW50aXphdGlvbiA9PT0gZmFsc2UgJiYgcGVyQXhpc1F1YW50aXphdGlvbiA9PT0gZmFsc2U7XG4gIGNvbnN0IG1heENvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKG91dHB1dFNpemUpO1xuICBjb25zdCB1c2VDb21wb25lbnRzID0gcGVyTGF5ZXJRdWFudGl6YXRpb24gJiYgKCFpc1BhY2tlZCB8fCBtYXhDb21wb25lbnRzID09PSA0KTtcbiAgY29uc3QgY29tcG9uZW50cyA9IHVzZUNvbXBvbmVudHMgPyBtYXhDb21wb25lbnRzIDogMTtcbiAgY29uc3QgaW5wdXRDb21wb25lbnQgPSB1c2VDb21wb25lbnRzICYmICFpc1BhY2tlZCA/IG1heENvbXBvbmVudHMgOiAxO1xuICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgaXNQYWNrZWQgPyBEYXRhVHlwZS51aW50MzIgOiBpbnB1dFR5cGUsIGlucHV0U2hhcGUubGVuZ3RoLCBpbnB1dENvbXBvbmVudCk7XG4gIGNvbnN0IHNjYWxlID0gaW5wdXRWYXJpYWJsZSgnc2NhbGUnLCBkYXRhVHlwZSwgc2NhbGVTaGFwZS5sZW5ndGgpO1xuICBjb25zdCB6ZXJvUG9pbnQgPSB6ZXJvUG9pbnRJbnB1dFxuICAgID8gaW5wdXRWYXJpYWJsZSgnemVyb19wb2ludCcsIGlzUGFja2VkID8gRGF0YVR5cGUudWludDMyIDogaW5wdXRUeXBlLCB6ZXJvUG9pbnRTaGFwZSEubGVuZ3RoKVxuICAgIDogdW5kZWZpbmVkO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gIGNvbnN0IGlucHV0VmFyaWFibGVzID0gW2lucHV0LCBzY2FsZV07XG4gIGlmICh6ZXJvUG9pbnQpIHtcbiAgICBpbnB1dFZhcmlhYmxlcy5wdXNoKHplcm9Qb2ludCk7XG4gIH1cbiAgY29uc3QgaW5wdXRTaGFwZXMgPSBbaW5wdXRTaGFwZSwgc2NhbGVTaGFwZV07XG4gIGlmICh6ZXJvUG9pbnRJbnB1dCkge1xuICAgIGlucHV0U2hhcGVzLnB1c2goemVyb1BvaW50U2hhcGUhKTtcbiAgfVxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgLyBjb21wb25lbnRzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF4aXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXR0cmlidXRlcy5ibG9ja1NpemUgfSxcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyguLi5pbnB1dFNoYXBlcywgb3V0cHV0U2hhcGUpLFxuICBdO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdheGlzJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2Jsb2NrX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG4gICAgcmV0dXJuIGBcbiAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICAgICAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcblxuICAgICAgICAgIC8vIFNldCBpbnB1dCB4XG4gICAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGlzUGFja2VkKSB7XG4gICAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICBsZXQgaW5wdXQgPSAke2lucHV0LmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4IC8gNCcpfTtcbiAgICAgICAgICAgIGxldCB4X3ZlYyA9ICR7aXNTaWduZWQgPyAndW5wYWNrNHhJOChpbnB1dCknIDogJ3VucGFjazR4VTgoaW5wdXQpJ307XG4gICAgICAgICAgICBsZXQgeF92YWx1ZSA9ICR7Y29tcG9uZW50cyA9PT0gMSA/ICd4X3ZlY1tnbG9iYWxfaWR4ICUgNF0nIDogJ3hfdmVjJ307YDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBgbGV0IHhfdmFsdWUgPSAke2lucHV0LmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4Jyl9O2A7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSkoKX07XG5cbiAgICAgICAgICAvLyBTZXQgc2NhbGUgaW5wdXRcbiAgICAgICAgICAkeygoKSA9PiB7XG4gICAgICAgICAgICBpZiAocGVyTGF5ZXJRdWFudGl6YXRpb24pIHtcbiAgICAgICAgICAgICAgLy8gc2NhbGUgaW5wdXQgaXMgYSBzY2FsYXIgKClcbiAgICAgICAgICAgICAgcmV0dXJuIGBsZXQgc2NhbGVfdmFsdWU9ICR7c2NhbGUuZ2V0QnlPZmZzZXQoJzAnKX1gO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwZXJBeGlzUXVhbnRpemF0aW9uKSB7XG4gICAgICAgICAgICAgIC8vIHNjYWxlIGlucHV0IGlzIGEgMUQgdGVuc29yXG4gICAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICBsZXQgc2NhbGVfaW5kZXggPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsICd1bmlmb3Jtcy5heGlzJyl9O1xuICAgICAgICAgICAgbGV0IHNjYWxlX3ZhbHVlPSAke3NjYWxlLmdldEJ5T2Zmc2V0KCdzY2FsZV9pbmRleCcpfTtgO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gQmxvY2sgcXVhbnRpemF0aW9uLiBTY2FsZSBpbnB1dCByYW5rIGlzIHNhbWUgYXMgaW5wdXQvb3V0cHV0IHJhbmsuXG4gICAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICB2YXIgc2NhbGVfaW5kaWNlczogJHtzY2FsZS50eXBlLmluZGljZXN9ID0gb3V0cHV0X2luZGljZXM7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAke3NjYWxlLmluZGljZXNHZXQoJ3NjYWxlX2luZGljZXMnLCAndW5pZm9ybXMuYXhpcycpfSAvIHVuaWZvcm1zLmJsb2NrX3NpemU7XG4gICAgICAgICAgICAke3NjYWxlLmluZGljZXNTZXQoJ3NjYWxlX2luZGljZXMnLCAndW5pZm9ybXMuYXhpcycsICdpbmRleCcpfTtcbiAgICAgICAgICAgIGxldCBzY2FsZV92YWx1ZT0gJHtzY2FsZS5nZXRCeUluZGljZXMoJ3NjYWxlX2luZGljZXMnKX07YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSgpfTtcblxuICAgICAgICAgIC8vIFNldCB6ZXJvLXBvaW50IGlucHV0XG4gICAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHplcm9Qb2ludCkge1xuICAgICAgICAgICAgICBpZiAocGVyTGF5ZXJRdWFudGl6YXRpb24pIHtcbiAgICAgICAgICAgICAgICAvLyB6ZXJvLXBvaW50IGlucHV0IGlzIGEgc2NhbGFyXG4gICAgICAgICAgICAgICAgaWYgKGlzUGFja2VkKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2lucHV0ID0gJHt6ZXJvUG9pbnQuZ2V0QnlPZmZzZXQoJzAnKX07XG4gICAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfdmVjID0gICR7aXNTaWduZWQgPyAndW5wYWNrNHhJOCh6ZXJvX3BvaW50X2lucHV0KScgOiAndW5wYWNrNHhVOCh6ZXJvX3BvaW50X2lucHV0KSd9O1xuICAgICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X3ZhbHVlPSB6ZXJvX3BvaW50X3ZlY1swXWA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgbGV0IHplcm9fcG9pbnRfdmFsdWUgPSAke3plcm9Qb2ludC5nZXRCeU9mZnNldCgnMCcpfWA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBlckF4aXNRdWFudGl6YXRpb24pIHtcbiAgICAgICAgICAgICAgICAvLyB6ZXJvLXBvaW50IGlucHV0IGlzIGEgMUQgdGVuc29yXG4gICAgICAgICAgICAgICAgaWYgKGlzUGFja2VkKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2luZGV4ID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCAndW5pZm9ybXMuYXhpcycpfTtcbiAgICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF9pbnB1dCA9ICR7emVyb1BvaW50LmdldEJ5T2Zmc2V0KCd6ZXJvX3BvaW50X2luZGV4IC8gNCcpfTtcbiAgICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF92ZWMgPSAgJHtpc1NpZ25lZCA/ICd1bnBhY2s0eEk4KHplcm9fcG9pbnRfaW5wdXQpJyA6ICd1bnBhY2s0eFU4KHplcm9fcG9pbnRfaW5wdXQpJ307XG4gICAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfdmFsdWUgPSB6ZXJvX3BvaW50X3ZlY1t6ZXJvX3BvaW50X2luZGV4ICUgNF1gO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2luZGV4ID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCAndW5pZm9ybXMuYXhpcycpfTtcbiAgICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF92YWx1ZSA9ICR7emVyb1BvaW50LmdldEJ5T2Zmc2V0KCd6ZXJvX3BvaW50X2luZGV4Jyl9O2A7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIEJsb2NrZWRRdWFudGl6YXRpb24uIFRoZSB6ZXJvLXBvaW50IGlucHV0IHNoYXBlIGlzIHNhbWUgYXMgdGhlIGlucHV0IHNoYXBlIGV4Y2VwdCBhbG9uZyBheGlzLlxuICAgICAgICAgICAgICAgIGlmIChpc1BhY2tlZCkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF9vZmZzZXQgPSAke3NjYWxlLmluZGljZXNUb09mZnNldCgnc2NhbGVfaW5kaWNlcycpfTtcbiAgICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF9pbnB1dCA9ICR7emVyb1BvaW50LmdldEJ5T2Zmc2V0KCd6ZXJvX3BvaW50X29mZnNldCAvIDQnKX07XG4gICAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfdmVjID0gJHtpc1NpZ25lZCA/ICd1bnBhY2s0eEk4KHplcm9fcG9pbnRfaW5wdXQpJyA6ICd1bnBhY2s0eFU4KHplcm9fcG9pbnRfaW5wdXQpJ307XG4gICAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfdmFsdWUgPSB6ZXJvX3BvaW50X3ZlY1t6ZXJvX3BvaW50X29mZnNldCAlIDRdO2A7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgbGV0IHplcm9fcG9pbnRfdmFsdWUgPSAke3plcm9Qb2ludC5nZXRCeUluZGljZXMoJ3NjYWxlX2luZGljZXMnKX07YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBgbGV0IHplcm9fcG9pbnRfdmFsdWUgPSAke2lzUGFja2VkID8gKGlzU2lnbmVkID8gJ2kzMicgOiAndTMyJykgOiBpbnB1dC50eXBlLnZhbHVlfSgwKTtgO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pKCl9O1xuICAgICAgLy8gQ29tcHV0ZSBhbmQgd3JpdGUgb3V0cHV0XG4gICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsIGAke291dHB1dC50eXBlLnZhbHVlfSh4X3ZhbHVlIC0gemVyb19wb2ludF92YWx1ZSkgKiBzY2FsZV92YWx1ZWApfTtcbiAgICAgIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdEZXF1YW50aXplTGluZWFyJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiB6ZXJvUG9pbnQgPyBbJ3JhbmsnLCAncmFuaycsICdyYW5rJ10gOiBbJ3JhbmsnLCAncmFuayddLFxuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gY29tcG9uZW50cyAvIDY0KSwgeTogMSwgejogMSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGRlcXVhbnRpemVMaW5lYXIgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IERlcXVhbnRpemVMaW5lckF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRGVxdWFudGl6ZUxpbmVhclByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VEZXF1YW50aXplTGluZWFyQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IERlcXVhbnRpemVMaW5lckF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgYXhpczogYXR0cmlidXRlcy5heGlzIGFzIG51bWJlciwgYmxvY2tTaXplOiBhdHRyaWJ1dGVzLmJsb2NrU2l6ZSBhcyBudW1iZXIgfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGVudiB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzQ29udGVudCA9IChzdGFydDogbnVtYmVyLCBsaW1pdDogbnVtYmVyLCBkZWx0YTogbnVtYmVyKTogdm9pZCA9PiB7XG4gIGNvbnN0IHNhbWVTdGFydExpbWl0ID0gc3RhcnQgPT09IGxpbWl0O1xuICBjb25zdCBpbmNyZWFzaW5nUmFuZ2VOZWdhdGl2ZVN0ZXAgPSBzdGFydCA8IGxpbWl0ICYmIGRlbHRhIDwgMDtcbiAgY29uc3QgZGVjcmVhc2luZ1JhbmdlUG9zaXRpdmVTdGVwID0gc3RhcnQgPiBsaW1pdCAmJiBkZWx0YSA+IDA7XG5cbiAgaWYgKHNhbWVTdGFydExpbWl0IHx8IGluY3JlYXNpbmdSYW5nZU5lZ2F0aXZlU3RlcCB8fCBkZWNyZWFzaW5nUmFuZ2VQb3NpdGl2ZVN0ZXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJSYW5nZSB0aGVzZSBpbnB1dHMnIGNvbnRlbnRzIGFyZSBpbnZhbGlkLlwiKTtcbiAgfVxufTtcblxuY29uc3QgY3JlYXRlUmFuZ2VQcm9ncmFtSW5mbyA9IChzdGFydDogbnVtYmVyLCBsaW1pdDogbnVtYmVyLCBkZWx0YTogbnVtYmVyLCBkYXRhVHlwZTogRGF0YVR5cGUpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IG51bUVsZW1lbnRzID0gTWF0aC5hYnMoTWF0aC5jZWlsKChsaW1pdCAtIHN0YXJ0KSAvIGRlbHRhKSk7XG4gIGNvbnN0IG91dHB1dFNoYXBlOiBudW1iZXJbXSA9IFtudW1FbGVtZW50c107XG4gIGNvbnN0IG91dHB1dFNpemUgPSBudW1FbGVtZW50cztcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBkYXRhVHlwZSwgZGF0YTogc3RhcnQgfSxcbiAgICB7IHR5cGU6IGRhdGFUeXBlLCBkYXRhOiBkZWx0YSB9LFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlKSxcbiAgXTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gICAgY29uc3Qgd2dzbFR5cGUgPSBvdXRwdXQudHlwZS52YWx1ZTtcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRTaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3N0YXJ0JywgdHlwZTogd2dzbFR5cGUgYXMgVW5pZm9ybURhdGFFbGVtZW50VHlwZSB9LFxuICAgICAgeyBuYW1lOiAnZGVsdGEnLCB0eXBlOiB3Z3NsVHlwZSBhcyBVbmlmb3JtRGF0YUVsZW1lbnRUeXBlIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKG91dHB1dCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG4gICAgICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9IHVuaWZvcm1zLnN0YXJ0ICsgJHt3Z3NsVHlwZX0oZ2xvYmFsX2lkeCkgKiB1bmlmb3Jtcy5kZWx0YTtcbiAgICAgIH1gO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1JhbmdlJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtkYXRhVHlwZX1gIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgcmFuZ2UgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgbGV0IHN0YXJ0ID0gMDtcbiAgbGV0IGxpbWl0ID0gMDtcbiAgbGV0IGRlbHRhID0gMDtcbiAgaWYgKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlID09PSBEYXRhVHlwZS5pbnQzMikge1xuICAgIHN0YXJ0ID0gY29udGV4dC5pbnB1dHNbMF0uZ2V0SW50MzJBcnJheSgpWzBdO1xuICAgIGxpbWl0ID0gY29udGV4dC5pbnB1dHNbMV0uZ2V0SW50MzJBcnJheSgpWzBdO1xuICAgIGRlbHRhID0gY29udGV4dC5pbnB1dHNbMl0uZ2V0SW50MzJBcnJheSgpWzBdO1xuICB9IGVsc2UgaWYgKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlID09PSBEYXRhVHlwZS5mbG9hdCkge1xuICAgIHN0YXJ0ID0gY29udGV4dC5pbnB1dHNbMF0uZ2V0RmxvYXQzMkFycmF5KClbMF07XG4gICAgbGltaXQgPSBjb250ZXh0LmlucHV0c1sxXS5nZXRGbG9hdDMyQXJyYXkoKVswXTtcbiAgICBkZWx0YSA9IGNvbnRleHQuaW5wdXRzWzJdLmdldEZsb2F0MzJBcnJheSgpWzBdO1xuICB9XG4gIGlmIChlbnYud2ViZ3B1LnZhbGlkYXRlSW5wdXRDb250ZW50KSB7XG4gICAgdmFsaWRhdGVJbnB1dHNDb250ZW50KHN0YXJ0LCBsaW1pdCwgZGVsdGEpO1xuICB9XG5cbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVJhbmdlUHJvZ3JhbUluZm8oc3RhcnQsIGxpbWl0LCBkZWx0YSwgY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpLCB7IGlucHV0czogW10gfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGF0b21pY091dHB1dFZhcmlhYmxlLFxuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbn0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNjYXR0ZXJOREF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWR1Y3Rpb246IHN0cmluZztcbn1cblxudHlwZSBSZWR1Y3Rpb25UeXBlID0gJ2kzMicgfCAndTMyJyB8ICdmMzInO1xuXG5jb25zdCBhdG9taWNSZWR1Y3Rpb25TbmlwcGV0ID0gKHJlZHVjdGlvbjogc3RyaW5nLCBwdHI6IHN0cmluZywgdjogc3RyaW5nLCB0eXBlOiBSZWR1Y3Rpb25UeXBlKSA9PiB7XG4gIGlmIChyZWR1Y3Rpb24gIT09ICdub25lJyAmJiB0eXBlICE9PSAnaTMyJyAmJiB0eXBlICE9PSAndTMyJyAmJiB0eXBlICE9PSAnZjMyJykge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgJHt0eXBlfSBpcyBub3Qgc3VwcG9ydGVkIHdpdGggcmVkdWN0aW9uICR7cmVkdWN0aW9ufS5gKTtcbiAgfVxuXG4gIGNvbnN0IGZsb2F0U3RhcnQgPSBge1xuICAgICAgICAgICAgICAgIHZhciBvbGRWYWx1ZSA9IDA7XG4gICAgICAgICAgICAgICAgbG9vcCB7XG4gICAgICAgICAgICAgICAgICBsZXQgbmV3VmFsdWVGMzIgPWA7XG4gIGNvbnN0IGZsb2F0RW5kID0gYDtcbiAgICAgICAgICAgICAgICAgIGxldCBuZXdWYWx1ZSA9IGJpdGNhc3Q8aTMyPihuZXdWYWx1ZUYzMik7XG4gICAgICAgICAgICAgICAgICBsZXQgcmVzID0gYXRvbWljQ29tcGFyZUV4Y2hhbmdlV2VhaygmJHtwdHJ9LCBvbGRWYWx1ZSwgbmV3VmFsdWUpO1xuICAgICAgICAgICAgICAgICAgaWYgcmVzLmV4Y2hhbmdlZCB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSByZXMub2xkX3ZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfWA7XG5cbiAgc3dpdGNoIChyZWR1Y3Rpb24pIHtcbiAgICBjYXNlICdub25lJzpcbiAgICAgIHJldHVybiBgJHtwdHJ9PSR7dn07YDtcbiAgICBjYXNlICdhZGQnOlxuICAgICAgaWYgKHR5cGUgPT09ICdpMzInIHx8IHR5cGUgPT09ICd1MzInKSB7XG4gICAgICAgIHJldHVybiBgYXRvbWljQWRkKCYke3B0cn0sIGJpdGNhc3Q8JHt0eXBlfT4oJHt2fSkpO2A7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBhdG9taWNBZGQgb25seSBzdXBwb3J0cyB1aW50L2ludCB0eXBlLiBGb3IgZmxvYXQsIHdlIHVzZVxuICAgICAgICAvLyBhdG9taWNDb21wYXJlRXhjaGFuZ2VXZWFrIHRvIHNpbXVsYXRlLlxuICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgICAke2Zsb2F0U3RhcnR9Yml0Y2FzdDwke3R5cGV9PihvbGRWYWx1ZSkgKyAoJHt2fSkke2Zsb2F0RW5kfWA7XG4gICAgICB9XG4gICAgY2FzZSAnbWF4JzpcbiAgICAgIGlmICh0eXBlID09PSAnaTMyJyB8fCB0eXBlID09PSAndTMyJykge1xuICAgICAgICByZXR1cm4gYGF0b21pY01heCgmJHtwdHJ9LCBiaXRjYXN0PCR7dHlwZX0+KCR7dn0pKTtgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gYXRvbWljTWF4IG9ubHkgc3VwcG9ydHMgdWludC9pbnQgdHlwZS4gRm9yIGZsb2F0LCB3ZSB1c2VcbiAgICAgICAgLy8gYXRvbWljQ29tcGFyZUV4Y2hhbmdlV2VhayB0byBzaW11bGF0ZS5cbiAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgICAke2Zsb2F0U3RhcnR9bWF4KGJpdGNhc3Q8ZjMyPihvbGRWYWx1ZSksICgke3Z9KSkke2Zsb2F0RW5kfWA7XG4gICAgICB9XG4gICAgY2FzZSAnbWluJzpcbiAgICAgIGlmICh0eXBlID09PSAnaTMyJyB8fCB0eXBlID09PSAndTMyJykge1xuICAgICAgICByZXR1cm4gYGF0b21pY01pbigmJHtwdHJ9LCBiaXRjYXN0PCR7dHlwZX0+KCR7dn0pKTtgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gYXRvbWljTWluIG9ubHkgc3VwcG9ydHMgdWludC9pbnQgdHlwZS4gRm9yIGZsb2F0LCB3ZSB1c2VcbiAgICAgICAgLy8gYXRvbWljQ29tcGFyZUV4Y2hhbmdlV2VhayB0byBzaW11bGF0ZS5cbiAgICAgICAgcmV0dXJuIGAke2Zsb2F0U3RhcnR9bWluKGJpdGNhc3Q8JHt0eXBlfT4ob2xkVmFsdWUpLCAoJHt2fSkpJHtmbG9hdEVuZH1gO1xuICAgICAgfVxuICAgIGNhc2UgJ211bCc6XG4gICAgICAvLyBhdG9taWNNdWwgaXMgbm90IHN1cHBvcnRlZCwgd2UgdXNlIGF0b21pY0NvbXBhcmVFeGNoYW5nZVdlYWsgdG8gc2ltdWxhdGUuXG4gICAgICByZXR1cm4gYCR7ZmxvYXRTdGFydH0oYml0Y2FzdDwke3R5cGV9PihvbGRWYWx1ZSkgKiAoJHt2fSkpJHtmbG9hdEVuZH1gO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUmVkdWN0aW9uICR7cmVkdWN0aW9ufSBpcyBub3Qgc3VwcG9ydGVkLmApO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVTY2F0dGVyTkRQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogU2NhdHRlck5EQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBpbmRpY2VzU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlO1xuICAvLyBUT0RPOiBzdXBwb3J0IGJvb2wgd2l0aCBjb21wb25lbnRzIDQuXG4gIGNvbnN0IGNvbXBvbmVudHMgPSAxO1xuICBjb25zdCBvdXRwdXRTaXplID0gTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplVG9EaW1lbnNpb24oaW5kaWNlc1NoYXBlLCBpbmRpY2VzU2hhcGUubGVuZ3RoIC0gMSkgLyBjb21wb25lbnRzKTtcbiAgY29uc3QgbGFzdEluZGV4RGltZW5zaW9uID0gaW5kaWNlc1NoYXBlW2luZGljZXNTaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3QgbnVtVXBkYXRlc0VsZW1lbnRzID0gU2hhcGVVdGlsLnNpemVGcm9tRGltZW5zaW9uKGlucHV0U2hhcGUsIGxhc3RJbmRleERpbWVuc2lvbik7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGxhc3RJbmRleERpbWVuc2lvbiB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBudW1VcGRhdGVzRWxlbWVudHMgfSxcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMV0uZGltcywgaW5wdXRzWzJdLmRpbXMsIG91dHB1dFNoYXBlKSxcbiAgXTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBpbmRpY2VzID0gaW5wdXRWYXJpYWJsZSgnaW5kaWNlcycsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCB1cGRhdGVzID0gaW5wdXRWYXJpYWJsZSgndXBkYXRlcycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBvdXRwdXQgPVxuICAgICAgYXR0cmlidXRlcy5yZWR1Y3Rpb24gIT09ICdub25lJyAmJiBhdHRyaWJ1dGVzLnJlZHVjdGlvbiAhPT0gJydcbiAgICAgICAgPyBhdG9taWNPdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpXG4gICAgICAgIDogb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcblxuICAgIHJldHVybiBgXG4gICAgICAke3NoYWRlckhlbHBlclxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRfc2l6ZScsICd1MzInKVxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdsYXN0X2luZGV4X2RpbWVuc2lvbicsICd1MzInKVxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdudW1fdXBkYXRlc19lbGVtZW50cycsICd1MzInKVxuICAgICAgICAuZGVjbGFyZVZhcmlhYmxlcyhpbmRpY2VzLCB1cGRhdGVzLCBvdXRwdXQpfVxuICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gIHZhciBkYXRhX29mZnNldCA9IDB1O1xuICBsZXQgaW5kaWNlc19zdGFydCA9IHVuaWZvcm1zLmxhc3RfaW5kZXhfZGltZW5zaW9uICogZ2xvYmFsX2lkeDtcbiAgbGV0IGluZGljZXNfZW5kID0gaW5kaWNlc19zdGFydCArIHVuaWZvcm1zLmxhc3RfaW5kZXhfZGltZW5zaW9uO1xuICBmb3IgKHZhciBpID0gaW5kaWNlc19zdGFydDsgaSA8IGluZGljZXNfZW5kOyBpKyspIHtcbiAgICB2YXIgaW5kZXggPSBpMzIoaW5kaWNlc1tpXS54KTtcbiAgICAke1xuICAgICAgaW5wdXRzWzBdLmRpbXMubGVuZ3RoID09PSAxXG4gICAgICAgID8gYFxuICAgIGxldCBlbGVtZW50X2NvdW50X2RpbSA9IHVuaWZvcm1zLm91dHB1dF9zdHJpZGVzO1xuICAgIGxldCBkaW1fdmFsdWUgPSB1bmlmb3Jtcy5vdXRwdXRfc2hhcGU7YFxuICAgICAgICA6IGBcbiAgICBsZXQgZWxlbWVudF9jb3VudF9kaW0gPSB1bmlmb3Jtcy5vdXRwdXRfc3RyaWRlc1tpIC0gaW5kaWNlc19zdGFydF07XG4gICAgbGV0IGRpbV92YWx1ZSA9IHVuaWZvcm1zLm91dHB1dF9zaGFwZVtpIC0gaW5kaWNlc19zdGFydF07YFxuICAgIH1cbiAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgaWYgKGluZGV4ID49IGkzMihkaW1fdmFsdWUpKSB7XG4gICAgICAgIGluZGV4ID0gaTMyKGRpbV92YWx1ZSAtIDEpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaW5kZXggPCAtaTMyKGRpbV92YWx1ZSkpIHtcbiAgICAgICAgaW5kZXggPSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5kZXggKz0gaTMyKGRpbV92YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGRhdGFfb2Zmc2V0ICs9IHUzMigodTMyKGluZGV4KSAqIGVsZW1lbnRfY291bnRfZGltKSk7XG4gIH1cblxuICBmb3IgKHZhciBpID0gMHU7IGkgPCB1bmlmb3Jtcy5udW1fdXBkYXRlc19lbGVtZW50czsgaSsrKSB7XG4gICAgbGV0IHZhbHVlID0gdXBkYXRlc1t1bmlmb3Jtcy5udW1fdXBkYXRlc19lbGVtZW50cyAqIGdsb2JhbF9pZHggKyBpXTtcbiAgICAke2F0b21pY1JlZHVjdGlvblNuaXBwZXQoXG4gICAgICBhdHRyaWJ1dGVzLnJlZHVjdGlvbixcbiAgICAgICdvdXRwdXRbZGF0YV9vZmZzZXQgKyBpXScsXG4gICAgICAndmFsdWUnLFxuICAgICAgb3V0cHV0LnR5cGUudmFsdWUgYXMgUmVkdWN0aW9uVHlwZSxcbiAgICApfVxuICB9XG5cbiAgICAgIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdTY2F0dGVyTkQnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fV8ke2F0dHJpYnV0ZXMucmVkdWN0aW9ufWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJywgJ3JhbmsnXSxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VTY2F0dGVyTkRBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogU2NhdHRlck5EQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyByZWR1Y3Rpb246IGF0dHJpYnV0ZXMucmVkdWN0aW9uIGFzIHN0cmluZyB9KTtcblxuZXhwb3J0IGNvbnN0IHNjYXR0ZXJORCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogU2NhdHRlck5EQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlU2NhdHRlck5EUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpLCB7XG4gICAgaW5wdXRzOiBbY29udGV4dC5pbnB1dHNbMV0sIGNvbnRleHQuaW5wdXRzWzJdXSxcbiAgICBvdXRwdXRzOiBbXSxcbiAgfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldEVsZW1lbnRBdCxcbiAgSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbn0gZnJvbSAnLi9jb21tb24nO1xuXG50eXBlIENvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlID1cbiAgfCAnaGFsZl9waXhlbCdcbiAgfCAnYXN5bW1ldHJpYydcbiAgfCAncHl0b3JjaF9oYWxmX3BpeGVsJ1xuICB8ICd0Zl9oYWxmX3BpeGVsX2Zvcl9ubidcbiAgfCAnYWxpZ25fY29ybmVycydcbiAgfCAndGZfY3JvcF9hbmRfcmVzaXplJ1xuICB8ICdoYWxmX3BpeGVsX3N5bW1ldHJpYyc7XG5cbnR5cGUgS2VlcEFzcGVjdFJhdGlvUG9saWN5ID0gJ3N0cmV0Y2gnIHwgJ25vdF9zbWFsbGVyJyB8ICdub3RfbGFyZ2VyJztcblxudHlwZSBNb2RlID0gJ25lYXJlc3QnIHwgJ2xpbmVhcicgfCAnY3ViaWMnO1xuXG50eXBlIE5lYXJlc3RNb2RlID0gJ3JvdW5kX3ByZWZlcl9mbG9vcicgfCAncm91bmRfcHJlZmVyX2NlaWwnIHwgJ2Zsb29yJyB8ICdjZWlsJyB8ICdzaW1wbGUnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlc2l6ZUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICBhbnRpYWxpYXM6IG51bWJlcjtcbiAgYXhlczogbnVtYmVyW107XG4gIGNvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlOiBDb29yZGluYXRlVHJhbnNmb3JtTW9kZTtcbiAgY3ViaWNDb2VmZkE6IG51bWJlcjtcbiAgZXhjbHVkZU91dHNpZGU6IGJvb2xlYW47XG4gIGV4dHJhcG9sYXRpb25WYWx1ZTogbnVtYmVyO1xuICBrZWVwQXNwZWN0UmF0aW9Qb2xpY3k6IEtlZXBBc3BlY3RSYXRpb1BvbGljeTtcbiAgbW9kZTogTW9kZTtcbiAgbmVhcmVzdE1vZGU6IE5lYXJlc3RNb2RlO1xufVxuXG5jb25zdCB2YWxpZGF0ZVNjYWxlcyA9IChzY2FsZXM6IG51bWJlcltdLCBhdHRyaWJ1dGVzOiBSZXNpemVBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHNjYWxlcy5ldmVyeShcbiAgICAodmFsdWUpID0+XG4gICAgICB2YWx1ZSA+IDAgfHxcbiAgICAgICgoKSA9PiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUmVzaXplIHJlcXVpcmVzIHNjYWxlcyBpbnB1dCB2YWx1ZXMgdG8gYmUgcG9zaXRpdmUnKTtcbiAgICAgIH0pLFxuICApO1xuICAvLyBDaGVjayBzY2FsZXMgZGltcyBiYXNlZCBvbiBtb2RlOiBMSU5FQVIsIENVQklDXG4gIGlmIChzY2FsZXMubGVuZ3RoID4gMCkge1xuICAgIGlmIChhdHRyaWJ1dGVzLm1vZGUgPT09ICdsaW5lYXInKSB7XG4gICAgICBpZiAoXG4gICAgICAgICEoXG4gICAgICAgICAgc2NhbGVzLmxlbmd0aCA9PT0gMiB8fFxuICAgICAgICAgIHNjYWxlcy5sZW5ndGggPT09IDMgfHxcbiAgICAgICAgICAoc2NhbGVzLmxlbmd0aCA9PT0gNCAmJiBzY2FsZXNbMF0gPT09IDEgJiYgc2NhbGVzWzFdID09PSAxKSB8fFxuICAgICAgICAgIChzY2FsZXMubGVuZ3RoID09PSA0ICYmIHNjYWxlc1swXSA9PT0gMSAmJiBzY2FsZXNbM10gPT09IDEpIHx8XG4gICAgICAgICAgKHNjYWxlcy5sZW5ndGggPT09IDUgJiYgc2NhbGVzWzBdID09PSAxICYmIHNjYWxlc1sxXSA9PT0gMSlcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgRm9yIGxpbmVhciBtb2RlLCBSZXNpemUgcmVxdWlyZXMgc2NhbGVzIHRvIGJlIDJELCAzRCwgNEQgd2l0aCBlaXRoZXIgdHdvIG91dGVybW9zdCBvciBvbmUgaW5uZXJtb3N0IGFuZFxuICAgICAgICAgICAgb25lIG91dGVybW9zdCBzY2FsZSB2YWx1ZXMgZXF1YWwgdG8gMSwgb3IgNUQgd2l0aCB0d28gb3V0ZXJtb3N0IHNjYWxlIHZhbHVlcyBlcXVhbCB0byAxYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMubW9kZSA9PT0gJ2N1YmljJykge1xuICAgICAgaWYgKFxuICAgICAgICAhKFxuICAgICAgICAgIHNjYWxlcy5sZW5ndGggPT09IDIgfHxcbiAgICAgICAgICAoc2NhbGVzLmxlbmd0aCA9PT0gNCAmJiBzY2FsZXNbMF0gPT09IDEgJiYgc2NhbGVzWzFdID09PSAxKSB8fFxuICAgICAgICAgIChzY2FsZXMubGVuZ3RoID09PSA0ICYmIHNjYWxlc1swXSA9PT0gMSAmJiBzY2FsZXNbM10gPT09IDEpXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Jlc2l6ZSByZXF1aXJlcyBzY2FsZXMgaW5wdXQgc2l6ZSB0byBiZSAyIG9yIDQgZm9yIGN1YmljIG1vZGUnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn07XG5cbmNvbnN0IHVwZGF0ZVNjYWxlcyA9IChzY2FsZXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGVzOiByZWFkb25seSBudW1iZXJbXSwgcmFuazogbnVtYmVyKTogbnVtYmVyW10gPT4ge1xuICBheGVzLmV2ZXJ5KFxuICAgICh2YWx1ZSkgPT5cbiAgICAgICh2YWx1ZSA+PSAwICYmIHZhbHVlIDwgcmFuaykgfHxcbiAgICAgICgoKSA9PiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUmVzaXplIHJlcXVpcmVzIGF4ZXMgaW5wdXQgdmFsdWVzIHRvIGJlIHBvc2l0aXZlIGFuZCBsZXNzIHRoYW4gcmFuaycpO1xuICAgICAgfSksXG4gICk7XG4gIGNvbnN0IG5ld1NjYWxlcyA9IG5ldyBBcnJheShyYW5rKS5maWxsKDEuMCk7XG4gIGF4ZXMuZm9yRWFjaCgodmFsdWUsIGluZGV4KSA9PiAobmV3U2NhbGVzW3ZhbHVlXSA9IHNjYWxlc1tpbmRleF0pKTtcbiAgcmV0dXJuIG5ld1NjYWxlcztcbn07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogUmVzaXplQXR0cmlidXRlcyxcbiAgb3BzZXRWZXJzaW9uOiBudW1iZXIsXG4gIHNjYWxlczogbnVtYmVyW10sXG4gIHNpemVzOiBudW1iZXJbXSxcbiAgcm9pOiBudW1iZXJbXSxcbik6IHZvaWQgPT4ge1xuICBjb25zdCBbcm9pSW5wdXRJbmRleCwgc2NhbGVzSW5wdXRJbmRleCwgc2l6ZXNJbnB1dEluZGV4XSA9XG4gICAgb3BzZXRWZXJzaW9uID4gMTAgPyBbMSwgMiwgM10gOiBbLTEsIGlucHV0cy5sZW5ndGggPiAxID8gMSA6IC0xLCAtMV07XG4gIGNvbnN0IHJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGg7XG4gIGlmIChyb2lJbnB1dEluZGV4ID4gMCAmJiBpbnB1dHMubGVuZ3RoID4gcm9pSW5wdXRJbmRleCAmJiBpbnB1dHNbcm9pSW5wdXRJbmRleF0uZGltcy5sZW5ndGggPiAwKSB7XG4gICAgaW5wdXRzW3JvaUlucHV0SW5kZXhdLmdldEZsb2F0MzJBcnJheSgpLmZvckVhY2goKHZhbHVlKSA9PiByb2kucHVzaCh2YWx1ZSkpO1xuICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMuY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUgPT09ICd0Zl9jcm9wX2FuZF9yZXNpemUnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdSZXNpemUgcmVxdWlyZXMgUm9JIGlucHV0IHRvIGJlIHNwZWNpZmllZCB3aGVuIGNvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlIGlzIHRmQ3JvcEFuZFJlc2l6ZScpO1xuICB9XG5cbiAgaWYgKFxuICAgIHNjYWxlc0lucHV0SW5kZXggPiAwICYmXG4gICAgaW5wdXRzLmxlbmd0aCA+IHNjYWxlc0lucHV0SW5kZXggJiZcbiAgICBpbnB1dHNbc2NhbGVzSW5wdXRJbmRleF0uZGltcy5sZW5ndGggPT09IDEgJiZcbiAgICBpbnB1dHNbc2NhbGVzSW5wdXRJbmRleF0uZGltc1swXSA+IDBcbiAgKSB7XG4gICAgaW5wdXRzW3NjYWxlc0lucHV0SW5kZXhdLmdldEZsb2F0MzJBcnJheSgpLmZvckVhY2goKHZhbHVlKSA9PiBzY2FsZXMucHVzaCh2YWx1ZSkpO1xuICAgIGlmIChcbiAgICAgIHNjYWxlcy5sZW5ndGggIT09IDAgJiZcbiAgICAgIHNjYWxlcy5sZW5ndGggIT09IHJhbmsgJiZcbiAgICAgIG9wc2V0VmVyc2lvbiA+PSAxOCAmJlxuICAgICAgc2NhbGVzLmxlbmd0aCAhPT0gYXR0cmlidXRlcy5heGVzLmxlbmd0aFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXNpemUgcmVxdWlyZXMgc2NhbGVzIGlucHV0IHNpemUgdG8gYmUgc2FtZSBhcyBpbnB1dCByYW5rIG9yIGF4ZXMgc2l6ZSBmb3Igb3BzZXQgMTggYW5kIHVwJyk7XG4gICAgfVxuICAgIHZhbGlkYXRlU2NhbGVzKHNjYWxlcywgYXR0cmlidXRlcyk7XG4gICAgaWYgKGF0dHJpYnV0ZXMuYXhlcy5sZW5ndGggPiAwKSB7XG4gICAgICB1cGRhdGVTY2FsZXMoc2NhbGVzLCBhdHRyaWJ1dGVzLmF4ZXMsIHJhbmspLmZvckVhY2goKHZhbHVlLCBpbmRleCkgPT4gKHNjYWxlc1tpbmRleF0gPSB2YWx1ZSkpO1xuICAgIH1cbiAgfVxuICBpZiAoXG4gICAgc2l6ZXNJbnB1dEluZGV4ID4gMCAmJlxuICAgIGlucHV0cy5sZW5ndGggPiBzaXplc0lucHV0SW5kZXggJiZcbiAgICBpbnB1dHNbc2l6ZXNJbnB1dEluZGV4XS5kaW1zLmxlbmd0aCA9PT0gMSAmJlxuICAgIGlucHV0c1tzaXplc0lucHV0SW5kZXhdLmRpbXNbMF0gPiAwXG4gICkge1xuICAgIGlucHV0c1tzaXplc0lucHV0SW5kZXhdLmdldEJpZ0ludDY0QXJyYXkoKS5mb3JFYWNoKCh2YWx1ZSkgPT4gc2l6ZXMucHVzaChOdW1iZXIodmFsdWUpKSk7XG4gICAgaWYgKHNpemVzLmxlbmd0aCAhPT0gMCAmJiBzaXplcy5sZW5ndGggIT09IHJhbmsgJiYgb3BzZXRWZXJzaW9uID49IDE4ICYmIHNpemVzLmxlbmd0aCAhPT0gYXR0cmlidXRlcy5heGVzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXNpemUgcmVxdWlyZXMgc2l6ZXMgaW5wdXQgc2l6ZSB0byBiZSBzYW1lIGFzIGlucHV0IHJhbmsgb3IgYXhlcyBzaXplIGZvciBvcHNldCAxOCBhbmQgdXAnKTtcbiAgICB9XG4gIH1cblxuICBpZiAoYXR0cmlidXRlcy5heGVzLmxlbmd0aCA+IDApIHtcbiAgICBpZiAoc2NhbGVzLmxlbmd0aCAhPT0gMCAmJiBzY2FsZXMubGVuZ3RoICE9PSBhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Jlc2l6ZSByZXF1aXJlcyBcInNjYWxlc1wiIGlucHV0IHNpemUgdG8gYmUgb2YgYXhlcyByYW5rIHdoZW4gYXhlcyBhdHRyaWJ1dGVzIGlzIHNwZWNpZmllZCcpO1xuICAgIH1cbiAgICBpZiAoc2l6ZXMubGVuZ3RoICE9PSAwICYmIHNpemVzLmxlbmd0aCAhPT0gYXR0cmlidXRlcy5heGVzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXNpemUgcmVxdWlyZXMgXCJzaXplc1wiIGlucHV0IHNpemUgdG8gYmUgb2YgcmFuayBheGVzIHJhbmsgd2hlbiBheGVzIGF0dHJpYnV0ZXMgaXMgc3BlY2lmaWVkJyk7XG4gICAgfVxuICB9XG4gIGlmICh0eXBlb2Ygc2NhbGVzICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygc2l6ZXMgIT09ICd1bmRlZmluZWQnICYmIHNjYWxlcy5sZW5ndGggPiAwICYmIHNpemVzLmxlbmd0aCA+IHJhbmspIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Jlc2l6ZSByZXF1aXJlcyBvbmx5IG9mIHNjYWxlcyBvciBzaXplcyB0byBiZSBzcGVjaWZpZWQnKTtcbiAgfVxufTtcblxuY29uc3QgZ2V0U2FmZUludGVnZXJEaXZpc2lvbiA9IChhOiBzdHJpbmcsIGI6IHN0cmluZywgYzogc3RyaW5nLCBkVHlwZTogc3RyaW5nKTogc3RyaW5nID0+IGBcbiAgLy8gVGhlIHdob2xlIHBhcnQgYW5kIHRoZSBmcmFjdGlvbmFsIHBhcnQgYXJlIGNhbGN1bGF0ZWQgc2VwYXJhdGVseSBkdWUgdG8gaW5hY2N1cmFjeSBvZiBmbG9hdGluZ1xuICAvLyBwb2ludCBkaXZpc2lvbi4gQXMgYW4gZXhhbXBsZSwgZjMyKDIxKSAvIGYzMig3KSBtYXkgZXZhbHVhdGUgdG8gMi45OS4uLiBpbnN0ZWFkIG9mIDMsIGNhdXNpbmcgYW5cbiAgLy8gb2Zmc2V0LWJ5LW9uZSBlcnJvciBsYXRlciBpbiBmbG9vcigpLlxuICBsZXQgYmlnID0gKCR7YX0pICogKCR7Yn0pO1xuICBsZXQgd2hvbGUgPSAke2RUeXBlfShiaWcgLyAoJHtjfSkpO1xuICBsZXQgZnJhY3QgPSAke2RUeXBlfShiaWcgJSAoJHtjfSkpIC8gJHtkVHlwZX0oJHtjfSk7XG4gIHJldHVybiB3aG9sZSArIGZyYWN0O1xuYDtcblxuY29uc3QgZ2V0T3JpZ2luYWxDb29yZGluYXRlRnJvbVJlc2l6ZWRDb29yZGluYXRlID0gKFxuICBjb29yZGluYXRlVHJhbnNmZXJNb2RlOiBDb29yZGluYXRlVHJhbnNmb3JtTW9kZSxcbiAgZFR5cGU6IHN0cmluZyxcbik6IHN0cmluZyA9PlxuICBgZm4gZ2V0T3JpZ2luYWxDb29yZGluYXRlRnJvbVJlc2l6ZWRDb29yZGluYXRlKHhSZXNpemVkOiB1MzIsIHhTY2FsZTogZjMyLCBsZW5ndGhSZXNpemVkOiB1MzIsXG4gICAgIGxlbmd0aE9yaWdpbmFsOiB1MzIsIHJvaVN0YXJ0OiBmMzIsIHJvaUVuZDogZjMyKSAtPiAke2RUeXBlfSB7IGAgK1xuICAoKCkgPT4ge1xuICAgIHN3aXRjaCAoY29vcmRpbmF0ZVRyYW5zZmVyTW9kZSkge1xuICAgICAgY2FzZSAnYXN5bW1ldHJpYyc6XG4gICAgICAgIHJldHVybiBgXG4gICAgICAgICAgaWYgKHhTY2FsZSA8IDEuMCB8fCBmbG9vcih4U2NhbGUpICE9IHhTY2FsZSkge1xuICAgICAgICAgICAgcmV0dXJuICR7ZFR5cGV9KHhSZXNpemVkKSAvICR7ZFR5cGV9KHhTY2FsZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICR7Z2V0U2FmZUludGVnZXJEaXZpc2lvbigneFJlc2l6ZWQnLCAnbGVuZ3RoT3JpZ2luYWwnLCAnbGVuZ3RoUmVzaXplZCcsIGRUeXBlKX1cbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICBjYXNlICdweXRvcmNoX2hhbGZfcGl4ZWwnOlxuICAgICAgICByZXR1cm4gYGlmIChsZW5ndGhSZXNpemVkID4gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKCR7ZFR5cGV9KHhSZXNpemVkKSArIDAuNSkgLyAke2RUeXBlfSh4U2NhbGUpIC0gMC41O1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDAuMDtcbiAgICAgICAgICAgICAgICAgIH1gO1xuICAgICAgY2FzZSAndGZfaGFsZl9waXhlbF9mb3Jfbm4nOlxuICAgICAgICByZXR1cm4gYHJldHVybiAoJHtkVHlwZX0oeFJlc2l6ZWQpICsgMC41KSAvICR7ZFR5cGV9KHhTY2FsZSk7YDtcbiAgICAgIGNhc2UgJ2FsaWduX2Nvcm5lcnMnOlxuICAgICAgICByZXR1cm4gYGlmIChsZW5ndGhSZXNpemVkID09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDAuMDtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICR7Z2V0U2FmZUludGVnZXJEaXZpc2lvbigneFJlc2l6ZWQnLCAnbGVuZ3RoT3JpZ2luYWwgLSAxJywgJ2xlbmd0aFJlc2l6ZWQgLSAxJywgZFR5cGUpfVxuICAgICAgICAgICAgICAgICAgfWA7XG4gICAgICBjYXNlICd0Zl9jcm9wX2FuZF9yZXNpemUnOlxuICAgICAgICByZXR1cm4gYGlmIChsZW5ndGhSZXNpemVkID4gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJHtkVHlwZX0ocm9pU3RhcnQpICogJHtkVHlwZX0obGVuZ3RoT3JpZ2luYWwgLSAxKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAoJHtkVHlwZX0oeFJlc2l6ZWQpICogJHtkVHlwZX0ocm9pRW5kIC0gcm9pU3RhcnQpICogJHtkVHlwZX0obGVuZ3RoT3JpZ2luYWwgLSAxKSkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgJHtkVHlwZX0obGVuZ3RoUmVzaXplZCAtIDEpO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDAuNSAqICR7ZFR5cGV9KHJvaVN0YXJ0ICsgcm9pRW5kKSAqICR7ZFR5cGV9KGxlbmd0aE9yaWdpbmFsIC0gMSk7XG4gICAgICAgICAgICAgICAgICB9YDtcbiAgICAgIGNhc2UgJ2hhbGZfcGl4ZWxfc3ltbWV0cmljJzpcbiAgICAgICAgcmV0dXJuIGBjb25zdCBvdXRwdXRXaWR0aCA9ICR7ZFR5cGV9eFNjYWxlICogJHtkVHlwZX0obGVuZ3RoUmVzaXplZCk7XG4gICAgICAgICAgICAgICAgICBjb25zdCBhZGp1c3RtZW50ID0gJHtkVHlwZX0obGVuZ3RoUmVzaXplZCkgLyBvdXRwdXRXaWR0aDtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGNlbnRlciA9ICR7ZFR5cGV9KGxlbmd0aE9yaWdpbmFsKSAvIDI7XG4gICAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBjZW50ZXIgKiAoMSAtIGFkanVzdG1lbnQpO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIG9mZnNldCArICgoJHtkVHlwZX0oeFJlc2l6ZWQpICsgMC41KSAvICR7ZFR5cGV9KHhTY2FsZSkpIC0gMC41O2A7XG4gICAgICBjYXNlICdoYWxmX3BpeGVsJzpcbiAgICAgICAgcmV0dXJuIGByZXR1cm4gKCgke2RUeXBlfSh4UmVzaXplZCkgKyAwLjUpIC8gJHtkVHlwZX0oeFNjYWxlKSkgLSAwLjU7YDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ29vcmRpbmF0ZSB0cmFuc2Zvcm0gbW9kZSAke2Nvb3JkaW5hdGVUcmFuc2Zlck1vZGV9IGlzIG5vdCBzdXBwb3J0ZWRgKTtcbiAgICB9XG4gIH0pKCkgK1xuICAnfSc7XG5cbmNvbnN0IGdldE5lYXJlc3RQaXhlbEZyb21PcmlnaW5hbCA9IChuZWFyZXN0TW9kZTogTmVhcmVzdE1vZGUsIG9wc2V0VmVyc2lvbjogbnVtYmVyLCBkVHlwZTogc3RyaW5nKTogc3RyaW5nID0+XG4gIGBmbiBnZXROZWFyZXN0UGl4ZWxGcm9tT3JpZ2luYWwoeE9yaWdpbmFsOiAke2RUeXBlfSwgaXNEb3duU2FtcGxlOiBib29sKSAtPiAke2RUeXBlfSB7YCArXG4gICgoKSA9PiB7XG4gICAgc3dpdGNoIChuZWFyZXN0TW9kZSkge1xuICAgICAgY2FzZSAncm91bmRfcHJlZmVyX2NlaWwnOlxuICAgICAgICByZXR1cm4gJ2lmIChmcmFjdCh4T3JpZ2luYWwpID09IDAuNSkgeyBcXFxuICAgICAgICAgICAgcmV0dXJuIGNlaWwoeE9yaWdpbmFsKTsgXFxcbiAgICAgICAgICB9IGVsc2UgeyBcXFxuICAgICAgICAgICAgcmV0dXJuIHJvdW5kKHhPcmlnaW5hbCk7IFxcXG4gICAgICAgICAgfSc7XG4gICAgICBjYXNlICdmbG9vcic6XG4gICAgICAgIHJldHVybiAncmV0dXJuIGZsb29yKHhPcmlnaW5hbCk7JztcbiAgICAgIGNhc2UgJ2NlaWwnOlxuICAgICAgICByZXR1cm4gJ3JldHVybiBjZWlsKHhPcmlnaW5hbCk7JztcbiAgICAgIGNhc2UgJ3JvdW5kX3ByZWZlcl9mbG9vcic6XG4gICAgICAgIHJldHVybiAnaWYgKGZyYWN0KHhPcmlnaW5hbCkgPT0gMC41KSB7IFxcXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmbG9vcih4T3JpZ2luYWwpOyBcXFxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHsgXFxcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvdW5kKHhPcmlnaW5hbCk7IFxcXG4gICAgICAgICAgICAgICAgICB9JztcbiAgICAgIGNhc2UgJ3NpbXBsZSc6XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAob3BzZXRWZXJzaW9uIDwgMTEpIHtcbiAgICAgICAgICByZXR1cm4gJ2lmIChpc0Rvd25TYW1wbGUpIFxcXG4gICAgICAgICAgICAgICAgICAgIHsgXFxcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2VpbCh4T3JpZ2luYWwpOyBcXFxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgeyBcXFxuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB4T3JpZ2luYWw7IFxcXG4gICAgICAgICAgICAgICAgICAgIH0nO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTmVhcmVzdCBtb2RlICR7bmVhcmVzdE1vZGV9IGlzIG5vdCBzdXBwb3J0ZWRgKTtcbiAgICB9XG4gIH0pKCkgK1xuICAnfSc7XG5cbmNvbnN0IHVwZGF0ZVJvSSA9IChyb2k6IHJlYWRvbmx5IG51bWJlcltdLCBheGVzOiByZWFkb25seSBudW1iZXJbXSwgcmFuazogbnVtYmVyKTogbnVtYmVyW10gPT4ge1xuICBjb25zdCByb2lUbXAgPSBuZXcgQXJyYXkocmFuaykuZmlsbCgwKS5jb25jYXQobmV3IEFycmF5KHJhbmspLmZpbGwoMSkpO1xuICBjb25zdCByb2lMb2NhbCA9IHJvaS5sZW5ndGggPT09IDAgPyByb2lUbXAgOiByb2kuc2xpY2UoKTtcbiAgaWYgKGF4ZXMubGVuZ3RoID4gMCkge1xuICAgIGF4ZXMuZm9yRWFjaCgodiwgaSkgPT4ge1xuICAgICAgcm9pVG1wW3ZdID0gcm9pTG9jYWxbaV07XG4gICAgICByb2lUbXBbaSArIHJhbmtdID0gcm9pTG9jYWxbYXhlcy5sZW5ndGggKyBpXTtcbiAgICB9KTtcbiAgICByZXR1cm4gcm9pVG1wO1xuICB9XG4gIHJldHVybiByb2lMb2NhbDtcbn07XG5cbmNvbnN0IGluaXRPdXRwdXRTaGFwZSA9IChcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHNjYWxlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHNpemVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgYXhlczogcmVhZG9ubHkgbnVtYmVyW10sXG4pOiBudW1iZXJbXSA9PiB7XG4gIGxldCBvdXRwdXRTaGFwZTogbnVtYmVyW10gPSBbXTtcbiAgaWYgKHNpemVzLmxlbmd0aCA+IDApIHtcbiAgICBpZiAoYXhlcy5sZW5ndGggPiAwKSB7XG4gICAgICBpbnB1dFNoYXBlLmZvckVhY2goKHYpID0+IG91dHB1dFNoYXBlLnB1c2godikpO1xuICAgICAgaWYgKE1hdGgubWF4KC4uLmF4ZXMpID4gaW5wdXRTaGFwZS5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdheGVzIGlzIG91dCBvZiBib3VuZCcpO1xuICAgICAgfVxuICAgICAgYXhlcy5mb3JFYWNoKCh2LCBpKSA9PiAob3V0cHV0U2hhcGVbdl0gPSBzaXplc1tpXSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzaXplcy5mb3JFYWNoKCh2KSA9PiBvdXRwdXRTaGFwZS5wdXNoKHYpKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKHNjYWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVzaXplIHJlcXVpcmVzIGVpdGhlciBzY2FsZXMgb3Igc2l6ZXMuJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dFNoYXBlID0gaW5wdXRTaGFwZS5tYXAoKHZhbHVlLCBpbmRleCkgPT4gTWF0aC5yb3VuZCh2YWx1ZSAqIHNjYWxlc1tpbmRleF0pKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dHB1dFNoYXBlO1xufTtcblxuY29uc3QgYWRqdXN0T3V0cHV0U2hhcGUgPSAoaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHNjYWxlczogbnVtYmVyW10sIGF0dHJpYnV0ZXM6IFJlc2l6ZUF0dHJpYnV0ZXMpID0+IHtcbiAgY29uc3Qgc2NhbGVJblBvbGljeSA9ICgoKSA9PiB7XG4gICAgc3dpdGNoIChhdHRyaWJ1dGVzLmtlZXBBc3BlY3RSYXRpb1BvbGljeSkge1xuICAgICAgY2FzZSAnbm90X2xhcmdlcic6XG4gICAgICAgIHJldHVybiBhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoID4gMFxuICAgICAgICAgID8gTWF0aC5taW4oLi4uYXR0cmlidXRlcy5heGVzLm1hcCgoaSkgPT4gc2NhbGVzW2ldKSwgTnVtYmVyLk1BWF9WQUxVRSlcbiAgICAgICAgICA6IE1hdGgubWluKC4uLnNjYWxlcywgTnVtYmVyLk1BWF9WQUxVRSk7XG4gICAgICBjYXNlICdub3Rfc21hbGxlcic6XG4gICAgICAgIHJldHVybiBhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoID4gMFxuICAgICAgICAgID8gTWF0aC5tYXgoLi4uYXR0cmlidXRlcy5heGVzLm1hcCgoaSkgPT4gc2NhbGVzW2ldKSwgTnVtYmVyLk1JTl9WQUxVRSlcbiAgICAgICAgICA6IE1hdGgubWF4KC4uLnNjYWxlcywgTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEtlZXAgYXNwZWN0IHJhdGlvIHBvbGljeSAke2F0dHJpYnV0ZXMua2VlcEFzcGVjdFJhdGlvUG9saWN5fSBpcyBub3Qgc3VwcG9ydGVkYCk7XG4gICAgfVxuICB9KSgpO1xuICBzY2FsZXMuZmlsbCgxLjAsIDAsIHNjYWxlcy5sZW5ndGgpO1xuICBjb25zdCBhZGp1c3RlZE91dHB1dFNoYXBlID0gaW5wdXRTaGFwZS5zbGljZSgpO1xuICBpZiAoYXR0cmlidXRlcy5heGVzLmxlbmd0aCA+IDApIHtcbiAgICBhdHRyaWJ1dGVzLmF4ZXMuZm9yRWFjaCgodikgPT4gKHNjYWxlc1t2XSA9IHNjYWxlSW5Qb2xpY3kpKTtcbiAgICBhdHRyaWJ1dGVzLmF4ZXMuZm9yRWFjaCgodikgPT4gKGFkanVzdGVkT3V0cHV0U2hhcGVbdl0gPSBNYXRoLnJvdW5kKGlucHV0U2hhcGVbdl0gKiBzY2FsZXNbdl0pKSk7XG4gIH0gZWxzZSB7XG4gICAgc2NhbGVzLmZpbGwoc2NhbGVJblBvbGljeSwgMCwgc2NhbGVzLmxlbmd0aCk7XG4gICAgYWRqdXN0ZWRPdXRwdXRTaGFwZS5mb3JFYWNoKCh2LCBpKSA9PiAoYWRqdXN0ZWRPdXRwdXRTaGFwZVtpXSA9IE1hdGgucm91bmQodiAqIHNjYWxlc1tpXSkpKTtcbiAgfVxuICByZXR1cm4gYWRqdXN0ZWRPdXRwdXRTaGFwZTtcbn07XG5cbmNvbnN0IGNhbGN1bGF0ZU9yaWdpbmFsSW5kaWNlc0Zyb21PdXRwdXRJbmRpY2VzID0gKFxuICBvdXRwdXQ6IEluZGljZXNIZWxwZXIsXG4gIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHNjYWxlc0xlbmd0aDogbnVtYmVyLFxuICByb2lMZW5ndGg6IG51bWJlcixcbik6IHN0cmluZyA9PiBgXG4gICAgZm4gY2FsY3VsYXRlT3JpZ2luYWxJbmRpY2VzRnJvbU91dHB1dEluZGljZXMob3V0cHV0X2luZGljZXM6ICR7b3V0cHV0LnR5cGUuaW5kaWNlc30pIC0+IGFycmF5PCR7XG4gICAgICBvdXRwdXQudHlwZS52YWx1ZVxuICAgIH0sICR7b3V0cHV0U2hhcGUubGVuZ3RofT4ge1xuICAgICAgdmFyIG9yaWdpbmFsX2luZGljZXM6IGFycmF5PCR7b3V0cHV0LnR5cGUudmFsdWV9LCAke291dHB1dFNoYXBlLmxlbmd0aH0+O1xuICAgICAgZm9yICh2YXIgaTp1MzIgPSAwOyBpIDwgJHtvdXRwdXRTaGFwZS5sZW5ndGh9OyBpKyspIHtcbiAgICAgICAgdmFyIG91dHB1dF9pbmRleCA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dF9pbmRpY2VzJywgJ2knKX07XG4gICAgICAgIHZhciBzY2FsZSA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5zY2FsZXMnLCAnaScsIHNjYWxlc0xlbmd0aCl9O1xuICAgICAgICB2YXIgcm9pX2xvdyA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5yb2knLCAnaScsIHJvaUxlbmd0aCl9O1xuICAgICAgICB2YXIgcm9pX2hpID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnJvaScsIGBpICsgJHtpbnB1dFNoYXBlLmxlbmd0aH1gLCByb2lMZW5ndGgpfTtcbiAgICAgICAgaWYgKHNjYWxlID09IDEuMCkge1xuICAgICAgICAgIG9yaWdpbmFsX2luZGljZXNbaV0gPSAke291dHB1dC50eXBlLnZhbHVlfShvdXRwdXRfaW5kZXgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBpbnB1dF9zaGFwZV9pID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLmlucHV0X3NoYXBlJywgJ2knLCBpbnB1dFNoYXBlLmxlbmd0aCl9O1xuICAgICAgICAgIHZhciBvdXRwdXRfc2hhcGVfaSA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5vdXRwdXRfc2hhcGUnLCAnaScsIG91dHB1dFNoYXBlLmxlbmd0aCl9O1xuICAgICAgICAgIG9yaWdpbmFsX2luZGljZXNbaV0gPSBnZXRPcmlnaW5hbENvb3JkaW5hdGVGcm9tUmVzaXplZENvb3JkaW5hdGUob3V0cHV0X2luZGV4LCBzY2FsZSwgb3V0cHV0X3NoYXBlX2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dF9zaGFwZV9pLCByb2lfbG93LCByb2lfaGkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gb3JpZ2luYWxfaW5kaWNlcztcbiAgICB9YDtcblxuY29uc3QgY2FsY3VsYXRlSW5wdXRJbmRpY2VzRnJvbU91dHB1dEluZGljZXMgPSAoXG4gIGlucHV0OiBJbmRpY2VzSGVscGVyLFxuICBvdXRwdXQ6IEluZGljZXNIZWxwZXIsXG4gIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHNjYWxlc0xlbmd0aDogbnVtYmVyLFxuICByb2lMZW5ndGg6IG51bWJlcixcbiAgdXNlRXh0cmFwb2xhdGlvbjogYm9vbGVhbixcbik6IHN0cmluZyA9PiBgXG4gICAgZm4gY2FsY3VsYXRlSW5wdXRJbmRpY2VzRnJvbU91dHB1dEluZGljZXMob3V0cHV0X2luZGljZXM6ICR7b3V0cHV0LnR5cGUuaW5kaWNlc30pIC0+ICR7aW5wdXQudHlwZS5pbmRpY2VzfSB7XG4gICAgICB2YXIgaW5wdXRfaW5kaWNlczogJHtpbnB1dC50eXBlLmluZGljZXN9O1xuICAgICAgZm9yICh2YXIgaTp1MzIgPSAwOyBpIDwgJHtvdXRwdXRTaGFwZS5sZW5ndGh9OyBpKyspIHtcbiAgICAgICAgdmFyIG91dHB1dF9pbmRleCA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dF9pbmRpY2VzJywgJ2knKX07XG4gICAgICAgIHZhciBpbnB1dF9pbmRleDogdTMyO1xuICAgICAgICB2YXIgc2NhbGUgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMuc2NhbGVzJywgJ2knLCBzY2FsZXNMZW5ndGgpfTtcbiAgICAgICAgaWYgKHNjYWxlID09IDEuMCkge1xuICAgICAgICAgIGlucHV0X2luZGV4ID0gb3V0cHV0X2luZGV4O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciByb2lfbG93ID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnJvaScsICdpJywgcm9pTGVuZ3RoKX07XG4gICAgICAgICAgdmFyIHJvaV9oaSA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5yb2knLCBgaSArICR7aW5wdXRTaGFwZS5sZW5ndGh9YCwgcm9pTGVuZ3RoKX07XG4gICAgICAgICAgdmFyIGlucHV0X3NoYXBlX2kgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMuaW5wdXRfc2hhcGUnLCAnaScsIGlucHV0U2hhcGUubGVuZ3RoKX07XG4gICAgICAgICAgdmFyIG91dHB1dF9zaGFwZV9pID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLm91dHB1dF9zaGFwZScsICdpJywgb3V0cHV0U2hhcGUubGVuZ3RoKX07XG4gICAgICAgICAgdmFyIG9yaWdpbmFsX2lkeCA9IGdldE9yaWdpbmFsQ29vcmRpbmF0ZUZyb21SZXNpemVkQ29vcmRpbmF0ZShvdXRwdXRfaW5kZXgsIHNjYWxlLCBvdXRwdXRfc2hhcGVfaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0X3NoYXBlX2ksIHJvaV9sb3csIHJvaV9oaSk7XG4gICAgICAgICAgaWYgKCEke3VzZUV4dHJhcG9sYXRpb259IHx8IChvcmlnaW5hbF9pZHggPj0gMCAmJiBvcmlnaW5hbF9pZHggPCAke291dHB1dC50eXBlLnZhbHVlfShpbnB1dF9zaGFwZV9pKSkpIHtcbiAgICAgICAgICAgIGlmIChvcmlnaW5hbF9pZHggPCAwKSB7XG4gICAgICAgICAgICAgIGlucHV0X2luZGV4ID0gMDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAob3JpZ2luYWxfaWR4ID4gJHtvdXRwdXQudHlwZS52YWx1ZX0oaW5wdXRfc2hhcGVfaSAtIDEpKSB7XG4gICAgICAgICAgICAgIGlucHV0X2luZGV4ID0gaW5wdXRfc2hhcGVfaSAtIDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpbnB1dF9pbmRleCA9IHUzMihnZXROZWFyZXN0UGl4ZWxGcm9tT3JpZ2luYWwob3JpZ2luYWxfaWR4LCBzY2FsZSA8IDEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaW5wdXRfaW5kZXggPSB1MzIob3JpZ2luYWxfaWR4KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgJ2knLCAnaW5wdXRfaW5kZXgnKX1cbiAgICAgIH1cbiAgICAgIHJldHVybiBpbnB1dF9pbmRpY2VzO1xuICAgIH1gO1xuY29uc3QgY2hlY2tJbnB1dEluZGljZXMgPSAoaW5wdXQ6IEluZGljZXNIZWxwZXIsIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogc3RyaW5nID0+IGBcbiAgICBmbiBjaGVja0lucHV0SW5kaWNlcyhpbnB1dF9pbmRpY2VzOiAke2lucHV0LnR5cGUuaW5kaWNlc30pIC0+IGJvb2wge1xuICAgICAgZm9yICh2YXIgaTp1MzIgPSAwOyBpIDwgJHtpbnB1dFNoYXBlLmxlbmd0aH07IGkrKykge1xuICAgICAgICB2YXIgaW5wdXRfaW5kZXggPSAke2lucHV0LmluZGljZXNHZXQoJ2lucHV0X2luZGljZXMnLCAnaScpfTtcbiAgICAgICAgaWYgKGlucHV0X2luZGV4IDwgMCB8fCBpbnB1dF9pbmRleCA+PSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMuaW5wdXRfc2hhcGUnLCAnaScsIGlucHV0U2hhcGUubGVuZ3RoKX0pIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1gO1xuXG5jb25zdCBzZXRDaGFubmVsQW5kQmF0Y2hJbmRpY2VzID0gKFxuICBpbnB1dDogSW5kaWNlc0hlbHBlcixcbiAgY2hhbm5lbElkeDogbnVtYmVyLFxuICBiYXRjaElkeDogbnVtYmVyLFxuICBzcGFjaWFsRGltczogbnVtYmVyLFxuKTogc3RyaW5nID0+XG4gIGlucHV0LnJhbmsgPiBzcGFjaWFsRGltc1xuICAgID8gYFxuICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsIGNoYW5uZWxJZHgsICdjaGFubmVsJyl9O1xuICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsIGJhdGNoSWR4LCAnYmF0Y2gnKX07XG5gXG4gICAgOiAnJztcblxuY29uc3QgYmlsaW5lYXJJbnRlcnBvbGF0aW9uID0gKFxuICBpbnB1dDogSW5kaWNlc0hlbHBlcixcbiAgb3V0cHV0OiBJbmRpY2VzSGVscGVyLFxuICBpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgdXNlRXh0cmFwb2xhdGlvbjogYm9vbGVhbixcbiAgZXh0cmFwb2xhdGlvblZhbHVlOiBudW1iZXIsXG4pOiBzdHJpbmcgPT4ge1xuICBjb25zdCBpc05jaHcgPSB0cnVlO1xuICBjb25zdCBbYmF0Y2hJZHgsIGhlaWdodElkeCwgd2lkdGhJZHgsIGNoYW5uZWxJZHhdID1cbiAgICBpbnB1dFNoYXBlLmxlbmd0aCA9PT0gMiA/IFstMSwgMCwgMSwgLTFdIDogaXNOY2h3ID8gWzAsIDIsIDMsIDFdIDogWzAsIDEsIDIsIDNdO1xuICBjb25zdCBkVHlwZSA9IGlucHV0LnR5cGUudmFsdWU7XG4gIHJldHVybiBgXG4gICAgZm4gZ2V0SW5wdXRWYWx1ZShiYXRjaDogdTMyLCBjaGFubmVsOiB1MzIsIHJvdzogdTMyLCBjb2w6IHUzMikgLT4gJHtkVHlwZX0ge1xuICAgICAgdmFyIGlucHV0X2luZGljZXM6ICR7aW5wdXQudHlwZS5pbmRpY2VzfTtcbiAgICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsIGhlaWdodElkeCwgYG1heCgwLCBtaW4ocm93LCAke2lucHV0U2hhcGVbaGVpZ2h0SWR4XX0gLSAxKSlgKX07XG4gICAgICAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0X2luZGljZXMnLCB3aWR0aElkeCwgYG1heCgwLCBtaW4oY29sLCAke2lucHV0U2hhcGVbd2lkdGhJZHhdfSAtIDEpKWApfTtcbiAgICAgICR7c2V0Q2hhbm5lbEFuZEJhdGNoSW5kaWNlcyhpbnB1dCwgY2hhbm5lbElkeCwgYmF0Y2hJZHgsIDIpfVxuICAgICAgcmV0dXJuICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9O1xuICAgIH1cblxuICAgIGZuIGJpbGluZWFySW50ZXJwb2xhdGlvbihvdXRwdXRfaW5kaWNlczogJHtvdXRwdXQudHlwZS5pbmRpY2VzfSkgLT4gJHtkVHlwZX0ge1xuICAgICAgdmFyIG9yaWdpbmFsSW5kaWNlcyA9IGNhbGN1bGF0ZU9yaWdpbmFsSW5kaWNlc0Zyb21PdXRwdXRJbmRpY2VzKG91dHB1dF9pbmRpY2VzKTtcbiAgICAgIHZhciByb3c6JHtkVHlwZX0gPSBvcmlnaW5hbEluZGljZXNbJHtoZWlnaHRJZHh9XTtcbiAgICAgIHZhciBjb2w6JHtkVHlwZX0gPSBvcmlnaW5hbEluZGljZXNbJHt3aWR0aElkeH1dO1xuICAgICAgJHtcbiAgICAgICAgdXNlRXh0cmFwb2xhdGlvblxuICAgICAgICAgID8gYGlmIChyb3cgPCAwIHx8IHJvdyA+ICgke2lucHV0U2hhcGVbaGVpZ2h0SWR4XX0gLSAxKSB8fCBjb2wgPCAwIHx8IGNvbCA+ICgke2lucHV0U2hhcGVbd2lkdGhJZHhdfSAtIDEpKSB7XG4gICAgICAgIHJldHVybiAke2V4dHJhcG9sYXRpb25WYWx1ZX07XG4gICAgICB9YFxuICAgICAgICAgIDogJydcbiAgICAgIH07XG4gICAgICByb3cgPSBtYXgoMCwgbWluKHJvdywgJHtpbnB1dFNoYXBlW2hlaWdodElkeF19IC0gMSkpO1xuICAgICAgY29sID0gbWF4KDAsIG1pbihjb2wsICR7aW5wdXRTaGFwZVt3aWR0aElkeF19IC0gMSkpO1xuICAgICAgdmFyIHJvdzE6IHUzMiA9IHUzMihyb3cpO1xuICAgICAgdmFyIGNvbDE6IHUzMiA9IHUzMihjb2wpO1xuICAgICAgdmFyIHJvdzI6IHUzMiA9IHUzMihyb3cgKyAxKTtcbiAgICAgIHZhciBjb2wyOiB1MzIgPSB1MzIoY29sICsgMSk7XG4gICAgICB2YXIgY2hhbm5lbDogdTMyID0gJHtpbnB1dFNoYXBlLmxlbmd0aCA+IDIgPyBgdTMyKG9yaWdpbmFsSW5kaWNlc1ske2NoYW5uZWxJZHh9XSlgIDogJzAnfTtcbiAgICAgIHZhciBiYXRjaDogdTMyID0gICR7aW5wdXRTaGFwZS5sZW5ndGggPiAyID8gYHUzMihvcmlnaW5hbEluZGljZXNbJHtiYXRjaElkeH1dKWAgOiAnMCd9O1xuICAgICAgdmFyIHgxMTogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCByb3cxLCBjb2wxKTtcbiAgICAgIHZhciB4MTI6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgcm93MSwgY29sMik7XG4gICAgICB2YXIgeDIxOiAke2RUeXBlfSA9IGdldElucHV0VmFsdWUoYmF0Y2gsIGNoYW5uZWwsIHJvdzIsIGNvbDEpO1xuICAgICAgdmFyIHgyMjogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCByb3cyLCBjb2wyKTtcbiAgICAgIHZhciBkeDE6ICR7ZFR5cGV9ID0gYWJzKHJvdyAtICR7ZFR5cGV9KHJvdzEpKTtcbiAgICAgIHZhciBkeDI6ICR7ZFR5cGV9ID0gYWJzKCR7ZFR5cGV9KHJvdzIpIC0gcm93KTtcbiAgICAgIHZhciBkeTE6ICR7ZFR5cGV9ID0gYWJzKGNvbCAtICR7ZFR5cGV9KGNvbDEpKTtcbiAgICAgIHZhciBkeTI6ICR7ZFR5cGV9ID0gYWJzKCR7ZFR5cGV9KGNvbDIpIC0gY29sKTtcbiAgICAgIGlmIChyb3cxID09IHJvdzIpIHtcbiAgICAgICAgZHgxID0gMC41O1xuICAgICAgICBkeDIgPSAwLjU7XG4gICAgICB9XG4gICAgICBpZiAoY29sMSA9PSBjb2wyKSB7XG4gICAgICAgIGR5MSA9IDAuNTtcbiAgICAgICAgZHkyID0gMC41O1xuICAgICAgfVxuICAgICAgcmV0dXJuICh4MTEgKiBkeDIgKiBkeTIgKyB4MTIgKiBkeDIgKiBkeTEgKyB4MjEgKiBkeDEgKiBkeTIgKyB4MjIgKiBkeDEgKiBkeTEpO1xuICAgIH1gO1xufTtcblxuY29uc3QgYmljdWJpY0ludGVycG9sYXRpb24gPSAoXG4gIGlucHV0OiBJbmRpY2VzSGVscGVyLFxuICBvdXRwdXQ6IEluZGljZXNIZWxwZXIsXG4gIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHNjYWxlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHJvaTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGN1YmljQ29lZmZBOiBudW1iZXIsXG4gIHVzZUV4dHJhcG9sYXRpb246IGJvb2xlYW4sXG4gIGV4dHJhcG9sYXRpb25WYWx1ZTogbnVtYmVyLFxuICBleGNsdWRlT3V0c2lkZTogYm9vbGVhbixcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGlzMkQgPSBpbnB1dFNoYXBlLmxlbmd0aCA9PT0gMjtcbiAgY29uc3QgaXNOY2h3ID0gdHJ1ZTtcbiAgY29uc3QgW2hlaWdodElkeCwgd2lkdGhJZHhdID0gaXMyRCA/IFswLCAxXSA6IGlzTmNodyA/IFsyLCAzXSA6IFsxLCAyXTtcbiAgY29uc3QgZFR5cGUgPSBpbnB1dC50eXBlLnZhbHVlO1xuICBjb25zdCBjcmVhdGVDdWJpY0ludGVycG9sYXRpb25GdW5jdGlvbiA9IChpZHg6IG51bWJlcik6IHN0cmluZyA9PiB7XG4gICAgY29uc3QgZGlyZWN0aW9uID0gaWR4ID09PSBoZWlnaHRJZHggPyAncm93JyA6ICdjb2wnO1xuICAgIHJldHVybiBgXG4gICAgICBmbiAke2RpcmVjdGlvbn1DdWJpY0ludGVycG9sYXRpb24oaW5wdXRfaW5kaWNlczogJHtpbnB1dC50eXBlLmluZGljZXN9LCBvdXRwdXRfaW5kaWNlczogJHtcbiAgICAgICAgb3V0cHV0LnR5cGUuaW5kaWNlc1xuICAgICAgfSkgLT4gJHtkVHlwZX0ge1xuICAgICAgICB2YXIgb3V0cHV0X2luZGV4ID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCBpZHgpfTtcbiAgICAgICAgdmFyIG9yaWdpbmFsSWR4OiAke2RUeXBlfSA9IGdldE9yaWdpbmFsQ29vcmRpbmF0ZUZyb21SZXNpemVkQ29vcmRpbmF0ZShvdXRwdXRfaW5kZXgsICR7c2NhbGVzW2lkeF19LFxuICAgICAgICAke291dHB1dFNoYXBlW2lkeF19LCAke2lucHV0U2hhcGVbaWR4XX0sICR7cm9pW2lkeF19LCAke3JvaVtpZHhdfSArICR7aW5wdXRTaGFwZS5sZW5ndGh9KTtcbiAgICAgICAgdmFyIGZyYWN0T3JpZ2luYWxJZHg6ICR7ZFR5cGV9ID0gb3JpZ2luYWxJZHggLSBmbG9vcihvcmlnaW5hbElkeCk7XG4gICAgICAgIHZhciBjb2VmcyA9IGdldEN1YmljSW50ZXJwb2xhdGlvbkNvZWZzKGZyYWN0T3JpZ2luYWxJZHgpO1xuXG4gICAgICAgIGlmICgke3VzZUV4dHJhcG9sYXRpb259ICYmIChvcmlnaW5hbElkeCA8IDAgfHwgb3JpZ2luYWxJZHggPiAoJHtpbnB1dFNoYXBlW2lkeF19IC0gMSkpKSB7XG4gICAgICAgICAgcmV0dXJuICR7ZXh0cmFwb2xhdGlvblZhbHVlfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGF0YTogYXJyYXk8JHtkVHlwZX0sIDQ+ID0gYXJyYXk8JHtkVHlwZX0sIDQ+KDAuMCwgMC4wLCAwLjAsIDAuMCk7XG4gICAgICAgIGZvciAodmFyIGk6IGkzMiA9IC0xOyBpIDwgMzsgaSsrKSB7XG4gICAgICAgICAgdmFyICR7ZGlyZWN0aW9ufTogJHtkVHlwZX0gPSBvcmlnaW5hbElkeCArICR7ZFR5cGV9KGkpO1xuICAgICAgICAgIGlmICgke2RpcmVjdGlvbn0gPCAwIHx8ICR7ZGlyZWN0aW9ufSA+PSAke2lucHV0U2hhcGVbaWR4XX0pIHtcbiAgICAgICAgICAgICR7KCgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKGV4Y2x1ZGVPdXRzaWRlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGBjb2Vmc1tpICsgMV0gPSAwLjA7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtgO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKHVzZUV4dHJhcG9sYXRpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYHJldHVybiAke2V4dHJhcG9sYXRpb25WYWx1ZX07YDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYCR7ZGlyZWN0aW9ufSA9IG1heCgwLCBtaW4oJHtkaXJlY3Rpb259LCAke2lucHV0U2hhcGVbaWR4XX0gLSAxKSk7YDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkoKX07XG4gICAgICAgICAgfVxuICAgICAgICB2YXIgaW5wdXRfaW5kaWNlc19jb3B5OiAke2lucHV0LnR5cGUuaW5kaWNlc30gPSBpbnB1dF9pbmRpY2VzO1xuICAgICAgICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlc19jb3B5JywgaWR4LCBgdTMyKCR7ZGlyZWN0aW9ufSlgKX07XG4gICAgICAgICAgZGF0YVtpICsgMV0gPSAke1xuICAgICAgICAgICAgaWR4ID09PSBoZWlnaHRJZHhcbiAgICAgICAgICAgICAgPyBpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXNfY29weScpXG4gICAgICAgICAgICAgIDogJ3Jvd0N1YmljSW50ZXJwb2xhdGlvbihpbnB1dF9pbmRpY2VzX2NvcHksIG91dHB1dF9pbmRpY2VzKSdcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjdWJpY0ludGVycG9sYXRpb24xRChkYXRhLCBjb2Vmcyk7XG4gICAgICB9YDtcbiAgfTtcblxuICByZXR1cm4gYFxuICAgICR7Y3JlYXRlQ3ViaWNJbnRlcnBvbGF0aW9uRnVuY3Rpb24oaGVpZ2h0SWR4KX07XG4gICAgJHtjcmVhdGVDdWJpY0ludGVycG9sYXRpb25GdW5jdGlvbih3aWR0aElkeCl9O1xuICBmbiBnZXRDdWJpY0ludGVycG9sYXRpb25Db2VmcyhzOiAke2RUeXBlfSkgLT4gYXJyYXk8JHtkVHlwZX0sIDQ+IHtcbiAgICB2YXIgYWJzUyA9IGFicyhzKTtcbiAgICB2YXIgY29lZmZzOiBhcnJheTwke2RUeXBlfSwgND4gPSBhcnJheTwke2RUeXBlfSwgND4oMC4wLCAwLjAsIDAuMCwgMC4wKTtcbiAgICB2YXIgb25lTWludXNBYnNTOiAke2RUeXBlfSA9IDEuMCAtIGFic1M7XG4gICAgdmFyIHR3b01pbnVzQWJzUzogJHtkVHlwZX0gPSAyLjAgLSBhYnNTO1xuICAgIHZhciBvbmVQbHVzQWJzUzogJHtkVHlwZX0gPSAxLjAgKyBhYnNTO1xuICAgIGNvZWZmc1swXSA9ICgoJHtjdWJpY0NvZWZmQX0gKiBvbmVQbHVzQWJzUyAtIDUgKiAke2N1YmljQ29lZmZBfSkgKiBvbmVQbHVzQWJzUyArIDggKiAke1xuICAgICAgY3ViaWNDb2VmZkFcbiAgICB9KSAqIG9uZVBsdXNBYnNTIC0gNCAqICR7Y3ViaWNDb2VmZkF9O1xuICAgIGNvZWZmc1sxXSA9ICgoJHtjdWJpY0NvZWZmQX0gKyAyKSAqIGFic1MgLSAoJHtjdWJpY0NvZWZmQX0gKyAzKSkgKiBhYnNTICogYWJzUyArIDE7XG4gICAgY29lZmZzWzJdID0gKCgke2N1YmljQ29lZmZBfSArIDIpICogb25lTWludXNBYnNTIC0gKCR7Y3ViaWNDb2VmZkF9ICsgMykpICogb25lTWludXNBYnNTICogb25lTWludXNBYnNTICsgMTtcbiAgICBjb2VmZnNbM10gPSAoKCR7Y3ViaWNDb2VmZkF9ICogdHdvTWludXNBYnNTIC0gNSAqICR7Y3ViaWNDb2VmZkF9KSAqIHR3b01pbnVzQWJzUyArIDggKiAke1xuICAgICAgY3ViaWNDb2VmZkFcbiAgICB9KSAqIHR3b01pbnVzQWJzUyAtIDQgKiAke2N1YmljQ29lZmZBfTtcbiAgICByZXR1cm4gY29lZmZzO1xuICB9XG5cbiAgZm4gY3ViaWNJbnRlcnBvbGF0aW9uMUQoeDogYXJyYXk8JHtkVHlwZX0sIDQ+LCBjb2VmczogYXJyYXk8JHtkVHlwZX0sIDQ+KSAtPiAke2RUeXBlfSB7XG4gICAgdmFyIGNvZWZzU3VtOiAke2RUeXBlfSA9IGNvZWZzWzBdICsgY29lZnNbMV0gKyBjb2Vmc1syXSArIGNvZWZzWzNdO1xuICAgIHJldHVybiAoeFswXSAqIGNvZWZzWzBdICsgeFsxXSAqIGNvZWZzWzFdKyB4WzJdICogY29lZnNbMl0rIHhbM10gKiBjb2Vmc1szXSkgLyBjb2Vmc1N1bTtcbiAgfVxuXG4gIGZuIGJpY3ViaWNJbnRlcnBvbGF0aW9uKG91dHB1dF9pbmRpY2VzOiAke291dHB1dC50eXBlLmluZGljZXN9KSAtPiAke2RUeXBlfSB7XG4gICAgdmFyIGlucHV0X2luZGljZXM6ICR7aW5wdXQudHlwZS5pbmRpY2VzfSA9IG91dHB1dF9pbmRpY2VzO1xuICAgIHJldHVybiBjb2xDdWJpY0ludGVycG9sYXRpb24oaW5wdXRfaW5kaWNlcywgb3V0cHV0X2luZGljZXMpO1xuICB9XG4gICAgYDtcbn07XG5cbmNvbnN0IHRyaWxpbmVhckludGVycG9sYXRpb24gPSAoXG4gIGlucHV0OiBJbmRpY2VzSGVscGVyLFxuICBvdXRwdXQ6IEluZGljZXNIZWxwZXIsXG4gIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICB1c2VFeHRyYXBvbGF0aW9uOiBib29sZWFuLFxuICBleHRyYXBvbGF0aW9uVmFsdWU6IG51bWJlcixcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGlzTmNodyA9IHRydWU7XG4gIGNvbnN0IFtiYXRjaElkeCwgZGVwdGhJZHgsIGhlaWdodElkeCwgd2lkdGhJZHgsIGNoYW5uZWxJZHhdID1cbiAgICBpbnB1dFNoYXBlLmxlbmd0aCA9PT0gMyA/IFstMSwgMCwgMSwgMiwgLTFdIDogaXNOY2h3ID8gWzAsIDIsIDMsIDQsIDFdIDogWzAsIDEsIDIsIDMsIDRdO1xuICBjb25zdCBkVHlwZSA9IGlucHV0LnR5cGUudmFsdWU7XG4gIHJldHVybiBgXG4gICAgZm4gZ2V0SW5wdXRWYWx1ZShiYXRjaDogdTMyLCBjaGFubmVsOiB1MzIsIGRlcHRoOnUzMiwgaGVpZ2h0OiB1MzIsIHdpZHRoOiB1MzIpIC0+ICR7ZFR5cGV9IHtcbiAgICAgIHZhciBpbnB1dF9pbmRpY2VzOiAke2lucHV0LnR5cGUuaW5kaWNlc307XG4gICAgICAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0X2luZGljZXMnLCBkZXB0aElkeCwgYG1heCgwLCBtaW4oZGVwdGgsICR7aW5wdXRTaGFwZVtkZXB0aElkeF19IC0gMSkpYCl9O1xuICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgaGVpZ2h0SWR4LCBgbWF4KDAsIG1pbihoZWlnaHQsICR7aW5wdXRTaGFwZVtoZWlnaHRJZHhdfSAtIDEpKWApfTtcbiAgICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsIHdpZHRoSWR4LCBgbWF4KDAsIG1pbih3aWR0aCwgJHtpbnB1dFNoYXBlW3dpZHRoSWR4XX0gLSAxKSlgKX07XG4gICAgICAke3NldENoYW5uZWxBbmRCYXRjaEluZGljZXMoaW5wdXQsIGNoYW5uZWxJZHgsIGJhdGNoSWR4LCAzKX1cbiAgICAgIHJldHVybiAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTtcbiAgICB9XG5cbiAgICBmbiB0cmlsaW5lYXJJbnRlcnBvbGF0aW9uKG91dHB1dF9pbmRpY2VzOiAke291dHB1dC50eXBlLmluZGljZXN9KSAtPiAke2RUeXBlfSB7XG4gICAgICB2YXIgb3JpZ2luYWxJbmRpY2VzID0gY2FsY3VsYXRlT3JpZ2luYWxJbmRpY2VzRnJvbU91dHB1dEluZGljZXMob3V0cHV0X2luZGljZXMpO1xuICAgICAgdmFyIGRlcHRoOiR7ZFR5cGV9ID0gb3JpZ2luYWxJbmRpY2VzWyR7ZGVwdGhJZHh9XTtcbiAgICAgIHZhciBoZWlnaHQ6JHtkVHlwZX0gPSBvcmlnaW5hbEluZGljZXNbJHtoZWlnaHRJZHh9XTtcbiAgICAgIHZhciB3aWR0aDoke2RUeXBlfSA9IG9yaWdpbmFsSW5kaWNlc1ske3dpZHRoSWR4fV07XG4gICAgICAke1xuICAgICAgICB1c2VFeHRyYXBvbGF0aW9uXG4gICAgICAgICAgPyBgaWYgKGRlcHRoIDwgMCB8fCBkZXB0aCA+ICgke2lucHV0U2hhcGVbZGVwdGhJZHhdfSAtIDEpIHx8IGhlaWdodCA8IDAgfHwgaGVpZ2h0ID4gKCR7XG4gICAgICAgICAgICAgIGlucHV0U2hhcGVbaGVpZ2h0SWR4XVxuICAgICAgICAgICAgfSAtIDEpIHx8IHdpZHRoIDwgMCB8fCAod2lkdGggPiAke2lucHV0U2hhcGVbd2lkdGhJZHhdfSAtIDEpKSB7XG4gICAgICByZXR1cm4gJHtleHRyYXBvbGF0aW9uVmFsdWV9O1xuICAgICAgICB9YFxuICAgICAgICAgIDogJydcbiAgICAgIH07XG5cbiAgICBkZXB0aCA9IG1heCgwLCBtaW4oZGVwdGgsICR7aW5wdXRTaGFwZVtkZXB0aElkeF19IC0gMSkpO1xuICAgICAgaGVpZ2h0ID0gbWF4KDAsIG1pbihoZWlnaHQsICR7aW5wdXRTaGFwZVtoZWlnaHRJZHhdfSAtIDEpKTtcbiAgICAgIHdpZHRoID0gbWF4KDAsIG1pbih3aWR0aCwgJHtpbnB1dFNoYXBlW3dpZHRoSWR4XX0gLSAxKSk7XG4gICAgICB2YXIgZGVwdGgxOiB1MzIgPSB1MzIoZGVwdGgpO1xuICAgICAgdmFyIGhlaWdodDE6IHUzMiA9IHUzMihoZWlnaHQpO1xuICAgICAgdmFyIHdpZHRoMTogdTMyID0gdTMyKHdpZHRoKTtcbiAgICAgIHZhciBkZXB0aDI6IHUzMiA9IHUzMihkZXB0aCArIDEpO1xuICAgICAgdmFyIGhlaWdodDI6IHUzMiA9IHUzMihoZWlnaHQgKyAxKTtcbiAgICAgIHZhciB3aWR0aDI6IHUzMiA9IHUzMih3aWR0aCArIDEpO1xuICAgICAgdmFyIGNoYW5uZWw6IHUzMiA9ICR7aW5wdXRTaGFwZS5sZW5ndGggPiAzID8gYHUzMihvcmlnaW5hbEluZGljZXNbJHtjaGFubmVsSWR4fV0pYCA6ICcwJ307XG4gICAgICB2YXIgYmF0Y2g6IHUzMiA9ICAke2lucHV0U2hhcGUubGVuZ3RoID4gMyA/IGB1MzIob3JpZ2luYWxJbmRpY2VzWyR7YmF0Y2hJZHh9XSlgIDogJzAnfTtcblxuICAgICAgdmFyIHgxMTE6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgZGVwdGgxLCBoZWlnaHQxLCB3aWR0aDEpO1xuICAgICAgdmFyIHgxMTI6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgZGVwdGgxLCBoZWlnaHQxLCB3aWR0aDIpO1xuICAgICAgdmFyIHgxMjE6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgZGVwdGgxLCBoZWlnaHQyLCB3aWR0aDEpO1xuICAgICAgdmFyIHgxMjI6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgZGVwdGgxLCBoZWlnaHQyLCB3aWR0aDIpO1xuICAgICAgdmFyIHgyMTE6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgZGVwdGgyLCBoZWlnaHQxLCB3aWR0aDEpO1xuICAgICAgdmFyIHgyMTI6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgZGVwdGgyLCBoZWlnaHQxLCB3aWR0aDIpO1xuICAgICAgdmFyIHgyMjE6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgZGVwdGgyLCBoZWlnaHQyLCB3aWR0aDEpO1xuICAgICAgdmFyIHgyMjI6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgZGVwdGgyLCBoZWlnaHQyLCB3aWR0aDIpO1xuICAgICAgdmFyIGR4MTogJHtkVHlwZX0gPSBhYnMoZGVwdGggLSAke2RUeXBlfShkZXB0aDEpKTtcbiAgICAgIHZhciBkeDI6ICR7ZFR5cGV9ID0gYWJzKCR7ZFR5cGV9KGRlcHRoMikgLSBkZXB0aCk7XG4gICAgICB2YXIgZHkxOiAke2RUeXBlfSA9IGFicyhoZWlnaHQgLSAke2RUeXBlfShoZWlnaHQxKSk7XG4gICAgICB2YXIgZHkyOiAke2RUeXBlfSA9IGFicygke2RUeXBlfShoZWlnaHQyKSAtIGhlaWdodCk7XG4gICAgICB2YXIgZHoxOiAke2RUeXBlfSA9IGFicyh3aWR0aCAtICR7ZFR5cGV9KHdpZHRoMSkpO1xuICAgICAgdmFyIGR6MjogJHtkVHlwZX0gPSBhYnMoJHtkVHlwZX0od2lkdGgyKSAtIHdpZHRoKTtcbiAgICAgIGlmIChkZXB0aDEgPT0gZGVwdGgyKSB7XG4gICAgICAgIGR4MSA9IDAuNTtcbiAgICAgICAgZHgyID0gMC41O1xuICAgICAgfVxuICAgICAgaWYgKGhlaWdodDEgPT0gaGVpZ2h0Mikge1xuICAgICAgICBkeTEgPSAwLjU7XG4gICAgICAgIGR5MiA9IDAuNTtcbiAgICAgIH1cbiAgICAgIGlmICh3aWR0aDEgPT0gd2lkdGgyKSB7XG4gICAgICAgIGR6MSA9IDAuNTtcbiAgICAgICAgZHoyID0gMC41O1xuICAgICAgfVxuICAgICAgcmV0dXJuICh4MTExICogZHgyICogZHkyICogZHoyICsgeDExMiAqIGR4MiAqIGR5MiAqIGR6MSArIHgxMjEgKiBkeDIgKiBkeTEgKmR6MiArIHgxMjIgKiBkeDIgKiBkeTEgKiBkejEgK1xuICAgICAgICAgICAgICB4MjExICogZHgxICogZHkyICogZHoyICsgeDIxMiAqIGR4MSAqIGR5MiAqIGR6MSArIHgyMjEgKiBkeDEgKiBkeTEgKmR6MiArIHgyMjIgKiBkeDEgKiBkeTEgKiBkejEpO1xuICAgIH1gO1xufTtcblxuY29uc3QgY3JlYXRlUmVzaXplUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0VGVuc29yOiBUZW5zb3JWaWV3LFxuICBhdHRyaWJ1dGVzOiBSZXNpemVBdHRyaWJ1dGVzLFxuICBvcHNldFZlcnNpb246IG51bWJlcixcbiAgc2NhbGVzSW5wdXQ6IHJlYWRvbmx5IG51bWJlcltdLFxuICBzaXplczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHJvaUlucHV0OiByZWFkb25seSBudW1iZXJbXSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0VGVuc29yLmRpbXM7XG4gIGNvbnN0IHJvaSA9IHVwZGF0ZVJvSShyb2lJbnB1dCwgYXR0cmlidXRlcy5heGVzLCBpbnB1dFNoYXBlLmxlbmd0aCk7XG5cbiAgbGV0IG91dHB1dFNoYXBlID0gaW5pdE91dHB1dFNoYXBlKGlucHV0U2hhcGUsIHNjYWxlc0lucHV0LCBzaXplcywgYXR0cmlidXRlcy5heGVzKTtcbiAgbGV0IHNjYWxlcyA9IHNjYWxlc0lucHV0LnNsaWNlKCk7XG4gIGlmIChzY2FsZXNJbnB1dC5sZW5ndGggPT09IDApIHtcbiAgICBzY2FsZXMgPSBpbnB1dFNoYXBlLm1hcCgodmFsdWUsIGluZGV4KSA9PiAodmFsdWUgPT09IDAgPyAxLjAgOiBvdXRwdXRTaGFwZVtpbmRleF0gLyB2YWx1ZSkpO1xuICAgIGlmIChhdHRyaWJ1dGVzLmtlZXBBc3BlY3RSYXRpb1BvbGljeSAhPT0gJ3N0cmV0Y2gnKSB7XG4gICAgICBvdXRwdXRTaGFwZSA9IGFkanVzdE91dHB1dFNoYXBlKGlucHV0U2hhcGUsIHNjYWxlcywgYXR0cmlidXRlcyk7XG4gICAgfVxuICB9XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dFRlbnNvci5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0VGVuc29yLmRhdGFUeXBlLCBpbnB1dFNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IG5vU2NhbGUgPSBpbnB1dFNoYXBlLmxlbmd0aCA9PT0gb3V0cHV0U2hhcGUubGVuZ3RoICYmIGlucHV0U2hhcGUuZXZlcnkoKGQsIGkpID0+IGQgPT09IG91dHB1dFNoYXBlW2ldKTtcbiAgY29uc3QgdXNlRXh0cmFwb2xhdGlvbiA9IGF0dHJpYnV0ZXMuY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUgPT09ICd0Zl9jcm9wX2FuZF9yZXNpemUnO1xuICBjb25zdCBleHRyYXBvbGF0aW9uVmFsdWUgPSBhdHRyaWJ1dGVzLmV4dHJhcG9sYXRpb25WYWx1ZTtcbiAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dC50eXBlLnZhbHVlO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgICAgICR7XG4gICAgICAgIG5vU2NhbGVcbiAgICAgICAgICA/ICcnXG4gICAgICAgICAgOiBgXG4gICAgICAke2dldE9yaWdpbmFsQ29vcmRpbmF0ZUZyb21SZXNpemVkQ29vcmRpbmF0ZShhdHRyaWJ1dGVzLmNvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlLCBkYXRhVHlwZSl9O1xuICAgICAgJHsoKCkgPT4ge1xuICAgICAgICBzd2l0Y2ggKGF0dHJpYnV0ZXMubW9kZSkge1xuICAgICAgICAgIGNhc2UgJ25lYXJlc3QnOlxuICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgJHtjaGVja0lucHV0SW5kaWNlcyhpbnB1dCwgaW5wdXRTaGFwZSl9O1xuICAgICAgICAgICAgICAke2dldE5lYXJlc3RQaXhlbEZyb21PcmlnaW5hbChhdHRyaWJ1dGVzLm5lYXJlc3RNb2RlLCBvcHNldFZlcnNpb24sIGRhdGFUeXBlKX07XG4gICAgICAgICAgICAgICR7Y2FsY3VsYXRlSW5wdXRJbmRpY2VzRnJvbU91dHB1dEluZGljZXMoXG4gICAgICAgICAgICAgICAgaW5wdXQsXG4gICAgICAgICAgICAgICAgb3V0cHV0LFxuICAgICAgICAgICAgICAgIGlucHV0U2hhcGUsXG4gICAgICAgICAgICAgICAgb3V0cHV0U2hhcGUsXG4gICAgICAgICAgICAgICAgc2NhbGVzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICByb2kubGVuZ3RoLFxuICAgICAgICAgICAgICAgIHVzZUV4dHJhcG9sYXRpb24sXG4gICAgICAgICAgICAgICl9O1xuICAgICAgICAgICAgICBgO1xuICAgICAgICAgIGNhc2UgJ2xpbmVhcic6XG4gICAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgICAke2NhbGN1bGF0ZU9yaWdpbmFsSW5kaWNlc0Zyb21PdXRwdXRJbmRpY2VzKG91dHB1dCwgaW5wdXRTaGFwZSwgb3V0cHV0U2hhcGUsIHNjYWxlcy5sZW5ndGgsIHJvaS5sZW5ndGgpfTtcbiAgICAgICAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dFNoYXBlLmxlbmd0aCA9PT0gMiB8fCBpbnB1dFNoYXBlLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGAke2JpbGluZWFySW50ZXJwb2xhdGlvbihpbnB1dCwgb3V0cHV0LCBpbnB1dFNoYXBlLCB1c2VFeHRyYXBvbGF0aW9uLCBleHRyYXBvbGF0aW9uVmFsdWUpfWA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpbnB1dFNoYXBlLmxlbmd0aCA9PT0gMyB8fCBpbnB1dFNoYXBlLmxlbmd0aCA9PT0gNSkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGAke3RyaWxpbmVhckludGVycG9sYXRpb24oaW5wdXQsIG91dHB1dCwgaW5wdXRTaGFwZSwgdXNlRXh0cmFwb2xhdGlvbiwgZXh0cmFwb2xhdGlvblZhbHVlKX1gO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcignTGluZWFyIG1vZGUgb25seSBzdXBwb3J0cyBpbnB1dCBkaW1zIDIsIDMsIDQgYW5kIDUgYXJlIHN1cHBvcnRlZCBpbiBsaW5lYXIgbW9kZS4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pKCl9O1xuICAgICAgICAgICAgYDtcbiAgICAgICAgICBjYXNlICdjdWJpYyc6XG4gICAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoaW5wdXRTaGFwZS5sZW5ndGggPT09IDIgfHwgaW5wdXRTaGFwZS5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYCR7YmljdWJpY0ludGVycG9sYXRpb24oXG4gICAgICAgICAgICAgICAgICBpbnB1dCxcbiAgICAgICAgICAgICAgICAgIG91dHB1dCxcbiAgICAgICAgICAgICAgICAgIGlucHV0U2hhcGUsXG4gICAgICAgICAgICAgICAgICBvdXRwdXRTaGFwZSxcbiAgICAgICAgICAgICAgICAgIHNjYWxlcyxcbiAgICAgICAgICAgICAgICAgIHJvaSxcbiAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXMuY3ViaWNDb2VmZkEsXG4gICAgICAgICAgICAgICAgICB1c2VFeHRyYXBvbGF0aW9uLFxuICAgICAgICAgICAgICAgICAgYXR0cmlidXRlcy5leHRyYXBvbGF0aW9uVmFsdWUsXG4gICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLmV4Y2x1ZGVPdXRzaWRlLFxuICAgICAgICAgICAgICAgICl9YDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcignQ3ViaWMgbW9kZSBvbmx5IHN1cHBvcnRzIGlucHV0IGRpbXMgMiBhbmQgNCBhcmUgc3VwcG9ydGVkIGluIGxpbmVhciBtb2RlLicpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSgpfTtcbiAgICAgICAgICAgIGA7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IEVycm9yKCdJbnZhbGlkIHJlc2l6ZSBtb2RlJyk7XG4gICAgICAgIH1cbiAgICAgIH0pKCl9O1xuICAgICAgYFxuICAgICAgfVxuICAgICAgJHtzaGFkZXJIZWxwZXJcbiAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJylcbiAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnc2NhbGVzJywgJ2YzMicsIHNjYWxlcy5sZW5ndGgpXG4gICAgICAgIC5yZWdpc3RlclVuaWZvcm0oJ3JvaScsICdmMzInLCByb2kubGVuZ3RoKVxuICAgICAgICAuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgb3V0cHV0KX1cbiAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICAgICAgICAke1xuICAgICAgICAgIG5vU2NhbGVcbiAgICAgICAgICAgID8gJ291dHB1dFtnbG9iYWxfaWR4XSA9IGlucHV0W2dsb2JhbF9pZHhdOydcbiAgICAgICAgICAgIDogYFxuICAgICAgICBsZXQgb3V0cHV0X2luZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICAgIHZhciBpbnB1dF9pbmRpY2VzOiAke2lucHV0LnR5cGUuaW5kaWNlc307XG4gICAgICAgICR7KCgpID0+IHtcbiAgICAgICAgICBzd2l0Y2ggKGF0dHJpYnV0ZXMubW9kZSkge1xuICAgICAgICAgICAgY2FzZSAnbmVhcmVzdCc6XG4gICAgICAgICAgICAgIHJldHVybiBgaW5wdXRfaW5kaWNlcyA9IGNhbGN1bGF0ZUlucHV0SW5kaWNlc0Zyb21PdXRwdXRJbmRpY2VzKG91dHB1dF9pbmRpY2VzKTtcbiAgICAgICAgICAgICAgICBpZiAoY2hlY2tJbnB1dEluZGljZXMoaW5wdXRfaW5kaWNlcykpIHtcbiAgICAgICAgICAgICAgICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9ICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBvdXRwdXRbZ2xvYmFsX2lkeF0gPSAke2F0dHJpYnV0ZXMuZXh0cmFwb2xhdGlvblZhbHVlfTtcbiAgICAgICAgICAgICAgICB9YDtcbiAgICAgICAgICAgIGNhc2UgJ2xpbmVhcic6XG4gICAgICAgICAgICAgIHJldHVybiBgb3V0cHV0W2dsb2JhbF9pZHhdID0gJHtcbiAgICAgICAgICAgICAgICBpbnB1dFNoYXBlLmxlbmd0aCA9PT0gMiB8fCBpbnB1dFNoYXBlLmxlbmd0aCA9PT0gNCA/ICdiaWxpbmVhckludGVycG9sYXRpb24nIDogJ3RyaWxpbmVhckludGVycG9sYXRpb24nXG4gICAgICAgICAgICAgIH0ob3V0cHV0X2luZGljZXMpO2A7XG4gICAgICAgICAgICBjYXNlICdjdWJpYyc6XG4gICAgICAgICAgICAgIHJldHVybiAnb3V0cHV0W2dsb2JhbF9pZHhdID0gYmljdWJpY0ludGVycG9sYXRpb24ob3V0cHV0X2luZGljZXMpOyc7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICB0aHJvdyBFcnJvcihgVW5zdXBwb3J0ZWQgcmVzaXplIG1vZGU6ICR7YXR0cmlidXRlcy5tb2RlfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKX07XG5gXG4gICAgICAgIH1cbiAgICAgIH1gO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1Jlc2l6ZScsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9fCR7b3BzZXRWZXJzaW9ufXwke1xuICAgICAgICBzY2FsZXMubGVuZ3RoID4gMCA/IChhdHRyaWJ1dGVzLm1vZGUgPT09ICdjdWJpYycgPyBzY2FsZXMgOiBzY2FsZXMubGVuZ3RoKSA6ICcnXG4gICAgICB9fCR7c2l6ZXMubGVuZ3RoID4gMCA/IHNpemVzIDogJyd9fCR7cm9pLmxlbmd0aCA+IDAgPyByb2kgOiAnJ318JHtub1NjYWxlfXwke1xuICAgICAgICBhdHRyaWJ1dGVzLm1vZGUgPT09ICduZWFyZXN0JyA/IGlucHV0U2hhcGUubGVuZ3RoIDogaW5wdXRTaGFwZVxuICAgICAgfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJ10sXG4gICAgfSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRUZW5zb3IuZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXM6IFtcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogc2NhbGVzIH0sXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IHJvaSB9LFxuICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlLCBvdXRwdXRTaGFwZSksXG4gICAgICBdLFxuICAgIH0pLFxuICB9O1xufTtcblxuY29uc3QgZ2V0T3BzZXRWZXJzaW9uRnJvbUN1c3RvbURhdGFCdWZmZXIgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiBudW1iZXIgPT4ge1xuICBjb25zdCBjdXN0b21EYXRhQnVmZmVyID0gY29udGV4dC5jdXN0b21EYXRhQnVmZmVyO1xuICBjb25zdCBjdXN0b21EYXRhQnVmZmVyMzIgPSBuZXcgVWludDMyQXJyYXkoY3VzdG9tRGF0YUJ1ZmZlciwgY3VzdG9tRGF0YUJ1ZmZlci5ieXRlT2Zmc2V0LCAxKTtcbiAgY29uc3Qgb3BzZXRWZXJzaW9uID0gY3VzdG9tRGF0YUJ1ZmZlcjMyWzBdO1xuICByZXR1cm4gb3BzZXRWZXJzaW9uO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlc2l6ZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVzaXplQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBzY2FsZXM6IG51bWJlcltdID0gW107XG4gIGNvbnN0IHNpemVzOiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCByb2k6IG51bWJlcltdID0gW107XG5cbiAgLy8gTm90ZSB0aGF0IHNjYWxlcyBpbiByZXNpemUgYXJlIGFsd2F5cyBmMzIuIHJvaSBjYW4gYmUgZjMyIG9yIGYxNi5cbiAgLy8gVE9ETzogQ3VycmVudGx5IHRoaXMgY29kZSBkb2VzIG5vdCBzdXBwb3J0IGYxNiBmb3Igcm9pIHdoZW4gcGFzc2VkIGFzIG9wdGlvbmFsIGlucHV0LlxuXG4gIGNvbnN0IG9wc2V0VmVyc2lvbiA9IGdldE9wc2V0VmVyc2lvbkZyb21DdXN0b21EYXRhQnVmZmVyKGNvbnRleHQpO1xuICBpZiAoYXR0cmlidXRlcy5hbnRpYWxpYXMgIT09IDApIHtcbiAgICB0aHJvdyBFcnJvcignT25seSBkZWZhdWx0IHZhbHVlICgwKSBmb3IgQW50aWFsaWFzIGF0dHJpYnV0ZSBpcyBzdXBwb3J0ZWQnKTtcbiAgfVxuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcywgb3BzZXRWZXJzaW9uLCBzY2FsZXMsIHNpemVzLCByb2kpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlUmVzaXplUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sIGF0dHJpYnV0ZXMsIG9wc2V0VmVyc2lvbiwgc2NhbGVzLCBzaXplcywgcm9pKSwge1xuICAgIGlucHV0czogWzBdLFxuICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBSZXNpemVBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgYW50aWFsaWFzID0gYXR0cmlidXRlcy5hbnRpYWxpYXMgYXMgbnVtYmVyO1xuICBjb25zdCBheGVzID0gYXR0cmlidXRlcy5heGVzIGFzIG51bWJlcltdO1xuICBjb25zdCBjb29yZGluYXRlVHJhbnNmb3JtTW9kZTogQ29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUgPVxuICAgIGF0dHJpYnV0ZXMuY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUgYXMgQ29vcmRpbmF0ZVRyYW5zZm9ybU1vZGU7XG4gIGNvbnN0IGN1YmljQ29lZmZBID0gYXR0cmlidXRlcy5jdWJpY0NvZWZmQSBhcyBudW1iZXI7XG4gIGNvbnN0IGV4Y2x1ZGVPdXRzaWRlID0gKGF0dHJpYnV0ZXMuZXhjbHVkZU91dHNpZGUgYXMgbnVtYmVyKSAhPT0gMDtcbiAgY29uc3QgZXh0cmFwb2xhdGlvblZhbHVlID0gYXR0cmlidXRlcy5leHRyYXBvbGF0aW9uVmFsdWUgYXMgbnVtYmVyO1xuICBjb25zdCBrZWVwQXNwZWN0UmF0aW9Qb2xpY3k6IEtlZXBBc3BlY3RSYXRpb1BvbGljeSA9IGF0dHJpYnV0ZXMua2VlcEFzcGVjdFJhdGlvUG9saWN5IGFzIEtlZXBBc3BlY3RSYXRpb1BvbGljeTtcbiAgY29uc3QgbW9kZTogTW9kZSA9IGF0dHJpYnV0ZXMubW9kZSBhcyBNb2RlO1xuICAvLyBJZiBuZWFyZXN0TW9kZSBpcyBub3Qgc3BlY2lmaWVkLCB1c2Ugc2ltcGxlIG1vZGUuXG4gIGNvbnN0IG5lYXJlc3RNb2RlOiBOZWFyZXN0TW9kZSA9IChhdHRyaWJ1dGVzLm5lYXJlc3RNb2RlID09PSAnJyA/ICdzaW1wbGUnIDogYXR0cmlidXRlcy5uZWFyZXN0TW9kZSkgYXMgTmVhcmVzdE1vZGU7XG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe1xuICAgIGFudGlhbGlhcyxcbiAgICBheGVzLFxuICAgIGNvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlLFxuICAgIGN1YmljQ29lZmZBLFxuICAgIGV4Y2x1ZGVPdXRzaWRlLFxuICAgIGV4dHJhcG9sYXRpb25WYWx1ZSxcbiAgICBrZWVwQXNwZWN0UmF0aW9Qb2xpY3ksXG4gICAgbW9kZSxcbiAgICBuZWFyZXN0TW9kZSxcbiAgfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNhc3RUb0YzMixcbiAgZ2V0TWF4Q29tcG9uZW50cyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgc3VtVmVjdG9yLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2tpcExheWVyTm9ybUF0dHJpYnV0ZXMge1xuICBzaW1wbGlmaWVkOiBib29sZWFuO1xuICBlcHNpbG9uOiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPCAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdsYXllck5vcm0gcmVxdWlyZXMgYXQgbGVhc3QgMyBpbnB1dHMuJyk7XG4gIH1cblxuICBjb25zdCBpbnB1dDogVGVuc29yVmlldyA9IGlucHV0c1swXTtcbiAgY29uc3Qgc2tpcDogVGVuc29yVmlldyA9IGlucHV0c1sxXTtcbiAgY29uc3QgZ2FtbWE6IFRlbnNvclZpZXcgPSBpbnB1dHNbMl07XG5cbiAgaWYgKGlucHV0LmRhdGFUeXBlICE9PSBza2lwLmRhdGFUeXBlIHx8IGlucHV0LmRhdGFUeXBlICE9PSBnYW1tYS5kYXRhVHlwZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQWxsIGlucHV0cyBtdXN0IGhhdmUgdGhlIHNhbWUgZGF0YSB0eXBlJyk7XG4gIH1cblxuICBpZiAoaW5wdXQuZGltcy5sZW5ndGggIT09IDMgJiYgaW5wdXQuZGltcy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IG11c3QgYmUgMkQgb3IgM0QnKTtcbiAgfVxuXG4gIGlmIChza2lwLmRpbXMubGVuZ3RoICE9PSAzICYmIHNraXAuZGltcy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1NraXAgbXVzdCBiZSAyRCBvciAzRCcpO1xuICB9XG5cbiAgY29uc3QgaGlkZGVuU2l6ZSA9IGlucHV0LmRpbXNbaW5wdXQuZGltcy5sZW5ndGggLSAxXTtcbiAgY29uc3Qgc2VxdWVuY2VMZW5ndGggPSBpbnB1dC5kaW1zW2lucHV0LmRpbXMubGVuZ3RoIC0gMl07XG4gIGlmIChza2lwLmRpbXNbc2tpcC5kaW1zLmxlbmd0aCAtIDFdICE9PSBoaWRkZW5TaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTa2lwIG11c3QgaGF2ZSB0aGUgc2FtZSBoaWRkZW4gc2l6ZSBhcyBpbnB1dCcpO1xuICB9XG4gIGlmIChza2lwLmRpbXNbc2tpcC5kaW1zLmxlbmd0aCAtIDJdICE9PSBzZXF1ZW5jZUxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignU2tpcCBtdXN0IGhhdmUgdGhlIHNhbWUgc2VxdWVuY2UgbGVuZ3RoIGFzIGlucHV0Jyk7XG4gIH1cblxuICBpZiAoZ2FtbWEuZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0dhbW1hIG11c3QgYmUgMUQnKTtcbiAgfVxuICBpZiAoZ2FtbWEuZGltc1tnYW1tYS5kaW1zLmxlbmd0aCAtIDFdICE9PSBoaWRkZW5TaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdHYW1tYSBtdXN0IGhhdmUgdGhlIHNhbWUgaGlkZGVuIHNpemUgYXMgaW5wdXQnKTtcbiAgfVxuICBpZiAoaW5wdXRzLmxlbmd0aCA+IDMpIHtcbiAgICBjb25zdCBiZXRhOiBUZW5zb3JWaWV3ID0gaW5wdXRzWzNdO1xuICAgIGlmIChiZXRhLmRpbXMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0JldGEgbXVzdCBiZSAxRCcpO1xuICAgIH1cbiAgICBpZiAoYmV0YS5kaW1zW2JldGEuZGltcy5sZW5ndGggLSAxXSAhPT0gaGlkZGVuU2l6ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCZXRhIG11c3QgaGF2ZSB0aGUgc2FtZSBoaWRkZW4gc2l6ZSBhcyBpbnB1dCcpO1xuICAgIH1cbiAgfVxuICBpZiAoaW5wdXRzLmxlbmd0aCA+IDQpIHtcbiAgICBjb25zdCBiaWFzOiBUZW5zb3JWaWV3ID0gaW5wdXRzWzRdO1xuICAgIGlmIChiaWFzLmRpbXMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0JpYXMgbXVzdCBiZSAxRCcpO1xuICAgIH1cbiAgICBpZiAoYmlhcy5kaW1zW2JpYXMuZGltcy5sZW5ndGggLSAxXSAhPT0gaGlkZGVuU2l6ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCaWFzIG11c3QgaGF2ZSB0aGUgc2FtZSBoaWRkZW4gc2l6ZSBhcyBpbnB1dCcpO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgY3JlYXRlU2tpcExheWVyTm9ybVByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogU2tpcExheWVyTm9ybUF0dHJpYnV0ZXMsXG4gIG91dHB1dENvdW50OiBudW1iZXIsXG4gIGlzVHJhaW5pbmc6IGJvb2xlYW4sXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IHNpbXBsaWZpZWQgPSBhdHRyaWJ1dGVzLnNpbXBsaWZpZWQ7XG5cbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBpbnB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShpbnB1dFNoYXBlKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlO1xuICBjb25zdCBvdXRwdXRTaXplID0gaW5wdXRTaXplO1xuICBjb25zdCBoaWRkZW5TaXplID0gaW5wdXRTaGFwZS5zbGljZSgtMSlbMF07XG4gIGNvbnN0IG1lYW5JbnZTdGREZXZEaW0gPSBpc1RyYWluaW5nID8gaW5wdXRTaGFwZS5zbGljZSgwLCAtMSkuY29uY2F0KDEpIDogW107XG4gIGNvbnN0IGhhc0JldGFJbnB1dCA9ICFzaW1wbGlmaWVkICYmIGlucHV0cy5sZW5ndGggPiAzO1xuICBjb25zdCBoYXNCaWFzSW5wdXQgPSBpbnB1dHMubGVuZ3RoID4gNDtcbiAgY29uc3QgaGFzTWVhbk91dHB1dCA9IGlzVHJhaW5pbmcgJiYgb3V0cHV0Q291bnQgPiAxO1xuICBjb25zdCBoYXNJbnZTdGREZXZPdXRwdXQgPSBpc1RyYWluaW5nICYmIG91dHB1dENvdW50ID4gMjtcbiAgY29uc3QgaGFzSW5wdXRTa2lwQmlhc1N1bU91dHB1dCA9IG91dHB1dENvdW50ID4gMztcbiAgY29uc3Qgd29ya2dyb3VwU2l6ZSA9IDY0O1xuXG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKGhpZGRlblNpemUpO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBjb21wb25lbnRzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGhpZGRlblNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhdHRyaWJ1dGVzLmVwc2lsb24gfSxcbiAgXTtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgdW5pZm9ybXNBcnJheTogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdjb21wb25lbnRzJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2hpZGRlbl9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2Vwc2lsb24nLCB0eXBlOiAnZjMyJyB9LFxuICAgIF07XG4gICAgY29uc3QgdmFyaWFibGVzID0gW1xuICAgICAgaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMsIGNvbXBvbmVudHMpLFxuICAgICAgaW5wdXRWYXJpYWJsZSgnc2tpcCcsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMsIGNvbXBvbmVudHMpLFxuICAgICAgaW5wdXRWYXJpYWJsZSgnZ2FtbWEnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLCBjb21wb25lbnRzKSxcbiAgICBdO1xuICAgIGlmIChoYXNCZXRhSW5wdXQpIHtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKGlucHV0VmFyaWFibGUoJ2JldGEnLCBpbnB1dHNbM10uZGF0YVR5cGUsIGlucHV0c1szXS5kaW1zLCBjb21wb25lbnRzKSk7XG4gICAgfVxuICAgIGlmIChoYXNCaWFzSW5wdXQpIHtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKGlucHV0VmFyaWFibGUoJ2JpYXMnLCBpbnB1dHNbNF0uZGF0YVR5cGUsIGlucHV0c1s0XS5kaW1zLCBjb21wb25lbnRzKSk7XG4gICAgfVxuICAgIHZhcmlhYmxlcy5wdXNoKG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLCBjb21wb25lbnRzKSk7XG4gICAgaWYgKGhhc01lYW5PdXRwdXQpIHtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKG91dHB1dFZhcmlhYmxlKCdtZWFuX291dHB1dCcsIERhdGFUeXBlLmZsb2F0LCBtZWFuSW52U3RkRGV2RGltKSk7XG4gICAgfVxuICAgIGlmIChoYXNJbnZTdGREZXZPdXRwdXQpIHtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKG91dHB1dFZhcmlhYmxlKCdpbnZfc3RkX291dHB1dCcsIERhdGFUeXBlLmZsb2F0LCBtZWFuSW52U3RkRGV2RGltKSk7XG4gICAgfVxuICAgIGlmIChoYXNJbnB1dFNraXBCaWFzU3VtT3V0cHV0KSB7XG4gICAgICB2YXJpYWJsZXMucHVzaChvdXRwdXRWYXJpYWJsZSgnaW5wdXRfc2tpcF9iaWFzX3N1bScsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUsIGNvbXBvbmVudHMpKTtcbiAgICB9XG4gICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgICBjb25zdCB2ZWNEYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShEYXRhVHlwZS5mbG9hdCwgY29tcG9uZW50cyk7XG4gICAgcmV0dXJuIGBcblxuICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3Jtc0FycmF5KS5kZWNsYXJlVmFyaWFibGVzKC4uLnZhcmlhYmxlcyl9XG4gICAgICB2YXI8d29ya2dyb3VwPiBzdW1fc2hhcmVkIDogYXJyYXk8JHt2ZWNEYXRhVHlwZX0sICR7d29ya2dyb3VwU2l6ZX0+O1xuICAgICAgdmFyPHdvcmtncm91cD4gc3VtX3NxdWFyZWRfc2hhcmVkIDogYXJyYXk8JHt2ZWNEYXRhVHlwZX0sICR7d29ya2dyb3VwU2l6ZX0+O1xuXG4gICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoW3dvcmtncm91cFNpemUsIDEsIDFdKX1cbiAgICAgICAgbGV0IGl4ID0gbG9jYWxfaWQueDtcbiAgICAgICAgbGV0IGl5ID0gZ2xvYmFsX2lkLnggLyAke3dvcmtncm91cFNpemV9O1xuXG4gICAgICAgIGxldCBoaWRkZW5fc2l6ZV92ZWN0b3JpemVkOiB1MzIgPSB1bmlmb3Jtcy5oaWRkZW5fc2l6ZSAvIHVuaWZvcm1zLmNvbXBvbmVudHM7XG4gICAgICAgIHZhciBzdHJpZGUgPSBoaWRkZW5fc2l6ZV92ZWN0b3JpemVkIC8gJHt3b3JrZ3JvdXBTaXplfTtcbiAgICAgICAgbGV0IG9mZnNldCA9IGl4ICogc3RyaWRlICsgaXkgKiBoaWRkZW5fc2l6ZV92ZWN0b3JpemVkO1xuICAgICAgICBsZXQgb2Zmc2V0MWQgPSBzdHJpZGUgKiBpeDtcbiAgICAgICAgaWYgKGl4ID09ICR7d29ya2dyb3VwU2l6ZSAtIDF9KSB7XG4gICAgICAgICAgc3RyaWRlID0gaGlkZGVuX3NpemVfdmVjdG9yaXplZCAtIHN0cmlkZSAqIGl4O1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCBzdHJpZGU7IGkrKykge1xuICAgICAgICAgIGxldCBza2lwX3ZhbHVlID0gc2tpcFtvZmZzZXQgKyBpXTtcbiAgICAgICAgICBsZXQgYmlhc192YWx1ZSA9ICR7aGFzQmlhc0lucHV0ID8gJ2JpYXNbb2Zmc2V0MWQgKyBpXScgOiBkYXRhVHlwZSArICcoMC4wKSd9O1xuICAgICAgICAgIGxldCBpbnB1dF92YWx1ZSA9IHhbb2Zmc2V0ICsgaV07XG4gICAgICAgICAgbGV0IHZhbHVlID0gaW5wdXRfdmFsdWUgKyBza2lwX3ZhbHVlICsgYmlhc192YWx1ZTtcbiAgICAgICAgICAke2hhc0lucHV0U2tpcEJpYXNTdW1PdXRwdXQgPyAnaW5wdXRfc2tpcF9iaWFzX3N1bVtvZmZzZXQgKyBpXSA9IHZhbHVlOycgOiAnJ31cbiAgICAgICAgICBvdXRwdXRbb2Zmc2V0ICsgaV0gPSB2YWx1ZTtcbiAgICAgICAgICBsZXQgZjMyX3ZhbHVlID0gJHtjYXN0VG9GMzIoZGF0YVR5cGUsIGNvbXBvbmVudHMsICd2YWx1ZScpfTtcbiAgICAgICAgICBzdW1fc2hhcmVkW2l4XSArPSBmMzJfdmFsdWU7XG4gICAgICAgICAgc3VtX3NxdWFyZWRfc2hhcmVkW2l4XSArPSBmMzJfdmFsdWUgKiBmMzJfdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgICAgIHZhciByZWR1Y2Vfc2l6ZSA6IHUzMiA9ICR7d29ya2dyb3VwU2l6ZX07XG4gICAgICAgIGZvciAodmFyIGN1cnJfc2l6ZSA9IHJlZHVjZV9zaXplID4+IDE7ICBjdXJyX3NpemUgPiAwOyBjdXJyX3NpemUgPSByZWR1Y2Vfc2l6ZSA+PiAxKSB7XG4gICAgICAgICAgcmVkdWNlX3NpemUgPSBjdXJyX3NpemUgKyAocmVkdWNlX3NpemUgJiAxKTtcbiAgICAgICAgICBpZiAoaXggPCBjdXJyX3NpemUpIHtcbiAgICAgICAgICAgIHN1bV9zaGFyZWRbaXhdICs9IHN1bV9zaGFyZWRbaXggKyByZWR1Y2Vfc2l6ZV07XG4gICAgICAgICAgICBzdW1fc3F1YXJlZF9zaGFyZWRbaXhdICs9IHN1bV9zcXVhcmVkX3NoYXJlZFtpeCArIHJlZHVjZV9zaXplXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHN1bSA9IHN1bV9zaGFyZWRbMF07XG4gICAgICAgIGxldCBzcXVhcmVfc3VtID0gc3VtX3NxdWFyZWRfc2hhcmVkWzBdO1xuICAgICAgICBsZXQgbWVhbiA9ICR7c3VtVmVjdG9yKCdzdW0nLCBjb21wb25lbnRzKX0gLyBmMzIodW5pZm9ybXMuaGlkZGVuX3NpemUpO1xuICAgICAgICBsZXQgaW52X3N0ZF9kZXYgPSBpbnZlcnNlU3FydCgke3N1bVZlY3Rvcignc3F1YXJlX3N1bScsIGNvbXBvbmVudHMpfSAvIGYzMih1bmlmb3Jtcy5oaWRkZW5fc2l6ZSkgJHtcbiAgICAgICAgICBzaW1wbGlmaWVkID8gJycgOiAnLSBtZWFuICogbWVhbidcbiAgICAgICAgfSArIHVuaWZvcm1zLmVwc2lsb24pO1xuICAgICAgICAke2hhc01lYW5PdXRwdXQgPyAnbWVhbl9vdXRwdXRbZ2xvYmFsX2lkeF0gPSBtZWFuOycgOiAnJ31cbiAgICAgICAgJHtoYXNJbnZTdGREZXZPdXRwdXQgPyAnaW52X3N0ZF9vdXRwdXRbZ2xvYmFsX2lkeF0gPSBpbnZfc3RkX2RldjsnIDogJyd9XG5cbiAgICAgICAgZm9yICh2YXIgaTogdTMyID0gMDsgaSA8IHN0cmlkZTsgaSsrKSB7XG4gICAgICAgICAgb3V0cHV0W29mZnNldCArIGldID0gKG91dHB1dFtvZmZzZXQgKyBpXSAke3NpbXBsaWZpZWQgPyAnJyA6IGAtICR7ZGF0YVR5cGV9KG1lYW4pYH0pICpcbiAgICAgICAgICAgICR7ZGF0YVR5cGV9KGludl9zdGRfZGV2KSAqIGdhbW1hW29mZnNldDFkICsgaV1cbiAgICAgICAgICAgICR7aGFzQmV0YUlucHV0ID8gJysgYmV0YVtvZmZzZXQxZCArIGldJyA6ICcnfTtcbiAgICAgICAgfVxuICAgICAgfWA7XG4gIH07XG4gIGNvbnN0IG91dHB1dHMgPSBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XTtcbiAgaWYgKG91dHB1dENvdW50ID4gMSkge1xuICAgIG91dHB1dHMucHVzaCh7IGRpbXM6IG1lYW5JbnZTdGREZXZEaW0sIGRhdGFUeXBlOiBEYXRhVHlwZS5mbG9hdCB9KTtcbiAgfVxuICBpZiAob3V0cHV0Q291bnQgPiAyKSB7XG4gICAgb3V0cHV0cy5wdXNoKHsgZGltczogbWVhbkludlN0ZERldkRpbSwgZGF0YVR5cGU6IERhdGFUeXBlLmZsb2F0IH0pO1xuICB9XG4gIGlmIChvdXRwdXRDb3VudCA+IDMpIHtcbiAgICBvdXRwdXRzLnB1c2goeyBkaW1zOiBpbnB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH0pO1xuICB9XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1NraXBMYXllck5vcm1hbGl6YXRpb24nLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHtjb21wb25lbnRzfTske2hhc01lYW5PdXRwdXR9OyR7aGFzSW52U3RkRGV2T3V0cHV0fTske2hhc0lucHV0U2tpcEJpYXNTdW1PdXRwdXR9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBpbnB1dHMubWFwKChfaW5wdXQsIF9pbmRleCkgPT4gJ3R5cGUnKSxcbiAgICB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0cyxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHtcbiAgICAgICAgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyBoaWRkZW5TaXplKSxcbiAgICAgIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3Qgc2tpcExheWVyTm9ybSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogU2tpcExheWVyTm9ybUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgLy8gVE9ETzogaW5pdGlhbGl6ZSBpc1RyYWluaW5nIGZyb20gQ29tcHV0ZUNvbnRleHRcbiAgY29uc3QgaXNUcmFpbmluZyA9IGZhbHNlO1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIC8vIE1lYW4gYW5kIEludlN0ZERldiBhcmUgb25seSB1c2VkIGluIHRyYWluaW5nIG1vZGUgYW5kIGFyZSBub3QgcmVxdWlyZWQgZm9yIGluZmVyZW5jZS5cbiAgLy8gVGhleSBhcmUgYWRkZWQgaGVyZSBmb3IgY29tcGxldGVuZXNzIG9ubHkuXG4gIGNvbnN0IG91dHB1dHMgPSBbMF07XG4gIGlmIChjb250ZXh0Lm91dHB1dENvdW50ID4gMSkge1xuICAgIG91dHB1dHMucHVzaChpc1RyYWluaW5nID8gMSA6IC0zKTtcbiAgfVxuICBpZiAoY29udGV4dC5vdXRwdXRDb3VudCA+IDIpIHtcbiAgICBvdXRwdXRzLnB1c2goaXNUcmFpbmluZyA/IDIgOiAtMyk7XG4gIH1cbiAgaWYgKGNvbnRleHQub3V0cHV0Q291bnQgPiAzKSB7XG4gICAgb3V0cHV0cy5wdXNoKDMpO1xuICB9XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVTa2lwTGF5ZXJOb3JtUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMsIGNvbnRleHQub3V0cHV0Q291bnQsIGlzVHJhaW5pbmcpLCB7XG4gICAgb3V0cHV0cyxcbiAgfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0sIFRlbnNvckluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRFbGVtZW50QXQsXG4gIEluZGljZXNIZWxwZXIsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2xpY2VBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgc3RhcnRzOiBudW1iZXJbXTtcbiAgcmVhZG9ubHkgZW5kczogbnVtYmVyW107XG4gIHJlYWRvbmx5IGF4ZXM6IG51bWJlcltdO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogU2xpY2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd0b28gZmV3IGlucHV0cycpO1xuICB9XG4gIGlmIChhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoICE9PSAwKSB7XG4gICAgaWYgKGF0dHJpYnV0ZXMuYXhlcy5sZW5ndGggIT09IGF0dHJpYnV0ZXMuc3RhcnRzLmxlbmd0aCB8fCBhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoICE9PSBhdHRyaWJ1dGVzLmVuZHMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F4ZXMsIHN0YXJ0cyBhbmQgZW5kcyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoJyk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMuc3RhcnRzLmxlbmd0aCAhPT0gYXR0cmlidXRlcy5lbmRzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc3RhcnRzIGFuZCBlbmRzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGgnKTtcbiAgfVxuICBpbnB1dHMuc2xpY2UoMSkuZm9yRWFjaCgoXywgaWR4KSA9PiB7XG4gICAgaWYgKGlucHV0c1tpZHggKyAxXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuaW50MzIgJiYgaW5wdXRzW2lkeCArIDFdLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5pbnQ2NCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnB1dCAke2lkeH0gbXVzdCBiZSBhbiBhcnJheSBvZiBpbnQzMiBvciBpbnQ2NGApO1xuICAgIH1cbiAgfSk7XG59O1xuXG5jb25zdCByZWFkSW5wdXQgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGlkeDogbnVtYmVyKTogbnVtYmVyW10gPT4ge1xuICBjb25zdCBpbnB1dDogbnVtYmVyW10gPSBbXTtcbiAgaWYgKGlucHV0cy5sZW5ndGggPiBpZHgpIHtcbiAgICBpZiAoaW5wdXRzW2lkeF0uZGF0YVR5cGUgPT09IERhdGFUeXBlLmludDY0KSB7XG4gICAgICBpbnB1dHNbaWR4XS5nZXRCaWdJbnQ2NEFycmF5KCkuZm9yRWFjaCgodikgPT4gaW5wdXQucHVzaChOdW1iZXIodikpKTtcbiAgICB9IGVsc2UgaWYgKGlucHV0c1tpZHhdLmRhdGFUeXBlID09PSBEYXRhVHlwZS5pbnQzMikge1xuICAgICAgaW5wdXRzW2lkeF0uZ2V0SW50MzJBcnJheSgpLmZvckVhY2goKHYpID0+IGlucHV0LnB1c2goTnVtYmVyKHYpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgJHtpZHh9IG11c3QgYmUgYW4gYXJyYXkgb2YgaW50MzIgb3IgaW50NjRgKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGlucHV0O1xufTtcblxuY29uc3QgY3JlYXRlU2xpY2VBdHRyaWJ1dGVzRnJvbUlucHV0cyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IFNsaWNlQXR0cmlidXRlcyxcbik6IFNsaWNlQXR0cmlidXRlcyA9PiB7XG4gIGlmIChpbnB1dHMubGVuZ3RoID4gMSkge1xuICAgIGNvbnN0IHN0YXJ0czogbnVtYmVyW10gPSByZWFkSW5wdXQoaW5wdXRzLCAxKTtcbiAgICBjb25zdCBlbmRzOiBudW1iZXJbXSA9IHJlYWRJbnB1dChpbnB1dHMsIDIpO1xuICAgIGxldCBheGVzOiBudW1iZXJbXSA9IHJlYWRJbnB1dChpbnB1dHMsIDMpO1xuICAgIGlmIChheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYXhlcyA9IFsuLi5BcnJheShpbnB1dHNbMF0uZGltcy5sZW5ndGgpLmtleXMoKV07XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBzdGFydHMsIGVuZHMsIGF4ZXMgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZXM7XG4gIH1cbn07XG5cbmNvbnN0IGZpeFN0YXJ0RW5kVmFsdWVzID0gKFxuICB2YWx1ZTogbnVtYmVyLFxuICBpbmRleDogbnVtYmVyLFxuICBpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgYXhlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHN0ZXBzOiByZWFkb25seSBudW1iZXJbXSxcbik6IG51bWJlciA9PiB7XG4gIGxldCBuZXdWYWx1ZSA9IHZhbHVlO1xuICBpZiAodmFsdWUgPCAwKSB7XG4gICAgbmV3VmFsdWUgKz0gaW5wdXRTaGFwZVtheGVzW2luZGV4XV07XG4gIH1cbiAgaWYgKHN0ZXBzW2luZGV4XSA8IDApIHtcbiAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4obmV3VmFsdWUsIGlucHV0U2hhcGVbYXhlc1tpbmRleF1dIC0gMSkpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBNYXRoLm1heCgwLCBNYXRoLm1pbihuZXdWYWx1ZSwgaW5wdXRTaGFwZVtheGVzW2luZGV4XV0pKTtcbiAgfVxufTtcblxuY29uc3QgY2FsY3VsYXRlSW5wdXRJbmRpY2VzSW1wbCA9IChcbiAgaW5wdXQ6IEluZGljZXNIZWxwZXIsXG4gIG91dHB1dDogSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4pOiBzdHJpbmcgPT5cbiAgYGZuIGNhbGN1bGF0ZUlucHV0SW5kaWNlcyhvdXRwdXRfaW5kaWNlczogJHtvdXRwdXQudHlwZS5pbmRpY2VzfSkgLT4gJHtpbnB1dC50eXBlLmluZGljZXN9IHtcbiAgICAgICAgICB2YXIgaW5wdXRfaW5kaWNlczogJHtpbnB1dC50eXBlLmluZGljZXN9O1xuICAgICAgICAgIHZhciBjYXJyeSA9IDB1O1xuICAgICAgICAgIGZvciAodmFyIGkgPSAke2lucHV0U2hhcGUubGVuZ3RoIC0gMX07IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBsZXQgaW5wdXRfc2hhcGVfaSA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5pbnB1dF9zaGFwZScsICdpJywgaW5wdXRTaGFwZS5sZW5ndGgpfTtcbiAgICAgICAgICAgIGxldCBzdGVwc19pID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnN0ZXBzJywgJ2knLCBpbnB1dFNoYXBlLmxlbmd0aCl9O1xuICAgICAgICAgICAgbGV0IHNpZ25zX2kgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMuc2lnbnMnLCAnaScsIGlucHV0U2hhcGUubGVuZ3RoKX07XG4gICAgICAgICAgICBsZXQgc3RhcnRzX2kgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMuc3RhcnRzJywgJ2knLCBpbnB1dFNoYXBlLmxlbmd0aCl9O1xuICAgICAgICAgICAgdmFyIG91dHB1dF9pbmRleCA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dF9pbmRpY2VzJywgJ2knKX07XG4gICAgICAgICAgICB2YXIgaW5wdXRfaW5kZXggPSBvdXRwdXRfaW5kZXggKiBzdGVwc19pICsgc3RhcnRzX2kgKyBjYXJyeTtcbiAgICAgICAgICAgIGNhcnJ5ID0gaW5wdXRfaW5kZXggLyBpbnB1dF9zaGFwZV9pO1xuICAgICAgICAgICAgaW5wdXRfaW5kZXggPSBpbnB1dF9pbmRleCAlIGlucHV0X3NoYXBlX2k7XG4gICAgICAgICAgICBpZiAoc2lnbnNfaSA8IDApIHtcbiAgICAgICAgICAgICAgaW5wdXRfaW5kZXggPSBpbnB1dF9zaGFwZV9pIC0gaW5wdXRfaW5kZXggLSAxdSArIHN0YXJ0c19pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgJ2knLCAnaW5wdXRfaW5kZXgnKX07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBpbnB1dF9pbmRpY2VzO1xuICAgICAgfWA7XG5cbmNvbnN0IGNyZWF0ZVNsaWNlUHJvZ3JhbUluZm8gPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IFNsaWNlQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBpbnB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShpbnB1dFNoYXBlKTtcbiAgY29uc3QgYXhlcyA9XG4gICAgYXR0cmlidXRlcy5heGVzLmxlbmd0aCA+IDBcbiAgICAgID8gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4ZXMoYXR0cmlidXRlcy5heGVzLCBpbnB1dFNoYXBlLmxlbmd0aClcbiAgICAgIDogWy4uLkFycmF5KGlucHV0U2hhcGUubGVuZ3RoKS5rZXlzKCldO1xuICBsZXQgc3RlcHMgPSByZWFkSW5wdXQoaW5wdXRzLCA0KTtcbiAgc3RlcHMuZm9yRWFjaChcbiAgICAoc3RlcCkgPT5cbiAgICAgIHN0ZXAgIT09IDAgfHxcbiAgICAgICgoKSA9PiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignc3RlcCBjYW5ub3QgYmUgMCcpO1xuICAgICAgfSksXG4gICk7XG4gIGlmIChzdGVwcy5sZW5ndGggPT09IDApIHtcbiAgICBzdGVwcyA9IEFycmF5KGF4ZXMubGVuZ3RoKS5maWxsKDEpO1xuICB9XG4gIGNvbnN0IHN0YXJ0cyA9IGF0dHJpYnV0ZXMuc3RhcnRzLm1hcCgoc3RhcnQsIGkpID0+IGZpeFN0YXJ0RW5kVmFsdWVzKHN0YXJ0LCBpLCBpbnB1dFNoYXBlLCBheGVzLCBzdGVwcykpO1xuXG4gIGNvbnN0IGVuZHMgPSBhdHRyaWJ1dGVzLmVuZHMubWFwKChlbmQsIGkpID0+IGZpeFN0YXJ0RW5kVmFsdWVzKGVuZCwgaSwgaW5wdXRTaGFwZSwgYXhlcywgc3RlcHMpKTtcblxuICBpZiAoYXhlcy5sZW5ndGggIT09IHN0YXJ0cy5sZW5ndGggfHwgYXhlcy5sZW5ndGggIT09IGVuZHMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzdGFydCwgZW5kcyBhbmQgYXhlcyBzaG91bGQgaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2YgZWxlbWVudHMnKTtcbiAgfVxuXG4gIGlmIChheGVzLmxlbmd0aCAhPT0gaW5wdXRTaGFwZS5sZW5ndGgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0U2hhcGUubGVuZ3RoOyArK2kpIHtcbiAgICAgIGlmICghYXhlcy5pbmNsdWRlcyhpKSkge1xuICAgICAgICBzdGFydHMuc3BsaWNlKGksIDAsIDApO1xuICAgICAgICBlbmRzLnNwbGljZShpLCAwLCBpbnB1dFNoYXBlW2ldKTtcbiAgICAgICAgc3RlcHMuc3BsaWNlKGksIDAsIDEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBjb25zdCBzaWducyA9IHN0ZXBzLm1hcCgoc3RlcCkgPT4gTWF0aC5zaWduKHN0ZXApKTtcbiAgLy8gQ29udmVydCBuZWdhdGl2ZSBzdGVwcyB0byBwb3NpdGl2ZSBzdGVwcyBhbmQgcmV2ZXJzZSBzdGFydHMgYW5kIGVuZHNcbiAgc3RlcHMuZm9yRWFjaCgoc3RlcCwgaSwgYXJyYXkpID0+IHtcbiAgICBpZiAoc3RlcCA8IDApIHtcbiAgICAgIGNvbnN0IG51bVN0ZXBzID0gKGVuZHNbaV0gLSBzdGFydHNbaV0pIC8gc3RlcDtcbiAgICAgIGNvbnN0IG5ld0VuZCA9IHN0YXJ0c1tpXTtcbiAgICAgIGNvbnN0IG5ld1N0YXJ0ID0gbmV3RW5kICsgbnVtU3RlcHMgKiBzdGVwc1tpXTtcbiAgICAgIHN0YXJ0c1tpXSA9IG5ld1N0YXJ0O1xuICAgICAgZW5kc1tpXSA9IG5ld0VuZDtcbiAgICAgIGFycmF5W2ldID0gLXN0ZXA7XG4gICAgfVxuICB9KTtcbiAgLy8gT3V0cHV0IHJhbmsgaXMgZXhwZWN0ZWQgdG8gYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBpbnB1dCByYW5rLlxuICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoMCk7XG4gIGF4ZXMuZm9yRWFjaCgoYXhpcywgXykgPT4ge1xuICAgIG91dHB1dFNoYXBlW2F4aXNdID0gTWF0aC5jZWlsKChlbmRzW2F4aXNdIC0gc3RhcnRzW2F4aXNdKSAvIHN0ZXBzW2F4aXNdKTtcbiAgfSk7XG4gIGNvbnN0IG91dHB1dFRlbnNvckluZm86IFRlbnNvckluZm8gPSB7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH07XG5cbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgIHsgbmFtZTogJ291dHB1dFNpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgIHsgbmFtZTogJ3N0YXJ0cycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IHN0YXJ0cy5sZW5ndGggfSxcbiAgICB7IG5hbWU6ICdzaWducycsIHR5cGU6ICdpMzInLCBsZW5ndGg6IHNpZ25zLmxlbmd0aCB9LFxuICAgIHsgbmFtZTogJ3N0ZXBzJywgdHlwZTogJ3UzMicsIGxlbmd0aDogc3RlcHMubGVuZ3RoIH0sXG4gIF07XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHN0YXJ0cyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IHNpZ25zIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHN0ZXBzIH0sXG4gICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzBdLmRpbXMsIG91dHB1dFNoYXBlKSxcbiAgXTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG4gICAgICAgICR7Y2FsY3VsYXRlSW5wdXRJbmRpY2VzSW1wbChpbnB1dCwgb3V0cHV0LCBpbnB1dFNoYXBlKX1cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0U2l6ZScpfVxuICAgICAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgICAgICBsZXQgaW5wdXRfaW5kaWNlcyA9IGNhbGN1bGF0ZUlucHV0SW5kaWNlcyhvdXRwdXRfaW5kaWNlcyk7XG4gICAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCBpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKSl9XG4gICAgICB9YDtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnU2xpY2UnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke3NpZ25zLmxlbmd0aH1fJHtzdGFydHMubGVuZ3RofV8ke3N0ZXBzLmxlbmd0aH1gLCBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJ10gfSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFtvdXRwdXRUZW5zb3JJbmZvXSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKGlucHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHNsaWNlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBTbGljZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBjb25zdCB1cGRhdGVkQXR0cmlidXRlcyA9IGNyZWF0ZVNsaWNlQXR0cmlidXRlc0Zyb21JbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlU2xpY2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgdXBkYXRlZEF0dHJpYnV0ZXMpLCB7IGlucHV0czogWzBdIH0pO1xuICAvLyBpZiAoU2hhcGVVdGlsLnNpemUocHJvZ3JhbS5vdXRwdXRzWzBdLmRpbXMpID4gMCkge1xuICAvLyAgIGNvbnRleHQuY29tcHV0ZShwcm9ncmFtSW5mb0xvYWRlciwge2lucHV0czogWzBdfSk7XG4gIC8vIH0gZWxzZSB7XG4gIC8vICAgLy8gVE9ETzogc3VwcG9ydCBlbXB0eSBvdXRwdXRcbiAgLy8gICB0aHJvdyBuZXcgRXJyb3IoJ3NsaWNlOiBvdXRwdXQgc2l6ZSBpcyAwJyk7XG4gIC8vIH1cbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZVNsaWNlQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFNsaWNlQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IHN0YXJ0cyA9IGF0dHJpYnV0ZXMuc3RhcnRzIGFzIG51bWJlcltdO1xuICBjb25zdCBlbmRzID0gYXR0cmlidXRlcy5lbmRzIGFzIG51bWJlcltdO1xuICBjb25zdCBheGVzID0gYXR0cmlidXRlcy5heGVzIGFzIG51bWJlcltdO1xuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgc3RhcnRzLCBlbmRzLCBheGVzIH0pO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLy8gVE9ETzogdGhpcyBpcyB0aGUgc2FtZSBuYWl2ZSBpbXBsZW1lbnRhdGlvbiB3ZSB1c2UgZm9yIHJlZHVjZSB0aGF0IGhhc1xuLy8gcGVyZm9ybWFuY2UgbGltaXRhdGlvbnMgd2hlbiB0aGUgcmVkdWNlZCBheGlzIGlzIGxvbmcuIE5lZWQgdG8gYWRkXG4vLyBhIG9wdGltaXplZCBjb2RlcGF0aCBmb3IgdGhpcy5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCB9IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvIH0gZnJvbSAnLi90cmFuc3Bvc2UnO1xuXG5pbXBvcnQge1xuICBnZXRNYXhDb21wb25lbnRzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICBzdW1WZWN0b3IsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTb2Z0bWF4IG9wIHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgU29mdG1heEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBheGlzOiBudW1iZXI7XG59XG5cbmNvbnN0IGNyZWF0ZVNvZnRtYXhQcm9ncmFtSW5mbyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogU29mdG1heEF0dHJpYnV0ZXMpID0+IHtcbiAgY29uc3QgaW5wdXQgPSBjb250ZXh0LmlucHV0c1swXTtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0LmRpbXM7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShpbnB1dFNoYXBlKTtcbiAgY29uc3QgaW5wdXRSYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG4gIGNvbnN0IGF4aXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhpcyhhdHRyaWJ1dGVzLmF4aXMsIGlucHV0UmFuayk7XG4gIGNvbnN0IGlzVHJhbnNwb3NlUmVxdWlyZWQgPSBheGlzIDwgaW5wdXRTaGFwZS5sZW5ndGggLSAxO1xuICBsZXQgdHJhbnNwb3NlZElucHV0OiBUZW5zb3JWaWV3O1xuICBsZXQgcGVybTogbnVtYmVyW10gPSBbXTtcblxuICBpZiAoaXNUcmFuc3Bvc2VSZXF1aXJlZCkge1xuICAgIHBlcm0gPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiBpbnB1dFJhbmsgfSwgKF8sIGkpID0+IGkpO1xuICAgIHBlcm1bYXhpc10gPSBpbnB1dFJhbmsgLSAxO1xuICAgIHBlcm1baW5wdXRSYW5rIC0gMV0gPSBheGlzO1xuXG4gICAgdHJhbnNwb3NlZElucHV0ID0gY29udGV4dC5jb21wdXRlKGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKGlucHV0LCBwZXJtKSwge1xuICAgICAgaW5wdXRzOiBbaW5wdXRdLFxuICAgICAgb3V0cHV0czogWy0xXSxcbiAgICB9KVswXTtcbiAgfSBlbHNlIHtcbiAgICB0cmFuc3Bvc2VkSW5wdXQgPSBpbnB1dDtcbiAgfVxuXG4gIGNvbnN0IHRyYW5zcG9zZWRJbnB1dFNoYXBlID0gdHJhbnNwb3NlZElucHV0LmRpbXM7XG4gIGNvbnN0IGNvbHMgPSB0cmFuc3Bvc2VkSW5wdXRTaGFwZVtpbnB1dFJhbmsgLSAxXTtcbiAgY29uc3Qgcm93cyA9IG91dHB1dFNpemUgLyBjb2xzO1xuICBjb25zdCBjb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhjb2xzKTtcbiAgY29uc3QgcGFja2VkQ29scyA9IGNvbHMgLyBjb21wb25lbnRzO1xuICBsZXQgV0cgPSA2NDtcbiAgLy8gSWYgb25seSBvbmUgd29ya2dyb3VwIGlzIGRpc3BhdGNoZWQsIGluY3JlYXNlIHdvcmtncm91cFNpemUgdG8gaW1wcm92ZSBwYXJhbGxlbGlzbS5cbiAgaWYgKHJvd3MgPT09IDEpIHtcbiAgICBXRyA9IDI1NjtcbiAgfVxuICBjb25zdCBtYXhWZWN0b3IgPSAobmFtZTogc3RyaW5nLCBjb21wb25lbnRzOiBudW1iZXIpID0+IHtcbiAgICBpZiAoY29tcG9uZW50cyA9PT0gNCkge1xuICAgICAgcmV0dXJuIGBtYXgobWF4KCR7bmFtZX0ueCwgJHtuYW1lfS55KSwgbWF4KCR7bmFtZX0ueiwgJHtuYW1lfS53KSlgO1xuICAgIH0gZWxzZSBpZiAoY29tcG9uZW50cyA9PT0gMikge1xuICAgICAgcmV0dXJuIGBtYXgoJHtuYW1lfS54LCAke25hbWV9LnkpYDtcbiAgICB9IGVsc2UgaWYgKGNvbXBvbmVudHMgPT09IDMpIHtcbiAgICAgIHJldHVybiBgbWF4KG1heCgke25hbWV9LngsICR7bmFtZX0ueSksICR7bmFtZX0ueilgO1xuICAgIH1cblxuICAgIHJldHVybiBuYW1lO1xuICB9O1xuICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZSgneCcsIHRyYW5zcG9zZWRJbnB1dC5kYXRhVHlwZSwgdHJhbnNwb3NlZElucHV0LmRpbXMsIGNvbXBvbmVudHMpO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgncmVzdWx0JywgdHJhbnNwb3NlZElucHV0LmRhdGFUeXBlLCB0cmFuc3Bvc2VkSW5wdXQuZGltcywgY29tcG9uZW50cyk7XG4gIGNvbnN0IHZhbHVlVHlwZSA9IHgudHlwZS52YWx1ZTtcbiAgLy8gNi4yLjQgaW4gd2dzbCBzcGVjXG4gIGNvbnN0IHRocmVhZE1heERlY2wgPVxuICAgIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSh0cmFuc3Bvc2VkSW5wdXQuZGF0YVR5cGUpID09PSAnZjMyJ1xuICAgICAgPyBgdmFyIHRocmVhZE1heCA9ICR7dmFsdWVUeXBlfSgtMy40MDI4MjM0NjYzODUyODg2ZSszOGYpO2BcbiAgICAgIDogYHZhciB0aHJlYWRNYXggPSAke3ZhbHVlVHlwZX0oLTY1NTA0LjBoKTtgO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgICAgIHZhcjx3b3JrZ3JvdXA+IHJvd01heFNoYXJlZCA6ICR7dmFsdWVUeXBlfTtcbiAgICAgIHZhcjx3b3JrZ3JvdXA+IHJvd1N1bVNoYXJlZCA6ICR7dmFsdWVUeXBlfTtcbiAgICAgIHZhcjx3b3JrZ3JvdXA+IHRocmVhZFNoYXJlZCA6IGFycmF5PCR7dmFsdWVUeXBlfSwgJHtXR30+O1xuXG4gICAgICBmbiBnZXRWYWx1ZShyb3c6IGkzMiwgY29sOiBpMzIsIHJvd19zdHJpZGU6IGkzMikgLT4gJHt2YWx1ZVR5cGV9IHtcbiAgICAgICAgbGV0IGluZGV4ID0gcm93ICogcm93X3N0cmlkZSArIGNvbDtcbiAgICAgICAgcmV0dXJuIHhbaW5kZXhdO1xuICAgICAgfVxuXG4gICAgICBmbiBzZXRWYWx1ZShyb3c6IGkzMiwgY29sOiBpMzIsIHJvd19zdHJpZGU6IGkzMiwgdmFsdWU6ICR7dmFsdWVUeXBlfSkge1xuICAgICAgICBsZXQgaW5kZXggPSByb3cgKiByb3dfc3RyaWRlICsgY29sO1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gdmFsdWU7XG4gICAgICB9XG4gICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ3BhY2tlZENvbHMnLCAnaTMyJykuZGVjbGFyZVZhcmlhYmxlcyh4LCBvdXRwdXQpfVxuICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFdHKX1cbiAgICAgICAgbGV0IGdpbmRleCA9IGkzMihnbG9iYWxfaWR4KTtcbiAgICAgICAgbGV0IGxpbmRleCA9IGkzMihsb2NhbF9pZHgpO1xuICAgICAgICBjb25zdCB3ZyA9ICR7V0d9O1xuICAgICAgICBsZXQgcm93ID0gZ2luZGV4IC8gd2c7XG4gICAgICAgIGxldCBjb2xzID0gdW5pZm9ybXMucGFja2VkQ29scztcbiAgICAgICAgbGV0IHJvd19zdHJpZGUgOiBpMzIgPSB1bmlmb3Jtcy5wYWNrZWRDb2xzO1xuXG4gICAgICAgIC8vIGZpbmQgdGhlIHJvd3MgbWF4XG4gICAgICAgICR7dGhyZWFkTWF4RGVjbH1cbiAgICAgICAgZm9yICh2YXIgY29sID0gbGluZGV4OyBjb2wgPCBjb2xzOyBjb2wgKz0gd2cpIHtcbiAgICAgICAgICBsZXQgdmFsdWUgPSBnZXRWYWx1ZShyb3csIGNvbCwgcm93X3N0cmlkZSk7XG4gICAgICAgICAgdGhyZWFkTWF4ID0gbWF4KHRocmVhZE1heCwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsaW5kZXggPCBjb2xzKSB7XG4gICAgICAgICAgdGhyZWFkU2hhcmVkW2xpbmRleF0gPSB0aHJlYWRNYXg7XG4gICAgICAgIH1cbiAgICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgICAgIHZhciByZWR1Y2VTaXplID0gbWluKGNvbHMsIHdnKTtcbiAgICAgICAgZm9yICh2YXIgY3VyclNpemUgPSByZWR1Y2VTaXplID4+IDE7ICBjdXJyU2l6ZSA+IDA7IGN1cnJTaXplID0gcmVkdWNlU2l6ZSA+PiAxKSB7XG4gICAgICAgICAgcmVkdWNlU2l6ZSA9IGN1cnJTaXplICsgKHJlZHVjZVNpemUgJiAxKTtcbiAgICAgICAgICBpZiAobGluZGV4IDwgY3VyclNpemUpIHtcbiAgICAgICAgICAgIHRocmVhZFNoYXJlZFtsaW5kZXhdID0gbWF4KHRocmVhZFNoYXJlZFtsaW5kZXhdLCB0aHJlYWRTaGFyZWRbbGluZGV4ICsgcmVkdWNlU2l6ZV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxpbmRleCA9PSAwKSB7XG4gICAgICAgICAgcm93TWF4U2hhcmVkID0gJHt2YWx1ZVR5cGV9KCR7bWF4VmVjdG9yKCd0aHJlYWRTaGFyZWRbMF0nLCBjb21wb25lbnRzKX0pO1xuICAgICAgICB9XG4gICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgICAvLyBmaW5kIHRoZSByb3dzIHN1bVxuICAgICAgICB2YXIgdGhyZWFkU3VtID0gJHt2YWx1ZVR5cGV9KDAuMCk7XG4gICAgICAgIGZvciAodmFyIGNvbCA9IGxpbmRleDsgY29sIDwgY29sczsgY29sICs9IHdnKSB7XG4gICAgICAgICAgbGV0IHN1YkV4cCA9IGV4cChnZXRWYWx1ZShyb3csIGNvbCwgcm93X3N0cmlkZSkgLSByb3dNYXhTaGFyZWQpO1xuICAgICAgICAgIHRocmVhZFN1bSArPSBzdWJFeHA7XG4gICAgICAgIH1cbiAgICAgICAgdGhyZWFkU2hhcmVkW2xpbmRleF0gPSB0aHJlYWRTdW07XG4gICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgICBmb3IgKHZhciBjdXJyU2l6ZSA9IHdnID4+IDE7ICBjdXJyU2l6ZSA+IDA7IGN1cnJTaXplID0gY3VyclNpemUgPj4gMSkge1xuICAgICAgICAgIGlmIChsaW5kZXggPCBjdXJyU2l6ZSkge1xuICAgICAgICAgICAgdGhyZWFkU2hhcmVkW2xpbmRleF0gPSB0aHJlYWRTaGFyZWRbbGluZGV4XSArIHRocmVhZFNoYXJlZFtsaW5kZXggKyBjdXJyU2l6ZV07XG4gICAgICAgICAgfVxuICAgICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGluZGV4ID09IDApIHtcbiAgICAgICAgICByb3dTdW1TaGFyZWQgPSAke3ZhbHVlVHlwZX0oJHtzdW1WZWN0b3IoJ3RocmVhZFNoYXJlZFswXScsIGNvbXBvbmVudHMpfSk7XG4gICAgICAgIH1cbiAgICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgICAgIC8vIGNhbGN1bGF0ZSBmaW5hbCB2YWx1ZSBmb3IgZWFjaCBlbGVtZW50IGluIHRoZSByb3dcbiAgICAgICAgZm9yICh2YXIgY29sID0gbGluZGV4OyBjb2wgPCBjb2xzOyBjb2wgKz0gd2cpIHtcbiAgICAgICAgICB2YXIgdmFsdWUgPSBleHAoZ2V0VmFsdWUocm93LCBjb2wsIHJvd19zdHJpZGUpIC0gcm93TWF4U2hhcmVkKSAvIHJvd1N1bVNoYXJlZDtcbiAgICAgICAgICAvLyBtYXggb3BlcmF0aW9uIHByb3RlY3RzIGFnYWluc3QgTmFOIHNpbmNlIGFsbCB2YWx1ZXMgc2hvdWxkIGJlID49MFxuICAgICAgICAgIHZhbHVlID0gbWF4KHZhbHVlLCAke3ZhbHVlVHlwZX0oMC4wKSk7XG4gICAgICAgICAgc2V0VmFsdWUocm93LCBjb2wsIHJvd19zdHJpZGUsIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfWA7XG4gIGNvbnN0IHJlc3VsdCA9IGNvbnRleHQuY29tcHV0ZShcbiAgICB7XG4gICAgICBuYW1lOiAnU29mdG1heCcsXG4gICAgICAvLyBOb3RlIHRoYXQgaW4gSlNFUCwgV0cgc2l6ZSBpcyBub3QgaW5jbHVkZWQgaW4gY2FjaGUgYnkgZGVmYXVsdCwgYnV0IFdlYkdQVSBFUCBpdCBpcy5cbiAgICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2NvbXBvbmVudHN9OyR7V0d9YCwgaW5wdXREZXBlbmRlbmNpZXM6IFsndHlwZSddIH0sXG4gICAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiB0cmFuc3Bvc2VkSW5wdXRTaGFwZSwgZGF0YVR5cGU6IHRyYW5zcG9zZWRJbnB1dC5kYXRhVHlwZSB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiByb3dzIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtczogW3sgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IHBhY2tlZENvbHMgfV0sXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGlucHV0czogW3RyYW5zcG9zZWRJbnB1dF0sXG4gICAgICBvdXRwdXRzOiBbaXNUcmFuc3Bvc2VSZXF1aXJlZCA/IC0xIDogMF0sXG4gICAgfSxcbiAgKVswXTtcblxuICBpZiAoaXNUcmFuc3Bvc2VSZXF1aXJlZCkge1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhyZXN1bHQsIHBlcm0pLCB7XG4gICAgICBpbnB1dHM6IFtyZXN1bHRdLFxuICAgIH0pO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3Qgc29mdG1heCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogU29mdG1heEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjcmVhdGVTb2Z0bWF4UHJvZ3JhbUluZm8oY29udGV4dCwgYXR0cmlidXRlcyk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VTb2Z0bWF4QXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFNvZnRtYXhBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IGF4aXM6IGF0dHJpYnV0ZXMuYXhpcyBhcyBudW1iZXIgfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgZ2V0UmVwZWF0cyA9IChyZXBlYXRzVGVuc29yVmlldzogVGVuc29yVmlldyk6IHJlYWRvbmx5IG51bWJlcltdID0+XG4gIEFycmF5LmZyb20ocmVwZWF0c1RlbnNvclZpZXcuZ2V0QmlnSW50NjRBcnJheSgpLCBOdW1iZXIpO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaWxlIHJlcXVpcmVzIDIgaW5wdXRzLicpO1xuICB9XG5cbiAgaWYgKFxuICAgIGlucHV0c1swXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQgJiZcbiAgICBpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0MTYgJiZcbiAgICBpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmludDMyICYmXG4gICAgaW5wdXRzWzBdLmRhdGFUeXBlICE9PSBEYXRhVHlwZS51aW50MzJcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaWxlIG9ubHkgc3VwcG9ydCBmbG9hdCwgZmxvYXQxNiwgaW50MzIsIGFuZCB1aW50MzIgZGF0YSB0eXBlcycpO1xuICB9XG5cbiAgaWYgKGlucHV0c1sxXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuaW50NjQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbGUgYHJlcGVhdHNgIGlucHV0IHNob3VsZCBiZSBvZiBpbnQ2NCBkYXRhIHR5cGUnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbGUgYHJlcGVhdHNgIGlucHV0IHNob3VsZCBiZSAxLUQnKTtcbiAgfVxuXG4gIGNvbnN0IHJlcGVhdHM6IHJlYWRvbmx5IG51bWJlcltdID0gZ2V0UmVwZWF0cyhpbnB1dHNbMV0pO1xuXG4gIGlmIChyZXBlYXRzLmxlbmd0aCAhPT0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaWxlIGByZXBlYXRzYCBpbnB1dCBzaG91bGQgaGF2ZSBzYW1lIG51bWJlciBvZiBlbGVtZW50cyBhcyByYW5rIG9mIGlucHV0IGRhdGEgdGVuc29yJyk7XG4gIH1cbn07XG5cbmNvbnN0IGdldE91dHB1dFNoYXBlID0gKGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCByZXBlYXRzOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdID0+IHtcbiAgY29uc3Qgb3V0cHV0U2hhcGU6IG51bWJlcltdID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFNoYXBlLmxlbmd0aDsgKytpKSB7XG4gICAgb3V0cHV0U2hhcGUucHVzaChpbnB1dFNoYXBlW2ldICogcmVwZWF0c1tpXSk7XG4gIH1cblxuICByZXR1cm4gb3V0cHV0U2hhcGU7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVGlsZVByb2dyYW1JbmZvID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBzaGFwZT86IG51bWJlcltdKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IHJlcGVhdHM6IHJlYWRvbmx5IG51bWJlcltdID0gc2hhcGUgPT0gbnVsbCA/IGdldFJlcGVhdHMoaW5wdXRzWzFdKSA6IHNoYXBlO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGdldE91dHB1dFNoYXBlKGlucHV0U2hhcGUsIHJlcGVhdHMpO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuXG4gIGNvbnN0IGRhdGFUeXBlID0gaW5wdXRzWzBdLmRhdGFUeXBlO1xuICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgZGF0YVR5cGUsIGlucHV0U2hhcGUubGVuZ3RoKTtcbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICAgICAgY29uc3QgaW5wdXRTaGFwZSA9ICR7aW5wdXQuaW5kaWNlcyguLi5pbnB1dFNoYXBlKX07XG4gICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dF9zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG4gICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgICBsZXQgb3V0cHV0X2luZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICB2YXIgaW5wdXRfaW5kaWNlczogJHtpbnB1dC50eXBlLmluZGljZXN9O1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAke2lucHV0U2hhcGUubGVuZ3RofTsgaSsrKSB7XG4gICAgICAgIGxldCBpbnB1dF9kaW1faSA9ICR7aW5wdXQuaW5kaWNlc0dldCgndW5pZm9ybXMuaW5wdXRfc2hhcGUnLCAnaScpfTtcbiAgICAgICAgbGV0IGlucHV0X2RpbV92YWx1ZSA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dF9pbmRpY2VzJywgJ2knKX0gICUgaW5wdXRfZGltX2k7XG5cbiAgICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgJ2knLCAnaW5wdXRfZGltX3ZhbHVlJyl9XG4gICAgICB9XG4gICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsIGlucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpKX1cbiAgICB9YDtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdUaWxlJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtyZXBlYXRzfWAsIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgb3V0cHV0U2hhcGUpLFxuICAgICAgXSxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgdGlsZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUaWxlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMpLCB7IGlucHV0czogWzBdIH0pO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgQnJvYWRjYXN0VXRpbCwgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5jb25zdCBjcmVhdGVXaGVyZU9wUHJvZ3JhbVNoYWRlciA9IChcbiAgc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIsXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBkaW1zT3V0cHV0OiByZWFkb25seSBudW1iZXJbXSxcbiAgaXNCcm9hZGNhc3Q6IGJvb2xlYW4sXG4gIHR5cGVPdXRwdXQ6IG51bWJlcixcbikgPT4ge1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0X2RhdGEnLCB0eXBlT3V0cHV0LCBkaW1zT3V0cHV0Lmxlbmd0aCwgNCk7XG4gIGNvbnN0IGEgPSBpbnB1dFZhcmlhYmxlKCdhX2RhdGEnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLmxlbmd0aCwgNCk7XG4gIGNvbnN0IGIgPSBpbnB1dFZhcmlhYmxlKCdiX2RhdGEnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCwgNCk7XG4gIGNvbnN0IGMgPSBpbnB1dFZhcmlhYmxlKCdjX2RhdGEnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLmxlbmd0aCwgNCk7XG5cbiAgbGV0IGFzc2lnbm1lbnQ6IHN0cmluZztcbiAgY29uc3QgZXhwcmVzc2lvbiA9IChhOiBzdHJpbmcsIGI6IHN0cmluZywgYzogc3RyaW5nKSA9PiBgc2VsZWN0KCR7Yn0sICR7YX0sICR7Y30pYDtcbiAgaWYgKCFpc0Jyb2FkY2FzdCkge1xuICAgIGFzc2lnbm1lbnQgPSBvdXRwdXQuc2V0QnlPZmZzZXQoXG4gICAgICAnZ2xvYmFsX2lkeCcsXG4gICAgICBleHByZXNzaW9uKGEuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKSwgYi5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpLCBjLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JykpLFxuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3Qgc2luZ2xlQXNzaWdubWVudCA9IChyZXNTdHI6IHN0cmluZywgeDogbnVtYmVyLCB0eXBlQ2FzdCA9ICcnKSA9PiB7XG4gICAgICBjb25zdCBleHByZXNzaW9uQSA9IGBhX2RhdGFbaW5kZXhfYSR7eH1dW2NvbXBvbmVudF9hJHt4fV1gO1xuICAgICAgY29uc3QgZXhwcmVzc2lvbkIgPSBgYl9kYXRhW2luZGV4X2Ike3h9XVtjb21wb25lbnRfYiR7eH1dYDtcbiAgICAgIGNvbnN0IGV4cHJlc3Npb25DID0gYGJvb2woY19kYXRhW2luZGV4X2Mke3h9XSAmICgweGZmdSA8PCAoY29tcG9uZW50X2Mke3h9ICogOCkpKWA7XG4gICAgICByZXR1cm4gYFxuICAgICAgICAgICAgbGV0IG91dHB1dF9pbmRpY2VzJHt4fSA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgZ2xvYmFsX2lkeCAqIDR1ICsgJHt4fXVgKX07XG4gICAgICAgICAgICBsZXQgb2Zmc2V0X2Eke3h9ID0gJHthLmJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0KGBvdXRwdXRfaW5kaWNlcyR7eH1gLCBvdXRwdXQpfTtcbiAgICAgICAgICAgIGxldCBvZmZzZXRfYiR7eH0gPSAke2IuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoYG91dHB1dF9pbmRpY2VzJHt4fWAsIG91dHB1dCl9O1xuICAgICAgICAgICAgbGV0IG9mZnNldF9jJHt4fSA9ICR7Yy5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldChgb3V0cHV0X2luZGljZXMke3h9YCwgb3V0cHV0KX07XG4gICAgICAgICAgICBsZXQgaW5kZXhfYSR7eH0gPSBvZmZzZXRfYSR7eH0gLyA0dTtcbiAgICAgICAgICAgIGxldCBpbmRleF9iJHt4fSA9IG9mZnNldF9iJHt4fSAvIDR1O1xuICAgICAgICAgICAgbGV0IGluZGV4X2Mke3h9ID0gb2Zmc2V0X2Mke3h9IC8gNHU7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50X2Eke3h9ID0gb2Zmc2V0X2Eke3h9ICUgNHU7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50X2Ike3h9ID0gb2Zmc2V0X2Ike3h9ICUgNHU7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50X2Mke3h9ID0gb2Zmc2V0X2Mke3h9ICUgNHU7XG4gICAgICAgICAgICAke3Jlc1N0cn1bJHt4fV0gPSAke3R5cGVDYXN0fSgke2V4cHJlc3Npb24oZXhwcmVzc2lvbkEsIGV4cHJlc3Npb25CLCBleHByZXNzaW9uQyl9KTtcbiAgICAgICAgICBgO1xuICAgIH07XG4gICAgaWYgKHR5cGVPdXRwdXQgPT09IERhdGFUeXBlLmJvb2wpIHtcbiAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgICAgICB2YXIgZGF0YSA9IHZlYzQ8dTMyPigwKTtcbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDAsICd1MzInKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDEsICd1MzInKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDIsICd1MzInKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDMsICd1MzInKX1cbiAgICAgICAgICAgIG91dHB1dF9kYXRhW2dsb2JhbF9pZHhdID0gZG90KHZlYzQ8dTMyPigweDEsIDB4MTAwLCAweDEwMDAwLCAweDEwMDAwMDApLCB2ZWM0PHUzMj4oZGF0YSkpO2A7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dF9kYXRhW2dsb2JhbF9pZHhdJywgMCl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dF9kYXRhW2dsb2JhbF9pZHhdJywgMSl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dF9kYXRhW2dsb2JhbF9pZHhdJywgMil9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dF9kYXRhW2dsb2JhbF9pZHhdJywgMyl9XG4gICAgICAgICAgYDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYFxuICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ3ZlY19zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoYywgYSwgYiwgb3V0cHV0KX1cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLnZlY19zaXplJyl9XG4gICAgICAgICR7YXNzaWdubWVudH1cbiAgICAgIH1gO1xufTtcblxuY29uc3QgY3JlYXRlV2hlcmVPcFByb2dyYW1JbmZvID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBkaW1zQSA9IGlucHV0c1sxXS5kaW1zO1xuICBjb25zdCBkaW1zQiA9IGlucHV0c1syXS5kaW1zO1xuICBjb25zdCBkaW1zQyA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBvdXRwdXREYXRhVHlwZSA9IGlucHV0c1sxXS5kYXRhVHlwZTtcblxuICBjb25zdCBpc0Jyb2FkY2FzdCA9ICEoU2hhcGVVdGlsLmFyZUVxdWFsKGRpbXNBLCBkaW1zQikgJiYgU2hhcGVVdGlsLmFyZUVxdWFsKGRpbXNCLCBkaW1zQykpO1xuICBsZXQgb3V0cHV0U2hhcGUgPSBkaW1zQTtcbiAgbGV0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShkaW1zQSk7XG4gIC8vIFRPRE86IGRlYWwgd2l0aCB6ZXJvLXNpemVkIHRlbnNvcnMgKGVnLiBkaW1zPVsxLDBdKVxuXG4gIGlmIChpc0Jyb2FkY2FzdCkge1xuICAgIGNvbnN0IGNhbGN1bGF0ZWRTaGFwZSA9IEJyb2FkY2FzdFV0aWwuY2FsY1NoYXBlKEJyb2FkY2FzdFV0aWwuY2FsY1NoYXBlKGRpbXNBLCBkaW1zQiwgZmFsc2UpISwgZGltc0MsIGZhbHNlKTtcbiAgICBpZiAoIWNhbGN1bGF0ZWRTaGFwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgcGVyZm9ybSB3aGVyZSBvcCBvbiB0aGUgZ2l2ZW4gdGVuc29yc1wiKTtcbiAgICB9XG4gICAgb3V0cHV0U2hhcGUgPSBjYWxjdWxhdGVkU2hhcGU7XG4gICAgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgfVxuXG4gIGNvbnN0IHZlY1NpemUgPSBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDQpO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1doZXJlJyxcbiAgICBzaGFkZXJDYWNoZTogeyBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJywgJ3JhbmsnLCAncmFuayddIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlOiAoc2hhZGVySGVscGVyKSA9PlxuICAgICAgY3JlYXRlV2hlcmVPcFByb2dyYW1TaGFkZXIoc2hhZGVySGVscGVyLCBpbnB1dHMsIG91dHB1dFNoYXBlLCBpc0Jyb2FkY2FzdCwgb3V0cHV0RGF0YVR5cGUpLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IG91dHB1dERhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovIC8gNCAvKiB2ZWMgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogdmVjU2l6ZSB9LFxuICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhkaW1zQywgZGltc0EsIGRpbXNCLCBvdXRwdXRTaGFwZSksXG4gICAgICBdLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHdoZXJlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVXaGVyZU9wUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGFyZ01heCwgYXJnTWluLCBwYXJzZUFyZ01pbk1heEF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9hcmdtaW5tYXgnO1xuaW1wb3J0IHsgYXR0ZW50aW9uIH0gZnJvbSAnLi9vcHMvYXR0ZW50aW9uJztcbmltcG9ydCB7IGJhdGNoTm9ybSB9IGZyb20gJy4vb3BzL2JhdGNoLW5vcm0nO1xuaW1wb3J0IHsgYmlhc0FkZCB9IGZyb20gJy4vb3BzL2JpYXMtYWRkJztcbmltcG9ydCB7IGJpYXNTcGxpdEdlbHUgfSBmcm9tICcuL29wcy9iaWFzLXNwbGl0LWdlbHUnO1xuaW1wb3J0ICogYXMgYmluYXJ5T3BzIGZyb20gJy4vb3BzL2JpbmFyeS1vcCc7XG5pbXBvcnQgeyBjb25jYXQsIHBhcnNlQ29uY2F0QXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2NvbmNhdCc7XG5pbXBvcnQgeyBjb252LCBwYXJzZUNvbnZBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvY29udic7XG5pbXBvcnQgeyBjb252VHJhbnNwb3NlLCBwYXJzZUNvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvY29udi10cmFuc3Bvc2UnO1xuaW1wb3J0IHsgY3Vtc3VtLCBwYXJzZUN1bVN1bUF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9jdW1zdW0nO1xuaW1wb3J0IHsgZGVwdGhUb1NwYWNlLCBwYXJzZURlcHRoVG9TcGFjZUF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9kZXB0aC10by1zcGFjZSc7XG5pbXBvcnQgeyBlaW5zdW0sIHBhcnNlRWluc3VtQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2VpbnN1bSc7XG5pbXBvcnQgeyBleHBhbmQgfSBmcm9tICcuL29wcy9leHBhbmQnO1xuaW1wb3J0IHsgZmFzdEdlbHUgfSBmcm9tICcuL29wcy9mYXN0LWdlbHUnO1xuaW1wb3J0IHsgZ2F0aGVyLCBwYXJzZUdhdGhlckF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9nYXRoZXInO1xuaW1wb3J0IHsgZ2F0aGVyTkQsIHBhcnNlR2F0aGVyTkRBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvZ2F0aGVyLW5kJztcbmltcG9ydCB7IGdhdGhlckJsb2NrUXVhbnRpemVkLCBwYXJzZUdhdGhlckJsb2NrUXVhbnRpemVkQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2dhdGhlci1ibG9jay1xdWFudGl6ZWQnO1xuaW1wb3J0IHsgZ2F0aGVyRWxlbWVudHMsIHBhcnNlR2F0aGVyRWxlbWVudHNBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvZ2F0aGVyLWVsZW1lbnRzJztcbmltcG9ydCB7IGdlbW0sIHBhcnNlR2VtbUF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9nZW1tJztcbmltcG9ydCB7IGdyaWRTYW1wbGUsIHBhcnNlR3JpZFNhbXBsZUF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9ncmlkLXNhbXBsZSc7XG5pbXBvcnQgeyBncm91cFF1ZXJ5QXR0ZW50aW9uIH0gZnJvbSAnLi9vcHMvZ3JvdXAtcXVlcnktYXR0ZW50aW9uJztcbmltcG9ydCB7IGluc3RhbmNlTm9ybSB9IGZyb20gJy4vb3BzL2luc3RhbmNlLW5vcm0nO1xuaW1wb3J0IHsgbGF5ZXJOb3JtIH0gZnJvbSAnLi9vcHMvbGF5ZXItbm9ybSc7XG5pbXBvcnQgeyBtYXRNdWwgfSBmcm9tICcuL29wcy9tYXRtdWwnO1xuaW1wb3J0IHsgbWF0TXVsTkJpdHMsIHBhcnNlTWF0TXVsTkJpdHNBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvbWF0bXVsbmJpdHMnO1xuaW1wb3J0IHsgbXVsdGlIZWFkQXR0ZW50aW9uLCBwYXJzZU11bHRpSGVhZEF0dGVudGlvbkF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9tdWx0aWhlYWQtYXR0ZW50aW9uJztcbmltcG9ydCB7IHBhZCB9IGZyb20gJy4vb3BzL3BhZCc7XG5pbXBvcnQgKiBhcyBwb29sIGZyb20gJy4vb3BzL3Bvb2wnO1xuaW1wb3J0IHsgZGVxdWFudGl6ZUxpbmVhciwgcGFyc2VEZXF1YW50aXplTGluZWFyQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL3F1YW50aXplLWxpbmVhcic7XG5pbXBvcnQgeyByYW5nZSB9IGZyb20gJy4vb3BzL3JhbmdlJztcbmltcG9ydCB7IHNjYXR0ZXJORCwgcGFyc2VTY2F0dGVyTkRBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvc2NhdHRlci1uZCc7XG5pbXBvcnQge1xuICByZWR1Y2VMMSxcbiAgcmVkdWNlTDIsXG4gIHJlZHVjZUxvZ1N1bSxcbiAgcmVkdWNlTG9nU3VtRXhwLFxuICByZWR1Y2VNYXgsXG4gIHJlZHVjZU1lYW4sXG4gIHJlZHVjZU1pbixcbiAgcmVkdWNlUHJvZCxcbiAgcmVkdWNlU3VtLFxuICByZWR1Y2VTdW1TcXVhcmUsXG59IGZyb20gJy4vb3BzL3JlZHVjZSc7XG5pbXBvcnQgeyBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXMsIHJlc2l6ZSB9IGZyb20gJy4vb3BzL3Jlc2l6ZSc7XG5pbXBvcnQgeyByb3RhcnlFbWJlZGRpbmcgfSBmcm9tICcuL29wcy9yb3RhcnktZW1iZWRkaW5nJztcbmltcG9ydCB7IHNraXBMYXllck5vcm0gfSBmcm9tICcuL29wcy9za2lwLWxheWVyLW5vcm0nO1xuaW1wb3J0IHsgcGFyc2VTbGljZUF0dHJpYnV0ZXMsIHNsaWNlIH0gZnJvbSAnLi9vcHMvc2xpY2UnO1xuaW1wb3J0IHsgcGFyc2VTb2Z0bWF4QXR0cmlidXRlcywgc29mdG1heCB9IGZyb20gJy4vb3BzL3NvZnRtYXgnO1xuaW1wb3J0IHsgcGFyc2VTcGxpdEF0dHJpYnV0ZXMsIHNwbGl0IH0gZnJvbSAnLi9vcHMvc3BsaXQnO1xuaW1wb3J0IHsgdGlsZSB9IGZyb20gJy4vb3BzL3RpbGUnO1xuaW1wb3J0IHsgcGFyc2VUcmFuc3Bvc2VBdHRyaWJ1dGVzLCB0cmFuc3Bvc2UgfSBmcm9tICcuL29wcy90cmFuc3Bvc2UnO1xuaW1wb3J0ICogYXMgdW5hcnlPcHMgZnJvbSAnLi9vcHMvdW5hcnktb3AnO1xuaW1wb3J0IHsgd2hlcmUgfSBmcm9tICcuL29wcy93aGVyZSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCB9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgdHlwZSBSdW5GdW5jdGlvbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlPzogdW5rbm93bikgPT4gdm9pZDtcbmV4cG9ydCB0eXBlIFBhcnNlQXR0cmlidXRlRnVuY3Rpb24gPSAoYXR0cmlidXRlUmF3OiB1bmtub3duKSA9PiB1bmtub3duO1xuZXhwb3J0IHR5cGUgT3BlcmF0b3JJbXBsZW1lbnRhdGlvbiA9IFtSdW5GdW5jdGlvbl0gfCBbUnVuRnVuY3Rpb24sIFBhcnNlQXR0cmlidXRlRnVuY3Rpb25dO1xuXG5leHBvcnQgY29uc3QgV0VCR1BVX09QX1JFU09MVkVfUlVMRVM6IE1hcDxzdHJpbmcsIE9wZXJhdG9ySW1wbGVtZW50YXRpb24+ID0gbmV3IE1hcChbXG4gIFsnQWJzJywgW3VuYXJ5T3BzLmFic11dLFxuICBbJ0Fjb3MnLCBbdW5hcnlPcHMuYWNvc11dLFxuICBbJ0Fjb3NoJywgW3VuYXJ5T3BzLmFjb3NoXV0sXG4gIFsnQWRkJywgW2JpbmFyeU9wcy5hZGRdXSxcbiAgWydBcmdNYXgnLCBbYXJnTWF4LCBwYXJzZUFyZ01pbk1heEF0dHJpYnV0ZXNdXSxcbiAgWydBcmdNaW4nLCBbYXJnTWluLCBwYXJzZUFyZ01pbk1heEF0dHJpYnV0ZXNdXSxcbiAgWydBc2luJywgW3VuYXJ5T3BzLmFzaW5dXSxcbiAgWydBc2luaCcsIFt1bmFyeU9wcy5hc2luaF1dLFxuICBbJ0F0YW4nLCBbdW5hcnlPcHMuYXRhbl1dLFxuICBbJ0F0YW5oJywgW3VuYXJ5T3BzLmF0YW5oXV0sXG4gIFsnQXR0ZW50aW9uJywgW2F0dGVudGlvbl1dLFxuICAvLyBUT0RPOiBzdXBwb3J0IG5ldyBhdHRyaWJ1dGVzIGZvciBBdmVyYWdlUG9vbC0xMFxuICBbJ0F2ZXJhZ2VQb29sJywgW3Bvb2wuYXZlcmFnZVBvb2wsIHBvb2wucGFyc2VBdmVyYWdlUG9vbEF0dHJpYnV0ZXNdXSxcbiAgWydCYXRjaE5vcm1hbGl6YXRpb24nLCBbYmF0Y2hOb3JtXV0sXG4gIFsnQmlhc0FkZCcsIFtiaWFzQWRkXV0sXG4gIFsnQmlhc1NwbGl0R2VsdScsIFtiaWFzU3BsaXRHZWx1XV0sXG4gIFsnQ2FzdCcsIFt1bmFyeU9wcy5jYXN0LCB1bmFyeU9wcy5wYXJzZUNhc3RBdHRyaWJ1dGVzXV0sXG4gIFsnQ2VpbCcsIFt1bmFyeU9wcy5jZWlsXV0sXG4gIFsnQ2xpcCcsIFt1bmFyeU9wcy5jbGlwXV0sXG4gIFsnQ29uY2F0JywgW2NvbmNhdCwgcGFyc2VDb25jYXRBdHRyaWJ1dGVzXV0sXG4gIFsnQ29udicsIFtjb252LCBwYXJzZUNvbnZBdHRyaWJ1dGVzXV0sXG4gIFsnQ29udlRyYW5zcG9zZScsIFtjb252VHJhbnNwb3NlLCBwYXJzZUNvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzXV0sXG4gIFsnQ29zJywgW3VuYXJ5T3BzLmNvc11dLFxuICBbJ0Nvc2gnLCBbdW5hcnlPcHMuY29zaF1dLFxuICBbJ0N1bVN1bScsIFtjdW1zdW0sIHBhcnNlQ3VtU3VtQXR0cmlidXRlc11dLFxuICBbJ0RlcHRoVG9TcGFjZScsIFtkZXB0aFRvU3BhY2UsIHBhcnNlRGVwdGhUb1NwYWNlQXR0cmlidXRlc11dLFxuICBbJ0RlcXVhbnRpemVMaW5lYXInLCBbZGVxdWFudGl6ZUxpbmVhciwgcGFyc2VEZXF1YW50aXplTGluZWFyQXR0cmlidXRlc11dLFxuICBbJ0RpdicsIFtiaW5hcnlPcHMuZGl2XV0sXG4gIFsnRWluc3VtJywgW2VpbnN1bSwgcGFyc2VFaW5zdW1BdHRyaWJ1dGVzXV0sXG4gIFsnRWx1JywgW3VuYXJ5T3BzLmVsdSwgdW5hcnlPcHMucGFyc2VBbHBoYUF0dHJpYnV0ZXNdXSxcbiAgWydFcXVhbCcsIFtiaW5hcnlPcHMuZXF1YWxdXSxcbiAgWydFcmYnLCBbdW5hcnlPcHMuZXJmXV0sXG4gIFsnRXhwJywgW3VuYXJ5T3BzLmV4cF1dLFxuICBbJ0V4cGFuZCcsIFtleHBhbmRdXSxcbiAgWydGYXN0R2VsdScsIFtmYXN0R2VsdV1dLFxuICBbJ0Zsb29yJywgW3VuYXJ5T3BzLmZsb29yXV0sXG4gIFsnRnVzZWRDb252JywgW2NvbnYsIHBhcnNlQ29udkF0dHJpYnV0ZXNdXSxcbiAgWydHYXRoZXInLCBbZ2F0aGVyLCBwYXJzZUdhdGhlckF0dHJpYnV0ZXNdXSxcbiAgWydHYXRoZXJFbGVtZW50cycsIFtnYXRoZXJFbGVtZW50cywgcGFyc2VHYXRoZXJFbGVtZW50c0F0dHJpYnV0ZXNdXSxcbiAgWydHYXRoZXJCbG9ja1F1YW50aXplZCcsIFtnYXRoZXJCbG9ja1F1YW50aXplZCwgcGFyc2VHYXRoZXJCbG9ja1F1YW50aXplZEF0dHJpYnV0ZXNdXSxcbiAgWydHYXRoZXJORCcsIFtnYXRoZXJORCwgcGFyc2VHYXRoZXJOREF0dHJpYnV0ZXNdXSxcbiAgWydHZWx1JywgW3VuYXJ5T3BzLmdlbHVdXSxcbiAgWydHZW1tJywgW2dlbW0sIHBhcnNlR2VtbUF0dHJpYnV0ZXNdXSxcbiAgWydHbG9iYWxBdmVyYWdlUG9vbCcsIFtwb29sLmdsb2JhbEF2ZXJhZ2VQb29sLCBwb29sLnBhcnNlR2xvYmFsQXZlcmFnZVBvb2xBdHRyaWJ1dGVzXV0sXG4gIFsnR2xvYmFsTWF4UG9vbCcsIFtwb29sLmdsb2JhbE1heFBvb2wsIHBvb2wucGFyc2VHbG9iYWxNYXhQb29sQXR0cmlidXRlc11dLFxuICBbJ0dyZWF0ZXInLCBbYmluYXJ5T3BzLmdyZWF0ZXJdXSxcbiAgWydHcmVhdGVyT3JFcXVhbCcsIFtiaW5hcnlPcHMuZ3JlYXRlck9yRXF1YWxdXSxcbiAgWydHcmlkU2FtcGxlJywgW2dyaWRTYW1wbGUsIHBhcnNlR3JpZFNhbXBsZUF0dHJpYnV0ZXNdXSxcbiAgWydHcm91cFF1ZXJ5QXR0ZW50aW9uJywgW2dyb3VwUXVlcnlBdHRlbnRpb25dXSxcbiAgWydIYXJkU2lnbW9pZCcsIFt1bmFyeU9wcy5oYXJkU2lnbW9pZCwgdW5hcnlPcHMucGFyc2VIYXJkU2lnbW9pZEF0dHJpYnV0ZXNdXSxcbiAgWydJbnN0YW5jZU5vcm1hbGl6YXRpb24nLCBbaW5zdGFuY2VOb3JtXV0sXG4gIFsnTGF5ZXJOb3JtYWxpemF0aW9uJywgW2xheWVyTm9ybV1dLFxuICBbJ0xlYWt5UmVsdScsIFt1bmFyeU9wcy5sZWFreVJlbHUsIHVuYXJ5T3BzLnBhcnNlQWxwaGFBdHRyaWJ1dGVzXV0sXG4gIFsnTGVzcycsIFtiaW5hcnlPcHMubGVzc11dLFxuICBbJ0xlc3NPckVxdWFsJywgW2JpbmFyeU9wcy5sZXNzT3JFcXVhbF1dLFxuICBbJ0xvZycsIFt1bmFyeU9wcy5sb2ddXSxcbiAgWydNYXRNdWwnLCBbbWF0TXVsXV0sXG4gIFsnTWF0TXVsTkJpdHMnLCBbbWF0TXVsTkJpdHMsIHBhcnNlTWF0TXVsTkJpdHNBdHRyaWJ1dGVzXV0sXG4gIC8vIFRPRE86IHN1cHBvcnQgbmV3IGF0dHJpYnV0ZXMgZm9yIE1heFBvb2wtOCBhbmQgTWF4UG9vbC0xMFxuICBbJ01heFBvb2wnLCBbcG9vbC5tYXhQb29sLCBwb29sLnBhcnNlTWF4UG9vbEF0dHJpYnV0ZXNdXSxcbiAgWydNdWwnLCBbYmluYXJ5T3BzLm11bF1dLFxuICBbJ011bHRpSGVhZEF0dGVudGlvbicsIFttdWx0aUhlYWRBdHRlbnRpb24sIHBhcnNlTXVsdGlIZWFkQXR0ZW50aW9uQXR0cmlidXRlc11dLFxuICBbJ05lZycsIFt1bmFyeU9wcy5uZWddXSxcbiAgWydOb3QnLCBbdW5hcnlPcHMubm90XV0sXG4gIFsnUGFkJywgW3BhZF1dLFxuICBbJ1BvdycsIFtiaW5hcnlPcHMucG93XV0sXG4gIFsnUXVpY2tHZWx1JywgW3VuYXJ5T3BzLnF1aWNrZ2VsdSwgdW5hcnlPcHMucGFyc2VBbHBoYUF0dHJpYnV0ZXNdXSxcbiAgWydSYW5nZScsIFtyYW5nZV1dLFxuICBbJ1JlY2lwcm9jYWwnLCBbdW5hcnlPcHMucmVjaXByb2NhbF1dLFxuICBbJ1JlZHVjZU1pbicsIFtyZWR1Y2VNaW5dXSxcbiAgWydSZWR1Y2VNZWFuJywgW3JlZHVjZU1lYW5dXSxcbiAgWydSZWR1Y2VNYXgnLCBbcmVkdWNlTWF4XV0sXG4gIFsnUmVkdWNlU3VtJywgW3JlZHVjZVN1bV1dLFxuICBbJ1JlZHVjZVByb2QnLCBbcmVkdWNlUHJvZF1dLFxuICBbJ1JlZHVjZUwxJywgW3JlZHVjZUwxXV0sXG4gIFsnUmVkdWNlTDInLCBbcmVkdWNlTDJdXSxcbiAgWydSZWR1Y2VMb2dTdW0nLCBbcmVkdWNlTG9nU3VtXV0sXG4gIFsnUmVkdWNlTG9nU3VtRXhwJywgW3JlZHVjZUxvZ1N1bUV4cF1dLFxuICBbJ1JlZHVjZVN1bVNxdWFyZScsIFtyZWR1Y2VTdW1TcXVhcmVdXSxcbiAgWydSZWx1JywgW3VuYXJ5T3BzLnJlbHVdXSxcbiAgWydSZXNpemUnLCBbcmVzaXplLCBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXNdXSxcbiAgWydSb3RhcnlFbWJlZGRpbmcnLCBbcm90YXJ5RW1iZWRkaW5nXV0sXG4gIFsnU2NhdHRlck5EJywgW3NjYXR0ZXJORCwgcGFyc2VTY2F0dGVyTkRBdHRyaWJ1dGVzXV0sXG4gIFsnU2lnbW9pZCcsIFt1bmFyeU9wcy5zaWdtb2lkXV0sXG4gIFsnU2luJywgW3VuYXJ5T3BzLnNpbl1dLFxuICBbJ1NpbmgnLCBbdW5hcnlPcHMuc2luaF1dLFxuICBbJ1NsaWNlJywgW3NsaWNlLCBwYXJzZVNsaWNlQXR0cmlidXRlc11dLFxuICBbJ1NraXBMYXllck5vcm1hbGl6YXRpb24nLCBbc2tpcExheWVyTm9ybV1dLFxuICBbJ1NwbGl0JywgW3NwbGl0LCBwYXJzZVNwbGl0QXR0cmlidXRlc11dLFxuICBbJ1NxcnQnLCBbdW5hcnlPcHMuc3FydF1dLFxuICBbJ1NvZnRtYXgnLCBbc29mdG1heCwgcGFyc2VTb2Z0bWF4QXR0cmlidXRlc11dLFxuICBbJ1N1YicsIFtiaW5hcnlPcHMuc3ViXV0sXG4gIFsnVGFuJywgW3VuYXJ5T3BzLnRhbl1dLFxuICBbJ1RhbmgnLCBbdW5hcnlPcHMudGFuaF1dLFxuICBbJ1RocmVzaG9sZGVkUmVsdScsIFt1bmFyeU9wcy50aHJlc2hvbGRlZFJlbHUsIHVuYXJ5T3BzLnBhcnNlQWxwaGFBdHRyaWJ1dGVzXV0sXG4gIFsnVGlsZScsIFt0aWxlXV0sXG4gIFsnVHJhbnNwb3NlJywgW3RyYW5zcG9zZSwgcGFyc2VUcmFuc3Bvc2VBdHRyaWJ1dGVzXV0sXG4gIFsnV2hlcmUnLCBbd2hlcmVdXSxcbl0pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUUkFDRV9GVU5DX0JFR0lOLCBUUkFDRV9GVU5DX0VORCB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IFdlYkdwdUJhY2tlbmQgfSBmcm9tICcuLi9iYWNrZW5kLXdlYmdwdSc7XG5pbXBvcnQgeyBMT0dfREVCVUcgfSBmcm9tICcuLi9sb2cnO1xuXG5pbXBvcnQgeyBjcmVhdGVTaGFkZXJIZWxwZXIgfSBmcm9tICcuL29wcy9jb21tb24nO1xuaW1wb3J0IHsgQXJ0aWZhY3QsIEdwdURhdGEsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogUHJvZ3JhbU1hbmFnZXIgaXMgdGhlIG1haW4gY2xhc3MgYmVoaW5kIHJ1bm5pbmcgY29tcHV0YXRpb25zXG4gKiBJdCBidWlsZHMgUHJvZ3JhbUluZm8ncyBpbnRvIEFydGlmYWN0c1xuICogSXQgY29tcGlsZXMgZ2l2ZW4gUHJvZ3JhbUluZm8ncyBpbnRvIFdlYkdMIFByb3JhbXMgKGNhY2hlZCBhcyBBcnRpZmFjdHMpXG4gKiBVc2VzIHRoZSBhcnRpZmFjdCB0byBydW4gdGhlIGNvbXB1dGF0aW9uIGJ5IGNhbGxpbmcgRHJhdyBvblxuICogdGhlIFdlYkdMIGRyYXdpbmcgYnVmZmVyXG4gKiBQcm9ncmFtTWFuYWdlciBhdXRvbWF0aWNhbGx5IG1hcHMgKGJpbmRzKSBpbnB1dCB2YXJpYWJsZXMgdG8gdGhlaXJcbiAqIGNvcnJlc3BvbmRpbmcgTG9jYXRpb24ncyBpbiB0aGUgYmluYXJ5IHByb2dyYW1cbiAqL1xuZXhwb3J0IGNsYXNzIFByb2dyYW1NYW5hZ2VyIHtcbiAgcmVwbzogTWFwPHVua25vd24sIEFydGlmYWN0PjsgLy8gdGhpcyBzaG91bGQgYmUgcGVyLXNlc3Npb24gb2JqZWN0XG4gIGF0dHJpYnV0ZXNCb3VuZDogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGJhY2tlbmQ6IFdlYkdwdUJhY2tlbmQpIHtcbiAgICB0aGlzLnJlcG8gPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5hdHRyaWJ1dGVzQm91bmQgPSBmYWxzZTtcbiAgfVxuICBnZXRBcnRpZmFjdChrZXk6IHVua25vd24pOiBBcnRpZmFjdCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucmVwby5nZXQoa2V5KTtcbiAgfVxuICBzZXRBcnRpZmFjdChrZXk6IHVua25vd24sIGFydGlmYWN0OiBBcnRpZmFjdCk6IHZvaWQge1xuICAgIHRoaXMucmVwby5zZXQoa2V5LCBhcnRpZmFjdCk7XG4gIH1cbiAgcnVuKFxuICAgIGJ1aWxkQXJ0aWZhY3Q6IEFydGlmYWN0LFxuICAgIGlucHV0czogR3B1RGF0YVtdLFxuICAgIG91dHB1dHM6IEdwdURhdGFbXSxcbiAgICBkaXNwYXRjaEdyb3VwOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgdW5pZm9ybUJ1ZmZlckJpbmRpbmc6IEdQVUJpbmRpbmdSZXNvdXJjZSB8IHVuZGVmaW5lZCxcbiAgKTogdm9pZCB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTihidWlsZEFydGlmYWN0LnByb2dyYW1JbmZvLm5hbWUpO1xuICAgIGNvbnN0IGRldmljZSA9IHRoaXMuYmFja2VuZC5kZXZpY2U7XG4gICAgY29uc3QgY29tcHV0ZVBhc3NFbmNvZGVyID0gdGhpcy5iYWNrZW5kLmdldENvbXB1dGVQYXNzRW5jb2RlcigpO1xuICAgIHRoaXMuYmFja2VuZC53cml0ZVRpbWVzdGFtcCh0aGlzLmJhY2tlbmQucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMik7XG4gICAgY29uc3QgZW50cmllcyA9IFtdO1xuICAgIGZvciAoY29uc3QgaW5wdXQgb2YgaW5wdXRzKSB7XG4gICAgICBlbnRyaWVzLnB1c2goeyBiaW5kaW5nOiBlbnRyaWVzLmxlbmd0aCwgcmVzb3VyY2U6IHsgYnVmZmVyOiBpbnB1dC5idWZmZXIgfSB9KTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBvdXRwdXQgb2Ygb3V0cHV0cykge1xuICAgICAgZW50cmllcy5wdXNoKHsgYmluZGluZzogZW50cmllcy5sZW5ndGgsIHJlc291cmNlOiB7IGJ1ZmZlcjogb3V0cHV0LmJ1ZmZlciB9IH0pO1xuICAgIH1cbiAgICBpZiAodW5pZm9ybUJ1ZmZlckJpbmRpbmcpIHtcbiAgICAgIGVudHJpZXMucHVzaCh7IGJpbmRpbmc6IGVudHJpZXMubGVuZ3RoLCByZXNvdXJjZTogdW5pZm9ybUJ1ZmZlckJpbmRpbmcgfSk7XG4gICAgfVxuICAgIGNvbnN0IGJpbmRHcm91cCA9IGRldmljZS5jcmVhdGVCaW5kR3JvdXAoe1xuICAgICAgbGF5b3V0OiBidWlsZEFydGlmYWN0LmNvbXB1dGVQaXBlbGluZS5nZXRCaW5kR3JvdXBMYXlvdXQoMCksXG4gICAgICBlbnRyaWVzLFxuICAgICAgbGFiZWw6IGJ1aWxkQXJ0aWZhY3QucHJvZ3JhbUluZm8ubmFtZSxcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLmJhY2tlbmQuc2Vzc2lvblN0YXR1cyA9PT0gJ2NhcHR1cmluZycpIHtcbiAgICAgIGNvbnN0IGNvbW1hbmRJbmZvID0ge1xuICAgICAgICBrZXJuZWxJZDogdGhpcy5iYWNrZW5kLmN1cnJlbnRLZXJuZWxJZCEsXG4gICAgICAgIGNvbXB1dGVQaXBlbGluZTogYnVpbGRBcnRpZmFjdC5jb21wdXRlUGlwZWxpbmUsXG4gICAgICAgIGJpbmRHcm91cCxcbiAgICAgICAgZGlzcGF0Y2hHcm91cCxcbiAgICAgIH07XG4gICAgICBjb25zdCBzZXNzaW9uQ29tbWFuZExpc3QgPSB0aGlzLmJhY2tlbmQuY2FwdHVyZWRDb21tYW5kTGlzdC5nZXQodGhpcy5iYWNrZW5kLmN1cnJlbnRTZXNzaW9uSWQhKTtcbiAgICAgIHNlc3Npb25Db21tYW5kTGlzdCEucHVzaChjb21tYW5kSW5mbyk7XG4gICAgfVxuXG4gICAgY29tcHV0ZVBhc3NFbmNvZGVyLnNldFBpcGVsaW5lKGJ1aWxkQXJ0aWZhY3QuY29tcHV0ZVBpcGVsaW5lKTtcbiAgICBjb21wdXRlUGFzc0VuY29kZXIuc2V0QmluZEdyb3VwKDAsIGJpbmRHcm91cCk7XG4gICAgY29tcHV0ZVBhc3NFbmNvZGVyLmRpc3BhdGNoV29ya2dyb3VwcyguLi5kaXNwYXRjaEdyb3VwKTtcbiAgICB0aGlzLmJhY2tlbmQud3JpdGVUaW1lc3RhbXAodGhpcy5iYWNrZW5kLnBlbmRpbmdEaXNwYXRjaE51bWJlciAqIDIgKyAxKTtcbiAgICB0aGlzLmJhY2tlbmQucGVuZGluZ0Rpc3BhdGNoTnVtYmVyKys7XG5cbiAgICBpZiAoXG4gICAgICB0aGlzLmJhY2tlbmQucGVuZGluZ0Rpc3BhdGNoTnVtYmVyID49IHRoaXMuYmFja2VuZC5tYXhEaXNwYXRjaE51bWJlciB8fFxuICAgICAgdGhpcy5iYWNrZW5kLnF1ZXJ5VHlwZSA9PT0gJ2F0LXBhc3NlcydcbiAgICApIHtcbiAgICAgIHRoaXMuYmFja2VuZC5lbmRDb21wdXRlUGFzcygpO1xuICAgIH1cbiAgICBpZiAodGhpcy5iYWNrZW5kLnBlbmRpbmdEaXNwYXRjaE51bWJlciA+PSB0aGlzLmJhY2tlbmQubWF4RGlzcGF0Y2hOdW1iZXIpIHtcbiAgICAgIHRoaXMuYmFja2VuZC5mbHVzaCgpO1xuICAgIH1cbiAgICBUUkFDRV9GVU5DX0VORChidWlsZEFydGlmYWN0LnByb2dyYW1JbmZvLm5hbWUpO1xuICB9XG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgLy8gdGhpcy5yZXBvLmZvckVhY2goYSA9PiB0aGlzLmdsQ29udGV4dC5kZWxldGVQcm9ncmFtKGEucHJvZ3JhbSkpO1xuICB9XG4gIGJ1aWxkKHByb2dyYW1JbmZvOiBQcm9ncmFtSW5mbywgbm9ybWFsaXplZERpc3BhdGNoR3JvdXBTaXplOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pOiBBcnRpZmFjdCB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTihwcm9ncmFtSW5mby5uYW1lKTtcbiAgICBjb25zdCBkZXZpY2UgPSB0aGlzLmJhY2tlbmQuZGV2aWNlO1xuICAgIGNvbnN0IGVuYWJsZURpcmVjdGl2ZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICAvLyBFbmFibGUgV0dTTCBleHRlbnNpb25zIGJhc2VkIG9uIGF2YWlsYWJsZSBXZWJHUFUgZmVhdHVyZXNcbiAgICBjb25zdCBleHRlbnNpb25zSW5mbzogQXJyYXk8eyBmZWF0dXJlOiBHUFVGZWF0dXJlTmFtZTsgZXh0ZW5zaW9uOiBzdHJpbmcgfT4gPSBbXG4gICAgICB7IGZlYXR1cmU6ICdzaGFkZXItZjE2JywgZXh0ZW5zaW9uOiAnZjE2JyB9LFxuICAgICAgeyBmZWF0dXJlOiAnc3ViZ3JvdXBzJyBhcyBHUFVGZWF0dXJlTmFtZSwgZXh0ZW5zaW9uOiAnc3ViZ3JvdXBzJyB9LFxuICAgIF07XG4gICAgZXh0ZW5zaW9uc0luZm8uZm9yRWFjaCgoaW5mbykgPT4ge1xuICAgICAgaWYgKGRldmljZS5mZWF0dXJlcy5oYXMoaW5mby5mZWF0dXJlKSkge1xuICAgICAgICBlbmFibGVEaXJlY3RpdmVzLnB1c2goYGVuYWJsZSAke2luZm8uZXh0ZW5zaW9ufTtgKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbnN0IHNoYWRlckhlbHBlciA9IGNyZWF0ZVNoYWRlckhlbHBlcihub3JtYWxpemVkRGlzcGF0Y2hHcm91cFNpemUsIHRoaXMuYmFja2VuZC5kZXZpY2UubGltaXRzKTtcbiAgICBjb25zdCB1c2VyQ29kZSA9IHByb2dyYW1JbmZvLmdldFNoYWRlclNvdXJjZShzaGFkZXJIZWxwZXIpO1xuICAgIGNvbnN0IGNvZGUgPSBgJHtlbmFibGVEaXJlY3RpdmVzLmpvaW4oJ1xcbicpfVxcbiR7c2hhZGVySGVscGVyLmFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbnN9XFxuJHt1c2VyQ29kZX1gO1xuICAgIGNvbnN0IHNoYWRlck1vZHVsZSA9IGRldmljZS5jcmVhdGVTaGFkZXJNb2R1bGUoeyBjb2RlLCBsYWJlbDogcHJvZ3JhbUluZm8ubmFtZSB9KTtcbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYkdQVV0gJHtwcm9ncmFtSW5mby5uYW1lfSBzaGFkZXIgY29kZTogJHtjb2RlfWApO1xuXG4gICAgY29uc3QgY29tcHV0ZVBpcGVsaW5lID0gZGV2aWNlLmNyZWF0ZUNvbXB1dGVQaXBlbGluZSh7XG4gICAgICBjb21wdXRlOiB7IG1vZHVsZTogc2hhZGVyTW9kdWxlLCBlbnRyeVBvaW50OiAnbWFpbicgfSxcbiAgICAgIGxheW91dDogJ2F1dG8nLFxuICAgICAgbGFiZWw6IHByb2dyYW1JbmZvLm5hbWUsXG4gICAgfSk7XG5cbiAgICBUUkFDRV9GVU5DX0VORChwcm9ncmFtSW5mby5uYW1lKTtcbiAgICByZXR1cm4geyBwcm9ncmFtSW5mbywgY29tcHV0ZVBpcGVsaW5lLCB1bmlmb3JtVmFyaWFibGVzSW5mbzogc2hhZGVySGVscGVyLnZhcmlhYmxlc0luZm8gfTtcbiAgfVxuXG4gIG5vcm1hbGl6ZURpc3BhdGNoR3JvdXBTaXplKFxuICAgIGRpc3BhdGNoR3JvdXA6IFJldHVyblR5cGU8UHJvZ3JhbUluZm9bJ2dldFJ1bkRhdGEnXT5bJ2Rpc3BhdGNoR3JvdXAnXSxcbiAgKTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdIHtcbiAgICBjb25zdCB4ID0gdHlwZW9mIGRpc3BhdGNoR3JvdXAgPT09ICdudW1iZXInID8gZGlzcGF0Y2hHcm91cCA6IGRpc3BhdGNoR3JvdXAueDtcbiAgICBjb25zdCB5ID0gdHlwZW9mIGRpc3BhdGNoR3JvdXAgPT09ICdudW1iZXInID8gMSA6IGRpc3BhdGNoR3JvdXAueSB8fCAxO1xuICAgIGNvbnN0IHogPSB0eXBlb2YgZGlzcGF0Y2hHcm91cCA9PT0gJ251bWJlcicgPyAxIDogZGlzcGF0Y2hHcm91cC56IHx8IDE7XG4gICAgY29uc3QgbGltaXRQZXJEaW1lbnNpb24gPSB0aGlzLmJhY2tlbmQuZGV2aWNlLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3Vwc1BlckRpbWVuc2lvbjtcbiAgICBpZiAoeCA8PSBsaW1pdFBlckRpbWVuc2lvbiAmJiB5IDw9IGxpbWl0UGVyRGltZW5zaW9uICYmIHogPD0gbGltaXRQZXJEaW1lbnNpb24pIHtcbiAgICAgIHJldHVybiBbeCwgeSwgel07XG4gICAgfVxuICAgIGNvbnN0IHNpemUgPSB4ICogeSAqIHo7XG4gICAgbGV0IGRpc3BhdGNoQXZlcmFnZSA9IE1hdGguY2VpbChNYXRoLnNxcnQoc2l6ZSkpO1xuICAgIGlmIChkaXNwYXRjaEF2ZXJhZ2UgPiBsaW1pdFBlckRpbWVuc2lvbikge1xuICAgICAgZGlzcGF0Y2hBdmVyYWdlID0gTWF0aC5jZWlsKE1hdGguY2JydChzaXplKSk7XG4gICAgICBpZiAoZGlzcGF0Y2hBdmVyYWdlID4gbGltaXRQZXJEaW1lbnNpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUb3RhbCBkaXNwYXRjaCBzaXplIGV4Y2VlZHMgV2ViR1BVIG1heGltdW0uJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gW2Rpc3BhdGNoQXZlcmFnZSwgZGlzcGF0Y2hBdmVyYWdlLCBkaXNwYXRjaEF2ZXJhZ2VdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW2Rpc3BhdGNoQXZlcmFnZSwgZGlzcGF0Y2hBdmVyYWdlLCAxXTtcbiAgICB9XG4gIH1cbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRW52LCBUZW5zb3IsIFRSQUNFLCBUUkFDRV9GVU5DX0JFR0lOLCBUUkFDRV9GVU5DX0VORCB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IERhdGFUeXBlLCB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyB9IGZyb20gJy4uL3dhc20tY29tbW9uJztcblxuaW1wb3J0IHsgY29uZmlndXJlTG9nZ2VyLCBMT0dfREVCVUcgfSBmcm9tICcuL2xvZyc7XG5pbXBvcnQgeyBjcmVhdGVWaWV3LCBUZW5zb3JWaWV3IH0gZnJvbSAnLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBjcmVhdGVHcHVEYXRhTWFuYWdlciwgZG93bmxvYWRHcHVEYXRhLCBHcHVEYXRhTWFuYWdlciB9IGZyb20gJy4vd2ViZ3B1L2dwdS1kYXRhLW1hbmFnZXInO1xuaW1wb3J0IHsgUnVuRnVuY3Rpb24sIFdFQkdQVV9PUF9SRVNPTFZFX1JVTEVTIH0gZnJvbSAnLi93ZWJncHUvb3AtcmVzb2x2ZS1ydWxlcyc7XG5pbXBvcnQgeyBQcm9ncmFtTWFuYWdlciB9IGZyb20gJy4vd2ViZ3B1L3Byb2dyYW0tbWFuYWdlcic7XG5pbXBvcnQge1xuICBBZGFwdGVySW5mbyxcbiAgQ29tcHV0ZUNvbnRleHQsXG4gIEdwdUFyY2hpdGVjdHVyZSxcbiAgR3B1RGF0YSxcbiAgR3B1VmVuZG9yLFxuICBQcm9ncmFtSW5mbyxcbiAgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksXG4gIFNlc3Npb25TdGF0ZSxcbiAgVGltZXN0YW1wUXVlcnksXG59IGZyb20gJy4vd2ViZ3B1L3R5cGVzJztcblxuaW50ZXJmYWNlIENvbW1hbmRJbmZvIHtcbiAgcmVhZG9ubHkga2VybmVsSWQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgY29tcHV0ZVBpcGVsaW5lOiBHUFVDb21wdXRlUGlwZWxpbmU7XG4gIHJlYWRvbmx5IGJpbmRHcm91cDogR1BVQmluZEdyb3VwO1xuICByZWFkb25seSBkaXNwYXRjaEdyb3VwOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG59XG5cbmludGVyZmFjZSBLZXJuZWxJbmZvIHtcbiAgcmVhZG9ubHkga2VybmVsVHlwZTogc3RyaW5nO1xuICByZWFkb25seSBrZXJuZWxOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGtlcm5lbEVudHJ5OiBSdW5GdW5jdGlvbjtcbiAgcmVhZG9ubHkgYXR0cmlidXRlczogWygoYXR0cmlidXRlOiB1bmtub3duKSA9PiB1bmtub3duKSB8IHVuZGVmaW5lZCwgdW5rbm93bl07XG59XG5cbmludGVyZmFjZSBQZW5kaW5nS2VybmVsSW5mbyB7XG4gIHJlYWRvbmx5IGtlcm5lbElkOiBudW1iZXI7XG4gIHJlYWRvbmx5IHByb2dyYW1OYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGlucHV0VGVuc29yVmlld3M6IHJlYWRvbmx5IFRlbnNvclZpZXdbXTtcbiAgcmVhZG9ubHkgb3V0cHV0VGVuc29yVmlld3M6IHJlYWRvbmx5IFRlbnNvclZpZXdbXTtcbn1cblxuY29uc3QgZ2V0UHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lLZXkgPSAoXG4gIGlucHV0VGVuc29yczogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBpbnB1dERlcGVuZGVuY2llczogcmVhZG9ubHkgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSxcbik6IHN0cmluZyA9PiB7XG4gIGlmIChpbnB1dERlcGVuZGVuY2llcy5sZW5ndGggIT09IGlucHV0VGVuc29ycy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgaW5wdXREZXBlbmRlbmNpZXMgbGVuZ3RoICR7aW5wdXREZXBlbmRlbmNpZXMubGVuZ3RofSBpcyBub3QgZXF1YWwgdG8gaW5wdXRUZW5zb3JzIGxlbmd0aCAke1xuICAgICAgICBpbnB1dFRlbnNvcnMubGVuZ3RoXG4gICAgICB9LmAsXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IGlucHV0SW5mb3M6IHN0cmluZ1tdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRUZW5zb3JzLmxlbmd0aDsgKytpKSB7XG4gICAgY29uc3QgdHlwZSA9IGlucHV0VGVuc29yc1tpXS5kYXRhVHlwZTtcbiAgICBzd2l0Y2ggKGlucHV0RGVwZW5kZW5jaWVzW2ldKSB7XG4gICAgICBjYXNlICdub25lJzoge1xuICAgICAgICBpbnB1dEluZm9zLnB1c2goJycpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3R5cGUnOiB7XG4gICAgICAgIGlucHV0SW5mb3MucHVzaChgJHt0eXBlfWApO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3JhbmsnOiB7XG4gICAgICAgIGNvbnN0IHJhbmsgPSBpbnB1dFRlbnNvcnNbaV0uZGltcy5sZW5ndGg7XG4gICAgICAgIGlucHV0SW5mb3MucHVzaChgJHt0eXBlfTske3Jhbmt9YCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnZGltcyc6IHtcbiAgICAgICAgY29uc3QgZGltcyA9IGlucHV0VGVuc29yc1tpXS5kaW1zLmpvaW4oJywnKTtcbiAgICAgICAgaW5wdXRJbmZvcy5wdXNoKGAke3R5cGV9OyR7ZGltc31gKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGlucHV0IGRlcGVuZGVuY3k6ICR7aW5wdXREZXBlbmRlbmNpZXNbaV19YCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGlucHV0SW5mb3Muam9pbignfCcpO1xufTtcblxuLyoqXG4gKiBnZXQgYSB1bmlxdWUga2V5IHJlcHJlc2VudGluZyB0aGUgcHJvZ3JhbSBmcm9tIHRoZSBwcm9ncmFtIGluZm8sIGlucHV0IHNoYXBlcyBhbmQgdHlwZXMuXG4gKlxuICogQHJldHVybnMgYSB1bmlxdWUga2V5IGlzIGEgc2hvcnRlciBzdHJpbmcgdGhhbiB0aGUgc2hhZGVyIHNvdXJjZSwgd2hpY2ggY29udGFpbnMgYWxsIHRoZSBpbmZvcm1hdGlvbiB0byBpZGVudGlmeSBhXG4gKiBwcm9ncmFtLiBpZiB0aGUga2V5IGlzIHRoZSBzYW1lLCB0aGUgcHJvZ3JhbSBzaGFkZXIgc291cmNlIHNob3VsZCBiZSB0aGUgc2FtZSwgc28gd2UgY2FuIHJldXNlIHRoZSBwcm9ncmFtLlxuICpcbiAqL1xuY29uc3QgZ2V0UHJvZ3JhbUluZm9VbmlxdWVLZXkgPSAoXG4gIHByb2dyYW1JbmZvOiBQcm9ncmFtSW5mbyxcbiAgaW5wdXRUZW5zb3JzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGlzMURpbWVuc2lvbkRpc3BhdGNoOiBib29sZWFuLFxuKTogc3RyaW5nID0+IHtcbiAgLy8gZmluYWwga2V5IGZvcm1hdDpcbiAgLy8gPFBST0dSQU1fTkFNRT5bPFBST0dSQU1fQ1VTVE9NX0NBQ0hFX0hJTlQ+XTppczFEaW1lbnNpb25EaXNwYXRjaDo8SU5QVVRTX0lORk9fMD58PElOUFVUU19JTkZPXzE+fC4uLlxuICBsZXQga2V5ID0gcHJvZ3JhbUluZm8ubmFtZTtcbiAgaWYgKHByb2dyYW1JbmZvLnNoYWRlckNhY2hlPy5oaW50KSB7XG4gICAga2V5ICs9ICdbJyArIHByb2dyYW1JbmZvLnNoYWRlckNhY2hlLmhpbnQgKyAnXSc7XG4gIH1cbiAga2V5ICs9XG4gICAgJzonICtcbiAgICBpczFEaW1lbnNpb25EaXNwYXRjaCArXG4gICAgYDoke2dldFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5S2V5KFxuICAgICAgaW5wdXRUZW5zb3JzLFxuICAgICAgcHJvZ3JhbUluZm8uc2hhZGVyQ2FjaGU/LmlucHV0RGVwZW5kZW5jaWVzID8/XG4gICAgICAgIG5ldyBBcnJheTxQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeT4oaW5wdXRUZW5zb3JzLmxlbmd0aCkuZmlsbCgnZGltcycpLFxuICAgICl9YDtcbiAgcmV0dXJuIGtleTtcbn07XG5cbmNsYXNzIEFkYXB0ZXJJbmZvSW1wbCBpbXBsZW1lbnRzIEFkYXB0ZXJJbmZvIHtcbiAgcmVhZG9ubHkgYXJjaGl0ZWN0dXJlPzogc3RyaW5nO1xuICByZWFkb25seSB2ZW5kb3I/OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoYWRhcHRlckluZm86IEdQVUFkYXB0ZXJJbmZvKSB7XG4gICAgaWYgKGFkYXB0ZXJJbmZvKSB7XG4gICAgICB0aGlzLmFyY2hpdGVjdHVyZSA9IGFkYXB0ZXJJbmZvLmFyY2hpdGVjdHVyZTtcbiAgICAgIHRoaXMudmVuZG9yID0gYWRhcHRlckluZm8udmVuZG9yO1xuICAgIH1cbiAgfVxuXG4gIGlzQXJjaGl0ZWN0dXJlKGFyY2hpdGVjdHVyZTogR3B1QXJjaGl0ZWN0dXJlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuYXJjaGl0ZWN0dXJlID09PSBhcmNoaXRlY3R1cmU7XG4gIH1cblxuICBpc1ZlbmRvcih2ZW5kb3I6IEdwdVZlbmRvcik6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnZlbmRvciA9PT0gdmVuZG9yO1xuICB9XG59XG5cbi8qKlxuICogdGhpcyBjbGFzcyBpcyBkZXNpZ25lZCB0byBzdG9yZSBzdGF0dXMgYW5kIGJlaW5nIHVzZWQgYXMgYSBzaW5nbGV0b24gZm9yIEpTRVAuIEl0IHdpbGwgYmUgcGFzc2VkIHRvIGpzZXBJbml0KCkgYXNcbiAqIHRoZSBmaXJzdCBwYXJhbWV0ZXIgc28gdGhhdCBpdCBpcyBzdG9yZWQgZm9yIGZ1dHVyZSB1c2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJHcHVCYWNrZW5kIHtcbiAgYWRhcHRlckluZm86IEFkYXB0ZXJJbmZvSW1wbDtcbiAgZGV2aWNlOiBHUFVEZXZpY2U7XG4gIC8qKlxuICAgKiBhbiBpbnN0YW5jZSBvZiBHcHVEYXRhTWFuYWdlciB0byBtYW5hZ2UgYSBHcHVEYXRhSWQgLT4gR3B1QnVmZmVyIG1hcHBpbmdcbiAgICovXG4gIGdwdURhdGFNYW5hZ2VyOiBHcHVEYXRhTWFuYWdlcjtcbiAgLyoqXG4gICAqIGFuIGluc3RhbmNlIG9mIFByb2dyYW1NYW5hZ2VyIHRvIGJ1aWxkIGFuZCBydW4gV2ViR1BVIGNvbXB1dGUgc2hhZGVyIHByb2dyYW0sIGFuZCBtYW5hZ2UgYSBQcm9ncmFtS2V5IC0+IFByb2dyYW1cbiAgICogYXJ0aWZhY3RzIG1hcHBpbmdcbiAgICovXG4gIHByb2dyYW1NYW5hZ2VyOiBQcm9ncmFtTWFuYWdlcjtcblxuICAvKipcbiAgICogcmVwcmVzZW50aW5nIHRoZSBzZXNzaW9uIElEIG9mIHdoaWNoIGlzIGN1cnJlbnRseSBiZWluZyBydW4uXG4gICAqIGBudWxsYCBtZWFucyBubyBzZXNzaW9uIGlzIGJlaW5nIHJ1bi5cbiAgICogb25seSB2YWxpZCB3aGVuIHNlc3Npb24ucnVuIGlzIGV4ZWN1dGVkLlxuICAgKi9cbiAgY3VycmVudFNlc3Npb25JZDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIHJlcHJlc2VudGluZyB0aGUga2VybmVsIElEIG9mIHdoaWNoIGlzIGN1cnJlbnRseSBiZWluZyBjb21wdXRlZCAoQ1BVIGNvZGUgcGVyc3BlY3RpdmUpLlxuICAgKiBgbnVsbGAgbWVhbnMgbm8ga2VybmVsIGlzIGJlaW5nIGNvbXB1dGVkLlxuICAgKiBvbmx5IG9uZSBrZXJuZWwgY2FuIGJlIGNvbXB1dGVkIGF0IGEgbW9tZW50LlxuICAgKi9cbiAgY3VycmVudEtlcm5lbElkOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIGEgbGlzdCBvZiB0ZW1wb3JhcnkgR1BVIGRhdGEgZm9yIHRoZSBjdXJyZW50IGtlcm5lbC4gc2hvdWxkIHJlbGVhc2Ugd2hlbiB0aGUga2VybmVsIGRvbmUgY29tcHV0YXRpb24uXG4gICAqL1xuICBwcml2YXRlIHRlbXBvcmFyeURhdGE6IEdwdURhdGFbXTtcbiAgLyoqXG4gICAqIGEgS2VybmVsSUQgLT4gYSBHUFUgZGF0YSBsaXN0LCB3aGljaCBzdG9yZXMgcGVyc2lzdGVudCBHUFUgZGF0YSBvd25lZCBieSB0aGUgc3BlY2lmaWMga2VybmVsLlxuICAgKi9cbiAgcHJpdmF0ZSBrZXJuZWxQZXJzaXN0ZW50RGF0YTogTWFwPG51bWJlciwgR3B1RGF0YVtdPjtcbiAgLyoqXG4gICAqIGEgS2VybmVsSUQgLT4gYSBjdXN0b20gZGF0YSwgd2hpY2ggc3RvcmVzIGN1c3RvbSBkYXRhIG93bmVkIGJ5IHRoZSBzcGVjaWZpYyBrZXJuZWwuXG4gICAqL1xuICBwcml2YXRlIGtlcm5lbEN1c3RvbURhdGE6IE1hcDxudW1iZXIsIHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9PjtcbiAgLyoqXG4gICAqIGdldCB0aGUgY3VzdG9tIGRhdGEgb2YgdGhlIGN1cnJlbnQga2VybmVsXG4gICAqL1xuICBnZXQgY3VycmVudEtlcm5lbEN1c3RvbURhdGEoKTogeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0ge1xuICAgIGlmICh0aGlzLmN1cnJlbnRLZXJuZWxJZCA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjdXJyZW50S2VybmVsQ3VzdG9tRGF0YSgpOiBjdXJyZW50S2VybmVsSWQgaXMgbnVsbC4gKHNob3VsZCBub3QgaGFwcGVuKScpO1xuICAgIH1cblxuICAgIGxldCBkYXRhID0gdGhpcy5rZXJuZWxDdXN0b21EYXRhLmdldCh0aGlzLmN1cnJlbnRLZXJuZWxJZCk7XG4gICAgaWYgKCFkYXRhKSB7XG4gICAgICBkYXRhID0ge307XG4gICAgICB0aGlzLmtlcm5lbEN1c3RvbURhdGEuc2V0KHRoaXMuY3VycmVudEtlcm5lbElkLCBkYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIC8vIEtlcm5lbElEIC0+IGtlcm5lbEluZm8gbWFwcGluZ1xuICBrZXJuZWxzOiBNYXA8bnVtYmVyLCBLZXJuZWxJbmZvPjtcbiAgcHJpdmF0ZSBjb21tYW5kRW5jb2RlcjogR1BVQ29tbWFuZEVuY29kZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjb21wdXRlUGFzc0VuY29kZXI6IEdQVUNvbXB1dGVQYXNzRW5jb2RlciB8IG51bGwgPSBudWxsO1xuICBtYXhEaXNwYXRjaE51bWJlciA9IDE2O1xuICBwZW5kaW5nRGlzcGF0Y2hOdW1iZXIgPSAwO1xuXG4gIC8vIGluZm8gb2Yga2VybmVscyBwZW5kaW5nIHN1Ym1pc3Npb24gZm9yIGEgc2luZ2xlIGJhdGNoXG4gIHByaXZhdGUgcGVuZGluZ0tlcm5lbHM6IFBlbmRpbmdLZXJuZWxJbmZvW10gPSBbXTtcbiAgLy8gcXVlcnlSZWFkQnVmZmVyIC0+IHBlbmRpbmdLZXJuZWxzIG1hcHBpbmcgZm9yIGFsbCB0aGUgYmF0Y2hlc1xuICBwcml2YXRlIHBlbmRpbmdRdWVyaWVzOiBNYXA8R1BVQnVmZmVyLCBQZW5kaW5nS2VybmVsSW5mb1tdPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBxdWVyeVJlc29sdmVCdWZmZXI/OiBHUFVCdWZmZXI7XG4gIHByaXZhdGUgcXVlcnlTZXQ/OiBHUFVRdWVyeVNldDtcbiAgcHJpdmF0ZSBxdWVyeVRpbWVCYXNlPzogYmlnaW50O1xuICBxdWVyeVR5cGU6IFRpbWVzdGFtcFF1ZXJ5O1xuXG4gIGVudjogRW52O1xuICBzZXNzaW9uU3RhdHVzOiBTZXNzaW9uU3RhdGUgPSAnZGVmYXVsdCc7XG4gIC8qKlxuICAgKiBhIFNlc3Npb25JRCAtPiBDb21tYW5kSW5mb1tdIG1hcHBpbmcuIEl0J3MgdXNlZCB0byByZWNvcmQgYWxsIEdQVSBjb21tYW5kcyBmb3IgY29ycmVzcG9uZGluZyBzZXNzaW9uLlxuICAgKi9cbiAgY2FwdHVyZWRDb21tYW5kTGlzdDogTWFwPG51bWJlciwgQ29tbWFuZEluZm9bXT4gPSBuZXcgTWFwKCk7XG5cbiAgLyoqXG4gICAqIGEgU2Vzc2lvbklEIC0+IFBlbmRpbmdLZXJuZWxJbmZvW10gbWFwcGluZyBmb3IgcHJvZmlsaW5nLlxuICAgKi9cbiAgcHJpdmF0ZSBjYXB0dXJlZFBlbmRpbmdLZXJuZWxzOiBNYXA8bnVtYmVyLCBQZW5kaW5nS2VybmVsSW5mb1tdPiA9IG5ldyBNYXAoKTtcblxuICAvKipcbiAgICogYSBTZXNzaW9uSUQgLT4gYSBNYXAgb2YgKElucHV0T3V0cHV0SW5kZXggLT4gW0lELCBHUFVCdWZmZXJdKSBtYXBwaW5nLlxuICAgKi9cbiAgc2Vzc2lvbkV4dGVybmFsRGF0YU1hcHBpbmc6IE1hcDxudW1iZXIsIE1hcDxudW1iZXIsIFtudW1iZXIsIEdQVUJ1ZmZlcl0+PiA9IG5ldyBNYXAoKTtcblxuICBhc3luYyBpbml0aWFsaXplKGVudjogRW52LCBhZGFwdGVyOiBHUFVBZGFwdGVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5lbnYgPSBlbnY7XG4gICAgY29uc3QgcmVxdWlyZWRGZWF0dXJlczogR1BVRmVhdHVyZU5hbWVbXSA9IFtdO1xuICAgIGNvbnN0IGRldmljZURlc2NyaXB0b3I6IEdQVURldmljZURlc2NyaXB0b3IgPSB7XG4gICAgICByZXF1aXJlZExpbWl0czoge1xuICAgICAgICBtYXhDb21wdXRlV29ya2dyb3VwU3RvcmFnZVNpemU6IGFkYXB0ZXIubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBTdG9yYWdlU2l6ZSxcbiAgICAgICAgbWF4Q29tcHV0ZVdvcmtncm91cHNQZXJEaW1lbnNpb246IGFkYXB0ZXIubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBzUGVyRGltZW5zaW9uLFxuICAgICAgICBtYXhTdG9yYWdlQnVmZmVyQmluZGluZ1NpemU6IGFkYXB0ZXIubGltaXRzLm1heFN0b3JhZ2VCdWZmZXJCaW5kaW5nU2l6ZSxcbiAgICAgICAgbWF4QnVmZmVyU2l6ZTogYWRhcHRlci5saW1pdHMubWF4QnVmZmVyU2l6ZSxcbiAgICAgICAgbWF4Q29tcHV0ZUludm9jYXRpb25zUGVyV29ya2dyb3VwOiBhZGFwdGVyLmxpbWl0cy5tYXhDb21wdXRlSW52b2NhdGlvbnNQZXJXb3JrZ3JvdXAsXG4gICAgICAgIG1heENvbXB1dGVXb3JrZ3JvdXBTaXplWDogYWRhcHRlci5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cFNpemVYLFxuICAgICAgICBtYXhDb21wdXRlV29ya2dyb3VwU2l6ZVk6IGFkYXB0ZXIubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBTaXplWSxcbiAgICAgICAgbWF4Q29tcHV0ZVdvcmtncm91cFNpemVaOiBhZGFwdGVyLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3VwU2l6ZVosXG4gICAgICB9LFxuICAgICAgcmVxdWlyZWRGZWF0dXJlcyxcbiAgICB9O1xuXG4gICAgLy8gVHJ5IHJlcXVpcmluZyBXZWJHUFUgZmVhdHVyZXNcbiAgICBjb25zdCByZXF1aXJlRmVhdHVyZUlmQXZhaWxhYmxlID0gKGZlYXR1cmU6IEdQVUZlYXR1cmVOYW1lKSA9PlxuICAgICAgYWRhcHRlci5mZWF0dXJlcy5oYXMoZmVhdHVyZSkgJiYgcmVxdWlyZWRGZWF0dXJlcy5wdXNoKGZlYXR1cmUpICYmIHRydWU7XG4gICAgLy8gVHJ5IGNocm9taXVtLWV4cGVyaW1lbnRhbC10aW1lc3RhbXAtcXVlcnktaW5zaWRlLXBhc3NlcyBhbmQgZmFsbGJhY2sgdG8gdGltZXN0YW1wLXF1ZXJ5XG4gICAgaWYgKCFyZXF1aXJlRmVhdHVyZUlmQXZhaWxhYmxlKCdjaHJvbWl1bS1leHBlcmltZW50YWwtdGltZXN0YW1wLXF1ZXJ5LWluc2lkZS1wYXNzZXMnIGFzIEdQVUZlYXR1cmVOYW1lKSkge1xuICAgICAgcmVxdWlyZUZlYXR1cmVJZkF2YWlsYWJsZSgndGltZXN0YW1wLXF1ZXJ5Jyk7XG4gICAgfVxuICAgIHJlcXVpcmVGZWF0dXJlSWZBdmFpbGFibGUoJ3NoYWRlci1mMTYnKTtcbiAgICAvLyBUcnkgc3ViZ3JvdXBzXG4gICAgcmVxdWlyZUZlYXR1cmVJZkF2YWlsYWJsZSgnc3ViZ3JvdXBzJyBhcyBHUFVGZWF0dXJlTmFtZSk7XG5cbiAgICB0aGlzLmRldmljZSA9IGF3YWl0IGFkYXB0ZXIucmVxdWVzdERldmljZShkZXZpY2VEZXNjcmlwdG9yKTtcbiAgICB0aGlzLmFkYXB0ZXJJbmZvID0gbmV3IEFkYXB0ZXJJbmZvSW1wbChhZGFwdGVyLmluZm8gfHwgKGF3YWl0IGFkYXB0ZXIucmVxdWVzdEFkYXB0ZXJJbmZvKCkpKTtcbiAgICB0aGlzLmdwdURhdGFNYW5hZ2VyID0gY3JlYXRlR3B1RGF0YU1hbmFnZXIodGhpcyk7XG4gICAgdGhpcy5wcm9ncmFtTWFuYWdlciA9IG5ldyBQcm9ncmFtTWFuYWdlcih0aGlzKTtcbiAgICB0aGlzLmtlcm5lbHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5rZXJuZWxQZXJzaXN0ZW50RGF0YSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmtlcm5lbEN1c3RvbURhdGEgPSBuZXcgTWFwKCk7XG5cbiAgICAvLyBzZXQgdXAgZmxhZ3MgZm9yIGxvZ2dlclxuICAgIGNvbmZpZ3VyZUxvZ2dlcihlbnYubG9nTGV2ZWwhLCAhIWVudi5kZWJ1Zyk7XG5cbiAgICAvLyBUT0RPOiBzZXQgdXAgZmxhZ3NcblxuICAgIHRoaXMuZGV2aWNlLm9udW5jYXB0dXJlZGVycm9yID0gKGV2KSA9PiB7XG4gICAgICBpZiAoZXYuZXJyb3IgaW5zdGFuY2VvZiBHUFVWYWxpZGF0aW9uRXJyb3IpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5lcnJvcihgQW4gdW5jYXVnaHQgV2ViR1BVIHZhbGlkYXRpb24gZXJyb3Igd2FzIHJhaXNlZDogJHtldi5lcnJvci5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcy5lbnYud2ViZ3B1LCAnZGV2aWNlJywge1xuICAgICAgdmFsdWU6IHRoaXMuZGV2aWNlLFxuICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwgLy8gQWxsb3cgZGVsZXRpb24gd2hlbiBkZXZpY2UgaXMgZGVzdHJveWVkXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMuZW52LndlYmdwdSwgJ2FkYXB0ZXInLCB7XG4gICAgICB2YWx1ZTogYWRhcHRlcixcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgLy8gaW5pdCBxdWVyeVR5cGUsIHdoaWNoIGlzIG5lY2Vzc2FyeSBmb3IgSW5mZXJlbmNlU2Vzc2lvbi5jcmVhdGVcbiAgICB0aGlzLnNldFF1ZXJ5VHlwZSgpO1xuICB9XG5cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIHRoaXMucXVlcnlTZXQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLnF1ZXJ5U2V0LmRlc3Ryb3koKTtcbiAgICB9XG4gICAgdGhpcy5ncHVEYXRhTWFuYWdlci5kaXNwb3NlKCk7XG5cbiAgICAvLyBDbGVhciB0aGUgZGV2aWNlIHJlZmVyZW5jZSB3aGVuIGl0J3MgbG9zdCB0byBhbGxvdyBuZXcgc2Vzc2lvbnMgdG8gY3JlYXRlIGEgZnJlc2ggZGV2aWNlXG4gICAgLy8gVGhpcyBoYW5kbGVzIHRoZSBjYXNlIHdoZXJlIHByZXNlcnZlX2RldmljZT1mYWxzZSAoZGVmYXVsdCkgY2F1c2VzIHRoZSBDKysgc2lkZSB0byBkZXN0cm95IHRoZSBkZXZpY2VcbiAgICBpZiAodGhpcy5kZXZpY2UgJiYgdGhpcy5lbnY/LndlYmdwdSkge1xuICAgICAgdm9pZCB0aGlzLmRldmljZS5sb3N0LnRoZW4oKCkgPT4ge1xuICAgICAgICBkZWxldGUgKHRoaXMuZW52LndlYmdwdSBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5kZXZpY2U7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBnZXRDb21tYW5kRW5jb2RlcigpOiBHUFVDb21tYW5kRW5jb2RlciB7XG4gICAgaWYgKCF0aGlzLmNvbW1hbmRFbmNvZGVyKSB7XG4gICAgICB0aGlzLmNvbW1hbmRFbmNvZGVyID0gdGhpcy5kZXZpY2UuY3JlYXRlQ29tbWFuZEVuY29kZXIoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY29tbWFuZEVuY29kZXI7XG4gIH1cblxuICBnZXRDb21wdXRlUGFzc0VuY29kZXIoKTogR1BVQ29tcHV0ZVBhc3NFbmNvZGVyIHtcbiAgICBpZiAoIXRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyKSB7XG4gICAgICBjb25zdCBjb21tYW5kRW5jb2RlciA9IHRoaXMuZ2V0Q29tbWFuZEVuY29kZXIoKTtcbiAgICAgIGNvbnN0IGNvbXB1dGVQYXNzRGVzY3JpcHRvcjogR1BVQ29tcHV0ZVBhc3NEZXNjcmlwdG9yID0ge307XG5cbiAgICAgIGlmICh0aGlzLnF1ZXJ5VHlwZSA9PT0gJ2F0LXBhc3NlcycpIHtcbiAgICAgICAgY29tcHV0ZVBhc3NEZXNjcmlwdG9yLnRpbWVzdGFtcFdyaXRlcyA9IHtcbiAgICAgICAgICBxdWVyeVNldDogdGhpcy5xdWVyeVNldCEsXG4gICAgICAgICAgYmVnaW5uaW5nT2ZQYXNzV3JpdGVJbmRleDogdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgKiAyLFxuICAgICAgICAgIGVuZE9mUGFzc1dyaXRlSW5kZXg6IHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMiArIDEsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyID0gY29tbWFuZEVuY29kZXIuYmVnaW5Db21wdXRlUGFzcyhjb21wdXRlUGFzc0Rlc2NyaXB0b3IpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jb21wdXRlUGFzc0VuY29kZXI7XG4gIH1cblxuICBlbmRDb21wdXRlUGFzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jb21wdXRlUGFzc0VuY29kZXIpIHtcbiAgICAgIHRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyLmVuZCgpO1xuICAgICAgdGhpcy5jb21wdXRlUGFzc0VuY29kZXIgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGZsdXNoKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb21tYW5kRW5jb2Rlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIFRSQUNFX0ZVTkNfQkVHSU4oKTtcblxuICAgIHRoaXMuZW5kQ29tcHV0ZVBhc3MoKTtcbiAgICBsZXQgcXVlcnlSZWFkQnVmZmVyOiBHUFVCdWZmZXI7XG4gICAgaWYgKHRoaXMucXVlcnlUeXBlICE9PSAnbm9uZScpIHtcbiAgICAgIHRoaXMuY29tbWFuZEVuY29kZXIucmVzb2x2ZVF1ZXJ5U2V0KFxuICAgICAgICB0aGlzLnF1ZXJ5U2V0ISxcbiAgICAgICAgMCxcbiAgICAgICAgdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgKiAyLFxuICAgICAgICB0aGlzLnF1ZXJ5UmVzb2x2ZUJ1ZmZlciEsXG4gICAgICAgIDAsXG4gICAgICApO1xuXG4gICAgICBxdWVyeVJlYWRCdWZmZXIgPSB0aGlzLmRldmljZS5jcmVhdGVCdWZmZXIoXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgICAgIHsgc2l6ZTogdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgKiAyICogOCwgdXNhZ2U6IEdQVUJ1ZmZlclVzYWdlLk1BUF9SRUFEIHwgR1BVQnVmZmVyVXNhZ2UuQ09QWV9EU1QgfSxcbiAgICAgICk7XG5cbiAgICAgIHRoaXMucGVuZGluZ1F1ZXJpZXMuc2V0KHF1ZXJ5UmVhZEJ1ZmZlciwgdGhpcy5wZW5kaW5nS2VybmVscyk7XG4gICAgICB0aGlzLnBlbmRpbmdLZXJuZWxzID0gW107XG4gICAgICB0aGlzLmNvbW1hbmRFbmNvZGVyLmNvcHlCdWZmZXJUb0J1ZmZlcihcbiAgICAgICAgdGhpcy5xdWVyeVJlc29sdmVCdWZmZXIhLFxuICAgICAgICAwLFxuICAgICAgICBxdWVyeVJlYWRCdWZmZXIsXG4gICAgICAgIDAsXG4gICAgICAgIHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMiAqIDgsXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuZGV2aWNlLnF1ZXVlLnN1Ym1pdChbdGhpcy5jb21tYW5kRW5jb2Rlci5maW5pc2goKV0pO1xuICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIucmVmcmVzaFBlbmRpbmdCdWZmZXJzKCk7XG4gICAgdGhpcy5jb21tYW5kRW5jb2RlciA9IG51bGw7XG4gICAgdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgPSAwO1xuXG4gICAgaWYgKHRoaXMucXVlcnlUeXBlICE9PSAnbm9uZScpIHtcbiAgICAgIHZvaWQgcXVlcnlSZWFkQnVmZmVyIS5tYXBBc3luYyhHUFVNYXBNb2RlLlJFQUQpLnRoZW4oKCkgPT4ge1xuICAgICAgICBjb25zdCBtYXBwZWREYXRhID0gbmV3IEJpZ1VpbnQ2NEFycmF5KHF1ZXJ5UmVhZEJ1ZmZlci5nZXRNYXBwZWRSYW5nZSgpKTtcbiAgICAgICAgY29uc3QgcGVuZGluZ0tlcm5lbHMgPSB0aGlzLnBlbmRpbmdRdWVyaWVzLmdldChxdWVyeVJlYWRCdWZmZXIpITtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXBwZWREYXRhLmxlbmd0aCAvIDI7IGkrKykge1xuICAgICAgICAgIGNvbnN0IHBlbmRpbmdLZXJuZWxJbmZvID0gcGVuZGluZ0tlcm5lbHNbaV07XG4gICAgICAgICAgY29uc3Qga2VybmVsSWQgPSBwZW5kaW5nS2VybmVsSW5mby5rZXJuZWxJZDtcbiAgICAgICAgICBjb25zdCBrZXJuZWxJbmZvID0gdGhpcy5rZXJuZWxzLmdldChrZXJuZWxJZCkhO1xuICAgICAgICAgIGNvbnN0IGtlcm5lbFR5cGUgPSBrZXJuZWxJbmZvLmtlcm5lbFR5cGU7XG4gICAgICAgICAgY29uc3Qga2VybmVsTmFtZSA9IGtlcm5lbEluZm8ua2VybmVsTmFtZTtcbiAgICAgICAgICBjb25zdCBwcm9ncmFtTmFtZSA9IHBlbmRpbmdLZXJuZWxJbmZvLnByb2dyYW1OYW1lO1xuICAgICAgICAgIGNvbnN0IGlucHV0VGVuc29yVmlld3MgPSBwZW5kaW5nS2VybmVsSW5mby5pbnB1dFRlbnNvclZpZXdzO1xuICAgICAgICAgIGNvbnN0IG91dHB1dFRlbnNvclZpZXdzID0gcGVuZGluZ0tlcm5lbEluZm8ub3V0cHV0VGVuc29yVmlld3M7XG4gICAgICAgICAgY29uc3Qgc3RhcnRUaW1lVTY0ID0gbWFwcGVkRGF0YVtpICogMl07XG4gICAgICAgICAgY29uc3QgZW5kVGltZVU2NCA9IG1hcHBlZERhdGFbaSAqIDIgKyAxXTtcblxuICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5xdWVyeVRpbWVCYXNlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhpcy5xdWVyeVRpbWVCYXNlID0gc3RhcnRUaW1lVTY0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IE51bWJlcihzdGFydFRpbWVVNjQgLSB0aGlzLnF1ZXJ5VGltZUJhc2UpO1xuICAgICAgICAgIGNvbnN0IGVuZFRpbWUgPSBOdW1iZXIoZW5kVGltZVU2NCAtIHRoaXMucXVlcnlUaW1lQmFzZSk7XG5cbiAgICAgICAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKHN0YXJ0VGltZSkgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKGVuZFRpbWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5jb3JyZWN0IHRpbWVzdGFtcCByYW5nZScpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0aGlzLmVudi53ZWJncHUucHJvZmlsaW5nPy5vbmRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuZW52LndlYmdwdS5wcm9maWxpbmcub25kYXRhKHtcbiAgICAgICAgICAgICAgdmVyc2lvbjogMSxcbiAgICAgICAgICAgICAgaW5wdXRzTWV0YWRhdGE6IGlucHV0VGVuc29yVmlld3MubWFwKCh2YWx1ZSkgPT4gKHtcbiAgICAgICAgICAgICAgICBkaW1zOiB2YWx1ZS5kaW1zLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyh2YWx1ZS5kYXRhVHlwZSksXG4gICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgICAgb3V0cHV0c01ldGFkYXRhOiBvdXRwdXRUZW5zb3JWaWV3cy5tYXAoKHZhbHVlKSA9PiAoe1xuICAgICAgICAgICAgICAgIGRpbXM6IHZhbHVlLmRpbXMsXG4gICAgICAgICAgICAgICAgZGF0YVR5cGU6IHRlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nKHZhbHVlLmRhdGFUeXBlKSxcbiAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgICBrZXJuZWxJZCxcbiAgICAgICAgICAgICAga2VybmVsVHlwZSxcbiAgICAgICAgICAgICAga2VybmVsTmFtZSxcbiAgICAgICAgICAgICAgcHJvZ3JhbU5hbWUsXG4gICAgICAgICAgICAgIHN0YXJ0VGltZSxcbiAgICAgICAgICAgICAgZW5kVGltZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBpZiBubyBjYWxsYmFjayBpcyBwcm92aWRlZCwgcHJpbnQgdGhlIHByb2ZpbGluZyBtZXNzYWdlIHRvIGNvbnNvbGVcbiAgICAgICAgICAgIGxldCBpbnB1dFNoYXBlcyA9ICcnO1xuICAgICAgICAgICAgaW5wdXRUZW5zb3JWaWV3cy5mb3JFYWNoKCh2YWx1ZSwgaSkgPT4ge1xuICAgICAgICAgICAgICBpbnB1dFNoYXBlcyArPSBgaW5wdXRbJHtpfV06IFske3ZhbHVlLmRpbXN9XSB8ICR7dGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcodmFsdWUuZGF0YVR5cGUpfSwgYDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgbGV0IG91dHB1dFNoYXBlcyA9ICcnO1xuICAgICAgICAgICAgb3V0cHV0VGVuc29yVmlld3MuZm9yRWFjaCgodmFsdWUsIGkpID0+IHtcbiAgICAgICAgICAgICAgb3V0cHV0U2hhcGVzICs9IGBvdXRwdXRbJHtpfV06IFske3ZhbHVlLmRpbXN9XSB8ICR7dGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcodmFsdWUuZGF0YVR5cGUpfSwgYDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICBgW3Byb2ZpbGluZ10ga2VybmVsIFwiJHtrZXJuZWxJZH18JHtrZXJuZWxUeXBlfXwke2tlcm5lbE5hbWV9fCR7cHJvZ3JhbU5hbWV9XCIgJHtpbnB1dFNoYXBlc30ke1xuICAgICAgICAgICAgICAgIG91dHB1dFNoYXBlc1xuICAgICAgICAgICAgICB9c3RhcnQgdGltZTogJHtzdGFydFRpbWV9IG5zLCBleGVjdXRpb24gdGltZTogJHtlbmRUaW1lIC0gc3RhcnRUaW1lfSBuc2AsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBUUkFDRSgnR1BVJywgYCR7cHJvZ3JhbU5hbWV9Ojoke3N0YXJ0VGltZVU2NH06OiR7ZW5kVGltZVU2NH1gKTtcbiAgICAgICAgfVxuICAgICAgICBxdWVyeVJlYWRCdWZmZXIudW5tYXAoKTtcbiAgICAgICAgdGhpcy5wZW5kaW5nUXVlcmllcy5kZWxldGUocXVlcnlSZWFkQnVmZmVyKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBUUkFDRV9GVU5DX0VORCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIHJ1biBhIFdlYkdQVSBwcm9ncmFtLlxuICAgKiBAcGFyYW0gcHJvZ3JhbSBhIFByb2dyYW1JbmZvIGluc3RhbmNlXG4gICAqIEBwYXJhbSBpbnB1dFRlbnNvclZpZXdzIGEgVGVuc29yVmlldyBhcnJheS4gZWFjaCBlbGVtZW50IHJlcHJlc2VudHMgYSB2YWx1ZSBhbHJlYWR5IGV4aXN0cyBpbiBHUFUuXG4gICAqIEBwYXJhbSBvdXRwdXRJbmRpY2VzIGFuIGluZGljZXMgYXJyYXkuIGVhY2ggZWxlbWVudCBjYW4gYmUgZWl0aGVyIC0xICh0ZW1wb3JhcnkgZGF0YSksIC0yIChwZXJzaXN0ZW50IGRhdGEpIG9yIGFuXG4gICAqIGluZGV4IHRvIHRoZSBrZXJuZWwncyBvdXRwdXQuXG4gICAqIEBwYXJhbSBjcmVhdGVLZXJuZWxPdXRwdXQgYSBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IGNyZWF0ZSBhIHZhbHVlIHRvIGtlcm5lbCdzIG91dHB1dCB3aXRoIHRoZSBnaXZlbiBpbmRleFxuICAgKiBAcGFyYW0gY3JlYXRlSW50ZXJtZWRpYXRlT3V0cHV0IGEgY2FsbGJhY2sgZnVuY3Rpb24gdGhhdCBjcmVhdGUgYSB2YWx1ZSBhcyBhIGludGVybWVkaWF0ZSB2YWx1ZSwgZWl0aGVyIHRlbXBvcmFyeVxuICAgKiBvciBwZXJzaXN0ZW50IChvd25lZCBieSB0aGUgY3VycmVudCBrZXJuZWwpXG4gICAqIEByZXR1cm5zIGEgVGVuc29yVmlldyBhcnJheSByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC5cbiAgICovXG4gIHJ1bihcbiAgICBwcm9ncmFtOiBQcm9ncmFtSW5mbyxcbiAgICBpbnB1dFRlbnNvclZpZXdzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gICAgb3V0cHV0SW5kaWNlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgY3JlYXRlS2VybmVsT3V0cHV0OiAoaW5kZXg6IG51bWJlciwgZGF0YVR5cGU6IG51bWJlciwgZGltczogcmVhZG9ubHkgbnVtYmVyW10pID0+IFRlbnNvclZpZXcsXG4gICAgY3JlYXRlSW50ZXJtZWRpYXRlT3V0cHV0OiAoZGF0YVR5cGU6IG51bWJlciwgZGltczogcmVhZG9ubHkgbnVtYmVyW10pID0+IFRlbnNvclZpZXcsXG4gICAgb3V0cHV0Q291bnQ6IG51bWJlcixcbiAgKTogVGVuc29yVmlld1tdIHtcbiAgICBUUkFDRV9GVU5DX0JFR0lOKHByb2dyYW0ubmFtZSk7XG4gICAgLy8gY3JlYXRlIGluZm8gZm9yIGlucHV0c1xuICAgIGNvbnN0IGlucHV0RGF0YXM6IEdwdURhdGFbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRUZW5zb3JWaWV3cy5sZW5ndGg7ICsraSkge1xuICAgICAgY29uc3QgZGF0YSA9IGlucHV0VGVuc29yVmlld3NbaV0uZGF0YTtcbiAgICAgIC8vIGlmIHRlbnNvciB2aWV3IGRhdGEgaXMgMCwgaXQgbWVhbnMgdGhlIG91dHB1dCBpcyB6ZXJvLXNpemVkIHRlbnNvciwgYW5kIHRoZXJlIGlzIG5vIEdQVSBkYXRhIGZvciBpdC5cbiAgICAgIGlmIChkYXRhID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZ3B1RGF0YSA9IHRoaXMuZ3B1RGF0YU1hbmFnZXIuZ2V0KGRhdGEpO1xuICAgICAgaWYgKCFncHVEYXRhKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm8gR1BVIGRhdGEgZm9yIGlucHV0OiAke2RhdGF9YCk7XG4gICAgICB9XG4gICAgICBpbnB1dERhdGFzLnB1c2goZ3B1RGF0YSk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBvdXRwdXRzLCBkaXNwYXRjaEdyb3VwLCBwcm9ncmFtVW5pZm9ybXMgfSA9IHByb2dyYW0uZ2V0UnVuRGF0YShpbnB1dFRlbnNvclZpZXdzKTtcblxuICAgIC8vIGNoZWNrIG91dHB1dCBpbmRpY2VzXG4gICAgY29uc3QgdmFsaWRhdGVkT3V0cHV0SW5kaWNlcyA9IG91dHB1dEluZGljZXMubGVuZ3RoID09PSAwID8gb3V0cHV0cy5tYXAoKF8sIGkpID0+IGkpIDogb3V0cHV0SW5kaWNlcztcbiAgICBpZiAodmFsaWRhdGVkT3V0cHV0SW5kaWNlcy5sZW5ndGggIT09IG91dHB1dHMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE91dHB1dCBzaXplICR7dmFsaWRhdGVkT3V0cHV0SW5kaWNlcy5sZW5ndGh9IG11c3QgYmUgZXF1YWwgdG8gJHtvdXRwdXRzLmxlbmd0aH0uYCk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIGluZm8gZm9yIG91dHB1dHNcbiAgICBjb25zdCBvdXRwdXRUZW5zb3JWaWV3czogVGVuc29yVmlld1tdID0gW107XG4gICAgY29uc3Qgb3V0cHV0RGF0YXM6IEdwdURhdGFbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0cy5sZW5ndGg7ICsraSkge1xuICAgICAgLy8gdmFsdWUgLTEgYW5kIC0yIGFyZSB1c2VkIGZvciBjcmVhdGluZyB0ZW1wb3JhcnkgYW5kIHBlcnNpc3RlbnQgb3V0cHV0cy5cbiAgICAgIC8vIHZhbHVlIC0zIGlzIHVzZWQgZm9yIHBsYWNlaG9sZGVyIG91dHB1dC4gU28gLTMsIC0yLCAtMSBhbmQgMCwgMSwgMiwgLi4uIGFyZSB2YWxpZFxuICAgICAgLy8gb3V0cHV0IGluZGljZXMuIHNlZSB0eXBlIGRlZmluaXRpb24gb2YgQ29tcHV0ZUNvbnRleHRJbnB1dHNPdXRwdXRzTWFwcGluZyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgaWYgKFxuICAgICAgICAhTnVtYmVyLmlzSW50ZWdlcih2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldKSB8fFxuICAgICAgICB2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldIDwgLTMgfHxcbiAgICAgICAgdmFsaWRhdGVkT3V0cHV0SW5kaWNlc1tpXSA+PSBvdXRwdXRDb3VudFxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBvdXRwdXQgaW5kZXg6ICR7dmFsaWRhdGVkT3V0cHV0SW5kaWNlc1tpXX1gKTtcbiAgICAgIH1cbiAgICAgIGlmICh2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldID09PSAtMykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGlzVGVtcG9yYXJ5ID0gdmFsaWRhdGVkT3V0cHV0SW5kaWNlc1tpXSA9PT0gLTE7XG4gICAgICBjb25zdCBpc1BlcnNpc3RlbnQgPSB2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldID09PSAtMjtcbiAgICAgIGNvbnN0IHRlbnNvclZpZXcgPVxuICAgICAgICBpc1RlbXBvcmFyeSB8fCBpc1BlcnNpc3RlbnRcbiAgICAgICAgICA/IGNyZWF0ZUludGVybWVkaWF0ZU91dHB1dChvdXRwdXRzW2ldLmRhdGFUeXBlLCBvdXRwdXRzW2ldLmRpbXMpXG4gICAgICAgICAgOiBjcmVhdGVLZXJuZWxPdXRwdXQodmFsaWRhdGVkT3V0cHV0SW5kaWNlc1tpXSwgb3V0cHV0c1tpXS5kYXRhVHlwZSwgb3V0cHV0c1tpXS5kaW1zKTtcbiAgICAgIG91dHB1dFRlbnNvclZpZXdzLnB1c2godGVuc29yVmlldyk7XG4gICAgICAvLyBpZiB0ZW5zb3IgdmlldyBkYXRhIGlzIDAsIGl0IG1lYW5zIHRoZSBvdXRwdXQgaXMgemVyby1zaXplZCB0ZW5zb3IsIGFuZCB0aGVyZSBpcyBubyBHUFUgZGF0YSBmb3IgaXQuXG4gICAgICBpZiAodGVuc29yVmlldy5kYXRhID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZ3B1RGF0YSA9IHRoaXMuZ3B1RGF0YU1hbmFnZXIuZ2V0KHRlbnNvclZpZXcuZGF0YSk7XG4gICAgICBpZiAoIWdwdURhdGEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBubyBHUFUgZGF0YSBmb3Igb3V0cHV0OiAke3RlbnNvclZpZXcuZGF0YX1gKTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1RlbXBvcmFyeSkge1xuICAgICAgICB0aGlzLnRlbXBvcmFyeURhdGEucHVzaChncHVEYXRhKTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1BlcnNpc3RlbnQpIHtcbiAgICAgICAgbGV0IHBlcnNpc3RlbnREYXRhID0gdGhpcy5rZXJuZWxQZXJzaXN0ZW50RGF0YS5nZXQodGhpcy5jdXJyZW50S2VybmVsSWQhKTtcbiAgICAgICAgaWYgKCFwZXJzaXN0ZW50RGF0YSkge1xuICAgICAgICAgIHBlcnNpc3RlbnREYXRhID0gW107XG4gICAgICAgICAgdGhpcy5rZXJuZWxQZXJzaXN0ZW50RGF0YS5zZXQodGhpcy5jdXJyZW50S2VybmVsSWQhLCBwZXJzaXN0ZW50RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgcGVyc2lzdGVudERhdGEucHVzaChncHVEYXRhKTtcbiAgICAgIH1cbiAgICAgIG91dHB1dERhdGFzLnB1c2goZ3B1RGF0YSk7XG4gICAgfVxuXG4gICAgLy8gd2hlbiB0aGVyZSBhcmUgYW55IHplcm8tc2l6ZWQgdGVuc29yIGluIHRoZSBpbnB1dHMgb3Igb3V0cHV0cywgd2Ugc2hvdWxkIHJlcG9ydCBlcnJvciB1bmxlc3MgYWxsIG91dHB1dHMgYXJlXG4gICAgLy8gemVyby1zaXplZCB0ZW5zb3JzLlxuICAgIGlmIChpbnB1dERhdGFzLmxlbmd0aCAhPT0gaW5wdXRUZW5zb3JWaWV3cy5sZW5ndGggfHwgb3V0cHV0RGF0YXMubGVuZ3RoICE9PSBvdXRwdXRUZW5zb3JWaWV3cy5sZW5ndGgpIHtcbiAgICAgIC8vIGlmIGFsbCBvdXRwdXRzIGFyZSB6ZXJvLXNpemVkIHRlbnNvcnMsIHRoZXJlIGlzIG5vIG5lZWQgdG8gcnVuIHRoZSBwcm9ncmFtLlxuICAgICAgaWYgKG91dHB1dERhdGFzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBUUkFDRV9GVU5DX0VORChwcm9ncmFtLm5hbWUpO1xuICAgICAgICByZXR1cm4gb3V0cHV0VGVuc29yVmlld3M7XG4gICAgICB9XG4gICAgICAvLyBpZiBzb21lIG91dHB1dHMgYXJlIHplcm8tc2l6ZWQgdGVuc29ycywgcmVwb3J0IGFuIGVycm9yLlxuICAgICAgLy9cbiAgICAgIC8vIFRPRE86IHNvIGZhciB3ZSBkb24ndCBzZWUgYW55IHVzZSBjYXNlIHRoYXQgb3V0cHV0cyBpbmNsdWRlIGJvdGggemVyby1zaXplZCB0ZW5zb3JzIGFuZCBub24temVyby1zaXplZCB0ZW5zb3JzLlxuICAgICAgLy8gSWYgd2Ugc2VlIHN1Y2ggdXNlIGNhc2UsIHdlIG5lZWQgdG8gbWFrZSBhIGNoYW5nZSBoZXJlIHRvIHN1cHBvcnQgaXQuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBQcm9ncmFtICR7cHJvZ3JhbS5uYW1lfSBoYXMgemVyby1zaXplZCB0ZW5zb3IocykgaW4gaW5wdXRzIG9yIG91dHB1dHMuIFRoaXMgaXMgbm90IHN1cHBvcnRlZCBub3cuYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gbG9hZCB1bmlmb3Jtc1xuICAgIC8vIFRPRE86IGFkZCBjYWNoZSBmb3IgdW5pZm9ybSAoaXMgaXQgbmVjZXNzYXJ5PylcbiAgICAvL1xuICAgIGxldCB1bmlmb3JtQnVmZmVyQmluZGluZzogR1BVQmluZGluZ1Jlc291cmNlIHwgdW5kZWZpbmVkO1xuICAgIGlmIChwcm9ncmFtVW5pZm9ybXMpIHtcbiAgICAgIGxldCBjdXJyZW50T2Zmc2V0ID0gMDtcbiAgICAgIGNvbnN0IG9mZnNldHM6IG51bWJlcltdID0gW107XG5cbiAgICAgIHByb2dyYW1Vbmlmb3Jtcy5mb3JFYWNoKCh2KSA9PiB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB0eXBlb2Ygdi5kYXRhID09PSAnbnVtYmVyJyA/IFt2LmRhdGFdIDogdi5kYXRhO1xuICAgICAgICBpZiAoZGF0YS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gaHR0cHM6Ly93d3cudzMub3JnL1RSL1dHU0wvI2FsaWdub2ZcbiAgICAgICAgY29uc3Qgc2l6ZU9mRWxlbWVudCA9IHYudHlwZSA9PT0gRGF0YVR5cGUuZmxvYXQxNiA/IDIgOiA0O1xuICAgICAgICBsZXQgc2l6ZU9mVmVjT3JNYXQ7XG4gICAgICAgIGxldCBiYXNlQWxpZ25tZW50O1xuICAgICAgICBpZiAodi50eXBlID09PSBEYXRhVHlwZS5mbG9hdDE2KSB7XG4gICAgICAgICAgYmFzZUFsaWdubWVudCA9IGRhdGEubGVuZ3RoID4gNCA/IDE2IDogZGF0YS5sZW5ndGggPiAyID8gOCA6IGRhdGEubGVuZ3RoICogc2l6ZU9mRWxlbWVudDtcbiAgICAgICAgICBzaXplT2ZWZWNPck1hdCA9IGRhdGEubGVuZ3RoID4gNCA/IDE2IDogc2l6ZU9mRWxlbWVudCAqIGRhdGEubGVuZ3RoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJhc2VBbGlnbm1lbnQgPSBkYXRhLmxlbmd0aCA8PSAyID8gZGF0YS5sZW5ndGggKiBzaXplT2ZFbGVtZW50IDogMTY7XG4gICAgICAgICAgc2l6ZU9mVmVjT3JNYXQgPSAxNjtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50T2Zmc2V0ID0gTWF0aC5jZWlsKGN1cnJlbnRPZmZzZXQgLyBiYXNlQWxpZ25tZW50KSAqIGJhc2VBbGlnbm1lbnQ7XG4gICAgICAgIG9mZnNldHMucHVzaChjdXJyZW50T2Zmc2V0KTtcbiAgICAgICAgLy8gRm9yIG5vbi1mbG9hdDE2IHR5cGUsIHdoZW4gZGF0YS5sZW5ndGggPiA0LCB0aGUgdW5pZm9ybSB2YXJpYWJsZSBpcyBvZiB0eXBlIGFycmF5PHZlYzQ8aTMyfHUzMnxmMzI+LE4+LCB3aGVyZVxuICAgICAgICAvLyBOID0gTWF0aC5jZWlsKGRhdGEubGVuZ3RoIC8gNCkgYW5kIFNpemVPZih2ZWM0PGkzMnx1MzJ8ZjMyPikgPSAxNi4gVGhlIHRvdGFsIGJ5dGUgbGVuZ3RoIGlzIE4gKlxuICAgICAgICAvLyBTaXplT2YodmVjNDxpMzJ8dTMyfGYzMj4pLiBGb3IgZmxvYXQxNiB0eXBlLCB3aGVuIGRhdGEubGVuZ3RoID4gNCwgdGhlIHVuaWZvcm0gdmFyaWFibGUgaXMgb2YgdHlwZVxuICAgICAgICAvLyBhcnJheTxtYXQyeDQ8ZjE2PixOPiwgd2hlcmUgTiA9IE1hdGguY2VpbChkYXRhLmxlbmd0aCAvIDgpIGFuZCBTaXplT2YobWF0Mng0PGYxNj4pID0gMTYuIFRoZSB0b3RhbCBieXRlXG4gICAgICAgIC8vIGxlbmd0aCBpcyBOICogU2l6ZU9mKG1hdDJ4NDxmMTY+KS5cbiAgICAgICAgY29uc3QgZWxlbWVudFBlclZlY09yTWF0ID0gdi50eXBlID09PSBEYXRhVHlwZS5mbG9hdDE2ID8gOCA6IDQ7XG4gICAgICAgIGN1cnJlbnRPZmZzZXQgKz1cbiAgICAgICAgICBkYXRhLmxlbmd0aCA+IDQgPyBNYXRoLmNlaWwoZGF0YS5sZW5ndGggLyBlbGVtZW50UGVyVmVjT3JNYXQpICogc2l6ZU9mVmVjT3JNYXQgOiBkYXRhLmxlbmd0aCAqIHNpemVPZkVsZW1lbnQ7XG4gICAgICB9KTtcblxuICAgICAgLy8gTWVldCBhbGlnbm1lbnQgb2Ygc3RydWN0IGhlcmU6IGh0dHBzOi8vd3d3LnczLm9yZy9UUi9XR1NMLyNhbGlnbm1lbnQtYW5kLXNpemUuIEZvciBzaW1wbGljaXR5LCBzZXRcbiAgICAgIC8vIG1heEFsaWdubWVudE9mRmllbGQgdG8gMTYgc2luY2UgdGhlIHVuZGVybHlpbmcgYnVmZmVyIGhhcyBiZWVuIHJvdW5kZWQgdXAgdG8gMTYuXG4gICAgICBjb25zdCBtYXhBbGlnbm1lbnRPZkZpZWxkID0gMTY7XG4gICAgICBjdXJyZW50T2Zmc2V0ID0gTWF0aC5jZWlsKGN1cnJlbnRPZmZzZXQgLyBtYXhBbGlnbm1lbnRPZkZpZWxkKSAqIG1heEFsaWdubWVudE9mRmllbGQ7XG4gICAgICBjb25zdCBhcnJheUJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcihjdXJyZW50T2Zmc2V0KTtcbiAgICAgIHByb2dyYW1Vbmlmb3Jtcy5mb3JFYWNoKCh2LCBpKSA9PiB7XG4gICAgICAgIGNvbnN0IG9mZnNldCA9IG9mZnNldHNbaV07XG4gICAgICAgIGNvbnN0IGRhdGEgPSB0eXBlb2Ygdi5kYXRhID09PSAnbnVtYmVyJyA/IFt2LmRhdGFdIDogdi5kYXRhO1xuICAgICAgICBpZiAodi50eXBlID09PSBEYXRhVHlwZS5pbnQzMikge1xuICAgICAgICAgIG5ldyBJbnQzMkFycmF5KGFycmF5QnVmZmVyLCBvZmZzZXQsIGRhdGEubGVuZ3RoKS5zZXQoZGF0YSk7XG4gICAgICAgIH0gZWxzZSBpZiAodi50eXBlID09PSBEYXRhVHlwZS51aW50MzIpIHtcbiAgICAgICAgICBuZXcgVWludDMyQXJyYXkoYXJyYXlCdWZmZXIsIG9mZnNldCwgZGF0YS5sZW5ndGgpLnNldChkYXRhKTtcbiAgICAgICAgfSBlbHNlIGlmICh2LnR5cGUgPT09IERhdGFUeXBlLmZsb2F0MTYpIHtcbiAgICAgICAgICBuZXcgVWludDE2QXJyYXkoYXJyYXlCdWZmZXIsIG9mZnNldCwgZGF0YS5sZW5ndGgpLnNldChkYXRhKTtcbiAgICAgICAgfSBlbHNlIGlmICh2LnR5cGUgPT09IERhdGFUeXBlLmZsb2F0KSB7XG4gICAgICAgICAgbmV3IEZsb2F0MzJBcnJheShhcnJheUJ1ZmZlciwgb2Zmc2V0LCBkYXRhLmxlbmd0aCkuc2V0KGRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgdW5pZm9ybSB0eXBlOiAke3RlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nKHYudHlwZSl9YCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB1bmlmb3JtQnVmZmVyRGF0YSA9XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIuY3JlYXRlKGN1cnJlbnRPZmZzZXQsIEdQVUJ1ZmZlclVzYWdlLkNPUFlfRFNUIHwgR1BVQnVmZmVyVXNhZ2UuVU5JRk9STSk7XG4gICAgICB0aGlzLmRldmljZS5xdWV1ZS53cml0ZUJ1ZmZlcih1bmlmb3JtQnVmZmVyRGF0YS5idWZmZXIsIDAsIGFycmF5QnVmZmVyLCAwLCBjdXJyZW50T2Zmc2V0KTtcbiAgICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIucmVsZWFzZSh1bmlmb3JtQnVmZmVyRGF0YS5pZCk7XG4gICAgICB1bmlmb3JtQnVmZmVyQmluZGluZyA9IHsgb2Zmc2V0OiAwLCBzaXplOiBjdXJyZW50T2Zmc2V0LCBidWZmZXI6IHVuaWZvcm1CdWZmZXJEYXRhLmJ1ZmZlciB9O1xuICAgIH1cblxuICAgIGNvbnN0IG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwID0gdGhpcy5wcm9ncmFtTWFuYWdlci5ub3JtYWxpemVEaXNwYXRjaEdyb3VwU2l6ZShkaXNwYXRjaEdyb3VwKTtcbiAgICBjb25zdCBpczFEaW1lbnNpb25EaXNwYXRjaCA9IG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwWzFdID09PSAxICYmIG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwWzJdID09PSAxO1xuICAgIC8vIGdldCBwcm9ncmFtIGluZm9cbiAgICBjb25zdCBrZXkgPSBnZXRQcm9ncmFtSW5mb1VuaXF1ZUtleShwcm9ncmFtLCBpbnB1dFRlbnNvclZpZXdzLCBpczFEaW1lbnNpb25EaXNwYXRjaCk7XG4gICAgbGV0IGFydGlmYWN0ID0gdGhpcy5wcm9ncmFtTWFuYWdlci5nZXRBcnRpZmFjdChrZXkpO1xuICAgIGlmICghYXJ0aWZhY3QpIHtcbiAgICAgIGFydGlmYWN0ID0gdGhpcy5wcm9ncmFtTWFuYWdlci5idWlsZChwcm9ncmFtLCBub3JtYWxpemVkRGlzcGF0Y2hHcm91cCk7XG4gICAgICB0aGlzLnByb2dyYW1NYW5hZ2VyLnNldEFydGlmYWN0KGtleSwgYXJ0aWZhY3QpO1xuICAgICAgTE9HX0RFQlVHKCdpbmZvJywgKCkgPT4gYFthcnRpZmFjdF0ga2V5OiAke2tleX0sIHByb2dyYW1OYW1lOiAke3Byb2dyYW0ubmFtZX1gKTtcbiAgICB9XG5cbiAgICAvLyB2YWxpZGF0ZSB1bmlmb3JtIHZhcmlhYmxlc1xuICAgIGlmIChwcm9ncmFtVW5pZm9ybXMgJiYgYXJ0aWZhY3QudW5pZm9ybVZhcmlhYmxlc0luZm8pIHtcbiAgICAgIGlmIChwcm9ncmFtVW5pZm9ybXMubGVuZ3RoICE9PSBhcnRpZmFjdC51bmlmb3JtVmFyaWFibGVzSW5mby5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBVbmlmb3JtIHZhcmlhYmxlcyBjb3VudCBtaXNtYXRjaDogZXhwZWN0ICR7YXJ0aWZhY3QudW5pZm9ybVZhcmlhYmxlc0luZm8ubGVuZ3RofSwgZ290ICR7XG4gICAgICAgICAgICBwcm9ncmFtVW5pZm9ybXMubGVuZ3RoXG4gICAgICAgICAgfSBpbiBwcm9ncmFtIFwiJHthcnRpZmFjdC5wcm9ncmFtSW5mby5uYW1lfVwiLmAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHByb2dyYW1Vbmlmb3Jtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCB1bmlmb3JtID0gcHJvZ3JhbVVuaWZvcm1zW2ldO1xuICAgICAgICBjb25zdCBhY3R1YWxUeXBlID0gdW5pZm9ybS50eXBlO1xuICAgICAgICBjb25zdCBhY3R1YWxMZW5ndGggPSB0eXBlb2YgdW5pZm9ybS5kYXRhID09PSAnbnVtYmVyJyA/IDEgOiB1bmlmb3JtLmRhdGEubGVuZ3RoO1xuICAgICAgICBjb25zdCBbdHlwZSwgbGVuZ3RoXSA9IGFydGlmYWN0LnVuaWZvcm1WYXJpYWJsZXNJbmZvW2ldO1xuICAgICAgICBpZiAoYWN0dWFsVHlwZSAhPT0gdHlwZSB8fCBhY3R1YWxMZW5ndGggIT09IGxlbmd0aCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBVbmlmb3JtIHZhcmlhYmxlICR7aX0gbWlzbWF0Y2g6IGV4cGVjdCB0eXBlICR7dHlwZX0gd2l0aCBzaXplICR7bGVuZ3RofSwgZ290IHR5cGUgJHtcbiAgICAgICAgICAgICAgYWN0dWFsVHlwZVxuICAgICAgICAgICAgfSB3aXRoIHNpemUgJHthY3R1YWxMZW5ndGh9IGluIHByb2dyYW0gXCIke2FydGlmYWN0LnByb2dyYW1JbmZvLm5hbWV9XCIuYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgTE9HX0RFQlVHKFxuICAgICAgJ2luZm8nLFxuICAgICAgKCkgPT5cbiAgICAgICAgYFtQcm9ncmFtTWFuYWdlcl0gcnVuIFwiJHtwcm9ncmFtLm5hbWV9XCIgKGtleT0ke2tleX0pIHdpdGggJHtub3JtYWxpemVkRGlzcGF0Y2hHcm91cFswXX14JHtcbiAgICAgICAgICBub3JtYWxpemVkRGlzcGF0Y2hHcm91cFsxXVxuICAgICAgICB9eCR7bm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMl19YCxcbiAgICApO1xuXG4gICAgaWYgKHRoaXMucXVlcnlUeXBlICE9PSAnbm9uZScgfHwgdGhpcy5zZXNzaW9uU3RhdHVzID09PSAnY2FwdHVyaW5nJykge1xuICAgICAgY29uc3QgcGVuZGluZ0tlcm5lbEluZm86IFBlbmRpbmdLZXJuZWxJbmZvID0ge1xuICAgICAgICBrZXJuZWxJZDogdGhpcy5jdXJyZW50S2VybmVsSWQhLFxuICAgICAgICBwcm9ncmFtTmFtZTogYXJ0aWZhY3QucHJvZ3JhbUluZm8ubmFtZSxcbiAgICAgICAgaW5wdXRUZW5zb3JWaWV3cyxcbiAgICAgICAgb3V0cHV0VGVuc29yVmlld3MsXG4gICAgICB9O1xuICAgICAgdGhpcy5wZW5kaW5nS2VybmVscy5wdXNoKHBlbmRpbmdLZXJuZWxJbmZvKTtcblxuICAgICAgaWYgKHRoaXMuc2Vzc2lvblN0YXR1cyA9PT0gJ2NhcHR1cmluZycpIHtcbiAgICAgICAgY29uc3Qgc2Vzc2lvblBlbmRpbmdLZXJuZWxzID0gdGhpcy5jYXB0dXJlZFBlbmRpbmdLZXJuZWxzLmdldCh0aGlzLmN1cnJlbnRTZXNzaW9uSWQhKTtcbiAgICAgICAgc2Vzc2lvblBlbmRpbmdLZXJuZWxzIS5wdXNoKHBlbmRpbmdLZXJuZWxJbmZvKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnByb2dyYW1NYW5hZ2VyLnJ1bihhcnRpZmFjdCwgaW5wdXREYXRhcywgb3V0cHV0RGF0YXMsIG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwLCB1bmlmb3JtQnVmZmVyQmluZGluZyk7XG5cbiAgICBUUkFDRV9GVU5DX0VORChwcm9ncmFtLm5hbWUpO1xuICAgIHJldHVybiBvdXRwdXRUZW5zb3JWaWV3cztcbiAgfVxuXG4gIHVwbG9hZChncHVEYXRhSWQ6IG51bWJlciwgZGF0YTogVWludDhBcnJheSk6IHZvaWQge1xuICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIudXBsb2FkKGdwdURhdGFJZCwgZGF0YSk7XG4gIH1cblxuICBtZW1jcHkoc3JjOiBudW1iZXIsIGRzdDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5ncHVEYXRhTWFuYWdlci5tZW1jcHkoc3JjLCBkc3QpO1xuICB9XG5cbiAgYXN5bmMgZG93bmxvYWQoZ3B1RGF0YUlkOiBudW1iZXIsIGdldFRhcmdldEJ1ZmZlcjogKCkgPT4gVWludDhBcnJheSk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIHRoZSB1bmRlcmx5aW5nIGJ1ZmZlciBtYXkgYmUgY2hhbmdlZCBhZnRlciB0aGUgYXN5bmMgZnVuY3Rpb24gaXMgY2FsbGVkLiBzbyB3ZSB1c2UgYSBnZXR0ZXIgZnVuY3Rpb24gdG8gbWFrZSBzdXJlXG4gICAgLy8gdGhlIGJ1ZmZlciBpcyB1cC10by1kYXRlLlxuICAgIGF3YWl0IHRoaXMuZ3B1RGF0YU1hbmFnZXIuZG93bmxvYWQoZ3B1RGF0YUlkLCBnZXRUYXJnZXRCdWZmZXIpO1xuICB9XG5cbiAgYWxsb2Moc2l6ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5ncHVEYXRhTWFuYWdlci5jcmVhdGUoc2l6ZSkuaWQ7XG4gIH1cblxuICBmcmVlKHB0cjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5ncHVEYXRhTWFuYWdlci5yZWxlYXNlKHB0cik7XG4gIH1cblxuICBjcmVhdGVLZXJuZWwoa2VybmVsVHlwZTogc3RyaW5nLCBrZXJuZWxJZDogbnVtYmVyLCBhdHRyaWJ1dGU6IHVua25vd24sIGtlcm5lbE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IG9wID0gV0VCR1BVX09QX1JFU09MVkVfUlVMRVMuZ2V0KGtlcm5lbFR5cGUpO1xuICAgIGlmICghb3ApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihga2VybmVsIG5vdCBpbXBsZW1lbnRlZDogJHtrZXJuZWxUeXBlfWApO1xuICAgIH1cblxuICAgIGNvbnN0IGtlcm5lbEluZm86IEtlcm5lbEluZm8gPSB7XG4gICAgICBrZXJuZWxUeXBlLFxuICAgICAga2VybmVsTmFtZSxcbiAgICAgIGtlcm5lbEVudHJ5OiBvcFswXSxcbiAgICAgIGF0dHJpYnV0ZXM6IFtvcFsxXSwgYXR0cmlidXRlXSxcbiAgICB9O1xuICAgIHRoaXMua2VybmVscy5zZXQoa2VybmVsSWQsIGtlcm5lbEluZm8pO1xuICB9XG5cbiAgcmVsZWFzZUtlcm5lbChrZXJuZWxJZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgcGVyc2lzdGVudERhdGEgPSB0aGlzLmtlcm5lbFBlcnNpc3RlbnREYXRhLmdldChrZXJuZWxJZCk7XG4gICAgaWYgKHBlcnNpc3RlbnREYXRhKSB7XG4gICAgICBmb3IgKGNvbnN0IGRhdGEgb2YgcGVyc2lzdGVudERhdGEpIHtcbiAgICAgICAgdGhpcy5ncHVEYXRhTWFuYWdlci5yZWxlYXNlKGRhdGEuaWQpO1xuICAgICAgfVxuICAgICAgdGhpcy5rZXJuZWxQZXJzaXN0ZW50RGF0YS5kZWxldGUoa2VybmVsSWQpO1xuICAgIH1cblxuICAgIHRoaXMua2VybmVsQ3VzdG9tRGF0YS5kZWxldGUoa2VybmVsSWQpO1xuICAgIHRoaXMua2VybmVscy5kZWxldGUoa2VybmVsSWQpO1xuICB9XG5cbiAgY29tcHV0ZUtlcm5lbChrZXJuZWxJZDogbnVtYmVyLCBjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgZXJyb3JzOiBBcnJheTxQcm9taXNlPHN0cmluZyB8IG51bGw+Pik6IG51bWJlciB7XG4gICAgY29uc3Qga2VybmVsID0gdGhpcy5rZXJuZWxzLmdldChrZXJuZWxJZCk7XG4gICAgaWYgKCFrZXJuZWwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihga2VybmVsIG5vdCBjcmVhdGVkOiAke2tlcm5lbElkfWApO1xuICAgIH1cbiAgICBjb25zdCBrZXJuZWxUeXBlID0ga2VybmVsLmtlcm5lbFR5cGU7XG4gICAgY29uc3Qga2VybmVsTmFtZSA9IGtlcm5lbC5rZXJuZWxOYW1lO1xuICAgIGNvbnN0IGtlcm5lbEVudHJ5ID0ga2VybmVsLmtlcm5lbEVudHJ5O1xuICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBrZXJuZWwuYXR0cmlidXRlcztcbiAgICBpZiAodGhpcy5jdXJyZW50S2VybmVsSWQgIT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihga2VybmVsIFwiWyR7a2VybmVsVHlwZX1dICR7a2VybmVsTmFtZX1cIiBpcyBub3QgYWxsb3dlZCB0byBiZSBjYWxsZWQgcmVjdXJzaXZlbHlgKTtcbiAgICB9XG4gICAgdGhpcy5jdXJyZW50S2VybmVsSWQgPSBrZXJuZWxJZDtcblxuICAgIC8vIHBhcnNlIGF0dHJpYnV0ZXMgaWYgbmVjZXNzYXJ5XG4gICAgaWYgKGF0dHJpYnV0ZXNbMF0pIHtcbiAgICAgIGF0dHJpYnV0ZXNbMV0gPSBhdHRyaWJ1dGVzWzBdKGF0dHJpYnV0ZXNbMV0pO1xuICAgICAgYXR0cmlidXRlc1swXSA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBMT0dfREVCVUcoJ2luZm8nLCAoKSA9PiBgW1dlYkdQVV0gU3RhcnQgdG8gcnVuIGtlcm5lbCBcIlske2tlcm5lbFR5cGV9XSAke2tlcm5lbE5hbWV9XCIuLi5gKTtcblxuICAgIGNvbnN0IHVzZUVycm9yU2NvcGUgPSB0aGlzLmVudi5kZWJ1ZztcblxuICAgIHRoaXMudGVtcG9yYXJ5RGF0YSA9IFtdO1xuICAgIHRyeSB7XG4gICAgICBpZiAodXNlRXJyb3JTY29wZSkge1xuICAgICAgICB0aGlzLmRldmljZS5wdXNoRXJyb3JTY29wZSgndmFsaWRhdGlvbicpO1xuICAgICAgfVxuXG4gICAgICBrZXJuZWxFbnRyeShjb250ZXh0LCBhdHRyaWJ1dGVzWzFdKTtcbiAgICAgIHJldHVybiAwOyAvLyBPUlRfT0tcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBlcnJvcnMucHVzaChQcm9taXNlLnJlc29sdmUoYFtXZWJHUFVdIEtlcm5lbCBcIlske2tlcm5lbFR5cGV9XSAke2tlcm5lbE5hbWV9XCIgZmFpbGVkLiAke2V9YCkpO1xuICAgICAgcmV0dXJuIDE7IC8vIE9SVF9GQUlMXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmICh1c2VFcnJvclNjb3BlKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKFxuICAgICAgICAgIHRoaXMuZGV2aWNlXG4gICAgICAgICAgICAucG9wRXJyb3JTY29wZSgpXG4gICAgICAgICAgICAudGhlbigoZXJyKSA9PlxuICAgICAgICAgICAgICBlcnIgPyBgR1BVIHZhbGlkYXRpb24gZXJyb3IgZm9yIGtlcm5lbCBcIlske2tlcm5lbFR5cGV9XSAke2tlcm5lbE5hbWV9XCI6ICR7ZXJyLm1lc3NhZ2V9YCA6IG51bGwsXG4gICAgICAgICAgICApLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGRhdGEgb2YgdGhpcy50ZW1wb3JhcnlEYXRhKSB7XG4gICAgICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIucmVsZWFzZShkYXRhLmlkKTtcbiAgICAgIH1cbiAgICAgIHRoaXMudGVtcG9yYXJ5RGF0YSA9IFtdO1xuICAgICAgdGhpcy5jdXJyZW50S2VybmVsSWQgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8vICNyZWdpb24gZXh0ZXJuYWwgYnVmZmVyXG4gIHJlZ2lzdGVyQnVmZmVyKHNlc3Npb25JZDogbnVtYmVyLCBpbmRleDogbnVtYmVyLCBidWZmZXI6IEdQVUJ1ZmZlciwgc2l6ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZyA9IHRoaXMuc2Vzc2lvbkV4dGVybmFsRGF0YU1hcHBpbmcuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCFzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nKSB7XG4gICAgICBzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nID0gbmV3IE1hcCgpO1xuICAgICAgdGhpcy5zZXNzaW9uRXh0ZXJuYWxEYXRhTWFwcGluZy5zZXQoc2Vzc2lvbklkLCBzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nKTtcbiAgICB9XG5cbiAgICAvLyB0aGUgYnVmZmVyIG1heSBiZSB1c2VyIGNyZWF0ZWQsIG9yIG1hbmFnZWQgYnkgR1BVIGRhdGEgbWFuYWdlci5cbiAgICAvLyBUaGUgR1BVIGRhdGEgbWFuYWdlciB3aWxsIG5vdCBtYW5hZ2UgdGhlc2UgYnVmZmVycy4gd2UgcmVnaXN0ZXIgdGhlbSBhcyBleHRlcm5hbCBidWZmZXJzLlxuICAgIC8vXG4gICAgLy8gVGhlIG1hcCBgc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZ2AgaXMgdXNlZCB0byBzdG9yZSB0aGUgZGF0YSBJRCBhbmQgYnVmZmVyIGZvciBlYWNoIGlucHV0L291dHB1dC4gT25jZSBhXG4gICAgLy8gc3BlY2lmaWMgaW5wdXQvb3V0cHV0IGlzIHJlZ2lzdGVyZWQsIHRoZSBkYXRhIElEIHdpbGwgbm90IGNoYW5nZS5cbiAgICBjb25zdCBwcmV2aW91c0J1ZmZlciA9IHNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmcuZ2V0KGluZGV4KTtcbiAgICBjb25zdCBpZCA9IHRoaXMuZ3B1RGF0YU1hbmFnZXIucmVnaXN0ZXJFeHRlcm5hbEJ1ZmZlcihidWZmZXIsIHNpemUsIHByZXZpb3VzQnVmZmVyKTtcbiAgICBzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nLnNldChpbmRleCwgW2lkLCBidWZmZXJdKTtcbiAgICByZXR1cm4gaWQ7XG4gIH1cbiAgdW5yZWdpc3RlckJ1ZmZlcnMoc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nID0gdGhpcy5zZXNzaW9uRXh0ZXJuYWxEYXRhTWFwcGluZy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZykge1xuICAgICAgc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZy5mb3JFYWNoKChidWZmZXJJbmZvKSA9PiB0aGlzLmdwdURhdGFNYW5hZ2VyLnVucmVnaXN0ZXJFeHRlcm5hbEJ1ZmZlcihidWZmZXJJbmZvWzBdKSk7XG4gICAgICB0aGlzLnNlc3Npb25FeHRlcm5hbERhdGFNYXBwaW5nLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIH1cbiAgfVxuICBnZXRCdWZmZXIoZ3B1RGF0YUlkOiBudW1iZXIpOiBHUFVCdWZmZXIge1xuICAgIGNvbnN0IGdwdURhdGEgPSB0aGlzLmdwdURhdGFNYW5hZ2VyLmdldChncHVEYXRhSWQpO1xuICAgIGlmICghZ3B1RGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBubyBHUFUgZGF0YSBmb3IgYnVmZmVyOiAke2dwdURhdGFJZH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGdwdURhdGEuYnVmZmVyO1xuICB9XG4gIGNyZWF0ZURvd25sb2FkZXIoXG4gICAgZ3B1QnVmZmVyOiBHUFVCdWZmZXIsXG4gICAgc2l6ZTogbnVtYmVyLFxuICAgIHR5cGU6IFRlbnNvci5HcHVCdWZmZXJEYXRhVHlwZXMsXG4gICk6ICgpID0+IFByb21pc2U8VGVuc29yLkRhdGFUeXBlPiB7XG4gICAgcmV0dXJuIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBkb3dubG9hZEdwdURhdGEodGhpcywgZ3B1QnVmZmVyLCBzaXplKTtcbiAgICAgIHJldHVybiBjcmVhdGVWaWV3KGRhdGEuYnVmZmVyLCB0eXBlKTtcbiAgICB9O1xuICB9XG4gIC8vICNlbmRyZWdpb25cbiAgd3JpdGVUaW1lc3RhbXAoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh0aGlzLnF1ZXJ5VHlwZSAhPT0gJ2luc2lkZS1wYXNzZXMnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAodGhpcy5jb21wdXRlUGFzc0VuY29kZXIgYXMgYW55KS53cml0ZVRpbWVzdGFtcCh0aGlzLnF1ZXJ5U2V0LCBpbmRleCk7XG4gIH1cbiAgc2V0UXVlcnlUeXBlKCk6IHZvaWQge1xuICAgIHRoaXMucXVlcnlUeXBlID0gJ25vbmUnO1xuICAgIGlmIChcbiAgICAgIHRoaXMuZW52LndlYmdwdS5wcm9maWxpbmc/Lm1vZGUgPT09ICdkZWZhdWx0JyB8fFxuICAgICAgKHR5cGVvZiB0aGlzLmVudi50cmFjZSA9PT0gJ3VuZGVmaW5lZCcgPyB0aGlzLmVudi53YXNtLnRyYWNlIDogdGhpcy5lbnYudHJhY2UpXG4gICAgKSB7XG4gICAgICBpZiAodGhpcy5kZXZpY2UuZmVhdHVyZXMuaGFzKCdjaHJvbWl1bS1leHBlcmltZW50YWwtdGltZXN0YW1wLXF1ZXJ5LWluc2lkZS1wYXNzZXMnKSkge1xuICAgICAgICB0aGlzLnF1ZXJ5VHlwZSA9ICdpbnNpZGUtcGFzc2VzJztcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5kZXZpY2UuZmVhdHVyZXMuaGFzKCd0aW1lc3RhbXAtcXVlcnknKSkge1xuICAgICAgICB0aGlzLnF1ZXJ5VHlwZSA9ICdhdC1wYXNzZXMnO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5xdWVyeVR5cGUgIT09ICdub25lJyAmJiB0eXBlb2YgdGhpcy5xdWVyeVNldCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhpcy5xdWVyeVNldCA9IHRoaXMuZGV2aWNlLmNyZWF0ZVF1ZXJ5U2V0KHtcbiAgICAgICAgICB0eXBlOiAndGltZXN0YW1wJyxcbiAgICAgICAgICBjb3VudDogdGhpcy5tYXhEaXNwYXRjaE51bWJlciAqIDIsXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnF1ZXJ5UmVzb2x2ZUJ1ZmZlciA9IHRoaXMuZGV2aWNlLmNyZWF0ZUJ1ZmZlcihcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgICAgICAgIHsgc2l6ZTogdGhpcy5tYXhEaXNwYXRjaE51bWJlciAqIDIgKiA4LCB1c2FnZTogR1BVQnVmZmVyVXNhZ2UuQ09QWV9TUkMgfCBHUFVCdWZmZXJVc2FnZS5RVUVSWV9SRVNPTFZFIH0sXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY2FwdHVyZUJlZ2luKCk6IHZvaWQge1xuICAgIExPR19ERUJVRygnaW5mbycsICdjYXB0dXJlQmVnaW4nKTtcbiAgICBpZiAoIXRoaXMuY2FwdHVyZWRDb21tYW5kTGlzdC5nZXQodGhpcy5jdXJyZW50U2Vzc2lvbklkISkpIHtcbiAgICAgIHRoaXMuY2FwdHVyZWRDb21tYW5kTGlzdC5zZXQodGhpcy5jdXJyZW50U2Vzc2lvbklkISwgW10pO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuY2FwdHVyZWRQZW5kaW5nS2VybmVscy5nZXQodGhpcy5jdXJyZW50U2Vzc2lvbklkISkpIHtcbiAgICAgIHRoaXMuY2FwdHVyZWRQZW5kaW5nS2VybmVscy5zZXQodGhpcy5jdXJyZW50U2Vzc2lvbklkISwgW10pO1xuICAgIH1cbiAgICAvLyBmbHVzaCB0aGUgbGVmdCBjb21tYW5kcyBiZWZvcmUgd2UgY2hhbmdlIHRoZSBzdGF0dXMuXG4gICAgdGhpcy5mbHVzaCgpO1xuICAgIHRoaXMuc2Vzc2lvblN0YXR1cyA9ICdjYXB0dXJpbmcnO1xuICB9XG4gIGNhcHR1cmVFbmQoKTogdm9pZCB7XG4gICAgTE9HX0RFQlVHKCdpbmZvJywgJ2NhcHR1cmVFbmQnKTtcbiAgICAvLyBmbHVzaCB0aGUgbGVmdCBjb21tYW5kcyBiZWZvcmUgd2UgY2hhbmdlIHRoZSBzdGF0dXMuXG4gICAgdGhpcy5mbHVzaCgpO1xuICAgIHRoaXMuc2Vzc2lvblN0YXR1cyA9ICdkZWZhdWx0JztcbiAgfVxuICByZXBsYXkoKTogdm9pZCB7XG4gICAgTE9HX0RFQlVHKCdpbmZvJywgJ3JlcGxheScpO1xuICAgIHRoaXMuc2Vzc2lvblN0YXR1cyA9ICdyZXBsYXlpbmcnO1xuICAgIGNvbnN0IHNlc3Npb25Db21tYW5kTGlzdCA9IHRoaXMuY2FwdHVyZWRDb21tYW5kTGlzdC5nZXQodGhpcy5jdXJyZW50U2Vzc2lvbklkISk7XG4gICAgY29uc3Qgc2Vzc2lvblBlbmRpbmdLZXJuZWxzID0gdGhpcy5jYXB0dXJlZFBlbmRpbmdLZXJuZWxzLmdldCh0aGlzLmN1cnJlbnRTZXNzaW9uSWQhKTtcbiAgICBjb25zdCBsZW5ndGggPSBzZXNzaW9uQ29tbWFuZExpc3QhLmxlbmd0aDtcbiAgICB0aGlzLnBlbmRpbmdLZXJuZWxzID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgY29tcHV0ZVBhc3NFbmNvZGVyID0gdGhpcy5nZXRDb21wdXRlUGFzc0VuY29kZXIoKTtcbiAgICAgIGNvbnN0IGNvbW1hbmQgPSBzZXNzaW9uQ29tbWFuZExpc3QhW2ldO1xuICAgICAgdGhpcy53cml0ZVRpbWVzdGFtcCh0aGlzLnBlbmRpbmdEaXNwYXRjaE51bWJlciAqIDIpO1xuICAgICAgY29tcHV0ZVBhc3NFbmNvZGVyLnNldFBpcGVsaW5lKGNvbW1hbmQuY29tcHV0ZVBpcGVsaW5lKTtcbiAgICAgIGNvbXB1dGVQYXNzRW5jb2Rlci5zZXRCaW5kR3JvdXAoMCwgY29tbWFuZC5iaW5kR3JvdXApO1xuICAgICAgY29tcHV0ZVBhc3NFbmNvZGVyLmRpc3BhdGNoV29ya2dyb3VwcyguLi5jb21tYW5kLmRpc3BhdGNoR3JvdXApO1xuICAgICAgdGhpcy53cml0ZVRpbWVzdGFtcCh0aGlzLnBlbmRpbmdEaXNwYXRjaE51bWJlciAqIDIgKyAxKTtcbiAgICAgIHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyKys7XG4gICAgICBpZiAodGhpcy5xdWVyeVR5cGUgIT09ICdub25lJykge1xuICAgICAgICB0aGlzLnBlbmRpbmdLZXJuZWxzLnB1c2goc2Vzc2lvblBlbmRpbmdLZXJuZWxzIVtpXSk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgPj0gdGhpcy5tYXhEaXNwYXRjaE51bWJlciB8fCB0aGlzLnF1ZXJ5VHlwZSA9PT0gJ2F0LXBhc3NlcycpIHtcbiAgICAgICAgdGhpcy5lbmRDb21wdXRlUGFzcygpO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyID49IHRoaXMubWF4RGlzcGF0Y2hOdW1iZXIpIHtcbiAgICAgICAgdGhpcy5mbHVzaCgpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBmbHVzaCB0aGUgbGVmdCBjb21tYW5kcyBiZWZvcmUgd2UgY2hhbmdlIHRoZSBzdGF0dXMuXG4gICAgdGhpcy5mbHVzaCgpO1xuICAgIHRoaXMuc2Vzc2lvblN0YXR1cyA9ICdkZWZhdWx0JztcbiAgfVxuXG4gIG9uQ3JlYXRlU2Vzc2lvbigpOiB2b2lkIHtcbiAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLm9uQ3JlYXRlU2Vzc2lvbigpO1xuICB9XG5cbiAgb25SZWxlYXNlU2Vzc2lvbihzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMudW5yZWdpc3RlckJ1ZmZlcnMoc2Vzc2lvbklkKTtcbiAgICBpZiAodGhpcy5jYXB0dXJlZENvbW1hbmRMaXN0LmhhcyhzZXNzaW9uSWQpKSB7XG4gICAgICB0aGlzLmNhcHR1cmVkQ29tbWFuZExpc3QuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgfVxuICAgIGlmICh0aGlzLmNhcHR1cmVkUGVuZGluZ0tlcm5lbHMuaGFzKHNlc3Npb25JZCkpIHtcbiAgICAgIHRoaXMuY2FwdHVyZWRQZW5kaW5nS2VybmVscy5kZWxldGUoc2Vzc2lvbklkKTtcbiAgICB9XG4gICAgdGhpcy5ncHVEYXRhTWFuYWdlci5vblJlbGVhc2VTZXNzaW9uKHNlc3Npb25JZCk7XG4gIH1cblxuICBvblJ1blN0YXJ0KHNlc3Npb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50U2Vzc2lvbklkID0gc2Vzc2lvbklkO1xuICAgIHRoaXMuc2V0UXVlcnlUeXBlKCk7XG4gIH1cbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHR5cGUgeyBFbnYgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBjYWxjdWxhdGVUZW5zb3JTaXplSW5CeXRlcywgRGF0YVR5cGUgfSBmcm9tICcuLi93YXNtLWNvbW1vbic7XG5cbmltcG9ydCB0eXBlIHsgT3J0V2FzbU1vZHVsZSB9IGZyb20gJy4uL3dhc20tdHlwZXMnO1xuXG5pbXBvcnQgdHlwZSB7IFdlYkdwdUJhY2tlbmQgfSBmcm9tICcuL2JhY2tlbmQtd2ViZ3B1JztcbmltcG9ydCB7IExPR19ERUJVRyB9IGZyb20gJy4vbG9nJztcbmltcG9ydCB0eXBlIHsgVGVuc29yVmlldyB9IGZyb20gJy4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi91dGlsJztcbmltcG9ydCB0eXBlIHsgQWRhcHRlckluZm8sIENvbXB1dGVDb250ZXh0LCBDb21wdXRlQ29udGV4dElucHV0c091dHB1dHNNYXBwaW5nLCBQcm9ncmFtSW5mbyB9IGZyb20gJy4vd2ViZ3B1L3R5cGVzJztcbmltcG9ydCB7IFdlYk5OQmFja2VuZCB9IGZyb20gJy4vYmFja2VuZC13ZWJubic7XG5cbi8qIGVzbGludC1kaXNhYmxlIG5vLWJpdHdpc2UgKi9cblxuY2xhc3MgVGVuc29yVmlld0ltcGwgaW1wbGVtZW50cyBUZW5zb3JWaWV3IHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBtb2R1bGU6IE9ydFdhc21Nb2R1bGUsXG4gICAgcHVibGljIHJlYWRvbmx5IGRhdGFUeXBlOiBudW1iZXIsXG4gICAgcHVibGljIHJlYWRvbmx5IGRhdGE6IG51bWJlcixcbiAgICBwdWJsaWMgcmVhZG9ubHkgZGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICkge31cblxuICBnZXRGbG9hdDMyQXJyYXkoKTogRmxvYXQzMkFycmF5IHtcbiAgICBpZiAodGhpcy5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBkYXRhIHR5cGUnKTtcbiAgICB9XG4gICAgY29uc3QgZWxlbWVudENvdW50ID0gU2hhcGVVdGlsLnNpemUodGhpcy5kaW1zKTtcbiAgICByZXR1cm4gZWxlbWVudENvdW50ID09PSAwXG4gICAgICA/IG5ldyBGbG9hdDMyQXJyYXkoKVxuICAgICAgOiBuZXcgRmxvYXQzMkFycmF5KHRoaXMubW9kdWxlLkhFQVA4LmJ1ZmZlciwgdGhpcy5kYXRhLCBlbGVtZW50Q291bnQpO1xuICB9XG5cbiAgZ2V0QmlnSW50NjRBcnJheSgpOiBCaWdJbnQ2NEFycmF5IHtcbiAgICBpZiAodGhpcy5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuaW50NjQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBkYXRhIHR5cGUnKTtcbiAgICB9XG4gICAgY29uc3QgZWxlbWVudENvdW50ID0gU2hhcGVVdGlsLnNpemUodGhpcy5kaW1zKTtcbiAgICByZXR1cm4gZWxlbWVudENvdW50ID09PSAwXG4gICAgICA/IG5ldyBCaWdJbnQ2NEFycmF5KClcbiAgICAgIDogbmV3IEJpZ0ludDY0QXJyYXkodGhpcy5tb2R1bGUuSEVBUDguYnVmZmVyLCB0aGlzLmRhdGEsIGVsZW1lbnRDb3VudCk7XG4gIH1cblxuICBnZXRJbnQzMkFycmF5KCk6IEludDMyQXJyYXkge1xuICAgIGlmICh0aGlzLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5pbnQzMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRhdGEgdHlwZScpO1xuICAgIH1cbiAgICBjb25zdCBlbGVtZW50Q291bnQgPSBTaGFwZVV0aWwuc2l6ZSh0aGlzLmRpbXMpO1xuICAgIHJldHVybiBlbGVtZW50Q291bnQgPT09IDAgPyBuZXcgSW50MzJBcnJheSgpIDogbmV3IEludDMyQXJyYXkodGhpcy5tb2R1bGUuSEVBUDguYnVmZmVyLCB0aGlzLmRhdGEsIGVsZW1lbnRDb3VudCk7XG4gIH1cblxuICBnZXRVaW50MTZBcnJheSgpOiBVaW50MTZBcnJheSB7XG4gICAgaWYgKHRoaXMuZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0MTYgJiYgdGhpcy5kYXRhVHlwZSAhPT0gRGF0YVR5cGUudWludDE2KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZGF0YSB0eXBlJyk7XG4gICAgfVxuICAgIGNvbnN0IGVsZW1lbnRDb3VudCA9IFNoYXBlVXRpbC5zaXplKHRoaXMuZGltcyk7XG4gICAgcmV0dXJuIGVsZW1lbnRDb3VudCA9PT0gMCA/IG5ldyBVaW50MTZBcnJheSgpIDogbmV3IFVpbnQxNkFycmF5KHRoaXMubW9kdWxlLkhFQVA4LmJ1ZmZlciwgdGhpcy5kYXRhLCBlbGVtZW50Q291bnQpO1xuICB9XG5cbiAgcmVzaGFwZShuZXdEaW1zOiByZWFkb25seSBudW1iZXJbXSk6IFRlbnNvclZpZXcge1xuICAgIGlmIChTaGFwZVV0aWwuc2l6ZShuZXdEaW1zKSAhPT0gU2hhcGVVdGlsLnNpemUodGhpcy5kaW1zKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG5ldyBzaGFwZScpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IFRlbnNvclZpZXdJbXBsKHRoaXMubW9kdWxlLCB0aGlzLmRhdGFUeXBlLCB0aGlzLmRhdGEsIG5ld0RpbXMpO1xuICB9XG59XG5cbmNsYXNzIENvbXB1dGVDb250ZXh0SW1wbCBpbXBsZW1lbnRzIENvbXB1dGVDb250ZXh0IHtcbiAgcmVhZG9ubHkgYWRhcHRlckluZm86IEFkYXB0ZXJJbmZvO1xuICByZWFkb25seSBvcEtlcm5lbENvbnRleHQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W107XG4gIHJlYWRvbmx5IG91dHB1dENvdW50OiBudW1iZXI7XG4gIGdldCBrZXJuZWxDdXN0b21EYXRhKCk6IHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9IHtcbiAgICByZXR1cm4gdGhpcy5iYWNrZW5kLmN1cnJlbnRLZXJuZWxDdXN0b21EYXRhO1xuICB9XG4gIGdldCBjdXN0b21EYXRhQnVmZmVyKCk6IFVpbnQ4QXJyYXkge1xuICAgIHJldHVybiB0aGlzLm1vZHVsZS5IRUFQVTguc3ViYXJyYXkodGhpcy5jdXN0b21EYXRhT2Zmc2V0LCB0aGlzLmN1c3RvbURhdGFPZmZzZXQgKyB0aGlzLmN1c3RvbURhdGFTaXplKTtcbiAgfVxuICBwcml2YXRlIGN1c3RvbURhdGFPZmZzZXQgPSAwO1xuICBwcml2YXRlIGN1c3RvbURhdGFTaXplID0gMDtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBtb2R1bGU6IE9ydFdhc21Nb2R1bGUsXG4gICAgcHJpdmF0ZSBiYWNrZW5kOiBXZWJHcHVCYWNrZW5kLFxuICAgIGNvbnRleHREYXRhT2Zmc2V0OiBudW1iZXIsXG4gICkge1xuICAgIHRoaXMuYWRhcHRlckluZm8gPSBiYWNrZW5kLmFkYXB0ZXJJbmZvO1xuXG4gICAgLy8gZXh0cmFjdCBjb250ZXh0IGRhdGFcbiAgICBjb25zdCBwdHJTaXplID0gbW9kdWxlLlBUUl9TSVpFO1xuICAgIGxldCBkYXRhSW5kZXggPSBjb250ZXh0RGF0YU9mZnNldCAvIG1vZHVsZS5QVFJfU0laRTtcbiAgICBjb25zdCB0eXBlID0gcHRyU2l6ZSA9PT0gNCA/ICdpMzInIDogJ2k2NCc7XG4gICAgdGhpcy5vcEtlcm5lbENvbnRleHQgPSBOdW1iZXIobW9kdWxlLmdldFZhbHVlKHB0clNpemUgKiBkYXRhSW5kZXgrKywgdHlwZSkpO1xuICAgIGNvbnN0IGlucHV0Q291bnQgPSBOdW1iZXIobW9kdWxlLmdldFZhbHVlKHB0clNpemUgKiBkYXRhSW5kZXgrKywgdHlwZSkpO1xuICAgIHRoaXMub3V0cHV0Q291bnQgPSBOdW1iZXIobW9kdWxlLmdldFZhbHVlKHB0clNpemUgKiBkYXRhSW5kZXgrKywgdHlwZSkpO1xuICAgIHRoaXMuY3VzdG9tRGF0YU9mZnNldCA9IE51bWJlcihtb2R1bGUuZ2V0VmFsdWUocHRyU2l6ZSAqIGRhdGFJbmRleCsrLCAnKicpKTtcbiAgICB0aGlzLmN1c3RvbURhdGFTaXplID0gTnVtYmVyKG1vZHVsZS5nZXRWYWx1ZShwdHJTaXplICogZGF0YUluZGV4KyssIHR5cGUpKTtcblxuICAgIGNvbnN0IGlucHV0czogVGVuc29yVmlld1tdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IGRhdGFUeXBlID0gTnVtYmVyKG1vZHVsZS5nZXRWYWx1ZShwdHJTaXplICogZGF0YUluZGV4KyssIHR5cGUpKTtcbiAgICAgIGNvbnN0IGRhdGEgPSBOdW1iZXIobW9kdWxlLmdldFZhbHVlKHB0clNpemUgKiBkYXRhSW5kZXgrKywgJyonKSk7XG4gICAgICBjb25zdCBkaW0gPSBOdW1iZXIobW9kdWxlLmdldFZhbHVlKHB0clNpemUgKiBkYXRhSW5kZXgrKywgdHlwZSkpO1xuICAgICAgY29uc3QgZGltczogbnVtYmVyW10gPSBbXTtcbiAgICAgIGZvciAobGV0IGQgPSAwOyBkIDwgZGltOyBkKyspIHtcbiAgICAgICAgZGltcy5wdXNoKE51bWJlcihtb2R1bGUuZ2V0VmFsdWUocHRyU2l6ZSAqIGRhdGFJbmRleCsrLCB0eXBlKSkpO1xuICAgICAgfVxuICAgICAgaW5wdXRzLnB1c2gobmV3IFRlbnNvclZpZXdJbXBsKG1vZHVsZSwgZGF0YVR5cGUsIGRhdGEsIGRpbXMpKTtcbiAgICB9XG4gICAgdGhpcy5pbnB1dHMgPSBpbnB1dHM7XG4gIH1cblxuICBjb21wdXRlKHByb2dyYW06IFByb2dyYW1JbmZvLCBpbnB1dHNPdXRwdXRzTWFwcGluZz86IENvbXB1dGVDb250ZXh0SW5wdXRzT3V0cHV0c01hcHBpbmcpOiBUZW5zb3JWaWV3W10ge1xuICAgIC8vIHByZXBhcmUgaW5wdXRzLiBpbnB1dHMgc2hvdWxkIGFsd2F5cyBiZSB2YWxpZCBkYXRhLlxuICAgIGNvbnN0IG1hcHBlZElucHV0cyA9XG4gICAgICBpbnB1dHNPdXRwdXRzTWFwcGluZz8uaW5wdXRzPy5tYXAoKGkpID0+ICh0eXBlb2YgaSA9PT0gJ251bWJlcicgPyB0aGlzLmlucHV0c1tpXSA6IGkpKSA/PyB0aGlzLmlucHV0cztcbiAgICAvLyBwcmVwYXJlIG91dHB1dHMuXG4gICAgY29uc3Qgb3V0cHV0SW5kaWNlcyA9IGlucHV0c091dHB1dHNNYXBwaW5nPy5vdXRwdXRzID8/IFtdO1xuICAgIGNvbnN0IGNyZWF0ZUtlcm5lbE91dHB1dCA9IChpbmRleDogbnVtYmVyLCBkYXRhVHlwZTogbnVtYmVyLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IFRlbnNvclZpZXcgPT5cbiAgICAgIG5ldyBUZW5zb3JWaWV3SW1wbCh0aGlzLm1vZHVsZSwgZGF0YVR5cGUsIHRoaXMub3V0cHV0KGluZGV4LCBkaW1zKSwgZGltcyk7XG4gICAgY29uc3QgY3JlYXRlVGVtcG9yYXJ5T3V0cHV0ID0gKGRhdGFUeXBlOiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yVmlldyA9PiB7XG4gICAgICBjb25zdCBidWZmZXJTaXplID0gY2FsY3VsYXRlVGVuc29yU2l6ZUluQnl0ZXMoZGF0YVR5cGUsIGRpbXMpO1xuICAgICAgaWYgKCFidWZmZXJTaXplKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke2RhdGFUeXBlfWApO1xuICAgICAgfVxuICAgICAgY29uc3QgZ3B1RGF0YUlkID0gYnVmZmVyU2l6ZSA+IDAgPyB0aGlzLmJhY2tlbmQuZ3B1RGF0YU1hbmFnZXIuY3JlYXRlKGJ1ZmZlclNpemUpLmlkIDogMDtcbiAgICAgIHJldHVybiBuZXcgVGVuc29yVmlld0ltcGwodGhpcy5tb2R1bGUsIGRhdGFUeXBlLCBncHVEYXRhSWQsIGRpbXMpO1xuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuYmFja2VuZC5ydW4oXG4gICAgICBwcm9ncmFtLFxuICAgICAgbWFwcGVkSW5wdXRzLFxuICAgICAgb3V0cHV0SW5kaWNlcyxcbiAgICAgIGNyZWF0ZUtlcm5lbE91dHB1dCxcbiAgICAgIGNyZWF0ZVRlbXBvcmFyeU91dHB1dCxcbiAgICAgIHRoaXMub3V0cHV0Q291bnQsXG4gICAgKTtcbiAgfVxuXG4gIG91dHB1dChpbmRleDogbnVtYmVyLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IG51bWJlciB7XG4gICAgY29uc3Qgc3RhY2sgPSB0aGlzLm1vZHVsZS5zdGFja1NhdmUoKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcHRyU2l6ZSA9IHRoaXMubW9kdWxlLlBUUl9TSVpFO1xuICAgICAgY29uc3QgdHlwZSA9IHB0clNpemUgPT09IDQgPyAnaTMyJyA6ICdpNjQnO1xuICAgICAgY29uc3QgZGF0YSA9IHRoaXMubW9kdWxlLnN0YWNrQWxsb2MoKDEgKyBkaW1zLmxlbmd0aCkgKiBwdHJTaXplIC8qIHNpemVvZihzaXplX3QpICovKTtcbiAgICAgIHRoaXMubW9kdWxlLnNldFZhbHVlKGRhdGEsIGRpbXMubGVuZ3RoLCB0eXBlKTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGltcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLm1vZHVsZS5zZXRWYWx1ZShkYXRhICsgcHRyU2l6ZSAqIChpICsgMSksIGRpbXNbaV0sIHR5cGUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMubW9kdWxlLl9Kc2VwT3V0cHV0ISh0aGlzLm9wS2VybmVsQ29udGV4dCwgaW5kZXgsIGRhdGEpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBnZW5lcmF0ZSBrZXJuZWwncyBvdXRwdXRbJHtpbmRleH1dIHdpdGggZGltcyBbJHtkaW1zfV0uIGAgK1xuICAgICAgICAgICdJZiB5b3UgYXJlIHJ1bm5pbmcgd2l0aCBwcmUtYWxsb2NhdGVkIG91dHB1dCwgcGxlYXNlIG1ha2Ugc3VyZSB0aGUgb3V0cHV0IHR5cGUvZGltcyBhcmUgY29ycmVjdC4gJyArXG4gICAgICAgICAgYEVycm9yOiAke2V9YCxcbiAgICAgICk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMubW9kdWxlLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBKU0VQIHdpdGggV2ViR1BVIGJhY2tlbmQuXG4gKlxuICogVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBhZnRlciB0aGUgV2ViQXNzZW1ibHkgbW9kdWxlIGlzIGxvYWRlZCBhbmQgaW5pdGlhbGl6ZWQgKFwiX09ydEluaXRcIiBpcyBjYWxsZWQpLCBvbmNlIGZvclxuICogZWFjaCBvZiB0aGUgZm9sbG93aW5nIEVQcyBpZiB0aGV5IGFyZSBzcGVjaWZpZWQ6XG4gKiAtIFwid2ViZ3B1XCJcbiAqIC0gXCJ3ZWJublwiXG4gKlxuICogRm9yIFdlYkdQVSwgdGhpcyBmdW5jdGlvbiBleHBlY3RzOlxuICogIC0gV2ViR1BVIGlzIGVuYWJsZWQgaW4gYnVpbGQgKEJVSUxEX0RFRlMuRElTQUJMRV9KU0VQID09PSBmYWxzZSkuXG4gKiAgLSBXZWJHUFUgaXMgYXZhaWxhYmxlIGluIGN1cnJlbnQgZW52aXJvbm1lbnQuIChhIHZhbGlkIEdQVUFkYXB0ZXIgaXMgcGFzc2VkIGluKVxuICpcbiAqIEZvciBXZWJOTiwgdGhpcyBmdW5jdGlvbiBleHBlY3RzOlxuICogLSBXZWJOTiBpcyBlbmFibGVkIGluIGJ1aWxkIChCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUCA9PT0gZmFsc2UpLlxuICogLSBXZWJOTiBpcyBhdmFpbGFibGUgaW4gY3VycmVudCBlbnZpcm9ubWVudC4gKG5hdmlnYXRvci5tbCBpcyBub3QgdW5kZWZpbmVkKVxuICpcbiAqIElmIHRoZSBXZWJBc3NlbWJseSBtb2R1bGUgaXMgbm90IGJ1aWx0IHdpdGggSlNFUCBzdXBwb3J0LCB0aGlzIGZ1bmN0aW9uIHdpbGwgdGhyb3cgYW4gZXJyb3IuIFRoaXMgd2lsbCBpbnZhbGlkYXRlXG4gKiAnd2ViZ3B1Jy8nd2Vibm4nIGJhY2tlbmQuXG4gKlxuICogQHBhcmFtIG5hbWUgLSB0aGUgbmFtZSBvZiB0aGUgRVAsIGVpdGhlciBcIndlYmdwdVwiIG9yIFwid2Vibm5cIlxuICogQHBhcmFtIG1vZHVsZSAtIHRoZSBPUlQgV2ViQXNzZW1ibHkgbW9kdWxlXG4gKiBAcGFyYW0gZW52IC0gdGhlIE9SVCBlbnZpcm9ubWVudCB2YXJpYWJsZSAob3J0LmVudilcbiAqIEBwYXJhbSBncHVBZGFwdGVyIC0gdGhlIHByZS1jcmVhdGVkIEdQVSBhZGFwdGVyXG4gKi9cbmV4cG9ydCBjb25zdCBpbml0ID0gYXN5bmMgKFxuICBuYW1lOiAnd2ViZ3B1JyB8ICd3ZWJubicsXG4gIG1vZHVsZTogT3J0V2FzbU1vZHVsZSxcbiAgZW52OiBFbnYsXG4gIGdwdUFkYXB0ZXI/OiBHUFVBZGFwdGVyLFxuKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGNvbnN0IGpzZXBJbml0ID0gbW9kdWxlLmpzZXBJbml0O1xuICBpZiAoIWpzZXBJbml0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gaW5pdGlhbGl6ZSBKU0VQLiBUaGUgV2ViQXNzZW1ibHkgbW9kdWxlIGlzIG5vdCBidWlsdCB3aXRoIEpTRVAgc3VwcG9ydC4nKTtcbiAgfVxuXG4gIGlmIChuYW1lID09PSAnd2ViZ3B1Jykge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgY29uc3Qgd2ViR3B1QmFja2VuZEltcGwgPSByZXF1aXJlKCcuL2JhY2tlbmQtd2ViZ3B1JykuV2ViR3B1QmFja2VuZDtcbiAgICBjb25zdCBiYWNrZW5kID0gbmV3IHdlYkdwdUJhY2tlbmRJbXBsKCk7XG4gICAgYXdhaXQgYmFja2VuZC5pbml0aWFsaXplKGVudiwgZ3B1QWRhcHRlciEpO1xuXG4gICAganNlcEluaXQoJ3dlYmdwdScsIFtcbiAgICAgIC8vIGJhY2tlbmRcbiAgICAgIGJhY2tlbmQsXG5cbiAgICAgIC8vIGpzZXBBbGxvYygpXG4gICAgICAoc2l6ZTogbnVtYmVyKSA9PiBiYWNrZW5kLmFsbG9jKE51bWJlcihzaXplKSksXG5cbiAgICAgIC8vIGpzZXBGcmVlKClcbiAgICAgIChwdHI6IG51bWJlcikgPT4gYmFja2VuZC5mcmVlKHB0ciksXG5cbiAgICAgIC8vIGpzZXBDb3B5KHNyYywgZHN0LCBzaXplLCBpc1NvdXJjZUdwdSlcbiAgICAgIChzcmM6IG51bWJlciwgZHN0OiBudW1iZXIsIHNpemU6IG51bWJlciwgaXNTb3VyY2VHcHUgPSBmYWxzZSkgPT4ge1xuICAgICAgICBpZiAoaXNTb3VyY2VHcHUpIHtcbiAgICAgICAgICBMT0dfREVCVUcoXG4gICAgICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICAgICAoKSA9PiBgW1dlYkdQVV0ganNlcENvcHlHcHVUb0dwdTogc3JjPSR7TnVtYmVyKHNyYyl9LCBkc3Q9JHtOdW1iZXIoZHN0KX0sIHNpemU9JHtOdW1iZXIoc2l6ZSl9YCxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJhY2tlbmQubWVtY3B5KE51bWJlcihzcmMpLCBOdW1iZXIoZHN0KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgTE9HX0RFQlVHKFxuICAgICAgICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgICAgYFtXZWJHUFVdIGpzZXBDb3B5Q3B1VG9HcHU6IGRhdGFPZmZzZXQ9JHtOdW1iZXIoc3JjKX0sIGdwdURhdGFJZD0ke051bWJlcihkc3QpfSwgc2l6ZT0ke051bWJlcihzaXplKX1gLFxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgZGF0YSA9IG1vZHVsZS5IRUFQVTguc3ViYXJyYXkoTnVtYmVyKHNyYyA+Pj4gMCksIE51bWJlcihzcmMgPj4+IDApICsgTnVtYmVyKHNpemUpKTtcbiAgICAgICAgICBiYWNrZW5kLnVwbG9hZChOdW1iZXIoZHN0KSwgZGF0YSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG5cbiAgICAgIC8vIGpzZXBDb3B5QXN5bmMoc3JjLCBkc3QsIHNpemUpXG4gICAgICBhc3luYyAoZ3B1RGF0YUlkOiBudW1iZXIsIGRhdGFPZmZzZXQ6IG51bWJlciwgc2l6ZTogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIExPR19ERUJVRyhcbiAgICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICAgKCkgPT4gYFtXZWJHUFVdIGpzZXBDb3B5R3B1VG9DcHU6IGdwdURhdGFJZD0ke2dwdURhdGFJZH0sIGRhdGFPZmZzZXQ9JHtkYXRhT2Zmc2V0fSwgc2l6ZT0ke3NpemV9YCxcbiAgICAgICAgKTtcblxuICAgICAgICBhd2FpdCBiYWNrZW5kLmRvd25sb2FkKE51bWJlcihncHVEYXRhSWQpLCAoKSA9PlxuICAgICAgICAgIG1vZHVsZS5IRUFQVTguc3ViYXJyYXkoTnVtYmVyKGRhdGFPZmZzZXQpID4+PiAwLCBOdW1iZXIoZGF0YU9mZnNldCArIHNpemUpID4+PiAwKSxcbiAgICAgICAgKTtcbiAgICAgIH0sXG5cbiAgICAgIC8vIGpzZXBDcmVhdGVLZXJuZWxcbiAgICAgIChrZXJuZWxUeXBlOiBzdHJpbmcsIGtlcm5lbElkOiBudW1iZXIsIGF0dHJpYnV0ZTogdW5rbm93bikgPT5cbiAgICAgICAgYmFja2VuZC5jcmVhdGVLZXJuZWwoXG4gICAgICAgICAga2VybmVsVHlwZSxcbiAgICAgICAgICBOdW1iZXIoa2VybmVsSWQpLFxuICAgICAgICAgIGF0dHJpYnV0ZSxcbiAgICAgICAgICBtb2R1bGUuVVRGOFRvU3RyaW5nKG1vZHVsZS5fSnNlcEdldE5vZGVOYW1lIShOdW1iZXIoa2VybmVsSWQpKSksXG4gICAgICAgICksXG5cbiAgICAgIC8vIGpzZXBSZWxlYXNlS2VybmVsXG4gICAgICAoa2VybmVsOiBudW1iZXIpID0+IGJhY2tlbmQucmVsZWFzZUtlcm5lbChrZXJuZWwpLFxuXG4gICAgICAvLyBqc2VwUnVuXG4gICAgICAoa2VybmVsOiBudW1iZXIsIGNvbnRleHREYXRhT2Zmc2V0OiBudW1iZXIsIHNlc3Npb25IYW5kbGU6IG51bWJlciwgZXJyb3JzOiBBcnJheTxQcm9taXNlPHN0cmluZyB8IG51bGw+PikgPT4ge1xuICAgICAgICBMT0dfREVCVUcoXG4gICAgICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgICAgICgpID0+XG4gICAgICAgICAgICBgW1dlYkdQVV0ganNlcFJ1bjogc2Vzc2lvbkhhbmRsZT0ke3Nlc3Npb25IYW5kbGV9LCBrZXJuZWw9JHtrZXJuZWx9LCBjb250ZXh0RGF0YU9mZnNldD0ke2NvbnRleHREYXRhT2Zmc2V0fWAsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSBuZXcgQ29tcHV0ZUNvbnRleHRJbXBsKG1vZHVsZSwgYmFja2VuZCwgTnVtYmVyKGNvbnRleHREYXRhT2Zmc2V0KSk7XG4gICAgICAgIHJldHVybiBiYWNrZW5kLmNvbXB1dGVLZXJuZWwoTnVtYmVyKGtlcm5lbCksIGNvbnRleHQsIGVycm9ycyk7XG4gICAgICB9LFxuICAgICAgLy8ganNlcENhcHR1cmVCZWdpblxuICAgICAgKCkgPT4gYmFja2VuZC5jYXB0dXJlQmVnaW4oKSxcbiAgICAgIC8vIGpzZXBDYXB0dXJlRW5kXG4gICAgICAoKSA9PiBiYWNrZW5kLmNhcHR1cmVFbmQoKSxcbiAgICAgIC8vIGpzZXBSZXBsYXlcbiAgICAgICgpID0+IGJhY2tlbmQucmVwbGF5KCksXG4gICAgXSk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgYmFja2VuZCA9IG5ldyBXZWJOTkJhY2tlbmQoZW52KTtcbiAgICBqc2VwSW5pdCgnd2Vibm4nLCBbXG4gICAgICBiYWNrZW5kLFxuICAgICAgLy8gd2Vibm5SZXNlcnZlVGVuc29ySWRcbiAgICAgICgpID0+IGJhY2tlbmQucmVzZXJ2ZVRlbnNvcklkKCksXG4gICAgICAvLyB3ZWJublJlbGVhc2VUZW5zb3JJZFxuICAgICAgKHRlbnNvcklkOiBudW1iZXIpID0+IGJhY2tlbmQucmVsZWFzZVRlbnNvcklkKHRlbnNvcklkKSxcbiAgICAgIC8vIHdlYm5uRW5zdXJlVGVuc29yXG4gICAgICBhc3luYyAoXG4gICAgICAgIHNlc3Npb25JZDogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICAgICAgICB0ZW5zb3JJZDogbnVtYmVyLFxuICAgICAgICBvbm54RGF0YVR5cGU6IG51bWJlcixcbiAgICAgICAgc2hhcGU6IG51bWJlcltdLFxuICAgICAgICBjb3B5T2xkOiBib29sZWFuLFxuICAgICAgKSA9PiBiYWNrZW5kLmVuc3VyZVRlbnNvcihzZXNzaW9uSWQsIHRlbnNvcklkLCBvbm54RGF0YVR5cGUsIHNoYXBlLCBjb3B5T2xkKSxcbiAgICAgIC8vIHdlYm5uVXBsb2FkVGVuc29yXG4gICAgICAodGVuc29ySWQ6IG51bWJlciwgZGF0YTogVWludDhBcnJheSkgPT4ge1xuICAgICAgICBiYWNrZW5kLnVwbG9hZFRlbnNvcih0ZW5zb3JJZCwgZGF0YSk7XG4gICAgICB9LFxuICAgICAgLy8gd2Vibm5Eb3dubG9hZFRlbnNvclxuICAgICAgYXN5bmMgKHRlbnNvcklkOiBudW1iZXIsIGRzdEJ1ZmZlcjogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpID0+IGJhY2tlbmQuZG93bmxvYWRUZW5zb3IodGVuc29ySWQsIGRzdEJ1ZmZlciksXG4gICAgICAvLyB3ZWJublJlZ2lzdGVyTUxDb250ZXh0XG4gICAgICAoc2Vzc2lvbklkOiBudW1iZXIsIG1sQ29udGV4dDogTUxDb250ZXh0KSA9PiBiYWNrZW5kLnJlZ2lzdGVyTUxDb250ZXh0KHNlc3Npb25JZCwgbWxDb250ZXh0KSxcbiAgICAgIC8vIHdlYm5uRW5hYmxlVHJhY2VFdmVudFxuICAgICAgISFlbnYudHJhY2UsXG4gICAgXSk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8vIFdlYk5OIEFQSSBjdXJyZW50bHkgZG9lcyBub3QgaGF2ZSBhIFR5cGVTY3JpcHQgZGVmaW5pdGlvbiBmaWxlLiBUaGlzIGZpbGUgaXMgYSB3b3JrYXJvdW5kIHdpdGggdHlwZXMgZ2VuZXJhdGVkIGZyb21cbi8vIFdlYk5OIEFQSSBzcGVjaWZpY2F0aW9uLlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3dlYm1hY2hpbmVsZWFybmluZy93ZWJubi9pc3N1ZXMvNjc3XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwianNlcC93ZWJubi93ZWJubi5kLnRzXCIgLz5cblxuaW1wb3J0IHsgRW52LCBJbmZlcmVuY2VTZXNzaW9uLCBUZW5zb3IsIFRSQUNFX0VWRU5UX0JFR0lOLCBUUkFDRV9FVkVOVF9FTkQgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge1xuICBTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlcixcbiAgU2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhLFxuICBTZXJpYWxpemFibGVUZW5zb3JNZXRhZGF0YSxcbiAgVGVuc29yTWV0YWRhdGEsXG59IGZyb20gJy4vcHJveHktbWVzc2FnZXMnO1xuaW1wb3J0IHsgc2V0UnVuT3B0aW9ucyB9IGZyb20gJy4vcnVuLW9wdGlvbnMnO1xuaW1wb3J0IHsgc2V0U2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuL3Nlc3Npb24tb3B0aW9ucyc7XG5pbXBvcnQge1xuICBjYWxjdWxhdGVUZW5zb3JTaXplSW5CeXRlcyxcbiAgZGF0YUxvY2F0aW9uU3RyaW5nVG9FbnVtLFxuICBpc0dwdUJ1ZmZlclN1cHBvcnRlZFR5cGUsXG4gIGlzTUxUZW5zb3JTdXBwb3J0ZWRUeXBlLFxuICBsb2dMZXZlbFN0cmluZ1RvRW51bSxcbiAgdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcsXG4gIHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtLFxuICB0ZW5zb3JUeXBlVG9UeXBlZEFycmF5Q29uc3RydWN0b3IsXG59IGZyb20gJy4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgZ2V0SW5zdGFuY2UgfSBmcm9tICcuL3dhc20tZmFjdG9yeSc7XG5pbXBvcnQgeyBhbGxvY1dhc21TdHJpbmcsIGNoZWNrTGFzdEVycm9yIH0gZnJvbSAnLi93YXNtLXV0aWxzJztcbmltcG9ydCB7IGxvYWRGaWxlIH0gZnJvbSAnLi93YXNtLXV0aWxzLWxvYWQtZmlsZSc7XG5cbi8vICNyZWdpb24gSW5pdGlhbGl6YXRpb25zXG5cbi8qKlxuICogVGhlcmUgYXJlIDQgZGlmZmVyZW50IFwiaW5pdGlhbGl6YXRpb25cIiBzdGVwcyBmb3IgT1JULiBUaGV5IGhhcHBlbiBpbiBkaWZmZXJlbnQgcGxhY2VzIGFuZCBkaWZmZXJlbnQgdGltZS5cbiAqXG4gKiAxLiBKYXZhU2NyaXB0IGluaXRpYWxpemF0aW9uIGZvciBvbm54cnVudGltZS1jb21tb24gYW5kIG9ubnhydW50aW1lLXdlYi5cbiAqICAgIFRoaXMgaXMgdGhlIGZpcnN0IGluaXRpYWxpemF0aW9uIHN0ZXAuIEluIHRoaXMgc3RlcCwgb25ueHJ1bnRpbWUtd2ViIGNhbGxzIG9ubnhydW50aW1lLWNvbW1vbidzIHJlZ2lzdGVyQmFja2VuZCgpXG4gKiBmdW5jdGlvbiBtdWx0aXBsZSB0aW1lcyB0byByZWdpc3RlciBhbGwgdGhlIGF2YWlsYWJsZSBiYWNrZW5kcy4gVGhlIGJhY2tlbmQgcmVnaXN0cmF0aW9uIGlzIHZlcnkgZmFzdC4gSXQgb25seVxuICogcmVnaXN0ZXJzIHRoZSBiYWNrZW5kIG5hbWUgd2l0aCB0aGUgdW5pbml0aWFsaXplZCBiYWNrZW5kIG9iamVjdC4gTm8gaGVhdnkgaW5pdGlhbGl6YXRpb24gaXMgZG9uZSBpbiB0aGlzIHN0ZXAuXG4gKiAgICBSZWZlciB0byB3ZWIvbGliL2luZGV4LnRzIGZvciB0aGUgYmFja2VuZCByZWdpc3RyYXRpb24uXG4gKlxuICogMi4gV2ViQXNzZW1ibHkgYXJ0aWZhY3QgaW5pdGlhbGl6YXRpb24uXG4gKiAgICBUaGlzIGhhcHBlbnMgd2hlbiBhbnkgcmVnaXN0ZXJlZCB3YXNtIGJhY2tlbmQgaXMgdXNlZCBmb3IgdGhlIGZpcnN0IHRpbWUgKGllLiBgb3J0LkluZmVyZW5jZVNlc3Npb24uY3JlYXRlKClgIGlzXG4gKiBjYWxsZWQpLiBJbiB0aGlzIHN0ZXAsIG9ubnhydW50aW1lLXdlYiBkb2VzIHRoZSBmb2xsb3dpbmdzOlxuICogICAgIC0gY3JlYXRlIGEgcHJveHkgd29ya2VyIGFuZCBtYWtlIHN1cmUgdGhlIHByb3h5IHdvcmtlciBpcyByZWFkeSB0byByZWNlaXZlIG1lc3NhZ2VzLCBpZiBwcm94eSBpcyBlbmFibGVkLlxuICogICAgIC0gcGVyZm9ybSBmZWF0dXJlIGRldGVjdGlvbiwgbG9jYXRlIGNvcnJlY3QgV2ViQXNzZW1ibHkgYXJ0aWZhY3QgcGF0aCBhbmQgY2FsbCB0aGUgRW1zY3JpcHRlbiBnZW5lcmF0ZWRcbiAqIEphdmFTY3JpcHQgY29kZSB0byBpbml0aWFsaXplIHRoZSBXZWJBc3NlbWJseSBydW50aW1lLlxuICogICAgICAgICAtIGlmIHByb3h5IGlzIGVuYWJsZWQsIHRoaXMgc3RlcCBoYXBwZW5zIGluIHRoZSBwcm94eSB3b3JrZXIgdXNpbmcgbWVzc2FnZSAnaW5pdC13YXNtJy5cbiAqICAgICAgICAgLSBkb3dubG9hZGluZyB0aGUgJ29ydC13YXNtey4uLn0ud2FzbScgZmlsZSBpcyBkb25lIGluIHRoaXMgc3RlcC5cbiAqICAgICAgICAgLSBpZiBtdWx0aS10aHJlYWQgaXMgZW5hYmxlZCwgb25lIG9yIG1vcmUgd2Vid29ya2VyIHdpbGwgYmUgY3JlYXRlZCB0byBpbml0aWFsaXplIHRoZSBQVGhyZWFkIHRocmVhZHBvb2wuXG4gKlxuICogMy4gT1JUIGVudmlyb25tZW50IGluaXRpYWxpemF0aW9uLlxuICogICAgVGhpcyBoYXBwZW5zIGFmdGVyIHN0ZXAgMi4gSW4gdGhpcyBzdGVwLCBvbm54cnVudGltZS13ZWIgcGVyZm9ybXMgT05OWCBSdW50aW1lIGVudmlyb25tZW50IGluaXRpYWxpemF0aW9uLlxuICogRnVuY3Rpb24gYF9PcnRJbml0KClgIGlzIGNhbGxlZCBpbiB0aGlzIHN0ZXAuXG4gKiAgICAgLSBpZiBwcm94eSBpcyBlbmFibGVkLCB0aGlzIHN0ZXAgaGFwcGVucyBpbiB0aGUgcHJveHkgd29ya2VyIHVzaW5nIG1lc3NhZ2UgJ2luaXQtb3J0Jy5cbiAqICAgICAtIGxvZ2dpbmcgbGV2ZWwgKG9ydC5lbnYubG9nTGV2ZWwpIGFuZCB0aHJlYWQgbnVtYmVyIChvcnQuZW52Lndhc20ubnVtVGhyZWFkcykgYXJlIHNldCBpbiB0aGlzIHN0ZXAuXG4gKlxuICogNC4gU2Vzc2lvbiBpbml0aWFsaXphdGlvbi5cbiAqICAgIFRoaXMgaGFwcGVucyB3aGVuIGBvcnQuSW5mZXJlbmNlU2Vzc2lvbi5jcmVhdGUoKWAgaXMgY2FsbGVkLiBVbmxpa2UgdGhlIGZpcnN0IDMgc3RlcHMgKHRoZXkgb25seSBjYWxsZWQgb25jZSksXG4gKiB0aGlzIHN0ZXAgd2lsbCBiZSBkb25lIGZvciBlYWNoIHNlc3Npb24uIEluIHRoaXMgc3RlcCwgb25ueHJ1bnRpbWUtd2ViIGRvZXMgdGhlIGZvbGxvd2luZ3M6XG4gKiAgICBJZiB0aGUgcGFyYW1ldGVyIGlzIGEgVVJMOlxuICogICAgLSBkb3dubG9hZCB0aGUgbW9kZWwgZGF0YSBmcm9tIHRoZSBVUkwuXG4gKiAgICAtIGNvcHkgdGhlIG1vZGVsIGRhdGEgdG8gdGhlIFdBU00gaGVhcC4gKHByb3h5OiAnY29weS1mcm9tJylcbiAqICAgIC0gZGVyZWZlcmVuY2UgdGhlIG1vZGVsIGJ1ZmZlci4gVGhpcyBzdGVwIGFsbG93cyB0aGUgb3JpZ2luYWwgQXJyYXlCdWZmZXIgdG8gYmUgZ2FyYmFnZSBjb2xsZWN0ZWQuXG4gKiAgICAtIGNhbGwgYF9PcnRDcmVhdGVTZXNzaW9uKClgIHRvIGNyZWF0ZSB0aGUgc2Vzc2lvbi4gKHByb3h5OiAnY3JlYXRlJylcbiAqXG4gKiAgICBJZiB0aGUgcGFyYW1ldGVyIGlzIGEgVWludDhBcnJheSBvYmplY3Q6XG4gKiAgICAtIGNvcHkgdGhlIG1vZGVsIGRhdGEgdG8gdGhlIFdBU00gaGVhcC4gKHByb3h5OiAnY29weS1mcm9tJylcbiAqICAgIC0gY2FsbCBgX09ydENyZWF0ZVNlc3Npb24oKWAgdG8gY3JlYXRlIHRoZSBzZXNzaW9uLiAocHJveHk6ICdjcmVhdGUnKVxuICpcbiAqXG4gKi9cblxuLyoqXG4gKiBpbml0aWFsaXplIE9SVCBlbnZpcm9ubWVudC5cbiAqXG4gKiBAcGFyYW0gbnVtVGhyZWFkcyBTZXRHbG9iYWxJbnRyYU9wTnVtVGhyZWFkcyhudW1UaHJlYWRzKVxuICogQHBhcmFtIGxvZ2dpbmdMZXZlbCBDcmVhdGVFbnYoc3RhdGljX2Nhc3Q8T3J0TG9nZ2luZ0xldmVsPihsb2dnaW5nX2xldmVsKSlcbiAqL1xuY29uc3QgaW5pdE9ydCA9IChudW1UaHJlYWRzOiBudW1iZXIsIGxvZ2dpbmdMZXZlbDogbnVtYmVyKTogdm9pZCA9PiB7XG4gIGNvbnN0IGVycm9yQ29kZSA9IGdldEluc3RhbmNlKCkuX09ydEluaXQobnVtVGhyZWFkcywgbG9nZ2luZ0xldmVsKTtcbiAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xuICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgaW5pdGlhbGl6ZSBvbm54cnVudGltZS5cIik7XG4gIH1cbn07XG5cbi8qKlxuICogaW5pdGlhbGl6ZSBydW50aW1lIGVudmlyb25tZW50LlxuICogQHBhcmFtIGVudiBwYXNzZWQgaW4gdGhlIGVudmlyb25tZW50IGNvbmZpZyBvYmplY3QuXG4gKi9cbmV4cG9ydCBjb25zdCBpbml0UnVudGltZSA9IGFzeW5jIChlbnY6IEVudik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAvLyBpbml0IE9SVFxuICBpbml0T3J0KGVudi53YXNtLm51bVRocmVhZHMhLCBsb2dMZXZlbFN0cmluZ1RvRW51bShlbnYubG9nTGV2ZWwpKTtcbn07XG5cbi8qKlxuICogcGVyZm9ybSBFUCBzcGVjaWZpYyBpbml0aWFsaXphdGlvbi5cbiAqXG4gKiBAcGFyYW0gZW52XG4gKiBAcGFyYW0gZXBOYW1lXG4gKi9cbmV4cG9ydCBjb25zdCBpbml0RXAgPSBhc3luYyAoZW52OiBFbnYsIGVwTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIC8vIGluaXRpYWxpemUgQVNZTkNJRlkgc3VwcG9ydFxuICBnZXRJbnN0YW5jZSgpLmFzeW5jSW5pdD8uKCk7XG5cbiAgLy8gcGVyZm9ybSBXZWJHUFUgYXZhaWxhYmlsaXR5IGNoZWNrICggZWl0aGVyIEpTRVAgb3IgV2ViR1BVIEVQIClcbiAgbGV0IHdlYmdwdUFkYXB0ZXIgPSBlbnYud2ViZ3B1LmFkYXB0ZXIgYXMgR1BVQWRhcHRlciB8IG51bGw7XG4gIGlmIChlcE5hbWUgPT09ICd3ZWJncHUnKSB7XG4gICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgPT09ICd1bmRlZmluZWQnIHx8ICFuYXZpZ2F0b3IuZ3B1KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlYkdQVSBpcyBub3Qgc3VwcG9ydGVkIGluIGN1cnJlbnQgZW52aXJvbm1lbnQnKTtcbiAgICB9XG4gICAgaWYgKCF3ZWJncHVBZGFwdGVyKSB7XG4gICAgICAvLyBpZiBhZGFwdGVyIGlzIG5vdCBzZXQsIHJlcXVlc3QgYSBuZXcgYWRhcHRlci5cbiAgICAgIGNvbnN0IHBvd2VyUHJlZmVyZW5jZSA9IGVudi53ZWJncHUucG93ZXJQcmVmZXJlbmNlO1xuICAgICAgaWYgKHBvd2VyUHJlZmVyZW5jZSAhPT0gdW5kZWZpbmVkICYmIHBvd2VyUHJlZmVyZW5jZSAhPT0gJ2xvdy1wb3dlcicgJiYgcG93ZXJQcmVmZXJlbmNlICE9PSAnaGlnaC1wZXJmb3JtYW5jZScpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHBvd2VyUHJlZmVyZW5jZSBzZXR0aW5nOiBcIiR7cG93ZXJQcmVmZXJlbmNlfVwiYCk7XG4gICAgICB9XG4gICAgICBjb25zdCBmb3JjZUZhbGxiYWNrQWRhcHRlciA9IGVudi53ZWJncHUuZm9yY2VGYWxsYmFja0FkYXB0ZXI7XG4gICAgICBpZiAoZm9yY2VGYWxsYmFja0FkYXB0ZXIgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgZm9yY2VGYWxsYmFja0FkYXB0ZXIgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgZm9yY2VGYWxsYmFja0FkYXB0ZXIgc2V0dGluZzogXCIke2ZvcmNlRmFsbGJhY2tBZGFwdGVyfVwiYCk7XG4gICAgICB9XG4gICAgICB3ZWJncHVBZGFwdGVyID0gYXdhaXQgbmF2aWdhdG9yLmdwdS5yZXF1ZXN0QWRhcHRlcih7IHBvd2VyUHJlZmVyZW5jZSwgZm9yY2VGYWxsYmFja0FkYXB0ZXIgfSk7XG4gICAgICBpZiAoIXdlYmdwdUFkYXB0ZXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICdGYWlsZWQgdG8gZ2V0IEdQVSBhZGFwdGVyLiAnICtcbiAgICAgICAgICAgICdZb3UgbWF5IG5lZWQgdG8gZW5hYmxlIGZsYWcgXCItLWVuYWJsZS11bnNhZmUtd2ViZ3B1XCIgaWYgeW91IGFyZSB1c2luZyBDaHJvbWUuJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgYWRhcHRlciBpcyBzZXQsIHZhbGlkYXRlIGl0LlxuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2Ygd2ViZ3B1QWRhcHRlci5saW1pdHMgIT09ICdvYmplY3QnIHx8XG4gICAgICAgIHR5cGVvZiB3ZWJncHVBZGFwdGVyLmZlYXR1cmVzICE9PSAnb2JqZWN0JyB8fFxuICAgICAgICB0eXBlb2Ygd2ViZ3B1QWRhcHRlci5yZXF1ZXN0RGV2aWNlICE9PSAnZnVuY3Rpb24nXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEdQVSBhZGFwdGVyIHNldCBpbiBgZW52LndlYmdwdS5hZGFwdGVyYC4gSXQgbXVzdCBiZSBhIEdQVUFkYXB0ZXIgb2JqZWN0LicpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIHBlcmZvcm0gV2ViTk4gYXZhaWxhYmlsaXR5IGNoZWNrICggZWl0aGVyIEpTRVAgb3IgV2ViTk4gRVAgKVxuICBpZiAoZXBOYW1lID09PSAnd2Vibm4nKSB7XG4gICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgPT09ICd1bmRlZmluZWQnIHx8ICEobmF2aWdhdG9yIGFzIHVua25vd24gYXMgeyBtbDogdW5rbm93biB9KS5tbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdXZWJOTiBpcyBub3Qgc3VwcG9ydGVkIGluIGN1cnJlbnQgZW52aXJvbm1lbnQnKTtcbiAgICB9XG4gIH1cblxuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMsIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbiAgICBjb25zdCBpbml0SnNlcCA9IHJlcXVpcmUoJy4vanNlcC9pbml0JykuaW5pdDtcblxuICAgIGlmIChlcE5hbWUgPT09ICd3ZWJncHUnKSB7XG4gICAgICBhd2FpdCBpbml0SnNlcCgnd2ViZ3B1JywgZ2V0SW5zdGFuY2UoKSwgZW52LCB3ZWJncHVBZGFwdGVyKTtcbiAgICB9XG4gICAgaWYgKGVwTmFtZSA9PT0gJ3dlYm5uJykge1xuICAgICAgYXdhaXQgaW5pdEpzZXAoJ3dlYm5uJywgZ2V0SW5zdGFuY2UoKSwgZW52KTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVICYmIGVwTmFtZSA9PT0gJ3dlYmdwdScpIHtcbiAgICAgIGdldEluc3RhbmNlKCkud2ViZ3B1SW5pdCEoKGRldmljZSkgPT4ge1xuICAgICAgICBlbnYud2ViZ3B1LmRldmljZSA9IGRldmljZTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XRUJOTiAmJiBlcE5hbWUgPT09ICd3ZWJubicpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgICBjb25zdCBiYWNrZW5kID0gbmV3IChyZXF1aXJlKCcuL2pzZXAvYmFja2VuZC13ZWJubicpLldlYk5OQmFja2VuZCkoZW52KTtcbiAgICAgIGdldEluc3RhbmNlKCkud2Vibm5Jbml0IShbXG4gICAgICAgIGJhY2tlbmQsXG4gICAgICAgIC8vIHdlYm5uUmVzZXJ2ZVRlbnNvcklkXG4gICAgICAgICgpID0+IGJhY2tlbmQucmVzZXJ2ZVRlbnNvcklkKCksXG4gICAgICAgIC8vIHdlYm5uUmVsZWFzZVRlbnNvcklkLFxuICAgICAgICAodGVuc29ySWQ6IG51bWJlcikgPT4gYmFja2VuZC5yZWxlYXNlVGVuc29ySWQodGVuc29ySWQpLFxuICAgICAgICAvLyB3ZWJubkVuc3VyZVRlbnNvclxuICAgICAgICBhc3luYyAoc2Vzc2lvbklkOiBudW1iZXIgfCB1bmRlZmluZWQsIHRlbnNvcklkOiBudW1iZXIsIG9ubnhEYXRhVHlwZTogbnVtYmVyLCBzaGFwZTogbnVtYmVyW10sIGNvcHlPbGQpID0+XG4gICAgICAgICAgYmFja2VuZC5lbnN1cmVUZW5zb3Ioc2Vzc2lvbklkLCB0ZW5zb3JJZCwgb25ueERhdGFUeXBlLCBzaGFwZSwgY29weU9sZCksXG4gICAgICAgIC8vIHdlYm5uVXBsb2FkVGVuc29yXG4gICAgICAgICh0ZW5zb3JJZDogbnVtYmVyLCBkYXRhOiBVaW50OEFycmF5KSA9PiB7XG4gICAgICAgICAgYmFja2VuZC51cGxvYWRUZW5zb3IodGVuc29ySWQsIGRhdGEpO1xuICAgICAgICB9LFxuICAgICAgICAvLyB3ZWJubkRvd25sb2FkVGVuc29yXG4gICAgICAgIGFzeW5jICh0ZW5zb3JJZDogbnVtYmVyLCBkc3RCdWZmZXI6IEFycmF5QnVmZmVyVmlldyB8IEFycmF5QnVmZmVyKSA9PlxuICAgICAgICAgIGJhY2tlbmQuZG93bmxvYWRUZW5zb3IodGVuc29ySWQsIGRzdEJ1ZmZlciksXG4gICAgICAgIC8vIHdlYm5uUmVnaXN0ZXJNTENvbnRleHRcbiAgICAgICAgKHNlc3Npb25JZDogbnVtYmVyLCBtbENvbnRleHQ6IE1MQ29udGV4dCkgPT4gYmFja2VuZC5yZWdpc3Rlck1MQ29udGV4dChzZXNzaW9uSWQsIG1sQ29udGV4dCksXG4gICAgICAgIC8vIHdlYm5uRW5hYmxlVHJhY2VFdmVudFxuICAgICAgICAhIWVudi50cmFjZSxcbiAgICAgIF0pO1xuICAgIH1cbiAgfVxufTtcblxuLy8gI2VuZHJlZ2lvbiBJbml0aWFsaXphdGlvbnNcblxuLyoqXG4gKiB2YWxpZCBkYXRhIGxvY2F0aW9ucyBmb3IgaW5wdXQvb3V0cHV0IHRlbnNvcnMuXG4gKi9cbnR5cGUgU3VwcG9ydGVkVGVuc29yRGF0YUxvY2F0aW9uRm9ySW5wdXRPdXRwdXQgPVxuICB8ICdjcHUnXG4gIHwgJ2NwdS1waW5uZWQnXG4gIHwgJ2dwdS1idWZmZXInXG4gIHwgJ21sLXRlbnNvcidcbiAgLy8gVXNlICdtbC10ZW5zb3InIGR1cmluZyBpbmZlcmVuY2UsIGJ1dCBvdXRwdXQgYSB0ZW5zb3IgbG9jYXRlZCBvbiB0aGUgQ1BVLlxuICB8ICdtbC10ZW5zb3ItY3B1LW91dHB1dCc7XG5cbnR5cGUgSU9CaW5kaW5nU3RhdGUgPSB7XG4gIC8qKlxuICAgKiB0aGUgaGFuZGxlIG9mIElPIGJpbmRpbmcuXG4gICAqL1xuICByZWFkb25seSBoYW5kbGU6IG51bWJlcjtcblxuICAvKipcbiAgICogdGhlIHByZWZlcnJlZCBsb2NhdGlvbiBmb3IgZWFjaCBvdXRwdXQgdGVuc29yLlxuICAgKlxuICAgKiB2YWx1ZSBpcyBvbmUgb2YgJ2NwdScsICdjcHUtcGlubmVkJywgJ2dwdS1idWZmZXInLCAnbWwtdGVuc29yJy5cbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dFByZWZlcnJlZExvY2F0aW9uczogcmVhZG9ubHkgU3VwcG9ydGVkVGVuc29yRGF0YUxvY2F0aW9uRm9ySW5wdXRPdXRwdXRbXTtcblxuICAvKipcbiAgICogZW51bSB2YWx1ZSBvZiB0aGUgcHJlZmVycmVkIGxvY2F0aW9uIGZvciBlYWNoIG91dHB1dCB0ZW5zb3IuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnNFbmNvZGVkOiByZWFkb25seSBudW1iZXJbXTtcbn07XG5cbi8qKlxuICogIHR1cGxlIGVsZW1lbnRzIGFyZTogSW5mZXJlbmNlU2Vzc2lvbiBJRDsgaW5wdXROYW1lc1VURjhFbmNvZGVkOyBvdXRwdXROYW1lc1VURjhFbmNvZGVkOyBiaW5kaW5nU3RhdGVcbiAqL1xudHlwZSBTZXNzaW9uTWV0YWRhdGEgPSBbXG4gIGluZmVyZW5jZVNlc3Npb25JZDogbnVtYmVyLFxuICBpbnB1dE5hbWVzVVRGOEVuY29kZWQ6IG51bWJlcltdLFxuICBvdXRwdXROYW1lc1VURjhFbmNvZGVkOiBudW1iZXJbXSxcbiAgYmluZGluZ1N0YXRlOiBJT0JpbmRpbmdTdGF0ZSB8IG51bGwsXG4gIGVuYWJsZUdyYXBoQ2FwdHVyZTogYm9vbGVhbixcbiAgaW5wdXRPdXRwdXRCb3VuZDogYm9vbGVhbixcbl07XG5cbmNvbnN0IGFjdGl2ZVNlc3Npb25zID0gbmV3IE1hcDxudW1iZXIsIFNlc3Npb25NZXRhZGF0YT4oKTtcblxuLyoqXG4gKiBnZXQgdGhlIGlucHV0L291dHB1dCBjb3VudCBvZiB0aGUgc2Vzc2lvbi5cbiAqIEBwYXJhbSBzZXNzaW9uSGFuZGxlIHRoZSBoYW5kbGUgcmVwcmVzZW50aW5nIHRoZSBzZXNzaW9uLiBzaG91bGQgYmUgbm9uLXplcm8uXG4gKiBAcmV0dXJucyBhIHR1cGxlIGluY2x1ZGluZyAyIG51bWJlcnMsIHJlcHJlc2VudGluZyB0aGUgaW5wdXQgY291bnQgYW5kIG91dHB1dCBjb3VudC5cbiAqL1xuY29uc3QgZ2V0U2Vzc2lvbklucHV0T3V0cHV0Q291bnQgPSAoc2Vzc2lvbkhhbmRsZTogbnVtYmVyKTogW251bWJlciwgbnVtYmVyXSA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBjb25zdCBzdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XG4gIHRyeSB7XG4gICAgY29uc3QgcHRyU2l6ZSA9IHdhc20uUFRSX1NJWkU7XG4gICAgY29uc3QgZGF0YU9mZnNldCA9IHdhc20uc3RhY2tBbGxvYygyICogcHRyU2l6ZSk7XG4gICAgY29uc3QgZXJyb3JDb2RlID0gd2FzbS5fT3J0R2V0SW5wdXRPdXRwdXRDb3VudChzZXNzaW9uSGFuZGxlLCBkYXRhT2Zmc2V0LCBkYXRhT2Zmc2V0ICsgcHRyU2l6ZSk7XG4gICAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBnZXQgc2Vzc2lvbiBpbnB1dC9vdXRwdXQgY291bnQuXCIpO1xuICAgIH1cbiAgICBjb25zdCB0eXBlID0gcHRyU2l6ZSA9PT0gNCA/ICdpMzInIDogJ2k2NCc7XG4gICAgcmV0dXJuIFtOdW1iZXIod2FzbS5nZXRWYWx1ZShkYXRhT2Zmc2V0LCB0eXBlKSksIE51bWJlcih3YXNtLmdldFZhbHVlKGRhdGFPZmZzZXQgKyBwdHJTaXplLCB0eXBlKSldO1xuICB9IGZpbmFsbHkge1xuICAgIHdhc20uc3RhY2tSZXN0b3JlKHN0YWNrKTtcbiAgfVxufTtcblxuY29uc3QgZ2V0U2Vzc2lvbklucHV0T3V0cHV0TWV0YWRhdGEgPSAoXG4gIHNlc3Npb25IYW5kbGU6IG51bWJlcixcbiAgaW5kZXg6IG51bWJlcixcbik6IFtuYW1lT2Zmc2V0OiBudW1iZXIsIGVsZW1lbnRUeXBlOiBudW1iZXIsIGRpbXM/OiBBcnJheTxudW1iZXIgfCBzdHJpbmc+XSA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBjb25zdCBzdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XG4gIGxldCBtZXRhZGF0YU9mZnNldCA9IDA7XG4gIHRyeSB7XG4gICAgY29uc3QgcHRyU2l6ZSA9IHdhc20uUFRSX1NJWkU7XG4gICAgY29uc3QgZGF0YU9mZnNldCA9IHdhc20uc3RhY2tBbGxvYygyICogcHRyU2l6ZSk7XG4gICAgY29uc3QgZXJyb3JDb2RlID0gd2FzbS5fT3J0R2V0SW5wdXRPdXRwdXRNZXRhZGF0YShzZXNzaW9uSGFuZGxlLCBpbmRleCwgZGF0YU9mZnNldCwgZGF0YU9mZnNldCArIHB0clNpemUpO1xuICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgZ2V0IHNlc3Npb24gaW5wdXQvb3V0cHV0IG1ldGFkYXRhLlwiKTtcbiAgICB9XG4gICAgY29uc3QgbmFtZU9mZnNldCA9IE51bWJlcih3YXNtLmdldFZhbHVlKGRhdGFPZmZzZXQsICcqJykpO1xuICAgIG1ldGFkYXRhT2Zmc2V0ID0gTnVtYmVyKHdhc20uZ2V0VmFsdWUoZGF0YU9mZnNldCArIHB0clNpemUsICcqJykpO1xuICAgIC8vIGdldCBlbGVtZW50IHR5cGVcbiAgICBjb25zdCBlbGVtZW50VHlwZSA9IHdhc20uSEVBUDMyW21ldGFkYXRhT2Zmc2V0IC8gNF07XG4gICAgaWYgKGVsZW1lbnRUeXBlID09PSAwKSB7XG4gICAgICByZXR1cm4gW25hbWVPZmZzZXQsIDBdOyAvLyBub24tdGVuc29yXG4gICAgfVxuXG4gICAgLy8gZ2V0IGRpbXMgY291bnRcbiAgICBjb25zdCBkaW1zQ291bnQgPSB3YXNtLkhFQVBVMzJbbWV0YWRhdGFPZmZzZXQgLyA0ICsgMV07XG4gICAgLy8gZ2V0IGRpbXNcbiAgICBjb25zdCBkaW1zOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+ID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1zQ291bnQ7IGkrKykge1xuICAgICAgY29uc3Qgc3ltYm9saWNEaW1OYW1lT2Zmc2V0ID0gTnVtYmVyKHdhc20uZ2V0VmFsdWUobWV0YWRhdGFPZmZzZXQgKyA4ICsgaSAqIHB0clNpemUsICcqJykpO1xuICAgICAgZGltcy5wdXNoKFxuICAgICAgICBzeW1ib2xpY0RpbU5hbWVPZmZzZXQgIT09IDBcbiAgICAgICAgICA/IHdhc20uVVRGOFRvU3RyaW5nKHN5bWJvbGljRGltTmFtZU9mZnNldClcbiAgICAgICAgICA6IE51bWJlcih3YXNtLmdldFZhbHVlKG1ldGFkYXRhT2Zmc2V0ICsgOCArIChpICsgZGltc0NvdW50KSAqIHB0clNpemUsICcqJykpLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIFtuYW1lT2Zmc2V0LCBlbGVtZW50VHlwZSwgZGltc107XG4gIH0gZmluYWxseSB7XG4gICAgd2FzbS5zdGFja1Jlc3RvcmUoc3RhY2spO1xuICAgIGlmIChtZXRhZGF0YU9mZnNldCAhPT0gMCkge1xuICAgICAgd2FzbS5fT3J0RnJlZShtZXRhZGF0YU9mZnNldCk7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIGFsbG9jYXRlIHRoZSBtZW1vcnkgYW5kIG1lbWNweSB0aGUgZXh0ZXJuYWwgYnVmZmVyLlxuICpcbiAqIEBwYXJhbSBtb2RlbCAtIHRoZSBleHRlcm5hbCBidWZmZXIgY29udGFpbmluZyB0aGUgbW9kZWwgZGF0YS4gTXVzdCBub3QgYmUgdGhlIHNhbWUgYnVmZmVyIGFzIHRoZSBXQVNNIGhlYXAuXG4gKiBAcmV0dXJucyBhIDItZWxlbWVudHMgdHVwbGUgLSB0aGUgcG9pbnRlciBhbmQgc2l6ZSBvZiB0aGUgYWxsb2NhdGVkIGJ1ZmZlclxuICovXG5leHBvcnQgY29uc3QgY29weUZyb21FeHRlcm5hbEJ1ZmZlciA9IChtb2RlbDogVWludDhBcnJheSk6IFtudW1iZXIsIG51bWJlcl0gPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3QgbW9kZWxEYXRhT2Zmc2V0ID0gd2FzbS5fbWFsbG9jKG1vZGVsLmJ5dGVMZW5ndGgpO1xuICBpZiAobW9kZWxEYXRhT2Zmc2V0ID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBjcmVhdGUgYSBzZXNzaW9uLiBmYWlsZWQgdG8gYWxsb2NhdGUgYSBidWZmZXIgb2Ygc2l6ZSAke21vZGVsLmJ5dGVMZW5ndGh9LmApO1xuICB9XG4gIHdhc20uSEVBUFU4LnNldChtb2RlbCwgbW9kZWxEYXRhT2Zmc2V0KTtcbiAgcmV0dXJuIFttb2RlbERhdGFPZmZzZXQsIG1vZGVsLmJ5dGVMZW5ndGhdO1xufTtcblxuLyoqXG4gKiBjcmVhdGUgYW4gaW5mZXJlbmNlIHNlc3Npb24gZnJvbSBhIG1vZGVsIGRhdGEgYnVmZmVyLlxuICpcbiAqIEBwYXJhbSBtb2RlbERhdGEgLSBlaXRoZXIgYSBVaW50OEFycmF5IG9iamVjdCByZXByZXNlbnRpbmcgdGhlIG1vZGVsIGRhdGEsIG9yIGEgMi1lbGVtZW50cyB0dXBsZSBjb250YWluaW5nIHRoZVxuICogICAgIHBvaW50ZXIgYW5kIHNpemUgb2YgdGhlIG1vZGVsIGRhdGEgYnVmZmVyLlxuICogQHBhcmFtIG9wdGlvbnMgYW4gb3B0aW9uYWwgc2Vzc2lvbiBvcHRpb25zIG9iamVjdC5cbiAqIEByZXR1cm5zIGEgMy1lbGVtZW50cyB0dXBsZSBjb250YWluaW5nIFtzZXNzaW9uIGhhbmRsZSwgaW5wdXQgbmFtZXMsIG91dHB1dCBuYW1lc11cbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZVNlc3Npb24gPSBhc3luYyAoXG4gIG1vZGVsRGF0YTogVWludDhBcnJheSB8IFNlcmlhbGl6YWJsZUludGVybmFsQnVmZmVyLFxuICBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyxcbik6IFByb21pc2U8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPiA9PiB7XG4gIGxldCBtb2RlbERhdGFPZmZzZXQ6IG51bWJlciwgbW9kZWxEYXRhTGVuZ3RoOiBudW1iZXI7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuXG4gIGlmIChBcnJheS5pc0FycmF5KG1vZGVsRGF0YSkpIHtcbiAgICAvLyBpZiBtb2RlbCBkYXRhIGlzIGFuIGFycmF5LCBpdCBtdXN0IGJlIGEgMi1lbGVtZW50cyB0dXBsZSBjb250YWluaW5nIHRoZSBwb2ludGVyIGFuZCBzaXplIG9mIHRoZSBtb2RlbCBkYXRhXG4gICAgW21vZGVsRGF0YU9mZnNldCwgbW9kZWxEYXRhTGVuZ3RoXSA9IG1vZGVsRGF0YTtcbiAgfSBlbHNlIGlmIChtb2RlbERhdGEuYnVmZmVyID09PSB3YXNtLkhFQVBVOC5idWZmZXIpIHtcbiAgICAvLyBpZiBtb2RlbCBkYXRhIHVzZXMgdGhlIHNhbWUgYnVmZmVyIGFzIHRoZSBXQVNNIGhlYXAsIHdlIGRvbid0IG5lZWQgdG8gY29weSBpdC5cbiAgICBbbW9kZWxEYXRhT2Zmc2V0LCBtb2RlbERhdGFMZW5ndGhdID0gW21vZGVsRGF0YS5ieXRlT2Zmc2V0LCBtb2RlbERhdGEuYnl0ZUxlbmd0aF07XG4gIH0gZWxzZSB7XG4gICAgLy8gb3RoZXJ3aXNlLCBjb3B5IHRoZSBtb2RlbCBkYXRhIHRvIHRoZSBXQVNNIGhlYXAuXG4gICAgW21vZGVsRGF0YU9mZnNldCwgbW9kZWxEYXRhTGVuZ3RoXSA9IGNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIobW9kZWxEYXRhKTtcbiAgfVxuXG4gIGxldCBzZXNzaW9uSGFuZGxlID0gMDtcbiAgbGV0IHNlc3Npb25PcHRpb25zSGFuZGxlID0gMDtcbiAgbGV0IGlvQmluZGluZ0hhbmRsZSA9IDA7XG4gIGxldCBhbGxvY3M6IG51bWJlcltdID0gW107XG4gIGNvbnN0IGlucHV0TmFtZXNVVEY4RW5jb2RlZCA9IFtdO1xuICBjb25zdCBvdXRwdXROYW1lc1VURjhFbmNvZGVkID0gW107XG5cbiAgdHJ5IHtcbiAgICBbc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGFsbG9jc10gPSBhd2FpdCBzZXRTZXNzaW9uT3B0aW9ucyhvcHRpb25zKTtcblxuICAgIGlmIChvcHRpb25zPy5leHRlcm5hbERhdGEgJiYgd2FzbS5tb3VudEV4dGVybmFsRGF0YSkge1xuICAgICAgY29uc3QgbG9hZGluZ1Byb21pc2VzID0gW107XG4gICAgICBmb3IgKGNvbnN0IGZpbGUgb2Ygb3B0aW9ucy5leHRlcm5hbERhdGEpIHtcbiAgICAgICAgY29uc3QgcGF0aCA9IHR5cGVvZiBmaWxlID09PSAnc3RyaW5nJyA/IGZpbGUgOiBmaWxlLnBhdGg7XG4gICAgICAgIGxvYWRpbmdQcm9taXNlcy5wdXNoKFxuICAgICAgICAgIGxvYWRGaWxlKHR5cGVvZiBmaWxlID09PSAnc3RyaW5nJyA/IGZpbGUgOiBmaWxlLmRhdGEpLnRoZW4oKGRhdGEpID0+IHtcbiAgICAgICAgICAgIHdhc20ubW91bnRFeHRlcm5hbERhdGEocGF0aCwgZGF0YSk7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIHdhaXQgZm9yIGFsbCBleHRlcm5hbCBkYXRhIGZpbGVzIHRvIGJlIGxvYWRlZFxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwobG9hZGluZ1Byb21pc2VzKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHByb3ZpZGVyIG9mIG9wdGlvbnM/LmV4ZWN1dGlvblByb3ZpZGVycyA/PyBbXSkge1xuICAgICAgY29uc3QgcHJvdmlkZXJOYW1lID0gdHlwZW9mIHByb3ZpZGVyID09PSAnc3RyaW5nJyA/IHByb3ZpZGVyIDogcHJvdmlkZXIubmFtZTtcbiAgICAgIGlmIChwcm92aWRlck5hbWUgPT09ICd3ZWJubicpIHtcbiAgICAgICAgd2FzbS5zaG91bGRUcmFuc2ZlclRvTUxUZW5zb3IgPSBmYWxzZTtcbiAgICAgICAgaWYgKHR5cGVvZiBwcm92aWRlciAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBjb25zdCB3ZWJubk9wdGlvbnMgPSBwcm92aWRlciBhcyBJbmZlcmVuY2VTZXNzaW9uLldlYk5ORXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgICAgICAgY29uc3QgY29udGV4dCA9ICh3ZWJubk9wdGlvbnMgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJOTk9wdGlvbnNXaXRoTUxDb250ZXh0KT8uY29udGV4dDtcbiAgICAgICAgICBjb25zdCBncHVEZXZpY2UgPSAod2Vibm5PcHRpb25zIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViTk5PcHRpb25zV2ViR3B1KT8uZ3B1RGV2aWNlO1xuICAgICAgICAgIGNvbnN0IGRldmljZVR5cGUgPSAod2Vibm5PcHRpb25zIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViTk5Db250ZXh0T3B0aW9ucyk/LmRldmljZVR5cGU7XG4gICAgICAgICAgY29uc3QgcG93ZXJQcmVmZXJlbmNlID0gKHdlYm5uT3B0aW9ucyBhcyBJbmZlcmVuY2VTZXNzaW9uLldlYk5OQ29udGV4dE9wdGlvbnMpPy5wb3dlclByZWZlcmVuY2U7XG4gICAgICAgICAgaWYgKGNvbnRleHQpIHtcbiAgICAgICAgICAgIHdhc20uY3VycmVudENvbnRleHQgPSBjb250ZXh0IGFzIE1MQ29udGV4dDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGdwdURldmljZSkge1xuICAgICAgICAgICAgd2FzbS5jdXJyZW50Q29udGV4dCA9IGF3YWl0IHdhc20ud2Vibm5DcmVhdGVNTENvbnRleHQhKGdwdURldmljZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdhc20uY3VycmVudENvbnRleHQgPSBhd2FpdCB3YXNtLndlYm5uQ3JlYXRlTUxDb250ZXh0ISh7IGRldmljZVR5cGUsIHBvd2VyUHJlZmVyZW5jZSB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgd2FzbS5jdXJyZW50Q29udGV4dCA9IGF3YWl0IHdhc20ud2Vibm5DcmVhdGVNTENvbnRleHQhKCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgc2Vzc2lvbkhhbmRsZSA9IGF3YWl0IHdhc20uX09ydENyZWF0ZVNlc3Npb24obW9kZWxEYXRhT2Zmc2V0LCBtb2RlbERhdGFMZW5ndGgsIHNlc3Npb25PcHRpb25zSGFuZGxlKTtcbiAgICB3YXNtLndlYmdwdU9uQ3JlYXRlU2Vzc2lvbj8uKHNlc3Npb25IYW5kbGUpO1xuICAgIGlmIChzZXNzaW9uSGFuZGxlID09PSAwKSB7XG4gICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGNyZWF0ZSBhIHNlc3Npb24uXCIpO1xuICAgIH1cblxuICAgIHdhc20uanNlcE9uQ3JlYXRlU2Vzc2lvbj8uKCk7XG5cbiAgICAvLyBjbGVhciBjdXJyZW50IE1MQ29udGV4dCBhZnRlciBzZXNzaW9uIGNyZWF0aW9uXG4gICAgaWYgKHdhc20uY3VycmVudENvbnRleHQpIHtcbiAgICAgIHdhc20ud2Vibm5SZWdpc3Rlck1MQ29udGV4dCEoc2Vzc2lvbkhhbmRsZSwgd2FzbS5jdXJyZW50Q29udGV4dCk7XG4gICAgICB3YXNtLmN1cnJlbnRDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgd2FzbS5zaG91bGRUcmFuc2ZlclRvTUxUZW5zb3IgPSB0cnVlO1xuICAgIH1cblxuICAgIGNvbnN0IFtpbnB1dENvdW50LCBvdXRwdXRDb3VudF0gPSBnZXRTZXNzaW9uSW5wdXRPdXRwdXRDb3VudChzZXNzaW9uSGFuZGxlKTtcblxuICAgIGNvbnN0IGVuYWJsZUdyYXBoQ2FwdHVyZSA9ICEhb3B0aW9ucz8uZW5hYmxlR3JhcGhDYXB0dXJlO1xuXG4gICAgY29uc3QgaW5wdXROYW1lcyA9IFtdO1xuICAgIGNvbnN0IG91dHB1dE5hbWVzID0gW107XG4gICAgY29uc3QgaW5wdXRNZXRhZGF0YTogSW5mZXJlbmNlU2Vzc2lvbi5WYWx1ZU1ldGFkYXRhW10gPSBbXTtcbiAgICBjb25zdCBvdXRwdXRNZXRhZGF0YTogSW5mZXJlbmNlU2Vzc2lvbi5WYWx1ZU1ldGFkYXRhW10gPSBbXTtcbiAgICBjb25zdCBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnM6IFN1cHBvcnRlZFRlbnNvckRhdGFMb2NhdGlvbkZvcklucHV0T3V0cHV0W10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Q291bnQ7IGkrKykge1xuICAgICAgY29uc3QgW25hbWVPZmZzZXQsIGVsZW1lbnRUeXBlLCBzaGFwZV0gPSBnZXRTZXNzaW9uSW5wdXRPdXRwdXRNZXRhZGF0YShzZXNzaW9uSGFuZGxlLCBpKTtcbiAgICAgIGlmIChuYW1lT2Zmc2V0ID09PSAwKSB7XG4gICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgZ2V0IGFuIGlucHV0IG5hbWUuXCIpO1xuICAgICAgfVxuICAgICAgaW5wdXROYW1lc1VURjhFbmNvZGVkLnB1c2gobmFtZU9mZnNldCk7XG4gICAgICBjb25zdCBuYW1lID0gd2FzbS5VVEY4VG9TdHJpbmcobmFtZU9mZnNldCk7XG4gICAgICBpbnB1dE5hbWVzLnB1c2gobmFtZSk7XG4gICAgICBpbnB1dE1ldGFkYXRhLnB1c2goXG4gICAgICAgIGVsZW1lbnRUeXBlID09PSAwXG4gICAgICAgICAgPyB7IG5hbWUsIGlzVGVuc29yOiBmYWxzZSB9XG4gICAgICAgICAgOiB7IG5hbWUsIGlzVGVuc29yOiB0cnVlLCB0eXBlOiB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyhlbGVtZW50VHlwZSksIHNoYXBlOiBzaGFwZSEgfSxcbiAgICAgICk7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xuICAgICAgY29uc3QgW25hbWVPZmZzZXQsIGVsZW1lbnRUeXBlLCBzaGFwZV0gPSBnZXRTZXNzaW9uSW5wdXRPdXRwdXRNZXRhZGF0YShzZXNzaW9uSGFuZGxlLCBpICsgaW5wdXRDb3VudCk7XG4gICAgICBpZiAobmFtZU9mZnNldCA9PT0gMCkge1xuICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGdldCBhbiBvdXRwdXQgbmFtZS5cIik7XG4gICAgICB9XG4gICAgICBvdXRwdXROYW1lc1VURjhFbmNvZGVkLnB1c2gobmFtZU9mZnNldCk7XG4gICAgICBjb25zdCBuYW1lU3RyaW5nID0gd2FzbS5VVEY4VG9TdHJpbmcobmFtZU9mZnNldCk7XG4gICAgICBvdXRwdXROYW1lcy5wdXNoKG5hbWVTdHJpbmcpO1xuICAgICAgb3V0cHV0TWV0YWRhdGEucHVzaChcbiAgICAgICAgZWxlbWVudFR5cGUgPT09IDBcbiAgICAgICAgICA/IHsgbmFtZTogbmFtZVN0cmluZywgaXNUZW5zb3I6IGZhbHNlIH1cbiAgICAgICAgICA6IHsgbmFtZTogbmFtZVN0cmluZywgaXNUZW5zb3I6IHRydWUsIHR5cGU6IHRlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nKGVsZW1lbnRUeXBlKSwgc2hhcGU6IHNoYXBlISB9LFxuICAgICAgKTtcblxuICAgICAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUCB8fCAhQlVJTERfREVGUy5ESVNBQkxFX1dFQkdQVSkge1xuICAgICAgICBpZiAoZW5hYmxlR3JhcGhDYXB0dXJlICYmIG9wdGlvbnM/LnByZWZlcnJlZE91dHB1dExvY2F0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnMucHVzaCgnZ3B1LWJ1ZmZlcicpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxvY2F0aW9uID1cbiAgICAgICAgICB0eXBlb2Ygb3B0aW9ucz8ucHJlZmVycmVkT3V0cHV0TG9jYXRpb24gPT09ICdzdHJpbmcnXG4gICAgICAgICAgICA/IG9wdGlvbnMucHJlZmVycmVkT3V0cHV0TG9jYXRpb25cbiAgICAgICAgICAgIDogKG9wdGlvbnM/LnByZWZlcnJlZE91dHB1dExvY2F0aW9uPy5bbmFtZVN0cmluZ10gPz8gJ2NwdScpO1xuICAgICAgICBjb25zdCBpc0dyYXBoT3V0cHV0ID0gd2FzbS53ZWJubklzR3JhcGhPdXRwdXQ7XG4gICAgICAgIGlmIChsb2NhdGlvbiA9PT0gJ2NwdScgJiYgaXNHcmFwaE91dHB1dCAmJiBpc0dyYXBoT3V0cHV0KHNlc3Npb25IYW5kbGUsIG5hbWVTdHJpbmcpKSB7XG4gICAgICAgICAgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zLnB1c2goJ21sLXRlbnNvci1jcHUtb3V0cHV0Jyk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxvY2F0aW9uICE9PSAnY3B1JyAmJiBsb2NhdGlvbiAhPT0gJ2NwdS1waW5uZWQnICYmIGxvY2F0aW9uICE9PSAnZ3B1LWJ1ZmZlcicgJiYgbG9jYXRpb24gIT09ICdtbC10ZW5zb3InKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOb3Qgc3VwcG9ydGVkIHByZWZlcnJlZCBvdXRwdXQgbG9jYXRpb246ICR7bG9jYXRpb259LmApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlbmFibGVHcmFwaENhcHR1cmUgJiYgbG9jYXRpb24gIT09ICdncHUtYnVmZmVyJykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBOb3Qgc3VwcG9ydGVkIHByZWZlcnJlZCBvdXRwdXQgbG9jYXRpb246ICR7bG9jYXRpb259LiBPbmx5ICdncHUtYnVmZmVyJyBsb2NhdGlvbiBpcyBzdXBwb3J0ZWQgd2hlbiBlbmFibGVHcmFwaENhcHR1cmUgaXMgdHJ1ZS5gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zLnB1c2gobG9jYXRpb24pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHVzZSBJTyBiaW5kaW5nIG9ubHkgd2hlbiBhdCBsZWFzdCBvbmUgb3V0cHV0IGlzIHByZWZlcnJlZCB0byBiZSBvbiBHUFUuXG4gICAgbGV0IGJpbmRpbmdTdGF0ZTogSU9CaW5kaW5nU3RhdGUgfCBudWxsID0gbnVsbDtcbiAgICBpZiAoXG4gICAgICAoIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQIHx8ICFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVKSAmJlxuICAgICAgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zLnNvbWUoKGwpID0+IGwgPT09ICdncHUtYnVmZmVyJyB8fCBsID09PSAnbWwtdGVuc29yJyB8fCBsID09PSAnbWwtdGVuc29yLWNwdS1vdXRwdXQnKVxuICAgICkge1xuICAgICAgaW9CaW5kaW5nSGFuZGxlID0gd2FzbS5fT3J0Q3JlYXRlQmluZGluZyhzZXNzaW9uSGFuZGxlKTtcbiAgICAgIGlmIChpb0JpbmRpbmdIYW5kbGUgPT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBjcmVhdGUgSU8gYmluZGluZy5cIik7XG4gICAgICB9XG5cbiAgICAgIGJpbmRpbmdTdGF0ZSA9IHtcbiAgICAgICAgaGFuZGxlOiBpb0JpbmRpbmdIYW5kbGUsXG4gICAgICAgIG91dHB1dFByZWZlcnJlZExvY2F0aW9ucyxcbiAgICAgICAgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zRW5jb2RlZDogb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zXG4gICAgICAgICAgLy8gJ21sLXRlbnNvci1jcHUtb3V0cHV0JyBpcyB0cmVhdGVkIGFzICdtbC10ZW5zb3InIGZvciB0aGUgcHVycG9zZSBvZiBJTyBiaW5kaW5nLlxuICAgICAgICAgIC5tYXAoKGwpID0+IChsID09PSAnbWwtdGVuc29yLWNwdS1vdXRwdXQnID8gJ21sLXRlbnNvcicgOiBsKSlcbiAgICAgICAgICAubWFwKChsKSA9PiBkYXRhTG9jYXRpb25TdHJpbmdUb0VudW0obCkpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBhY3RpdmVTZXNzaW9ucy5zZXQoc2Vzc2lvbkhhbmRsZSwgW1xuICAgICAgc2Vzc2lvbkhhbmRsZSxcbiAgICAgIGlucHV0TmFtZXNVVEY4RW5jb2RlZCxcbiAgICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWQsXG4gICAgICBiaW5kaW5nU3RhdGUsXG4gICAgICBlbmFibGVHcmFwaENhcHR1cmUsXG4gICAgICBmYWxzZSxcbiAgICBdKTtcbiAgICByZXR1cm4gW3Nlc3Npb25IYW5kbGUsIGlucHV0TmFtZXMsIG91dHB1dE5hbWVzLCBpbnB1dE1ldGFkYXRhLCBvdXRwdXRNZXRhZGF0YV07XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWQuZm9yRWFjaCgoYnVmKSA9PiB3YXNtLl9PcnRGcmVlKGJ1ZikpO1xuICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWQuZm9yRWFjaCgoYnVmKSA9PiB3YXNtLl9PcnRGcmVlKGJ1ZikpO1xuXG4gICAgaWYgKGlvQmluZGluZ0hhbmRsZSAhPT0gMCkge1xuICAgICAgaWYgKHdhc20uX09ydFJlbGVhc2VCaW5kaW5nKGlvQmluZGluZ0hhbmRsZSkgIT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIElPIGJpbmRpbmcuXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzZXNzaW9uSGFuZGxlICE9PSAwKSB7XG4gICAgICBpZiAod2FzbS5fT3J0UmVsZWFzZVNlc3Npb24oc2Vzc2lvbkhhbmRsZSkgIT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIHNlc3Npb24uXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIHdhc20uX2ZyZWUobW9kZWxEYXRhT2Zmc2V0KTtcbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUgIT09IDApIHtcbiAgICAgIGlmICh3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnMoc2Vzc2lvbk9wdGlvbnNIYW5kbGUpICE9PSAwKSB7XG4gICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgcmVsZWFzZSBzZXNzaW9uIG9wdGlvbnMuXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICBhbGxvY3MuZm9yRWFjaCgoYWxsb2MpID0+IHdhc20uX2ZyZWUoYWxsb2MpKTtcblxuICAgIC8vIHVubW91bnQgZXh0ZXJuYWwgZGF0YSBpZiBuZWNlc3NhcnlcbiAgICB3YXNtLnVubW91bnRFeHRlcm5hbERhdGE/LigpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVsZWFzZVNlc3Npb24gPSAoc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IHNlc3Npb24gPSBhY3RpdmVTZXNzaW9ucy5nZXQoc2Vzc2lvbklkKTtcbiAgaWYgKCFzZXNzaW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgcmVsZWFzZSBzZXNzaW9uLiBpbnZhbGlkIHNlc3Npb24gaWQ6ICR7c2Vzc2lvbklkfWApO1xuICB9XG4gIGNvbnN0IFtzZXNzaW9uSGFuZGxlLCBpbnB1dE5hbWVzVVRGOEVuY29kZWQsIG91dHB1dE5hbWVzVVRGOEVuY29kZWQsIGlvQmluZGluZ1N0YXRlLCBlbmFibGVHcmFwaENhcHR1cmVdID0gc2Vzc2lvbjtcblxuICBpZiAoaW9CaW5kaW5nU3RhdGUpIHtcbiAgICBpZiAoZW5hYmxlR3JhcGhDYXB0dXJlKSB7XG4gICAgICBpZiAod2FzbS5fT3J0Q2xlYXJCb3VuZE91dHB1dHMoaW9CaW5kaW5nU3RhdGUuaGFuZGxlKSAhPT0gMCkge1xuICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGNsZWFyIGJvdW5kIG91dHB1dHMuXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAod2FzbS5fT3J0UmVsZWFzZUJpbmRpbmcoaW9CaW5kaW5nU3RhdGUuaGFuZGxlKSAhPT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIElPIGJpbmRpbmcuXCIpO1xuICAgIH1cbiAgfVxuXG4gIHdhc20uanNlcE9uUmVsZWFzZVNlc3Npb24/LihzZXNzaW9uSWQpO1xuICB3YXNtLndlYm5uT25SZWxlYXNlU2Vzc2lvbj8uKHNlc3Npb25JZCk7XG4gIHdhc20ud2ViZ3B1T25SZWxlYXNlU2Vzc2lvbj8uKHNlc3Npb25JZCk7XG5cbiAgaW5wdXROYW1lc1VURjhFbmNvZGVkLmZvckVhY2goKGJ1ZikgPT4gd2FzbS5fT3J0RnJlZShidWYpKTtcbiAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5mb3JFYWNoKChidWYpID0+IHdhc20uX09ydEZyZWUoYnVmKSk7XG4gIGlmICh3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbihzZXNzaW9uSGFuZGxlKSAhPT0gMCkge1xuICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgcmVsZWFzZSBzZXNzaW9uLlwiKTtcbiAgfVxuICBhY3RpdmVTZXNzaW9ucy5kZWxldGUoc2Vzc2lvbklkKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwcmVwYXJlSW5wdXRPdXRwdXRUZW5zb3IgPSBhc3luYyAoXG4gIHRlbnNvcjogVGVuc29yTWV0YWRhdGEgfCBudWxsLFxuICB0ZW5zb3JIYW5kbGVzOiBudW1iZXJbXSxcbiAgYWxsb2NzOiBudW1iZXJbXSxcbiAgc2Vzc2lvbklkOiBudW1iZXIsXG4gIHRlbnNvck5hbWVVVEY4RW5jb2RlZDogbnVtYmVyLFxuICBpbmRleDogbnVtYmVyLFxuICBlbmFibGVHcmFwaENhcHR1cmUgPSBmYWxzZSxcbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoIXRlbnNvcikge1xuICAgIHRlbnNvckhhbmRsZXMucHVzaCgwKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3QgcHRyU2l6ZSA9IHdhc20uUFRSX1NJWkU7XG5cbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JbMF07XG4gIGNvbnN0IGRpbXMgPSB0ZW5zb3JbMV07XG4gIGNvbnN0IGxvY2F0aW9uID0gdGVuc29yWzNdO1xuICBsZXQgYWN0dWFsTG9jYXRpb24gPSBsb2NhdGlvbjtcblxuICBsZXQgcmF3RGF0YTogbnVtYmVyO1xuICBsZXQgZGF0YUJ5dGVMZW5ndGg6IG51bWJlcjtcblxuICBpZiAoZGF0YVR5cGUgPT09ICdzdHJpbmcnICYmIChsb2NhdGlvbiA9PT0gJ2dwdS1idWZmZXInIHx8IGxvY2F0aW9uID09PSAnbWwtdGVuc29yJykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1N0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCBvbiBHUFUuJyk7XG4gIH1cblxuICBpZiAoZW5hYmxlR3JhcGhDYXB0dXJlICYmIGxvY2F0aW9uICE9PSAnZ3B1LWJ1ZmZlcicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRXh0ZXJuYWwgYnVmZmVyIG11c3QgYmUgcHJvdmlkZWQgZm9yIGlucHV0L291dHB1dCBpbmRleCAke2luZGV4fSB3aGVuIGVuYWJsZUdyYXBoQ2FwdHVyZSBpcyB0cnVlLmAsXG4gICAgKTtcbiAgfVxuXG4gIGlmIChsb2NhdGlvbiA9PT0gJ2dwdS1idWZmZXInKSB7XG4gICAgY29uc3QgZ3B1QnVmZmVyID0gdGVuc29yWzJdLmdwdUJ1ZmZlcjtcbiAgICBkYXRhQnl0ZUxlbmd0aCA9IGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzKHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKGRhdGFUeXBlKSwgZGltcykhO1xuXG4gICAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVKSB7XG4gICAgICBjb25zdCByZWdpc3RlckJ1ZmZlciA9IHdhc20ud2ViZ3B1UmVnaXN0ZXJCdWZmZXI7XG4gICAgICBpZiAoIXJlZ2lzdGVyQnVmZmVyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIGxvY2F0aW9uIFwiZ3B1LWJ1ZmZlclwiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJHUFUuJyk7XG4gICAgICB9XG5cbiAgICAgIHJhd0RhdGEgPSByZWdpc3RlckJ1ZmZlcihncHVCdWZmZXIsIHNlc3Npb25JZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJlZ2lzdGVyQnVmZmVyID0gd2FzbS5qc2VwUmVnaXN0ZXJCdWZmZXI7XG4gICAgICBpZiAoIXJlZ2lzdGVyQnVmZmVyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIGxvY2F0aW9uIFwiZ3B1LWJ1ZmZlclwiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJHUFUuJyk7XG4gICAgICB9XG4gICAgICByYXdEYXRhID0gcmVnaXN0ZXJCdWZmZXIoc2Vzc2lvbklkLCBpbmRleCwgZ3B1QnVmZmVyLCBkYXRhQnl0ZUxlbmd0aCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGxvY2F0aW9uID09PSAnbWwtdGVuc29yJykge1xuICAgIGNvbnN0IG1sVGVuc29yID0gdGVuc29yWzJdLm1sVGVuc29yIGFzIE1MVGVuc29yO1xuICAgIGRhdGFCeXRlTGVuZ3RoID0gY2FsY3VsYXRlVGVuc29yU2l6ZUluQnl0ZXModGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0oZGF0YVR5cGUpLCBkaW1zKSE7XG5cbiAgICBjb25zdCByZWdpc3Rlck1MVGVuc29yID0gd2FzbS53ZWJublJlZ2lzdGVyTUxUZW5zb3I7XG4gICAgaWYgKCFyZWdpc3Rlck1MVGVuc29yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiBcIm1sLXRlbnNvclwiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJOTi4nKTtcbiAgICB9XG4gICAgcmF3RGF0YSA9IHJlZ2lzdGVyTUxUZW5zb3Ioc2Vzc2lvbklkLCBtbFRlbnNvciwgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0oZGF0YVR5cGUpLCBkaW1zKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBkYXRhID0gdGVuc29yWzJdO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgIC8vIHN0cmluZyB0ZW5zb3JcbiAgICAgIGRhdGFCeXRlTGVuZ3RoID0gcHRyU2l6ZSAqIGRhdGEubGVuZ3RoO1xuICAgICAgcmF3RGF0YSA9IHdhc20uX21hbGxvYyhkYXRhQnl0ZUxlbmd0aCk7XG4gICAgICBhbGxvY3MucHVzaChyYXdEYXRhKTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodHlwZW9mIGRhdGFbaV0gIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgdGVuc29yIGRhdGEgYXQgaW5kZXggJHtpfSBpcyBub3QgYSBzdHJpbmdgKTtcbiAgICAgICAgfVxuICAgICAgICB3YXNtLnNldFZhbHVlKHJhd0RhdGEgKyBpICogcHRyU2l6ZSwgYWxsb2NXYXNtU3RyaW5nKGRhdGFbaV0sIGFsbG9jcyksICcqJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGlzR3JhcGhJbnB1dCA9IHdhc20ud2Vibm5Jc0dyYXBoSW5wdXQ7XG4gICAgICBjb25zdCBpc0dyYXBoT3V0cHV0ID0gd2FzbS53ZWJubklzR3JhcGhPdXRwdXQ7XG4gICAgICBpZiAoZGF0YVR5cGUgIT09ICdzdHJpbmcnICYmIGlzR3JhcGhJbnB1dCAmJiBpc0dyYXBoT3V0cHV0KSB7XG4gICAgICAgIGNvbnN0IHRlbnNvck5hbWUgPSB3YXNtLlVURjhUb1N0cmluZyh0ZW5zb3JOYW1lVVRGOEVuY29kZWQpO1xuICAgICAgICAvLyBQcm9tb3RlIHRoZSB0ZW5zb3IgdG8gJ21sLXRlbnNvcicgaWYgaXQgaXMgYSBncmFwaCBpbnB1dC5cbiAgICAgICAgaWYgKGlzR3JhcGhJbnB1dChzZXNzaW9uSWQsIHRlbnNvck5hbWUpIHx8IGlzR3JhcGhPdXRwdXQoc2Vzc2lvbklkLCB0ZW5zb3JOYW1lKSkge1xuICAgICAgICAgIGNvbnN0IGRhdGFUeXBlRW51bSA9IHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKGRhdGFUeXBlKTtcbiAgICAgICAgICBkYXRhQnl0ZUxlbmd0aCA9IGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzKGRhdGFUeXBlRW51bSwgZGltcykhO1xuICAgICAgICAgIGFjdHVhbExvY2F0aW9uID0gJ21sLXRlbnNvcic7XG4gICAgICAgICAgY29uc3QgY3JlYXRlVGVtcG9yYXJ5VGVuc29yID0gd2FzbS53ZWJubkNyZWF0ZVRlbXBvcmFyeVRlbnNvcjtcbiAgICAgICAgICBjb25zdCB1cGxvYWRUZW5zb3IgPSB3YXNtLndlYm5uVXBsb2FkVGVuc29yO1xuICAgICAgICAgIGlmICghY3JlYXRlVGVtcG9yYXJ5VGVuc29yIHx8ICF1cGxvYWRUZW5zb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIGxvY2F0aW9uIFwibWwtdGVuc29yXCIgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IHVzaW5nIFdlYk5OLicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCB0ZW5zb3JJZCA9IGF3YWl0IGNyZWF0ZVRlbXBvcmFyeVRlbnNvcihzZXNzaW9uSWQsIGRhdGFUeXBlRW51bSwgZGltcyBhcyBudW1iZXJbXSk7XG4gICAgICAgICAgdXBsb2FkVGVuc29yKHRlbnNvcklkLCBuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhLmJ5dGVMZW5ndGgpKTtcbiAgICAgICAgICByYXdEYXRhID0gdGVuc29ySWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGF0YUJ5dGVMZW5ndGggPSBkYXRhLmJ5dGVMZW5ndGg7XG4gICAgICAgICAgcmF3RGF0YSA9IHdhc20uX21hbGxvYyhkYXRhQnl0ZUxlbmd0aCk7XG4gICAgICAgICAgYWxsb2NzLnB1c2gocmF3RGF0YSk7XG4gICAgICAgICAgd2FzbS5IRUFQVTguc2V0KG5ldyBVaW50OEFycmF5KGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQsIGRhdGFCeXRlTGVuZ3RoKSwgcmF3RGF0YSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRhdGFCeXRlTGVuZ3RoID0gZGF0YS5ieXRlTGVuZ3RoO1xuICAgICAgICByYXdEYXRhID0gd2FzbS5fbWFsbG9jKGRhdGFCeXRlTGVuZ3RoKTtcbiAgICAgICAgYWxsb2NzLnB1c2gocmF3RGF0YSk7XG4gICAgICAgIHdhc20uSEVBUFU4LnNldChuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhQnl0ZUxlbmd0aCksIHJhd0RhdGEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHN0YWNrID0gd2FzbS5zdGFja1NhdmUoKTtcbiAgY29uc3QgZGltc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyg0ICogZGltcy5sZW5ndGgpO1xuICB0cnkge1xuICAgIGRpbXMuZm9yRWFjaCgoZCwgaW5kZXgpID0+IHdhc20uc2V0VmFsdWUoZGltc09mZnNldCArIGluZGV4ICogcHRyU2l6ZSwgZCwgcHRyU2l6ZSA9PT0gNCA/ICdpMzInIDogJ2k2NCcpKTtcbiAgICBjb25zdCB0ZW5zb3IgPSB3YXNtLl9PcnRDcmVhdGVUZW5zb3IoXG4gICAgICB0ZW5zb3JEYXRhVHlwZVN0cmluZ1RvRW51bShkYXRhVHlwZSksXG4gICAgICByYXdEYXRhLFxuICAgICAgZGF0YUJ5dGVMZW5ndGgsXG4gICAgICBkaW1zT2Zmc2V0LFxuICAgICAgZGltcy5sZW5ndGgsXG4gICAgICBkYXRhTG9jYXRpb25TdHJpbmdUb0VudW0oYWN0dWFsTG9jYXRpb24pLFxuICAgICk7XG4gICAgaWYgKHRlbnNvciA9PT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoYENhbid0IGNyZWF0ZSB0ZW5zb3IgZm9yIGlucHV0L291dHB1dC4gc2Vzc2lvbj0ke3Nlc3Npb25JZH0sIGluZGV4PSR7aW5kZXh9LmApO1xuICAgIH1cbiAgICB0ZW5zb3JIYW5kbGVzLnB1c2godGVuc29yKTtcbiAgfSBmaW5hbGx5IHtcbiAgICB3YXNtLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gIH1cbn07XG5cbi8qKlxuICogcGVyZm9ybSBpbmZlcmVuY2UgcnVuXG4gKi9cbmV4cG9ydCBjb25zdCBydW4gPSBhc3luYyAoXG4gIHNlc3Npb25JZDogbnVtYmVyLFxuICBpbnB1dEluZGljZXM6IG51bWJlcltdLFxuICBpbnB1dFRlbnNvcnM6IFRlbnNvck1ldGFkYXRhW10sXG4gIG91dHB1dEluZGljZXM6IG51bWJlcltdLFxuICBvdXRwdXRUZW5zb3JzOiBBcnJheTxUZW5zb3JNZXRhZGF0YSB8IG51bGw+LFxuICBvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMsXG4pOiBQcm9taXNlPFRlbnNvck1ldGFkYXRhW10+ID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IHB0clNpemUgPSB3YXNtLlBUUl9TSVpFO1xuICBjb25zdCBzZXNzaW9uID0gYWN0aXZlU2Vzc2lvbnMuZ2V0KHNlc3Npb25JZCk7XG4gIGlmICghc2Vzc2lvbikge1xuICAgIHRocm93IG5ldyBFcnJvcihgY2Fubm90IHJ1biBpbmZlcmVuY2UuIGludmFsaWQgc2Vzc2lvbiBpZDogJHtzZXNzaW9uSWR9YCk7XG4gIH1cbiAgY29uc3Qgc2Vzc2lvbkhhbmRsZSA9IHNlc3Npb25bMF07XG4gIGNvbnN0IGlucHV0TmFtZXNVVEY4RW5jb2RlZCA9IHNlc3Npb25bMV07XG4gIGNvbnN0IG91dHB1dE5hbWVzVVRGOEVuY29kZWQgPSBzZXNzaW9uWzJdO1xuICBjb25zdCBpb0JpbmRpbmdTdGF0ZSA9IHNlc3Npb25bM107XG4gIGNvbnN0IGVuYWJsZUdyYXBoQ2FwdHVyZSA9IHNlc3Npb25bNF07XG4gIGNvbnN0IGlucHV0T3V0cHV0Qm91bmQgPSBzZXNzaW9uWzVdO1xuXG4gIGNvbnN0IGlucHV0Q291bnQgPSBpbnB1dEluZGljZXMubGVuZ3RoO1xuICBjb25zdCBvdXRwdXRDb3VudCA9IG91dHB1dEluZGljZXMubGVuZ3RoO1xuXG4gIGxldCBydW5PcHRpb25zSGFuZGxlID0gMDtcbiAgbGV0IHJ1bk9wdGlvbnNBbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgY29uc3QgaW5wdXRUZW5zb3JIYW5kbGVzOiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCBvdXRwdXRUZW5zb3JIYW5kbGVzOiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCBpbnB1dE91dHB1dEFsbG9jczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgcHJlQWxsb2NhdGVkT3V0cHV0czogbnVtYmVyW10gPSBbXTtcblxuICBjb25zdCBiZWZvcmVSdW5TdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XG4gIGNvbnN0IGlucHV0VmFsdWVzT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKGlucHV0Q291bnQgKiBwdHJTaXplKTtcbiAgY29uc3QgaW5wdXROYW1lc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhpbnB1dENvdW50ICogcHRyU2l6ZSk7XG4gIGNvbnN0IG91dHB1dFZhbHVlc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhvdXRwdXRDb3VudCAqIHB0clNpemUpO1xuICBjb25zdCBvdXRwdXROYW1lc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhvdXRwdXRDb3VudCAqIHB0clNpemUpO1xuXG4gIHRyeSB7XG4gICAgW3J1bk9wdGlvbnNIYW5kbGUsIHJ1bk9wdGlvbnNBbGxvY3NdID0gc2V0UnVuT3B0aW9ucyhvcHRpb25zKTtcblxuICAgIFRSQUNFX0VWRU5UX0JFR0lOKCd3YXNtIHByZXBhcmVJbnB1dE91dHB1dFRlbnNvcicpO1xuICAgIC8vIGNyZWF0ZSBpbnB1dCB0ZW5zb3JzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcbiAgICAgIGF3YWl0IHByZXBhcmVJbnB1dE91dHB1dFRlbnNvcihcbiAgICAgICAgaW5wdXRUZW5zb3JzW2ldLFxuICAgICAgICBpbnB1dFRlbnNvckhhbmRsZXMsXG4gICAgICAgIGlucHV0T3V0cHV0QWxsb2NzLFxuICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgIGlucHV0TmFtZXNVVEY4RW5jb2RlZFtpbnB1dEluZGljZXNbaV1dLFxuICAgICAgICBpbnB1dEluZGljZXNbaV0sXG4gICAgICAgIGVuYWJsZUdyYXBoQ2FwdHVyZSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIG91dHB1dCB0ZW5zb3JzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XG4gICAgICBhd2FpdCBwcmVwYXJlSW5wdXRPdXRwdXRUZW5zb3IoXG4gICAgICAgIG91dHB1dFRlbnNvcnNbaV0sXG4gICAgICAgIG91dHB1dFRlbnNvckhhbmRsZXMsXG4gICAgICAgIGlucHV0T3V0cHV0QWxsb2NzLFxuICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWRbb3V0cHV0SW5kaWNlc1tpXV0sXG4gICAgICAgIGlucHV0Q291bnQgKyBvdXRwdXRJbmRpY2VzW2ldLFxuICAgICAgICBlbmFibGVHcmFwaENhcHR1cmUsXG4gICAgICApO1xuICAgIH1cbiAgICBUUkFDRV9FVkVOVF9FTkQoJ3dhc20gcHJlcGFyZUlucHV0T3V0cHV0VGVuc29yJyk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Q291bnQ7IGkrKykge1xuICAgICAgd2FzbS5zZXRWYWx1ZShpbnB1dFZhbHVlc09mZnNldCArIGkgKiBwdHJTaXplLCBpbnB1dFRlbnNvckhhbmRsZXNbaV0sICcqJyk7XG4gICAgICB3YXNtLnNldFZhbHVlKGlucHV0TmFtZXNPZmZzZXQgKyBpICogcHRyU2l6ZSwgaW5wdXROYW1lc1VURjhFbmNvZGVkW2lucHV0SW5kaWNlc1tpXV0sICcqJyk7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xuICAgICAgd2FzbS5zZXRWYWx1ZShvdXRwdXRWYWx1ZXNPZmZzZXQgKyBpICogcHRyU2l6ZSwgb3V0cHV0VGVuc29ySGFuZGxlc1tpXSwgJyonKTtcbiAgICAgIHdhc20uc2V0VmFsdWUob3V0cHV0TmFtZXNPZmZzZXQgKyBpICogcHRyU2l6ZSwgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZFtvdXRwdXRJbmRpY2VzW2ldXSwgJyonKTtcbiAgICB9XG5cbiAgICBpZiAoKCFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUCB8fCAhQlVJTERfREVGUy5ESVNBQkxFX1dFQkdQVSkgJiYgaW9CaW5kaW5nU3RhdGUgJiYgIWlucHV0T3V0cHV0Qm91bmQpIHtcbiAgICAgIGNvbnN0IHsgaGFuZGxlLCBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnMsIG91dHB1dFByZWZlcnJlZExvY2F0aW9uc0VuY29kZWQgfSA9IGlvQmluZGluZ1N0YXRlO1xuXG4gICAgICBpZiAoaW5wdXROYW1lc1VURjhFbmNvZGVkLmxlbmd0aCAhPT0gaW5wdXRDb3VudCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYGlucHV0IGNvdW50IGZyb20gZmVlZHMgKCR7aW5wdXRDb3VudH0pIGlzIGV4cGVjdGVkIHRvIGJlIGFsd2F5cyBlcXVhbCB0byBtb2RlbCdzIGlucHV0IGNvdW50ICgke2lucHV0TmFtZXNVVEY4RW5jb2RlZC5sZW5ndGh9KS5gLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBUUkFDRV9FVkVOVF9CRUdJTignd2FzbSBiaW5kSW5wdXRzT3V0cHV0cycpO1xuICAgICAgLy8gcHJvY2VzcyBpbnB1dHNcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gaW5wdXRJbmRpY2VzW2ldO1xuICAgICAgICBjb25zdCBlcnJvckNvZGUgPSBhd2FpdCB3YXNtLl9PcnRCaW5kSW5wdXQoaGFuZGxlLCBpbnB1dE5hbWVzVVRGOEVuY29kZWRbaW5kZXhdLCBpbnB1dFRlbnNvckhhbmRsZXNbaV0pO1xuICAgICAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICAgICAgY2hlY2tMYXN0RXJyb3IoYENhbid0IGJpbmQgaW5wdXRbJHtpfV0gZm9yIHNlc3Npb249JHtzZXNzaW9uSWR9LmApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIHByb2Nlc3MgcHJlLWFsbG9jYXRlZCBvdXRwdXRzXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dENvdW50OyBpKyspIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBvdXRwdXRJbmRpY2VzW2ldO1xuICAgICAgICBjb25zdCBsb2NhdGlvbiA9IG91dHB1dFRlbnNvcnNbaV0/LlszXTsgLy8gdW5kZWZpbmVkIG1lYW5zIG91dHB1dCBpcyBub3QgcHJlLWFsbG9jYXRlZC5cblxuICAgICAgICBpZiAobG9jYXRpb24pIHtcbiAgICAgICAgICAvLyBvdXRwdXQgaXMgcHJlLWFsbG9jYXRlZCwgc3RvcmUgYW5kIGJpbmQgdGhlIHRlbnNvci5cbiAgICAgICAgICBwcmVBbGxvY2F0ZWRPdXRwdXRzLnB1c2gob3V0cHV0VGVuc29ySGFuZGxlc1tpXSk7XG4gICAgICAgICAgY29uc3QgZXJyb3JDb2RlID0gd2FzbS5fT3J0QmluZE91dHB1dChoYW5kbGUsIG91dHB1dE5hbWVzVVRGOEVuY29kZWRbaW5kZXhdLCBvdXRwdXRUZW5zb3JIYW5kbGVzW2ldLCAwKTtcbiAgICAgICAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICAgICAgICBjaGVja0xhc3RFcnJvcihgQ2FuJ3QgYmluZCBwcmUtYWxsb2NhdGVkIG91dHB1dFske2l9XSBmb3Igc2Vzc2lvbj0ke3Nlc3Npb25JZH0uYCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIG91dHB1dCBpcyBub3QgcHJlLWFsbG9jYXRlZC4gcmVzZXQgcHJlZmVycmVkIGxvY2F0aW9uLlxuICAgICAgICAgIGNvbnN0IGVycm9yQ29kZSA9IHdhc20uX09ydEJpbmRPdXRwdXQoXG4gICAgICAgICAgICBoYW5kbGUsXG4gICAgICAgICAgICBvdXRwdXROYW1lc1VURjhFbmNvZGVkW2luZGV4XSxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnNFbmNvZGVkW2luZGV4XSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICAgICAgICAgIGNoZWNrTGFzdEVycm9yKGBDYW4ndCBiaW5kIG91dHB1dFske2l9XSB0byAke291dHB1dFByZWZlcnJlZExvY2F0aW9uc1tpXX0gZm9yIHNlc3Npb249JHtzZXNzaW9uSWR9LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgVFJBQ0VfRVZFTlRfRU5EKCd3YXNtIGJpbmRJbnB1dHNPdXRwdXRzJyk7XG4gICAgICBhY3RpdmVTZXNzaW9ucy5zZXQoc2Vzc2lvbklkLCBbXG4gICAgICAgIHNlc3Npb25IYW5kbGUsXG4gICAgICAgIGlucHV0TmFtZXNVVEY4RW5jb2RlZCxcbiAgICAgICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZCxcbiAgICAgICAgaW9CaW5kaW5nU3RhdGUsXG4gICAgICAgIGVuYWJsZUdyYXBoQ2FwdHVyZSxcbiAgICAgICAgdHJ1ZSxcbiAgICAgIF0pO1xuICAgIH1cblxuICAgIHdhc20uanNlcE9uUnVuU3RhcnQ/LihzZXNzaW9uSGFuZGxlKTtcbiAgICB3YXNtLndlYm5uT25SdW5TdGFydD8uKHNlc3Npb25IYW5kbGUpO1xuXG4gICAgbGV0IGVycm9yQ29kZTogbnVtYmVyO1xuICAgIGlmICgoIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQIHx8ICFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVKSAmJiBpb0JpbmRpbmdTdGF0ZSkge1xuICAgICAgZXJyb3JDb2RlID0gYXdhaXQgd2FzbS5fT3J0UnVuV2l0aEJpbmRpbmcoXG4gICAgICAgIHNlc3Npb25IYW5kbGUsXG4gICAgICAgIGlvQmluZGluZ1N0YXRlLmhhbmRsZSxcbiAgICAgICAgb3V0cHV0Q291bnQsXG4gICAgICAgIG91dHB1dFZhbHVlc09mZnNldCxcbiAgICAgICAgcnVuT3B0aW9uc0hhbmRsZSxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVycm9yQ29kZSA9IGF3YWl0IHdhc20uX09ydFJ1bihcbiAgICAgICAgc2Vzc2lvbkhhbmRsZSxcbiAgICAgICAgaW5wdXROYW1lc09mZnNldCxcbiAgICAgICAgaW5wdXRWYWx1ZXNPZmZzZXQsXG4gICAgICAgIGlucHV0Q291bnQsXG4gICAgICAgIG91dHB1dE5hbWVzT2Zmc2V0LFxuICAgICAgICBvdXRwdXRDb3VudCxcbiAgICAgICAgb3V0cHV0VmFsdWVzT2Zmc2V0LFxuICAgICAgICBydW5PcHRpb25zSGFuZGxlLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICBjaGVja0xhc3RFcnJvcignZmFpbGVkIHRvIGNhbGwgT3J0UnVuKCkuJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0OiBUZW5zb3JNZXRhZGF0YVtdID0gW107XG4gICAgY29uc3Qgb3V0cHV0UHJvbWlzZXM6IEFycmF5PFByb21pc2U8W251bWJlciwgVGVuc29yLkRhdGFUeXBlXT4+ID0gW107XG5cbiAgICBUUkFDRV9FVkVOVF9CRUdJTignd2FzbSBQcm9jZXNzT3V0cHV0VGVuc29yJyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCB0ZW5zb3IgPSBOdW1iZXIod2FzbS5nZXRWYWx1ZShvdXRwdXRWYWx1ZXNPZmZzZXQgKyBpICogcHRyU2l6ZSwgJyonKSk7XG4gICAgICAvLyBUT0RPOiByZXZpc2l0IHRoaXMgcGFydCB0byBlbnN1cmUgaXQgd29ya3MgZm9yIFdlYkdQVSB3aGVuIGJvdGggcHJlLWFsbG9jYXRlZCBvdXRwdXRzIGFuZFxuICAgICAgLy8gcHJlZmVycmVkIGxvY2F0aW9uIGFyZSBzcGVjaWZpZWQuXG4gICAgICAvLyBDZXJ0YWluIHByZS1hbGxvY2F0ZWQgdGVuc29ycyBtYXkgYWxyZWFkeSBiZSBib3VuZCBpbiB0aGUgSU8gYmluZGluZy4gZS5nLiB0aGUgV2ViTk4gYmFja2VuZFxuICAgICAgLy8gYWx3YXlzIGJpbmRzIGl0cyB0ZW5zb3IgdG8gJ21sLXRlbnNvcicuIEluIHN1Y2ggY2FzZXMsIHRoZSB0ZW5zb3IgSUQgbWlnaHQgY2hhbmdlIGFmdGVyIGJpbmRpbmcsXG4gICAgICAvLyBidXQgY29weWluZyBkYXRhIGZvciB0aGVzZSB0ZW5zb3JzIHNob3VsZCBzdGlsbCBiZSBhdm9pZGVkLlxuICAgICAgaWYgKHRlbnNvciA9PT0gb3V0cHV0VGVuc29ySGFuZGxlc1tpXSB8fCBwcmVBbGxvY2F0ZWRPdXRwdXRzLmluY2x1ZGVzKG91dHB1dFRlbnNvckhhbmRsZXNbaV0pKSB7XG4gICAgICAgIC8vIG91dHB1dCB0ZW5zb3IgaXMgcHJlLWFsbG9jYXRlZC4gbm8gbmVlZCB0byBjb3B5IGRhdGEuXG4gICAgICAgIG91dHB1dC5wdXNoKG91dHB1dFRlbnNvcnNbaV0hKTtcbiAgICAgICAgaWYgKHRlbnNvciAhPT0gb3V0cHV0VGVuc29ySGFuZGxlc1tpXSkge1xuICAgICAgICAgIC8vIHJlbGVhc2UgcmVkdW5kYW50IHRlbnNvciBlYXJsaWVyLlxuICAgICAgICAgIGlmICh3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHRlbnNvcikgIT09IDApIHtcbiAgICAgICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgcmVsZWFzZSB0ZW5zb3IuXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYmVmb3JlR2V0VGVuc29yRGF0YVN0YWNrID0gd2FzbS5zdGFja1NhdmUoKTtcbiAgICAgIC8vIHN0YWNrIGFsbG9jYXRlIDQgcG9pbnRlciB2YWx1ZVxuICAgICAgY29uc3QgdGVuc29yRGF0YU9mZnNldCA9IHdhc20uc3RhY2tBbGxvYyg0ICogcHRyU2l6ZSk7XG5cbiAgICAgIGxldCBrZWVwT3V0cHV0VGVuc29yID0gZmFsc2U7XG4gICAgICBsZXQgdHlwZTogVGVuc29yLlR5cGUgfCB1bmRlZmluZWQsXG4gICAgICAgIGRhdGFPZmZzZXQgPSAwO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZXJyb3JDb2RlID0gd2FzbS5fT3J0R2V0VGVuc29yRGF0YShcbiAgICAgICAgICB0ZW5zb3IsXG4gICAgICAgICAgdGVuc29yRGF0YU9mZnNldCxcbiAgICAgICAgICB0ZW5zb3JEYXRhT2Zmc2V0ICsgcHRyU2l6ZSxcbiAgICAgICAgICB0ZW5zb3JEYXRhT2Zmc2V0ICsgMiAqIHB0clNpemUsXG5cbiAgICAgICAgICB0ZW5zb3JEYXRhT2Zmc2V0ICsgMyAqIHB0clNpemUsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICAgICAgICBjaGVja0xhc3RFcnJvcihgQ2FuJ3QgYWNjZXNzIG91dHB1dCB0ZW5zb3IgZGF0YSBvbiBpbmRleCAke2l9LmApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZhbHVlVHlwZSA9IHB0clNpemUgPT09IDQgPyAnaTMyJyA6ICdpNjQnO1xuICAgICAgICBjb25zdCBkYXRhVHlwZSA9IE51bWJlcih3YXNtLmdldFZhbHVlKHRlbnNvckRhdGFPZmZzZXQsIHZhbHVlVHlwZSkpO1xuICAgICAgICBkYXRhT2Zmc2V0ID0gd2FzbS5nZXRWYWx1ZSh0ZW5zb3JEYXRhT2Zmc2V0ICsgcHRyU2l6ZSwgJyonKTtcbiAgICAgICAgY29uc3QgZGltc09mZnNldCA9IHdhc20uZ2V0VmFsdWUodGVuc29yRGF0YU9mZnNldCArIHB0clNpemUgKiAyLCAnKicpO1xuICAgICAgICBjb25zdCBkaW1zTGVuZ3RoID0gTnVtYmVyKHdhc20uZ2V0VmFsdWUodGVuc29yRGF0YU9mZnNldCArIHB0clNpemUgKiAzLCB2YWx1ZVR5cGUpKTtcbiAgICAgICAgY29uc3QgZGltcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRpbXNMZW5ndGg7IGkrKykge1xuICAgICAgICAgIGRpbXMucHVzaChOdW1iZXIod2FzbS5nZXRWYWx1ZShkaW1zT2Zmc2V0ICsgaSAqIHB0clNpemUsIHZhbHVlVHlwZSkpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAod2FzbS5fT3J0RnJlZShkaW1zT2Zmc2V0KSAhPT0gMCkge1xuICAgICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgZnJlZSBtZW1vcnkgZm9yIHRlbnNvciBkaW1zLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzaXplID0gZGltcy5yZWR1Y2UoKGEsIGIpID0+IGEgKiBiLCAxKTtcbiAgICAgICAgdHlwZSA9IHRlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nKGRhdGFUeXBlKTtcblxuICAgICAgICBjb25zdCBwcmVmZXJyZWRMb2NhdGlvbiA9IGlvQmluZGluZ1N0YXRlPy5vdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnNbb3V0cHV0SW5kaWNlc1tpXV07XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgaWYgKHByZWZlcnJlZExvY2F0aW9uID09PSAnZ3B1LWJ1ZmZlcicgfHwgcHJlZmVycmVkTG9jYXRpb24gPT09ICdtbC10ZW5zb3InKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1N0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCBvbiBHUFUuJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHN0cmluZ0RhdGE6IHN0cmluZ1tdID0gW107XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHdhc20uZ2V0VmFsdWUoZGF0YU9mZnNldCArIGkgKiBwdHJTaXplLCAnKicpO1xuICAgICAgICAgICAgY29uc3QgbmV4dE9mZnNldCA9IHdhc20uZ2V0VmFsdWUoZGF0YU9mZnNldCArIChpICsgMSkgKiBwdHJTaXplLCAnKicpO1xuICAgICAgICAgICAgY29uc3QgbWF4Qnl0ZXNUb1JlYWQgPSBpID09PSBzaXplIC0gMSA/IHVuZGVmaW5lZCA6IG5leHRPZmZzZXQgLSBvZmZzZXQ7XG4gICAgICAgICAgICBzdHJpbmdEYXRhLnB1c2god2FzbS5VVEY4VG9TdHJpbmcob2Zmc2V0LCBtYXhCeXRlc1RvUmVhZCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvdXRwdXQucHVzaChbdHlwZSwgZGltcywgc3RyaW5nRGF0YSwgJ2NwdSddKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBJZiBhIGNlcnRhaW4gb3V0cHV0J3MgcHJlZmVycmVkIGxvY2F0aW9uIGlzIEdQVSBidXQgdGhlIHRlbnNvciBpcyBlbXB0eSwgd2Ugc3RpbGwgbmVlZCB0byBjcmVhdGUgYSBDUFVcbiAgICAgICAgICAvLyB0ZW5zb3IgZm9yIGl0LiBUaGVyZSBpcyBubyBtYXBwaW5nIEdQVSBidWZmZXIgZm9yIGFuIGVtcHR5IHRlbnNvci5cbiAgICAgICAgICBpZiAocHJlZmVycmVkTG9jYXRpb24gPT09ICdncHUtYnVmZmVyJyAmJiBzaXplID4gMCkge1xuICAgICAgICAgICAgY29uc3QgZ2V0QnVmZmVyID0gIUJVSUxEX0RFRlMuRElTQUJMRV9XRUJHUFUgPyB3YXNtLndlYmdwdUdldEJ1ZmZlciA6IHdhc20uanNlcEdldEJ1ZmZlcjtcbiAgICAgICAgICAgIGlmICghZ2V0QnVmZmVyKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncHJlZmVycmVkTG9jYXRpb24gXCJncHUtYnVmZmVyXCIgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IHVzaW5nIFdlYkdQVS4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGdwdUJ1ZmZlciA9IGdldEJ1ZmZlcihkYXRhT2Zmc2V0KTtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlclNpemUgPSBjYWxjdWxhdGVUZW5zb3JTaXplSW5CeXRlcyhkYXRhVHlwZSwgc2l6ZSk7XG4gICAgICAgICAgICBpZiAoYnVmZmVyU2l6ZSA9PT0gdW5kZWZpbmVkIHx8ICFpc0dwdUJ1ZmZlclN1cHBvcnRlZFR5cGUodHlwZSkpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dHlwZX1gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gZG8gbm90IHJlbGVhc2UgdGhlIHRlbnNvciByaWdodCBub3cuIGl0IHdpbGwgYmUgcmVsZWFzZWQgd2hlbiB1c2VyIGNhbGxzIHRlbnNvci5kaXNwb3NlKCkuXG4gICAgICAgICAgICBrZWVwT3V0cHV0VGVuc29yID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVKSB7XG4gICAgICAgICAgICAgIHdhc20ud2ViZ3B1UmVnaXN0ZXJCdWZmZXIhKGdwdUJ1ZmZlciwgc2Vzc2lvbklkLCBkYXRhT2Zmc2V0KTtcbiAgICAgICAgICAgICAgY29uc3QgZG93bmxvYWREYXRhRnVuY3Rpb24gPSB3YXNtLndlYmdwdUNyZWF0ZURvd25sb2FkZXIhKGdwdUJ1ZmZlciwgYnVmZmVyU2l6ZSwgc2Vzc2lvbklkKTtcbiAgICAgICAgICAgICAgb3V0cHV0LnB1c2goW1xuICAgICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICAgICAgZGltcyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBncHVCdWZmZXIsXG4gICAgICAgICAgICAgICAgICBkb3dubG9hZDogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBhcnJheUJ1ZmZlciA9IGF3YWl0IGRvd25sb2FkRGF0YUZ1bmN0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBuZXcgKHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3Rvcih0eXBlISkpKGFycmF5QnVmZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdGEgYXMgVGVuc29yLkRhdGFUeXBlTWFwW1RlbnNvci5HcHVCdWZmZXJEYXRhVHlwZXNdO1xuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIGRpc3Bvc2U6ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhc20uX09ydFJlbGVhc2VUZW5zb3IodGVuc29yKSAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgcmVsZWFzZSB0ZW5zb3IuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ2dwdS1idWZmZXInLFxuICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG91dHB1dC5wdXNoKFtcbiAgICAgICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgICAgIGRpbXMsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgZ3B1QnVmZmVyLFxuICAgICAgICAgICAgICAgICAgZG93bmxvYWQ6IHdhc20uanNlcENyZWF0ZURvd25sb2FkZXIhKGdwdUJ1ZmZlciwgYnVmZmVyU2l6ZSwgdHlwZSksXG4gICAgICAgICAgICAgICAgICBkaXNwb3NlOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHRlbnNvcikgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IHJlbGVhc2UgdGVuc29yLlwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICdncHUtYnVmZmVyJyxcbiAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChwcmVmZXJyZWRMb2NhdGlvbiA9PT0gJ21sLXRlbnNvcicgJiYgc2l6ZSA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGVuc3VyZVRlbnNvciA9IHdhc20ud2Vibm5FbnN1cmVUZW5zb3I7XG4gICAgICAgICAgICBjb25zdCBpc0dyYXBoSW5wdXRPdXRwdXRUeXBlU3VwcG9ydGVkID0gd2FzbS53ZWJubklzR3JhcGhJbnB1dE91dHB1dFR5cGVTdXBwb3J0ZWQ7XG4gICAgICAgICAgICBpZiAoIWVuc3VyZVRlbnNvciB8fCAhaXNHcmFwaElucHV0T3V0cHV0VHlwZVN1cHBvcnRlZCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uIFwibWwtdGVuc29yXCIgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IHVzaW5nIFdlYk5OLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdGVuc29yU2l6ZSA9IGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzKGRhdGFUeXBlLCBzaXplKTtcbiAgICAgICAgICAgIGlmICh0ZW5zb3JTaXplID09PSB1bmRlZmluZWQgfHwgIWlzTUxUZW5zb3JTdXBwb3J0ZWRUeXBlKHR5cGUpKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGV9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzR3JhcGhJbnB1dE91dHB1dFR5cGVTdXBwb3J0ZWQoc2Vzc2lvbklkLCB0eXBlLCBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIGBwcmVmZXJyZWRMb2NhdGlvbiBcIm1sLXRlbnNvclwiIGZvciAke3R5cGV9IG91dHB1dCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGN1cnJlbnQgV2ViTk4gQ29udGV4dC5gLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiB0aGUgZ3JhcGggaGFzIGJlZW4gcGFydGl0aW9uZWQsIHRoZSBvdXRwdXQgdGVuc29yIG1heSBoYXZlIG5vdCBiZWVuIGNyZWF0ZWQuIEZvciB0aGlzIHJlYXNvbiwgd2UgdXNlXG4gICAgICAgICAgICAvLyBlbnN1cmVUZW5zb3IgdG8gZ2V0L2NyZWF0ZSB0aGUgTUxUZW5zb3IuIEluIHdoaWNoIGNhc2UsIHdlIGRvbid0IG5lZWQgdG8gY29weSB0aGUgZGF0YSBpZiBhIG5ldyB0ZW5zb3JcbiAgICAgICAgICAgIC8vIGhhcyBiZWVuIGNyZWF0ZWQuXG4gICAgICAgICAgICBjb25zdCBtbFRlbnNvciA9IGF3YWl0IGVuc3VyZVRlbnNvcihzZXNzaW9uSWQsIGRhdGFPZmZzZXQsIGRhdGFUeXBlLCBkaW1zLCBmYWxzZSk7XG5cbiAgICAgICAgICAgIC8vIGRvIG5vdCByZWxlYXNlIHRoZSB0ZW5zb3IgcmlnaHQgbm93LiBpdCB3aWxsIGJlIHJlbGVhc2VkIHdoZW4gdXNlciBjYWxscyB0ZW5zb3IuZGlzcG9zZSgpLlxuICAgICAgICAgICAga2VlcE91dHB1dFRlbnNvciA9IHRydWU7XG5cbiAgICAgICAgICAgIG91dHB1dC5wdXNoKFtcbiAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgZGltcyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIG1sVGVuc29yLFxuICAgICAgICAgICAgICAgIGRvd25sb2FkOiB3YXNtLndlYm5uQ3JlYXRlTUxUZW5zb3JEb3dubG9hZGVyIShkYXRhT2Zmc2V0LCB0eXBlKSxcbiAgICAgICAgICAgICAgICBkaXNwb3NlOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICB3YXNtLndlYm5uUmVsZWFzZVRlbnNvcklkIShkYXRhT2Zmc2V0KTtcbiAgICAgICAgICAgICAgICAgIHdhc20uX09ydFJlbGVhc2VUZW5zb3IodGVuc29yKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAnbWwtdGVuc29yJyxcbiAgICAgICAgICAgIF0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAocHJlZmVycmVkTG9jYXRpb24gPT09ICdtbC10ZW5zb3ItY3B1LW91dHB1dCcgJiYgc2l6ZSA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB3YXNtLndlYm5uQ3JlYXRlTUxUZW5zb3JEb3dubG9hZGVyIShkYXRhT2Zmc2V0LCB0eXBlIGFzIFRlbnNvci5NTFRlbnNvckRhdGFUeXBlcykoKTtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gb3V0cHV0Lmxlbmd0aDtcbiAgICAgICAgICAgIC8vIERlbGF5IHRoZSBkYXRhIGRvd25sb2FkIGFuZCByZWxlYXNpbmcgdGhlIHRlbnNvciB1bnRpbCB3ZSBjYW4gd2FpdCBmb3IgYWxsIG91dHB1dCB0ZW5zb3JzIHRvIGJlIGRvd25sb2FkZWQuXG4gICAgICAgICAgICBrZWVwT3V0cHV0VGVuc29yID0gdHJ1ZTtcbiAgICAgICAgICAgIG91dHB1dFByb21pc2VzLnB1c2goXG4gICAgICAgICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0OiBbbnVtYmVyLCBUZW5zb3IuRGF0YVR5cGVdID0gW2luZGV4LCBhd2FpdCBkYXRhXTtcbiAgICAgICAgICAgICAgICB3YXNtLndlYm5uUmVsZWFzZVRlbnNvcklkIShkYXRhT2Zmc2V0KTtcbiAgICAgICAgICAgICAgICB3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHRlbnNvcik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgfSkoKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBvdXRwdXQucHVzaChbdHlwZSwgZGltcywgW10sICdjcHUnXSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3Rvcih0eXBlKTtcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBuZXcgdHlwZWRBcnJheUNvbnN0cnVjdG9yKHNpemUpO1xuICAgICAgICAgICAgbmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgZGF0YS5ieXRlTGVuZ3RoKS5zZXQoXG4gICAgICAgICAgICAgIHdhc20uSEVBUFU4LnN1YmFycmF5KGRhdGFPZmZzZXQsIGRhdGFPZmZzZXQgKyBkYXRhLmJ5dGVMZW5ndGgpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIG91dHB1dC5wdXNoKFt0eXBlLCBkaW1zLCBkYXRhLCAnY3B1J10pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgd2FzbS5zdGFja1Jlc3RvcmUoYmVmb3JlR2V0VGVuc29yRGF0YVN0YWNrKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnICYmIGRhdGFPZmZzZXQpIHtcbiAgICAgICAgICB3YXNtLl9mcmVlKGRhdGFPZmZzZXQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgha2VlcE91dHB1dFRlbnNvcikge1xuICAgICAgICAgIHdhc20uX09ydFJlbGVhc2VUZW5zb3IodGVuc29yKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChpb0JpbmRpbmdTdGF0ZSAmJiAhZW5hYmxlR3JhcGhDYXB0dXJlKSB7XG4gICAgICBpZiAod2FzbS5fT3J0Q2xlYXJCb3VuZE91dHB1dHMoaW9CaW5kaW5nU3RhdGUuaGFuZGxlKSAhPT0gMCkge1xuICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGNsZWFyIGJvdW5kIG91dHB1dHMuXCIpO1xuICAgICAgfVxuICAgICAgYWN0aXZlU2Vzc2lvbnMuc2V0KHNlc3Npb25JZCwgW1xuICAgICAgICBzZXNzaW9uSGFuZGxlLFxuICAgICAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWQsXG4gICAgICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWQsXG4gICAgICAgIGlvQmluZGluZ1N0YXRlLFxuICAgICAgICBlbmFibGVHcmFwaENhcHR1cmUsXG4gICAgICAgIGZhbHNlLFxuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIFdhaXQgZm9yIGFsbCBvdXRwdXQgdGVuc29yIGRhdGEgdG8gYmUgZG93bmxvYWRlZC5cbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgZGF0YV0gb2YgYXdhaXQgUHJvbWlzZS5hbGwob3V0cHV0UHJvbWlzZXMpKSB7XG4gICAgICBvdXRwdXRbaW5kZXhdWzJdID0gZGF0YTtcbiAgICB9XG4gICAgVFJBQ0VfRVZFTlRfRU5EKCd3YXNtIFByb2Nlc3NPdXRwdXRUZW5zb3InKTtcbiAgICByZXR1cm4gb3V0cHV0O1xuICB9IGZpbmFsbHkge1xuICAgIHdhc20ud2Vibm5PblJ1bkVuZD8uKHNlc3Npb25IYW5kbGUpO1xuXG4gICAgd2FzbS5zdGFja1Jlc3RvcmUoYmVmb3JlUnVuU3RhY2spO1xuXG4gICAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVKSB7XG4gICAgICBpbnB1dFRlbnNvcnMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgICBpZiAodCAmJiB0WzNdID09PSAnZ3B1LWJ1ZmZlcicpIHtcbiAgICAgICAgICB3YXNtLndlYmdwdVVucmVnaXN0ZXJCdWZmZXIhKHRbMl0uZ3B1QnVmZmVyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvdXRwdXRUZW5zb3JzLmZvckVhY2goKHQpID0+IHtcbiAgICAgICAgaWYgKHQgJiYgdFszXSA9PT0gJ2dwdS1idWZmZXInKSB7XG4gICAgICAgICAgd2FzbS53ZWJncHVVbnJlZ2lzdGVyQnVmZmVyISh0WzJdLmdwdUJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICBpbnB1dFRlbnNvckhhbmRsZXMuZm9yRWFjaCgodikgPT4gd2FzbS5fT3J0UmVsZWFzZVRlbnNvcih2KSk7XG4gICAgb3V0cHV0VGVuc29ySGFuZGxlcy5mb3JFYWNoKCh2KSA9PiB3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHYpKTtcbiAgICBpbnB1dE91dHB1dEFsbG9jcy5mb3JFYWNoKChwKSA9PiB3YXNtLl9mcmVlKHApKTtcblxuICAgIGlmIChydW5PcHRpb25zSGFuZGxlICE9PSAwKSB7XG4gICAgICB3YXNtLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyhydW5PcHRpb25zSGFuZGxlKTtcbiAgICB9XG4gICAgcnVuT3B0aW9uc0FsbG9jcy5mb3JFYWNoKChwKSA9PiB3YXNtLl9mcmVlKHApKTtcbiAgfVxufTtcblxuLyoqXG4gKiBlbmQgcHJvZmlsaW5nXG4gKi9cbmV4cG9ydCBjb25zdCBlbmRQcm9maWxpbmcgPSAoc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IHNlc3Npb24gPSBhY3RpdmVTZXNzaW9ucy5nZXQoc2Vzc2lvbklkKTtcbiAgaWYgKCFzZXNzaW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNlc3Npb24gaWQnKTtcbiAgfVxuICBjb25zdCBzZXNzaW9uSGFuZGxlID0gc2Vzc2lvblswXTtcblxuICAvLyBwcm9maWxlIGZpbGUgbmFtZSBpcyBub3QgdXNlZCB5ZXQsIGJ1dCBpdCBtdXN0IGJlIGZyZWVkLlxuICBjb25zdCBwcm9maWxlRmlsZU5hbWUgPSB3YXNtLl9PcnRFbmRQcm9maWxpbmcoc2Vzc2lvbkhhbmRsZSk7XG4gIGlmIChwcm9maWxlRmlsZU5hbWUgPT09IDApIHtcbiAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGdldCBhbiBwcm9maWxlIGZpbGUgbmFtZS5cIik7XG4gIH1cbiAgd2FzbS5fT3J0RnJlZShwcm9maWxlRmlsZU5hbWUpO1xufTtcblxuZXhwb3J0IGNvbnN0IGV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzID0gKHRlbnNvcnM6IHJlYWRvbmx5IFNlcmlhbGl6YWJsZVRlbnNvck1ldGFkYXRhW10pOiBBcnJheUJ1ZmZlckxpa2VbXSA9PiB7XG4gIGNvbnN0IGJ1ZmZlcnM6IEFycmF5QnVmZmVyTGlrZVtdID0gW107XG4gIGZvciAoY29uc3QgdGVuc29yIG9mIHRlbnNvcnMpIHtcbiAgICBjb25zdCBkYXRhID0gdGVuc29yWzJdO1xuICAgIGlmICghQXJyYXkuaXNBcnJheShkYXRhKSAmJiAnYnVmZmVyJyBpbiBkYXRhKSB7XG4gICAgICBidWZmZXJzLnB1c2goZGF0YS5idWZmZXIpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYnVmZmVycztcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGVudiwgSW5mZXJlbmNlU2Vzc2lvbiB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7XG4gIE9ydFdhc21NZXNzYWdlLFxuICBTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlcixcbiAgU2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhLFxuICBTZXJpYWxpemFibGVUZW5zb3JNZXRhZGF0YSxcbiAgVGVuc29yTWV0YWRhdGEsXG59IGZyb20gJy4vcHJveHktbWVzc2FnZXMnO1xuaW1wb3J0ICogYXMgY29yZSBmcm9tICcuL3dhc20tY29yZS1pbXBsJztcbmltcG9ydCB7IGluaXRpYWxpemVXZWJBc3NlbWJseSB9IGZyb20gJy4vd2FzbS1mYWN0b3J5JztcbmltcG9ydCB7XG4gIGltcG9ydFByb3h5V29ya2VyLFxuICBpbmZlcldhc21QYXRoUHJlZml4RnJvbVNjcmlwdFNyYyxcbiAgaXNFc21JbXBvcnRNZXRhVXJsSGFyZGNvZGVkQXNGaWxlVXJpLFxufSBmcm9tICcuL3dhc20tdXRpbHMtaW1wb3J0JztcblxuY29uc3QgaXNQcm94eSA9ICgpOiBib29sZWFuID0+ICEhZW52Lndhc20ucHJveHkgJiYgdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJztcbmxldCBwcm94eVdvcmtlcjogV29ya2VyIHwgdW5kZWZpbmVkO1xubGV0IGluaXRpYWxpemluZyA9IGZhbHNlO1xubGV0IGluaXRpYWxpemVkID0gZmFsc2U7XG5sZXQgYWJvcnRlZCA9IGZhbHNlO1xubGV0IHRlbXBvcmFyeU9iamVjdFVybDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG50eXBlIFByb21pc2VDYWxsYmFja3M8VCA9IHZvaWQ+ID0gW3Jlc29sdmU6IChyZXN1bHQ6IFQpID0+IHZvaWQsIHJlamVjdDogKHJlYXNvbjogdW5rbm93bikgPT4gdm9pZF07XG5sZXQgaW5pdFdhc21DYWxsYmFja3M6IFByb21pc2VDYWxsYmFja3M7XG5jb25zdCBxdWV1ZWRDYWxsYmFja3M6IE1hcDxPcnRXYXNtTWVzc2FnZVsndHlwZSddLCBBcnJheTxQcm9taXNlQ2FsbGJhY2tzPHVua25vd24+Pj4gPSBuZXcgTWFwKCk7XG5cbmNvbnN0IGVucXVldWVDYWxsYmFja3MgPSAodHlwZTogT3J0V2FzbU1lc3NhZ2VbJ3R5cGUnXSwgY2FsbGJhY2tzOiBQcm9taXNlQ2FsbGJhY2tzPHVua25vd24+KTogdm9pZCA9PiB7XG4gIGNvbnN0IHF1ZXVlID0gcXVldWVkQ2FsbGJhY2tzLmdldCh0eXBlKTtcbiAgaWYgKHF1ZXVlKSB7XG4gICAgcXVldWUucHVzaChjYWxsYmFja3MpO1xuICB9IGVsc2Uge1xuICAgIHF1ZXVlZENhbGxiYWNrcy5zZXQodHlwZSwgW2NhbGxiYWNrc10pO1xuICB9XG59O1xuXG5jb25zdCBlbnN1cmVXb3JrZXIgPSAoKTogdm9pZCA9PiB7XG4gIGlmIChpbml0aWFsaXppbmcgfHwgIWluaXRpYWxpemVkIHx8IGFib3J0ZWQgfHwgIXByb3h5V29ya2VyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd3b3JrZXIgbm90IHJlYWR5Jyk7XG4gIH1cbn07XG5cbmNvbnN0IG9uUHJveHlXb3JrZXJNZXNzYWdlID0gKGV2OiBNZXNzYWdlRXZlbnQ8T3J0V2FzbU1lc3NhZ2U+KTogdm9pZCA9PiB7XG4gIHN3aXRjaCAoZXYuZGF0YS50eXBlKSB7XG4gICAgY2FzZSAnaW5pdC13YXNtJzpcbiAgICAgIGluaXRpYWxpemluZyA9IGZhbHNlO1xuICAgICAgaWYgKGV2LmRhdGEuZXJyKSB7XG4gICAgICAgIGFib3J0ZWQgPSB0cnVlO1xuICAgICAgICBpbml0V2FzbUNhbGxiYWNrc1sxXShldi5kYXRhLmVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbml0aWFsaXplZCA9IHRydWU7XG4gICAgICAgIGluaXRXYXNtQ2FsbGJhY2tzWzBdKCk7XG4gICAgICB9XG4gICAgICBpZiAodGVtcG9yYXJ5T2JqZWN0VXJsKSB7XG4gICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwodGVtcG9yYXJ5T2JqZWN0VXJsKTtcbiAgICAgICAgdGVtcG9yYXJ5T2JqZWN0VXJsID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaW5pdC1lcCc6XG4gICAgY2FzZSAnY29weS1mcm9tJzpcbiAgICBjYXNlICdjcmVhdGUnOlxuICAgIGNhc2UgJ3JlbGVhc2UnOlxuICAgIGNhc2UgJ3J1bic6XG4gICAgY2FzZSAnZW5kLXByb2ZpbGluZyc6IHtcbiAgICAgIGNvbnN0IGNhbGxiYWNrcyA9IHF1ZXVlZENhbGxiYWNrcy5nZXQoZXYuZGF0YS50eXBlKSE7XG4gICAgICBpZiAoZXYuZGF0YS5lcnIpIHtcbiAgICAgICAgY2FsbGJhY2tzLnNoaWZ0KCkhWzFdKGV2LmRhdGEuZXJyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhbGxiYWNrcy5zaGlmdCgpIVswXShldi5kYXRhLm91dCEpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBpbml0aWFsaXplV2ViQXNzZW1ibHlBbmRPcnRSdW50aW1lID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoaW5pdGlhbGl6ZWQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGluaXRpYWxpemluZykge1xuICAgIHRocm93IG5ldyBFcnJvcihcIm11bHRpcGxlIGNhbGxzIHRvICdpbml0V2FzbSgpJyBkZXRlY3RlZC5cIik7XG4gIH1cbiAgaWYgKGFib3J0ZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJwcmV2aW91cyBjYWxsIHRvICdpbml0V2FzbSgpJyBmYWlsZWQuXCIpO1xuICB9XG5cbiAgaW5pdGlhbGl6aW5nID0gdHJ1ZTtcblxuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBwcm94eVdvcmtlcj8udGVybWluYXRlKCk7XG5cbiAgICAgIHZvaWQgaW1wb3J0UHJveHlXb3JrZXIoKS50aGVuKChbb2JqZWN0VXJsLCB3b3JrZXJdKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcHJveHlXb3JrZXIgPSB3b3JrZXI7XG4gICAgICAgICAgcHJveHlXb3JrZXIub25lcnJvciA9IChldjogRXJyb3JFdmVudCkgPT4gcmVqZWN0KGV2KTtcbiAgICAgICAgICBwcm94eVdvcmtlci5vbm1lc3NhZ2UgPSBvblByb3h5V29ya2VyTWVzc2FnZTtcbiAgICAgICAgICBpbml0V2FzbUNhbGxiYWNrcyA9IFtyZXNvbHZlLCByZWplY3RdO1xuICAgICAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0geyB0eXBlOiAnaW5pdC13YXNtJywgaW46IGVudiB9O1xuXG4gICAgICAgICAgLy8gaWYgdGhlIHByb3h5IHdvcmtlciBpcyBsb2FkZWQgZnJvbSBhIGJsb2IgVVJMLCB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB0aGUgcGF0aCBpbmZvcm1hdGlvbiBpcyBub3QgbG9zdC5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIHdoZW4gYGVudi53YXNtLndhc21QYXRoc2AgaXMgbm90IHNldCwgd2UgbmVlZCB0byBwYXNzIHRoZSBwYXRoIGluZm9ybWF0aW9uIHRvIHRoZSB3b3JrZXIuXG4gICAgICAgICAgLy9cbiAgICAgICAgICBpZiAoIUJVSUxEX0RFRlMuRU5BQkxFX0JVTkRMRV9XQVNNX0pTICYmICFtZXNzYWdlLmluIS53YXNtLndhc21QYXRocyAmJiBvYmplY3RVcmwpIHtcbiAgICAgICAgICAgIC8vIGZvciBhIGJ1aWxkIG5vdCBidW5kbGVkIHRoZSB3YXNtIEpTLCB3ZSBuZWVkIHRvIHBhc3MgdGhlIHBhdGggcHJlZml4IHRvIHRoZSB3b3JrZXIuXG4gICAgICAgICAgICAvLyB0aGUgcGF0aCBwcmVmaXggd2lsbCBiZSB1c2VkIHRvIHJlc29sdmUgdGhlIHBhdGggdG8gYm90aCB0aGUgd2FzbSBKUyBhbmQgdGhlIHdhc20gZmlsZS5cbiAgICAgICAgICAgIGNvbnN0IGluZmVycmVkV2FzbVBhdGhQcmVmaXggPSBpbmZlcldhc21QYXRoUHJlZml4RnJvbVNjcmlwdFNyYygpO1xuICAgICAgICAgICAgaWYgKGluZmVycmVkV2FzbVBhdGhQcmVmaXgpIHtcbiAgICAgICAgICAgICAgbWVzc2FnZS5pbiEud2FzbS53YXNtUGF0aHMgPSBpbmZlcnJlZFdhc21QYXRoUHJlZml4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIEJVSUxEX0RFRlMuSVNfRVNNICYmXG4gICAgICAgICAgICBCVUlMRF9ERUZTLkVOQUJMRV9CVU5ETEVfV0FTTV9KUyAmJlxuICAgICAgICAgICAgIW1lc3NhZ2UuaW4hLndhc20ud2FzbVBhdGhzICYmXG4gICAgICAgICAgICAob2JqZWN0VXJsIHx8IGlzRXNtSW1wb3J0TWV0YVVybEhhcmRjb2RlZEFzRmlsZVVyaSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIC8vIGZvciBhIGJ1aWxkIGJ1bmRsZWQgdGhlIHdhc20gSlMsIGlmIGVpdGhlciBvZiB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgaXMgbWV0OlxuICAgICAgICAgICAgLy8gLSB0aGUgcHJveHkgd29ya2VyIGlzIGxvYWRlZCBmcm9tIGEgYmxvYiBVUkxcbiAgICAgICAgICAgIC8vIC0gYGltcG9ydC5tZXRhLnVybGAgaXMgYSBmaWxlIFVSTCwgaXQgbWVhbnMgaXQgaXMgb3ZlcndyaXR0ZW4gYnkgdGhlIGJ1bmRsZXIuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gaW4gZWl0aGVyIGNhc2UsIHRoZSBwYXRoIGluZm9ybWF0aW9uIGlzIGxvc3QsIHdlIG5lZWQgdG8gcGFzcyB0aGUgcGF0aCBvZiB0aGUgLndhc20gZmlsZSB0byB0aGUgd29ya2VyLlxuICAgICAgICAgICAgLy8gd2UgbmVlZCB0byB1c2UgdGhlIGJ1bmRsZXIgcHJlZmVycmVkIFVSTCBmb3JtYXQ6XG4gICAgICAgICAgICAvLyBuZXcgVVJMKCdmaWxlbmFtZScsIGltcG9ydC5tZXRhLnVybClcbiAgICAgICAgICAgIC8vIHNvIHRoYXQgdGhlIGJ1bmRsZXIgY2FuIGhhbmRsZSB0aGUgZmlsZSB1c2luZyBjb3JyZXNwb25kaW5nIGxvYWRlcnMuXG4gICAgICAgICAgICBtZXNzYWdlLmluIS53YXNtLndhc21QYXRocyA9IHtcbiAgICAgICAgICAgICAgd2FzbTogIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQXG4gICAgICAgICAgICAgICAgPyBuZXcgVVJMKCdvcnQtd2FzbS1zaW1kLXRocmVhZGVkLmpzZXAud2FzbScsIEJVSUxEX0RFRlMuRVNNX0lNUE9SVF9NRVRBX1VSTCkuaHJlZlxuICAgICAgICAgICAgICAgIDogQlVJTERfREVGUy5FTkFCTEVfSlNQSVxuICAgICAgICAgICAgICAgICAgPyBuZXcgVVJMKCdvcnQtd2FzbS1zaW1kLXRocmVhZGVkLmpzcGkud2FzbScsIEJVSUxEX0RFRlMuRVNNX0lNUE9SVF9NRVRBX1VSTCkuaHJlZlxuICAgICAgICAgICAgICAgICAgOiAhQlVJTERfREVGUy5ESVNBQkxFX1dFQkdQVVxuICAgICAgICAgICAgICAgICAgICA/IG5ldyBVUkwoJ29ydC13YXNtLXNpbWQtdGhyZWFkZWQuYXN5bmNpZnkud2FzbScsIEJVSUxEX0RFRlMuRVNNX0lNUE9SVF9NRVRBX1VSTCkuaHJlZlxuICAgICAgICAgICAgICAgICAgICA6IG5ldyBVUkwoJ29ydC13YXNtLXNpbWQtdGhyZWFkZWQud2FzbScsIEJVSUxEX0RFRlMuRVNNX0lNUE9SVF9NRVRBX1VSTCkuaHJlZixcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHByb3h5V29ya2VyLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuICAgICAgICAgIHRlbXBvcmFyeU9iamVjdFVybCA9IG9iamVjdFVybDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfSwgcmVqZWN0KTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgaW5pdGlhbGl6ZVdlYkFzc2VtYmx5KGVudi53YXNtKTtcbiAgICAgIGF3YWl0IGNvcmUuaW5pdFJ1bnRpbWUoZW52KTtcbiAgICAgIGluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBhYm9ydGVkID0gdHJ1ZTtcbiAgICAgIHRocm93IGU7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGluaXRpYWxpemluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGluaXRpYWxpemVPcnRFcCA9IGFzeW5jIChlcE5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBlbnF1ZXVlQ2FsbGJhY2tzKCdpbml0LWVwJywgW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7IHR5cGU6ICdpbml0LWVwJywgaW46IHsgZXBOYW1lLCBlbnYgfSB9O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGF3YWl0IGNvcmUuaW5pdEVwKGVudiwgZXBOYW1lKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIgPSBhc3luYyAoYnVmZmVyOiBVaW50OEFycmF5KTogUHJvbWlzZTxTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlcj4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZW5xdWV1ZUNhbGxiYWNrcygnY29weS1mcm9tJywgW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7IHR5cGU6ICdjb3B5LWZyb20nLCBpbjogeyBidWZmZXIgfSB9O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UsIFtidWZmZXIuYnVmZmVyXSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGNvcmUuY29weUZyb21FeHRlcm5hbEJ1ZmZlcihidWZmZXIpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlU2Vzc2lvbiA9IGFzeW5jIChcbiAgbW9kZWw6IFNlcmlhbGl6YWJsZUludGVybmFsQnVmZmVyIHwgVWludDhBcnJheSxcbiAgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMsXG4pOiBQcm9taXNlPFNlcmlhbGl6YWJsZVNlc3Npb25NZXRhZGF0YT4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIC8vIGNoZWNrIHVuc3VwcG9ydGVkIG9wdGlvbnNcbiAgICBpZiAob3B0aW9ucz8ucHJlZmVycmVkT3V0cHV0TG9jYXRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc2Vzc2lvbiBvcHRpb24gXCJwcmVmZXJyZWRPdXRwdXRMb2NhdGlvblwiIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIHByb3h5LicpO1xuICAgIH1cbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBlbnF1ZXVlQ2FsbGJhY2tzKCdjcmVhdGUnLCBbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHsgdHlwZTogJ2NyZWF0ZScsIGluOiB7IG1vZGVsLCBvcHRpb25zOiB7IC4uLm9wdGlvbnMgfSB9IH07XG4gICAgICBjb25zdCB0cmFuc2ZlcmFibGU6IFRyYW5zZmVyYWJsZVtdID0gW107XG4gICAgICBpZiAobW9kZWwgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICAgIHRyYW5zZmVyYWJsZS5wdXNoKG1vZGVsLmJ1ZmZlcik7XG4gICAgICB9XG4gICAgICBwcm94eVdvcmtlciEucG9zdE1lc3NhZ2UobWVzc2FnZSwgdHJhbnNmZXJhYmxlKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY29yZS5jcmVhdGVTZXNzaW9uKG1vZGVsLCBvcHRpb25zKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHJlbGVhc2VTZXNzaW9uID0gYXN5bmMgKHNlc3Npb25JZDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgZW5zdXJlV29ya2VyKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGVucXVldWVDYWxsYmFja3MoJ3JlbGVhc2UnLCBbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHsgdHlwZTogJ3JlbGVhc2UnLCBpbjogc2Vzc2lvbklkIH07XG4gICAgICBwcm94eVdvcmtlciEucG9zdE1lc3NhZ2UobWVzc2FnZSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgY29yZS5yZWxlYXNlU2Vzc2lvbihzZXNzaW9uSWQpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcnVuID0gYXN5bmMgKFxuICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgaW5wdXRJbmRpY2VzOiBudW1iZXJbXSxcbiAgaW5wdXRzOiBUZW5zb3JNZXRhZGF0YVtdLFxuICBvdXRwdXRJbmRpY2VzOiBudW1iZXJbXSxcbiAgb3V0cHV0czogQXJyYXk8VGVuc29yTWV0YWRhdGEgfCBudWxsPixcbiAgb3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zLFxuKTogUHJvbWlzZTxUZW5zb3JNZXRhZGF0YVtdPiA9PiB7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgLy8gY2hlY2sgaW5wdXRzIGxvY2F0aW9uXG4gICAgaWYgKGlucHV0cy5zb21lKCh0KSA9PiB0WzNdICE9PSAnY3B1JykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgdGVuc29yIG9uIEdQVSBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4nKTtcbiAgICB9XG4gICAgLy8gY2hlY2sgb3V0cHV0cyBsb2NhdGlvblxuICAgIGlmIChvdXRwdXRzLnNvbWUoKHQpID0+IHQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ByZS1hbGxvY2F0ZWQgb3V0cHV0IHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4nKTtcbiAgICB9XG4gICAgZW5zdXJlV29ya2VyKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPFNlcmlhbGl6YWJsZVRlbnNvck1ldGFkYXRhW10+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGVucXVldWVDYWxsYmFja3MoJ3J1bicsIFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IHNlcmlhbGl6YWJsZUlucHV0cyA9IGlucHV0cyBhcyBTZXJpYWxpemFibGVUZW5zb3JNZXRhZGF0YVtdOyAvLyBldmVyeSBpbnB1dCBpcyBvbiBDUFUuXG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHtcbiAgICAgICAgdHlwZTogJ3J1bicsXG4gICAgICAgIGluOiB7IHNlc3Npb25JZCwgaW5wdXRJbmRpY2VzLCBpbnB1dHM6IHNlcmlhbGl6YWJsZUlucHV0cywgb3V0cHV0SW5kaWNlcywgb3B0aW9ucyB9LFxuICAgICAgfTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlLCBjb3JlLmV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzKHNlcmlhbGl6YWJsZUlucHV0cykpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBjb3JlLnJ1bihzZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRzLCBvdXRwdXRJbmRpY2VzLCBvdXRwdXRzLCBvcHRpb25zKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGVuZFByb2ZpbGluZyA9IGFzeW5jIChzZXNzaW9uSWQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBlbnF1ZXVlQ2FsbGJhY2tzKCdlbmQtcHJvZmlsaW5nJywgW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7IHR5cGU6ICdlbmQtcHJvZmlsaW5nJywgaW46IHNlc3Npb25JZCB9O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNvcmUuZW5kUHJvZmlsaW5nKHNlc3Npb25JZCk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7XG4gIEluZmVyZW5jZVNlc3Npb24sXG4gIEluZmVyZW5jZVNlc3Npb25IYW5kbGVyLFxuICBTZXNzaW9uSGFuZGxlcixcbiAgVGVuc29yLFxuICBUUkFDRV9GVU5DX0JFR0lOLFxuICBUUkFDRV9GVU5DX0VORCxcbn0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgU2VyaWFsaXphYmxlSW50ZXJuYWxCdWZmZXIsIFRlbnNvck1ldGFkYXRhIH0gZnJvbSAnLi9wcm94eS1tZXNzYWdlcyc7XG5pbXBvcnQgeyBjb3B5RnJvbUV4dGVybmFsQnVmZmVyLCBjcmVhdGVTZXNzaW9uLCBlbmRQcm9maWxpbmcsIHJlbGVhc2VTZXNzaW9uLCBydW4gfSBmcm9tICcuL3Byb3h5LXdyYXBwZXInO1xuaW1wb3J0IHsgaXNHcHVCdWZmZXJTdXBwb3J0ZWRUeXBlLCBpc01MVGVuc29yU3VwcG9ydGVkVHlwZSB9IGZyb20gJy4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgaXNOb2RlIH0gZnJvbSAnLi93YXNtLXV0aWxzLWVudic7XG5pbXBvcnQgeyBsb2FkRmlsZSB9IGZyb20gJy4vd2FzbS11dGlscy1sb2FkLWZpbGUnO1xuXG5leHBvcnQgY29uc3QgZW5jb2RlVGVuc29yTWV0YWRhdGEgPSAodGVuc29yOiBUZW5zb3IsIGdldE5hbWU6ICgpID0+IHN0cmluZyk6IFRlbnNvck1ldGFkYXRhID0+IHtcbiAgc3dpdGNoICh0ZW5zb3IubG9jYXRpb24pIHtcbiAgICBjYXNlICdjcHUnOlxuICAgICAgcmV0dXJuIFt0ZW5zb3IudHlwZSwgdGVuc29yLmRpbXMsIHRlbnNvci5kYXRhLCAnY3B1J107XG4gICAgY2FzZSAnZ3B1LWJ1ZmZlcic6XG4gICAgICByZXR1cm4gW3RlbnNvci50eXBlLCB0ZW5zb3IuZGltcywgeyBncHVCdWZmZXI6IHRlbnNvci5ncHVCdWZmZXIgfSwgJ2dwdS1idWZmZXInXTtcbiAgICBjYXNlICdtbC10ZW5zb3InOlxuICAgICAgcmV0dXJuIFt0ZW5zb3IudHlwZSwgdGVuc29yLmRpbXMsIHsgbWxUZW5zb3I6IHRlbnNvci5tbFRlbnNvciB9LCAnbWwtdGVuc29yJ107XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkYXRhIGxvY2F0aW9uOiAke3RlbnNvci5sb2NhdGlvbn0gZm9yICR7Z2V0TmFtZSgpfWApO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZGVjb2RlVGVuc29yTWV0YWRhdGEgPSAodGVuc29yOiBUZW5zb3JNZXRhZGF0YSk6IFRlbnNvciA9PiB7XG4gIHN3aXRjaCAodGVuc29yWzNdKSB7XG4gICAgY2FzZSAnY3B1JzpcbiAgICAgIHJldHVybiBuZXcgVGVuc29yKHRlbnNvclswXSwgdGVuc29yWzJdLCB0ZW5zb3JbMV0pO1xuICAgIGNhc2UgJ2dwdS1idWZmZXInOiB7XG4gICAgICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclswXTtcbiAgICAgIGlmICghaXNHcHVCdWZmZXJTdXBwb3J0ZWRUeXBlKGRhdGFUeXBlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vdCBzdXBwb3J0ZWQgZGF0YSB0eXBlOiAke2RhdGFUeXBlfSBmb3IgZGVzZXJpYWxpemluZyBHUFUgdGVuc29yYCk7XG4gICAgICB9XG4gICAgICBjb25zdCB7IGdwdUJ1ZmZlciwgZG93bmxvYWQsIGRpc3Bvc2UgfSA9IHRlbnNvclsyXTtcbiAgICAgIHJldHVybiBUZW5zb3IuZnJvbUdwdUJ1ZmZlcihncHVCdWZmZXIsIHsgZGF0YVR5cGUsIGRpbXM6IHRlbnNvclsxXSwgZG93bmxvYWQsIGRpc3Bvc2UgfSk7XG4gICAgfVxuICAgIGNhc2UgJ21sLXRlbnNvcic6IHtcbiAgICAgIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yWzBdO1xuICAgICAgaWYgKCFpc01MVGVuc29yU3VwcG9ydGVkVHlwZShkYXRhVHlwZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGRhdGEgdHlwZTogJHtkYXRhVHlwZX0gZm9yIGRlc2VyaWFsaXppbmcgTUxUZW5zb3IgdGVuc29yYCk7XG4gICAgICB9XG4gICAgICBjb25zdCB7IG1sVGVuc29yLCBkb3dubG9hZCwgZGlzcG9zZSB9ID0gdGVuc29yWzJdO1xuICAgICAgcmV0dXJuIFRlbnNvci5mcm9tTUxUZW5zb3IobWxUZW5zb3IsIHsgZGF0YVR5cGUsIGRpbXM6IHRlbnNvclsxXSwgZG93bmxvYWQsIGRpc3Bvc2UgfSk7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGF0YSBsb2NhdGlvbjogJHt0ZW5zb3JbM119YCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjbGFzcyBPbm54cnVudGltZVdlYkFzc2VtYmx5U2Vzc2lvbkhhbmRsZXIgaW1wbGVtZW50cyBJbmZlcmVuY2VTZXNzaW9uSGFuZGxlciB7XG4gIHByaXZhdGUgc2Vzc2lvbklkOiBudW1iZXI7XG5cbiAgaW5wdXROYW1lczogcmVhZG9ubHkgc3RyaW5nW107XG4gIG91dHB1dE5hbWVzOiByZWFkb25seSBzdHJpbmdbXTtcbiAgaW5wdXRNZXRhZGF0YTogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbi5WYWx1ZU1ldGFkYXRhW107XG4gIG91dHB1dE1ldGFkYXRhOiByZWFkb25seSBJbmZlcmVuY2VTZXNzaW9uLlZhbHVlTWV0YWRhdGFbXTtcblxuICBhc3luYyBmZXRjaE1vZGVsQW5kQ29weVRvV2FzbU1lbW9yeShwYXRoOiBzdHJpbmcpOiBQcm9taXNlPFNlcmlhbGl6YWJsZUludGVybmFsQnVmZmVyPiB7XG4gICAgLy8gZmV0Y2ggbW9kZWwgZnJvbSB1cmwgYW5kIG1vdmUgdG8gd2FzbSBoZWFwLlxuICAgIHJldHVybiBjb3B5RnJvbUV4dGVybmFsQnVmZmVyKGF3YWl0IGxvYWRGaWxlKHBhdGgpKTtcbiAgfVxuXG4gIGFzeW5jIGxvYWRNb2RlbChwYXRoT3JCdWZmZXI6IHN0cmluZyB8IFVpbnQ4QXJyYXksIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTigpO1xuICAgIGxldCBtb2RlbDogUGFyYW1ldGVyczx0eXBlb2YgY3JlYXRlU2Vzc2lvbj5bMF07XG5cbiAgICBpZiAodHlwZW9mIHBhdGhPckJ1ZmZlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlmIChpc05vZGUpIHtcbiAgICAgICAgLy8gbm9kZVxuICAgICAgICBtb2RlbCA9IGF3YWl0IGxvYWRGaWxlKHBhdGhPckJ1ZmZlcik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBicm93c2VyXG4gICAgICAgIC8vIGZldGNoIG1vZGVsIGFuZCBjb3B5IHRvIHdhc20gaGVhcC5cbiAgICAgICAgbW9kZWwgPSBhd2FpdCB0aGlzLmZldGNoTW9kZWxBbmRDb3B5VG9XYXNtTWVtb3J5KHBhdGhPckJ1ZmZlcik7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIG1vZGVsID0gcGF0aE9yQnVmZmVyO1xuICAgIH1cblxuICAgIFt0aGlzLnNlc3Npb25JZCwgdGhpcy5pbnB1dE5hbWVzLCB0aGlzLm91dHB1dE5hbWVzLCB0aGlzLmlucHV0TWV0YWRhdGEsIHRoaXMub3V0cHV0TWV0YWRhdGFdID0gYXdhaXQgY3JlYXRlU2Vzc2lvbihcbiAgICAgIG1vZGVsLFxuICAgICAgb3B0aW9ucyxcbiAgICApO1xuICAgIFRSQUNFX0ZVTkNfRU5EKCk7XG4gIH1cblxuICBhc3luYyBkaXNwb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiByZWxlYXNlU2Vzc2lvbih0aGlzLnNlc3Npb25JZCk7XG4gIH1cblxuICBhc3luYyBydW4oXG4gICAgZmVlZHM6IFNlc3Npb25IYW5kbGVyLkZlZWRzVHlwZSxcbiAgICBmZXRjaGVzOiBTZXNzaW9uSGFuZGxlci5GZXRjaGVzVHlwZSxcbiAgICBvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMsXG4gICk6IFByb21pc2U8U2Vzc2lvbkhhbmRsZXIuUmV0dXJuVHlwZT4ge1xuICAgIFRSQUNFX0ZVTkNfQkVHSU4oKTtcbiAgICBjb25zdCBpbnB1dEFycmF5OiBUZW5zb3JbXSA9IFtdO1xuICAgIGNvbnN0IGlucHV0SW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgICBPYmplY3QuZW50cmllcyhmZWVkcykuZm9yRWFjaCgoa3ZwKSA9PiB7XG4gICAgICBjb25zdCBuYW1lID0ga3ZwWzBdO1xuICAgICAgY29uc3QgdGVuc29yID0ga3ZwWzFdO1xuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmlucHV0TmFtZXMuaW5kZXhPZihuYW1lKTtcbiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGlucHV0ICcke25hbWV9J2ApO1xuICAgICAgfVxuICAgICAgaW5wdXRBcnJheS5wdXNoKHRlbnNvcik7XG4gICAgICBpbnB1dEluZGljZXMucHVzaChpbmRleCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBvdXRwdXRBcnJheTogQXJyYXk8VGVuc29yIHwgbnVsbD4gPSBbXTtcbiAgICBjb25zdCBvdXRwdXRJbmRpY2VzOiBudW1iZXJbXSA9IFtdO1xuICAgIE9iamVjdC5lbnRyaWVzKGZldGNoZXMpLmZvckVhY2goKGt2cCkgPT4ge1xuICAgICAgY29uc3QgbmFtZSA9IGt2cFswXTtcbiAgICAgIGNvbnN0IHRlbnNvciA9IGt2cFsxXTtcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5vdXRwdXROYW1lcy5pbmRleE9mKG5hbWUpO1xuICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgb3V0cHV0ICcke25hbWV9J2ApO1xuICAgICAgfVxuICAgICAgb3V0cHV0QXJyYXkucHVzaCh0ZW5zb3IpO1xuICAgICAgb3V0cHV0SW5kaWNlcy5wdXNoKGluZGV4KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IGlucHV0cyA9IGlucHV0QXJyYXkubWFwKCh0LCBpKSA9PlxuICAgICAgZW5jb2RlVGVuc29yTWV0YWRhdGEodCwgKCkgPT4gYGlucHV0IFwiJHt0aGlzLmlucHV0TmFtZXNbaW5wdXRJbmRpY2VzW2ldXX1cImApLFxuICAgICk7XG4gICAgY29uc3Qgb3V0cHV0cyA9IG91dHB1dEFycmF5Lm1hcCgodCwgaSkgPT5cbiAgICAgIHQgPyBlbmNvZGVUZW5zb3JNZXRhZGF0YSh0LCAoKSA9PiBgb3V0cHV0IFwiJHt0aGlzLm91dHB1dE5hbWVzW291dHB1dEluZGljZXNbaV1dfVwiYCkgOiBudWxsLFxuICAgICk7XG5cbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgcnVuKHRoaXMuc2Vzc2lvbklkLCBpbnB1dEluZGljZXMsIGlucHV0cywgb3V0cHV0SW5kaWNlcywgb3V0cHV0cywgb3B0aW9ucyk7XG5cbiAgICBjb25zdCByZXN1bHRNYXA6IFNlc3Npb25IYW5kbGVyLlJldHVyblR5cGUgPSB7fTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlc3VsdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdE1hcFt0aGlzLm91dHB1dE5hbWVzW291dHB1dEluZGljZXNbaV1dXSA9IG91dHB1dEFycmF5W2ldID8/IGRlY29kZVRlbnNvck1ldGFkYXRhKHJlc3VsdHNbaV0pO1xuICAgIH1cbiAgICBUUkFDRV9GVU5DX0VORCgpO1xuICAgIHJldHVybiByZXN1bHRNYXA7XG4gIH1cblxuICBzdGFydFByb2ZpbGluZygpOiB2b2lkIHtcbiAgICAvLyBUT0RPOiBpbXBsZW1lbnQgcHJvZmlsaW5nXG4gIH1cblxuICBlbmRQcm9maWxpbmcoKTogdm9pZCB7XG4gICAgdm9pZCBlbmRQcm9maWxpbmcodGhpcy5zZXNzaW9uSWQpO1xuICB9XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IEJhY2tlbmQsIGVudiwgSW5mZXJlbmNlU2Vzc2lvbiwgSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBpbml0aWFsaXplT3J0RXAsIGluaXRpYWxpemVXZWJBc3NlbWJseUFuZE9ydFJ1bnRpbWUgfSBmcm9tICcuL3dhc20vcHJveHktd3JhcHBlcic7XG5pbXBvcnQgeyBPbm54cnVudGltZVdlYkFzc2VtYmx5U2Vzc2lvbkhhbmRsZXIgfSBmcm9tICcuL3dhc20vc2Vzc2lvbi1oYW5kbGVyLWluZmVyZW5jZSc7XG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiBpbml0aWFsaXplcyBhbGwgZmxhZ3MgZm9yIFdlYkFzc2VtYmx5LlxuICpcbiAqIFRob3NlIGZsYWdzIGFyZSBhY2Nlc3NpYmxlIGZyb20gYG9ydC5lbnYud2FzbWAuIFVzZXJzIGFyZSBhbGxvdyB0byBzZXQgdGhvc2UgZmxhZ3MgYmVmb3JlIHRoZSBmaXJzdCBpbmZlcmVuY2Ugc2Vzc2lvblxuICogYmVpbmcgY3JlYXRlZCwgdG8gb3ZlcnJpZGUgZGVmYXVsdCB2YWx1ZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGluaXRpYWxpemVGbGFncyA9ICgpOiB2b2lkID0+IHtcbiAgaWYgKHR5cGVvZiBlbnYud2FzbS5pbml0VGltZW91dCAhPT0gJ251bWJlcicgfHwgZW52Lndhc20uaW5pdFRpbWVvdXQgPCAwKSB7XG4gICAgZW52Lndhc20uaW5pdFRpbWVvdXQgPSAwO1xuICB9XG5cbiAgY29uc3Qgc2ltZCA9IGVudi53YXNtLnNpbWQ7XG4gIGlmICh0eXBlb2Ygc2ltZCAhPT0gJ2Jvb2xlYW4nICYmIHNpbWQgIT09IHVuZGVmaW5lZCAmJiBzaW1kICE9PSAnZml4ZWQnICYmIHNpbWQgIT09ICdyZWxheGVkJykge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgY29uc29sZS53YXJuKFxuICAgICAgYFByb3BlcnR5IFwiZW52Lndhc20uc2ltZFwiIGlzIHNldCB0byB1bmtub3duIHZhbHVlIFwiJHtzaW1kfVwiLiBSZXNldCBpdCB0byBcXGBmYWxzZVxcYCBhbmQgaWdub3JlIFNJTUQgZmVhdHVyZSBjaGVja2luZy5gLFxuICAgICk7XG4gICAgZW52Lndhc20uc2ltZCA9IGZhbHNlO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBlbnYud2FzbS5wcm94eSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgZW52Lndhc20ucHJveHkgPSBmYWxzZTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgZW52Lndhc20udHJhY2UgIT09ICdib29sZWFuJykge1xuICAgIGVudi53YXNtLnRyYWNlID0gZmFsc2U7XG4gIH1cblxuICBpZiAodHlwZW9mIGVudi53YXNtLm51bVRocmVhZHMgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKGVudi53YXNtLm51bVRocmVhZHMpIHx8IGVudi53YXNtLm51bVRocmVhZHMgPD0gMCkge1xuICAgIC8vIFRoZSBmb2xsb3dpbmcgbG9naWMgb25seSBhcHBsaWVzIHdoZW4gYG9ydC5lbnYud2FzbS5udW1UaHJlYWRzYCBpcyBub3Qgc2V0IGJ5IHVzZXIuIFdlIHdpbGwgYWx3YXlzIGhvbm9yIHVzZXInc1xuICAgIC8vIHNldHRpbmcgaWYgaXQgaXMgcHJvdmlkZWQuXG5cbiAgICAvLyBCcm93c2VyOiB3aGVuIGNyb3NzT3JpZ2luSXNvbGF0ZWQgaXMgZmFsc2UsIFNoYXJlZEFycmF5QnVmZmVyIGlzIG5vdCBhdmFpbGFibGUgc28gV2ViQXNzZW1ibHkgdGhyZWFkcyB3aWxsIG5vdFxuICAgIC8vIHdvcmsuIEluIHRoaXMgY2FzZSwgd2Ugd2lsbCBzZXQgbnVtVGhyZWFkcyB0byAxLlxuICAgIC8vXG4gICAgLy8gVGhlcmUgaXMgYW4gZXhjZXB0aW9uOiB3aGVuIHRoZSBicm93c2VyIGlzIGNvbmZpZ3VyZWQgdG8gZm9yY2UtZW5hYmxlIFNoYXJlZEFycmF5QnVmZmVyIChlLmcuIENocm9tdWltIHdpdGhcbiAgICAvLyAtLWVuYWJsZS1mZWF0dXJlcz1TaGFyZWRBcnJheUJ1ZmZlciksIGl0IGlzIHBvc3NpYmxlIHRoYXQgYHNlbGYuY3Jvc3NPcmlnaW5Jc29sYXRlZGAgaXMgZmFsc2UgYW5kXG4gICAgLy8gU2hhcmVkQXJyYXlCdWZmZXIgaXMgYXZhaWxhYmxlIGF0IHRoZSBzYW1lIHRpbWUuIFRoaXMgaXMgdXN1YWxseSBmb3IgdGVzdGluZy4gSW4gdGhpcyBjYXNlLCAgd2Ugd2lsbCBzdGlsbCBzZXRcbiAgICAvLyBudW1UaHJlYWRzIHRvIDEgaGVyZS4gSWYgd2Ugd2FudCB0byBlbmFibGUgbXVsdGktdGhyZWFkaW5nIGluIHRlc3QsIHdlIHNob3VsZCBzZXQgYG9ydC5lbnYud2FzbS5udW1UaHJlYWRzYCB0byBhXG4gICAgLy8gdmFsdWUgZ3JlYXRlciB0aGFuIDEuXG4gICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyAmJiAhc2VsZi5jcm9zc09yaWdpbklzb2xhdGVkKSB7XG4gICAgICBlbnYud2FzbS5udW1UaHJlYWRzID0gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgbnVtQ3B1TG9naWNhbENvcmVzID1cbiAgICAgICAgdHlwZW9mIG5hdmlnYXRvciA9PT0gJ3VuZGVmaW5lZCcgPyByZXF1aXJlKCdub2RlOm9zJykuY3B1cygpLmxlbmd0aCA6IG5hdmlnYXRvci5oYXJkd2FyZUNvbmN1cnJlbmN5O1xuICAgICAgZW52Lndhc20ubnVtVGhyZWFkcyA9IE1hdGgubWluKDQsIE1hdGguY2VpbCgobnVtQ3B1TG9naWNhbENvcmVzIHx8IDEpIC8gMikpO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0IGNsYXNzIE9ubnhydW50aW1lV2ViQXNzZW1ibHlCYWNrZW5kIGltcGxlbWVudHMgQmFja2VuZCB7XG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGluaXRpYWxpemVzIHRoZSBXZWJBc3NlbWJseSBiYWNrZW5kLlxuICAgKlxuICAgKiBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIG9ubHkgb25jZSBmb3IgZWFjaCBiYWNrZW5kIG5hbWUuIEl0IHdpbGwgYmUgY2FsbGVkIHRoZSBmaXJzdCB0aW1lIHdoZW5cbiAgICogYG9ydC5JbmZlcmVuY2VTZXNzaW9uLmNyZWF0ZSgpYCBpcyBjYWxsZWQgd2l0aCBhIHJlZ2lzdGVyZWQgYmFja2VuZCBuYW1lLlxuICAgKlxuICAgKiBAcGFyYW0gYmFja2VuZE5hbWUgLSB0aGUgcmVnaXN0ZXJlZCBiYWNrZW5kIG5hbWUuXG4gICAqL1xuICBhc3luYyBpbml0KGJhY2tlbmROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBwb3B1bGF0ZSB3YXNtIGZsYWdzXG4gICAgaW5pdGlhbGl6ZUZsYWdzKCk7XG5cbiAgICAvLyBpbml0IHdhc21cbiAgICBhd2FpdCBpbml0aWFsaXplV2ViQXNzZW1ibHlBbmRPcnRSdW50aW1lKCk7XG5cbiAgICAvLyBwZXJmb3JtZSBFUCBzcGVjaWZpYyBpbml0aWFsaXphdGlvblxuICAgIGF3YWl0IGluaXRpYWxpemVPcnRFcChiYWNrZW5kTmFtZSk7XG4gIH1cbiAgY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIoXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zLFxuICApOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25IYW5kbGVyPjtcbiAgY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIoXG4gICAgYnVmZmVyOiBVaW50OEFycmF5LFxuICAgIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zLFxuICApOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25IYW5kbGVyPjtcbiAgYXN5bmMgY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIoXG4gICAgcGF0aE9yQnVmZmVyOiBzdHJpbmcgfCBVaW50OEFycmF5LFxuICAgIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zLFxuICApOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25IYW5kbGVyPiB7XG4gICAgY29uc3QgaGFuZGxlciA9IG5ldyBPbm54cnVudGltZVdlYkFzc2VtYmx5U2Vzc2lvbkhhbmRsZXIoKTtcbiAgICBhd2FpdCBoYW5kbGVyLmxvYWRNb2RlbChwYXRoT3JCdWZmZXIsIG9wdGlvbnMpO1xuICAgIHJldHVybiBoYW5kbGVyO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCB3YXNtQmFja2VuZCA9IG5ldyBPbm54cnVudGltZVdlYkFzc2VtYmx5QmFja2VuZCgpO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzICovXG5cbi8vIFdlIHVzZSBcInJlcXVpcmVcIiBpbnN0ZWFkIG9mIFwiaW1wb3J0XCIgaGVyZSBiZWNhdXNlIGltcG9ydCBzdGF0ZW1lbnQgbXVzdCBiZSBwdXQgaW4gdG9wIGxldmVsLiBPdXIgY3VycmVudCBjb2RlIGRvZXNcbi8vIG5vdCBhbGxvdyBidW5kbGVyIHRvIHRyZWUtc2hha2luZyBjb2RlIGFzIGV4cGVjdGVkIGJlY2F1c2Ugc29tZSBjb2RlcyBhcmUgdHJlYXRlZCBhcyBoYXZpbmcgc2lkZSBlZmZlY3RzLlxuLy8gU28gd2UgaW1wb3J0IGNvZGUgaW5zaWRlIHRoZSBpZi1jbGF1c2UgdG8gYWxsb3cgYnVuZGxlciByZW1vdmUgdGhlIGNvZGUgc2FmZWx5LlxuXG5leHBvcnQgKiBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuaW1wb3J0ICogYXMgb3J0IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5leHBvcnQgZGVmYXVsdCBvcnQ7XG5cbmltcG9ydCB7IHJlZ2lzdGVyQmFja2VuZCwgZW52IH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcbmltcG9ydCB7IHZlcnNpb24gfSBmcm9tICcuL3ZlcnNpb24nO1xuXG5pZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XRUJHTCkge1xuICBjb25zdCBvbm54anNCYWNrZW5kID0gcmVxdWlyZSgnLi9iYWNrZW5kLW9ubnhqcycpLm9ubnhqc0JhY2tlbmQ7XG4gIHJlZ2lzdGVyQmFja2VuZCgnd2ViZ2wnLCBvbm54anNCYWNrZW5kLCAtMTApO1xufVxuXG5pZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQICYmICFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVKSB7XG4gIHRocm93IG5ldyBFcnJvcihcbiAgICAnVGhlIGN1cnJlbnQgYnVpbGQgaXMgc3BlY2lmaWVkIHRvIGVuYWJsZSBib3RoIEpTRVAgYW5kIFdlYkdQVSBFUC4gVGhpcyBpcyBub3QgYSB2YWxpZCBjb25maWd1cmF0aW9uLiAnICtcbiAgICAgICdKU0VQIGFuZCBXZWJHUFUgRVBzIGNhbm5vdCBiZSBlbmFibGVkIGF0IHRoZSBzYW1lIHRpbWUuJyxcbiAgKTtcbn1cblxuaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCTk4gJiYgQlVJTERfREVGUy5ESVNBQkxFX0pTRVAgJiYgQlVJTERfREVGUy5ESVNBQkxFX1dFQkdQVSkge1xuICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgJ1RoZSBjdXJyZW50IGJ1aWxkIGlzIHNwZWNpZmllZCB0byBlbmFibGUgV2ViTk4gRVAgd2l0aG91dCBKU0VQIG9yIFdlYkdQVSBFUC4gVGhpcyBpcyBub3QgYSB2YWxpZCBjb25maWd1cmF0aW9uLiAnICtcbiAgICAgICdXZWJOTiBFUCByZXF1aXJlcyBlaXRoZXIgSlNFUCBvciBXZWJHUFUgRVAgdG8gYmUgZW5hYmxlZC4nLFxuICApO1xufVxuXG5pZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNKSB7XG4gIGNvbnN0IHdhc21CYWNrZW5kID0gcmVxdWlyZSgnLi9iYWNrZW5kLXdhc20nKS53YXNtQmFja2VuZDtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUCB8fCAhQlVJTERfREVGUy5ESVNBQkxFX1dFQkdQVSkge1xuICAgIHJlZ2lzdGVyQmFja2VuZCgnd2ViZ3B1Jywgd2FzbUJhY2tlbmQsIDUpO1xuICB9XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dFQk5OKSB7XG4gICAgcmVnaXN0ZXJCYWNrZW5kKCd3ZWJubicsIHdhc21CYWNrZW5kLCA1KTtcbiAgfVxuICByZWdpc3RlckJhY2tlbmQoJ2NwdScsIHdhc21CYWNrZW5kLCAxMCk7XG4gIHJlZ2lzdGVyQmFja2VuZCgnd2FzbScsIHdhc21CYWNrZW5kLCAxMCk7XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShlbnYudmVyc2lvbnMsICd3ZWInLCB7IHZhbHVlOiB2ZXJzaW9uLCBlbnVtZXJhYmxlOiB0cnVlIH0pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vLyBUaGlzIGZpbGUgaXMgZ2VuZXJhdGVkIGJ5IC9qcy9zY3JpcHRzL3VwZGF0ZS12ZXJzaW9uLnRzXG4vLyBEbyBub3QgbW9kaWZ5IGZpbGUgY29udGVudCBtYW51YWxseS5cblxuZXhwb3J0IGNvbnN0IHZlcnNpb24gPSAnMS4yNi4wJztcbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsTUFnQk0sVUFDQSwwQkFZTyxpQkF3Q1AsZ0NBd0NPO0FBN0diOzs7QUFnQkEsTUFBTSxXQUFxQyxvQkFBSSxJQUFHO0FBQ2xELE1BQU0sMkJBQXFDLENBQUE7QUFZcEMsTUFBTSxrQkFBa0IsQ0FBQyxNQUFjLFNBQWtCLGFBQTBCO0FBQ3hGLFlBQUksV0FBVyxPQUFPLFFBQVEsU0FBUyxjQUFjLE9BQU8sUUFBUSxrQ0FBa0MsWUFBWTtBQUNoSCxnQkFBTSxpQkFBaUIsU0FBUyxJQUFJLElBQUk7QUFDeEMsY0FBSSxtQkFBbUIsUUFBVztBQUNoQyxxQkFBUyxJQUFJLE1BQU0sRUFBRSxTQUFTLFNBQVEsQ0FBRTtxQkFDL0IsZUFBZSxXQUFXLFVBQVU7QUFFN0M7cUJBQ1MsZUFBZSxhQUFhLFVBQVU7QUFDL0MsZ0JBQUksZUFBZSxZ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QUFBLEVBQ0Y7QUFFQSxNQUFJLE1BQTBCO0FBQzVCLFVBQU1DLGVBQWMsMERBQTBCO0FBQzlDLFFBQUksTUFBd0Q7QUFDMUQsc0JBQWdCLFVBQVVBLGNBQWEsQ0FBQztBQUFBLElBQzFDO0FBQ0EsUUFBSSxNQUEyQjtBQUM3QixzQkFBZ0IsU0FBU0EsY0FBYSxDQUFDO0FBQUEsSUFDekM7QUFDQSxvQkFBZ0IsT0FBT0EsY0FBYSxFQUFFO0FBQ3RDLG9CQUFnQixRQUFRQSxjQUFhLEVBQUU7QUFBQSxFQUN6QztBQUVBLFNBQU8sZUFBZUMsS0FBSSxVQUFVLE9BQU8sRUFBRSxPQUFPQyxVQUFTLFlBQVksS0FBSyxDQUFDOyIsCiAgIm5hbWVzIjogWyJpIiwgImVudiIsICJGbG9hdDE2QXJyYXkiLCAiVGVuc29yIiwgIlRlbnNvciIsICJJbmZlcmVuY2VTZXNzaW9uIiwgIkluZmVyZW5jZVNlc3Npb24iLCAiVGVuc29yIiwgImVudiIsICJlbnYiLCAid2FzbSIsICJ3YXNtIiwgIndhc20iLCAibG9jYXRpb24iLCAicGFkIiwgInRlbnNvciIsICJlbnYiLCAibWxDb250ZXh0SW5kZXgiLCAid2FzbSIsICJpbml0IiwgIm9mZnNldHMiLCAiaW5kaWNlcyIsICJpbXBsIiwgInZhbGlkYXRlSW5wdXRzIiwgInJlZHVjZU9wcyIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJlbnYiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiYSIsICJiIiwgInZhbGlkYXRlSW5wdXRzIiwgImkiLCAiaW5wdXRWYXJpYWJsZSIsICJ0cmFuc3Bvc2UiLCAib3V0cHV0VmFyaWFibGUiLCAiaW5uZXJFbGVtZW50U2l6ZSIsICJwYWQiLCAidmFsaWRhdGVJbnB1dHMiLCAiY29udklucHV0cyIsICJ0cmFuc3Bvc2VkV2VpZ2h0IiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgInBlcm1GdW5jdGlvbkJvZHkiLCAic3ltYm9sIiwgInJlZHVjZU9wcyIsICJ2YWxpZGF0ZUlucHV0cyIsICJjYWxjdWxhdGVPdXRwdXRTaGFwZSIsICJmYXN0R2VsdSIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJpbnB1dHMiLCAib3V0cHV0U2l6ZSIsICJ2YWxpZGF0ZUlucHV0cyIsICJ3ZWlnaHRUcmFuc3Bvc2VBdHRyaWJ1dGUiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAid2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgImRhdGFUeXBlIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgImVudiIsICJ2YWxpZGF0ZUlucHV0cyIsICJlbnYiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiY29tcG9uZW50cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJnZXRPdXRwdXRTaGFwZSIsICJhIiwgImIiLCAiYyIsICJmYXN0R2VsdSIsICJlbnYiLCAiaSIsICJlbnYiLCAiZW52IiwgIndhc20iLCAibG9jYXRpb24iLCAiaW5kZXgiLCAidGVuc29yIiwgImVycm9yQ29kZSIsICJpIiwgImluaXRpYWxpemluZyIsICJpbml0aWFsaXplZCIsICJhYm9ydGVkIiwgImNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIiLCAiY3JlYXRlU2Vzc2lvbiIsICJyZWxlYXNlU2Vzc2lvbiIsICJydW4iLCAiZW5kUHJvZmlsaW5nIiwgImVudiIsICJUZW5zb3IiLCAiY29weUZyb21FeHRlcm5hbEJ1ZmZlciIsICJjcmVhdGVTZXNzaW9uIiwgInJlbGVhc2VTZXNzaW9uIiwgInJ1biIsICJlbmRQcm9maWxpbmciLCAiZW52IiwgIkluZmVyZW5jZVNlc3Npb24iLCAiVGVuc29yIiwgImVudiIsICJ2ZXJzaW9uIiwgIndhc21CYWNrZW5kIiwgImVudiIsICJ2ZXJzaW9uIl0KfQo=