diff --git "a/dist/ort.webgpu.js" "b/dist/ort.webgpu.js" new file mode 100755--- /dev/null +++ "b/dist/ort.webgpu.js" @@ -0,0 +1,17534 @@ +/*! + * ONNX Runtime Web v1.23.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); + + // web/node_modules/onnxruntime-common/dist/esm/backend-impl.js + var backends, backendsSortedByPriority, registerBackend, tryResolveAndInitializeBackend, resolveBackendAndExecutionProviders; + var init_backend_impl = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/backend-impl.js"() { + 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); + } + }) + ]; + }; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/backend.js + var init_backend = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/backend.js"() { + init_backend_impl(); + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/version.js + var version; + var init_version = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/version.js"() { + version = "1.23.0"; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/env-impl.js + var logLevelValue, env; + var init_env_impl = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/env-impl.js"() { + 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 }); + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/env.js + var env2; + var init_env = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/env.js"() { + init_env_impl(); + env2 = env; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/tensor-conversion-impl.js + var tensorToDataURL, tensorToImageData; + var init_tensor_conversion_impl = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/tensor-conversion-impl.js"() { + 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; + }; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/tensor-factory-impl.js + var bufferToTensor, tensorFromImage, tensorFromTexture, tensorFromGpuBuffer, tensorFromMLTensor, tensorFromPinnedBuffer; + var init_tensor_factory_impl = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/tensor-factory-impl.js"() { + 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] }); + } + }); + + // web/node_modules/onnxruntime-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({ + "web/node_modules/onnxruntime-common/dist/esm/tensor-impl-type-mapping.js"() { + 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); + } + } + }; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/tensor-utils-impl.js + var calculateSize, tensorReshape; + var init_tensor_utils_impl = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/tensor-utils-impl.js"() { + 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`); + } + }; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/tensor-impl.js + var Tensor; + var init_tensor_impl = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/tensor-impl.js"() { + 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); + } + }; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/tensor.js + var Tensor2; + var init_tensor = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/tensor.js"() { + init_tensor_impl(); + Tensor2 = Tensor; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/trace.js + var TRACE, TRACE_FUNC, TRACE_FUNC_BEGIN, TRACE_FUNC_END; + var init_trace = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/trace.js"() { + 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); + }; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/inference-session-impl.js + var InferenceSession; + var init_inference_session_impl = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/inference-session-impl.js"() { + init_backend_impl(); + init_tensor(); + init_trace(); + InferenceSession = class _InferenceSession { + constructor(handler) { + this.handler = handler; + } + async run(feeds, arg1, arg2) { + TRACE_FUNC_BEGIN(); + 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_FUNC_END(); + return returnValue; + } + async release() { + return this.handler.dispose(); + } + static async create(arg0, arg1, arg2, arg3) { + TRACE_FUNC_BEGIN(); + 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_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; + } + }; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/inference-session.js + var InferenceSession2; + var init_inference_session = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/inference-session.js"() { + init_inference_session_impl(); + InferenceSession2 = InferenceSession; + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/tensor-conversion.js + var init_tensor_conversion = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/tensor-conversion.js"() { + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/tensor-factory.js + var init_tensor_factory = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/tensor-factory.js"() { + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/onnx-model.js + var init_onnx_model = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/onnx-model.js"() { + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/onnx-value.js + var init_onnx_value = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/onnx-value.js"() { + } + }); + + // web/node_modules/onnxruntime-common/dist/esm/index.js + var esm_exports = {}; + __export(esm_exports, { + InferenceSession: () => InferenceSession2, + TRACE: () => TRACE, + TRACE_FUNC_BEGIN: () => TRACE_FUNC_BEGIN, + TRACE_FUNC_END: () => TRACE_FUNC_END, + Tensor: () => Tensor2, + env: () => env2, + registerBackend: () => registerBackend + }); + var init_esm = __esm({ + "web/node_modules/onnxruntime-common/dist/esm/index.js"() { + 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.webgpu.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 */ + 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 : null).default + ) : void 0; + importWasmModule = async (urlOverride, prefixOverride, isMultiThreaded) => { + if (!urlOverride && !prefixOverride && embeddedWasmModule && scriptSrc && isSameOrigin(scriptSrc)) { + return [void 0, embeddedWasmModule]; + } else { + const wasmModuleFilename = true ? "ort-wasm-simd-threaded.jsep.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 (e) { + 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 (e) { + 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 (e) { + 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."); + } + 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); + 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; + } 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 serverity 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 "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, executionProviders, allocs) => { + for (const ep of executionProviders) { + let epName = typeof ep === "string" ? ep : ep.name; + const epOptions = []; + switch (epName) { + case "webnn": + epName = "WEBNN"; + 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 customOptions = ep; + if (customOptions.device) { + if (typeof GPUDevice !== "undefined" && customOptions.device instanceof GPUDevice) { + customDevice = customOptions.device; + } else { + throw new Error("Invalid GPU device set in WebGPU EP options."); + } + } + } + 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 serverity 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.executionProviders, 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( + // eslint-disable-next-line max-len + "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; + } + /** + * normailze 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); + let fallbackDataType; + if (!context.opSupportLimits().input.dataTypes.includes(dataType)) { + fallbackDataType = webnnDataTypeToFallback.get(dataType); + if (!fallbackDataType || !context.opSupportLimits().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; + } + 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(); + 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.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); + 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); + } + 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 context = this.mlContextBySessionId.get(sessionId); + const dataType = onnxDataTypeToWebnnDataType.get(tensorDataTypeStringToEnum(type)); + if (typeof dataType === "undefined") { + return false; + } + if (isInput) { + return !!context?.opSupportLimits().input.dataTypes.includes(dataType); + } else { + return !!context?.opSupportLimits().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.402823e+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.402823e+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 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 (outputCount > 1 && pastKey && ShapeUtil.size(pastKey.dims) > 0) { + inputsK.push(pastKey); + } + if (attentionBias) { + inputsK.push(attentionBias); + } + if (seqLens) { + inputsK.push(seqLens); + } + if (totalSequenceLengthInput) { + inputsK.push(totalSequenceLengthInput); + } + const probs = context.compute( + createAttentionProbsProgramInfo( + outputCount, + q, + k, + pastKey, + 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 (outputCount > 1 && pastValue && ShapeUtil.size(pastValue.dims) > 0) { + inputsV.push(pastValue); + } + if (seqLens) { + inputsV.push(seqLens); + } + if (totalSequenceLengthInput) { + inputsV.push(totalSequenceLengthInput); + } + context.compute( + createVxAttentionScoreProgramInfo( + outputCount, + probs, + v, + pastValue, + 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((x) => Number(x) ?? 1); + const bDims = b.dims.map((x) => Number(x) ?? 1); + 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; + 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 lengh 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 (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]}` + ); + } + if (sequenceLength > maxSequenceLength) { + throw new Error("Updating cos_cache and sin_cache in RotaryEmbedding is not currently supported"); + } + }; + 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 && seqlLens.dims.length !== 1 && seqlLens.dims[0] !== batchSize) { + throw new Error('Input "seqlens" is expected to have 1 dimension and the same dim 0 as batch_size'); + } + 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.bits > 4 ? attributes.n * nBlocksPerCol : attributes.n * Math.floor((nBlocksPerCol + 1) / 2); + 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 processOneWord = () => { + let calcStr = ` + // reuse a data + var input_offset = ${a.indicesToOffset(`${a.type.indices}(batch, row, word_offset)`)}; + var a_data: ${qDqDataType}; + for (var j: u32 = 0; j < ${8 / aComponents}; j++) { + a_data[j] = ${a.getByOffset("input_offset")}; + input_offset++; + } + `; + for (let c = 0; c < components * outputNumber; c++) { + calcStr += ` + b_value = ${bComponents === 1 ? `b${c}_data` : `b${c}_data[i]`}; + b_value_lower = unpack4xU8(b_value & b_mask); + b_value_upper = unpack4xU8((b_value >> 4) & 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[${i}] * b_dequantized_values[${i}]` : `dot(a_data[${i}], b_dequantized_values[${i}])`}` + ).join(" + ")}; + `; + } + return calcStr; + }; + const prepareScaleAndZeroPoint = () => { + let calcStr = ` + var col_index = col * ${components}; + ${zeroPoints ? ` + let zero_point_bytes_per_col = (nBlocksPerCol + 1) / 2; + var zero_point_byte_count: u32; + var zero_point_word_index: u32; + var zero_point_byte_offset: u32; + let zero_point_nibble_offset: u32 = block & 0x1u; + var zero_point_bits_offset: u32; + var zero_point_word: u32;` : ` + // The default zero point is 8 for unsigned 4-bit quantization. + let zero_point = ${dataType2}(${8});`} + `; + 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 >> 0x1u); + 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_nibble_offset << 2); + zero_point_word = ${zeroPoints.getByOffset("zero_point_word_index")} >> zero_point_bits_offset; + let zero_point${c} = ${dataType2}((zero_point_word) & 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 = 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 += ${8 / 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 tileSize = workgroupX * bComponents * 8; + 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_bytes_per_col = (n_blocks_per_col + 1) / 2; + let zero_point_byte_count = b_row * zero_point_bytes_per_col + (block >> 0x1u); + let zero_point_word_index = zero_point_byte_count >> 0x2u; + let zero_point_byte_offset = zero_point_byte_count & 0x3u; + let zero_point_nibble_offset: u32 = block & 0x1u; + let zero_point_bits_offset = (zero_point_byte_offset << 3) + (zero_point_nibble_offset << 2); + let zero_point_word = ${zeroPoints.getByOffset("zero_point_word_index")} >> zero_point_bits_offset; + let zero_point = ${dataType2}((zero_point_word) & 0xFu);` : ` + // The default zero point is 8 for unsigned 4-bit quantization. + let zero_point = ${dataType2}(${8});`} + 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++) { + ${readA()} + let b_value = ${bComponents === 1 ? `b_data` : `b_data[i]`}; + let b_value_lower = unpack4xU8(b_value & 0x0F0F0F0Fu); + let b_value_upper = unpack4xU8((b_value >> 4) & 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}; + } + 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[0].dataType === 6 /* int32 */ && inputs.length > 2) { + throw new Error("In the case of dequantizing int32 there is no zero point."); + } + 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}; 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.402823e+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) { + let value = exp(getValue(row, col, row_stride) - rowMaxShared) / rowSumShared; + 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: false + }); + 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(); + } + 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}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") { + if (true) { + 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, + // jsepReserveTensorId + () => backend.reserveTensorId(), + // jsepReleaseTensorId, + (tensorId) => backend.releaseTensorId(tensorId), + // jsepEnsureTensor + async (sessionId, tensorId, onnxDataType, shape, copyOld) => backend.ensureTensor(sessionId, tensorId, onnxDataType, shape, copyOld), + // jsepUploadTensor + (tensorId, data) => { + backend.uploadTensor(tensorId, data); + }, + // jsepDownloadTensor + async (tensorId, dstBuffer) => backend.downloadTensor(tensorId, dstBuffer) + ]); + } + }; + } + }); + + // 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_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?.(); + if (epName === "webgpu" && false) { + getInstance().webgpuInit((device) => { + env3.webgpu.device = device; + }); + } + if (true) { + const initJsep = (init_init(), __toCommonJS(init_exports)).init; + if (epName === "webgpu" && true) { + if (typeof navigator === "undefined" || !navigator.gpu) { + throw new Error("WebGPU is not supported in current environment"); + } + let adapter = env3.webgpu.adapter; + if (!adapter) { + 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}"`); + } + adapter = await navigator.gpu.requestAdapter({ powerPreference, forceFallbackAdapter }); + if (!adapter) { + 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 adapter.limits !== "object" || typeof adapter.features !== "object" || typeof adapter.requestDevice !== "function") { + throw new Error("Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object."); + } + } + await initJsep("webgpu", getInstance(), env3, adapter); + } + if (epName === "webnn") { + if (typeof navigator === "undefined" || !navigator.ml) { + throw new Error("WebNN is not supported in current environment"); + } + await initJsep("webnn", getInstance(), env3); + } + } + }; + 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 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); + 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 + ); + } + 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}).` + ); + } + 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) { + 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}.`); + } + } + } + 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 = []; + for (let i = 0; i < outputCount; i++) { + const tensor = Number(wasm2.getValue(outputValuesOffset + i * ptrSize, "*")); + if (tensor === outputTensorHandles[i]) { + output.push(outputTensors[i]); + 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; + } + 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 : 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_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.23.0"; + + // web/lib/index.ts + var index_default = esm_exports; + if (false) { + const onnxjsBackend = null.onnxjsBackend; + registerBackend("webgl", onnxjsBackend, -10); + } + if (true) { + const wasmBackend2 = (init_backend_wasm(), __toCommonJS(backend_wasm_exports)).wasmBackend; + if (true) { + registerBackend("webgpu", wasmBackend2, 5); + 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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vbm9kZV9tb2R1bGVzL29ubnhydW50aW1lLWNvbW1vbi9saWIvYmFja2VuZC1pbXBsLnRzIiwgIi4uL25vZGVfbW9kdWxlcy9vbm54cnVudGltZS1jb21tb24vbGliL2JhY2tlbmQudHMiLCAiLi4vbm9kZV9tb2R1bGVzL29ubnhydW50aW1lLWNvbW1vbi9saWIvdmVyc2lvbi50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi9lbnYtaW1wbC50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi9lbnYudHMiLCAiLi4vbm9kZV9tb2R1bGVzL29ubnhydW50aW1lLWNvbW1vbi9saWIvdGVuc29yLWNvbnZlcnNpb24taW1wbC50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi90ZW5zb3ItZmFjdG9yeS1pbXBsLnRzIiwgIi4uL25vZGVfbW9kdWxlcy9vbm54cnVudGltZS1jb21tb24vbGliL3RlbnNvci1pbXBsLXR5cGUtbWFwcGluZy50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi90ZW5zb3ItdXRpbHMtaW1wbC50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi90ZW5zb3ItaW1wbC50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi90ZW5zb3IudHMiLCAiLi4vbm9kZV9tb2R1bGVzL29ubnhydW50aW1lLWNvbW1vbi9saWIvdHJhY2UudHMiLCAiLi4vbm9kZV9tb2R1bGVzL29ubnhydW50aW1lLWNvbW1vbi9saWIvaW5mZXJlbmNlLXNlc3Npb24taW1wbC50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi9pbmZlcmVuY2Utc2Vzc2lvbi50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi90ZW5zb3ItY29udmVyc2lvbi50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi90ZW5zb3ItZmFjdG9yeS50cyIsICIuLi9ub2RlX21vZHVsZXMvb25ueHJ1bnRpbWUtY29tbW9uL2xpYi9vbm54LW1vZGVsLnRzIiwgIi4uL25vZGVfbW9kdWxlcy9vbm54cnVudGltZS1jb21tb24vbGliL29ubngtdmFsdWUudHMiLCAiLi4vbm9kZV9tb2R1bGVzL29ubnhydW50aW1lLWNvbW1vbi9saWIvaW5kZXgudHMiLCAiLi4vbGliL3dhc20vd2FzbS11dGlscy1lbnYudHMiLCAiLi4vbGliL3dhc20vcHJveHktd29ya2VyL21haW4udHMiLCAiLi4vbGliL3dhc20vd2FzbS11dGlscy1pbXBvcnQudHMiLCAiLi4vbGliL3dhc20vd2FzbS1mYWN0b3J5LnRzIiwgIi4uL2xpYi93YXNtL3dhc20tdXRpbHMudHMiLCAiLi4vbGliL3dhc20vcnVuLW9wdGlvbnMudHMiLCAiLi4vbGliL3dhc20vc2Vzc2lvbi1vcHRpb25zLnRzIiwgIi4uL2xpYi93YXNtL3dhc20tY29tbW9uLnRzIiwgIi4uL2xpYi93YXNtL3dhc20tdXRpbHMtbG9hZC1maWxlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvbG9nLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvdXRpbC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3RlbnNvci12aWV3LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2Vibm4vdGVuc29yLW1hbmFnZXIudHMiLCAiLi4vbGliL3dhc20vanNlcC9iYWNrZW5kLXdlYm5uLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L3R5cGVzLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L2dwdS1kYXRhLW1hbmFnZXIudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jb21tb24udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3RyYW5zcG9zZS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvcmVkdWNlLXNoYXJlZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvcmVkdWNlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9hcmdtaW5tYXgudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2F0dGVudGlvbi50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvYmF0Y2gtbm9ybS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvYmlhcy1hZGQudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3VuYXJ5LW9wLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9iaWFzLXNwbGl0LWdlbHUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2JpbmFyeS1vcC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvY29uY2F0LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9mdXNlLXV0aWxzLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvYWN0aXZhdGlvbl91dGlsLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvY29udl91dGlsLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9tYXRtdWwtc2hhZGVycy50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvM3JkLXBhcnR5L21hdG11bF9wYWNrZWRfd2ViZ3B1LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvY29udjJkX21tX3dlYmdwdS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvM3JkLXBhcnR5L2NvbnYzZF9uYWl2ZV93ZWJncHUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2NvbnYtZ3JvdXBlZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvY29udi50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvM3JkLXBhcnR5L2NvbnZfYmFja3Byb3Bfd2ViZ3B1LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jb252LXRyYW5zcG9zZS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvY3Vtc3VtLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9kZXB0aC10by1zcGFjZS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZWluc3VtLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9leHBhbmQudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2Zhc3QtZ2VsdS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZ2F0aGVyLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9nYXRoZXItbmQudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2dhdGhlci1ibG9jay1xdWFudGl6ZWQudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2dhdGhlci1lbGVtZW50cy50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZ2VtbS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZ3JpZC1zYW1wbGUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL211bHRpaGVhZC1hdHRlbnRpb24udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3NwbGl0LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9yb3RhcnktZW1iZWRkaW5nLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9ncm91cC1xdWVyeS1hdHRlbnRpb24udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2luc3RhbmNlLW5vcm0udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2xheWVyLW5vcm0udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL21hdG11bC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvbWF0bXVsbmJpdHMudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3BhZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvcG9vbC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvcXVhbnRpemUtbGluZWFyLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9yYW5nZS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvc2NhdHRlci1uZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvcmVzaXplLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9za2lwLWxheWVyLW5vcm0udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3NsaWNlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9zb2Z0bWF4LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy90aWxlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy93aGVyZS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcC1yZXNvbHZlLXJ1bGVzLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L3Byb2dyYW0tbWFuYWdlci50cyIsICIuLi9saWIvd2FzbS9qc2VwL2JhY2tlbmQtd2ViZ3B1LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvaW5pdC50cyIsICIuLi9saWIvd2FzbS93YXNtLWNvcmUtaW1wbC50cyIsICIuLi9saWIvd2FzbS9wcm94eS13cmFwcGVyLnRzIiwgIi4uL2xpYi93YXNtL3Nlc3Npb24taGFuZGxlci1pbmZlcmVuY2UudHMiLCAiLi4vbGliL2JhY2tlbmQtd2FzbS50cyIsICIuLi9saWIvaW5kZXgudHMiLCAiLi4vbGliL3ZlcnNpb24udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBCYWNrZW5kIH0gZnJvbSAnLi9iYWNrZW5kLmpzJztcbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb24gfSBmcm9tICcuL2luZmVyZW5jZS1zZXNzaW9uLmpzJztcblxuaW50ZXJmYWNlIEJhY2tlbmRJbmZvIHtcbiAgYmFja2VuZDogQmFja2VuZDtcbiAgcHJpb3JpdHk6IG51bWJlcjtcblxuICBpbml0UHJvbWlzZT86IFByb21pc2U8dm9pZD47XG4gIGluaXRpYWxpemVkPzogYm9vbGVhbjtcbiAgYWJvcnRlZD86IGJvb2xlYW47XG4gIGVycm9yPzogc3RyaW5nO1xufVxuXG5jb25zdCBiYWNrZW5kczogTWFwPHN0cmluZywgQmFja2VuZEluZm8+ID0gbmV3IE1hcCgpO1xuY29uc3QgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5OiBzdHJpbmdbXSA9IFtdO1xuXG4vKipcbiAqIFJlZ2lzdGVyIGEgYmFja2VuZC5cbiAqXG4gKiBAcGFyYW0gbmFtZSAtIHRoZSBuYW1lIGFzIGEga2V5IHRvIGxvb2t1cCBhcyBhbiBleGVjdXRpb24gcHJvdmlkZXIuXG4gKiBAcGFyYW0gYmFja2VuZCAtIHRoZSBiYWNrZW5kIG9iamVjdC5cbiAqIEBwYXJhbSBwcmlvcml0eSAtIGFuIGludGVnZXIgaW5kaWNhdGluZyB0aGUgcHJpb3JpdHkgb2YgdGhlIGJhY2tlbmQuIEhpZ2hlciBudW1iZXIgbWVhbnMgaGlnaGVyIHByaW9yaXR5LiBpZiBwcmlvcml0eVxuICogPCAwLCBpdCB3aWxsIGJlIGNvbnNpZGVyZWQgYXMgYSAnYmV0YScgdmVyc2lvbiBhbmQgd2lsbCBub3QgYmUgdXNlZCBhcyBhIGZhbGxiYWNrIGJhY2tlbmQgYnkgZGVmYXVsdC5cbiAqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCByZWdpc3RlckJhY2tlbmQgPSAobmFtZTogc3RyaW5nLCBiYWNrZW5kOiBCYWNrZW5kLCBwcmlvcml0eTogbnVtYmVyKTogdm9pZCA9PiB7XG4gIGlmIChiYWNrZW5kICYmIHR5cGVvZiBiYWNrZW5kLmluaXQgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGJhY2tlbmQuY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjb25zdCBjdXJyZW50QmFja2VuZCA9IGJhY2tlbmRzLmdldChuYW1lKTtcbiAgICBpZiAoY3VycmVudEJhY2tlbmQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgYmFja2VuZHMuc2V0KG5hbWUsIHsgYmFja2VuZCwgcHJpb3JpdHkgfSk7XG4gICAgfSBlbHNlIGlmIChjdXJyZW50QmFja2VuZC5wcmlvcml0eSA+IHByaW9yaXR5KSB7XG4gICAgICAvLyBzYW1lIG5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHdpdGggYSBoaWdoZXIgcHJpb3JpdHkuIHNraXAgcmVnaXN0ZXJhdGlvbi5cbiAgICAgIHJldHVybjtcbiAgICB9IGVsc2UgaWYgKGN1cnJlbnRCYWNrZW5kLnByaW9yaXR5ID09PSBwcmlvcml0eSkge1xuICAgICAgaWYgKGN1cnJlbnRCYWNrZW5kLmJhY2tlbmQgIT09IGJhY2tlbmQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgcmVnaXN0ZXIgYmFja2VuZCBcIiR7bmFtZX1cIiB1c2luZyBwcmlvcml0eSAke3ByaW9yaXR5fWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwcmlvcml0eSA+PSAwKSB7XG4gICAgICBjb25zdCBpID0gYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5LmluZGV4T2YobmFtZSk7XG4gICAgICBpZiAoaSAhPT0gLTEpIHtcbiAgICAgICAgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5LnNwbGljZShpLCAxKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGJhY2tlbmRzLmdldChiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHlbaV0pIS5wcmlvcml0eSA8PSBwcmlvcml0eSkge1xuICAgICAgICAgIGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eS5zcGxpY2UoaSwgMCwgbmFtZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHkucHVzaChuYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVFcnJvcignbm90IGEgdmFsaWQgYmFja2VuZCcpO1xufTtcblxuLyoqXG4gKiBUcnkgdG8gcmVzb2x2ZSBhbmQgaW5pdGlhbGl6ZSBhIGJhY2tlbmQuXG4gKlxuICogQHBhcmFtIGJhY2tlbmROYW1lIC0gdGhlIG5hbWUgb2YgdGhlIGJhY2tlbmQuXG4gKiBAcmV0dXJucyB0aGUgYmFja2VuZCBpbnN0YW5jZSBpZiByZXNvbHZlZCBhbmQgaW5pdGlhbGl6ZWQgc3VjY2Vzc2Z1bGx5LCBvciBhbiBlcnJvciBtZXNzYWdlIGlmIGZhaWxlZC5cbiAqL1xuY29uc3QgdHJ5UmVzb2x2ZUFuZEluaXRpYWxpemVCYWNrZW5kID0gYXN5bmMgKGJhY2tlbmROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEJhY2tlbmQgfCBzdHJpbmc+ID0+IHtcbiAgY29uc3QgYmFja2VuZEluZm8gPSBiYWNrZW5kcy5nZXQoYmFja2VuZE5hbWUpO1xuICBpZiAoIWJhY2tlbmRJbmZvKSB7XG4gICAgcmV0dXJuICdiYWNrZW5kIG5vdCBmb3VuZC4nO1xuICB9XG5cbiAgaWYgKGJhY2tlbmRJbmZvLmluaXRpYWxpemVkKSB7XG4gICAgcmV0dXJuIGJhY2tlbmRJbmZvLmJhY2tlbmQ7XG4gIH0gZWxzZSBpZiAoYmFja2VuZEluZm8uYWJvcnRlZCkge1xuICAgIHJldHVybiBiYWNrZW5kSW5mby5lcnJvciE7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgaXNJbml0aWFsaXppbmcgPSAhIWJhY2tlbmRJbmZvLmluaXRQcm9taXNlO1xuICAgIHRyeSB7XG4gICAgICBpZiAoIWlzSW5pdGlhbGl6aW5nKSB7XG4gICAgICAgIGJhY2tlbmRJbmZvLmluaXRQcm9taXNlID0gYmFja2VuZEluZm8uYmFja2VuZC5pbml0KGJhY2tlbmROYW1lKTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IGJhY2tlbmRJbmZvLmluaXRQcm9taXNlO1xuICAgICAgYmFja2VuZEluZm8uaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGJhY2tlbmRJbmZvLmJhY2tlbmQ7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCFpc0luaXRpYWxpemluZykge1xuICAgICAgICBiYWNrZW5kSW5mby5lcnJvciA9IGAke2V9YDtcbiAgICAgICAgYmFja2VuZEluZm8uYWJvcnRlZCA9IHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFja2VuZEluZm8uZXJyb3IhO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBkZWxldGUgYmFja2VuZEluZm8uaW5pdFByb21pc2U7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIFJlc29sdmUgZXhlY3V0aW9uIHByb3ZpZGVycyBmcm9tIHRoZSBzcGVjaWZpYyBzZXNzaW9uIG9wdGlvbnMuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSB0aGUgc2Vzc2lvbiBvcHRpb25zIG9iamVjdC5cbiAqIEByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgdHVwbGUgb2YgYW4gaW5pdGlhbGl6ZWQgYmFja2VuZCBpbnN0YW5jZSBhbmQgYSBzZXNzaW9uIG9wdGlvbnMgb2JqZWN0IHdpdGhcbiAqIGZpbHRlcmVkIEVQIGxpc3QuXG4gKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgY29uc3QgcmVzb2x2ZUJhY2tlbmRBbmRFeGVjdXRpb25Qcm92aWRlcnMgPSBhc3luYyAoXG4gIG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMsXG4pOiBQcm9taXNlPFtiYWNrZW5kOiBCYWNrZW5kLCBvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zXT4gPT4ge1xuICAvLyBleHRyYWN0IGJhY2tlbmQgaGludHMgZnJvbSBzZXNzaW9uIG9wdGlvbnNcbiAgY29uc3QgZXBzID0gb3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMgfHwgW107XG4gIGNvbnN0IGJhY2tlbmRIaW50cyA9IGVwcy5tYXAoKGkpID0+ICh0eXBlb2YgaSA9PT0gJ3N0cmluZycgPyBpIDogaS5uYW1lKSk7XG4gIGNvbnN0IGJhY2tlbmROYW1lcyA9IGJhY2tlbmRIaW50cy5sZW5ndGggPT09IDAgPyBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHkgOiBiYWNrZW5kSGludHM7XG5cbiAgLy8gdHJ5IHRvIHJlc29sdmUgYW5kIGluaXRpYWxpemUgYWxsIHJlcXVlc3RlZCBiYWNrZW5kc1xuICBsZXQgYmFja2VuZDogQmFja2VuZCB8IHVuZGVmaW5lZDtcbiAgY29uc3QgZXJyb3JzID0gW107XG4gIGNvbnN0IGF2YWlsYWJsZUJhY2tlbmROYW1lcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBmb3IgKGNvbnN0IGJhY2tlbmROYW1lIG9mIGJhY2tlbmROYW1lcykge1xuICAgIGNvbnN0IHJlc29sdmVSZXN1bHQgPSBhd2FpdCB0cnlSZXNvbHZlQW5kSW5pdGlhbGl6ZUJhY2tlbmQoYmFja2VuZE5hbWUpO1xuICAgIGlmICh0eXBlb2YgcmVzb2x2ZVJlc3VsdCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVycm9ycy5wdXNoKHsgbmFtZTogYmFja2VuZE5hbWUsIGVycjogcmVzb2x2ZVJlc3VsdCB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCFiYWNrZW5kKSB7XG4gICAgICAgIGJhY2tlbmQgPSByZXNvbHZlUmVzdWx0O1xuICAgICAgfVxuICAgICAgaWYgKGJhY2tlbmQgPT09IHJlc29sdmVSZXN1bHQpIHtcbiAgICAgICAgYXZhaWxhYmxlQmFja2VuZE5hbWVzLmFkZChiYWNrZW5kTmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgbm8gYmFja2VuZCBpcyBhdmFpbGFibGUsIHRocm93IGVycm9yLlxuICBpZiAoIWJhY2tlbmQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYG5vIGF2YWlsYWJsZSBiYWNrZW5kIGZvdW5kLiBFUlI6ICR7ZXJyb3JzLm1hcCgoZSkgPT4gYFske2UubmFtZX1dICR7ZS5lcnJ9YCkuam9pbignLCAnKX1gKTtcbiAgfVxuXG4gIC8vIGZvciBlYWNoIGV4cGxpY2l0bHkgcmVxdWVzdGVkIGJhY2tlbmQsIGlmIGl0J3Mgbm90IGF2YWlsYWJsZSwgb3V0cHV0IHdhcm5pbmcgbWVzc2FnZS5cbiAgZm9yIChjb25zdCB7IG5hbWUsIGVyciB9IG9mIGVycm9ycykge1xuICAgIGlmIChiYWNrZW5kSGludHMuaW5jbHVkZXMobmFtZSkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGByZW1vdmluZyByZXF1ZXN0ZWQgZXhlY3V0aW9uIHByb3ZpZGVyIFwiJHtuYW1lfVwiIGZyb20gc2Vzc2lvbiBvcHRpb25zIGJlY2F1c2UgaXQgaXMgbm90IGF2YWlsYWJsZTogJHtlcnJ9YCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgZmlsdGVyZWRFcHMgPSBlcHMuZmlsdGVyKChpKSA9PiBhdmFpbGFibGVCYWNrZW5kTmFtZXMuaGFzKHR5cGVvZiBpID09PSAnc3RyaW5nJyA/IGkgOiBpLm5hbWUpKTtcblxuICByZXR1cm4gW1xuICAgIGJhY2tlbmQsXG4gICAgbmV3IFByb3h5KG9wdGlvbnMsIHtcbiAgICAgIGdldDogKHRhcmdldCwgcHJvcCkgPT4ge1xuICAgICAgICBpZiAocHJvcCA9PT0gJ2V4ZWN1dGlvblByb3ZpZGVycycpIHtcbiAgICAgICAgICByZXR1cm4gZmlsdGVyZWRFcHM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0KHRhcmdldCwgcHJvcCk7XG4gICAgICB9LFxuICAgIH0pLFxuICBdO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgSW5mZXJlbmNlU2Vzc2lvbiB9IGZyb20gJy4vaW5mZXJlbmNlLXNlc3Npb24uanMnO1xuaW1wb3J0IHsgT25ueFZhbHVlIH0gZnJvbSAnLi9vbm54LXZhbHVlLmpzJztcblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBTZXNzaW9uSGFuZGxlciB7XG4gIHR5cGUgRmVlZHNUeXBlID0geyBbbmFtZTogc3RyaW5nXTogT25ueFZhbHVlIH07XG4gIHR5cGUgRmV0Y2hlc1R5cGUgPSB7IFtuYW1lOiBzdHJpbmddOiBPbm54VmFsdWUgfCBudWxsIH07XG4gIHR5cGUgUmV0dXJuVHlwZSA9IHsgW25hbWU6IHN0cmluZ106IE9ubnhWYWx1ZSB9O1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgc2hhcmVkIFNlc3Npb25IYW5kbGVyIGZ1bmN0aW9uYWxpdHlcbiAqXG4gKiBAaWdub3JlXG4gKi9cbmludGVyZmFjZSBTZXNzaW9uSGFuZGxlciB7XG4gIGRpc3Bvc2UoKTogUHJvbWlzZTx2b2lkPjtcblxuICByZWFkb25seSBpbnB1dE5hbWVzOiByZWFkb25seSBzdHJpbmdbXTtcbiAgcmVhZG9ubHkgb3V0cHV0TmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuXG4gIHJlYWRvbmx5IGlucHV0TWV0YWRhdGE6IHJlYWRvbmx5IEluZmVyZW5jZVNlc3Npb24uVmFsdWVNZXRhZGF0YVtdO1xuICByZWFkb25seSBvdXRwdXRNZXRhZGF0YTogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbi5WYWx1ZU1ldGFkYXRhW107XG59XG5cbi8qKlxuICogUmVwcmVzZW50IGEgaGFuZGxlciBpbnN0YW5jZSBvZiBhbiBpbmZlcmVuY2Ugc2Vzc2lvbi5cbiAqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIgZXh0ZW5kcyBTZXNzaW9uSGFuZGxlciB7XG4gIHN0YXJ0UHJvZmlsaW5nKCk6IHZvaWQ7XG4gIGVuZFByb2ZpbGluZygpOiB2b2lkO1xuXG4gIHJ1bihcbiAgICBmZWVkczogU2Vzc2lvbkhhbmRsZXIuRmVlZHNUeXBlLFxuICAgIGZldGNoZXM6IFNlc3Npb25IYW5kbGVyLkZldGNoZXNUeXBlLFxuICAgIG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxTZXNzaW9uSGFuZGxlci5SZXR1cm5UeXBlPjtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnQgYSBiYWNrZW5kIHRoYXQgcHJvdmlkZXMgaW1wbGVtZW50YXRpb24gb2YgbW9kZWwgaW5mZXJlbmNpbmcuXG4gKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhY2tlbmQge1xuICAvKipcbiAgICogSW5pdGlhbGl6ZSB0aGUgYmFja2VuZCBhc3luY2hyb25vdXNseS4gU2hvdWxkIHRocm93IHdoZW4gZmFpbGVkLlxuICAgKi9cbiAgaW5pdChiYWNrZW5kTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcblxuICBjcmVhdGVJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcihcbiAgICB1cmlPckJ1ZmZlcjogc3RyaW5nIHwgVWludDhBcnJheSxcbiAgICBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcj47XG59XG5cbmV4cG9ydCB7IHJlZ2lzdGVyQmFja2VuZCB9IGZyb20gJy4vYmFja2VuZC1pbXBsLmpzJztcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLy8gVGhpcyBmaWxlIGlzIGdlbmVyYXRlZCBieSAvanMvc2NyaXB0cy91cGRhdGUtdmVyc2lvbi50c1xuLy8gRG8gbm90IG1vZGlmeSBmaWxlIGNvbnRlbnQgbWFudWFsbHkuXG5cbmV4cG9ydCBjb25zdCB2ZXJzaW9uID0gJzEuMjMuMCc7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IEVudiB9IGZyb20gJy4vZW52LmpzJztcbmltcG9ydCB7IHZlcnNpb24gfSBmcm9tICcuL3ZlcnNpb24uanMnO1xuXG50eXBlIExvZ0xldmVsVHlwZSA9IEVudlsnbG9nTGV2ZWwnXTtcblxubGV0IGxvZ0xldmVsVmFsdWU6IFJlcXVpcmVkPExvZ0xldmVsVHlwZT4gPSAnd2FybmluZyc7XG5cbmV4cG9ydCBjb25zdCBlbnY6IEVudiA9IHtcbiAgd2FzbToge30gYXMgRW52LldlYkFzc2VtYmx5RmxhZ3MsXG4gIHdlYmdsOiB7fSBhcyBFbnYuV2ViR0xGbGFncyxcbiAgd2ViZ3B1OiB7fSBhcyBFbnYuV2ViR3B1RmxhZ3MsXG4gIHZlcnNpb25zOiB7IGNvbW1vbjogdmVyc2lvbiB9LFxuXG4gIHNldCBsb2dMZXZlbCh2YWx1ZTogTG9nTGV2ZWxUeXBlKSB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycgfHwgWyd2ZXJib3NlJywgJ2luZm8nLCAnd2FybmluZycsICdlcnJvcicsICdmYXRhbCddLmluZGV4T2YodmFsdWUpID09PSAtMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBsb2dnaW5nIGxldmVsOiAke3ZhbHVlfWApO1xuICAgIH1cbiAgICBsb2dMZXZlbFZhbHVlID0gdmFsdWU7XG4gIH0sXG4gIGdldCBsb2dMZXZlbCgpOiBSZXF1aXJlZDxMb2dMZXZlbFR5cGU+IHtcbiAgICByZXR1cm4gbG9nTGV2ZWxWYWx1ZTtcbiAgfSxcbn07XG5cbi8vIHNldCBwcm9wZXJ0eSAnbG9nTGV2ZWwnIHNvIHRoYXQgdGhleSBjYW4gYmUgY29ycmVjdGx5IHRyYW5zZmVycmVkIHRvIHdvcmtlciBieSBgcG9zdE1lc3NhZ2UoKWAuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZW52LCAnbG9nTGV2ZWwnLCB7IGVudW1lcmFibGU6IHRydWUgfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGVudiBhcyBlbnZJbXBsIH0gZnJvbSAnLi9lbnYtaW1wbC5qcyc7XG5pbXBvcnQgeyBUcnlHZXRHbG9iYWxUeXBlIH0gZnJvbSAnLi90eXBlLWhlbHBlci5qcyc7XG5cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBFbnYge1xuICBleHBvcnQgdHlwZSBXYXNtUGF0aFByZWZpeCA9IHN0cmluZztcbiAgZXhwb3J0IGludGVyZmFjZSBXYXNtRmlsZVBhdGhzIHtcbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IHRoZSBvdmVycmlkZSBwYXRoIGZvciB0aGUgbWFpbiAud2FzbSBmaWxlLlxuICAgICAqXG4gICAgICogVGhpcyBwYXRoIHNob3VsZCBiZSBhbiBhYnNvbHV0ZSBwYXRoLlxuICAgICAqXG4gICAgICogSWYgbm90IG1vZGlmaWVkLCB0aGUgZmlsZW5hbWUgb2YgdGhlIC53YXNtIGZpbGUgaXM6XG4gICAgICogLSBgb3J0LXdhc20tc2ltZC10aHJlYWRlZC53YXNtYCBmb3IgZGVmYXVsdCBidWlsZFxuICAgICAqIC0gYG9ydC13YXNtLXNpbWQtdGhyZWFkZWQuanNlcC53YXNtYCBmb3IgSlNFUCBidWlsZCAod2l0aCBXZWJHUFUgYW5kIFdlYk5OKVxuICAgICAqL1xuICAgIHdhc20/OiBVUkwgfCBzdHJpbmc7XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSB0aGUgb3ZlcnJpZGUgcGF0aCBmb3IgdGhlIG1haW4gLm1qcyBmaWxlLlxuICAgICAqXG4gICAgICogVGhpcyBwYXRoIHNob3VsZCBiZSBhbiBhYnNvbHV0ZSBwYXRoLlxuICAgICAqXG4gICAgICogSWYgbm90IG1vZGlmaWVkLCB0aGUgZmlsZW5hbWUgb2YgdGhlIC5tanMgZmlsZSBpczpcbiAgICAgKiAtIGBvcnQtd2FzbS1zaW1kLXRocmVhZGVkLm1qc2AgZm9yIGRlZmF1bHQgYnVpbGRcbiAgICAgKiAtIGBvcnQtd2FzbS1zaW1kLXRocmVhZGVkLmpzZXAubWpzYCBmb3IgSlNFUCBidWlsZCAod2l0aCBXZWJHUFUgYW5kIFdlYk5OKVxuICAgICAqL1xuICAgIG1qcz86IFVSTCB8IHN0cmluZztcbiAgfVxuICBleHBvcnQgdHlwZSBXYXNtUHJlZml4T3JGaWxlUGF0aHMgPSBXYXNtUGF0aFByZWZpeCB8IFdhc21GaWxlUGF0aHM7XG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViQXNzZW1ibHlGbGFncyB7XG4gICAgLyoqXG4gICAgICogc2V0IG9yIGdldCBudW1iZXIgb2YgdGhyZWFkKHMpLiBJZiBvbWl0dGVkIG9yIHNldCB0byAwLCBudW1iZXIgb2YgdGhyZWFkKHMpIHdpbGwgYmUgZGV0ZXJtaW5lZCBieSBzeXN0ZW0uIElmIHNldFxuICAgICAqIHRvIDEsIG5vIHdvcmtlciB0aHJlYWQgd2lsbCBiZSBzcGF3bmVkLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IHdoZW4gV2ViQXNzZW1ibHkgbXVsdGl0aHJlYWQgZmVhdHVyZSBpcyBhdmFpbGFibGUgaW4gY3VycmVudCBjb250ZXh0LlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgMGBcbiAgICAgKi9cbiAgICBudW1UaHJlYWRzPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogc2V0IGEgdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRvIGVuYWJsZSBTSU1ELlxuICAgICAqXG4gICAgICogT05OWCBSdW50aW1lIHdpbGwgcGVyZm9ybSBmZWF0dXJlIGRldGVjdGlvbiBiYXNlZCBvbiB0aGUgdmFsdWUgb2YgdGhpcyBwcm9wZXJ0eS4gU3BlY2lmaWNhbGx5LCB3aGVuIHRoZSB2YWx1ZSBpc1xuICAgICAqIHNldCB0bzpcbiAgICAgKiAtIGB1bmRlZmluZWRgLCBgdHJ1ZWAgb3IgYFwiZml4ZWRcImA6IHdpbGwgY2hlY2sgYXZhaWxhYmlsaXR5IG9mIEZpeGVkLXdpZHRoIFNJTUQuXG4gICAgICogLSBgXCJyZWxheGVkXCJgOiB3aWxsIGNoZWNrIGF2YWlsYWJpbGl0eSBvZiBSZWxheGVkIFNJTUQuXG4gICAgICogLSBgZmFsc2VgOiB3aWxsIG5vdCBwZXJmb3JtIFNJTUQgZmVhdHVyZSBjaGVja2luZy5cbiAgICAgKlxuICAgICAqIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBkb2VzIG5vdCBtYWtlIE9OTlggUnVudGltZSB0byBzd2l0Y2ggdG8gdGhlIGNvcnJlc3BvbmRpbmcgcnVudGltZSBhdXRvbWF0aWNhbGx5LiBVc2VyIG5lZWRcbiAgICAgKiB0byBzZXQgYHdhc21QYXRoc2Agb3IgYHdhc21CaW5hcnlgIHByb3BlcnR5IHRvIGxvYWQgdGhlIGNvcnJlc3BvbmRpbmcgcnVudGltZS5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSB3aGVuIFdlYkFzc2VtYmx5IFNJTUQgZmVhdHVyZSBpcyBhdmFpbGFibGUgaW4gY3VycmVudCBjb250ZXh0LlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgdHJ1ZWBcbiAgICAgKi9cbiAgICBzaW1kPzogYm9vbGVhbiB8ICdmaXhlZCcgfCAncmVsYXhlZCc7XG5cbiAgICAvKipcbiAgICAgKiBzZXQgb3IgZ2V0IGEgYm9vbGVhbiB2YWx1ZSBpbmRpY2F0aW5nIHdoZXRoZXIgdG8gZW5hYmxlIHRyYWNlLlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgZmFsc2VgXG4gICAgICpcbiAgICAgKiBAZGVwcmVjYXRlZCBVc2UgYGVudi50cmFjZWAgaW5zdGVhZC4gSWYgYGVudi50cmFjZWAgaXMgc2V0LCB0aGlzIHByb3BlcnR5IHdpbGwgYmUgaWdub3JlZC5cbiAgICAgKi9cbiAgICB0cmFjZT86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IGEgbnVtYmVyIHNwZWNpZnlpbmcgdGhlIHRpbWVvdXQgZm9yIGluaXRpYWxpemF0aW9uIG9mIFdlYkFzc2VtYmx5IGJhY2tlbmQsIGluIG1pbGxpc2Vjb25kcy4gQSB6ZXJvXG4gICAgICogdmFsdWUgaW5kaWNhdGVzIG5vIHRpbWVvdXQgaXMgc2V0LlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgMGBcbiAgICAgKi9cbiAgICBpbml0VGltZW91dD86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFNldCBhIGN1c3RvbSBVUkwgcHJlZml4IHRvIHRoZSAud2FzbS8ubWpzIGZpbGVzLCBvciBhbiBvYmplY3Qgb2Ygb3ZlcnJpZGVzIGZvciBib3RoIC53YXNtLy5tanMgZmlsZS4gVGhlIG92ZXJyaWRlXG4gICAgICogcGF0aCBzaG91bGQgYmUgYW4gYWJzb2x1dGUgcGF0aC5cbiAgICAgKi9cbiAgICB3YXNtUGF0aHM/OiBXYXNtUHJlZml4T3JGaWxlUGF0aHM7XG5cbiAgICAvKipcbiAgICAgKiBTZXQgYSBjdXN0b20gYnVmZmVyIHdoaWNoIGNvbnRhaW5zIHRoZSBXZWJBc3NlbWJseSBiaW5hcnkuIElmIHRoaXMgcHJvcGVydHkgaXMgc2V0LCB0aGUgYHdhc21QYXRoc2AgcHJvcGVydHkgd2lsbFxuICAgICAqIGJlIGlnbm9yZWQuXG4gICAgICovXG4gICAgd2FzbUJpbmFyeT86IEFycmF5QnVmZmVyTGlrZSB8IFVpbnQ4QXJyYXk7XG5cbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IGEgYm9vbGVhbiB2YWx1ZSBpbmRpY2F0aW5nIHdoZXRoZXIgdG8gcHJveHkgdGhlIGV4ZWN1dGlvbiBvZiBtYWluIHRocmVhZCB0byBhIHdvcmtlciB0aHJlYWQuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGBmYWxzZWBcbiAgICAgKi9cbiAgICBwcm94eT86IGJvb2xlYW47XG4gIH1cblxuICBleHBvcnQgaW50ZXJmYWNlIFdlYkdMRmxhZ3Mge1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIFdlYkdMIENvbnRleHQgSUQgKHdlYmdsIG9yIHdlYmdsMikuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGAnd2ViZ2wyJ2BcbiAgICAgKi9cbiAgICBjb250ZXh0SWQ/OiAnd2ViZ2wnIHwgJ3dlYmdsMic7XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBXZWJHTCByZW5kZXJpbmcgY29udGV4dC5cbiAgICAgKi9cbiAgICByZWFkb25seSBjb250ZXh0OiBXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgbWF4aW11bSBiYXRjaCBzaXplIGZvciBtYXRtdWwuIDAgbWVhbnMgdG8gZGlzYWJsZSBiYXRjaGluZy5cbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkXG4gICAgICovXG4gICAgbWF0bXVsTWF4QmF0Y2hTaXplPzogbnVtYmVyO1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIHRleHR1cmUgY2FjaGUgbW9kZS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYCdmdWxsJ2BcbiAgICAgKi9cbiAgICB0ZXh0dXJlQ2FjaGVNb2RlPzogJ2luaXRpYWxpemVyT25seScgfCAnZnVsbCc7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgcGFja2VkIHRleHR1cmUgbW9kZVxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgZmFsc2VgXG4gICAgICovXG4gICAgcGFjaz86IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB3aGV0aGVyIGVuYWJsZSBhc3luYyBkb3dubG9hZC5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYGZhbHNlYFxuICAgICAqL1xuICAgIGFzeW5jPzogYm9vbGVhbjtcbiAgfVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViR3B1UHJvZmlsaW5nRGF0YVYxVGVuc29yTWV0YWRhdGEge1xuICAgIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICAgIGRhdGFUeXBlOiBzdHJpbmc7XG4gIH1cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJHcHVQcm9maWxpbmdEYXRhVjEge1xuICAgIHZlcnNpb246IDE7XG4gICAgaW5wdXRzTWV0YWRhdGE6IHJlYWRvbmx5IFdlYkdwdVByb2ZpbGluZ0RhdGFWMVRlbnNvck1ldGFkYXRhW107XG4gICAgb3V0cHV0c01ldGFkYXRhOiByZWFkb25seSBXZWJHcHVQcm9maWxpbmdEYXRhVjFUZW5zb3JNZXRhZGF0YVtdO1xuICAgIGtlcm5lbElkOiBudW1iZXI7XG4gICAga2VybmVsVHlwZTogc3RyaW5nO1xuICAgIGtlcm5lbE5hbWU6IHN0cmluZztcbiAgICBwcm9ncmFtTmFtZTogc3RyaW5nO1xuICAgIHN0YXJ0VGltZTogbnVtYmVyO1xuICAgIGVuZFRpbWU6IG51bWJlcjtcbiAgfVxuXG4gIGV4cG9ydCB0eXBlIFdlYkdwdVByb2ZpbGluZ0RhdGEgPSBXZWJHcHVQcm9maWxpbmdEYXRhVjE7XG5cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJHcHVGbGFncyB7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgcHJvZmlsaW5nIG1vZGUuXG4gICAgICpcbiAgICAgKiBAZGVwcmVjYXRlZCBVc2UgYGVudi53ZWJncHUucHJvZmlsaW5nLm1vZGVgIGluc3RlYWQuIElmIGBlbnYud2ViZ3B1LnByb2ZpbGluZy5tb2RlYCBpcyBzZXQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZVxuICAgICAqIGlnbm9yZWQuXG4gICAgICovXG4gICAgcHJvZmlsaW5nTW9kZT86ICdvZmYnIHwgJ2RlZmF1bHQnO1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIHByb2ZpbGluZyBjb25maWd1cmF0aW9uLlxuICAgICAqL1xuICAgIHByb2ZpbGluZzoge1xuICAgICAgLyoqXG4gICAgICAgKiBTZXQgb3IgZ2V0IHRoZSBwcm9maWxpbmcgbW9kZS5cbiAgICAgICAqXG4gICAgICAgKiBAZGVmYXVsdFZhbHVlIGAnb2ZmJ2BcbiAgICAgICAqL1xuICAgICAgbW9kZT86ICdvZmYnIHwgJ2RlZmF1bHQnO1xuXG4gICAgICAvKipcbiAgICAgICAqIFNldCBvciBnZXQgYSBjYWxsYmFjayBmdW5jdGlvbiB3aGVuIGEgcHJvZmlsaW5nIGRhdGEgaXMgcmVjZWl2ZWQuIElmIG5vdCBzZXQsIHRoZSBwcm9maWxpbmcgZGF0YSB3aWxsIGJlXG4gICAgICAgKiBwcmludGVkIHRvIGNvbnNvbGUuXG4gICAgICAgKi9cbiAgICAgIG9uZGF0YT86IChkYXRhOiBXZWJHcHVQcm9maWxpbmdEYXRhKSA9PiB2b2lkO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgcG93ZXIgcHJlZmVyZW5jZS5cbiAgICAgKlxuICAgICAqIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBvbmx5IGhhcyBlZmZlY3QgYmVmb3JlIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhlIHZhbHVlIHdpbGwgYmVcbiAgICAgKiB1c2VkIGFzIG9wdGlvbnMgZm9yIGBuYXZpZ2F0b3IuZ3B1LnJlcXVlc3RBZGFwdGVyKClgLlxuICAgICAqXG4gICAgICogU2VlIHtAbGluayBodHRwczovL2dwdXdlYi5naXRodWIuaW8vZ3B1d2ViLyNkaWN0ZGVmLWdwdXJlcXVlc3RhZGFwdGVyb3B0aW9uc30gZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYHVuZGVmaW5lZGBcbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkIENyZWF0ZSB5b3VyIG93biBHUFVBZGFwdGVyLCB1c2UgaXQgdG8gY3JlYXRlIGEgR1BVRGV2aWNlIGluc3RhbmNlIGFuZCBzZXQge0BsaW5rIGRldmljZX0gcHJvcGVydHkgaWZcbiAgICAgKiB5b3Ugd2FudCB0byB1c2UgYSBzcGVjaWZpYyBwb3dlciBwcmVmZXJlbmNlLlxuICAgICAqL1xuICAgIHBvd2VyUHJlZmVyZW5jZT86ICdsb3ctcG93ZXInIHwgJ2hpZ2gtcGVyZm9ybWFuY2UnO1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIGZvcmNlIGZhbGxiYWNrIGFkYXB0ZXIgZmxhZy5cbiAgICAgKlxuICAgICAqIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBvbmx5IGhhcyBlZmZlY3QgYmVmb3JlIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhlIHZhbHVlIHdpbGwgYmVcbiAgICAgKiB1c2VkIGFzIG9wdGlvbnMgZm9yIGBuYXZpZ2F0b3IuZ3B1LnJlcXVlc3RBZGFwdGVyKClgLlxuICAgICAqXG4gICAgICogU2VlIHtAbGluayBodHRwczovL2dwdXdlYi5naXRodWIuaW8vZ3B1d2ViLyNkaWN0ZGVmLWdwdXJlcXVlc3RhZGFwdGVyb3B0aW9uc30gZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYHVuZGVmaW5lZGBcbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkIENyZWF0ZSB5b3VyIG93biBHUFVBZGFwdGVyLCB1c2UgaXQgdG8gY3JlYXRlIGEgR1BVRGV2aWNlIGluc3RhbmNlIGFuZCBzZXQge0BsaW5rIGRldmljZX0gcHJvcGVydHkgaWZcbiAgICAgKiB5b3Ugd2FudCB0byB1c2UgYSBzcGVjaWZpYyBmYWxsYmFjayBvcHRpb24uXG4gICAgICovXG4gICAgZm9yY2VGYWxsYmFja0FkYXB0ZXI/OiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgdGhlIGFkYXB0ZXIgZm9yIFdlYkdQVS5cbiAgICAgKlxuICAgICAqIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBvbmx5IGhhcyBlZmZlY3QgYmVmb3JlIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhlIHZhbHVlIHdpbGwgYmVcbiAgICAgKiB1c2VkIGFzIHRoZSBHUFUgYWRhcHRlciBmb3IgdGhlIHVuZGVybHlpbmcgV2ViR1BVIGJhY2tlbmQgdG8gY3JlYXRlIEdQVSBkZXZpY2UuXG4gICAgICpcbiAgICAgKiBJZiB0aGlzIHByb3BlcnR5IGlzIG5vdCBzZXQsIGl0IHdpbGwgYmUgYXZhaWxhYmxlIHRvIGdldCBhZnRlciB0aGUgZmlyc3QgV2ViR1BVIGluZmVyZW5jZSBzZXNzaW9uIGlzIGNyZWF0ZWQuIFRoZVxuICAgICAqIHZhbHVlIHdpbGwgYmUgdGhlIEdQVSBhZGFwdGVyIHRoYXQgY3JlYXRlZCBieSB0aGUgdW5kZXJseWluZyBXZWJHUFUgYmFja2VuZC5cbiAgICAgKlxuICAgICAqIFdoZW4gdXNlIHdpdGggVHlwZVNjcmlwdCwgdGhlIHR5cGUgb2YgdGhpcyBwcm9wZXJ0eSBpcyBgR1BVQWRhcHRlcmAgZGVmaW5lZCBpbiBcIkB3ZWJncHUvdHlwZXNcIi5cbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkIEl0IGlzIG5vIGxvbmdlciByZWNvbW1lbmRlZCB0byB1c2UgdGhpcyBwcm9wZXJ0eS4gVGhlIGxhdGVzdCBXZWJHUFUgc3BlYyBhZGRzIGBHUFVEZXZpY2UuYWRhcHRlckluZm9gXG4gICAgICogKGh0dHBzOi8vd3d3LnczLm9yZy9UUi93ZWJncHUvI2RvbS1ncHVkZXZpY2UtYWRhcHRlcmluZm8pLCB3aGljaCBhbGxvd3MgdG8gZ2V0IHRoZSBhZGFwdGVyIGluZm9ybWF0aW9uIGZyb20gdGhlXG4gICAgICogZGV2aWNlLiBXaGVuIGl0J3MgYXZhaWxhYmxlLCB0aGVyZSBpcyBubyBuZWVkIHRvIHNldC9nZXQgdGhlIHtAbGluayBhZGFwdGVyfSBwcm9wZXJ0eS5cbiAgICAgKi9cbiAgICBhZGFwdGVyOiBUcnlHZXRHbG9iYWxUeXBlPCdHUFVBZGFwdGVyJz47XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgR1BVIGRldmljZSBmb3IgV2ViR1BVLlxuICAgICAqXG4gICAgICogVGhlcmUgYXJlIDMgdmFsaWQgc2NlbmFyaW9zIG9mIGFjY2Vzc2luZyB0aGlzIHByb3BlcnR5OlxuICAgICAqIC0gU2V0IGEgdmFsdWUgYmVmb3JlIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhlIHZhbHVlIHdpbGwgYmUgdXNlZCBieSB0aGUgV2ViR1BVIGJhY2tlbmRcbiAgICAgKiB0byBwZXJmb3JtIGNhbGN1bGF0aW9ucy4gSWYgdGhlIHZhbHVlIGlzIG5vdCBhIGBHUFVEZXZpY2VgIG9iamVjdCwgYW4gZXJyb3Igd2lsbCBiZSB0aHJvd24uXG4gICAgICogLSBHZXQgdGhlIHZhbHVlIGJlZm9yZSB0aGUgZmlyc3QgV2ViR1BVIGluZmVyZW5jZSBzZXNzaW9uIGlzIGNyZWF0ZWQuIFRoaXMgd2lsbCB0cnkgdG8gY3JlYXRlIGEgbmV3IEdQVURldmljZVxuICAgICAqIGluc3RhbmNlLiBSZXR1cm5zIGEgYFByb21pc2VgIHRoYXQgcmVzb2x2ZXMgdG8gYSBgR1BVRGV2aWNlYCBvYmplY3QuXG4gICAgICogLSBHZXQgdGhlIHZhbHVlIGFmdGVyIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gUmV0dXJucyBhIHJlc29sdmVkIGBQcm9taXNlYCB0byB0aGVcbiAgICAgKiBgR1BVRGV2aWNlYCBvYmplY3QgdXNlZCBieSB0aGUgV2ViR1BVIGJhY2tlbmQuXG4gICAgICovXG4gICAgZ2V0IGRldmljZSgpOiBQcm9taXNlPFRyeUdldEdsb2JhbFR5cGU8J0dQVURldmljZSc+PjtcbiAgICBzZXQgZGV2aWNlKHZhbHVlOiBUcnlHZXRHbG9iYWxUeXBlPCdHUFVEZXZpY2UnPik7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB3aGV0aGVyIHZhbGlkYXRlIGlucHV0IGNvbnRlbnQuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGBmYWxzZWBcbiAgICAgKi9cbiAgICB2YWxpZGF0ZUlucHV0Q29udGVudD86IGJvb2xlYW47XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBFbnYge1xuICAvKipcbiAgICogc2V0IHRoZSBzZXZlcml0eSBsZXZlbCBmb3IgbG9nZ2luZy5cbiAgICpcbiAgICogQGRlZmF1bHRWYWx1ZSBgJ3dhcm5pbmcnYFxuICAgKi9cbiAgbG9nTGV2ZWw/OiAndmVyYm9zZScgfCAnaW5mbycgfCAnd2FybmluZycgfCAnZXJyb3InIHwgJ2ZhdGFsJztcblxuICAvKipcbiAgICogSW5kaWNhdGUgd2hldGhlciBydW4gaW4gZGVidWcgbW9kZS5cbiAgICpcbiAgICogQGRlZmF1bHRWYWx1ZSBgZmFsc2VgXG4gICAqL1xuICBkZWJ1Zz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIHNldCBvciBnZXQgYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgd2hldGhlciB0byBlbmFibGUgdHJhY2UuXG4gICAqXG4gICAqIEBkZWZhdWx0VmFsdWUgYGZhbHNlYFxuICAgKi9cbiAgdHJhY2U/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBHZXQgdmVyc2lvbiBvZiB0aGUgY3VycmVudCBwYWNrYWdlLlxuICAgKi9cbiAgcmVhZG9ubHkgdmVyc2lvbnM6IHtcbiAgICByZWFkb25seSBjb21tb246IHN0cmluZztcbiAgICByZWFkb25seSB3ZWI/OiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgbm9kZT86IHN0cmluZztcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG4gICAgcmVhZG9ubHkgJ3JlYWN0LW5hdGl2ZSc/OiBzdHJpbmc7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudCBhIHNldCBvZiBmbGFncyBmb3IgV2ViQXNzZW1ibHlcbiAgICovXG4gIHJlYWRvbmx5IHdhc206IEVudi5XZWJBc3NlbWJseUZsYWdzO1xuXG4gIC8qKlxuICAgKiBSZXByZXNlbnQgYSBzZXQgb2YgZmxhZ3MgZm9yIFdlYkdMXG4gICAqL1xuICByZWFkb25seSB3ZWJnbDogRW52LldlYkdMRmxhZ3M7XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudCBhIHNldCBvZiBmbGFncyBmb3IgV2ViR1BVXG4gICAqL1xuICByZWFkb25seSB3ZWJncHU6IEVudi5XZWJHcHVGbGFncztcblxuICBbbmFtZTogc3RyaW5nXTogdW5rbm93bjtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnQgYSBzZXQgb2YgZmxhZ3MgYXMgYSBnbG9iYWwgc2luZ2xldG9uLlxuICovXG5leHBvcnQgY29uc3QgZW52OiBFbnYgPSBlbnZJbXBsO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3JUb0RhdGFVcmxPcHRpb25zLCBUZW5zb3JUb0ltYWdlRGF0YU9wdGlvbnMgfSBmcm9tICcuL3RlbnNvci1jb252ZXJzaW9uLmpzJztcbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yLmpzJztcblxuLyoqXG4gKiBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IudG9EYXRhVVJMKClcbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvclRvRGF0YVVSTCA9ICh0ZW5zb3I6IFRlbnNvciwgb3B0aW9ucz86IFRlbnNvclRvRGF0YVVybE9wdGlvbnMpOiBzdHJpbmcgPT4ge1xuICBjb25zdCBjYW52YXMgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykgOiBuZXcgT2Zmc2NyZWVuQ2FudmFzKDEsIDEpO1xuICBjYW52YXMud2lkdGggPSB0ZW5zb3IuZGltc1szXTtcbiAgY2FudmFzLmhlaWdodCA9IHRlbnNvci5kaW1zWzJdO1xuICBjb25zdCBwaXhlbHMyRENvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKSBhc1xuICAgIHwgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEXG4gICAgfCBPZmZzY3JlZW5DYW52YXNSZW5kZXJpbmdDb250ZXh0MkRcbiAgICB8IG51bGw7XG5cbiAgaWYgKHBpeGVsczJEQ29udGV4dCAhPSBudWxsKSB7XG4gICAgLy8gRGVmYXVsdCB2YWx1ZXMgZm9yIGhlaWdodCBhbmQgd2lkdGggJiBmb3JtYXRcbiAgICBsZXQgd2lkdGg6IG51bWJlcjtcbiAgICBsZXQgaGVpZ2h0OiBudW1iZXI7XG4gICAgaWYgKG9wdGlvbnM/LnRlbnNvckxheW91dCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMudGVuc29yTGF5b3V0ID09PSAnTkhXQycpIHtcbiAgICAgIHdpZHRoID0gdGVuc29yLmRpbXNbMl07XG4gICAgICBoZWlnaHQgPSB0ZW5zb3IuZGltc1szXTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGVmYXVsdCBsYXlvdXQgaXMgTkNXSFxuICAgICAgd2lkdGggPSB0ZW5zb3IuZGltc1szXTtcbiAgICAgIGhlaWdodCA9IHRlbnNvci5kaW1zWzJdO1xuICAgIH1cblxuICAgIGNvbnN0IGlucHV0Zm9ybWF0ID0gb3B0aW9ucz8uZm9ybWF0ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmZvcm1hdCA6ICdSR0InO1xuXG4gICAgY29uc3Qgbm9ybSA9IG9wdGlvbnM/Lm5vcm07XG4gICAgbGV0IG5vcm1NZWFuOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgICBsZXQgbm9ybUJpYXM6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICAgIGlmIChub3JtID09PSB1bmRlZmluZWQgfHwgbm9ybS5tZWFuID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5vcm1NZWFuID0gWzI1NSwgMjU1LCAyNTUsIDI1NV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0eXBlb2Ygbm9ybS5tZWFuID09PSAnbnVtYmVyJykge1xuICAgICAgICBub3JtTWVhbiA9IFtub3JtLm1lYW4sIG5vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW5dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9ybU1lYW4gPSBbbm9ybS5tZWFuWzBdLCBub3JtLm1lYW5bMV0sIG5vcm0ubWVhblsyXSwgMF07XG4gICAgICAgIGlmIChub3JtLm1lYW5bM10gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG5vcm1NZWFuWzNdID0gbm9ybS5tZWFuWzNdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChub3JtID09PSB1bmRlZmluZWQgfHwgbm9ybS5iaWFzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5vcm1CaWFzID0gWzAsIDAsIDAsIDBdO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodHlwZW9mIG5vcm0uYmlhcyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgbm9ybUJpYXMgPSBbbm9ybS5iaWFzLCBub3JtLmJpYXMsIG5vcm0uYmlhcywgbm9ybS5iaWFzXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5vcm1CaWFzID0gW25vcm0uYmlhc1swXSwgbm9ybS5iaWFzWzFdLCBub3JtLmJpYXNbMl0sIDBdO1xuICAgICAgICBpZiAobm9ybS5iaWFzWzNdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBub3JtQmlhc1szXSA9IG5vcm0uYmlhc1szXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHN0cmlkZSA9IGhlaWdodCAqIHdpZHRoO1xuICAgIC8vIERlZmF1bHQgcG9pbnRlciBhc3NpZ25tZW50c1xuICAgIGxldCByVGVuc29yUG9pbnRlciA9IDAsXG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSxcbiAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMixcbiAgICAgIGFUZW5zb3JQb2ludGVyID0gLTE7XG5cbiAgICAvLyBVcGRhdGluZyB0aGUgcG9pbnRlciBhc3NpZ25tZW50cyBiYXNlZCBvbiB0aGUgaW5wdXQgaW1hZ2UgZm9ybWF0XG4gICAgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCQScpIHtcbiAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgICAgYVRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAzO1xuICAgIH0gZWxzZSBpZiAoaW5wdXRmb3JtYXQgPT09ICdSR0InKSB7XG4gICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMjtcbiAgICB9IGVsc2UgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkJHJykge1xuICAgICAgclRlbnNvclBvaW50ZXIgPSAwO1xuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykge1xuICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7XG4gICAgICAgIGNvbnN0IFIgPSAoKHRlbnNvci5kYXRhW3JUZW5zb3JQb2ludGVyKytdIGFzIG51bWJlcikgLSBub3JtQmlhc1swXSkgKiBub3JtTWVhblswXTsgLy8gUiB2YWx1ZVxuICAgICAgICBjb25zdCBHID0gKCh0ZW5zb3IuZGF0YVtnVGVuc29yUG9pbnRlcisrXSBhcyBudW1iZXIpIC0gbm9ybUJpYXNbMV0pICogbm9ybU1lYW5bMV07IC8vIEcgdmFsdWVcbiAgICAgICAgY29uc3QgQiA9ICgodGVuc29yLmRhdGFbYlRlbnNvclBvaW50ZXIrK10gYXMgbnVtYmVyKSAtIG5vcm1CaWFzWzJdKSAqIG5vcm1NZWFuWzJdOyAvLyBCIHZhbHVlXG4gICAgICAgIGNvbnN0IEEgPSBhVGVuc29yUG9pbnRlciA9PT0gLTEgPyAyNTUgOiAoKHRlbnNvci5kYXRhW2FUZW5zb3JQb2ludGVyKytdIGFzIG51bWJlcikgLSBub3JtQmlhc1szXSkgKiBub3JtTWVhblszXTsgLy8gQSB2YWx1ZVxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L3Jlc3RyaWN0LXBsdXMtb3BlcmFuZHNcbiAgICAgICAgcGl4ZWxzMkRDb250ZXh0LmZpbGxTdHlsZSA9ICdyZ2JhKCcgKyBSICsgJywnICsgRyArICcsJyArIEIgKyAnLCcgKyBBICsgJyknO1xuICAgICAgICBwaXhlbHMyRENvbnRleHQuZmlsbFJlY3QoaiwgaSwgMSwgMSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICgndG9EYXRhVVJMJyBpbiBjYW52YXMpIHtcbiAgICAgIHJldHVybiBjYW52YXMudG9EYXRhVVJMKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndG9EYXRhVVJMIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhJyk7XG4gIH1cbn07XG5cbi8qKlxuICogaW1wbGVtZW50YXRpb24gb2YgVGVuc29yLnRvSW1hZ2VEYXRhKClcbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvclRvSW1hZ2VEYXRhID0gKHRlbnNvcjogVGVuc29yLCBvcHRpb25zPzogVGVuc29yVG9JbWFnZURhdGFPcHRpb25zKTogSW1hZ2VEYXRhID0+IHtcbiAgY29uc3QgcGl4ZWxzMkRDb250ZXh0ID1cbiAgICB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnXG4gICAgICA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpLmdldENvbnRleHQoJzJkJylcbiAgICAgIDogKG5ldyBPZmZzY3JlZW5DYW52YXMoMSwgMSkuZ2V0Q29udGV4dCgnMmQnKSBhcyBPZmZzY3JlZW5DYW52YXNSZW5kZXJpbmdDb250ZXh0MkQpO1xuICBsZXQgaW1hZ2U6IEltYWdlRGF0YTtcbiAgaWYgKHBpeGVsczJEQ29udGV4dCAhPSBudWxsKSB7XG4gICAgLy8gRGVmYXVsdCB2YWx1ZXMgZm9yIGhlaWdodCBhbmQgd2lkdGggJiBmb3JtYXRcbiAgICBsZXQgd2lkdGg6IG51bWJlcjtcbiAgICBsZXQgaGVpZ2h0OiBudW1iZXI7XG4gICAgbGV0IGNoYW5uZWxzOiBudW1iZXI7XG4gICAgaWYgKG9wdGlvbnM/LnRlbnNvckxheW91dCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMudGVuc29yTGF5b3V0ID09PSAnTkhXQycpIHtcbiAgICAgIHdpZHRoID0gdGVuc29yLmRpbXNbMl07XG4gICAgICBoZWlnaHQgPSB0ZW5zb3IuZGltc1sxXTtcbiAgICAgIGNoYW5uZWxzID0gdGVuc29yLmRpbXNbM107XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIERlZmF1bHQgbGF5b3V0IGlzIE5DV0hcbiAgICAgIHdpZHRoID0gdGVuc29yLmRpbXNbM107XG4gICAgICBoZWlnaHQgPSB0ZW5zb3IuZGltc1syXTtcbiAgICAgIGNoYW5uZWxzID0gdGVuc29yLmRpbXNbMV07XG4gICAgfVxuICAgIGNvbnN0IGlucHV0Zm9ybWF0ID0gb3B0aW9ucyAhPT0gdW5kZWZpbmVkID8gKG9wdGlvbnMuZm9ybWF0ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmZvcm1hdCA6ICdSR0InKSA6ICdSR0InO1xuXG4gICAgY29uc3Qgbm9ybSA9IG9wdGlvbnM/Lm5vcm07XG4gICAgbGV0IG5vcm1NZWFuOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgICBsZXQgbm9ybUJpYXM6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICAgIGlmIChub3JtID09PSB1bmRlZmluZWQgfHwgbm9ybS5tZWFuID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5vcm1NZWFuID0gWzI1NSwgMjU1LCAyNTUsIDI1NV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0eXBlb2Ygbm9ybS5tZWFuID09PSAnbnVtYmVyJykge1xuICAgICAgICBub3JtTWVhbiA9IFtub3JtLm1lYW4sIG5vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW5dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9ybU1lYW4gPSBbbm9ybS5tZWFuWzBdLCBub3JtLm1lYW5bMV0sIG5vcm0ubWVhblsyXSwgMjU1XTtcbiAgICAgICAgaWYgKG5vcm0ubWVhblszXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbm9ybU1lYW5bM10gPSBub3JtLm1lYW5bM107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG5vcm0gPT09IHVuZGVmaW5lZCB8fCBub3JtLmJpYXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgbm9ybUJpYXMgPSBbMCwgMCwgMCwgMF07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0eXBlb2Ygbm9ybS5iaWFzID09PSAnbnVtYmVyJykge1xuICAgICAgICBub3JtQmlhcyA9IFtub3JtLmJpYXMsIG5vcm0uYmlhcywgbm9ybS5iaWFzLCBub3JtLmJpYXNdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9ybUJpYXMgPSBbbm9ybS5iaWFzWzBdLCBub3JtLmJpYXNbMV0sIG5vcm0uYmlhc1syXSwgMF07XG4gICAgICAgIGlmIChub3JtLmJpYXNbM10gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG5vcm1CaWFzWzNdID0gbm9ybS5iaWFzWzNdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgc3RyaWRlID0gaGVpZ2h0ICogd2lkdGg7XG4gICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKFxuICAgICAgICAob3B0aW9ucy5mb3JtYXQgIT09IHVuZGVmaW5lZCAmJiBjaGFubmVscyA9PT0gNCAmJiBvcHRpb25zLmZvcm1hdCAhPT0gJ1JHQkEnKSB8fFxuICAgICAgICAoY2hhbm5lbHMgPT09IDMgJiYgb3B0aW9ucy5mb3JtYXQgIT09ICdSR0InICYmIG9wdGlvbnMuZm9ybWF0ICE9PSAnQkdSJylcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUZW5zb3IgZm9ybWF0IGRvZXNuJ3QgbWF0Y2ggaW5wdXQgdGVuc29yIGRpbXNcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGVmYXVsdCBwb2ludGVyIGFzc2lnbm1lbnRzXG4gICAgY29uc3Qgc3RlcCA9IDQ7XG4gICAgbGV0IHJJbWFnZVBvaW50ZXIgPSAwLFxuICAgICAgZ0ltYWdlUG9pbnRlciA9IDEsXG4gICAgICBiSW1hZ2VQb2ludGVyID0gMixcbiAgICAgIGFJbWFnZVBvaW50ZXIgPSAzO1xuICAgIGxldCByVGVuc29yUG9pbnRlciA9IDAsXG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSxcbiAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMixcbiAgICAgIGFUZW5zb3JQb2ludGVyID0gLTE7XG5cbiAgICAvLyBVcGRhdGluZyB0aGUgcG9pbnRlciBhc3NpZ25tZW50cyBiYXNlZCBvbiB0aGUgaW5wdXQgaW1hZ2UgZm9ybWF0XG4gICAgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCQScpIHtcbiAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgICAgYVRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAzO1xuICAgIH0gZWxzZSBpZiAoaW5wdXRmb3JtYXQgPT09ICdSR0InKSB7XG4gICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMjtcbiAgICB9IGVsc2UgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkJHJykge1xuICAgICAgclRlbnNvclBvaW50ZXIgPSAwO1xuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gICAgfVxuXG4gICAgaW1hZ2UgPSBwaXhlbHMyRENvbnRleHQuY3JlYXRlSW1hZ2VEYXRhKHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgZm9yIChcbiAgICAgIGxldCBpID0gMDtcbiAgICAgIGkgPCBoZWlnaHQgKiB3aWR0aDtcbiAgICAgIHJJbWFnZVBvaW50ZXIgKz0gc3RlcCwgZ0ltYWdlUG9pbnRlciArPSBzdGVwLCBiSW1hZ2VQb2ludGVyICs9IHN0ZXAsIGFJbWFnZVBvaW50ZXIgKz0gc3RlcCwgaSsrXG4gICAgKSB7XG4gICAgICBpbWFnZS5kYXRhW3JJbWFnZVBvaW50ZXJdID0gKCh0ZW5zb3IuZGF0YVtyVGVuc29yUG9pbnRlcisrXSBhcyBudW1iZXIpIC0gbm9ybUJpYXNbMF0pICogbm9ybU1lYW5bMF07IC8vIFIgdmFsdWVcbiAgICAgIGltYWdlLmRhdGFbZ0ltYWdlUG9pbnRlcl0gPSAoKHRlbnNvci5kYXRhW2dUZW5zb3JQb2ludGVyKytdIGFzIG51bWJlcikgLSBub3JtQmlhc1sxXSkgKiBub3JtTWVhblsxXTsgLy8gRyB2YWx1ZVxuICAgICAgaW1hZ2UuZGF0YVtiSW1hZ2VQb2ludGVyXSA9ICgodGVuc29yLmRhdGFbYlRlbnNvclBvaW50ZXIrK10gYXMgbnVtYmVyKSAtIG5vcm1CaWFzWzJdKSAqIG5vcm1NZWFuWzJdOyAvLyBCIHZhbHVlXG4gICAgICBpbWFnZS5kYXRhW2FJbWFnZVBvaW50ZXJdID1cbiAgICAgICAgYVRlbnNvclBvaW50ZXIgPT09IC0xID8gMjU1IDogKCh0ZW5zb3IuZGF0YVthVGVuc29yUG9pbnRlcisrXSBhcyBudW1iZXIpIC0gbm9ybUJpYXNbM10pICogbm9ybU1lYW5bM107IC8vIEEgdmFsdWVcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhJyk7XG4gIH1cbiAgcmV0dXJuIGltYWdlO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtcbiAgT3B0aW9uc0RpbWVuc2lvbnMsXG4gIE9wdGlvbnNGb3JtYXQsXG4gIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycyxcbiAgT3B0aW9uc1RlbnNvckZvcm1hdCxcbiAgT3B0aW9uc1RlbnNvckxheW91dCxcbiAgVGVuc29yRnJvbUdwdUJ1ZmZlck9wdGlvbnMsXG4gIFRlbnNvckZyb21JbWFnZUJpdG1hcE9wdGlvbnMsXG4gIFRlbnNvckZyb21JbWFnZURhdGFPcHRpb25zLFxuICBUZW5zb3JGcm9tSW1hZ2VFbGVtZW50T3B0aW9ucyxcbiAgVGVuc29yRnJvbU1MVGVuc29yT3B0aW9ucyxcbiAgVGVuc29yRnJvbVRleHR1cmVPcHRpb25zLFxuICBUZW5zb3JGcm9tVXJsT3B0aW9ucyxcbn0gZnJvbSAnLi90ZW5zb3ItZmFjdG9yeS5qcyc7XG5pbXBvcnQgeyBUZW5zb3IgfSBmcm9tICcuL3RlbnNvci1pbXBsLmpzJztcbmltcG9ydCB7IFRlbnNvciBhcyBUZW5zb3JJbnRlcmZhY2UgfSBmcm9tICcuL3RlbnNvci5qcyc7XG5cbmludGVyZmFjZSBCdWZmZXJUb1RlbnNvck9wdGlvbnNcbiAgZXh0ZW5kcyBPcHRpb25zRGltZW5zaW9ucyxcbiAgICBPcHRpb25zVGVuc29yTGF5b3V0LFxuICAgIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycyxcbiAgICBPcHRpb25zRm9ybWF0LFxuICAgIE9wdGlvbnNUZW5zb3JGb3JtYXQge31cblxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgdGVuc29yIG9iamVjdCBmcm9tIGltYWdlIG9iamVjdFxuICpcbiAqIEBwYXJhbSBidWZmZXIgLSBFeHRyYWN0ZWQgaW1hZ2UgYnVmZmVyIGRhdGEgLSBhc3N1bWluZyBSR0JBIGZvcm1hdFxuICogQHBhcmFtIGltYWdlRm9ybWF0IC0gaW5wdXQgaW1hZ2UgY29uZmlndXJhdGlvbiAtIHJlcXVpcmVkIGNvbmZpZ3VyYXRpb25zIGhlaWdodCwgd2lkdGgsIGZvcm1hdFxuICogQHBhcmFtIHRlbnNvckZvcm1hdCAtIG91dHB1dCB0ZW5zb3IgY29uZmlndXJhdGlvbiAtIERlZmF1bHQgaXMgUkdCIGZvcm1hdFxuICovXG5leHBvcnQgY29uc3QgYnVmZmVyVG9UZW5zb3IgPSAoYnVmZmVyOiBVaW50OENsYW1wZWRBcnJheSB8IHVuZGVmaW5lZCwgb3B0aW9uczogQnVmZmVyVG9UZW5zb3JPcHRpb25zKTogVGVuc29yID0+IHtcbiAgaWYgKGJ1ZmZlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBidWZmZXIgbXVzdCBiZSBkZWZpbmVkJyk7XG4gIH1cbiAgaWYgKG9wdGlvbnMuaGVpZ2h0ID09PSB1bmRlZmluZWQgfHwgb3B0aW9ucy53aWR0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBoZWlnaHQgYW5kIHdpZHRoIG11c3QgYmUgZGVmaW5lZCcpO1xuICB9XG4gIGlmIChvcHRpb25zLnRlbnNvckxheW91dCA9PT0gJ05IV0MnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdOSFdDIFRlbnNvciBsYXlvdXQgaXMgbm90IHN1cHBvcnRlZCB5ZXQnKTtcbiAgfVxuXG4gIGNvbnN0IHsgaGVpZ2h0LCB3aWR0aCB9ID0gb3B0aW9ucztcblxuICBjb25zdCBub3JtID0gb3B0aW9ucy5ub3JtID8/IHsgbWVhbjogMjU1LCBiaWFzOiAwIH07XG4gIGxldCBub3JtTWVhbjogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gIGxldCBub3JtQmlhczogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG5cbiAgaWYgKHR5cGVvZiBub3JtLm1lYW4gPT09ICdudW1iZXInKSB7XG4gICAgbm9ybU1lYW4gPSBbbm9ybS5tZWFuLCBub3JtLm1lYW4sIG5vcm0ubWVhbiwgbm9ybS5tZWFuXTtcbiAgfSBlbHNlIHtcbiAgICBub3JtTWVhbiA9IFtub3JtLm1lYW4hWzBdLCBub3JtLm1lYW4hWzFdLCBub3JtLm1lYW4hWzJdLCBub3JtLm1lYW4hWzNdID8/IDI1NV07XG4gIH1cblxuICBpZiAodHlwZW9mIG5vcm0uYmlhcyA9PT0gJ251bWJlcicpIHtcbiAgICBub3JtQmlhcyA9IFtub3JtLmJpYXMsIG5vcm0uYmlhcywgbm9ybS5iaWFzLCBub3JtLmJpYXNdO1xuICB9IGVsc2Uge1xuICAgIG5vcm1CaWFzID0gW25vcm0uYmlhcyFbMF0sIG5vcm0uYmlhcyFbMV0sIG5vcm0uYmlhcyFbMl0sIG5vcm0uYmlhcyFbM10gPz8gMF07XG4gIH1cblxuICBjb25zdCBpbnB1dGZvcm1hdCA9IG9wdGlvbnMuZm9ybWF0ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmZvcm1hdCA6ICdSR0JBJztcbiAgLy8gZGVmYXVsdCB2YWx1ZSBpcyBSR0JBIHNpbmNlIGltYWdlZGF0YSBhbmQgSFRNTEltYWdlRWxlbWVudCB1c2VzIGl0XG5cbiAgY29uc3Qgb3V0cHV0Zm9ybWF0ID1cbiAgICBvcHRpb25zLnRlbnNvckZvcm1hdCAhPT0gdW5kZWZpbmVkID8gKG9wdGlvbnMudGVuc29yRm9ybWF0ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnRlbnNvckZvcm1hdCA6ICdSR0InKSA6ICdSR0InO1xuICBjb25zdCBzdHJpZGUgPSBoZWlnaHQgKiB3aWR0aDtcbiAgY29uc3QgZmxvYXQzMkRhdGEgPSBvdXRwdXRmb3JtYXQgPT09ICdSR0JBJyA/IG5ldyBGbG9hdDMyQXJyYXkoc3RyaWRlICogNCkgOiBuZXcgRmxvYXQzMkFycmF5KHN0cmlkZSAqIDMpO1xuXG4gIC8vIERlZmF1bHQgcG9pbnRlciBhc3NpZ25tZW50c1xuICBsZXQgc3RlcCA9IDQsXG4gICAgckltYWdlUG9pbnRlciA9IDAsXG4gICAgZ0ltYWdlUG9pbnRlciA9IDEsXG4gICAgYkltYWdlUG9pbnRlciA9IDIsXG4gICAgYUltYWdlUG9pbnRlciA9IDM7XG4gIGxldCByVGVuc29yUG9pbnRlciA9IDAsXG4gICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGUsXG4gICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyLFxuICAgIGFUZW5zb3JQb2ludGVyID0gLTE7XG5cbiAgLy8gVXBkYXRpbmcgdGhlIHBvaW50ZXIgYXNzaWdubWVudHMgYmFzZWQgb24gdGhlIGlucHV0IGltYWdlIGZvcm1hdFxuICBpZiAoaW5wdXRmb3JtYXQgPT09ICdSR0InKSB7XG4gICAgc3RlcCA9IDM7XG4gICAgckltYWdlUG9pbnRlciA9IDA7XG4gICAgZ0ltYWdlUG9pbnRlciA9IDE7XG4gICAgYkltYWdlUG9pbnRlciA9IDI7XG4gICAgYUltYWdlUG9pbnRlciA9IC0xO1xuICB9XG5cbiAgLy8gVXBkYXRpbmcgdGhlIHBvaW50ZXIgYXNzaWdubWVudHMgYmFzZWQgb24gdGhlIG91dHB1dCB0ZW5zb3IgZm9ybWF0XG4gIGlmIChvdXRwdXRmb3JtYXQgPT09ICdSR0JBJykge1xuICAgIGFUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMztcbiAgfSBlbHNlIGlmIChvdXRwdXRmb3JtYXQgPT09ICdSQkcnKSB7XG4gICAgclRlbnNvclBvaW50ZXIgPSAwO1xuICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMjtcbiAgfSBlbHNlIGlmIChvdXRwdXRmb3JtYXQgPT09ICdCR1InKSB7XG4gICAgYlRlbnNvclBvaW50ZXIgPSAwO1xuICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgIHJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMjtcbiAgfVxuXG4gIGZvciAoXG4gICAgbGV0IGkgPSAwO1xuICAgIGkgPCBzdHJpZGU7XG4gICAgaSsrLCBySW1hZ2VQb2ludGVyICs9IHN0ZXAsIGJJbWFnZVBvaW50ZXIgKz0gc3RlcCwgZ0ltYWdlUG9pbnRlciArPSBzdGVwLCBhSW1hZ2VQb2ludGVyICs9IHN0ZXBcbiAgKSB7XG4gICAgZmxvYXQzMkRhdGFbclRlbnNvclBvaW50ZXIrK10gPSAoYnVmZmVyW3JJbWFnZVBvaW50ZXJdICsgbm9ybUJpYXNbMF0pIC8gbm9ybU1lYW5bMF07XG4gICAgZmxvYXQzMkRhdGFbZ1RlbnNvclBvaW50ZXIrK10gPSAoYnVmZmVyW2dJbWFnZVBvaW50ZXJdICsgbm9ybUJpYXNbMV0pIC8gbm9ybU1lYW5bMV07XG4gICAgZmxvYXQzMkRhdGFbYlRlbnNvclBvaW50ZXIrK10gPSAoYnVmZmVyW2JJbWFnZVBvaW50ZXJdICsgbm9ybUJpYXNbMl0pIC8gbm9ybU1lYW5bMl07XG4gICAgaWYgKGFUZW5zb3JQb2ludGVyICE9PSAtMSAmJiBhSW1hZ2VQb2ludGVyICE9PSAtMSkge1xuICAgICAgZmxvYXQzMkRhdGFbYVRlbnNvclBvaW50ZXIrK10gPSAoYnVmZmVyW2FJbWFnZVBvaW50ZXJdICsgbm9ybUJpYXNbM10pIC8gbm9ybU1lYW5bM107XG4gICAgfVxuICB9XG5cbiAgLy8gRmxvYXQzMkFycmF5IC0+IG9ydC5UZW5zb3JcbiAgY29uc3Qgb3V0cHV0VGVuc29yID1cbiAgICBvdXRwdXRmb3JtYXQgPT09ICdSR0JBJ1xuICAgICAgPyBuZXcgVGVuc29yKCdmbG9hdDMyJywgZmxvYXQzMkRhdGEsIFsxLCA0LCBoZWlnaHQsIHdpZHRoXSlcbiAgICAgIDogbmV3IFRlbnNvcignZmxvYXQzMicsIGZsb2F0MzJEYXRhLCBbMSwgMywgaGVpZ2h0LCB3aWR0aF0pO1xuICByZXR1cm4gb3V0cHV0VGVuc29yO1xufTtcblxuLyoqXG4gKiBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IuZnJvbUltYWdlKCkuXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JGcm9tSW1hZ2UgPSBhc3luYyAoXG4gIGltYWdlOiBJbWFnZURhdGEgfCBIVE1MSW1hZ2VFbGVtZW50IHwgSW1hZ2VCaXRtYXAgfCBzdHJpbmcsXG4gIG9wdGlvbnM/OlxuICAgIHwgVGVuc29yRnJvbUltYWdlRGF0YU9wdGlvbnNcbiAgICB8IFRlbnNvckZyb21JbWFnZUVsZW1lbnRPcHRpb25zXG4gICAgfCBUZW5zb3JGcm9tSW1hZ2VCaXRtYXBPcHRpb25zXG4gICAgfCBUZW5zb3JGcm9tVXJsT3B0aW9ucyxcbik6IFByb21pc2U8VGVuc29yPiA9PiB7XG4gIC8vIGNoZWNraW5nIHRoZSB0eXBlIG9mIGltYWdlIG9iamVjdFxuICBjb25zdCBpc0hUTUxJbWFnZUVsZSA9IHR5cGVvZiBIVE1MSW1hZ2VFbGVtZW50ICE9PSAndW5kZWZpbmVkJyAmJiBpbWFnZSBpbnN0YW5jZW9mIEhUTUxJbWFnZUVsZW1lbnQ7XG4gIGNvbnN0IGlzSW1hZ2VEYXRhRWxlID0gdHlwZW9mIEltYWdlRGF0YSAhPT0gJ3VuZGVmaW5lZCcgJiYgaW1hZ2UgaW5zdGFuY2VvZiBJbWFnZURhdGE7XG4gIGNvbnN0IGlzSW1hZ2VCaXRtYXAgPSB0eXBlb2YgSW1hZ2VCaXRtYXAgIT09ICd1bmRlZmluZWQnICYmIGltYWdlIGluc3RhbmNlb2YgSW1hZ2VCaXRtYXA7XG4gIGNvbnN0IGlzU3RyaW5nID0gdHlwZW9mIGltYWdlID09PSAnc3RyaW5nJztcblxuICBsZXQgZGF0YTogVWludDhDbGFtcGVkQXJyYXkgfCB1bmRlZmluZWQ7XG4gIGxldCBidWZmZXJUb1RlbnNvck9wdGlvbnM6IEJ1ZmZlclRvVGVuc29yT3B0aW9ucyA9IG9wdGlvbnMgPz8ge307XG5cbiAgY29uc3QgY3JlYXRlQ2FudmFzID0gKCkgPT4ge1xuICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgT2Zmc2NyZWVuQ2FudmFzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIG5ldyBPZmZzY3JlZW5DYW52YXMoMSwgMSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FudmFzIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG4gIH07XG4gIGNvbnN0IGNyZWF0ZUNhbnZhc0NvbnRleHQgPSAoY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCB8IE9mZnNjcmVlbkNhbnZhcykgPT4ge1xuICAgIGlmICh0eXBlb2YgSFRNTENhbnZhc0VsZW1lbnQgIT09ICd1bmRlZmluZWQnICYmIGNhbnZhcyBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50KSB7XG4gICAgICByZXR1cm4gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgfSBlbHNlIGlmIChjYW52YXMgaW5zdGFuY2VvZiBPZmZzY3JlZW5DYW52YXMpIHtcbiAgICAgIHJldHVybiBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKSBhcyBPZmZzY3JlZW5DYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfTtcbiAgLy8gZmlsbGluZyBhbmQgY2hlY2tpbmcgaW1hZ2UgY29uZmlndXJhdGlvbiBvcHRpb25zXG4gIGlmIChpc0hUTUxJbWFnZUVsZSkge1xuICAgIC8vIEhUTUxJbWFnZUVsZW1lbnQgLSBpbWFnZSBvYmplY3QgLSBmb3JtYXQgaXMgUkdCQSBieSBkZWZhdWx0XG4gICAgY29uc3QgY2FudmFzID0gY3JlYXRlQ2FudmFzKCk7XG4gICAgY2FudmFzLndpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgY2FudmFzLmhlaWdodCA9IGltYWdlLmhlaWdodDtcbiAgICBjb25zdCBwaXhlbHMyRENvbnRleHQgPSBjcmVhdGVDYW52YXNDb250ZXh0KGNhbnZhcyk7XG5cbiAgICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAgIGxldCBoZWlnaHQgPSBpbWFnZS5oZWlnaHQ7XG4gICAgICBsZXQgd2lkdGggPSBpbWFnZS53aWR0aDtcbiAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkSGVpZ2h0ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkV2lkdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBoZWlnaHQgPSBvcHRpb25zLnJlc2l6ZWRIZWlnaHQ7XG4gICAgICAgIHdpZHRoID0gb3B0aW9ucy5yZXNpemVkV2lkdGg7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zID0gb3B0aW9ucztcbiAgICAgICAgaWYgKG9wdGlvbnMudGVuc29yRm9ybWF0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGlucHV0IGNvbmZpZyBmb3JtYXQgbXVzdCBiZSBSR0JBIGZvciBIVE1MSW1hZ2VFbGVtZW50Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLnRlbnNvckZvcm1hdCA9ICdSR0JBJztcbiAgICAgICAgfVxuICAgICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMud2lkdGggPSB3aWR0aDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy50ZW5zb3JGb3JtYXQgPSAnUkdCQSc7XG4gICAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy53aWR0aCA9IHdpZHRoO1xuICAgICAgfVxuXG4gICAgICBwaXhlbHMyRENvbnRleHQuZHJhd0ltYWdlKGltYWdlLCAwLCAwKTtcbiAgICAgIGRhdGEgPSBwaXhlbHMyRENvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIHdpZHRoLCBoZWlnaHQpLmRhdGE7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YScpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpc0ltYWdlRGF0YUVsZSkge1xuICAgIGxldCBoZWlnaHQ6IG51bWJlcjtcbiAgICBsZXQgd2lkdGg6IG51bWJlcjtcblxuICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkV2lkdGggIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLnJlc2l6ZWRIZWlnaHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaGVpZ2h0ID0gb3B0aW9ucy5yZXNpemVkSGVpZ2h0O1xuICAgICAgd2lkdGggPSBvcHRpb25zLnJlc2l6ZWRXaWR0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0O1xuICAgICAgd2lkdGggPSBpbWFnZS53aWR0aDtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMgPSBvcHRpb25zO1xuICAgIH1cbiAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMuZm9ybWF0ID0gJ1JHQkEnO1xuICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLndpZHRoID0gd2lkdGg7XG5cbiAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCB0ZW1wQ2FudmFzID0gY3JlYXRlQ2FudmFzKCk7XG5cbiAgICAgIHRlbXBDYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgIHRlbXBDYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuXG4gICAgICBjb25zdCBwaXhlbHMyRENvbnRleHQgPSBjcmVhdGVDYW52YXNDb250ZXh0KHRlbXBDYW52YXMpO1xuXG4gICAgICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAgICAgcGl4ZWxzMkRDb250ZXh0LnB1dEltYWdlRGF0YShpbWFnZSwgMCwgMCk7XG4gICAgICAgIGRhdGEgPSBwaXhlbHMyRENvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIHdpZHRoLCBoZWlnaHQpLmRhdGE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZGF0YSA9IGltYWdlLmRhdGE7XG4gICAgfVxuICB9IGVsc2UgaWYgKGlzSW1hZ2VCaXRtYXApIHtcbiAgICAvLyBJbWFnZUJpdG1hcCAtIGltYWdlIG9iamVjdCAtIGZvcm1hdCBtdXN0IGJlIHByb3ZpZGVkIGJ5IHVzZXJcbiAgICBpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BsZWFzZSBwcm92aWRlIGltYWdlIGNvbmZpZyB3aXRoIGZvcm1hdCBmb3IgSW1hZ2ViaXRtYXAnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjYW52YXMgPSBjcmVhdGVDYW52YXMoKTtcbiAgICBjYW52YXMud2lkdGggPSBpbWFnZS53aWR0aDtcbiAgICBjYW52YXMuaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0O1xuICAgIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQoY2FudmFzKTtcblxuICAgIGlmIChwaXhlbHMyRENvbnRleHQgIT0gbnVsbCkge1xuICAgICAgY29uc3QgaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0O1xuICAgICAgY29uc3Qgd2lkdGggPSBpbWFnZS53aWR0aDtcbiAgICAgIHBpeGVsczJEQ29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgZGF0YSA9IHBpeGVsczJEQ29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgd2lkdGgsIGhlaWdodCkuZGF0YTtcbiAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMud2lkdGggPSB3aWR0aDtcbiAgICAgIHJldHVybiBidWZmZXJUb1RlbnNvcihkYXRhLCBidWZmZXJUb1RlbnNvck9wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoaXNTdHJpbmcpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgY2FudmFzID0gY3JlYXRlQ2FudmFzKCk7XG4gICAgICBjb25zdCBjb250ZXh0ID0gY3JlYXRlQ2FudmFzQ29udGV4dChjYW52YXMpO1xuICAgICAgaWYgKCFpbWFnZSB8fCAhY29udGV4dCkge1xuICAgICAgICByZXR1cm4gcmVqZWN0KCk7XG4gICAgICB9XG4gICAgICBjb25zdCBuZXdJbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgICAgbmV3SW1hZ2UuY3Jvc3NPcmlnaW4gPSAnQW5vbnltb3VzJztcbiAgICAgIG5ld0ltYWdlLnNyYyA9IGltYWdlO1xuICAgICAgbmV3SW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgICBjYW52YXMud2lkdGggPSBuZXdJbWFnZS53aWR0aDtcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IG5ld0ltYWdlLmhlaWdodDtcbiAgICAgICAgY29udGV4dC5kcmF3SW1hZ2UobmV3SW1hZ2UsIDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICAgIGNvbnN0IGltZyA9IGNvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLmhlaWdodCA9IGNhbnZhcy5oZWlnaHQ7XG4gICAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy53aWR0aCA9IGNhbnZhcy53aWR0aDtcbiAgICAgICAgcmVzb2x2ZShidWZmZXJUb1RlbnNvcihpbWcuZGF0YSwgYnVmZmVyVG9UZW5zb3JPcHRpb25zKSk7XG4gICAgICB9O1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgZGF0YSBwcm92aWRlZCBpcyBub3Qgc3VwcG9ydGVkIC0gYWJvcnRlZCB0ZW5zb3IgY3JlYXRpb24nKTtcbiAgfVxuXG4gIGlmIChkYXRhICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gYnVmZmVyVG9UZW5zb3IoZGF0YSwgYnVmZmVyVG9UZW5zb3JPcHRpb25zKTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGRhdGEgcHJvdmlkZWQgaXMgbm90IHN1cHBvcnRlZCAtIGFib3J0ZWQgdGVuc29yIGNyZWF0aW9uJyk7XG4gIH1cbn07XG5cbi8qKlxuICogaW1wbGVtZW50YXRpb24gb2YgVGVuc29yLmZyb21UZXh0dXJlKCkuXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JGcm9tVGV4dHVyZSA9IDxUIGV4dGVuZHMgVGVuc29ySW50ZXJmYWNlLlRleHR1cmVEYXRhVHlwZXM+KFxuICB0ZXh0dXJlOiBUZW5zb3JJbnRlcmZhY2UuVGV4dHVyZVR5cGUsXG4gIG9wdGlvbnM6IFRlbnNvckZyb21UZXh0dXJlT3B0aW9uczxUPixcbik6IFRlbnNvciA9PiB7XG4gIGNvbnN0IHsgd2lkdGgsIGhlaWdodCwgZG93bmxvYWQsIGRpc3Bvc2UgfSA9IG9wdGlvbnM7XG4gIC8vIEFsd2F5cyBhc3N1bWUgUkdCQUYzMi4gVE9ETzogc3VwcG9ydCBkaWZmZXJlbnQgdGV4dHVyZSBmb3JtYXRcbiAgY29uc3QgZGltcyA9IFsxLCBoZWlnaHQsIHdpZHRoLCA0XTtcbiAgcmV0dXJuIG5ldyBUZW5zb3IoeyBsb2NhdGlvbjogJ3RleHR1cmUnLCB0eXBlOiAnZmxvYXQzMicsIHRleHR1cmUsIGRpbXMsIGRvd25sb2FkLCBkaXNwb3NlIH0pO1xufTtcblxuLyoqXG4gKiBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IuZnJvbUdwdUJ1ZmZlcigpLlxuICovXG5leHBvcnQgY29uc3QgdGVuc29yRnJvbUdwdUJ1ZmZlciA9IDxUIGV4dGVuZHMgVGVuc29ySW50ZXJmYWNlLkdwdUJ1ZmZlckRhdGFUeXBlcz4oXG4gIGdwdUJ1ZmZlcjogVGVuc29ySW50ZXJmYWNlLkdwdUJ1ZmZlclR5cGUsXG4gIG9wdGlvbnM6IFRlbnNvckZyb21HcHVCdWZmZXJPcHRpb25zPFQ+LFxuKTogVGVuc29yID0+IHtcbiAgY29uc3QgeyBkYXRhVHlwZSwgZGltcywgZG93bmxvYWQsIGRpc3Bvc2UgfSA9IG9wdGlvbnM7XG4gIHJldHVybiBuZXcgVGVuc29yKHsgbG9jYXRpb246ICdncHUtYnVmZmVyJywgdHlwZTogZGF0YVR5cGUgPz8gJ2Zsb2F0MzInLCBncHVCdWZmZXIsIGRpbXMsIGRvd25sb2FkLCBkaXNwb3NlIH0pO1xufTtcblxuLyoqXG4gKiBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IuZnJvbU1MVGVuc29yKCkuXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JGcm9tTUxUZW5zb3IgPSA8VCBleHRlbmRzIFRlbnNvckludGVyZmFjZS5NTFRlbnNvckRhdGFUeXBlcz4oXG4gIG1sVGVuc29yOiBUZW5zb3JJbnRlcmZhY2UuTUxUZW5zb3JUeXBlLFxuICBvcHRpb25zOiBUZW5zb3JGcm9tTUxUZW5zb3JPcHRpb25zPFQ+LFxuKTogVGVuc29yID0+IHtcbiAgY29uc3QgeyBkYXRhVHlwZSwgZGltcywgZG93bmxvYWQsIGRpc3Bvc2UgfSA9IG9wdGlvbnM7XG4gIHJldHVybiBuZXcgVGVuc29yKHsgbG9jYXRpb246ICdtbC10ZW5zb3InLCB0eXBlOiBkYXRhVHlwZSA/PyAnZmxvYXQzMicsIG1sVGVuc29yLCBkaW1zLCBkb3dubG9hZCwgZGlzcG9zZSB9KTtcbn07XG5cbi8qKlxuICogaW1wbGVtZW50YXRpb24gb2YgVGVuc29yLmZyb21QaW5uZWRCdWZmZXIoKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvckZyb21QaW5uZWRCdWZmZXIgPSA8VCBleHRlbmRzIFRlbnNvckludGVyZmFjZS5DcHVQaW5uZWREYXRhVHlwZXM+KFxuICB0eXBlOiBULFxuICBidWZmZXI6IFRlbnNvckludGVyZmFjZS5EYXRhVHlwZU1hcFtUXSxcbiAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuKTogVGVuc29yID0+IG5ldyBUZW5zb3IoeyBsb2NhdGlvbjogJ2NwdS1waW5uZWQnLCB0eXBlLCBkYXRhOiBidWZmZXIsIGRpbXM6IGRpbXMgPz8gW2J1ZmZlci5sZW5ndGhdIH0pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3IgfSBmcm9tICcuL3RlbnNvci5qcyc7XG5cbmV4cG9ydCB0eXBlIFN1cHBvcnRlZFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnMgPVxuICB8IEZsb2F0MzJBcnJheUNvbnN0cnVjdG9yXG4gIHwgVWludDhBcnJheUNvbnN0cnVjdG9yXG4gIHwgSW50OEFycmF5Q29uc3RydWN0b3JcbiAgfCBVaW50MTZBcnJheUNvbnN0cnVjdG9yXG4gIHwgSW50MTZBcnJheUNvbnN0cnVjdG9yXG4gIHwgSW50MzJBcnJheUNvbnN0cnVjdG9yXG4gIHwgQmlnSW50NjRBcnJheUNvbnN0cnVjdG9yXG4gIHwgVWludDhBcnJheUNvbnN0cnVjdG9yXG4gIHwgRmxvYXQ2NEFycmF5Q29uc3RydWN0b3JcbiAgfCBVaW50MzJBcnJheUNvbnN0cnVjdG9yXG4gIHwgQmlnVWludDY0QXJyYXlDb25zdHJ1Y3RvcjtcbmV4cG9ydCB0eXBlIFN1cHBvcnRlZFR5cGVkQXJyYXkgPSBJbnN0YW5jZVR5cGU8U3VwcG9ydGVkVHlwZWRBcnJheUNvbnN0cnVjdG9ycz47XG5cbi8vIGEgcnVudGltZSBtYXAgdGhhdCBtYXBzIHR5cGUgc3RyaW5nIHRvIFR5cGVkQXJyYXkgY29uc3RydWN0b3IuIFNob3VsZCBtYXRjaCBUZW5zb3IuRGF0YVR5cGVNYXAuXG5leHBvcnQgY29uc3QgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUCA9IG5ldyBNYXA8c3RyaW5nLCBTdXBwb3J0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3JzPihbXG4gIFsnZmxvYXQzMicsIEZsb2F0MzJBcnJheV0sXG4gIFsndWludDgnLCBVaW50OEFycmF5XSxcbiAgWydpbnQ4JywgSW50OEFycmF5XSxcbiAgWyd1aW50MTYnLCBVaW50MTZBcnJheV0sXG4gIFsnaW50MTYnLCBJbnQxNkFycmF5XSxcbiAgWydpbnQzMicsIEludDMyQXJyYXldLFxuICBbJ2Jvb2wnLCBVaW50OEFycmF5XSxcbiAgWydmbG9hdDY0JywgRmxvYXQ2NEFycmF5XSxcbiAgWyd1aW50MzInLCBVaW50MzJBcnJheV0sXG4gIFsnaW50NCcsIFVpbnQ4QXJyYXldLFxuICBbJ3VpbnQ0JywgVWludDhBcnJheV0sXG5dKTtcblxuLy8gYSBydW50aW1lIG1hcCB0aGF0IG1hcHMgdHlwZSBzdHJpbmcgdG8gVHlwZWRBcnJheSBjb25zdHJ1Y3Rvci4gU2hvdWxkIG1hdGNoIFRlbnNvci5EYXRhVHlwZU1hcC5cbmV4cG9ydCBjb25zdCBOVU1FUklDX1RFTlNPUl9UWVBFREFSUkFZX1RPX1RZUEVfTUFQID0gbmV3IE1hcDxTdXBwb3J0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3JzLCBUZW5zb3IuVHlwZT4oW1xuICBbRmxvYXQzMkFycmF5LCAnZmxvYXQzMiddLFxuICBbVWludDhBcnJheSwgJ3VpbnQ4J10sXG4gIFtJbnQ4QXJyYXksICdpbnQ4J10sXG4gIFtVaW50MTZBcnJheSwgJ3VpbnQxNiddLFxuICBbSW50MTZBcnJheSwgJ2ludDE2J10sXG4gIFtJbnQzMkFycmF5LCAnaW50MzInXSxcbiAgW0Zsb2F0NjRBcnJheSwgJ2Zsb2F0NjQnXSxcbiAgW1VpbnQzMkFycmF5LCAndWludDMyJ10sXG5dKTtcblxuLy8gdGhlIGZvbGxvd2luZyBjb2RlIGFsbG93cyBkZWxheWluZyBleGVjdXRpb24gb2YgQmlnSW50L0Zsb2F0MTZBcnJheSBjaGVja2luZy4gVGhpcyBhbGxvd3MgbGF6eSBpbml0aWFsaXphdGlvbiBmb3Jcbi8vIE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAgYW5kIE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAsIHdoaWNoIGFsbG93cyBCaWdJbnQvRmxvYXQxNkFycmF5XG4vLyBwb2x5ZmlsbCBpZiBhdmFpbGFibGUuXG5sZXQgaXNUeXBlZEFycmF5Q2hlY2tlZCA9IGZhbHNlO1xuZXhwb3J0IGNvbnN0IGNoZWNrVHlwZWRBcnJheSA9ICgpID0+IHtcbiAgaWYgKCFpc1R5cGVkQXJyYXlDaGVja2VkKSB7XG4gICAgaXNUeXBlZEFycmF5Q2hlY2tlZCA9IHRydWU7XG4gICAgY29uc3QgaXNCaWdJbnQ2NEFycmF5QXZhaWxhYmxlID0gdHlwZW9mIEJpZ0ludDY0QXJyYXkgIT09ICd1bmRlZmluZWQnICYmIEJpZ0ludDY0QXJyYXkuZnJvbTtcbiAgICBjb25zdCBpc0JpZ1VpbnQ2NEFycmF5QXZhaWxhYmxlID0gdHlwZW9mIEJpZ1VpbnQ2NEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiBCaWdVaW50NjRBcnJheS5mcm9tO1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvbiwgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIGNvbnN0IEZsb2F0MTZBcnJheSA9IChnbG9iYWxUaGlzIGFzIGFueSkuRmxvYXQxNkFycmF5O1xuICAgIGNvbnN0IGlzRmxvYXQxNkFycmF5QXZhaWxhYmxlID0gdHlwZW9mIEZsb2F0MTZBcnJheSAhPT0gJ3VuZGVmaW5lZCcgJiYgRmxvYXQxNkFycmF5LmZyb207XG5cbiAgICBpZiAoaXNCaWdJbnQ2NEFycmF5QXZhaWxhYmxlKSB7XG4gICAgICBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQLnNldCgnaW50NjQnLCBCaWdJbnQ2NEFycmF5KTtcbiAgICAgIE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAuc2V0KEJpZ0ludDY0QXJyYXksICdpbnQ2NCcpO1xuICAgIH1cbiAgICBpZiAoaXNCaWdVaW50NjRBcnJheUF2YWlsYWJsZSkge1xuICAgICAgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5zZXQoJ3VpbnQ2NCcsIEJpZ1VpbnQ2NEFycmF5KTtcbiAgICAgIE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAuc2V0KEJpZ1VpbnQ2NEFycmF5LCAndWludDY0Jyk7XG4gICAgfVxuICAgIGlmIChpc0Zsb2F0MTZBcnJheUF2YWlsYWJsZSkge1xuICAgICAgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5zZXQoJ2Zsb2F0MTYnLCBGbG9hdDE2QXJyYXkpO1xuICAgICAgTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUC5zZXQoRmxvYXQxNkFycmF5LCAnZmxvYXQxNicpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBpZiBGbG9hdDE2QXJyYXkgaXMgbm90IGF2YWlsYWJsZSwgdXNlICdVaW50MTZBcnJheScgdG8gc3RvcmUgdGhlIGRhdGEuXG4gICAgICBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQLnNldCgnZmxvYXQxNicsIFVpbnQxNkFycmF5KTtcbiAgICB9XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7XG4gIENwdVBpbm5lZENvbnN0cnVjdG9yUGFyYW1ldGVycyxcbiAgR3B1QnVmZmVyQ29uc3RydWN0b3JQYXJhbWV0ZXJzLFxuICBNTFRlbnNvckNvbnN0cnVjdG9yUGFyYW1ldGVycyxcbiAgVGV4dHVyZUNvbnN0cnVjdG9yUGFyYW1ldGVycyxcbn0gZnJvbSAnLi90ZW5zb3ItZmFjdG9yeS5qcyc7XG5pbXBvcnQgeyBUZW5zb3IgfSBmcm9tICcuL3RlbnNvci1pbXBsLmpzJztcblxuLyoqXG4gKiBjYWxjdWxhdGUgc2l6ZSBmcm9tIGRpbXMuXG4gKlxuICogQHBhcmFtIGRpbXMgdGhlIGRpbXMgYXJyYXkuIE1heSBiZSBhbiBpbGxlZ2FsIGlucHV0LlxuICovXG5leHBvcnQgY29uc3QgY2FsY3VsYXRlU2l6ZSA9IChkaW1zOiByZWFkb25seSB1bmtub3duW10pOiBudW1iZXIgPT4ge1xuICBsZXQgc2l6ZSA9IDE7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZGltcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGRpbSA9IGRpbXNbaV07XG4gICAgaWYgKHR5cGVvZiBkaW0gIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNTYWZlSW50ZWdlcihkaW0pKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBkaW1zWyR7aX1dIG11c3QgYmUgYW4gaW50ZWdlciwgZ290OiAke2RpbX1gKTtcbiAgICB9XG4gICAgaWYgKGRpbSA8IDApIHtcbiAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGBkaW1zWyR7aX1dIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlciwgZ290OiAke2RpbX1gKTtcbiAgICB9XG4gICAgc2l6ZSAqPSBkaW07XG4gIH1cbiAgcmV0dXJuIHNpemU7XG59O1xuXG4vKipcbiAqIGltcGxlbWVudGF0aW9uIG9mIFRlbnNvci5yZXNoYXBlKClcbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvclJlc2hhcGUgPSAodGVuc29yOiBUZW5zb3IsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yID0+IHtcbiAgc3dpdGNoICh0ZW5zb3IubG9jYXRpb24pIHtcbiAgICBjYXNlICdjcHUnOlxuICAgICAgcmV0dXJuIG5ldyBUZW5zb3IodGVuc29yLnR5cGUsIHRlbnNvci5kYXRhLCBkaW1zKTtcbiAgICBjYXNlICdjcHUtcGlubmVkJzpcbiAgICAgIHJldHVybiBuZXcgVGVuc29yKHtcbiAgICAgICAgbG9jYXRpb246ICdjcHUtcGlubmVkJyxcbiAgICAgICAgZGF0YTogdGVuc29yLmRhdGEgYXMgQ3B1UGlubmVkQ29uc3RydWN0b3JQYXJhbWV0ZXJzWydkYXRhJ10sXG4gICAgICAgIHR5cGU6IHRlbnNvci50eXBlIGFzIENwdVBpbm5lZENvbnN0cnVjdG9yUGFyYW1ldGVyc1sndHlwZSddLFxuICAgICAgICBkaW1zLFxuICAgICAgfSk7XG4gICAgY2FzZSAndGV4dHVyZSc6XG4gICAgICByZXR1cm4gbmV3IFRlbnNvcih7XG4gICAgICAgIGxvY2F0aW9uOiAndGV4dHVyZScsXG4gICAgICAgIHRleHR1cmU6IHRlbnNvci50ZXh0dXJlLFxuICAgICAgICB0eXBlOiB0ZW5zb3IudHlwZSBhcyBUZXh0dXJlQ29uc3RydWN0b3JQYXJhbWV0ZXJzWyd0eXBlJ10sXG4gICAgICAgIGRpbXMsXG4gICAgICB9KTtcbiAgICBjYXNlICdncHUtYnVmZmVyJzpcbiAgICAgIHJldHVybiBuZXcgVGVuc29yKHtcbiAgICAgICAgbG9jYXRpb246ICdncHUtYnVmZmVyJyxcbiAgICAgICAgZ3B1QnVmZmVyOiB0ZW5zb3IuZ3B1QnVmZmVyLFxuICAgICAgICB0eXBlOiB0ZW5zb3IudHlwZSBhcyBHcHVCdWZmZXJDb25zdHJ1Y3RvclBhcmFtZXRlcnNbJ3R5cGUnXSxcbiAgICAgICAgZGltcyxcbiAgICAgIH0pO1xuICAgIGNhc2UgJ21sLXRlbnNvcic6XG4gICAgICByZXR1cm4gbmV3IFRlbnNvcih7XG4gICAgICAgIGxvY2F0aW9uOiAnbWwtdGVuc29yJyxcbiAgICAgICAgbWxUZW5zb3I6IHRlbnNvci5tbFRlbnNvcixcbiAgICAgICAgdHlwZTogdGVuc29yLnR5cGUgYXMgTUxUZW5zb3JDb25zdHJ1Y3RvclBhcmFtZXRlcnNbJ3R5cGUnXSxcbiAgICAgICAgZGltcyxcbiAgICAgIH0pO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHRlbnNvclJlc2hhcGU6IHRlbnNvciBsb2NhdGlvbiAke3RlbnNvci5sb2NhdGlvbn0gaXMgbm90IHN1cHBvcnRlZGApO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyB0ZW5zb3JUb0RhdGFVUkwsIHRlbnNvclRvSW1hZ2VEYXRhIH0gZnJvbSAnLi90ZW5zb3ItY29udmVyc2lvbi1pbXBsLmpzJztcbmltcG9ydCB7IFRlbnNvclRvRGF0YVVybE9wdGlvbnMsIFRlbnNvclRvSW1hZ2VEYXRhT3B0aW9ucyB9IGZyb20gJy4vdGVuc29yLWNvbnZlcnNpb24uanMnO1xuaW1wb3J0IHtcbiAgdGVuc29yRnJvbUdwdUJ1ZmZlcixcbiAgdGVuc29yRnJvbUltYWdlLFxuICB0ZW5zb3JGcm9tTUxUZW5zb3IsXG4gIHRlbnNvckZyb21QaW5uZWRCdWZmZXIsXG4gIHRlbnNvckZyb21UZXh0dXJlLFxufSBmcm9tICcuL3RlbnNvci1mYWN0b3J5LWltcGwuanMnO1xuaW1wb3J0IHtcbiAgQ3B1UGlubmVkQ29uc3RydWN0b3JQYXJhbWV0ZXJzLFxuICBHcHVCdWZmZXJDb25zdHJ1Y3RvclBhcmFtZXRlcnMsXG4gIE1MVGVuc29yQ29uc3RydWN0b3JQYXJhbWV0ZXJzLFxuICBUZW5zb3JGcm9tR3B1QnVmZmVyT3B0aW9ucyxcbiAgVGVuc29yRnJvbUltYWdlQml0bWFwT3B0aW9ucyxcbiAgVGVuc29yRnJvbUltYWdlRGF0YU9wdGlvbnMsXG4gIFRlbnNvckZyb21JbWFnZUVsZW1lbnRPcHRpb25zLFxuICBUZW5zb3JGcm9tTUxUZW5zb3JPcHRpb25zLFxuICBUZW5zb3JGcm9tVGV4dHVyZU9wdGlvbnMsXG4gIFRlbnNvckZyb21VcmxPcHRpb25zLFxuICBUZXh0dXJlQ29uc3RydWN0b3JQYXJhbWV0ZXJzLFxufSBmcm9tICcuL3RlbnNvci1mYWN0b3J5LmpzJztcbmltcG9ydCB7XG4gIGNoZWNrVHlwZWRBcnJheSxcbiAgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUCxcbiAgTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUCxcbiAgU3VwcG9ydGVkVHlwZWRBcnJheSxcbiAgU3VwcG9ydGVkVHlwZWRBcnJheUNvbnN0cnVjdG9ycyxcbn0gZnJvbSAnLi90ZW5zb3ItaW1wbC10eXBlLW1hcHBpbmcuanMnO1xuaW1wb3J0IHsgY2FsY3VsYXRlU2l6ZSwgdGVuc29yUmVzaGFwZSB9IGZyb20gJy4vdGVuc29yLXV0aWxzLWltcGwuanMnO1xuaW1wb3J0IHsgVGVuc29yIGFzIFRlbnNvckludGVyZmFjZSB9IGZyb20gJy4vdGVuc29yLmpzJztcblxuLy8gdHlwZSBhbGlhc2VzIGZvciB0aG9zZSBleHBvcnRlZCBmcm9tIFRlbnNvciBpbnRlcmZhY2VcblxudHlwZSBUZW5zb3JUeXBlID0gVGVuc29ySW50ZXJmYWNlLlR5cGU7XG50eXBlIFRlbnNvckRhdGFUeXBlID0gVGVuc29ySW50ZXJmYWNlLkRhdGFUeXBlO1xudHlwZSBUZW5zb3JEYXRhTG9jYXRpb24gPSBUZW5zb3JJbnRlcmZhY2UuRGF0YUxvY2F0aW9uO1xudHlwZSBUZW5zb3JUZXh0dXJlVHlwZSA9IFRlbnNvckludGVyZmFjZS5UZXh0dXJlVHlwZTtcbnR5cGUgVGVuc29yR3B1QnVmZmVyVHlwZSA9IFRlbnNvckludGVyZmFjZS5HcHVCdWZmZXJUeXBlO1xudHlwZSBUZW5zb3JNTFRlbnNvclR5cGUgPSBUZW5zb3JJbnRlcmZhY2UuTUxUZW5zb3JUeXBlO1xuXG4vKipcbiAqIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IgaW50ZXJmYWNlLlxuICpcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGNsYXNzIFRlbnNvciBpbXBsZW1lbnRzIFRlbnNvckludGVyZmFjZSB7XG4gIC8vICNyZWdpb24gY29uc3RydWN0b3JzXG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBDUFUgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiB0eXBlLCBkYXRhIGFuZCBkaW1zLlxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgdHlwZTogVGVuc29yVHlwZSxcbiAgICBkYXRhOiBUZW5zb3JEYXRhVHlwZSB8IFVpbnQ4Q2xhbXBlZEFycmF5IHwgcmVhZG9ubHkgc3RyaW5nW10gfCByZWFkb25seSBudW1iZXJbXSB8IHJlYWRvbmx5IGJvb2xlYW5bXSxcbiAgICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk7XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgQ1BVIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy4gVHlwZSBpcyBpbmZlcnJlZCBmcm9tIGRhdGEuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBkYXRhOiBUZW5zb3JEYXRhVHlwZSB8IFVpbnQ4Q2xhbXBlZEFycmF5IHwgcmVhZG9ubHkgc3RyaW5nW10gfCByZWFkb25seSBib29sZWFuW10sXG4gICAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuICApO1xuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgcGlubmVkIENQVSBkYXRhIHdpdGggdGhlIGdpdmVuIHR5cGUgYW5kIGRpbXMuXG4gICAqXG4gICAqIFRlbnNvcidzIGxvY2F0aW9uIHdpbGwgYmUgc2V0IHRvICdjcHUtcGlubmVkJy5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFNwZWNpZnkgdGhlIHBhcmFtZXRlcnMgdG8gY29uc3RydWN0IHRoZSB0ZW5zb3IuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihwYXJhbXM6IENwdVBpbm5lZENvbnN0cnVjdG9yUGFyYW1ldGVycyk7XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBXZWJHTCB0ZXh0dXJlIHdpdGggdGhlIGdpdmVuIHR5cGUgYW5kIGRpbXMuXG4gICAqXG4gICAqIFRlbnNvcidzIGxvY2F0aW9uIHdpbGwgYmUgc2V0IHRvICd0ZXh0dXJlJy5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFNwZWNpZnkgdGhlIHBhcmFtZXRlcnMgdG8gY29uc3RydWN0IHRoZSB0ZW5zb3IuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihwYXJhbXM6IFRleHR1cmVDb25zdHJ1Y3RvclBhcmFtZXRlcnMpO1xuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgV2ViR1BVIGJ1ZmZlciB3aXRoIHRoZSBnaXZlbiB0eXBlIGFuZCBkaW1zLlxuICAgKlxuICAgKiBUZW5zb3IncyBsb2NhdGlvbiB3aWxsIGJlIHNldCB0byAnZ3B1LWJ1ZmZlcicuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBTcGVjaWZ5IHRoZSBwYXJhbWV0ZXJzIHRvIGNvbnN0cnVjdCB0aGUgdGVuc29yLlxuICAgKi9cbiAgY29uc3RydWN0b3IocGFyYW1zOiBHcHVCdWZmZXJDb25zdHJ1Y3RvclBhcmFtZXRlcnMpO1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBXZWJOTiBNTFRlbnNvciB3aXRoIHRoZSBnaXZlbiB0eXBlIGFuZCBkaW1zLlxuICAgKlxuICAgKiBUZW5zb3IncyBsb2NhdGlvbiB3aWxsIGJlIHNldCB0byAnbWwtdGVuc29yJy5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFNwZWNpZnkgdGhlIHBhcmFtZXRlcnMgdG8gY29uc3RydWN0IHRoZSB0ZW5zb3IuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihwYXJhbXM6IE1MVGVuc29yQ29uc3RydWN0b3JQYXJhbWV0ZXJzKTtcblxuICAvKipcbiAgICogaW1wbGVtZW50YXRpb24uXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBhcmcwOlxuICAgICAgfCBUZW5zb3JUeXBlXG4gICAgICB8IFRlbnNvckRhdGFUeXBlXG4gICAgICB8IFVpbnQ4Q2xhbXBlZEFycmF5XG4gICAgICB8IHJlYWRvbmx5IHN0cmluZ1tdXG4gICAgICB8IHJlYWRvbmx5IGJvb2xlYW5bXVxuICAgICAgfCBDcHVQaW5uZWRDb25zdHJ1Y3RvclBhcmFtZXRlcnNcbiAgICAgIHwgVGV4dHVyZUNvbnN0cnVjdG9yUGFyYW1ldGVyc1xuICAgICAgfCBHcHVCdWZmZXJDb25zdHJ1Y3RvclBhcmFtZXRlcnNcbiAgICAgIHwgTUxUZW5zb3JDb25zdHJ1Y3RvclBhcmFtZXRlcnMsXG4gICAgYXJnMT86IFRlbnNvckRhdGFUeXBlIHwgVWludDhDbGFtcGVkQXJyYXkgfCByZWFkb25seSBudW1iZXJbXSB8IHJlYWRvbmx5IHN0cmluZ1tdIHwgcmVhZG9ubHkgYm9vbGVhbltdLFxuICAgIGFyZzI/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKSB7XG4gICAgLy8gcGVyZm9ybSBvbmUtdGltZSBjaGVjayBmb3IgQmlnSW50L0Zsb2F0MTZBcnJheSBzdXBwb3J0XG4gICAgY2hlY2tUeXBlZEFycmF5KCk7XG5cbiAgICBsZXQgdHlwZTogVGVuc29yVHlwZTtcbiAgICBsZXQgZGltczogcmVhZG9ubHkgbnVtYmVyW107XG5cbiAgICBpZiAodHlwZW9mIGFyZzAgPT09ICdvYmplY3QnICYmICdsb2NhdGlvbicgaW4gYXJnMCkge1xuICAgICAgLy9cbiAgICAgIC8vIGNvbnN0cnVjdGluZyB0ZW5zb3IgZnJvbSBzcGVjaWZpYyBsb2NhdGlvblxuICAgICAgLy9cbiAgICAgIHRoaXMuZGF0YUxvY2F0aW9uID0gYXJnMC5sb2NhdGlvbjtcbiAgICAgIHR5cGUgPSBhcmcwLnR5cGU7XG4gICAgICBkaW1zID0gYXJnMC5kaW1zO1xuICAgICAgc3dpdGNoIChhcmcwLmxvY2F0aW9uKSB7XG4gICAgICAgIGNhc2UgJ2NwdS1waW5uZWQnOiB7XG4gICAgICAgICAgY29uc3QgZXhwZWN0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3IgPSBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQLmdldCh0eXBlKTtcbiAgICAgICAgICBpZiAoIWV4cGVjdGVkVHlwZWRBcnJheUNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGB1bnN1cHBvcnRlZCB0eXBlIFwiJHt0eXBlfVwiIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSBwaW5uZWQgYnVmZmVyYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghKGFyZzAuZGF0YSBpbnN0YW5jZW9mIGV4cGVjdGVkVHlwZWRBcnJheUNvbnN0cnVjdG9yKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgYnVmZmVyIHNob3VsZCBiZSBvZiB0eXBlICR7ZXhwZWN0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3IubmFtZX1gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5jcHVEYXRhID0gYXJnMC5kYXRhO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ3RleHR1cmUnOiB7XG4gICAgICAgICAgaWYgKHR5cGUgIT09ICdmbG9hdDMyJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZSBcIiR7dHlwZX1cIiB0byBjcmVhdGUgdGVuc29yIGZyb20gdGV4dHVyZWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmdwdVRleHR1cmVEYXRhID0gYXJnMC50ZXh0dXJlO1xuICAgICAgICAgIHRoaXMuZG93bmxvYWRlciA9IGFyZzAuZG93bmxvYWQ7XG4gICAgICAgICAgdGhpcy5kaXNwb3NlciA9IGFyZzAuZGlzcG9zZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdncHUtYnVmZmVyJzoge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHR5cGUgIT09ICdmbG9hdDMyJyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2Zsb2F0MTYnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnaW50MzInICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnaW50NjQnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAndWludDMyJyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ3VpbnQ4JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2Jvb2wnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAndWludDQnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnaW50NCdcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgXCIke3R5cGV9XCIgdG8gY3JlYXRlIHRlbnNvciBmcm9tIGdwdSBidWZmZXJgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5ncHVCdWZmZXJEYXRhID0gYXJnMC5ncHVCdWZmZXI7XG4gICAgICAgICAgdGhpcy5kb3dubG9hZGVyID0gYXJnMC5kb3dubG9hZDtcbiAgICAgICAgICB0aGlzLmRpc3Bvc2VyID0gYXJnMC5kaXNwb3NlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ21sLXRlbnNvcic6IHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICB0eXBlICE9PSAnZmxvYXQzMicgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdmbG9hdDE2JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2ludDMyJyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2ludDY0JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ3VpbnQzMicgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICd1aW50NjQnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnaW50OCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICd1aW50OCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdib29sJyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ3VpbnQ0JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2ludDQnXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGB1bnN1cHBvcnRlZCB0eXBlIFwiJHt0eXBlfVwiIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSBNTFRlbnNvcmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLm1sVGVuc29yRGF0YSA9IGFyZzAubWxUZW5zb3I7XG4gICAgICAgICAgdGhpcy5kb3dubG9hZGVyID0gYXJnMC5kb3dubG9hZDtcbiAgICAgICAgICB0aGlzLmRpc3Bvc2VyID0gYXJnMC5kaXNwb3NlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5zb3IgY29uc3RydWN0b3I6IHVuc3VwcG9ydGVkIGxvY2F0aW9uICcke3RoaXMuZGF0YUxvY2F0aW9ufSdgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy9cbiAgICAgIC8vIGNvbnN0cnVjdGluZyB0ZW5zb3Igb2YgbG9jYXRpb24gJ2NwdSdcbiAgICAgIC8vXG4gICAgICBsZXQgZGF0YTogVGVuc29yRGF0YVR5cGU7XG4gICAgICBsZXQgbWF5YmVEaW1zOiB0eXBlb2YgYXJnMSB8IHR5cGVvZiBhcmcyO1xuICAgICAgLy8gY2hlY2sgd2hldGhlciBhcmcwIGlzIHR5cGUgb3IgZGF0YVxuICAgICAgaWYgKHR5cGVvZiBhcmcwID09PSAnc3RyaW5nJykge1xuICAgICAgICAvL1xuICAgICAgICAvLyBPdmVycmlkZTogY29uc3RydWN0b3IodHlwZSwgZGF0YSwgLi4uKVxuICAgICAgICAvL1xuICAgICAgICB0eXBlID0gYXJnMDtcbiAgICAgICAgbWF5YmVEaW1zID0gYXJnMjtcbiAgICAgICAgaWYgKGFyZzAgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgLy8gc3RyaW5nIHRlbnNvclxuICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShhcmcxKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkEgc3RyaW5nIHRlbnNvcidzIGRhdGEgbXVzdCBiZSBhIHN0cmluZyBhcnJheS5cIik7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIHdlIGRvbid0IGNoZWNrIHdoZXRoZXIgZXZlcnkgZWxlbWVudCBpbiB0aGUgYXJyYXkgaXMgc3RyaW5nOyB0aGlzIGlzIHRvbyBzbG93LiB3ZSBhc3N1bWUgaXQncyBjb3JyZWN0IGFuZFxuICAgICAgICAgIC8vIGVycm9yIHdpbGwgYmUgcG9wdWxhdGVkIGF0IGluZmVyZW5jZVxuICAgICAgICAgIGRhdGEgPSBhcmcxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIG51bWVyaWMgdGVuc29yXG4gICAgICAgICAgY29uc3QgdHlwZWRBcnJheUNvbnN0cnVjdG9yID0gTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5nZXQoYXJnMCk7XG4gICAgICAgICAgaWYgKHR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBVbnN1cHBvcnRlZCB0ZW5zb3IgdHlwZTogJHthcmcwfS5gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYXJnMSkpIHtcbiAgICAgICAgICAgIGlmICgoYXJnMCA9PT0gJ2Zsb2F0MTYnICYmIHR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9PT0gVWludDE2QXJyYXkpIHx8IGFyZzAgPT09ICd1aW50NCcgfHwgYXJnMCA9PT0gJ2ludDQnKSB7XG4gICAgICAgICAgICAgIC8vIC0gJ2Zsb2F0MTYnOlxuICAgICAgICAgICAgICAvLyAgIFdoZW4gbm8gRmxvYXQxNkFycmF5IHBvbHlmaWxsIGlzIHVzZWQsIHdlIGNhbm5vdCBjcmVhdGUgJ2Zsb2F0MTYnIHRlbnNvciBmcm9tIG51bWJlciBhcnJheS5cbiAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgLy8gICBUaHJvdyBlcnJvciBoZXJlIGJlY2F1c2Ugd2hlbiB1c2VyIHRyeSB0byB1c2UgbnVtYmVyIGFycmF5IGFzIGRhdGEsXG4gICAgICAgICAgICAgIC8vICAgZS5nLiBuZXcgVGVuc29yKCdmbG9hdDE2JywgWzEsIDIsIDMsIDRdLCBkaW1zKSksIGl0IHdpbGwgYWN0dWFsbHkgY2FsbFxuICAgICAgICAgICAgICAvLyAgIFVpbnQxNkFycmF5LmZyb20oYXJnMSkgd2hpY2ggZ2VuZXJhdGVzIHdyb25nIGRhdGEuXG4gICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgIC8vIC0gJ3VpbnQ0JyBhbmQgJ2ludDQnOlxuICAgICAgICAgICAgICAvLyAgIFVpbnQ4QXJyYXkuZnJvbShhcmcxKSB3aWxsIGdlbmVyYXRlIHdyb25nIGRhdGEgZm9yICd1aW50NCcgYW5kICdpbnQ0JyB0ZW5zb3IuXG4gICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICAgICAgYENyZWF0aW5nIGEgJHthcmcwfSB0ZW5zb3IgZnJvbSBudW1iZXIgYXJyYXkgaXMgbm90IHN1cHBvcnRlZC4gUGxlYXNlIHVzZSAke3R5cGVkQXJyYXlDb25zdHJ1Y3Rvci5uYW1lfSBhcyBkYXRhLmAsXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFyZzAgPT09ICd1aW50NjQnIHx8IGFyZzAgPT09ICdpbnQ2NCcpIHtcbiAgICAgICAgICAgICAgLy8gdXNlICdhcyBhbnknIGhlcmUgYmVjYXVzZTpcbiAgICAgICAgICAgICAgLy8gMS4gVHlwZVNjcmlwdCdzIGNoZWNrIG9uIHR5cGUgb2YgJ0FycmF5LmlzQXJyYXkoKScgZG9lcyBub3Qgd29yayB3aXRoIHJlYWRvbmx5IGFycmF5cy5cbiAgICAgICAgICAgICAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9taWNyb3NvZnQvVHlwZVNjcmlwdC9pc3N1ZXMvMTcwMDJcbiAgICAgICAgICAgICAgLy8gMi4gVHlwZVNjcmlwdCdzIGNoZWNrIG9uIHVuaW9uIHR5cGUgb2YgJyhCaWdJbnQ2NEFycmF5Q29uc3RydWN0b3J8QmlnVWludDY0QXJyYXlDb25zdHJ1Y3RvcikuZnJvbSgpJ1xuICAgICAgICAgICAgICAvLyBkb2VzIG5vdCBhY2NlcHQgcGFyYW1ldGVyIG1hcEZuLlxuICAgICAgICAgICAgICAvLyAzLiBwYXJhbWV0ZXJzIG9mICdTdXBwb3J0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3JzLmZyb20oKScgZG9lcyBub3QgbWF0Y2ggdGhlIHJlcXVpcmVtZW50IG9mIHRoZSB1bmlvblxuICAgICAgICAgICAgICAvLyB0eXBlLlxuXG4gICAgICAgICAgICAgIC8vIGFzc3VtZSAnYXJnMScgaXMgb2YgdHlwZSBcInJlYWRvbmx5IG51bWJlcltdfHJlYWRvbmx5IGJpZ2ludFtdXCIgaGVyZS5cblxuICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgICAgICBkYXRhID0gKHR5cGVkQXJyYXlDb25zdHJ1Y3RvciBhcyBhbnkpLmZyb20oYXJnMSwgQmlnSW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIGFzc3VtZSAnYXJnMScgaXMgb2YgdHlwZSBcInJlYWRvbmx5IG51bWJlcltdXCIgaGVyZS5cbiAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAgICAgZGF0YSA9ICh0eXBlZEFycmF5Q29uc3RydWN0b3IgYXMgYW55KS5mcm9tKGFyZzEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoYXJnMSBpbnN0YW5jZW9mIHR5cGVkQXJyYXlDb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgZGF0YSA9IGFyZzE7XG4gICAgICAgICAgfSBlbHNlIGlmIChhcmcxIGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXkpIHtcbiAgICAgICAgICAgIGlmIChhcmcwID09PSAndWludDgnKSB7XG4gICAgICAgICAgICAgIGRhdGEgPSBVaW50OEFycmF5LmZyb20oYXJnMSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBBIFVpbnQ4Q2xhbXBlZEFycmF5IHRlbnNvcidzIGRhdGEgbXVzdCBiZSB0eXBlIG9mIHVpbnQ4YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChhcmcwID09PSAnZmxvYXQxNicgJiYgYXJnMSBpbnN0YW5jZW9mIFVpbnQxNkFycmF5ICYmIHR5cGVkQXJyYXlDb25zdHJ1Y3RvciAhPT0gVWludDE2QXJyYXkpIHtcbiAgICAgICAgICAgIC8vIHdoZW4gRmxvYXQxNkFycmF5IGlzIGF2YWlsYWJsZSBhbmQgZGF0YSBpcyBvZiB0eXBlIFVpbnQxNkFycmF5LlxuICAgICAgICAgICAgLy8gV2UgYWxsb3cgVWludDE2QXJyYXkgdG8gYmUgcGFzc2VkIGluIGFzIGRhdGEgZm9yICdmbG9hdDE2JyB0ZW5zb3IgdW50aWwgRmxvYXQxNkFycmF5IGlzIGdlbmVyYWxseVxuICAgICAgICAgICAgLy8gc3VwcG9ydGVkIGluIEphdmFTY3JpcHQgZW52aXJvbm1lbnQuXG5cbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICBkYXRhID0gbmV3IChnbG9iYWxUaGlzIGFzIGFueSkuRmxvYXQxNkFycmF5KGFyZzEuYnVmZmVyLCBhcmcxLmJ5dGVPZmZzZXQsIGFyZzEubGVuZ3RoKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgQSAke3R5cGV9IHRlbnNvcidzIGRhdGEgbXVzdCBiZSB0eXBlIG9mICR7dHlwZWRBcnJheUNvbnN0cnVjdG9yfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy9cbiAgICAgICAgLy8gT3ZlcnJpZGU6IGNvbnN0cnVjdG9yKGRhdGEsIC4uLilcbiAgICAgICAgLy9cbiAgICAgICAgbWF5YmVEaW1zID0gYXJnMTtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYXJnMCkpIHtcbiAgICAgICAgICAvLyBvbmx5IGJvb2xlYW5bXSBhbmQgc3RyaW5nW10gaXMgc3VwcG9ydGVkXG4gICAgICAgICAgaWYgKGFyZzAubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUZW5zb3IgdHlwZSBjYW5ub3QgYmUgaW5mZXJyZWQgZnJvbSBhbiBlbXB0eSBhcnJheS4nKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgZmlyc3RFbGVtZW50VHlwZSA9IHR5cGVvZiBhcmcwWzBdO1xuICAgICAgICAgIGlmIChmaXJzdEVsZW1lbnRUeXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdHlwZSA9ICdzdHJpbmcnO1xuICAgICAgICAgICAgZGF0YSA9IGFyZzA7XG4gICAgICAgICAgfSBlbHNlIGlmIChmaXJzdEVsZW1lbnRUeXBlID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIHR5cGUgPSAnYm9vbCc7XG4gICAgICAgICAgICAvLyAnYXJnMCcgaXMgb2YgdHlwZSAnYm9vbGVhbltdJy4gVWludDhBcnJheS5mcm9tKGJvb2xlYW5bXSkgYWN0dWFsbHkgd29ya3MsIGJ1dCB0eXBlc2NyaXB0IHRoaW5rcyB0aGlzIGlzXG4gICAgICAgICAgICAvLyB3cm9uZyB0eXBlLiBXZSB1c2UgJ2FzIGFueScgdG8gbWFrZSBpdCBoYXBweS5cbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICBkYXRhID0gVWludDhBcnJheS5mcm9tKGFyZzAgYXMgYW55W10pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBJbnZhbGlkIGVsZW1lbnQgdHlwZSBvZiBkYXRhIGFycmF5OiAke2ZpcnN0RWxlbWVudFR5cGV9LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChhcmcwIGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXkpIHtcbiAgICAgICAgICB0eXBlID0gJ3VpbnQ4JztcbiAgICAgICAgICBkYXRhID0gVWludDhBcnJheS5mcm9tKGFyZzApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGdldCB0ZW5zb3IgdHlwZSBmcm9tIFR5cGVkQXJyYXlcbiAgICAgICAgICBjb25zdCBtYXBwZWRUeXBlID0gTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUC5nZXQoXG4gICAgICAgICAgICBhcmcwLmNvbnN0cnVjdG9yIGFzIFN1cHBvcnRlZFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnMsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAobWFwcGVkVHlwZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBVbnN1cHBvcnRlZCB0eXBlIGZvciB0ZW5zb3IgZGF0YTogJHthcmcwLmNvbnN0cnVjdG9yfS5gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdHlwZSA9IG1hcHBlZFR5cGU7XG4gICAgICAgICAgZGF0YSA9IGFyZzAgYXMgU3VwcG9ydGVkVHlwZWRBcnJheTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyB0eXBlIGFuZCBkYXRhIGlzIHByb2Nlc3NlZCwgbm93IHByb2Nlc3NpbmcgZGltc1xuICAgICAgaWYgKG1heWJlRGltcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIGFzc3VtZSAxLUQgdGVuc29yIGlmIGRpbXMgb21pdHRlZFxuICAgICAgICBtYXliZURpbXMgPSBbZGF0YS5sZW5ndGhdO1xuICAgICAgfSBlbHNlIGlmICghQXJyYXkuaXNBcnJheShtYXliZURpbXMpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJBIHRlbnNvcidzIGRpbXMgbXVzdCBiZSBhIG51bWJlciBhcnJheVwiKTtcbiAgICAgIH1cbiAgICAgIGRpbXMgPSBtYXliZURpbXMgYXMgcmVhZG9ubHkgbnVtYmVyW107XG5cbiAgICAgIHRoaXMuY3B1RGF0YSA9IGRhdGE7XG4gICAgICB0aGlzLmRhdGFMb2NhdGlvbiA9ICdjcHUnO1xuICAgIH1cblxuICAgIC8vIHBlcmZvcm0gY2hlY2sgb24gZGltc1xuICAgIGNvbnN0IHNpemUgPSBjYWxjdWxhdGVTaXplKGRpbXMpO1xuICAgIC8vIGlmIGRhdGEgaXMgb24gQ1BVLCBjaGVjayB3aGV0aGVyIGRhdGEgbGVuZ3RoIG1hdGNoZXMgdGVuc29yIHNpemVcbiAgICBpZiAodGhpcy5jcHVEYXRhICYmIHNpemUgIT09IHRoaXMuY3B1RGF0YS5sZW5ndGgpIHtcbiAgICAgIGlmICgodHlwZSA9PT0gJ3VpbnQ0JyB8fCB0eXBlID09PSAnaW50NCcpICYmIE1hdGguY2VpbChzaXplIC8gMikgPT09IHRoaXMuY3B1RGF0YS5sZW5ndGgpIHtcbiAgICAgICAgLy8gZm9yICh1KWludDQsIHRoZSBkYXRhIGxlbmd0aCBpcyBoYWxmIG9mIHRoZSB0ZW5zb3Igc2l6ZS4gU28gd2UgY2hlY2sgdGhpcyBzcGVjaWFsIGNhc2Ugd2hlbiBzaXplIGlzIG9kZC5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVGVuc29yJ3Mgc2l6ZSgke3NpemV9KSBkb2VzIG5vdCBtYXRjaCBkYXRhIGxlbmd0aCgke3RoaXMuY3B1RGF0YS5sZW5ndGh9KS5gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMuZGltcyA9IGRpbXM7XG4gICAgdGhpcy5zaXplID0gc2l6ZTtcbiAgfVxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBmYWN0b3J5XG4gIHN0YXRpYyBhc3luYyBmcm9tSW1hZ2UoXG4gICAgaW1hZ2U6IEltYWdlRGF0YSB8IEhUTUxJbWFnZUVsZW1lbnQgfCBJbWFnZUJpdG1hcCB8IHN0cmluZyxcbiAgICBvcHRpb25zPzpcbiAgICAgIHwgVGVuc29yRnJvbUltYWdlRGF0YU9wdGlvbnNcbiAgICAgIHwgVGVuc29yRnJvbUltYWdlRWxlbWVudE9wdGlvbnNcbiAgICAgIHwgVGVuc29yRnJvbUltYWdlQml0bWFwT3B0aW9uc1xuICAgICAgfCBUZW5zb3JGcm9tVXJsT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxUZW5zb3JJbnRlcmZhY2U+IHtcbiAgICByZXR1cm4gdGVuc29yRnJvbUltYWdlKGltYWdlLCBvcHRpb25zKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tVGV4dHVyZTxUIGV4dGVuZHMgVGVuc29ySW50ZXJmYWNlLlRleHR1cmVEYXRhVHlwZXM+KFxuICAgIHRleHR1cmU6IFRlbnNvclRleHR1cmVUeXBlLFxuICAgIG9wdGlvbnM6IFRlbnNvckZyb21UZXh0dXJlT3B0aW9uczxUPixcbiAgKTogVGVuc29ySW50ZXJmYWNlIHtcbiAgICByZXR1cm4gdGVuc29yRnJvbVRleHR1cmUodGV4dHVyZSwgb3B0aW9ucyk7XG4gIH1cblxuICBzdGF0aWMgZnJvbUdwdUJ1ZmZlcjxUIGV4dGVuZHMgVGVuc29ySW50ZXJmYWNlLkdwdUJ1ZmZlckRhdGFUeXBlcz4oXG4gICAgZ3B1QnVmZmVyOiBUZW5zb3JHcHVCdWZmZXJUeXBlLFxuICAgIG9wdGlvbnM6IFRlbnNvckZyb21HcHVCdWZmZXJPcHRpb25zPFQ+LFxuICApOiBUZW5zb3JJbnRlcmZhY2Uge1xuICAgIHJldHVybiB0ZW5zb3JGcm9tR3B1QnVmZmVyKGdwdUJ1ZmZlciwgb3B0aW9ucyk7XG4gIH1cblxuICBzdGF0aWMgZnJvbU1MVGVuc29yPFQgZXh0ZW5kcyBUZW5zb3JJbnRlcmZhY2UuTUxUZW5zb3JEYXRhVHlwZXM+KFxuICAgIG1sVGVuc29yOiBUZW5zb3JNTFRlbnNvclR5cGUsXG4gICAgb3B0aW9uczogVGVuc29yRnJvbU1MVGVuc29yT3B0aW9uczxUPixcbiAgKTogVGVuc29ySW50ZXJmYWNlIHtcbiAgICByZXR1cm4gdGVuc29yRnJvbU1MVGVuc29yKG1sVGVuc29yLCBvcHRpb25zKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tUGlubmVkQnVmZmVyPFQgZXh0ZW5kcyBUZW5zb3JJbnRlcmZhY2UuQ3B1UGlubmVkRGF0YVR5cGVzPihcbiAgICB0eXBlOiBULFxuICAgIGJ1ZmZlcjogVGVuc29ySW50ZXJmYWNlLkRhdGFUeXBlTWFwW1RdLFxuICAgIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogVGVuc29yIHtcbiAgICByZXR1cm4gdGVuc29yRnJvbVBpbm5lZEJ1ZmZlcih0eXBlLCBidWZmZXIsIGRpbXMpO1xuICB9XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gY29udmVyc2lvbnNcbiAgdG9EYXRhVVJMKG9wdGlvbnM/OiBUZW5zb3JUb0RhdGFVcmxPcHRpb25zKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGVuc29yVG9EYXRhVVJMKHRoaXMsIG9wdGlvbnMpO1xuICB9XG5cbiAgdG9JbWFnZURhdGEob3B0aW9ucz86IFRlbnNvclRvSW1hZ2VEYXRhT3B0aW9ucyk6IEltYWdlRGF0YSB7XG4gICAgcmV0dXJuIHRlbnNvclRvSW1hZ2VEYXRhKHRoaXMsIG9wdGlvbnMpO1xuICB9XG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIHB1YmxpYyBmaWVsZHNcbiAgcmVhZG9ubHkgZGltczogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IHR5cGU6IFRlbnNvclR5cGU7XG4gIHJlYWRvbmx5IHNpemU6IG51bWJlcjtcbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gcHJpdmF0ZSBmaWVsZHNcblxuICAvKipcbiAgICogc3RvcmVzIHRoZSBsb2NhdGlvbiBvZiB0aGUgZGF0YS5cbiAgICovXG4gIHByaXZhdGUgZGF0YUxvY2F0aW9uOiBUZW5zb3JEYXRhTG9jYXRpb247XG5cbiAgLyoqXG4gICAqIHN0b3JlcyB0aGUgZGF0YSBvbiBDUFUsIGlmIGxvY2F0aW9uIGlzICdjcHUnIG9yICdjcHUtcGlubmVkJy4gb3RoZXJ3aXNlIGVtcHR5LlxuICAgKi9cbiAgcHJpdmF0ZSBjcHVEYXRhPzogVGVuc29yRGF0YVR5cGU7XG5cbiAgLyoqXG4gICAqIHN0b3JlcyB0aGUgdW5kZXJseWluZyB0ZXh0dXJlIHdoZW4gbG9jYXRpb24gaXMgJ3RleHR1cmUnLiBvdGhlcndpc2UgZW1wdHkuXG4gICAqL1xuICBwcml2YXRlIGdwdVRleHR1cmVEYXRhPzogVGVuc29yVGV4dHVyZVR5cGU7XG5cbiAgLyoqXG4gICAqIHN0b3JlcyB0aGUgdW5kZXJseWluZyBHUFUgYnVmZmVyIHdoZW4gbG9jYXRpb24gaXMgJ2dwdS1idWZmZXInLiBvdGhlcndpc2UgZW1wdHkuXG4gICAqL1xuICBwcml2YXRlIGdwdUJ1ZmZlckRhdGE/OiBUZW5zb3JHcHVCdWZmZXJUeXBlO1xuXG4gIC8qKlxuICAgKiBzdG9yZXMgdGhlIHVuZGVybHlpbmcgV2ViTk4gTUxUZW5zb3Igd2hlbiBsb2NhdGlvbiBpcyAnbWwtdGVuc29yJy4gb3RoZXJ3aXNlIGVtcHR5LlxuICAgKi9cbiAgcHJpdmF0ZSBtbFRlbnNvckRhdGE/OiBUZW5zb3JNTFRlbnNvclR5cGU7XG5cbiAgLyoqXG4gICAqIHN0b3JlcyBhbiBvcHRpb25hbCBkb3dubG9hZGVyIGZ1bmN0aW9uIHRvIGRvd25sb2FkIGRhdGEgZnJvbSBHUFUgdG8gQ1BVLlxuICAgKi9cbiAgcHJpdmF0ZSBkb3dubG9hZGVyPygpOiBQcm9taXNlPFRlbnNvckRhdGFUeXBlPjtcblxuICAvKipcbiAgICogYSBmbGFnIGluZGljYXRpbmcgd2hldGhlciB0aGUgZGF0YSBpcyBiZWluZyBkb3dubG9hZGVkIGZyb20gR1BVIHRvIENQVS5cbiAgICovXG4gIHByaXZhdGUgaXNEb3dubG9hZGluZz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIHN0b3JlcyBhbiBvcHRpb25hbCBkaXNwb3NlciBmdW5jdGlvbiB0byBkaXNwb3NlIHRoZSB1bmRlcmx5aW5nIGRhdGEuXG4gICAqL1xuICBwcml2YXRlIGRpc3Bvc2VyPygpOiB2b2lkO1xuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBwcm9wZXJ0aWVzXG4gIGdldCBkYXRhKCk6IFRlbnNvckRhdGFUeXBlIHtcbiAgICB0aGlzLmVuc3VyZVZhbGlkKCk7XG4gICAgaWYgKCF0aGlzLmNwdURhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ1RoZSBkYXRhIGlzIG5vdCBvbiBDUFUuIFVzZSBgZ2V0RGF0YSgpYCB0byBkb3dubG9hZCBHUFUgZGF0YSB0byBDUFUsICcgK1xuICAgICAgICAgICdvciB1c2UgYHRleHR1cmVgIG9yIGBncHVCdWZmZXJgIHByb3BlcnR5IHRvIGFjY2VzcyB0aGUgR1BVIGRhdGEgZGlyZWN0bHkuJyxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmNwdURhdGE7XG4gIH1cblxuICBnZXQgbG9jYXRpb24oKTogVGVuc29yRGF0YUxvY2F0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhTG9jYXRpb247XG4gIH1cblxuICBnZXQgdGV4dHVyZSgpOiBUZW5zb3JUZXh0dXJlVHlwZSB7XG4gICAgdGhpcy5lbnN1cmVWYWxpZCgpO1xuICAgIGlmICghdGhpcy5ncHVUZXh0dXJlRGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR0wgdGV4dHVyZS4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ3B1VGV4dHVyZURhdGE7XG4gIH1cblxuICBnZXQgZ3B1QnVmZmVyKCk6IFRlbnNvckdwdUJ1ZmZlclR5cGUge1xuICAgIHRoaXMuZW5zdXJlVmFsaWQoKTtcbiAgICBpZiAoIXRoaXMuZ3B1QnVmZmVyRGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgZGF0YSBpcyBub3Qgc3RvcmVkIGFzIGEgV2ViR1BVIGJ1ZmZlci4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ3B1QnVmZmVyRGF0YTtcbiAgfVxuXG4gIGdldCBtbFRlbnNvcigpOiBUZW5zb3JNTFRlbnNvclR5cGUge1xuICAgIHRoaXMuZW5zdXJlVmFsaWQoKTtcbiAgICBpZiAoIXRoaXMubWxUZW5zb3JEYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBkYXRhIGlzIG5vdCBzdG9yZWQgYXMgYSBXZWJOTiBNTFRlbnNvci4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubWxUZW5zb3JEYXRhO1xuICB9XG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIG1ldGhvZHNcblxuICBhc3luYyBnZXREYXRhKHJlbGVhc2VEYXRhPzogYm9vbGVhbik6IFByb21pc2U8VGVuc29yRGF0YVR5cGU+IHtcbiAgICB0aGlzLmVuc3VyZVZhbGlkKCk7XG4gICAgc3dpdGNoICh0aGlzLmRhdGFMb2NhdGlvbikge1xuICAgICAgY2FzZSAnY3B1JzpcbiAgICAgIGNhc2UgJ2NwdS1waW5uZWQnOlxuICAgICAgICByZXR1cm4gdGhpcy5kYXRhO1xuICAgICAgY2FzZSAndGV4dHVyZSc6XG4gICAgICBjYXNlICdncHUtYnVmZmVyJzpcbiAgICAgIGNhc2UgJ21sLXRlbnNvcic6IHtcbiAgICAgICAgaWYgKCF0aGlzLmRvd25sb2FkZXIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjdXJyZW50IHRlbnNvciBpcyBub3QgY3JlYXRlZCB3aXRoIGEgc3BlY2lmaWVkIGRhdGEgZG93bmxvYWRlci4nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc0Rvd25sb2FkaW5nKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgY3VycmVudCB0ZW5zb3IgaXMgYmVpbmcgZG93bmxvYWRlZC4nKTtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgIHRoaXMuaXNEb3dubG9hZGluZyA9IHRydWU7XG4gICAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuZG93bmxvYWRlcigpO1xuICAgICAgICAgIHRoaXMuZG93bmxvYWRlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB0aGlzLmRhdGFMb2NhdGlvbiA9ICdjcHUnO1xuICAgICAgICAgIHRoaXMuY3B1RGF0YSA9IGRhdGE7XG5cbiAgICAgICAgICBpZiAocmVsZWFzZURhdGEgJiYgdGhpcy5kaXNwb3Nlcikge1xuICAgICAgICAgICAgdGhpcy5kaXNwb3NlcigpO1xuICAgICAgICAgICAgdGhpcy5kaXNwb3NlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICB0aGlzLmlzRG93bmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgZ2V0IGRhdGEgZnJvbSBsb2NhdGlvbjogJHt0aGlzLmRhdGFMb2NhdGlvbn1gKTtcbiAgICB9XG4gIH1cblxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzRG93bmxvYWRpbmcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGN1cnJlbnQgdGVuc29yIGlzIGJlaW5nIGRvd25sb2FkZWQuJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZGlzcG9zZXIpIHtcbiAgICAgIHRoaXMuZGlzcG9zZXIoKTtcbiAgICAgIHRoaXMuZGlzcG9zZXIgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRoaXMuY3B1RGF0YSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmdwdVRleHR1cmVEYXRhID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuZ3B1QnVmZmVyRGF0YSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm1sVGVuc29yRGF0YSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmRvd25sb2FkZXIgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5pc0Rvd25sb2FkaW5nID0gdW5kZWZpbmVkO1xuXG4gICAgdGhpcy5kYXRhTG9jYXRpb24gPSAnbm9uZSc7XG4gIH1cblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiB0ZW5zb3IgdXRpbGl0aWVzXG4gIHByaXZhdGUgZW5zdXJlVmFsaWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGF0YUxvY2F0aW9uID09PSAnbm9uZScpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIHRlbnNvciBpcyBkaXNwb3NlZC4nKTtcbiAgICB9XG4gIH1cblxuICByZXNoYXBlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29ySW50ZXJmYWNlIHtcbiAgICB0aGlzLmVuc3VyZVZhbGlkKCk7XG4gICAgaWYgKHRoaXMuZG93bmxvYWRlciB8fCB0aGlzLmRpc3Bvc2VyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCByZXNoYXBlIGEgdGVuc29yIHRoYXQgb3ducyBHUFUgcmVzb3VyY2UuJyk7XG4gICAgfVxuICAgIHJldHVybiB0ZW5zb3JSZXNoYXBlKHRoaXMsIGRpbXMpO1xuICB9XG4gIC8vICNlbmRyZWdpb25cbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yRmFjdG9yeSB9IGZyb20gJy4vdGVuc29yLWZhY3RvcnkuanMnO1xuaW1wb3J0IHsgVGVuc29yIGFzIFRlbnNvckltcGwgfSBmcm9tICcuL3RlbnNvci1pbXBsLmpzJztcbmltcG9ydCB7IFR5cGVkVGVuc29yVXRpbHMgfSBmcm9tICcuL3RlbnNvci11dGlscy5qcyc7XG5pbXBvcnQgeyBUcnlHZXRHbG9iYWxUeXBlIH0gZnJvbSAnLi90eXBlLWhlbHBlci5qcyc7XG5cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZWRlY2xhcmUgKi9cblxuLyoqXG4gKiByZXByZXNlbnQgYSBiYXNpYyB0ZW5zb3Igd2l0aCBzcGVjaWZpZWQgZGltZW5zaW9ucyBhbmQgZGF0YSB0eXBlLlxuICovXG5pbnRlcmZhY2UgVHlwZWRUZW5zb3JCYXNlPFQgZXh0ZW5kcyBUZW5zb3IuVHlwZT4ge1xuICAvKipcbiAgICogR2V0IHRoZSBkaW1lbnNpb25zIG9mIHRoZSB0ZW5zb3IuXG4gICAqL1xuICByZWFkb25seSBkaW1zOiByZWFkb25seSBudW1iZXJbXTtcbiAgLyoqXG4gICAqIEdldCB0aGUgZGF0YSB0eXBlIG9mIHRoZSB0ZW5zb3IuXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBUO1xuICAvKipcbiAgICogR2V0IHRoZSBidWZmZXIgZGF0YSBvZiB0aGUgdGVuc29yLlxuICAgKlxuICAgKiBJZiB0aGUgZGF0YSBpcyBub3Qgb24gQ1BVIChlZy4gaXQncyBpbiB0aGUgZm9ybSBvZiBXZWJHTCB0ZXh0dXJlIG9yIFdlYkdQVSBidWZmZXIpLCB0aHJvdyBlcnJvci5cbiAgICovXG4gIHJlYWRvbmx5IGRhdGE6IFRlbnNvci5EYXRhVHlwZU1hcFtUXTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbG9jYXRpb24gb2YgdGhlIGRhdGEuXG4gICAqL1xuICByZWFkb25seSBsb2NhdGlvbjogVGVuc29yLkRhdGFMb2NhdGlvbjtcbiAgLyoqXG4gICAqIEdldCB0aGUgV2ViR0wgdGV4dHVyZSB0aGF0IGhvbGRzIHRoZSB0ZW5zb3IgZGF0YS5cbiAgICpcbiAgICogSWYgdGhlIGRhdGEgaXMgbm90IG9uIEdQVSBhcyBXZWJHTCB0ZXh0dXJlLCB0aHJvdyBlcnJvci5cbiAgICovXG4gIHJlYWRvbmx5IHRleHR1cmU6IFRlbnNvci5UZXh0dXJlVHlwZTtcbiAgLyoqXG4gICAqIEdldCB0aGUgV2ViR1BVIGJ1ZmZlciB0aGF0IGhvbGRzIHRoZSB0ZW5zb3IgZGF0YS5cbiAgICpcbiAgICogSWYgdGhlIGRhdGEgaXMgbm90IG9uIEdQVSBhcyBXZWJHUFUgYnVmZmVyLCB0aHJvdyBlcnJvci5cbiAgICovXG4gIHJlYWRvbmx5IGdwdUJ1ZmZlcjogVGVuc29yLkdwdUJ1ZmZlclR5cGU7XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgV2ViTk4gTUxUZW5zb3IgdGhhdCBob2xkcyB0aGUgdGVuc29yIGRhdGEuXG4gICAqXG4gICAqIElmIHRoZSBkYXRhIGlzIG5vdCBpbiBhIFdlYk5OIE1MVGVuc29yLCB0aHJvdyBlcnJvci5cbiAgICovXG4gIHJlYWRvbmx5IG1sVGVuc29yOiBUZW5zb3IuTUxUZW5zb3JUeXBlO1xuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGJ1ZmZlciBkYXRhIG9mIHRoZSB0ZW5zb3IuXG4gICAqXG4gICAqIElmIHRoZSBkYXRhIGlzIG9uIENQVSwgcmV0dXJucyB0aGUgZGF0YSBpbW1lZGlhdGVseS5cbiAgICogSWYgdGhlIGRhdGEgaXMgb24gR1BVLCBkb3dubG9hZHMgdGhlIGRhdGEgYW5kIHJldHVybnMgdGhlIHByb21pc2UuXG4gICAqXG4gICAqIEBwYXJhbSByZWxlYXNlRGF0YSAtIHdoZXRoZXIgcmVsZWFzZSB0aGUgZGF0YSBvbiBHUFUuIElnbm9yZSBpZiBkYXRhIGlzIGFscmVhZHkgb24gQ1BVLlxuICAgKi9cbiAgZ2V0RGF0YShyZWxlYXNlRGF0YT86IGJvb2xlYW4pOiBQcm9taXNlPFRlbnNvci5EYXRhVHlwZU1hcFtUXT47XG5cbiAgLyoqXG4gICAqIERpc3Bvc2UgdGhlIHRlbnNvciBkYXRhLlxuICAgKlxuICAgKiBJZiB0aGUgZGF0YSBpcyBvbiBDUFUsIHJlbW92ZSBpdHMgaW50ZXJuYWwgcmVmZXJlbmNlIHRvIHRoZSB1bmRlcmx5aW5nIGRhdGEuXG4gICAqIElmIHRoZSBkYXRhIGlzIG9uIEdQVSwgcmVsZWFzZSB0aGUgZGF0YSBvbiBHUFUuXG4gICAqXG4gICAqIEFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiwgdGhlIHRlbnNvciBpcyBjb25zaWRlcmVkIG5vIGxvbmdlciB2YWxpZC4gSXRzIGxvY2F0aW9uIHdpbGwgYmUgc2V0IHRvICdub25lJy5cbiAgICovXG4gIGRpc3Bvc2UoKTogdm9pZDtcbn1cblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIFRlbnNvciB7XG4gIGludGVyZmFjZSBEYXRhVHlwZU1hcCB7XG4gICAgZmxvYXQzMjogRmxvYXQzMkFycmF5O1xuICAgIHVpbnQ4OiBVaW50OEFycmF5O1xuICAgIGludDg6IEludDhBcnJheTtcbiAgICB1aW50MTY6IFVpbnQxNkFycmF5O1xuICAgIGludDE2OiBJbnQxNkFycmF5O1xuICAgIGludDMyOiBJbnQzMkFycmF5O1xuICAgIGludDY0OiBCaWdJbnQ2NEFycmF5O1xuICAgIHN0cmluZzogc3RyaW5nW107XG4gICAgYm9vbDogVWludDhBcnJheTtcbiAgICBmbG9hdDE2OiBVaW50MTZBcnJheTsgLy8gS2VlcCB1c2luZyBVaW50MTZBcnJheSB1bnRpbCB3ZSBoYXZlIGEgY29uY3JldGUgc29sdXRpb24gZm9yIGZsb2F0IDE2LlxuICAgIGZsb2F0NjQ6IEZsb2F0NjRBcnJheTtcbiAgICB1aW50MzI6IFVpbnQzMkFycmF5O1xuICAgIHVpbnQ2NDogQmlnVWludDY0QXJyYXk7XG4gICAgLy8gY29tcGxleDY0OiBuZXZlcjtcbiAgICAvLyBjb21wbGV4MTI4OiBuZXZlcjtcbiAgICAvLyBiZmxvYXQxNjogbmV2ZXI7XG4gICAgdWludDQ6IFVpbnQ4QXJyYXk7XG4gICAgaW50NDogSW50OEFycmF5O1xuICB9XG5cbiAgaW50ZXJmYWNlIEVsZW1lbnRUeXBlTWFwIHtcbiAgICBmbG9hdDMyOiBudW1iZXI7XG4gICAgdWludDg6IG51bWJlcjtcbiAgICBpbnQ4OiBudW1iZXI7XG4gICAgdWludDE2OiBudW1iZXI7XG4gICAgaW50MTY6IG51bWJlcjtcbiAgICBpbnQzMjogbnVtYmVyO1xuICAgIGludDY0OiBiaWdpbnQ7XG4gICAgc3RyaW5nOiBzdHJpbmc7XG4gICAgYm9vbDogYm9vbGVhbjtcbiAgICBmbG9hdDE2OiBudW1iZXI7IC8vIEtlZXAgdXNpbmcgVWludDE2QXJyYXkgdW50aWwgd2UgaGF2ZSBhIGNvbmNyZXRlIHNvbHV0aW9uIGZvciBmbG9hdCAxNi5cbiAgICBmbG9hdDY0OiBudW1iZXI7XG4gICAgdWludDMyOiBudW1iZXI7XG4gICAgdWludDY0OiBiaWdpbnQ7XG4gICAgLy8gY29tcGxleDY0OiBuZXZlcjtcbiAgICAvLyBjb21wbGV4MTI4OiBuZXZlcjtcbiAgICAvLyBiZmxvYXQxNjogbmV2ZXI7XG4gICAgdWludDQ6IG51bWJlcjtcbiAgICBpbnQ0OiBudW1iZXI7XG4gIH1cblxuICB0eXBlIERhdGFUeXBlID0gRGF0YVR5cGVNYXBbVHlwZV07XG4gIHR5cGUgRWxlbWVudFR5cGUgPSBFbGVtZW50VHlwZU1hcFtUeXBlXTtcblxuICAvKipcbiAgICogc3VwcG9ydGVkIGRhdGEgdHlwZXMgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgcGlubmVkIENQVSBidWZmZXJcbiAgICovXG4gIGV4cG9ydCB0eXBlIENwdVBpbm5lZERhdGFUeXBlcyA9IEV4Y2x1ZGU8VGVuc29yLlR5cGUsICdzdHJpbmcnPjtcblxuICAvKipcbiAgICogdHlwZSBhbGlhcyBmb3IgV2ViR0wgdGV4dHVyZVxuICAgKi9cbiAgZXhwb3J0IHR5cGUgVGV4dHVyZVR5cGUgPSBXZWJHTFRleHR1cmU7XG5cbiAgLyoqXG4gICAqIHN1cHBvcnRlZCBkYXRhIHR5cGVzIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIFdlYkdMIHRleHR1cmVcbiAgICovXG4gIGV4cG9ydCB0eXBlIFRleHR1cmVEYXRhVHlwZXMgPSAnZmxvYXQzMic7XG5cbiAgdHlwZSBHcHVCdWZmZXJUeXBlRmFsbGJhY2sgPSB7IHNpemU6IG51bWJlcjsgbWFwU3RhdGU6ICd1bm1hcHBlZCcgfCAncGVuZGluZycgfCAnbWFwcGVkJyB9O1xuICAvKipcbiAgICogdHlwZSBhbGlhcyBmb3IgV2ViR1BVIGJ1ZmZlclxuICAgKi9cbiAgZXhwb3J0IHR5cGUgR3B1QnVmZmVyVHlwZSA9IFRyeUdldEdsb2JhbFR5cGU8J0dQVUJ1ZmZlcicsIEdwdUJ1ZmZlclR5cGVGYWxsYmFjaz47XG5cbiAgdHlwZSBNTFRlbnNvclR5cGVGYWxsYmFjayA9IHsgZGVzdHJveSgpOiB2b2lkIH07XG4gIC8qKlxuICAgKiB0eXBlIGFsaWFzIGZvciBXZWJOTiBNTFRlbnNvclxuICAgKlxuICAgKiBUaGUgc3BlY2lmaWNhdGlvbiBmb3IgV2ViTk4ncyBNTFRlbnNvciBpcyBjdXJyZW50bHkgaW4gZmx1eC5cbiAgICovXG4gIGV4cG9ydCB0eXBlIE1MVGVuc29yVHlwZSA9IFRyeUdldEdsb2JhbFR5cGU8J01MVGVuc29yJywgTUxUZW5zb3JUeXBlRmFsbGJhY2s+O1xuXG4gIC8qKlxuICAgKiBzdXBwb3J0ZWQgZGF0YSB0eXBlcyBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBXZWJHUFUgYnVmZmVyXG4gICAqL1xuICBleHBvcnQgdHlwZSBHcHVCdWZmZXJEYXRhVHlwZXMgPSAnZmxvYXQzMicgfCAnZmxvYXQxNicgfCAnaW50MzInIHwgJ2ludDY0JyB8ICd1aW50MzInIHwgJ3VpbnQ4JyB8ICdib29sJztcblxuICAvKipcbiAgICogc3VwcG9ydGVkIGRhdGEgdHlwZXMgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgV2ViTk4gTUxUZW5zb3JcbiAgICovXG4gIGV4cG9ydCB0eXBlIE1MVGVuc29yRGF0YVR5cGVzID1cbiAgICB8ICdmbG9hdDMyJ1xuICAgIHwgJ2Zsb2F0MTYnXG4gICAgfCAnaW50OCdcbiAgICB8ICd1aW50OCdcbiAgICB8ICdpbnQzMidcbiAgICB8ICd1aW50MzInXG4gICAgfCAnaW50NjQnXG4gICAgfCAndWludDY0J1xuICAgIHwgJ2Jvb2wnXG4gICAgfCAndWludDQnXG4gICAgfCAnaW50NCc7XG5cbiAgLyoqXG4gICAqIHJlcHJlc2VudCB3aGVyZSB0aGUgdGVuc29yIGRhdGEgaXMgc3RvcmVkXG4gICAqL1xuICBleHBvcnQgdHlwZSBEYXRhTG9jYXRpb24gPSAnbm9uZScgfCAnY3B1JyB8ICdjcHUtcGlubmVkJyB8ICd0ZXh0dXJlJyB8ICdncHUtYnVmZmVyJyB8ICdtbC10ZW5zb3InO1xuXG4gIC8qKlxuICAgKiByZXByZXNlbnQgdGhlIGRhdGEgdHlwZSBvZiBhIHRlbnNvclxuICAgKi9cbiAgZXhwb3J0IHR5cGUgVHlwZSA9IGtleW9mIERhdGFUeXBlTWFwO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudCBtdWx0aS1kaW1lbnNpb25hbCBhcnJheXMgdG8gZmVlZCB0byBvciBmZXRjaCBmcm9tIG1vZGVsIGluZmVyZW5jaW5nLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFR5cGVkVGVuc29yPFQgZXh0ZW5kcyBUZW5zb3IuVHlwZT4gZXh0ZW5kcyBUeXBlZFRlbnNvckJhc2U8VD4sIFR5cGVkVGVuc29yVXRpbHM8VD4ge31cbi8qKlxuICogUmVwcmVzZW50IG11bHRpLWRpbWVuc2lvbmFsIGFycmF5cyB0byBmZWVkIHRvIG9yIGZldGNoIGZyb20gbW9kZWwgaW5mZXJlbmNpbmcuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yIGV4dGVuZHMgVHlwZWRUZW5zb3JCYXNlPFRlbnNvci5UeXBlPiwgVHlwZWRUZW5zb3JVdGlsczxUZW5zb3IuVHlwZT4ge31cblxuLyoqXG4gKiB0eXBlIFRlbnNvckNvbnN0cnVjdG9yIGRlZmluZXMgdGhlIGNvbnN0cnVjdG9ycyBvZiAnVGVuc29yJyB0byBjcmVhdGUgQ1BVIHRlbnNvciBpbnN0YW5jZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yQ29uc3RydWN0b3IgZXh0ZW5kcyBUZW5zb3JGYWN0b3J5IHtcbiAgLy8gI3JlZ2lvbiBDUFUgdGVuc29yIC0gc3BlY2lmeSBlbGVtZW50IHR5cGVcbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBzdHJpbmcgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiB0eXBlLCBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIFNwZWNpZnkgdGhlIGVsZW1lbnQgdHlwZS5cbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChcbiAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICBkYXRhOiBUZW5zb3IuRGF0YVR5cGVNYXBbJ3N0cmluZyddIHwgcmVhZG9ubHkgc3RyaW5nW10sXG4gICAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiBUeXBlZFRlbnNvcjwnc3RyaW5nJz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBib29sIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gdHlwZSwgZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgLSBTcGVjaWZ5IHRoZSBlbGVtZW50IHR5cGUuXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoXG4gICAgdHlwZTogJ2Jvb2wnLFxuICAgIGRhdGE6IFRlbnNvci5EYXRhVHlwZU1hcFsnYm9vbCddIHwgcmVhZG9ubHkgYm9vbGVhbltdLFxuICAgIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogVHlwZWRUZW5zb3I8J2Jvb2wnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHVpbnQ4IHRlbnNvciBvYmplY3QgZnJvbSBhIFVpbnQ4Q2xhbXBlZEFycmF5LCBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIFNwZWNpZnkgdGhlIGVsZW1lbnQgdHlwZS5cbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3ICh0eXBlOiAndWludDgnLCBkYXRhOiBVaW50OENsYW1wZWRBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J3VpbnQ4Jz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyA2NC1iaXQgaW50ZWdlciB0eXBlZCB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIHR5cGUsIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gU3BlY2lmeSB0aGUgZWxlbWVudCB0eXBlLlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgPFQgZXh0ZW5kcyAndWludDY0JyB8ICdpbnQ2NCc+KFxuICAgIHR5cGU6IFQsXG4gICAgZGF0YTogVGVuc29yLkRhdGFUeXBlTWFwW1RdIHwgcmVhZG9ubHkgYmlnaW50W10gfCByZWFkb25seSBudW1iZXJbXSxcbiAgICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk6IFR5cGVkVGVuc29yPFQ+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgbnVtZXJpYyB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIHR5cGUsIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gU3BlY2lmeSB0aGUgZWxlbWVudCB0eXBlLlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgPFQgZXh0ZW5kcyBFeGNsdWRlPFRlbnNvci5UeXBlLCAnc3RyaW5nJyB8ICdib29sJyB8ICd1aW50NjQnIHwgJ2ludDY0Jz4+KFxuICAgIHR5cGU6IFQsXG4gICAgZGF0YTogVGVuc29yLkRhdGFUeXBlTWFwW1RdIHwgcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiBUeXBlZFRlbnNvcjxUPjtcbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gQ1BVIHRlbnNvciAtIGluZmVyIGVsZW1lbnQgdHlwZXNcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IGZsb2F0MzIgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IEZsb2F0MzJBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J2Zsb2F0MzInPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IGludDggdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IEludDhBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J2ludDgnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHVpbnQ4IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBVaW50OEFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwndWludDgnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHVpbnQ4IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBVaW50OENsYW1wZWRBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J3VpbnQ4Jz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB1aW50MTYgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IFVpbnQxNkFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwndWludDE2Jz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBpbnQxNiB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogSW50MTZBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J2ludDE2Jz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBpbnQzMiB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogSW50MzJBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J2ludDMyJz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBpbnQ2NCB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogQmlnSW50NjRBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J2ludDY0Jz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBzdHJpbmcgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IHJlYWRvbmx5IHN0cmluZ1tdLCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwnc3RyaW5nJz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBib29sIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiByZWFkb25seSBib29sZWFuW10sIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCdib29sJz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBmbG9hdDY0IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBGbG9hdDY0QXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCdmbG9hdDY0Jz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB1aW50MzIgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IFVpbnQzMkFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwndWludDMyJz47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB1aW50NjQgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IEJpZ1VpbnQ2NEFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwndWludDY0Jz47XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gQ1BVIHRlbnNvciAtIGZhbGwgYmFjayB0byBub24tZ2VuZXJpYyB0ZW5zb3IgdHlwZSBkZWNsYXJhdGlvblxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiB0eXBlLCBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIFNwZWNpZnkgdGhlIGVsZW1lbnQgdHlwZS5cbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChcbiAgICB0eXBlOiBUZW5zb3IuVHlwZSxcbiAgICBkYXRhOiBUZW5zb3IuRGF0YVR5cGUgfCByZWFkb25seSBudW1iZXJbXSB8IHJlYWRvbmx5IHN0cmluZ1tdIHwgcmVhZG9ubHkgYmlnaW50W10gfCByZWFkb25seSBib29sZWFuW10sXG4gICAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiBUZW5zb3I7XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogVGVuc29yLkRhdGFUeXBlLCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3I7XG4gIC8vICNlbmRyZWdpb25cbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuZXhwb3J0IGNvbnN0IFRlbnNvciA9IFRlbnNvckltcGwgYXMgVGVuc29yQ29uc3RydWN0b3I7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGVudiB9IGZyb20gJy4vZW52LWltcGwuanMnO1xuXG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGNvbnN0IFRSQUNFID0gKGRldmljZVR5cGU6IHN0cmluZywgbGFiZWw6IHN0cmluZykgPT4ge1xuICBpZiAodHlwZW9mIGVudi50cmFjZSA9PT0gJ3VuZGVmaW5lZCcgPyAhZW52Lndhc20udHJhY2UgOiAhZW52LnRyYWNlKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUudGltZVN0YW1wKGAke2RldmljZVR5cGV9OjpPUlQ6OiR7bGFiZWx9YCk7XG59O1xuXG5jb25zdCBUUkFDRV9GVU5DID0gKG1zZzogc3RyaW5nLCBleHRyYU1zZz86IHN0cmluZykgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrPy5zcGxpdCgvXFxyXFxufFxccnxcXG4vZykgfHwgW107XG4gIGxldCBoYXNUcmFjZUZ1bmMgPSBmYWxzZTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdGFjay5sZW5ndGg7IGkrKykge1xuICAgIGlmIChoYXNUcmFjZUZ1bmMgJiYgIXN0YWNrW2ldLmluY2x1ZGVzKCdUUkFDRV9GVU5DJykpIHtcbiAgICAgIGxldCBsYWJlbCA9IGBGVU5DXyR7bXNnfTo6JHtzdGFja1tpXS50cmltKCkuc3BsaXQoJyAnKVsxXX1gO1xuICAgICAgaWYgKGV4dHJhTXNnKSB7XG4gICAgICAgIGxhYmVsICs9IGA6OiR7ZXh0cmFNc2d9YDtcbiAgICAgIH1cbiAgICAgIFRSQUNFKCdDUFUnLCBsYWJlbCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChzdGFja1tpXS5pbmNsdWRlcygnVFJBQ0VfRlVOQycpKSB7XG4gICAgICBoYXNUcmFjZUZ1bmMgPSB0cnVlO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCBUUkFDRV9GVU5DX0JFR0lOID0gKGV4dHJhTXNnPzogc3RyaW5nKSA9PiB7XG4gIGlmICh0eXBlb2YgZW52LnRyYWNlID09PSAndW5kZWZpbmVkJyA/ICFlbnYud2FzbS50cmFjZSA6ICFlbnYudHJhY2UpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgVFJBQ0VfRlVOQygnQkVHSU4nLCBleHRyYU1zZyk7XG59O1xuXG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGNvbnN0IFRSQUNFX0ZVTkNfRU5EID0gKGV4dHJhTXNnPzogc3RyaW5nKSA9PiB7XG4gIGlmICh0eXBlb2YgZW52LnRyYWNlID09PSAndW5kZWZpbmVkJyA/ICFlbnYud2FzbS50cmFjZSA6ICFlbnYudHJhY2UpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgVFJBQ0VfRlVOQygnRU5EJywgZXh0cmFNc2cpO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgcmVzb2x2ZUJhY2tlbmRBbmRFeGVjdXRpb25Qcm92aWRlcnMgfSBmcm9tICcuL2JhY2tlbmQtaW1wbC5qcyc7XG5pbXBvcnQgeyBJbmZlcmVuY2VTZXNzaW9uSGFuZGxlciB9IGZyb20gJy4vYmFja2VuZC5qcyc7XG5pbXBvcnQgeyBJbmZlcmVuY2VTZXNzaW9uIGFzIEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2UgfSBmcm9tICcuL2luZmVyZW5jZS1zZXNzaW9uLmpzJztcbmltcG9ydCB7IE9ubnhWYWx1ZSB9IGZyb20gJy4vb25ueC12YWx1ZS5qcyc7XG5pbXBvcnQgeyBUZW5zb3IgfSBmcm9tICcuL3RlbnNvci5qcyc7XG5pbXBvcnQgeyBUUkFDRV9GVU5DX0JFR0lOLCBUUkFDRV9GVU5DX0VORCB9IGZyb20gJy4vdHJhY2UuanMnO1xuXG50eXBlIFNlc3Npb25PcHRpb25zID0gSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5TZXNzaW9uT3B0aW9ucztcbnR5cGUgUnVuT3B0aW9ucyA9IEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2UuUnVuT3B0aW9ucztcbnR5cGUgRmVlZHNUeXBlID0gSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5GZWVkc1R5cGU7XG50eXBlIEZldGNoZXNUeXBlID0gSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5GZXRjaGVzVHlwZTtcbnR5cGUgUmV0dXJuVHlwZSA9IEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2UuUmV0dXJuVHlwZTtcblxuZXhwb3J0IGNsYXNzIEluZmVyZW5jZVNlc3Npb24gaW1wbGVtZW50cyBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihoYW5kbGVyOiBJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcikge1xuICAgIHRoaXMuaGFuZGxlciA9IGhhbmRsZXI7XG4gIH1cbiAgcnVuKGZlZWRzOiBGZWVkc1R5cGUsIG9wdGlvbnM/OiBSdW5PcHRpb25zKTogUHJvbWlzZTxSZXR1cm5UeXBlPjtcbiAgcnVuKGZlZWRzOiBGZWVkc1R5cGUsIGZldGNoZXM6IEZldGNoZXNUeXBlLCBvcHRpb25zPzogUnVuT3B0aW9ucyk6IFByb21pc2U8UmV0dXJuVHlwZT47XG4gIGFzeW5jIHJ1bihmZWVkczogRmVlZHNUeXBlLCBhcmcxPzogRmV0Y2hlc1R5cGUgfCBSdW5PcHRpb25zLCBhcmcyPzogUnVuT3B0aW9ucyk6IFByb21pc2U8UmV0dXJuVHlwZT4ge1xuICAgIFRSQUNFX0ZVTkNfQkVHSU4oKTtcbiAgICBjb25zdCBmZXRjaGVzOiB7IFtuYW1lOiBzdHJpbmddOiBPbm54VmFsdWUgfCBudWxsIH0gPSB7fTtcbiAgICBsZXQgb3B0aW9uczogUnVuT3B0aW9ucyA9IHt9O1xuICAgIC8vIGNoZWNrIGlucHV0c1xuICAgIGlmICh0eXBlb2YgZmVlZHMgIT09ICdvYmplY3QnIHx8IGZlZWRzID09PSBudWxsIHx8IGZlZWRzIGluc3RhbmNlb2YgVGVuc29yIHx8IEFycmF5LmlzQXJyYXkoZmVlZHMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICBcIidmZWVkcycgbXVzdCBiZSBhbiBvYmplY3QgdGhhdCB1c2UgaW5wdXQgbmFtZXMgYXMga2V5cyBhbmQgT25ueFZhbHVlIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlwiLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBsZXQgaXNGZXRjaGVzRW1wdHkgPSB0cnVlO1xuICAgIC8vIGRldGVybWluZSB3aGljaCBvdmVycmlkZSBpcyBiZWluZyB1c2VkXG4gICAgaWYgKHR5cGVvZiBhcmcxID09PSAnb2JqZWN0Jykge1xuICAgICAgaWYgKGFyZzEgPT09IG51bGwpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5leHBlY3RlZCBhcmd1bWVudFsxXTogY2Fubm90IGJlIG51bGwuJyk7XG4gICAgICB9XG4gICAgICBpZiAoYXJnMSBpbnN0YW5jZW9mIFRlbnNvcikge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ2ZldGNoZXMnIGNhbm5vdCBiZSBhIFRlbnNvclwiKTtcbiAgICAgIH1cblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYXJnMSkpIHtcbiAgICAgICAgaWYgKGFyZzEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidmZXRjaGVzJyBjYW5ub3QgYmUgYW4gZW1wdHkgYXJyYXkuXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlzRmV0Y2hlc0VtcHR5ID0gZmFsc2U7XG4gICAgICAgIC8vIG91dHB1dCBuYW1lc1xuICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgYXJnMSkge1xuICAgICAgICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInZmV0Y2hlcycgbXVzdCBiZSBhIHN0cmluZyBhcnJheSBvciBhbiBvYmplY3QuXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodGhpcy5vdXRwdXROYW1lcy5pbmRleE9mKG5hbWUpID09PSAtMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYCdmZXRjaGVzJyBjb250YWlucyBpbnZhbGlkIG91dHB1dCBuYW1lOiAke25hbWV9LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmZXRjaGVzW25hbWVdID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgYXJnMiA9PT0gJ29iamVjdCcgJiYgYXJnMiAhPT0gbnVsbCkge1xuICAgICAgICAgIG9wdGlvbnMgPSBhcmcyO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuXCIpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBkZWNpZGUgd2hldGhlciBhcmcxIGlzIGZldGNoZXMgb3Igb3B0aW9uc1xuICAgICAgICAvLyBpZiBhbnkgb3V0cHV0IG5hbWUgaXMgcHJlc2VudCBhbmQgaXRzIHZhbHVlIGlzIHZhbGlkIE9ubnhWYWx1ZSwgd2UgY29uc2lkZXIgaXQgZmV0Y2hlc1xuICAgICAgICBsZXQgaXNGZXRjaGVzID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IGFyZzFLZXlzID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoYXJnMSk7XG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiB0aGlzLm91dHB1dE5hbWVzKSB7XG4gICAgICAgICAgaWYgKGFyZzFLZXlzLmluZGV4T2YobmFtZSkgIT09IC0xKSB7XG4gICAgICAgICAgICBjb25zdCB2ID0gKGFyZzEgYXMgSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5OdWxsYWJsZU9ubnhWYWx1ZU1hcFR5cGUpW25hbWVdO1xuICAgICAgICAgICAgaWYgKHYgPT09IG51bGwgfHwgdiBpbnN0YW5jZW9mIFRlbnNvcikge1xuICAgICAgICAgICAgICBpc0ZldGNoZXMgPSB0cnVlO1xuICAgICAgICAgICAgICBpc0ZldGNoZXNFbXB0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICBmZXRjaGVzW25hbWVdID0gdjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNGZXRjaGVzKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBhcmcyID09PSAnb2JqZWN0JyAmJiBhcmcyICE9PSBudWxsKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gYXJnMjtcbiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC5cIik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9wdGlvbnMgPSBhcmcxIGFzIFJ1bk9wdGlvbnM7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcxICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlVuZXhwZWN0ZWQgYXJndW1lbnRbMV06IG11c3QgYmUgJ2ZldGNoZXMnIG9yICdvcHRpb25zJy5cIik7XG4gICAgfVxuXG4gICAgLy8gY2hlY2sgaWYgYWxsIGlucHV0cyBhcmUgaW4gZmVlZFxuICAgIGZvciAoY29uc3QgbmFtZSBvZiB0aGlzLmlucHV0TmFtZXMpIHtcbiAgICAgIGlmICh0eXBlb2YgZmVlZHNbbmFtZV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW5wdXQgJyR7bmFtZX0nIGlzIG1pc3NpbmcgaW4gJ2ZlZWRzJy5gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpZiBubyBmZXRjaGVzIGlzIHNwZWNpZmllZCwgd2UgdXNlIHRoZSBmdWxsIG91dHB1dCBuYW1lcyBsaXN0XG4gICAgaWYgKGlzRmV0Y2hlc0VtcHR5KSB7XG4gICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgdGhpcy5vdXRwdXROYW1lcykge1xuICAgICAgICBmZXRjaGVzW25hbWVdID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmZWVkcywgZmV0Y2hlcyBhbmQgb3B0aW9ucyBhcmUgcHJlcGFyZWRcblxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLmhhbmRsZXIucnVuKGZlZWRzLCBmZXRjaGVzLCBvcHRpb25zKTtcbiAgICBjb25zdCByZXR1cm5WYWx1ZTogeyBbbmFtZTogc3RyaW5nXTogT25ueFZhbHVlIH0gPSB7fTtcbiAgICBmb3IgKGNvbnN0IGtleSBpbiByZXN1bHRzKSB7XG4gICAgICBpZiAoT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwocmVzdWx0cywga2V5KSkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSByZXN1bHRzW2tleV07XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBUZW5zb3IpIHtcbiAgICAgICAgICByZXR1cm5WYWx1ZVtrZXldID0gcmVzdWx0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVyblZhbHVlW2tleV0gPSBuZXcgVGVuc29yKHJlc3VsdC50eXBlLCByZXN1bHQuZGF0YSwgcmVzdWx0LmRpbXMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIFRSQUNFX0ZVTkNfRU5EKCk7XG4gICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICB9XG5cbiAgYXN5bmMgcmVsZWFzZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVyLmRpc3Bvc2UoKTtcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGUocGF0aDogc3RyaW5nLCBvcHRpb25zPzogU2Vzc2lvbk9wdGlvbnMpOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2U+O1xuICBzdGF0aWMgY3JlYXRlKGJ1ZmZlcjogQXJyYXlCdWZmZXJMaWtlLCBvcHRpb25zPzogU2Vzc2lvbk9wdGlvbnMpOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2U+O1xuICBzdGF0aWMgY3JlYXRlKFxuICAgIGJ1ZmZlcjogQXJyYXlCdWZmZXJMaWtlLFxuICAgIGJ5dGVPZmZzZXQ6IG51bWJlcixcbiAgICBieXRlTGVuZ3RoPzogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiBTZXNzaW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlPjtcbiAgc3RhdGljIGNyZWF0ZShidWZmZXI6IFVpbnQ4QXJyYXksIG9wdGlvbnM/OiBTZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZT47XG4gIHN0YXRpYyBhc3luYyBjcmVhdGUoXG4gICAgYXJnMDogc3RyaW5nIHwgQXJyYXlCdWZmZXJMaWtlIHwgVWludDhBcnJheSxcbiAgICBhcmcxPzogU2Vzc2lvbk9wdGlvbnMgfCBudW1iZXIsXG4gICAgYXJnMj86IG51bWJlcixcbiAgICBhcmczPzogU2Vzc2lvbk9wdGlvbnMsXG4gICk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZT4ge1xuICAgIFRSQUNFX0ZVTkNfQkVHSU4oKTtcbiAgICAvLyBlaXRoZXIgbG9hZCBmcm9tIGEgZmlsZSBvciBidWZmZXJcbiAgICBsZXQgZmlsZVBhdGhPclVpbnQ4QXJyYXk6IHN0cmluZyB8IFVpbnQ4QXJyYXk7XG4gICAgbGV0IG9wdGlvbnM6IFNlc3Npb25PcHRpb25zID0ge307XG5cbiAgICBpZiAodHlwZW9mIGFyZzAgPT09ICdzdHJpbmcnKSB7XG4gICAgICBmaWxlUGF0aE9yVWludDhBcnJheSA9IGFyZzA7XG4gICAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnICYmIGFyZzEgIT09IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucyA9IGFyZzE7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcxICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ29wdGlvbnMnIG11c3QgYmUgYW4gb2JqZWN0LlwiKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGFyZzAgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICBmaWxlUGF0aE9yVWludDhBcnJheSA9IGFyZzA7XG4gICAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnICYmIGFyZzEgIT09IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucyA9IGFyZzE7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcxICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ29wdGlvbnMnIG11c3QgYmUgYW4gb2JqZWN0LlwiKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKFxuICAgICAgYXJnMCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyIHx8XG4gICAgICAodHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyICE9PSAndW5kZWZpbmVkJyAmJiBhcmcwIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXIpXG4gICAgKSB7XG4gICAgICBjb25zdCBidWZmZXIgPSBhcmcwO1xuICAgICAgbGV0IGJ5dGVPZmZzZXQgPSAwO1xuICAgICAgbGV0IGJ5dGVMZW5ndGggPSBhcmcwLmJ5dGVMZW5ndGg7XG4gICAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnICYmIGFyZzEgIT09IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucyA9IGFyZzE7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcxID09PSAnbnVtYmVyJykge1xuICAgICAgICBieXRlT2Zmc2V0ID0gYXJnMTtcbiAgICAgICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihieXRlT2Zmc2V0KSkge1xuICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKFwiJ2J5dGVPZmZzZXQnIG11c3QgYmUgYW4gaW50ZWdlci5cIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJ5dGVPZmZzZXQgPCAwIHx8IGJ5dGVPZmZzZXQgPj0gYnVmZmVyLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2J5dGVPZmZzZXQnIGlzIG91dCBvZiByYW5nZSBbMCwgJHtidWZmZXIuYnl0ZUxlbmd0aH0pLmApO1xuICAgICAgICB9XG4gICAgICAgIGJ5dGVMZW5ndGggPSBhcmcwLmJ5dGVMZW5ndGggLSBieXRlT2Zmc2V0O1xuICAgICAgICBpZiAodHlwZW9mIGFyZzIgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgYnl0ZUxlbmd0aCA9IGFyZzI7XG4gICAgICAgICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihieXRlTGVuZ3RoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCInYnl0ZUxlbmd0aCcgbXVzdCBiZSBhbiBpbnRlZ2VyLlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGJ5dGVMZW5ndGggPD0gMCB8fCBieXRlT2Zmc2V0ICsgYnl0ZUxlbmd0aCA+IGJ1ZmZlci5ieXRlTGVuZ3RoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2J5dGVMZW5ndGgnIGlzIG91dCBvZiByYW5nZSAoMCwgJHtidWZmZXIuYnl0ZUxlbmd0aCAtIGJ5dGVPZmZzZXR9XS5gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHR5cGVvZiBhcmczID09PSAnb2JqZWN0JyAmJiBhcmczICE9PSBudWxsKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gYXJnMztcbiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmczICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC5cIik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInYnl0ZUxlbmd0aCcgbXVzdCBiZSBhIG51bWJlci5cIik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuXCIpO1xuICAgICAgfVxuICAgICAgZmlsZVBhdGhPclVpbnQ4QXJyYXkgPSBuZXcgVWludDhBcnJheShidWZmZXIsIGJ5dGVPZmZzZXQsIGJ5dGVMZW5ndGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5leHBlY3RlZCBhcmd1bWVudFswXTogbXVzdCBiZSAncGF0aCcgb3IgJ2J1ZmZlcicuXCIpO1xuICAgIH1cblxuICAgIC8vIHJlc29sdmUgYmFja2VuZCwgdXBkYXRlIHNlc3Npb24gb3B0aW9ucyB3aXRoIHZhbGlkYXRlZCBFUHMsIGFuZCBjcmVhdGUgc2Vzc2lvbiBoYW5kbGVyXG4gICAgY29uc3QgW2JhY2tlbmQsIG9wdGlvbnNXaXRoVmFsaWRhdGVkRVBzXSA9IGF3YWl0IHJlc29sdmVCYWNrZW5kQW5kRXhlY3V0aW9uUHJvdmlkZXJzKG9wdGlvbnMpO1xuICAgIGNvbnN0IGhhbmRsZXIgPSBhd2FpdCBiYWNrZW5kLmNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKGZpbGVQYXRoT3JVaW50OEFycmF5LCBvcHRpb25zV2l0aFZhbGlkYXRlZEVQcyk7XG4gICAgVFJBQ0VfRlVOQ19FTkQoKTtcbiAgICByZXR1cm4gbmV3IEluZmVyZW5jZVNlc3Npb24oaGFuZGxlcik7XG4gIH1cblxuICBzdGFydFByb2ZpbGluZygpOiB2b2lkIHtcbiAgICB0aGlzLmhhbmRsZXIuc3RhcnRQcm9maWxpbmcoKTtcbiAgfVxuICBlbmRQcm9maWxpbmcoKTogdm9pZCB7XG4gICAgdGhpcy5oYW5kbGVyLmVuZFByb2ZpbGluZygpO1xuICB9XG5cbiAgZ2V0IGlucHV0TmFtZXMoKTogcmVhZG9ubHkgc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmhhbmRsZXIuaW5wdXROYW1lcztcbiAgfVxuICBnZXQgb3V0cHV0TmFtZXMoKTogcmVhZG9ubHkgc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmhhbmRsZXIub3V0cHV0TmFtZXM7XG4gIH1cblxuICBnZXQgaW5wdXRNZXRhZGF0YSgpOiByZWFkb25seSBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLlZhbHVlTWV0YWRhdGFbXSB7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlci5pbnB1dE1ldGFkYXRhO1xuICB9XG5cbiAgZ2V0IG91dHB1dE1ldGFkYXRhKCk6IHJlYWRvbmx5IEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2UuVmFsdWVNZXRhZGF0YVtdIHtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVyLm91dHB1dE1ldGFkYXRhO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVyOiBJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcjtcbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgSW5mZXJlbmNlU2Vzc2lvbiBhcyBJbmZlcmVuY2VTZXNzaW9uSW1wbCB9IGZyb20gJy4vaW5mZXJlbmNlLXNlc3Npb24taW1wbC5qcyc7XG5pbXBvcnQgeyBPbm54TW9kZWxPcHRpb25zIH0gZnJvbSAnLi9vbm54LW1vZGVsLmpzJztcbmltcG9ydCB7IE9ubnhWYWx1ZSwgT25ueFZhbHVlRGF0YUxvY2F0aW9uIH0gZnJvbSAnLi9vbm54LXZhbHVlLmpzJztcbmltcG9ydCB0eXBlIHsgVGVuc29yIH0gZnJvbSAnLi90ZW5zb3IuanMnO1xuaW1wb3J0IHsgVHJ5R2V0R2xvYmFsVHlwZSB9IGZyb20gJy4vdHlwZS1oZWxwZXIuanMnO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVkZWNsYXJlICovXG5cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBJbmZlcmVuY2VTZXNzaW9uIHtcbiAgLy8gI3JlZ2lvbiBpbnB1dC9vdXRwdXQgdHlwZXNcblxuICB0eXBlIE9ubnhWYWx1ZU1hcFR5cGUgPSB7IHJlYWRvbmx5IFtuYW1lOiBzdHJpbmddOiBPbm54VmFsdWUgfTtcbiAgdHlwZSBOdWxsYWJsZU9ubnhWYWx1ZU1hcFR5cGUgPSB7IHJlYWRvbmx5IFtuYW1lOiBzdHJpbmddOiBPbm54VmFsdWUgfCBudWxsIH07XG5cbiAgLyoqXG4gICAqIEEgZmVlZHMgKG1vZGVsIGlucHV0cykgaXMgYW4gb2JqZWN0IHRoYXQgdXNlcyBpbnB1dCBuYW1lcyBhcyBrZXlzIGFuZCBPbm54VmFsdWUgYXMgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAqL1xuICB0eXBlIEZlZWRzVHlwZSA9IE9ubnhWYWx1ZU1hcFR5cGU7XG5cbiAgLyoqXG4gICAqIEEgZmV0Y2hlcyAobW9kZWwgb3V0cHV0cykgY291bGQgYmUgb25lIG9mIHRoZSBmb2xsb3dpbmc6XG4gICAqXG4gICAqIC0gT21pdHRlZC4gVXNlIG1vZGVsJ3Mgb3V0cHV0IG5hbWVzIGRlZmluaXRpb24uXG4gICAqIC0gQW4gYXJyYXkgb2Ygc3RyaW5nIGluZGljYXRpbmcgdGhlIG91dHB1dCBuYW1lcy5cbiAgICogLSBBbiBvYmplY3QgdGhhdCB1c2Ugb3V0cHV0IG5hbWVzIGFzIGtleXMgYW5kIE9ubnhWYWx1ZSBvciBudWxsIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcmVtYXJrXG4gICAqIGRpZmZlcmVudCBmcm9tIGlucHV0IGFyZ3VtZW50LCBpbiBvdXRwdXQsIE9ubnhWYWx1ZSBpcyBvcHRpb25hbC4gSWYgYW4gT25ueFZhbHVlIGlzIHByZXNlbnQgaXQgd2lsbCBiZVxuICAgKiB1c2VkIGFzIGEgcHJlLWFsbG9jYXRlZCB2YWx1ZSBieSB0aGUgaW5mZXJlbmNlIGVuZ2luZTsgaWYgb21pdHRlZCwgaW5mZXJlbmNlIGVuZ2luZSB3aWxsIGFsbG9jYXRlIGJ1ZmZlclxuICAgKiBpbnRlcm5hbGx5LlxuICAgKi9cbiAgdHlwZSBGZXRjaGVzVHlwZSA9IHJlYWRvbmx5IHN0cmluZ1tdIHwgTnVsbGFibGVPbm54VmFsdWVNYXBUeXBlO1xuXG4gIC8qKlxuICAgKiBBIGluZmVyZW5jaW5nIHJldHVybiB0eXBlIGlzIGFuIG9iamVjdCB0aGF0IHVzZXMgb3V0cHV0IG5hbWVzIGFzIGtleXMgYW5kIE9ubnhWYWx1ZSBhcyBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgICovXG4gIHR5cGUgUmV0dXJuVHlwZSA9IE9ubnhWYWx1ZU1hcFR5cGU7XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gc2Vzc2lvbiBvcHRpb25zXG5cbiAgLyoqXG4gICAqIEEgc2V0IG9mIGNvbmZpZ3VyYXRpb25zIGZvciBzZXNzaW9uIGJlaGF2aW9yLlxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBTZXNzaW9uT3B0aW9ucyBleHRlbmRzIE9ubnhNb2RlbE9wdGlvbnMge1xuICAgIC8qKlxuICAgICAqIEFuIGFycmF5IG9mIGV4ZWN1dGlvbiBwcm92aWRlciBvcHRpb25zLlxuICAgICAqXG4gICAgICogQW4gZXhlY3V0aW9uIHByb3ZpZGVyIG9wdGlvbiBjYW4gYmUgYSBzdHJpbmcgaW5kaWNhdGluZyB0aGUgbmFtZSBvZiB0aGUgZXhlY3V0aW9uIHByb3ZpZGVyLFxuICAgICAqIG9yIGFuIG9iamVjdCBvZiBjb3JyZXNwb25kaW5nIHR5cGUuXG4gICAgICovXG4gICAgZXhlY3V0aW9uUHJvdmlkZXJzPzogcmVhZG9ubHkgRXhlY3V0aW9uUHJvdmlkZXJDb25maWdbXTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBpbnRyYSBPUCB0aHJlYWRzIG51bWJlci5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpLlxuICAgICAqL1xuICAgIGludHJhT3BOdW1UaHJlYWRzPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGludGVyIE9QIHRocmVhZHMgbnVtYmVyLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkuXG4gICAgICovXG4gICAgaW50ZXJPcE51bVRocmVhZHM/OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGUuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKSBvciBXZWJBc3NlbWJseSBiYWNrZW5kXG4gICAgICovXG4gICAgZnJlZURpbWVuc2lvbk92ZXJyaWRlcz86IHsgcmVhZG9ubHkgW2RpbWVuc2lvbk5hbWU6IHN0cmluZ106IG51bWJlciB9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9wdGltaXphdGlvbiBsZXZlbC5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpIG9yIFdlYkFzc2VtYmx5IGJhY2tlbmRcbiAgICAgKi9cbiAgICBncmFwaE9wdGltaXphdGlvbkxldmVsPzogJ2Rpc2FibGVkJyB8ICdiYXNpYycgfCAnZXh0ZW5kZWQnIHwgJ2FsbCc7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIGVuYWJsZSBDUFUgbWVtb3J5IGFyZW5hLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIGVuYWJsZUNwdU1lbUFyZW5hPzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgZW5hYmxlIG1lbW9yeSBwYXR0ZXJuLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIGVuYWJsZU1lbVBhdHRlcm4/OiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogRXhlY3V0aW9uIG1vZGUuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKSBvciBXZWJBc3NlbWJseSBiYWNrZW5kXG4gICAgICovXG4gICAgZXhlY3V0aW9uTW9kZT86ICdzZXF1ZW50aWFsJyB8ICdwYXJhbGxlbCc7XG5cbiAgICAvKipcbiAgICAgKiBPcHRpbWl6ZWQgbW9kZWwgZmlsZSBwYXRoLlxuICAgICAqXG4gICAgICogSWYgdGhpcyBzZXR0aW5nIGlzIHNwZWNpZmllZCwgdGhlIG9wdGltaXplZCBtb2RlbCB3aWxsIGJlIGR1bXBlZC4gSW4gYnJvd3NlciwgYSBibG9iIHdpbGwgYmUgY3JlYXRlZFxuICAgICAqIHdpdGggYSBwb3AtdXAgd2luZG93LlxuICAgICAqL1xuICAgIG9wdGltaXplZE1vZGVsRmlsZVBhdGg/OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIGVuYWJsZSBwcm9maWxpbmcuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYSBwbGFjZWhvbGRlciBmb3IgYSBmdXR1cmUgdXNlLlxuICAgICAqL1xuICAgIGVuYWJsZVByb2ZpbGluZz86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBGaWxlIHByZWZpeCBmb3IgcHJvZmlsaW5nLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGEgcGxhY2Vob2xkZXIgZm9yIGEgZnV0dXJlIHVzZS5cbiAgICAgKi9cbiAgICBwcm9maWxlRmlsZVByZWZpeD86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIExvZyBJRC5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpIG9yIFdlYkFzc2VtYmx5IGJhY2tlbmRcbiAgICAgKi9cbiAgICBsb2dJZD86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIExvZyBzZXZlcml0eSBsZXZlbC4gU2VlXG4gICAgICogaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9vbm54cnVudGltZS9ibG9iL21haW4vaW5jbHVkZS9vbm54cnVudGltZS9jb3JlL2NvbW1vbi9sb2dnaW5nL3NldmVyaXR5LmhcbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpIG9yIFdlYkFzc2VtYmx5IGJhY2tlbmRcbiAgICAgKi9cbiAgICBsb2dTZXZlcml0eUxldmVsPzogMCB8IDEgfCAyIHwgMyB8IDQ7XG5cbiAgICAvKipcbiAgICAgKiBMb2cgdmVyYm9zaXR5IGxldmVsLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIFdlYkFzc2VtYmx5IGJhY2tlbmQuIFdpbGwgc3VwcG9ydCBOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSBsYXRlclxuICAgICAqL1xuICAgIGxvZ1ZlcmJvc2l0eUxldmVsPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogU3BlY2lmeSBzdHJpbmcgYXMgYSBwcmVmZXJyZWQgZGF0YSBsb2NhdGlvbiBmb3IgYWxsIG91dHB1dHMsIG9yIGFuIG9iamVjdCB0aGF0IHVzZSBvdXRwdXQgbmFtZXMgYXMga2V5cyBhbmQgYVxuICAgICAqIHByZWZlcnJlZCBkYXRhIGxvY2F0aW9uIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIFdlYiBmb3IgV2ViR0wgYW5kIFdlYkdQVSBFUC5cbiAgICAgKi9cbiAgICBwcmVmZXJyZWRPdXRwdXRMb2NhdGlvbj86IE9ubnhWYWx1ZURhdGFMb2NhdGlvbiB8IHsgcmVhZG9ubHkgW291dHB1dE5hbWU6IHN0cmluZ106IE9ubnhWYWx1ZURhdGFMb2NhdGlvbiB9O1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciBlbmFibGUgZ3JhcGggY2FwdHVyZS5cbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgV2ViIGZvciBXZWJHUFUgRVAuXG4gICAgICovXG4gICAgZW5hYmxlR3JhcGhDYXB0dXJlPzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFN0b3JlIGNvbmZpZ3VyYXRpb25zIGZvciBhIHNlc3Npb24uIFNlZVxuICAgICAqIGh0dHBzOi8vZ2l0aHViLmNvbS9taWNyb3NvZnQvb25ueHJ1bnRpbWUvYmxvYi9tYWluL2luY2x1ZGUvb25ueHJ1bnRpbWUvY29yZS9zZXNzaW9uL1xuICAgICAqIG9ubnhydW50aW1lX3Nlc3Npb25fb3B0aW9uc19jb25maWdfa2V5cy5oXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gV2ViQXNzZW1ibHkgYmFja2VuZC4gV2lsbCBzdXBwb3J0IE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlIGxhdGVyXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZXh0cmE6IHtcbiAgICAgKiAgIHNlc3Npb246IHtcbiAgICAgKiAgICAgc2V0X2Rlbm9ybWFsX2FzX3plcm86IFwiMVwiLFxuICAgICAqICAgICBkaXNhYmxlX3ByZXBhY2tpbmc6IFwiMVwiXG4gICAgICogICB9LFxuICAgICAqICAgb3B0aW1pemF0aW9uOiB7XG4gICAgICogICAgIGVuYWJsZV9nZWx1X2FwcHJveGltYXRpb246IFwiMVwiXG4gICAgICogICB9XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGV4dHJhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH1cblxuICAvLyAjcmVnaW9uIGV4ZWN1dGlvbiBwcm92aWRlcnNcblxuICAvLyBDdXJyZW50bHksIHdlIGhhdmUgdGhlIGZvbGxvd2luZyBiYWNrZW5kcyB0byBzdXBwb3J0IGV4ZWN1dGlvbiBwcm92aWRlcnM6XG4gIC8vIEJhY2tlbmQgTm9kZS5qcyBiaW5kaW5nOiBzdXBwb3J0cyAnY3B1JywgJ2RtbCcgKHdpbjMyKSwgJ2NvcmVtbCcgKG1hY09TKSBhbmQgJ2N1ZGEnIChsaW51eCkuXG4gIC8vIEJhY2tlbmQgV2ViQXNzZW1ibHk6IHN1cHBvcnRzICdjcHUnLCAnd2FzbScsICd3ZWJncHUnIGFuZCAnd2Vibm4nLlxuICAvLyBCYWNrZW5kIE9OTlguanM6IHN1cHBvcnRzICd3ZWJnbCcuXG4gIC8vIEJhY2tlbmQgUmVhY3QgTmF0aXZlOiBzdXBwb3J0cyAnY3B1JywgJ3hubnBhY2snLCAnY29yZW1sJyAoaU9TKSwgJ25uYXBpJyAoQW5kcm9pZCkuXG4gIGludGVyZmFjZSBFeGVjdXRpb25Qcm92aWRlck9wdGlvbk1hcCB7XG4gICAgY29yZW1sOiBDb3JlTUxFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICBjcHU6IENwdUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIGN1ZGE6IEN1ZGFFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICBkbWw6IERtbEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIG5uYXBpOiBObmFwaUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIHRlbnNvcnJ0OiBUZW5zb3JSdEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIHdhc206IFdlYkFzc2VtYmx5RXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgd2ViZ2w6IFdlYkdMRXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgd2ViZ3B1OiBXZWJHcHVFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICB3ZWJubjogV2ViTk5FeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICBxbm46IFFubkV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIHhubnBhY2s6IFhubnBhY2tFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgfVxuXG4gIHR5cGUgRXhlY3V0aW9uUHJvdmlkZXJOYW1lID0ga2V5b2YgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb25NYXA7XG4gIHR5cGUgRXhlY3V0aW9uUHJvdmlkZXJDb25maWcgPVxuICAgIHwgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb25NYXBbRXhlY3V0aW9uUHJvdmlkZXJOYW1lXVxuICAgIHwgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb25cbiAgICB8IEV4ZWN1dGlvblByb3ZpZGVyTmFtZVxuICAgIHwgc3RyaW5nO1xuXG4gIGV4cG9ydCBpbnRlcmZhY2UgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIENwdUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICdjcHUnO1xuICAgIHVzZUFyZW5hPzogYm9vbGVhbjtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIEN1ZGFFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnY3VkYSc7XG4gICAgZGV2aWNlSWQ/OiBudW1iZXI7XG4gIH1cbiAgZXhwb3J0IGludGVyZmFjZSBEbWxFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnZG1sJztcbiAgICBkZXZpY2VJZD86IG51bWJlcjtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIFRlbnNvclJ0RXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ3RlbnNvcnJ0JztcbiAgICBkZXZpY2VJZD86IG51bWJlcjtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIFdlYkFzc2VtYmx5RXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ3dhc20nO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViR0xFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnd2ViZ2wnO1xuICAgIC8vIFRPRE86IGFkZCBmbGFnc1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgWG5ucGFja0V4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICd4bm5wYWNrJztcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIFdlYkdwdUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICd3ZWJncHUnO1xuICAgIHByZWZlcnJlZExheW91dD86ICdOQ0hXJyB8ICdOSFdDJztcbiAgfVxuXG4gIC8vICNyZWdpb24gV2ViTk4gb3B0aW9uc1xuXG4gIGludGVyZmFjZSBXZWJOTkV4ZWN1dGlvblByb3ZpZGVyTmFtZSBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnd2Vibm4nO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgYSBzZXQgb2Ygb3B0aW9ucyBmb3IgY3JlYXRpbmcgYSBXZWJOTiBNTENvbnRleHQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly93d3cudzMub3JnL1RSL3dlYm5uLyNkaWN0ZGVmLW1sY29udGV4dG9wdGlvbnNcbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViTk5Db250ZXh0T3B0aW9ucyB7XG4gICAgZGV2aWNlVHlwZT86ICdjcHUnIHwgJ2dwdScgfCAnbnB1JztcbiAgICBudW1UaHJlYWRzPzogbnVtYmVyO1xuICAgIHBvd2VyUHJlZmVyZW5jZT86ICdkZWZhdWx0JyB8ICdsb3ctcG93ZXInIHwgJ2hpZ2gtcGVyZm9ybWFuY2UnO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgYSBzZXQgb2Ygb3B0aW9ucyBmb3IgV2ViTk4gZXhlY3V0aW9uIHByb3ZpZGVyIHdpdGhvdXQgTUxDb250ZXh0LlxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJOTk9wdGlvbnNXaXRob3V0TUxDb250ZXh0IGV4dGVuZHMgV2ViTk5FeGVjdXRpb25Qcm92aWRlck5hbWUsIFdlYk5OQ29udGV4dE9wdGlvbnMge1xuICAgIGNvbnRleHQ/OiBuZXZlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIGEgc2V0IG9mIG9wdGlvbnMgZm9yIFdlYk5OIGV4ZWN1dGlvbiBwcm92aWRlciB3aXRoIE1MQ29udGV4dC5cbiAgICpcbiAgICogV2hlbiBNTENvbnRleHQgaXMgcHJvdmlkZWQsIHRoZSBkZXZpY2VUeXBlIGlzIGFsc28gcmVxdWlyZWQgc28gdGhhdCB0aGUgV2ViTk4gRVAgY2FuIGRldGVybWluZSB0aGUgcHJlZmVycmVkXG4gICAqIGNoYW5uZWwgbGF5b3V0LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vd3d3LnczLm9yZy9UUi93ZWJubi8jZG9tLW1sLWNyZWF0ZWNvbnRleHRcbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViTk5PcHRpb25zV2l0aE1MQ29udGV4dFxuICAgIGV4dGVuZHMgV2ViTk5FeGVjdXRpb25Qcm92aWRlck5hbWUsXG4gICAgICBPbWl0PFdlYk5OQ29udGV4dE9wdGlvbnMsICdkZXZpY2VUeXBlJz4sXG4gICAgICBSZXF1aXJlZDxQaWNrPFdlYk5OQ29udGV4dE9wdGlvbnMsICdkZXZpY2VUeXBlJz4+IHtcbiAgICBjb250ZXh0OiBUcnlHZXRHbG9iYWxUeXBlPCdNTENvbnRleHQnPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIGEgc2V0IG9mIG9wdGlvbnMgZm9yIFdlYk5OIGV4ZWN1dGlvbiBwcm92aWRlciB3aXRoIE1MQ29udGV4dCB3aGljaCBpcyBjcmVhdGVkIGZyb20gR1BVRGV2aWNlLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vd3d3LnczLm9yZy9UUi93ZWJubi8jZG9tLW1sLWNyZWF0ZWNvbnRleHQtZ3B1ZGV2aWNlXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIFdlYk5OT3B0aW9uc1dlYkdwdSBleHRlbmRzIFdlYk5ORXhlY3V0aW9uUHJvdmlkZXJOYW1lIHtcbiAgICBjb250ZXh0OiBUcnlHZXRHbG9iYWxUeXBlPCdNTENvbnRleHQnPjtcbiAgICBncHVEZXZpY2U6IFRyeUdldEdsb2JhbFR5cGU8J0dQVURldmljZSc+O1xuICB9XG5cbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIFdlYk5OIGV4ZWN1dGlvbiBwcm92aWRlci5cbiAgICovXG4gIGV4cG9ydCB0eXBlIFdlYk5ORXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gPVxuICAgIHwgV2ViTk5PcHRpb25zV2l0aG91dE1MQ29udGV4dFxuICAgIHwgV2ViTk5PcHRpb25zV2l0aE1MQ29udGV4dFxuICAgIHwgV2ViTk5PcHRpb25zV2ViR3B1O1xuXG4gIC8vICNlbmRyZWdpb25cblxuICBleHBvcnQgaW50ZXJmYWNlIFFubkV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICdxbm4nO1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgdGhlIFFOTiBiYWNrZW5kIHR5cGUuIEUuZy4sICdjcHUnIG9yICdodHAnLlxuICAgICAqIE11dHVhbGx5IGV4Y2x1c2l2ZSB3aXRoIGBiYWNrZW5kUGF0aGAuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCAnaHRwJ1xuICAgICAqL1xuICAgIGJhY2tlbmRUeXBlPzogc3RyaW5nO1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgYSBwYXRoIHRvIHRoZSBRTk4gYmFja2VuZCBsaWJyYXJ5LlxuICAgICAqIE11dHVhbGx5IGV4Y2x1c2l2ZSB3aXRoIGBiYWNrZW5kVHlwZWAuXG4gICAgICovXG4gICAgYmFja2VuZFBhdGg/OiBzdHJpbmc7XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSB3aGV0aGVyIHRvIGVuYWJsZSBIVFAgRlAxNiBwcmVjaXNpb24uXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCB0cnVlXG4gICAgICovXG4gICAgZW5hYmxlRnAxNlByZWNpc2lvbj86IGJvb2xlYW47XG4gIH1cbiAgZXhwb3J0IGludGVyZmFjZSBDb3JlTUxFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnY29yZW1sJztcbiAgICAvKipcbiAgICAgKiBUaGUgYml0IGZsYWdzIGZvciBDb3JlTUwgZXhlY3V0aW9uIHByb3ZpZGVyLlxuICAgICAqXG4gICAgICogYGBgXG4gICAgICogQ09SRU1MX0ZMQUdfVVNFX0NQVV9PTkxZID0gMHgwMDFcbiAgICAgKiBDT1JFTUxfRkxBR19FTkFCTEVfT05fU1VCR1JBUEggPSAweDAwMlxuICAgICAqIENPUkVNTF9GTEFHX09OTFlfRU5BQkxFX0RFVklDRV9XSVRIX0FORSA9IDB4MDA0XG4gICAgICogQ09SRU1MX0ZMQUdfT05MWV9BTExPV19TVEFUSUNfSU5QVVRfU0hBUEVTID0gMHgwMDhcbiAgICAgKiBDT1JFTUxfRkxBR19DUkVBVEVfTUxQUk9HUkFNID0gMHgwMTBcbiAgICAgKiBDT1JFTUxfRkxBR19VU0VfQ1BVX0FORF9HUFUgPSAweDAyMFxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogU2VlIGluY2x1ZGUvb25ueHJ1bnRpbWUvY29yZS9wcm92aWRlcnMvY29yZW1sL2NvcmVtbF9wcm92aWRlcl9mYWN0b3J5LmggZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIFRoaXMgZmxhZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nKS5cbiAgICAgKi9cbiAgICBjb3JlTWxGbGFncz86IG51bWJlcjtcbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IHdoZXRoZXIgdG8gdXNlIENQVSBvbmx5IGluIENvcmVNTCBFUC5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAocmVhY3QtbmF0aXZlKS5cbiAgICAgKi9cbiAgICB1c2VDUFVPbmx5PzogYm9vbGVhbjtcbiAgICB1c2VDUFVBbmRHUFU/OiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgd2hldGhlciB0byBlbmFibGUgQ29yZU1MIEVQIG9uIHN1YmdyYXBoLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChyZWFjdC1uYXRpdmUpLlxuICAgICAqL1xuICAgIGVuYWJsZU9uU3ViZ3JhcGg/OiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgd2hldGhlciB0byBvbmx5IGVuYWJsZSBDb3JlTUwgRVAgZm9yIEFwcGxlIGRldmljZXMgd2l0aCBBTkUgKEFwcGxlIE5ldXJhbCBFbmdpbmUpLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChyZWFjdC1uYXRpdmUpLlxuICAgICAqL1xuICAgIG9ubHlFbmFibGVEZXZpY2VXaXRoQU5FPzogYm9vbGVhbjtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIE5uYXBpRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ25uYXBpJztcbiAgICB1c2VGUDE2PzogYm9vbGVhbjtcbiAgICB1c2VOQ0hXPzogYm9vbGVhbjtcbiAgICBjcHVEaXNhYmxlZD86IGJvb2xlYW47XG4gICAgY3B1T25seT86IGJvb2xlYW47XG4gIH1cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIHJ1biBvcHRpb25zXG5cbiAgLyoqXG4gICAqIEEgc2V0IG9mIGNvbmZpZ3VyYXRpb25zIGZvciBpbmZlcmVuY2UgcnVuIGJlaGF2aW9yXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIFJ1bk9wdGlvbnMge1xuICAgIC8qKlxuICAgICAqIExvZyBzZXZlcml0eSBsZXZlbC4gU2VlXG4gICAgICogaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9vbm54cnVudGltZS9ibG9iL21haW4vaW5jbHVkZS9vbm54cnVudGltZS9jb3JlL2NvbW1vbi9sb2dnaW5nL3NldmVyaXR5LmhcbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpIG9yIFdlYkFzc2VtYmx5IGJhY2tlbmRcbiAgICAgKi9cbiAgICBsb2dTZXZlcml0eUxldmVsPzogMCB8IDEgfCAyIHwgMyB8IDQ7XG5cbiAgICAvKipcbiAgICAgKiBMb2cgdmVyYm9zaXR5IGxldmVsLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIFdlYkFzc2VtYmx5IGJhY2tlbmQuIFdpbGwgc3VwcG9ydCBOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSBsYXRlclxuICAgICAqL1xuICAgIGxvZ1ZlcmJvc2l0eUxldmVsPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogVGVybWluYXRlIGFsbCBpbmNvbXBsZXRlIE9ydFJ1biBjYWxscyBhcyBzb29uIGFzIHBvc3NpYmxlIGlmIHRydWVcbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBXZWJBc3NlbWJseSBiYWNrZW5kLiBXaWxsIHN1cHBvcnQgTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUgbGF0ZXJcbiAgICAgKi9cbiAgICB0ZXJtaW5hdGU/OiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogQSB0YWcgZm9yIHRoZSBSdW4oKSBjYWxscyB1c2luZyB0aGlzXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKSBvciBXZWJBc3NlbWJseSBiYWNrZW5kXG4gICAgICovXG4gICAgdGFnPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogU2V0IGEgc2luZ2xlIHJ1biBjb25maWd1cmF0aW9uIGVudHJ5LiBTZWVcbiAgICAgKiBodHRwczovL2dpdGh1Yi5jb20vbWljcm9zb2Z0L29ubnhydW50aW1lL2Jsb2IvbWFpbi9pbmNsdWRlL29ubnhydW50aW1lL2NvcmUvc2Vzc2lvbi9cbiAgICAgKiBvbm54cnVudGltZV9ydW5fb3B0aW9uc19jb25maWdfa2V5cy5oXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gV2ViQXNzZW1ibHkgYmFja2VuZC4gV2lsbCBzdXBwb3J0IE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlIGxhdGVyXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBleHRyYToge1xuICAgICAqICAgbWVtb3J5OiB7XG4gICAgICogICAgIGVuYWJsZV9tZW1vcnlfYXJlbmFfc2hyaW5rYWdlOiBcIjFcIixcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZXh0cmE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgfVxuXG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIHZhbHVlIG1ldGFkYXRhXG5cbiAgLyoqXG4gICAqIFRoZSBjb21tb24gcGFydCBvZiB0aGUgdmFsdWUgbWV0YWRhdGEgdHlwZSBmb3IgYm90aCB0ZW5zb3IgYW5kIG5vbi10ZW5zb3IgdmFsdWVzLlxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBWYWx1ZU1ldGFkYXRhQmFzZSB7XG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHNwZWNpZmllZCBpbnB1dCBvciBvdXRwdXQuXG4gICAgICovXG4gICAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgdGhlIG1ldGFkYXRhIG9mIGEgbm9uLXRlbnNvciB2YWx1ZS5cbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgTm9uVGVuc29yVmFsdWVNZXRhZGF0YSBleHRlbmRzIFZhbHVlTWV0YWRhdGFCYXNlIHtcbiAgICAvKipcbiAgICAgKiBHZXQgYSB2YWx1ZSBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIHZhbHVlIGlzIGEgdGVuc29yLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IGlzVGVuc29yOiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIHRoZSBtZXRhZGF0YSBvZiBhIHRlbnNvciB2YWx1ZS5cbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgVGVuc29yVmFsdWVNZXRhZGF0YSBleHRlbmRzIFZhbHVlTWV0YWRhdGFCYXNlIHtcbiAgICAvKipcbiAgICAgKiBHZXQgYSB2YWx1ZSBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIHZhbHVlIGlzIGEgdGVuc29yLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IGlzVGVuc29yOiB0cnVlO1xuICAgIC8qKlxuICAgICAqIEdldCB0aGUgZGF0YSB0eXBlIG9mIHRoZSB0ZW5zb3IuXG4gICAgICovXG4gICAgcmVhZG9ubHkgdHlwZTogVGVuc29yLlR5cGU7XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBzaGFwZSBvZiB0aGUgdGVuc29yLlxuICAgICAqXG4gICAgICogSWYgdGhlIHNoYXBlIGlzIG5vdCBkZWZpbmVkLCB0aGUgdmFsdWUgd2lsbCBhbiBlbXB0eSBhcnJheS4gT3RoZXJ3aXNlLCBpdCB3aWxsIGJlIGFuIGFycmF5IHJlcHJlc2VudGluZyB0aGUgc2hhcGVcbiAgICAgKiBvZiB0aGUgdGVuc29yLiBFYWNoIGVsZW1lbnQgaW4gdGhlIGFycmF5IGNhbiBiZSBhIG51bWJlciBvciBhIHN0cmluZy4gSWYgdGhlIGVsZW1lbnQgaXMgYSBudW1iZXIsIGl0IHJlcHJlc2VudHNcbiAgICAgKiB0aGUgY29ycmVzcG9uZGluZyBkaW1lbnNpb24gc2l6ZS4gSWYgdGhlIGVsZW1lbnQgaXMgYSBzdHJpbmcsIGl0IHJlcHJlc2VudHMgYSBzeW1ib2xpYyBkaW1lbnNpb24uXG4gICAgICovXG4gICAgcmVhZG9ubHkgc2hhcGU6IFJlYWRvbmx5QXJyYXk8bnVtYmVyIHwgc3RyaW5nPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIHRoZSBtZXRhZGF0YSBvZiBhIHZhbHVlLlxuICAgKi9cbiAgZXhwb3J0IHR5cGUgVmFsdWVNZXRhZGF0YSA9IE5vblRlbnNvclZhbHVlTWV0YWRhdGEgfCBUZW5zb3JWYWx1ZU1ldGFkYXRhO1xuXG4gIC8vICNlbmRyZWdpb25cbn1cblxuLyoqXG4gKiBSZXByZXNlbnQgYSBydW50aW1lIGluc3RhbmNlIG9mIGFuIE9OTlggbW9kZWwuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW5mZXJlbmNlU2Vzc2lvbiB7XG4gIC8vICNyZWdpb24gcnVuKClcblxuICAvKipcbiAgICogRXhlY3V0ZSB0aGUgbW9kZWwgYXN5bmNocm9ub3VzbHkgd2l0aCB0aGUgZ2l2ZW4gZmVlZHMgYW5kIG9wdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSBmZWVkcyAtIFJlcHJlc2VudGF0aW9uIG9mIHRoZSBtb2RlbCBpbnB1dC4gU2VlIHR5cGUgZGVzY3JpcHRpb24gb2YgYEluZmVyZW5jZVNlc3Npb24uSW5wdXRUeXBlYCBmb3IgZGV0YWlsLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbmFsLiBBIHNldCBvZiBvcHRpb25zIHRoYXQgY29udHJvbHMgdGhlIGJlaGF2aW9yIG9mIG1vZGVsIGluZmVyZW5jZS5cbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBtYXAsIHdoaWNoIHVzZXMgb3V0cHV0IG5hbWVzIGFzIGtleXMgYW5kIE9ubnhWYWx1ZSBhcyBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgICovXG4gIHJ1bihmZWVkczogSW5mZXJlbmNlU2Vzc2lvbi5GZWVkc1R5cGUsIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMpOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb24uUmV0dXJuVHlwZT47XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGUgdGhlIG1vZGVsIGFzeW5jaHJvbm91c2x5IHdpdGggdGhlIGdpdmVuIGZlZWRzLCBmZXRjaGVzIGFuZCBvcHRpb25zLlxuICAgKlxuICAgKiBAcGFyYW0gZmVlZHMgLSBSZXByZXNlbnRhdGlvbiBvZiB0aGUgbW9kZWwgaW5wdXQuIFNlZSB0eXBlIGRlc2NyaXB0aW9uIG9mIGBJbmZlcmVuY2VTZXNzaW9uLklucHV0VHlwZWAgZm9yIGRldGFpbC5cbiAgICogQHBhcmFtIGZldGNoZXMgLSBSZXByZXNlbnRhdGlvbiBvZiB0aGUgbW9kZWwgb3V0cHV0LiBTZWUgdHlwZSBkZXNjcmlwdGlvbiBvZiBgSW5mZXJlbmNlU2Vzc2lvbi5PdXRwdXRUeXBlYCBmb3JcbiAgICogZGV0YWlsLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbmFsLiBBIHNldCBvZiBvcHRpb25zIHRoYXQgY29udHJvbHMgdGhlIGJlaGF2aW9yIG9mIG1vZGVsIGluZmVyZW5jZS5cbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBtYXAsIHdoaWNoIHVzZXMgb3V0cHV0IG5hbWVzIGFzIGtleXMgYW5kIE9ubnhWYWx1ZSBhcyBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgICovXG4gIHJ1bihcbiAgICBmZWVkczogSW5mZXJlbmNlU2Vzc2lvbi5GZWVkc1R5cGUsXG4gICAgZmV0Y2hlczogSW5mZXJlbmNlU2Vzc2lvbi5GZXRjaGVzVHlwZSxcbiAgICBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zLFxuICApOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb24uUmV0dXJuVHlwZT47XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gcmVsZWFzZSgpXG5cbiAgLyoqXG4gICAqIFJlbGVhc2UgdGhlIGluZmVyZW5jZSBzZXNzaW9uIGFuZCB0aGUgdW5kZXJseWluZyByZXNvdXJjZXMuXG4gICAqL1xuICByZWxlYXNlKCk6IFByb21pc2U8dm9pZD47XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gcHJvZmlsaW5nXG5cbiAgLyoqXG4gICAqIFN0YXJ0IHByb2ZpbGluZy5cbiAgICovXG4gIHN0YXJ0UHJvZmlsaW5nKCk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIEVuZCBwcm9maWxpbmcuXG4gICAqL1xuICBlbmRQcm9maWxpbmcoKTogdm9pZDtcblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBtZXRhZGF0YVxuXG4gIC8qKlxuICAgKiBHZXQgaW5wdXQgbmFtZXMgb2YgdGhlIGxvYWRlZCBtb2RlbC5cbiAgICovXG4gIHJlYWRvbmx5IGlucHV0TmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBHZXQgb3V0cHV0IG5hbWVzIG9mIHRoZSBsb2FkZWQgbW9kZWwuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXROYW1lczogcmVhZG9ubHkgc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEdldCBpbnB1dCBtZXRhZGF0YSBvZiB0aGUgbG9hZGVkIG1vZGVsLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5wdXRNZXRhZGF0YTogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbi5WYWx1ZU1ldGFkYXRhW107XG5cbiAgLyoqXG4gICAqIEdldCBvdXRwdXQgbWV0YWRhdGEgb2YgdGhlIGxvYWRlZCBtb2RlbC5cbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dE1ldGFkYXRhOiByZWFkb25seSBJbmZlcmVuY2VTZXNzaW9uLlZhbHVlTWV0YWRhdGFbXTtcblxuICAvLyAjZW5kcmVnaW9uXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5mZXJlbmNlU2Vzc2lvbkZhY3Rvcnkge1xuICAvLyAjcmVnaW9uIGNyZWF0ZSgpXG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBpbmZlcmVuY2Ugc2Vzc2lvbiBhbmQgbG9hZCBtb2RlbCBhc3luY2hyb25vdXNseSBmcm9tIGFuIE9OTlggbW9kZWwgZmlsZS5cbiAgICpcbiAgICogQHBhcmFtIHVyaSAtIFRoZSBVUkkgb3IgZmlsZSBwYXRoIG9mIHRoZSBtb2RlbCB0byBsb2FkLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIHNwZWNpZnkgY29uZmlndXJhdGlvbiBmb3IgY3JlYXRpbmcgYSBuZXcgaW5mZXJlbmNlIHNlc3Npb24uXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIEluZmVyZW5jZVNlc3Npb24gb2JqZWN0LlxuICAgKi9cbiAgY3JlYXRlKHVyaTogc3RyaW5nLCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbj47XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBpbmZlcmVuY2Ugc2Vzc2lvbiBhbmQgbG9hZCBtb2RlbCBhc3luY2hyb25vdXNseSBmcm9tIGFuIGFycmF5IGJ1ZmVyLlxuICAgKlxuICAgKiBAcGFyYW0gYnVmZmVyIC0gQW4gQXJyYXlCdWZmZXIgcmVwcmVzZW50YXRpb24gb2YgYW4gT05OWCBtb2RlbC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBzcGVjaWZ5IGNvbmZpZ3VyYXRpb24gZm9yIGNyZWF0aW5nIGEgbmV3IGluZmVyZW5jZSBzZXNzaW9uLlxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBJbmZlcmVuY2VTZXNzaW9uIG9iamVjdC5cbiAgICovXG4gIGNyZWF0ZShidWZmZXI6IEFycmF5QnVmZmVyTGlrZSwgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb24+O1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgaW5mZXJlbmNlIHNlc3Npb24gYW5kIGxvYWQgbW9kZWwgYXN5bmNocm9ub3VzbHkgZnJvbSBzZWdtZW50IG9mIGFuIGFycmF5IGJ1ZmVyLlxuICAgKlxuICAgKiBAcGFyYW0gYnVmZmVyIC0gQW4gQXJyYXlCdWZmZXIgcmVwcmVzZW50YXRpb24gb2YgYW4gT05OWCBtb2RlbC5cbiAgICogQHBhcmFtIGJ5dGVPZmZzZXQgLSBUaGUgYmVnaW5uaW5nIG9mIHRoZSBzcGVjaWZpZWQgcG9ydGlvbiBvZiB0aGUgYXJyYXkgYnVmZmVyLlxuICAgKiBAcGFyYW0gYnl0ZUxlbmd0aCAtIFRoZSBsZW5ndGggaW4gYnl0ZXMgb2YgdGhlIGFycmF5IGJ1ZmZlci5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBzcGVjaWZ5IGNvbmZpZ3VyYXRpb24gZm9yIGNyZWF0aW5nIGEgbmV3IGluZmVyZW5jZSBzZXNzaW9uLlxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBJbmZlcmVuY2VTZXNzaW9uIG9iamVjdC5cbiAgICovXG4gIGNyZWF0ZShcbiAgICBidWZmZXI6IEFycmF5QnVmZmVyTGlrZSxcbiAgICBieXRlT2Zmc2V0OiBudW1iZXIsXG4gICAgYnl0ZUxlbmd0aD86IG51bWJlcixcbiAgICBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uPjtcblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IGluZmVyZW5jZSBzZXNzaW9uIGFuZCBsb2FkIG1vZGVsIGFzeW5jaHJvbm91c2x5IGZyb20gYSBVaW50OEFycmF5LlxuICAgKlxuICAgKiBAcGFyYW0gYnVmZmVyIC0gQSBVaW50OEFycmF5IHJlcHJlc2VudGF0aW9uIG9mIGFuIE9OTlggbW9kZWwuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gc3BlY2lmeSBjb25maWd1cmF0aW9uIGZvciBjcmVhdGluZyBhIG5ldyBpbmZlcmVuY2Ugc2Vzc2lvbi5cbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gSW5mZXJlbmNlU2Vzc2lvbiBvYmplY3QuXG4gICAqL1xuICBjcmVhdGUoYnVmZmVyOiBVaW50OEFycmF5LCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbj47XG5cbiAgLy8gI2VuZHJlZ2lvblxufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG5leHBvcnQgY29uc3QgSW5mZXJlbmNlU2Vzc2lvbjogSW5mZXJlbmNlU2Vzc2lvbkZhY3RvcnkgPSBJbmZlcmVuY2VTZXNzaW9uSW1wbDtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgT3B0aW9uc0Zvcm1hdCwgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzLCBPcHRpb25zVGVuc29yTGF5b3V0IH0gZnJvbSAnLi90ZW5zb3ItZmFjdG9yeS5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yVG9EYXRhVXJsT3B0aW9ucyBleHRlbmRzIE9wdGlvbnNUZW5zb3JMYXlvdXQsIE9wdGlvbnNGb3JtYXQsIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycyB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvclRvSW1hZ2VEYXRhT3B0aW9ucyBleHRlbmRzIE9wdGlvbnNUZW5zb3JMYXlvdXQsIE9wdGlvbnNGb3JtYXQsIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycyB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnZlcnNpb25VdGlscyB7XG4gIC8qKlxuICAgKiBjcmVhdGVzIGEgRGF0YVVSTCBpbnN0YW5jZSBmcm9tIHRlbnNvclxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIG9iamVjdCByZXByZXNlbnRpbmcgb3B0aW9ucyBmb3IgY3JlYXRpbmcgYSBEYXRhVVJMIGluc3RhbmNlIGZyb20gdGhlIHRlbnNvci5cbiAgICpcbiAgICogVGhlIGZvbGxvd2luZyBkZWZhdWx0IHNldHRpbmdzIHdpbGwgYmUgYXBwbGllZDpcbiAgICogLSBgZm9ybWF0YDogYCdSR0InYFxuICAgKiAtIGB0ZW5zb3JMYXlvdXRgOiBgJ05DSFcnYFxuICAgKiBAcmV0dXJucyBhIERhdGFVUkwgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgaW1hZ2UgY29udmVydGVkIGZyb20gdGVuc29yIGRhdGFcbiAgICovXG4gIHRvRGF0YVVSTChvcHRpb25zPzogVGVuc29yVG9EYXRhVXJsT3B0aW9ucyk6IHN0cmluZztcblxuICAvKipcbiAgICogY3JlYXRlcyBhbiBJbWFnZURhdGEgaW5zdGFuY2UgZnJvbSB0ZW5zb3JcbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBbiBvcHRpb25hbCBvYmplY3QgcmVwcmVzZW50aW5nIG9wdGlvbnMgZm9yIGNyZWF0aW5nIGFuIEltYWdlRGF0YSBpbnN0YW5jZSBmcm9tIHRoZSB0ZW5zb3IuXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgZGVmYXVsdCBzZXR0aW5ncyB3aWxsIGJlIGFwcGxpZWQ6XG4gICAqIC0gYGZvcm1hdGA6IGAnUkdCJ2BcbiAgICogLSBgdGVuc29yTGF5b3V0YDogYCdOQ0hXJ2BcbiAgICogQHJldHVybnMgYW4gSW1hZ2VEYXRhIGluc3RhbmNlIHJlcHJlc2VudGluZyB0aGUgaW1hZ2UgY29udmVydGVkIGZyb20gdGVuc29yIGRhdGFcbiAgICovXG4gIHRvSW1hZ2VEYXRhKG9wdGlvbnM/OiBUZW5zb3JUb0ltYWdlRGF0YU9wdGlvbnMpOiBJbWFnZURhdGE7XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvciwgVHlwZWRUZW5zb3IgfSBmcm9tICcuL3RlbnNvci5qcyc7XG5cbmV4cG9ydCB0eXBlIEltYWdlRm9ybWF0ID0gJ1JHQicgfCAnUkdCQScgfCAnQkdSJyB8ICdSQkcnO1xuZXhwb3J0IHR5cGUgSW1hZ2VUZW5zb3JMYXlvdXQgPSAnTkhXQycgfCAnTkNIVyc7XG5cbi8vIHRoZSBmb2xsb3dpbmcgcmVnaW9uIGNvbnRhaW5zIHR5cGUgZGVmaW5pdGlvbnMgZm9yIGNvbnN0cnVjdGluZyB0ZW5zb3IgZnJvbSBhIHNwZWNpZmljIGxvY2F0aW9uLlxuXG4vLyAjcmVnaW9uIHR5cGVzIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIHNwZWNpZmljIGxvY2F0aW9uXG5cbi8qKlxuICogcmVwcmVzZW50IGNvbW1vbiBwcm9wZXJ0aWVzIG9mIHRoZSBwYXJhbWV0ZXIgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgc3BlY2lmaWMgbG9jYXRpb24uXG4gKi9cbmludGVyZmFjZSBDb21tb25Db25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4gZXh0ZW5kcyBQaWNrPFRlbnNvciwgJ2RpbXMnPiB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBkYXRhIHR5cGUgb2YgdGhlIHRlbnNvci5cbiAgICovXG4gIHJlYWRvbmx5IHR5cGU6IFQ7XG59XG5cbi8qKlxuICogcmVwcmVzZW50IHRoZSBwYXJhbWV0ZXIgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgR1BVIHJlc291cmNlLlxuICovXG5pbnRlcmZhY2UgR3B1UmVzb3VyY2VDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VCBleHRlbmRzIFRlbnNvci5UeXBlPiB7XG4gIC8qKlxuICAgKiBhbiBvcHRpb25hbCBjYWxsYmFjayBmdW5jdGlvbiB0byBkb3dubG9hZCBkYXRhIGZyb20gR1BVIHRvIENQVS5cbiAgICpcbiAgICogSWYgbm90IHByb3ZpZGVkLCB0aGUgdGVuc29yIHRyZWF0IHRoZSBHUFUgZGF0YSBhcyBleHRlcm5hbCByZXNvdXJjZS5cbiAgICovXG4gIGRvd25sb2FkPygpOiBQcm9taXNlPFRlbnNvci5EYXRhVHlwZU1hcFtUXT47XG5cbiAgLyoqXG4gICAqIGFuIG9wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2hlbiB0aGUgdGVuc29yIGlzIGRpc3Bvc2VkLlxuICAgKlxuICAgKiBJZiBub3QgcHJvdmlkZWQsIHRoZSB0ZW5zb3IgdHJlYXQgdGhlIEdQVSBkYXRhIGFzIGV4dGVybmFsIHJlc291cmNlLlxuICAgKi9cbiAgZGlzcG9zZT8oKTogdm9pZDtcbn1cblxuLyoqXG4gKiByZXByZXNlbnQgdGhlIHBhcmFtZXRlciBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBwaW5uZWQgQ1BVIGJ1ZmZlclxuICovXG5leHBvcnQgaW50ZXJmYWNlIENwdVBpbm5lZENvbnN0cnVjdG9yUGFyYW1ldGVyczxUIGV4dGVuZHMgVGVuc29yLkNwdVBpbm5lZERhdGFUeXBlcyA9IFRlbnNvci5DcHVQaW5uZWREYXRhVHlwZXM+XG4gIGV4dGVuZHMgQ29tbW9uQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+IHtcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIGxvY2F0aW9uIG9mIHRoZSBkYXRhIHRvIGJlICdjcHUtcGlubmVkJy5cbiAgICovXG4gIHJlYWRvbmx5IGxvY2F0aW9uOiAnY3B1LXBpbm5lZCc7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBDUFUgcGlubmVkIGJ1ZmZlciB0aGF0IGhvbGRzIHRoZSB0ZW5zb3IgZGF0YS5cbiAgICovXG4gIHJlYWRvbmx5IGRhdGE6IFRlbnNvci5EYXRhVHlwZU1hcFtUXTtcbn1cblxuLyoqXG4gKiByZXByZXNlbnQgdGhlIHBhcmFtZXRlciBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBXZWJHTCB0ZXh0dXJlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGV4dHVyZUNvbnN0cnVjdG9yUGFyYW1ldGVyczxUIGV4dGVuZHMgVGVuc29yLlRleHR1cmVEYXRhVHlwZXMgPSBUZW5zb3IuVGV4dHVyZURhdGFUeXBlcz5cbiAgZXh0ZW5kcyBDb21tb25Db25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4sXG4gICAgR3B1UmVzb3VyY2VDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4ge1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgbG9jYXRpb24gb2YgdGhlIGRhdGEgdG8gYmUgJ3RleHR1cmUnLlxuICAgKi9cbiAgcmVhZG9ubHkgbG9jYXRpb246ICd0ZXh0dXJlJztcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIFdlYkdMIHRleHR1cmUgdGhhdCBob2xkcyB0aGUgdGVuc29yIGRhdGEuXG4gICAqL1xuICByZWFkb25seSB0ZXh0dXJlOiBUZW5zb3IuVGV4dHVyZVR5cGU7XG59XG5cbi8qKlxuICogcmVwcmVzZW50IHRoZSBwYXJhbWV0ZXIgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgV2ViR1BVIGJ1ZmZlclxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdwdUJ1ZmZlckNvbnN0cnVjdG9yUGFyYW1ldGVyczxUIGV4dGVuZHMgVGVuc29yLkdwdUJ1ZmZlckRhdGFUeXBlcyA9IFRlbnNvci5HcHVCdWZmZXJEYXRhVHlwZXM+XG4gIGV4dGVuZHMgQ29tbW9uQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+LFxuICAgIEdwdVJlc291cmNlQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+IHtcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIGxvY2F0aW9uIG9mIHRoZSBkYXRhIHRvIGJlICdncHUtYnVmZmVyJy5cbiAgICovXG4gIHJlYWRvbmx5IGxvY2F0aW9uOiAnZ3B1LWJ1ZmZlcic7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBXZWJHUFUgYnVmZmVyIHRoYXQgaG9sZHMgdGhlIHRlbnNvciBkYXRhLlxuICAgKi9cbiAgcmVhZG9ubHkgZ3B1QnVmZmVyOiBUZW5zb3IuR3B1QnVmZmVyVHlwZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNTFRlbnNvckNvbnN0cnVjdG9yUGFyYW1ldGVyczxUIGV4dGVuZHMgVGVuc29yLk1MVGVuc29yRGF0YVR5cGVzID0gVGVuc29yLk1MVGVuc29yRGF0YVR5cGVzPlxuICBleHRlbmRzIENvbW1vbkNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPixcbiAgICBHcHVSZXNvdXJjZUNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPiB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBsb2NhdGlvbiBvZiB0aGUgZGF0YSB0byBiZSAnbWwtdGVuc29yJy5cbiAgICovXG4gIHJlYWRvbmx5IGxvY2F0aW9uOiAnbWwtdGVuc29yJztcblxuICAvKipcbiAgICogU3BlY2lmeSB0aGUgV2ViTk4gTUxUZW5zb3IgdGhhdCBob2xkcyB0aGUgdGVuc29yIGRhdGEuXG4gICAqL1xuICByZWFkb25seSBtbFRlbnNvcjogVGVuc29yLk1MVGVuc29yVHlwZTtcbn1cblxuLy8gI2VuZHJlZ2lvblxuXG4vLyB0aGUgZm9sbG93aW5nIHJlZ2lvbiBjb250YWlucyB0eXBlIGRlZmluaXRpb25zIG9mIGVhY2ggaW5kaXZpZHVhbCBvcHRpb25zLlxuLy8gdGhlIHRlbnNvciBmYWN0b3J5IGZ1bmN0aW9ucyB1c2UgYSBjb21wb3NpdGlvbiBvZiB0aG9zZSBvcHRpb25zIGFzIHRoZSBwYXJhbWV0ZXIgdHlwZS5cblxuLy8gI3JlZ2lvbiBPcHRpb25zIGZpZWxkc1xuXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvbnNGb3JtYXQge1xuICAvKipcbiAgICogRGVzY3JpYmVzIHRoZSBpbWFnZSBmb3JtYXQgcmVwcmVzZW50ZWQgaW4gUkdCQSBjb2xvciBzcGFjZS5cbiAgICovXG4gIGZvcm1hdD86IEltYWdlRm9ybWF0O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvbnNUZW5zb3JGb3JtYXQge1xuICAvKipcbiAgICogRGVzY3JpYmVzIHRoZSBpbWFnZSBmb3JtYXQgb2YgdGhlIHRlbnNvci5cbiAgICpcbiAgICogTk9URTogdGhpcyBpcyBkaWZmZXJlbnQgZnJvbSBvcHRpb24gJ2Zvcm1hdCcuIFdoaWxlIG9wdGlvbiAnZm9ybWF0JyByZXByZXNlbnRzIHRoZSBvcmlnaW5hbCBpbWFnZSwgJ3RlbnNvckZvcm1hdCdcbiAgICogcmVwcmVzZW50cyB0aGUgdGFyZ2V0IGZvcm1hdCBvZiB0aGUgdGVuc29yLiBBIHRyYW5zcG9zZSB3aWxsIGJlIHBlcmZvcm1lZCBpZiB0aGV5IGFyZSBkaWZmZXJlbnQuXG4gICAqL1xuICB0ZW5zb3JGb3JtYXQ/OiBJbWFnZUZvcm1hdDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zVGVuc29yRGF0YVR5cGUge1xuICAvKipcbiAgICogRGVzY3JpYmVzIHRoZSBkYXRhIHR5cGUgb2YgdGhlIHRlbnNvci5cbiAgICovXG4gIGRhdGFUeXBlPzogJ2Zsb2F0MzInIHwgJ3VpbnQ4Jztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zVGVuc29yTGF5b3V0IHtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyB0aGUgdGVuc29yIGxheW91dCB3aGVuIHJlcHJlc2VudGluZyBkYXRhIG9mIG9uZSBvciBtb3JlIGltYWdlKHMpLlxuICAgKi9cbiAgdGVuc29yTGF5b3V0PzogSW1hZ2VUZW5zb3JMYXlvdXQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uc0RpbWVuc2lvbnMge1xuICAvKipcbiAgICogRGVzY3JpYmVzIHRoZSBpbWFnZSBoZWlnaHQgaW4gcGl4ZWxcbiAgICovXG4gIGhlaWdodD86IG51bWJlcjtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyB0aGUgaW1hZ2Ugd2lkdGggaW4gcGl4ZWxcbiAgICovXG4gIHdpZHRoPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvblJlc2l6ZWREaW1lbnNpb25zIHtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyB0aGUgcmVzaXplZCBoZWlnaHQuIElmIG9taXR0ZWQsIG9yaWdpbmFsIGhlaWdodCB3aWxsIGJlIHVzZWQuXG4gICAqL1xuICByZXNpemVkSGVpZ2h0PzogbnVtYmVyO1xuICAvKipcbiAgICogRGVzY3JpYmVzIHJlc2l6ZWQgd2lkdGggLSBjYW4gYmUgYWNjZXNzZWQgdmlhIHRlbnNvciBkaW1lbnNpb25zIGFzIHdlbGxcbiAgICovXG4gIHJlc2l6ZWRXaWR0aD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMge1xuICAvKipcbiAgICogRGVzY3JpYmVzIG5vcm1hbGl6YXRpb24gcGFyYW1ldGVycyB3aGVuIHByZXByb2Nlc3NpbmcgdGhlIGltYWdlIGFzIG1vZGVsIGlucHV0LlxuICAgKlxuICAgKiBEYXRhIGVsZW1lbnQgYXJlIHJhbmdlZCBmcm9tIDAgdG8gMjU1LlxuICAgKi9cbiAgbm9ybT86IHtcbiAgICAvKipcbiAgICAgKiBUaGUgJ2JpYXMnIHZhbHVlIGZvciBpbWFnZSBub3JtYWxpemF0aW9uLlxuICAgICAqIC0gSWYgb21pdHRlZCwgdXNlIGRlZmF1bHQgdmFsdWUgMC5cbiAgICAgKiAtIElmIGl0J3MgYSBzaW5nbGUgbnVtYmVyLCBhcHBseSB0byBlYWNoIGNoYW5uZWxcbiAgICAgKiAtIElmIGl0J3MgYW4gYXJyYXkgb2YgMyBvciA0IG51bWJlcnMsIGFwcGx5IGVsZW1lbnQtd2lzZS4gTnVtYmVyIG9mIGVsZW1lbnRzIG5lZWQgdG8gbWF0Y2ggdGhlIG51bWJlciBvZiBjaGFubmVsc1xuICAgICAqIGZvciB0aGUgY29ycmVzcG9uZGluZyBpbWFnZSBmb3JtYXRcbiAgICAgKi9cbiAgICBiaWFzPzogbnVtYmVyIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXJdIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gICAgLyoqXG4gICAgICogVGhlICdtZWFuJyB2YWx1ZSBmb3IgaW1hZ2Ugbm9ybWFsaXphdGlvbi5cbiAgICAgKiAtIElmIG9taXR0ZWQsIHVzZSBkZWZhdWx0IHZhbHVlIDI1NS5cbiAgICAgKiAtIElmIGl0J3MgYSBzaW5nbGUgbnVtYmVyLCBhcHBseSB0byBlYWNoIGNoYW5uZWxcbiAgICAgKiAtIElmIGl0J3MgYW4gYXJyYXkgb2YgMyBvciA0IG51bWJlcnMsIGFwcGx5IGVsZW1lbnQtd2lzZS4gTnVtYmVyIG9mIGVsZW1lbnRzIG5lZWQgdG8gbWF0Y2ggdGhlIG51bWJlciBvZiBjaGFubmVsc1xuICAgICAqIGZvciB0aGUgY29ycmVzcG9uZGluZyBpbWFnZSBmb3JtYXRcbiAgICAgKi9cbiAgICBtZWFuPzogbnVtYmVyIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXJdIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gIH07XG59XG5cbi8vICNlbmRyZWdpb25cblxuLy8gI3JlZ2lvbiBPcHRpb25zIGNvbXBvc2l0aW9uXG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yRnJvbUltYWdlRGF0YU9wdGlvbnNcbiAgZXh0ZW5kcyBPcHRpb25SZXNpemVkRGltZW5zaW9ucyxcbiAgICBPcHRpb25zVGVuc29yRm9ybWF0LFxuICAgIE9wdGlvbnNUZW5zb3JMYXlvdXQsXG4gICAgT3B0aW9uc1RlbnNvckRhdGFUeXBlLFxuICAgIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycyB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckZyb21JbWFnZUVsZW1lbnRPcHRpb25zXG4gIGV4dGVuZHMgT3B0aW9uUmVzaXplZERpbWVuc2lvbnMsXG4gICAgT3B0aW9uc1RlbnNvckZvcm1hdCxcbiAgICBPcHRpb25zVGVuc29yTGF5b3V0LFxuICAgIE9wdGlvbnNUZW5zb3JEYXRhVHlwZSxcbiAgICBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMge31cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JGcm9tVXJsT3B0aW9uc1xuICBleHRlbmRzIE9wdGlvbnNEaW1lbnNpb25zLFxuICAgIE9wdGlvblJlc2l6ZWREaW1lbnNpb25zLFxuICAgIE9wdGlvbnNUZW5zb3JGb3JtYXQsXG4gICAgT3B0aW9uc1RlbnNvckxheW91dCxcbiAgICBPcHRpb25zVGVuc29yRGF0YVR5cGUsXG4gICAgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yRnJvbUltYWdlQml0bWFwT3B0aW9uc1xuICBleHRlbmRzIE9wdGlvblJlc2l6ZWREaW1lbnNpb25zLFxuICAgIE9wdGlvbnNUZW5zb3JGb3JtYXQsXG4gICAgT3B0aW9uc1RlbnNvckxheW91dCxcbiAgICBPcHRpb25zVGVuc29yRGF0YVR5cGUsXG4gICAgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yRnJvbVRleHR1cmVPcHRpb25zPFQgZXh0ZW5kcyBUZW5zb3IuVGV4dHVyZURhdGFUeXBlcz5cbiAgZXh0ZW5kcyBSZXF1aXJlZDxPcHRpb25zRGltZW5zaW9ucz4sXG4gICAgT3B0aW9uc0Zvcm1hdCxcbiAgICBHcHVSZXNvdXJjZUNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPiAvKiBUT0RPOiBhZGQgbW9yZSAqLyB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckZyb21HcHVCdWZmZXJPcHRpb25zPFQgZXh0ZW5kcyBUZW5zb3IuR3B1QnVmZmVyRGF0YVR5cGVzPlxuICBleHRlbmRzIFBpY2s8VGVuc29yLCAnZGltcyc+LFxuICAgIEdwdVJlc291cmNlQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+IHtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyB0aGUgZGF0YSB0eXBlIG9mIHRoZSB0ZW5zb3IuXG4gICAqL1xuICBkYXRhVHlwZT86IFQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yRnJvbU1MVGVuc29yT3B0aW9uczxUIGV4dGVuZHMgVGVuc29yLk1MVGVuc29yRGF0YVR5cGVzPlxuICBleHRlbmRzIFBpY2s8VGVuc29yLCAnZGltcyc+LFxuICAgIEdwdVJlc291cmNlQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+IHtcbiAgLyoqXG4gICAqIERlc2NyaWJlcyB0aGUgZGF0YSB0eXBlIG9mIHRoZSB0ZW5zb3IuXG4gICAqL1xuICBkYXRhVHlwZT86IFQ7XG59XG5cbi8vICNlbmRyZWdpb25cblxuLyoqXG4gKiB0eXBlIFRlbnNvckZhY3RvcnkgZGVmaW5lcyB0aGUgZmFjdG9yeSBmdW5jdGlvbnMgb2YgJ1RlbnNvcicgdG8gY3JlYXRlIHRlbnNvciBpbnN0YW5jZXMgZnJvbSBleGlzdGluZyBkYXRhIG9yXG4gKiByZXNvdXJjZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yRmFjdG9yeSB7XG4gIC8qKlxuICAgKiBjcmVhdGUgYSB0ZW5zb3IgZnJvbSBhbiBJbWFnZURhdGEgb2JqZWN0XG4gICAqXG4gICAqIEBwYXJhbSBpbWFnZURhdGEgLSB0aGUgSW1hZ2VEYXRhIG9iamVjdCB0byBjcmVhdGUgdGVuc29yIGZyb21cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBbiBvcHRpb25hbCBvYmplY3QgcmVwcmVzZW50aW5nIG9wdGlvbnMgZm9yIGNyZWF0aW5nIHRlbnNvciBmcm9tIEltYWdlRGF0YS5cbiAgICpcbiAgICogVGhlIGZvbGxvd2luZyBkZWZhdWx0IHNldHRpbmdzIHdpbGwgYmUgYXBwbGllZDpcbiAgICogLSBgdGVuc29yRm9ybWF0YDogYCdSR0InYFxuICAgKiAtIGB0ZW5zb3JMYXlvdXRgOiBgJ05DSFcnYFxuICAgKiAtIGBkYXRhVHlwZWA6IGAnZmxvYXQzMidgXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgdGVuc29yIG9iamVjdFxuICAgKi9cbiAgZnJvbUltYWdlKFxuICAgIGltYWdlRGF0YTogSW1hZ2VEYXRhLFxuICAgIG9wdGlvbnM/OiBUZW5zb3JGcm9tSW1hZ2VEYXRhT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxUeXBlZFRlbnNvcjwnZmxvYXQzMic+IHwgVHlwZWRUZW5zb3I8J3VpbnQ4Jz4+O1xuXG4gIC8qKlxuICAgKiBjcmVhdGUgYSB0ZW5zb3IgZnJvbSBhIEhUTUxJbWFnZUVsZW1lbnQgb2JqZWN0XG4gICAqXG4gICAqIEBwYXJhbSBpbWFnZUVsZW1lbnQgLSB0aGUgSFRNTEltYWdlRWxlbWVudCBvYmplY3QgdG8gY3JlYXRlIHRlbnNvciBmcm9tXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQW4gb3B0aW9uYWwgb2JqZWN0IHJlcHJlc2VudGluZyBvcHRpb25zIGZvciBjcmVhdGluZyB0ZW5zb3IgZnJvbSBIVE1MSW1hZ2VFbGVtZW50LlxuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGRlZmF1bHQgc2V0dGluZ3Mgd2lsbCBiZSBhcHBsaWVkOlxuICAgKiAtIGB0ZW5zb3JGb3JtYXRgOiBgJ1JHQidgXG4gICAqIC0gYHRlbnNvckxheW91dGA6IGAnTkNIVydgXG4gICAqIC0gYGRhdGFUeXBlYDogYCdmbG9hdDMyJ2BcbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSB0ZW5zb3Igb2JqZWN0XG4gICAqL1xuICBmcm9tSW1hZ2UoXG4gICAgaW1hZ2VFbGVtZW50OiBIVE1MSW1hZ2VFbGVtZW50LFxuICAgIG9wdGlvbnM/OiBUZW5zb3JGcm9tSW1hZ2VFbGVtZW50T3B0aW9ucyxcbiAgKTogUHJvbWlzZTxUeXBlZFRlbnNvcjwnZmxvYXQzMic+IHwgVHlwZWRUZW5zb3I8J3VpbnQ4Jz4+O1xuXG4gIC8qKlxuICAgKiBjcmVhdGUgYSB0ZW5zb3IgZnJvbSBVUkxcbiAgICpcbiAgICogQHBhcmFtIHVybFNvdXJjZSAtIGEgc3RyaW5nIGFzIGEgVVJMIHRvIHRoZSBpbWFnZSBvciBhIGRhdGEgVVJMIGNvbnRhaW5pbmcgdGhlIGltYWdlIGRhdGEuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQW4gb3B0aW9uYWwgb2JqZWN0IHJlcHJlc2VudGluZyBvcHRpb25zIGZvciBjcmVhdGluZyB0ZW5zb3IgZnJvbSBVUkwuXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgZGVmYXVsdCBzZXR0aW5ncyB3aWxsIGJlIGFwcGxpZWQ6XG4gICAqIC0gYHRlbnNvckZvcm1hdGA6IGAnUkdCJ2BcbiAgICogLSBgdGVuc29yTGF5b3V0YDogYCdOQ0hXJ2BcbiAgICogLSBgZGF0YVR5cGVgOiBgJ2Zsb2F0MzInYFxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIHRlbnNvciBvYmplY3RcbiAgICovXG4gIGZyb21JbWFnZSh1cmxTb3VyY2U6IHN0cmluZywgb3B0aW9ucz86IFRlbnNvckZyb21VcmxPcHRpb25zKTogUHJvbWlzZTxUeXBlZFRlbnNvcjwnZmxvYXQzMic+IHwgVHlwZWRUZW5zb3I8J3VpbnQ4Jz4+O1xuXG4gIC8qKlxuICAgKiBjcmVhdGUgYSB0ZW5zb3IgZnJvbSBhbiBJbWFnZUJpdG1hcCBvYmplY3RcbiAgICpcbiAgICogQHBhcmFtIGJpdG1hcCAtIHRoZSBJbWFnZUJpdG1hcCBvYmplY3QgdG8gY3JlYXRlIHRlbnNvciBmcm9tXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQW4gb3B0aW9uYWwgb2JqZWN0IHJlcHJlc2VudGluZyBvcHRpb25zIGZvciBjcmVhdGluZyB0ZW5zb3IgZnJvbSBVUkwuXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgZGVmYXVsdCBzZXR0aW5ncyB3aWxsIGJlIGFwcGxpZWQ6XG4gICAqIC0gYHRlbnNvckZvcm1hdGA6IGAnUkdCJ2BcbiAgICogLSBgdGVuc29yTGF5b3V0YDogYCdOQ0hXJ2BcbiAgICogLSBgZGF0YVR5cGVgOiBgJ2Zsb2F0MzInYFxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIHRlbnNvciBvYmplY3RcbiAgICovXG4gIGZyb21JbWFnZShcbiAgICBiaXRtYXA6IEltYWdlQml0bWFwLFxuICAgIG9wdGlvbnM6IFRlbnNvckZyb21JbWFnZUJpdG1hcE9wdGlvbnMsXG4gICk6IFByb21pc2U8VHlwZWRUZW5zb3I8J2Zsb2F0MzInPiB8IFR5cGVkVGVuc29yPCd1aW50OCc+PjtcblxuICAvKipcbiAgICogY3JlYXRlIGEgdGVuc29yIGZyb20gYSBXZWJHTCB0ZXh0dXJlXG4gICAqXG4gICAqIEBwYXJhbSB0ZXh0dXJlIC0gdGhlIFdlYkdMVGV4dHVyZSBvYmplY3QgdG8gY3JlYXRlIHRlbnNvciBmcm9tXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQW4gb3B0aW9uYWwgb2JqZWN0IHJlcHJlc2VudGluZyBvcHRpb25zIGZvciBjcmVhdGluZyB0ZW5zb3IgZnJvbSBXZWJHTCB0ZXh0dXJlLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBpbmNsdWRlIGZvbGxvd2luZyBwcm9wZXJ0aWVzOlxuICAgKiAtIGB3aWR0aGA6IHRoZSB3aWR0aCBvZiB0aGUgdGV4dHVyZS4gUmVxdWlyZWQuXG4gICAqIC0gYGhlaWdodGA6IHRoZSBoZWlnaHQgb2YgdGhlIHRleHR1cmUuIFJlcXVpcmVkLlxuICAgKiAtIGBmb3JtYXRgOiB0aGUgZm9ybWF0IG9mIHRoZSB0ZXh0dXJlLiBJZiBvbWl0dGVkLCBhc3N1bWUgJ1JHQkEnLlxuICAgKiAtIGBkb3dubG9hZGA6IGFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRvIGRvd25sb2FkIHRoZSB0ZW5zb3IgZGF0YSBmcm9tIEdQVSB0byBDUFUuIElmIG9taXR0ZWQsIHRoZSBHUFUgZGF0YVxuICAgKiB3aWxsIG5vdCBiZSBhYmxlIHRvIGRvd25sb2FkLiBVc3VhbGx5LCB0aGlzIGlzIHByb3ZpZGVkIGJ5IGEgR1BVIGJhY2tlbmQgZm9yIHRoZSBpbmZlcmVuY2Ugb3V0cHV0cy4gVXNlcnMgZG9uJ3RcbiAgICogbmVlZCB0byBwcm92aWRlIHRoaXMgZnVuY3Rpb24uXG4gICAqIC0gYGRpc3Bvc2VgOiBhbiBvcHRpb25hbCBmdW5jdGlvbiB0byBkaXNwb3NlIHRoZSB0ZW5zb3IgZGF0YSBvbiBHUFUuIElmIG9taXR0ZWQsIHRoZSBHUFUgZGF0YSB3aWxsIG5vdCBiZSBkaXNwb3NlZC5cbiAgICogVXN1YWxseSwgdGhpcyBpcyBwcm92aWRlZCBieSBhIEdQVSBiYWNrZW5kIGZvciB0aGUgaW5mZXJlbmNlIG91dHB1dHMuIFVzZXJzIGRvbid0IG5lZWQgdG8gcHJvdmlkZSB0aGlzIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJucyBhIHRlbnNvciBvYmplY3RcbiAgICovXG4gIGZyb21UZXh0dXJlPFQgZXh0ZW5kcyBUZW5zb3IuVGV4dHVyZURhdGFUeXBlcyA9ICdmbG9hdDMyJz4oXG4gICAgdGV4dHVyZTogVGVuc29yLlRleHR1cmVUeXBlLFxuICAgIG9wdGlvbnM6IFRlbnNvckZyb21UZXh0dXJlT3B0aW9uczxUPixcbiAgKTogVHlwZWRUZW5zb3I8J2Zsb2F0MzInPjtcblxuICAvKipcbiAgICogY3JlYXRlIGEgdGVuc29yIGZyb20gYSBXZWJHUFUgYnVmZmVyXG4gICAqXG4gICAqIEBwYXJhbSBidWZmZXIgLSB0aGUgR1BVQnVmZmVyIG9iamVjdCB0byBjcmVhdGUgdGVuc29yIGZyb21cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBbiBvcHRpb25hbCBvYmplY3QgcmVwcmVzZW50aW5nIG9wdGlvbnMgZm9yIGNyZWF0aW5nIHRlbnNvciBmcm9tIFdlYkdQVSBidWZmZXIuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGluY2x1ZGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gICAqIC0gYGRhdGFUeXBlYDogdGhlIGRhdGEgdHlwZSBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhc3N1bWUgJ2Zsb2F0MzInLlxuICAgKiAtIGBkaW1zYDogdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBSZXF1aXJlZC5cbiAgICogLSBgZG93bmxvYWRgOiBhbiBvcHRpb25hbCBmdW5jdGlvbiB0byBkb3dubG9hZCB0aGUgdGVuc29yIGRhdGEgZnJvbSBHUFUgdG8gQ1BVLiBJZiBvbWl0dGVkLCB0aGUgR1BVIGRhdGFcbiAgICogd2lsbCBub3QgYmUgYWJsZSB0byBkb3dubG9hZC4gVXN1YWxseSwgdGhpcyBpcyBwcm92aWRlZCBieSBhIEdQVSBiYWNrZW5kIGZvciB0aGUgaW5mZXJlbmNlIG91dHB1dHMuIFVzZXJzIGRvbid0XG4gICAqIG5lZWQgdG8gcHJvdmlkZSB0aGlzIGZ1bmN0aW9uLlxuICAgKiAtIGBkaXNwb3NlYDogYW4gb3B0aW9uYWwgZnVuY3Rpb24gdG8gZGlzcG9zZSB0aGUgdGVuc29yIGRhdGEgb24gR1BVLiBJZiBvbWl0dGVkLCB0aGUgR1BVIGRhdGEgd2lsbCBub3QgYmUgZGlzcG9zZWQuXG4gICAqIFVzdWFsbHksIHRoaXMgaXMgcHJvdmlkZWQgYnkgYSBHUFUgYmFja2VuZCBmb3IgdGhlIGluZmVyZW5jZSBvdXRwdXRzLiBVc2VycyBkb24ndCBuZWVkIHRvIHByb3ZpZGUgdGhpcyBmdW5jdGlvbi5cbiAgICpcbiAgICogQHJldHVybnMgYSB0ZW5zb3Igb2JqZWN0XG4gICAqL1xuICBmcm9tR3B1QnVmZmVyPFQgZXh0ZW5kcyBUZW5zb3IuR3B1QnVmZmVyRGF0YVR5cGVzPihcbiAgICBidWZmZXI6IFRlbnNvci5HcHVCdWZmZXJUeXBlLFxuICAgIG9wdGlvbnM6IFRlbnNvckZyb21HcHVCdWZmZXJPcHRpb25zPFQ+LFxuICApOiBUeXBlZFRlbnNvcjxUPjtcblxuICAvKipcbiAgICogY3JlYXRlIGEgdGVuc29yIGZyb20gYSBXZWJOTiBNTFRlbnNvclxuICAgKlxuICAgKiBAcGFyYW0gdGVuc29yIC0gdGhlIE1MVGVuc29yIG9iamVjdCB0byBjcmVhdGUgdGVuc29yIGZyb21cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBbiBvcHRpb25hbCBvYmplY3QgcmVwcmVzZW50aW5nIG9wdGlvbnMgZm9yIGNyZWF0aW5nIHRlbnNvciBmcm9tIGEgV2ViTk4gTUxUZW5zb3IuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGluY2x1ZGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gICAqIC0gYGRhdGFUeXBlYDogdGhlIGRhdGEgdHlwZSBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhc3N1bWUgJ2Zsb2F0MzInLlxuICAgKiAtIGBkaW1zYDogdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBSZXF1aXJlZC5cbiAgICogLSBgZG93bmxvYWRgOiBhbiBvcHRpb25hbCBmdW5jdGlvbiB0byBkb3dubG9hZCB0aGUgdGVuc29yIGRhdGEgZnJvbSB0aGUgTUxUZW5zb3IgdG8gQ1BVLiBJZiBvbWl0dGVkLCB0aGUgTUxUZW5zb3JcbiAgICogZGF0YSB3aWxsIG5vdCBiZSBhYmxlIHRvIGRvd25sb2FkLiBVc3VhbGx5LCB0aGlzIGlzIHByb3ZpZGVkIGJ5IHRoZSBXZWJOTiBiYWNrZW5kIGZvciB0aGUgaW5mZXJlbmNlIG91dHB1dHMuXG4gICAqIFVzZXJzIGRvbid0IG5lZWQgdG8gcHJvdmlkZSB0aGlzIGZ1bmN0aW9uLlxuICAgKiAtIGBkaXNwb3NlYDogYW4gb3B0aW9uYWwgZnVuY3Rpb24gdG8gZGlzcG9zZSB0aGUgdGVuc29yIGRhdGEgb24gdGhlIFdlYk5OIE1MVGVuc29yLiBJZiBvbWl0dGVkLCB0aGUgTUxUZW5zb3Igd2lsbFxuICAgKiBub3QgYmUgZGlzcG9zZWQuIFVzdWFsbHksIHRoaXMgaXMgcHJvdmlkZWQgYnkgdGhlIFdlYk5OIGJhY2tlbmQgZm9yIHRoZSBpbmZlcmVuY2Ugb3V0cHV0cy4gVXNlcnMgZG9uJ3QgbmVlZCB0b1xuICAgKiBwcm92aWRlIHRoaXMgZnVuY3Rpb24uXG4gICAqXG4gICAqIEByZXR1cm5zIGEgdGVuc29yIG9iamVjdFxuICAgKi9cbiAgZnJvbU1MVGVuc29yPFQgZXh0ZW5kcyBUZW5zb3IuTUxUZW5zb3JEYXRhVHlwZXM+KFxuICAgIHRlbnNvcjogVGVuc29yLk1MVGVuc29yVHlwZSxcbiAgICBvcHRpb25zOiBUZW5zb3JGcm9tTUxUZW5zb3JPcHRpb25zPFQ+LFxuICApOiBUeXBlZFRlbnNvcjxUPjtcblxuICAvKipcbiAgICogY3JlYXRlIGEgdGVuc29yIGZyb20gYSBwcmUtYWxsb2NhdGVkIGJ1ZmZlci4gVGhlIGJ1ZmZlciB3aWxsIGJlIHVzZWQgYXMgYSBwaW5uZWQgYnVmZmVyLlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIHRoZSB0ZW5zb3IgZWxlbWVudCB0eXBlLlxuICAgKiBAcGFyYW0gYnVmZmVyIC0gYSBUeXBlZEFycmF5IGNvcnJlc3BvbmRpbmcgdG8gdGhlIHR5cGUuXG4gICAqIEBwYXJhbSBkaW1zIC0gc3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKlxuICAgKiBAcmV0dXJucyBhIHRlbnNvciBvYmplY3RcbiAgICovXG4gIGZyb21QaW5uZWRCdWZmZXI8VCBleHRlbmRzIEV4Y2x1ZGU8VGVuc29yLlR5cGUsICdzdHJpbmcnPj4oXG4gICAgdHlwZTogVCxcbiAgICBidWZmZXI6IFRlbnNvci5EYXRhVHlwZU1hcFtUXSxcbiAgICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk6IFR5cGVkVGVuc29yPFQ+O1xufVxuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vKipcbiAqIEEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBhIGZpbGUncyBVUkwgb3IgcGF0aC5cbiAqXG4gKiBQYXRoIGlzIHZhaWxhYmxlIG9ubHkgaW4gb25ueHJ1bnRpbWUtbm9kZSBvciBvbm54cnVudGltZS13ZWIgcnVubmluZyBpbiBOb2RlLmpzLlxuICovXG5leHBvcnQgdHlwZSBGaWxlVXJsT3JQYXRoID0gc3RyaW5nO1xuXG4vKipcbiAqIEEgQmxvYiBvYmplY3QgdGhhdCByZXByZXNlbnRzIGEgZmlsZS5cbiAqL1xuZXhwb3J0IHR5cGUgRmlsZUJsb2IgPSBCbG9iO1xuXG4vKipcbiAqIEEgVWludDhBcnJheSwgQXJyYXlCdWZmZXIgb3IgU2hhcmVkQXJyYXlCdWZmZXIgb2JqZWN0IHRoYXQgcmVwcmVzZW50cyBhIGZpbGUgY29udGVudC5cbiAqXG4gKiBXaGVuIGl0IGlzIGFuIEFycmF5QnVmZmVyIG9yIFNoYXJlZEFycmF5QnVmZmVyLCB0aGUgd2hvbGUgYnVmZmVyIGlzIGFzc3VtZWQgdG8gYmUgdGhlIGZpbGUgY29udGVudC5cbiAqL1xuZXhwb3J0IHR5cGUgRmlsZURhdGEgPSBVaW50OEFycmF5IHwgQXJyYXlCdWZmZXJMaWtlO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBmaWxlIHRoYXQgY2FuIGJlIGxvYWRlZCBieSB0aGUgT05OWCBSdW50aW1lIEphdmFTY3JpcHQgQVBJLlxuICovXG5leHBvcnQgdHlwZSBGaWxlVHlwZSA9IEZpbGVVcmxPclBhdGggfCBGaWxlQmxvYiB8IEZpbGVEYXRhO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYW4gZXh0ZXJuYWwgZGF0YSBmaWxlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEV4dGVybmFsRGF0YUZpbGVEZXNjcmlwdGlvbiB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBleHRlcm5hbCBkYXRhIGZpbGUuXG4gICAqL1xuICBkYXRhOiBGaWxlVHlwZTtcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIGZpbGUgcGF0aC5cbiAgICovXG4gIHBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGFuIGV4dGVybmFsIGRhdGEgZmlsZS5cbiAqXG4gKiBXaGVuIHVzaW5nIGEgc3RyaW5nLCBpdCBzaG91bGQgYmUgYSBmaWxlIFVSTCBvciBwYXRoIHRoYXQgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBtb2RlbCBmaWxlLlxuICovXG5leHBvcnQgdHlwZSBFeHRlcm5hbERhdGFGaWxlVHlwZSA9IEV4dGVybmFsRGF0YUZpbGVEZXNjcmlwdGlvbiB8IEZpbGVVcmxPclBhdGg7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgbW9kZWwgbG9hZGluZy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPbm54TW9kZWxPcHRpb25zIHtcbiAgLyoqXG4gICAqIFNwZWNpZnlpbmcgYSBsaXN0IG9mIGZpbGVzIHRoYXQgcmVwcmVzZW50cyB0aGUgZXh0ZXJuYWwgZGF0YS5cbiAgICovXG4gIGV4dGVybmFsRGF0YT86IHJlYWRvbmx5IEV4dGVybmFsRGF0YUZpbGVUeXBlW107XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yLmpzJztcblxuZXhwb3J0IHR5cGUgTm9uVGVuc29yVHlwZSA9IG5ldmVyO1xuXG4vKipcbiAqIFR5cGUgT25ueFZhbHVlIFJlcHJlc2VudHMgYm90aCB0ZW5zb3JzIGFuZCBub24tdGVuc29ycyB2YWx1ZSBmb3IgbW9kZWwncyBpbnB1dHMvb3V0cHV0cy5cbiAqXG4gKiBOT1RFOiBjdXJyZW50bHkgbm90IHN1cHBvcnQgbm9uLXRlbnNvclxuICovXG5leHBvcnQgdHlwZSBPbm54VmFsdWUgPSBUZW5zb3IgfCBOb25UZW5zb3JUeXBlO1xuXG4vKipcbiAqIFR5cGUgT25ueFZhbHVlRGF0YUxvY2F0aW9uIHJlcHJlc2VudHMgdGhlIGxvY2F0aW9uIG9mIHRoZSBkYXRhIG9mIGFuIE9ubnhWYWx1ZS5cbiAqL1xuZXhwb3J0IHR5cGUgT25ueFZhbHVlRGF0YUxvY2F0aW9uID0gVGVuc29yLkRhdGFMb2NhdGlvbjtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLyoqXG4gKiAjIE9OTlggUnVudGltZSBKYXZhU2NyaXB0IEFQSVxuICpcbiAqIE9OTlggUnVudGltZSBKYXZhU2NyaXB0IEFQSSBpcyBhIHVuaWZpZWQgQVBJIGZvciBhbGwgSmF2YVNjcmlwdCB1c2FnZXMsIGluY2x1ZGluZyB0aGUgZm9sbG93aW5nIE5QTSBwYWNrYWdlczpcbiAqXG4gKiAtIFtvbm54cnVudGltZS1ub2RlXShodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9vbm54cnVudGltZS1ub2RlKVxuICogLSBbb25ueHJ1bnRpbWUtd2ViXShodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9vbm54cnVudGltZS13ZWIpXG4gKiAtIFtvbm54cnVudGltZS1yZWFjdC1uYXRpdmVdKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL29ubnhydW50aW1lLXJlYWN0LW5hdGl2ZSlcbiAqXG4gKiBTZWUgYWxzbzpcbiAqIC0gW0dldCBTdGFydGVkXShodHRwczovL29ubnhydW50aW1lLmFpL2RvY3MvZ2V0LXN0YXJ0ZWQvd2l0aC1qYXZhc2NyaXB0LylcbiAqIC0gW0luZmVyZW5jZSBleGFtcGxlc10oaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9vbm54cnVudGltZS1pbmZlcmVuY2UtZXhhbXBsZXMvdHJlZS9tYWluL2pzKVxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vYmFja2VuZC5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2Vudi5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2luZmVyZW5jZS1zZXNzaW9uLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vdGVuc29yLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vdGVuc29yLWNvbnZlcnNpb24uanMnO1xuZXhwb3J0ICogZnJvbSAnLi90ZW5zb3ItZmFjdG9yeS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3RyYWNlLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vb25ueC1tb2RlbC5qcyc7XG5leHBvcnQgKiBmcm9tICcuL29ubngtdmFsdWUuanMnO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5leHBvcnQgY29uc3QgaXNOb2RlID0gISEodHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmIHByb2Nlc3MudmVyc2lvbnMgJiYgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlKTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLy8vIDxyZWZlcmVuY2UgbGliPVwid2Vid29ya2VyXCIgLz5cblxuLy9cbi8vICogdHlwZSBoYWNrIGZvciBcIkhUTUxJbWFnZUVsZW1lbnRcIlxuLy9cbi8vIGluIHR5cGVzY3JpcHQsIHRoZSB0eXBlIG9mIFwiSFRNTEltYWdlRWxlbWVudFwiIGlzIGRlZmluZWQgaW4gbGliLmRvbS5kLnRzLCB3aGljaCBpcyBjb25mbGljdCB3aXRoIGxpYi53ZWJ3b3JrZXIuZC50cy5cbi8vIHdoZW4gd2UgdXNlIHdlYndvcmtlciwgdGhlIGxpYi53ZWJ3b3JrZXIuZC50cyB3aWxsIGJlIHVzZWQsIHdoaWNoIGRvZXMgbm90IGhhdmUgSFRNTEltYWdlRWxlbWVudCBkZWZpbmVkLlxuLy9cbi8vIHdlIHdpbGwgZ2V0IHRoZSBmb2xsb3dpbmcgZXJyb3JzIGNvbXBsYWluaW5nIHRoYXQgSFRNTEltYWdlRWxlbWVudCBpcyBub3QgZGVmaW5lZDpcbi8vXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy9cbi8vIC4uL2NvbW1vbi9kaXN0L2Nqcy90ZW5zb3ItZmFjdG9yeS5kLnRzOjE4NzoyOSAtIGVycm9yIFRTMjU1MjogQ2Fubm90IGZpbmQgbmFtZSAnSFRNTEltYWdlRWxlbWVudCcuIERpZCB5b3UgbWVhblxuLy8gJ0hUTUxMSUVsZW1lbnQnP1xuLy9cbi8vIDE4NyAgICAgZnJvbUltYWdlKGltYWdlRWxlbWVudDogSFRNTEltYWdlRWxlbWVudCwgb3B0aW9ucz86IFRlbnNvckZyb21JbWFnZUVsZW1lbnRPcHRpb25zKTpcbi8vIFByb21pc2U8VHlwZWRUZW5zb3I8J2Zsb2F0MzInPiB8IFR5cGVkVGVuc29yPCd1aW50OCc+Pjtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfn5+fn5+fn5+fn5+fn5+flxuLy9cbi8vIG5vZGVfbW9kdWxlcy9Ad2ViZ3B1L3R5cGVzL2Rpc3QvaW5kZXguZC50czo4Mzo3IC0gZXJyb3IgVFMyNTUyOiBDYW5ub3QgZmluZCBuYW1lICdIVE1MSW1hZ2VFbGVtZW50Jy4gRGlkIHlvdSBtZWFuXG4vLyAnSFRNTExJRWxlbWVudCc/XG4vL1xuLy8gODMgICAgIHwgSFRNTEltYWdlRWxlbWVudFxuLy8gICAgICAgICAgfn5+fn5+fn5+fn5+fn5+flxuLy9cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vL1xuLy8gYEhUTUxJbWFnZUVsZW1lbnRgIGlzIG9ubHkgdXNlZCBpbiB0eXBlIGRlY2xhcmF0aW9uIGFuZCBub3QgaW4gcmVhbCBjb2RlLiBTbyB3ZSBkZWZpbmUgaXQgYXMgYHVua25vd25gIGhlcmUgdG9cbi8vIGJ5cGFzcyB0aGUgdHlwZSBjaGVjay5cblxuLy9cbi8vICogdHlwZSBoYWNrIGZvciBcImRvY3VtZW50XCJcbi8vXG4vLyBpbiB0eXBlc2NyaXB0LCB0aGUgdHlwZSBvZiBcImRvY3VtZW50XCIgaXMgZGVmaW5lZCBpbiBsaWIuZG9tLmQudHMsIHNvIGl0J3Mgbm90IGF2YWlsYWJsZSBpbiB3ZWJ3b3JrZXIuXG4vL1xuLy8gd2Ugd2lsbCBnZXQgdGhlIGZvbGxvd2luZyBlcnJvcnMgY29tcGxhaW5pbmcgdGhhdCBkb2N1bWVudCBpcyBub3QgZGVmaW5lZDpcbi8vXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy9cbi8vIGxpYi93YXNtL3dhc20tdXRpbHMtaW1wb3J0LnRzOjc6MzMgLSBlcnJvciBUUzI1ODQ6IENhbm5vdCBmaW5kIG5hbWUgJ2RvY3VtZW50Jy4gRG8geW91IG5lZWQgdG8gY2hhbmdlIHlvdXIgdGFyZ2V0XG4vLyBsaWJyYXJ5PyBUcnkgY2hhbmdpbmcgdGhlICdsaWInIGNvbXBpbGVyIG9wdGlvbiB0byBpbmNsdWRlICdkb20nLlxuLy9cbi8vIDcgZXhwb3J0IGNvbnN0IHNjcmlwdFNyYyA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgPyAoZG9jdW1lbnQ/LmN1cnJlbnRTY3JpcHQgYXMgSFRNTFNjcmlwdEVsZW1lbnQpPy5zcmMgOlxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH5+fn5+fn5+XG4vL1xuLy8gbGliL3dhc20vd2FzbS11dGlscy1pbXBvcnQudHM6Nzo2MSAtIGVycm9yIFRTMjU4NDogQ2Fubm90IGZpbmQgbmFtZSAnZG9jdW1lbnQnLiBEbyB5b3UgbmVlZCB0byBjaGFuZ2UgeW91ciB0YXJnZXRcbi8vIGxpYnJhcnk/IFRyeSBjaGFuZ2luZyB0aGUgJ2xpYicgY29tcGlsZXIgb3B0aW9uIHRvIGluY2x1ZGUgJ2RvbScuXG4vL1xuLy8gNyBleHBvcnQgY29uc3Qgc2NyaXB0U3JjID0gdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyA/IChkb2N1bWVudD8uY3VycmVudFNjcmlwdCBhcyBIVE1MU2NyaXB0RWxlbWVudCk/LnNyYyA6XG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH5+fn5+fn5+XG4vL1xuLy8gbGliL3dhc20vd2FzbS11dGlscy1pbXBvcnQudHM6Nzo4OCAtIGVycm9yIFRTMjU1MjogQ2Fubm90IGZpbmQgbmFtZSAnSFRNTFNjcmlwdEVsZW1lbnQnLiBEaWQgeW91IG1lYW5cbi8vICdIVE1MTElFbGVtZW50Jz9cbi8vXG4vLyA3IGV4cG9ydCBjb25zdCBzY3JpcHRTcmMgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnID8gKGRvY3VtZW50Py5jdXJyZW50U2NyaXB0IGFzIEhUTUxTY3JpcHRFbGVtZW50KT8uc3JjIDpcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfn5+fn5+fn5+fn5+fn5+fn5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vL1xuLy8gYGRvY3VtZW50YCBpcyB1c2VkIHRvIGdldCB0aGUgY3VycmVudCBzY3JpcHQgVVJMLCB3aGljaCBpcyBub3QgYXZhaWxhYmxlIGluIHdlYndvcmtlci4gVGhpcyBmaWxlIGlzIHNlcnZlZCBhcyBhXG4vLyBcImR1YWxcIiBmaWxlIGZvciBlbnRyaWVzIG9mIGJvdGggd2Vid29ya2VyIGFuZCB0aGUgZXNtIG1vZHVsZS5cbi8vXG5kZWNsYXJlIGdsb2JhbCB7XG4gIHR5cGUgSFRNTEltYWdlRWxlbWVudCA9IHVua25vd247XG4gIHR5cGUgSFRNTFNjcmlwdEVsZW1lbnQgPSB7IHNyYz86IHN0cmluZyB9O1xuICBjb25zdCBkb2N1bWVudDogdW5kZWZpbmVkIHwgeyBjdXJyZW50U2NyaXB0PzogSFRNTFNjcmlwdEVsZW1lbnQgfTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeVxuICpcbiAqIFRoaXMgZmlsZSBpcyBzZXJ2ZWQgYXMgYSBcImR1YWxcIiBmaWxlIGZvciBib3RoIGVudHJpZXMgb2YgdGhlIGZvbGxvd2luZzpcbiAqIC0gVGhlIHByb3h5IHdvcmtlciBpdHNlbGYuXG4gKiAgIC0gV2hlbiB1c2VkIGFzIGEgd29ya2VyLCBpdCBsaXN0ZW5zIHRvIHRoZSBtZXNzYWdlcyBmcm9tIHRoZSBtYWluIHRocmVhZCBhbmQgcGVyZm9ybXMgdGhlIGNvcnJlc3BvbmRpbmcgb3BlcmF0aW9ucy5cbiAqICAgLSBTaG91bGQgYmUgaW1wb3J0ZWQgZGlyZWN0bHkgdXNpbmcgYG5ldyBXb3JrZXIoKWAgaW4gdGhlIG1haW4gdGhyZWFkLlxuICpcbiAqIC0gVGhlIEVTTSBtb2R1bGUgdGhhdCBjcmVhdGVzIHRoZSBwcm94eSB3b3JrZXIgKGFzIGEgd29ya2VyIGxhdW5jaGVyKS5cbiAqICAgLSBXaGVuIHVzZWQgYXMgYSB3b3JrZXIgbGF1bmNoZXIsIGl0IGNyZWF0ZXMgdGhlIHByb3h5IHdvcmtlciBhbmQgcmV0dXJucyBpdC5cbiAqICAgLSBTaG91bGQgYmUgaW1wb3J0ZWQgdXNpbmcgYGltcG9ydCgpYCBpbiB0aGUgbWFpbiB0aHJlYWQsIHdpdGggdGhlIHF1ZXJ5IHBhcmFtZXRlciBgaW1wb3J0PTFgLlxuICpcbiAqIFRoaXMgZmlsZSB3aWxsIGJlIGFsd2F5cyBjb21waWxpbmcgaW50byBFU00gZm9ybWF0LlxuICovXG5cbmltcG9ydCB0eXBlIHsgT3J0V2FzbU1lc3NhZ2UsIFNlcmlhbGl6YWJsZVRlbnNvck1ldGFkYXRhIH0gZnJvbSAnLi4vcHJveHktbWVzc2FnZXMuanMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlU2Vzc2lvbixcbiAgY29weUZyb21FeHRlcm5hbEJ1ZmZlcixcbiAgZW5kUHJvZmlsaW5nLFxuICBleHRyYWN0VHJhbnNmZXJhYmxlQnVmZmVycyxcbiAgaW5pdEVwLFxuICBpbml0UnVudGltZSxcbiAgcmVsZWFzZVNlc3Npb24sXG4gIHJ1bixcbn0gZnJvbSAnLi4vd2FzbS1jb3JlLWltcGwuanMnO1xuaW1wb3J0IHsgaW5pdGlhbGl6ZVdlYkFzc2VtYmx5IH0gZnJvbSAnLi4vd2FzbS1mYWN0b3J5LmpzJztcbmltcG9ydCB7IHNjcmlwdFNyYyB9IGZyb20gJy4uL3dhc20tdXRpbHMtaW1wb3J0LmpzJztcblxuY29uc3QgV09SS0VSX05BTUUgPSAnb3J0LXdhc20tcHJveHktd29ya2VyJztcbmNvbnN0IGlzUHJveHlXb3JrZXIgPSBnbG9iYWxUaGlzLnNlbGY/Lm5hbWUgPT09IFdPUktFUl9OQU1FO1xuXG5pZiAoaXNQcm94eVdvcmtlcikge1xuICAvLyBXb3JrZXIgdGhyZWFkXG4gIHNlbGYub25tZXNzYWdlID0gKGV2OiBNZXNzYWdlRXZlbnQ8T3J0V2FzbU1lc3NhZ2U+KTogdm9pZCA9PiB7XG4gICAgY29uc3QgeyB0eXBlLCBpbjogbWVzc2FnZSB9ID0gZXYuZGF0YTtcbiAgICB0cnkge1xuICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgIGNhc2UgJ2luaXQtd2FzbSc6XG4gICAgICAgICAgaW5pdGlhbGl6ZVdlYkFzc2VtYmx5KG1lc3NhZ2UhLndhc20pLnRoZW4oXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgIGluaXRSdW50aW1lKG1lc3NhZ2UhKS50aGVuKFxuICAgICAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSB9KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSwgZXJyIH0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUsIGVyciB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnaW5pdC1lcCc6IHtcbiAgICAgICAgICBjb25zdCB7IGVwTmFtZSwgZW52IH0gPSBtZXNzYWdlITtcbiAgICAgICAgICBpbml0RXAoZW52LCBlcE5hbWUpLnRoZW4oXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSwgZXJyIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ2NvcHktZnJvbSc6IHtcbiAgICAgICAgICBjb25zdCB7IGJ1ZmZlciB9ID0gbWVzc2FnZSE7XG4gICAgICAgICAgY29uc3QgYnVmZmVyRGF0YSA9IGNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIoYnVmZmVyKTtcbiAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUsIG91dDogYnVmZmVyRGF0YSB9IGFzIE9ydFdhc21NZXNzYWdlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdjcmVhdGUnOiB7XG4gICAgICAgICAgY29uc3QgeyBtb2RlbCwgb3B0aW9ucyB9ID0gbWVzc2FnZSE7XG4gICAgICAgICAgY3JlYXRlU2Vzc2lvbihtb2RlbCwgb3B0aW9ucykudGhlbihcbiAgICAgICAgICAgIChzZXNzaW9uTWV0YWRhdGEpID0+IHtcbiAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlLCBvdXQ6IHNlc3Npb25NZXRhZGF0YSB9IGFzIE9ydFdhc21NZXNzYWdlKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSwgZXJyIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ3JlbGVhc2UnOlxuICAgICAgICAgIHJlbGVhc2VTZXNzaW9uKG1lc3NhZ2UhKTtcbiAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3J1bic6IHtcbiAgICAgICAgICBjb25zdCB7IHNlc3Npb25JZCwgaW5wdXRJbmRpY2VzLCBpbnB1dHMsIG91dHB1dEluZGljZXMsIG9wdGlvbnMgfSA9IG1lc3NhZ2UhO1xuICAgICAgICAgIHJ1bihzZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRzLCBvdXRwdXRJbmRpY2VzLCBuZXcgQXJyYXkob3V0cHV0SW5kaWNlcy5sZW5ndGgpLmZpbGwobnVsbCksIG9wdGlvbnMpLnRoZW4oXG4gICAgICAgICAgICAob3V0cHV0cykgPT4ge1xuICAgICAgICAgICAgICBpZiAob3V0cHV0cy5zb21lKChvKSA9PiBvWzNdICE9PSAnY3B1JykpIHtcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUsIGVycjogJ1Byb3h5IGRvZXMgbm90IHN1cHBvcnQgbm9uLWNwdSB0ZW5zb3IgbG9jYXRpb24uJyB9KTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZShcbiAgICAgICAgICAgICAgICAgIHsgdHlwZSwgb3V0OiBvdXRwdXRzIH0gYXMgT3J0V2FzbU1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICBleHRyYWN0VHJhbnNmZXJhYmxlQnVmZmVycyhbLi4uaW5wdXRzLCAuLi5vdXRwdXRzXSBhcyBTZXJpYWxpemFibGVUZW5zb3JNZXRhZGF0YVtdKSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUsIGVyciB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdlbmQtcHJvZmlsaW5nJzpcbiAgICAgICAgICBlbmRQcm9maWxpbmcobWVzc2FnZSEpO1xuICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSB9KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSwgZXJyIH0gYXMgT3J0V2FzbU1lc3NhZ2UpO1xuICAgIH1cbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgaXNQcm94eVdvcmtlclxuICA/IG51bGxcbiAgOiAodXJsT3ZlcnJpZGU/OiBzdHJpbmcpID0+XG4gICAgICBuZXcgV29ya2VyKHVybE92ZXJyaWRlID8/IHNjcmlwdFNyYyEsIHsgdHlwZTogQlVJTERfREVGUy5JU19FU00gPyAnbW9kdWxlJyA6ICdjbGFzc2ljJywgbmFtZTogV09SS0VSX05BTUUgfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB0eXBlIHsgT3J0V2FzbU1vZHVsZSB9IGZyb20gJy4vd2FzbS10eXBlcyc7XG5pbXBvcnQgeyBpc05vZGUgfSBmcm9tICcuL3dhc20tdXRpbHMtZW52JztcblxuLyoqXG4gKiBUaGUgb3JpZ2luIG9mIHRoZSBjdXJyZW50IGxvY2F0aW9uLlxuICpcbiAqIEluIE5vZGUuanMsIHRoaXMgaXMgdW5kZWZpbmVkLlxuICovXG5jb25zdCBvcmlnaW4gPSBpc05vZGUgfHwgdHlwZW9mIGxvY2F0aW9uID09PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IGxvY2F0aW9uLm9yaWdpbjtcblxuLyoqXG4gKiBTb21lIGJ1bmRsZXJzIChlZy4gV2VicGFjaykgd2lsbCByZXdyaXRlIGBpbXBvcnQubWV0YS51cmxgIHRvIGEgZmlsZSBVUkwgYXQgY29tcGlsZSB0aW1lLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gY2hlY2tzIGlmIGBpbXBvcnQubWV0YS51cmxgIHN0YXJ0cyB3aXRoIGBmaWxlOmAsIGJ1dCB1c2luZyB0aGUgYD5gIGFuZCBgPGAgb3BlcmF0b3JzIGluc3RlYWQgb2ZcbiAqIGBzdGFydHNXaXRoYCBmdW5jdGlvbiBzbyB0aGF0IGNvZGUgbWluaW1pemVycyBjYW4gcmVtb3ZlIHRoZSBkZWFkIGNvZGUgY29ycmVjdGx5LlxuICpcbiAqIEZvciBleGFtcGxlLCBpZiB3ZSB1c2UgdGVyc2VyIHRvIG1pbmlmeSB0aGUgZm9sbG93aW5nIGNvZGU6XG4gKiBgYGBqc1xuICogaWYgKFwiZmlsZTovL2hhcmQtY29kZWQtZmlsZW5hbWVcIi5zdGFydHNXaXRoKFwiZmlsZTpcIikpIHtcbiAqICAgY29uc29sZS5sb2coMSlcbiAqIH0gZWxzZSB7XG4gKiAgIGNvbnNvbGUubG9nKDIpXG4gKiB9XG4gKlxuICogaWYgKFwiZmlsZTovL2hhcmQtY29kZWQtZmlsZW5hbWVcIiA+IFwiZmlsZTpcIiAmJiBcImZpbGU6Ly9oYXJkLWNvZGVkLWZpbGVuYW1lXCIgPCBcImZpbGU7XCIpIHtcbiAqICAgY29uc29sZS5sb2coMylcbiAqIH0gZWxzZSB7XG4gKiAgIGNvbnNvbGUubG9nKDQpXG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBUaGUgbWluaWZpZWQgY29kZSB3aWxsIGJlOlxuICogYGBganNcbiAqIFwiZmlsZTovL2hhcmQtY29kZWQtZmlsZW5hbWVcIi5zdGFydHNXaXRoKFwiZmlsZTpcIik/Y29uc29sZS5sb2coMSk6Y29uc29sZS5sb2coMiksY29uc29sZS5sb2coMyk7XG4gKiBgYGBcbiAqXG4gKiAodXNlIFRlcnNlciA1LjM5LjAgd2l0aCBkZWZhdWx0IG9wdGlvbnMsIGh0dHBzOi8vdHJ5LnRlcnNlci5vcmcvKVxuICpcbiAqIEByZXR1cm5zIHRydWUgaWYgdGhlIGltcG9ydC5tZXRhLnVybCBpcyBoYXJkY29kZWQgYXMgYSBmaWxlIFVSSS5cbiAqL1xuZXhwb3J0IGNvbnN0IGlzRXNtSW1wb3J0TWV0YVVybEhhcmRjb2RlZEFzRmlsZVVyaSA9XG4gIEJVSUxEX0RFRlMuSVNfRVNNICYmIEJVSUxEX0RFRlMuRVNNX0lNUE9SVF9NRVRBX1VSTCEgPiAnZmlsZTonICYmIEJVSUxEX0RFRlMuRVNNX0lNUE9SVF9NRVRBX1VSTCEgPCAnZmlsZTsnO1xuXG5jb25zdCBnZXRTY3JpcHRTcmMgPSAoKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+IHtcbiAgLy8gaWYgTm9kZWpzLCByZXR1cm4gdW5kZWZpbmVkXG4gIGlmIChpc05vZGUpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIC8vIGlmIEl0J3MgRVNNLCB1c2UgaW1wb3J0Lm1ldGEudXJsXG4gIGlmIChCVUlMRF9ERUZTLklTX0VTTSkge1xuICAgIC8vIEZvciBFU00sIGlmIHRoZSBpbXBvcnQubWV0YS51cmwgaXMgYSBmaWxlIFVSTCwgdGhpcyB1c3VhbGx5IG1lYW5zIHRoZSBidW5kbGVyIHJld3JpdGVzIGBpbXBvcnQubWV0YS51cmxgIHRvXG4gICAgLy8gdGhlIGZpbGUgcGF0aCBhdCBjb21waWxlIHRpbWUuIEluIHRoaXMgY2FzZSwgdGhpcyBmaWxlIHBhdGggY2Fubm90IGJlIHVzZWQgdG8gZGV0ZXJtaW5lIHRoZSBydW50aW1lIFVSTC5cbiAgICAvL1xuICAgIC8vIFdlIG5lZWQgdG8gdXNlIHRoZSBVUkwgY29uc3RydWN0b3IgbGlrZSB0aGlzOlxuICAgIC8vIGBgYGpzXG4gICAgLy8gbmV3IFVSTCgnYWN0dWFsLWJ1bmRsZS1uYW1lLmpzJywgaW1wb3J0Lm1ldGEudXJsKS5ocmVmXG4gICAgLy8gYGBgXG4gICAgLy8gU28gdGhhdCBidW5kbGVyIGNhbiBwcmVwcm9jZXNzIHRoZSBVUkwgY29ycmVjdGx5LlxuICAgIGlmIChpc0VzbUltcG9ydE1ldGFVcmxIYXJkY29kZWRBc0ZpbGVVcmkpIHtcbiAgICAgIC8vIGlmIHRoZSByZXdyaXR0ZW4gVVJMIGlzIGEgcmVsYXRpdmUgcGF0aCwgd2UgbmVlZCB0byB1c2UgdGhlIG9yaWdpbiB0byByZXNvbHZlIHRoZSBVUkwuXG5cbiAgICAgIC8vIFRoZSBmb2xsb3dpbmcgaXMgYSB3b3JrYXJvdW5kIGZvciBWaXRlLlxuICAgICAgLy9cbiAgICAgIC8vIFZpdGUgdXNlcyBhIGJ1bmRsZXIocm9sbHVwL3JvbGxkb3duKSB0aGF0IGRvZXMgbm90IHJld3JpdGUgYGltcG9ydC5tZXRhLnVybGAgdG8gYSBmaWxlIFVSTC4gU28gaW4gdGhlb3J5LCB0aGlzXG4gICAgICAvLyBjb2RlIHBhdGggc2hvdWxkIG5vdCBiZSBleGVjdXRlZCBpbiBWaXRlLiBIb3dldmVyLCB0aGUgYnVuZGxlciBkb2VzIG5vdCBrbm93IGl0IGFuZCBpdCBzdGlsbCB0cnkgdG8gbG9hZCB0aGVcbiAgICAgIC8vIGZvbGxvd2luZyBwYXR0ZXJuOlxuICAgICAgLy8gLSBgcmV0dXJuIG5ldyBVUkwoJ2ZpbGVuYW1lJywgaW1wb3J0Lm1ldGEudXJsKS5ocmVmYFxuICAgICAgLy9cbiAgICAgIC8vIEJ5IHJlcGxhY2luZyB0aGUgcGF0dGVybiBhYm92ZSB3aXRoIHRoZSBmb2xsb3dpbmcgY29kZSwgd2UgY2FuIHNraXAgdGhlIHJlc291cmNlIGxvYWRpbmcgYmVoYXZpb3I6XG4gICAgICAvLyAtIGBjb25zdCBVUkwyID0gVVJMOyByZXR1cm4gbmV3IFVSTDIoJ2ZpbGVuYW1lJywgaW1wb3J0Lm1ldGEudXJsKS5ocmVmO2BcbiAgICAgIC8vXG4gICAgICAvLyBBbmQgaXQgc3RpbGwgd29ya3MgaW4gV2VicGFjay5cbiAgICAgIGNvbnN0IFVSTDIgPSBVUkw7XG4gICAgICByZXR1cm4gbmV3IFVSTChuZXcgVVJMMihCVUlMRF9ERUZTLkJVTkRMRV9GSUxFTkFNRSwgQlVJTERfREVGUy5FU01fSU1QT1JUX01FVEFfVVJMKS5ocmVmLCBvcmlnaW4pLmhyZWY7XG4gICAgfVxuXG4gICAgcmV0dXJuIEJVSUxEX0RFRlMuRVNNX0lNUE9SVF9NRVRBX1VSTDtcbiAgfVxuXG4gIHJldHVybiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnXG4gICAgPyAoZG9jdW1lbnQuY3VycmVudFNjcmlwdCBhcyBIVE1MU2NyaXB0RWxlbWVudCk/LnNyY1xuICAgIDogLy8gdXNlIGBzZWxmLmxvY2F0aW9uLmhyZWZgIGlmIGF2YWlsYWJsZVxuICAgICAgdHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnXG4gICAgICA/IHNlbGYubG9jYXRpb24/LmhyZWZcbiAgICAgIDogdW5kZWZpbmVkO1xufTtcblxuLyoqXG4gKiBUaGUgY2xhc3NpYyBzY3JpcHQgc291cmNlIFVSTC4gVGhpcyBpcyBub3QgYWx3YXlzIGF2YWlsYWJsZSBpbiBub24gRVNNb2R1bGUgZW52aXJvbm1lbnRzLlxuICpcbiAqIEluIE5vZGUuanMsIHRoaXMgaXMgdW5kZWZpbmVkLlxuICovXG5leHBvcnQgY29uc3Qgc2NyaXB0U3JjID0gZ2V0U2NyaXB0U3JjKCk7XG5cbi8qKlxuICogSW5mZXIgdGhlIHdhc20gcGF0aCBwcmVmaXggZnJvbSB0aGUgc2NyaXB0IHNvdXJjZSBVUkwuXG4gKlxuICogQHJldHVybnMgVGhlIGluZmVycmVkIHdhc20gcGF0aCBwcmVmaXgsIG9yIHVuZGVmaW5lZCBpZiB0aGUgc2NyaXB0IHNvdXJjZSBVUkwgaXMgbm90IGF2YWlsYWJsZSBvciBpcyBhIGJsb2IgVVJMLlxuICovXG5leHBvcnQgY29uc3QgaW5mZXJXYXNtUGF0aFByZWZpeEZyb21TY3JpcHRTcmMgPSAoKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+IHtcbiAgaWYgKHNjcmlwdFNyYyAmJiAhc2NyaXB0U3JjLnN0YXJ0c1dpdGgoJ2Jsb2I6JykpIHtcbiAgICByZXR1cm4gc2NyaXB0U3JjLnN1YnN0cmluZygwLCBzY3JpcHRTcmMubGFzdEluZGV4T2YoJy8nKSArIDEpO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59O1xuXG4vKipcbiAqIENoZWNrIGlmIHRoZSBnaXZlbiBmaWxlbmFtZSB3aXRoIHByZWZpeCBpcyBmcm9tIHRoZSBzYW1lIG9yaWdpbi5cbiAqL1xuY29uc3QgaXNTYW1lT3JpZ2luID0gKGZpbGVuYW1lOiBzdHJpbmcsIHByZWZpeE92ZXJyaWRlPzogc3RyaW5nKSA9PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgYmFzZVVybCA9IHByZWZpeE92ZXJyaWRlID8/IHNjcmlwdFNyYztcbiAgICBjb25zdCB1cmwgPSBiYXNlVXJsID8gbmV3IFVSTChmaWxlbmFtZSwgYmFzZVVybCkgOiBuZXcgVVJMKGZpbGVuYW1lKTtcbiAgICByZXR1cm4gdXJsLm9yaWdpbiA9PT0gb3JpZ2luO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbi8qKlxuICogTm9ybWFsaXplIHRoZSBpbnB1dHMgdG8gYW4gYWJzb2x1dGUgVVJMIHdpdGggdGhlIGdpdmVuIHByZWZpeCBvdmVycmlkZS4gSWYgZmFpbGVkLCByZXR1cm4gdW5kZWZpbmVkLlxuICovXG5jb25zdCBub3JtYWxpemVVcmwgPSAoZmlsZW5hbWU6IHN0cmluZywgcHJlZml4T3ZlcnJpZGU/OiBzdHJpbmcpID0+IHtcbiAgY29uc3QgYmFzZVVybCA9IHByZWZpeE92ZXJyaWRlID8/IHNjcmlwdFNyYztcbiAgdHJ5IHtcbiAgICBjb25zdCB1cmwgPSBiYXNlVXJsID8gbmV3IFVSTChmaWxlbmFtZSwgYmFzZVVybCkgOiBuZXcgVVJMKGZpbGVuYW1lKTtcbiAgICByZXR1cm4gdXJsLmhyZWY7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn07XG5cbi8qKlxuICogQ3JlYXRlIGEgZmFsbGJhY2sgVVJMIGlmIGFuIGFic29sdXRlIFVSTCBjYW5ub3QgYmUgY3JlYXRlZCBieSB0aGUgbm9ybWFsaXplVXJsIGZ1bmN0aW9uLlxuICovXG5jb25zdCBmYWxsYmFja1VybCA9IChmaWxlbmFtZTogc3RyaW5nLCBwcmVmaXhPdmVycmlkZT86IHN0cmluZykgPT4gYCR7cHJlZml4T3ZlcnJpZGUgPz8gJy4vJ30ke2ZpbGVuYW1lfWA7XG5cbi8qKlxuICogVGhpcyBoZWxwZXIgZnVuY3Rpb24gaXMgdXNlZCB0byBwcmVsb2FkIGEgbW9kdWxlIGZyb20gYSBVUkwuXG4gKlxuICogSWYgdGhlIG9yaWdpbiBvZiB0aGUgd29ya2VyIFVSTCBpcyBkaWZmZXJlbnQgZnJvbSB0aGUgY3VycmVudCBvcmlnaW4sIHRoZSB3b3JrZXIgY2Fubm90IGJlIGxvYWRlZCBkaXJlY3RseS5cbiAqIFNlZSBkaXNjdXNzaW9ucyBpbiBodHRwczovL2dpdGh1Yi5jb20vd2VicGFjay1jb250cmliL3dvcmtlci1sb2FkZXIvaXNzdWVzLzE1NFxuICpcbiAqIEluIHRoaXMgY2FzZSwgd2Ugd2lsbCBmZXRjaCB0aGUgd29ya2VyIFVSTCBhbmQgY3JlYXRlIGEgbmV3IEJsb2IgVVJMIHdpdGggdGhlIHNhbWUgb3JpZ2luIGFzIGEgd29ya2Fyb3VuZC5cbiAqXG4gKiBAcGFyYW0gYWJzb2x1dGVVcmwgLSBUaGUgYWJzb2x1dGUgVVJMIHRvIHByZWxvYWQuXG4gKlxuICogQHJldHVybnMgLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIG5ldyBCbG9iIFVSTFxuICovXG5jb25zdCBwcmVsb2FkID0gYXN5bmMgKGFic29sdXRlVXJsOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGFic29sdXRlVXJsLCB7IGNyZWRlbnRpYWxzOiAnc2FtZS1vcmlnaW4nIH0pO1xuICBjb25zdCBibG9iID0gYXdhaXQgcmVzcG9uc2UuYmxvYigpO1xuICByZXR1cm4gVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcbn07XG5cbi8qKlxuICogVGhpcyBoZWxwZXIgZnVuY3Rpb24gaXMgdXNlZCB0byBkeW5hbWljYWxseSBpbXBvcnQgYSBtb2R1bGUgZnJvbSBhIFVSTC5cbiAqXG4gKiBUaGUgYnVpbGQgc2NyaXB0IGhhcyBzcGVjaWFsIGhhbmRsaW5nIGZvciB0aGlzIGZ1bmN0aW9uIHRvIGVuc3VyZSB0aGF0IHRoZSBVUkwgaXMgbm90IGJ1bmRsZWQgaW50byB0aGUgZmluYWwgb3V0cHV0LlxuICpcbiAqIEBwYXJhbSB1cmwgLSBUaGUgVVJMIHRvIGltcG9ydC5cbiAqXG4gKiBAcmV0dXJucyAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBkZWZhdWx0IGV4cG9ydCBvZiB0aGUgbW9kdWxlLlxuICovXG5jb25zdCBkeW5hbWljSW1wb3J0RGVmYXVsdCA9IGFzeW5jIDxUPih1cmw6IHN0cmluZyk6IFByb21pc2U8VD4gPT5cbiAgKGF3YWl0IGltcG9ydCgvKiB3ZWJwYWNrSWdub3JlOiB0cnVlICovIHVybCkpLmRlZmF1bHQ7XG5cbi8qKlxuICogVGhlIHByb3h5IHdvcmtlciBmYWN0b3J5IGltcG9ydGVkIGZyb20gdGhlIHByb3h5IHdvcmtlciBtb2R1bGUuXG4gKlxuICogVGhpcyBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuIHRoZSBXZWJBc3NlbWJseSBwcm94eSBpcyBub3QgZGlzYWJsZWQuXG4gKi9cbmNvbnN0IGNyZWF0ZVByb3h5V29ya2VyOiAoKHVybE92ZXJyaWRlPzogc3RyaW5nKSA9PiBXb3JrZXIpIHwgdW5kZWZpbmVkID1cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMsIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbiAgQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgPyB1bmRlZmluZWQgOiByZXF1aXJlKCcuL3Byb3h5LXdvcmtlci9tYWluJykuZGVmYXVsdDtcblxuLyoqXG4gKiBJbXBvcnQgdGhlIHByb3h5IHdvcmtlci5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgcGVyZm9ybSB0aGUgZm9sbG93aW5nIHN0ZXBzOlxuICogMS4gSWYgYSBwcmVsb2FkIGlzIG5lZWRlZCwgaXQgd2lsbCBwcmVsb2FkIHRoZSBtb2R1bGUgYW5kIHJldHVybiB0aGUgb2JqZWN0IFVSTC5cbiAqIDIuIFVzZSB0aGUgcHJveHkgd29ya2VyIGZhY3RvcnkgdG8gY3JlYXRlIHRoZSBwcm94eSB3b3JrZXIuXG4gKlxuICogQHJldHVybnMgLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIHR1cGxlIG9mIDIgZWxlbWVudHM6XG4gKiAgICAgICAgICAgIC0gVGhlIG9iamVjdCBVUkwgb2YgdGhlIHByZWxvYWRlZCBtb2R1bGUsIG9yIHVuZGVmaW5lZCBpZiBubyBwcmVsb2FkIGlzIG5lZWRlZC5cbiAqICAgICAgICAgICAgLSBUaGUgcHJveHkgd29ya2VyLlxuICovXG5leHBvcnQgY29uc3QgaW1wb3J0UHJveHlXb3JrZXIgPSBhc3luYyAoKTogUHJvbWlzZTxbdW5kZWZpbmVkIHwgc3RyaW5nLCBXb3JrZXJdPiA9PiB7XG4gIGlmICghc2NyaXB0U3JjKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gbG9hZCBwcm94eSB3b3JrZXI6IGNhbm5vdCBkZXRlcm1pbmUgdGhlIHNjcmlwdCBzb3VyY2UgVVJMLicpO1xuICB9XG5cbiAgLy8gSWYgdGhlIHNjcmlwdCBzb3VyY2UgaXMgZnJvbSB0aGUgc2FtZSBvcmlnaW4sIHdlIGNhbiB1c2UgdGhlIGVtYmVkZGVkIHByb3h5IG1vZHVsZSBkaXJlY3RseS5cbiAgaWYgKGlzU2FtZU9yaWdpbihzY3JpcHRTcmMpKSB7XG4gICAgcmV0dXJuIFt1bmRlZmluZWQsIGNyZWF0ZVByb3h5V29ya2VyISgpXTtcbiAgfVxuXG4gIC8vIE90aGVyd2lzZSwgbmVlZCB0byBwcmVsb2FkXG4gIGNvbnN0IHVybCA9IGF3YWl0IHByZWxvYWQoc2NyaXB0U3JjKTtcbiAgcmV0dXJuIFt1cmwsIGNyZWF0ZVByb3h5V29ya2VyISh1cmwpXTtcbn07XG5cbi8qKlxuICogVGhlIGVtYmVkZGVkIFdlYkFzc2VtYmx5IG1vZHVsZS5cbiAqXG4gKiBUaGlzIGlzIG9ubHkgYXZhaWxhYmxlIGluIEVTTSBhbmQgd2hlbiBlbWJlZGRpbmcgaXMgbm90IGRpc2FibGVkLlxuICovXG5jb25zdCBlbWJlZGRlZFdhc21Nb2R1bGU6IEVtc2NyaXB0ZW5Nb2R1bGVGYWN0b3J5PE9ydFdhc21Nb2R1bGU+IHwgdW5kZWZpbmVkID1cbiAgQlVJTERfREVGUy5JU19FU00gJiYgQlVJTERfREVGUy5FTkFCTEVfQlVORExFX1dBU01fSlNcbiAgICA/IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgICByZXF1aXJlKFxuICAgICAgICAhQlVJTERfREVGUy5ESVNBQkxFX0pTRVBcbiAgICAgICAgICA/ICcuLi8uLi9kaXN0L29ydC13YXNtLXNpbWQtdGhyZWFkZWQuanNlcC5tanMnXG4gICAgICAgICAgOiAnLi4vLi4vZGlzdC9vcnQtd2FzbS1zaW1kLXRocmVhZGVkLm1qcycsXG4gICAgICApLmRlZmF1bHRcbiAgICA6IHVuZGVmaW5lZDtcblxuLyoqXG4gKiBJbXBvcnQgdGhlIFdlYkFzc2VtYmx5IG1vZHVsZS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgcGVyZm9ybSB0aGUgZm9sbG93aW5nIHN0ZXBzOlxuICogMS4gSWYgdGhlIGVtYmVkZGVkIG1vZHVsZSBleGlzdHMgYW5kIG5vIGN1c3RvbSBVUkwgaXMgc3BlY2lmaWVkLCB1c2UgdGhlIGVtYmVkZGVkIG1vZHVsZS5cbiAqIDIuIElmIGEgcHJlbG9hZCBpcyBuZWVkZWQsIGl0IHdpbGwgcHJlbG9hZCB0aGUgbW9kdWxlIGFuZCByZXR1cm4gdGhlIG9iamVjdCBVUkwuXG4gKiAzLiBPdGhlcndpc2UsIGl0IHdpbGwgcGVyZm9ybSBhIGR5bmFtaWMgaW1wb3J0IG9mIHRoZSBtb2R1bGUuXG4gKlxuICogQHJldHVybnMgLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIHR1cGxlIG9mIDIgZWxlbWVudHM6XG4gKiAgICAgICAgICAgIC0gVGhlIG9iamVjdCBVUkwgb2YgdGhlIHByZWxvYWRlZCBtb2R1bGUsIG9yIHVuZGVmaW5lZCBpZiBubyBwcmVsb2FkIGlzIG5lZWRlZC5cbiAqICAgICAgICAgICAgLSBUaGUgZGVmYXVsdCBleHBvcnQgb2YgdGhlIG1vZHVsZSwgd2hpY2ggaXMgYSBmYWN0b3J5IGZ1bmN0aW9uIHRvIGNyZWF0ZSB0aGUgV2ViQXNzZW1ibHkgbW9kdWxlLlxuICovXG5leHBvcnQgY29uc3QgaW1wb3J0V2FzbU1vZHVsZSA9IGFzeW5jIChcbiAgdXJsT3ZlcnJpZGU6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgcHJlZml4T3ZlcnJpZGU6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgaXNNdWx0aVRocmVhZGVkOiBib29sZWFuLFxuKTogUHJvbWlzZTxbdW5kZWZpbmVkIHwgc3RyaW5nLCBFbXNjcmlwdGVuTW9kdWxlRmFjdG9yeTxPcnRXYXNtTW9kdWxlPl0+ID0+IHtcbiAgaWYgKCF1cmxPdmVycmlkZSAmJiAhcHJlZml4T3ZlcnJpZGUgJiYgZW1iZWRkZWRXYXNtTW9kdWxlICYmIHNjcmlwdFNyYyAmJiBpc1NhbWVPcmlnaW4oc2NyaXB0U3JjKSkge1xuICAgIHJldHVybiBbdW5kZWZpbmVkLCBlbWJlZGRlZFdhc21Nb2R1bGVdO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHdhc21Nb2R1bGVGaWxlbmFtZSA9ICFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUFxuICAgICAgPyAnb3J0LXdhc20tc2ltZC10aHJlYWRlZC5qc2VwLm1qcydcbiAgICAgIDogJ29ydC13YXNtLXNpbWQtdGhyZWFkZWQubWpzJztcbiAgICBjb25zdCB3YXNtTW9kdWxlVXJsID0gdXJsT3ZlcnJpZGUgPz8gbm9ybWFsaXplVXJsKHdhc21Nb2R1bGVGaWxlbmFtZSwgcHJlZml4T3ZlcnJpZGUpO1xuICAgIC8vIG5lZWQgdG8gcHJlbG9hZCBpZiBhbGwgb2YgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG4gICAgLy8gMS4gbm90IGluIE5vZGUuanMuXG4gICAgLy8gICAgLSBOb2RlLmpzIGRvZXMgbm90IGhhdmUgdGhlIHNhbWUgb3JpZ2luIHBvbGljeSBmb3IgY3JlYXRpbmcgd29ya2Vycy5cbiAgICAvLyAyLiBtdWx0aS10aHJlYWRlZCBpcyBlbmFibGVkLlxuICAgIC8vICAgIC0gSWYgbXVsdGktdGhyZWFkZWQgaXMgZGlzYWJsZWQsIG5vIHdvcmtlciB3aWxsIGJlIGNyZWF0ZWQuIFNvIHdlIGRvbid0IG5lZWQgdG8gcHJlbG9hZCB0aGUgbW9kdWxlLlxuICAgIC8vIDMuIHRoZSBhYnNvbHV0ZSBVUkwgaXMgYXZhaWxhYmxlLlxuICAgIC8vICAgIC0gSWYgdGhlIGFic29sdXRlIFVSTCBpcyBmYWlsZWQgdG8gYmUgY3JlYXRlZCwgdGhlIG9yaWdpbiBjYW5ub3QgYmUgZGV0ZXJtaW5lZC4gSW4gdGhpcyBjYXNlLCB3ZSB3aWxsIG5vdFxuICAgIC8vICAgIHByZWxvYWQgdGhlIG1vZHVsZS5cbiAgICAvLyA0LiB0aGUgd29ya2VyIFVSTCBpcyBub3QgZnJvbSB0aGUgc2FtZSBvcmlnaW4uXG4gICAgLy8gICAgLSBJZiB0aGUgd29ya2VyIFVSTCBpcyBmcm9tIHRoZSBzYW1lIG9yaWdpbiwgd2UgY2FuIGNyZWF0ZSB0aGUgd29ya2VyIGRpcmVjdGx5LlxuICAgIGNvbnN0IG5lZWRQcmVsb2FkID0gIWlzTm9kZSAmJiBpc011bHRpVGhyZWFkZWQgJiYgd2FzbU1vZHVsZVVybCAmJiAhaXNTYW1lT3JpZ2luKHdhc21Nb2R1bGVVcmwsIHByZWZpeE92ZXJyaWRlKTtcbiAgICBjb25zdCB1cmwgPSBuZWVkUHJlbG9hZFxuICAgICAgPyBhd2FpdCBwcmVsb2FkKHdhc21Nb2R1bGVVcmwpXG4gICAgICA6ICh3YXNtTW9kdWxlVXJsID8/IGZhbGxiYWNrVXJsKHdhc21Nb2R1bGVGaWxlbmFtZSwgcHJlZml4T3ZlcnJpZGUpKTtcbiAgICByZXR1cm4gW25lZWRQcmVsb2FkID8gdXJsIDogdW5kZWZpbmVkLCBhd2FpdCBkeW5hbWljSW1wb3J0RGVmYXVsdDxFbXNjcmlwdGVuTW9kdWxlRmFjdG9yeTxPcnRXYXNtTW9kdWxlPj4odXJsKV07XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IEVudiB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB0eXBlIHsgT3J0V2FzbU1vZHVsZSB9IGZyb20gJy4vd2FzbS10eXBlcyc7XG5pbXBvcnQgeyBpbXBvcnRXYXNtTW9kdWxlLCBpbmZlcldhc21QYXRoUHJlZml4RnJvbVNjcmlwdFNyYyB9IGZyb20gJy4vd2FzbS11dGlscy1pbXBvcnQnO1xuXG5sZXQgd2FzbTogT3J0V2FzbU1vZHVsZSB8IHVuZGVmaW5lZDtcbmxldCBpbml0aWFsaXplZCA9IGZhbHNlO1xubGV0IGluaXRpYWxpemluZyA9IGZhbHNlO1xubGV0IGFib3J0ZWQgPSBmYWxzZTtcblxuY29uc3QgaXNNdWx0aVRocmVhZFN1cHBvcnRlZCA9ICgpOiBib29sZWFuID0+IHtcbiAgLy8gSWYgJ1NoYXJlZEFycmF5QnVmZmVyJyBpcyBub3QgYXZhaWxhYmxlLCBXZWJBc3NlbWJseSB0aHJlYWRzIHdpbGwgbm90IHdvcmsuXG4gIGlmICh0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBUZXN0IGZvciB0cmFuc2ZlcmFiaWxpdHkgb2YgU0FCcyAoZm9yIGJyb3dzZXJzLiBuZWVkZWQgZm9yIEZpcmVmb3gpXG4gICAgLy8gaHR0cHM6Ly9ncm91cHMuZ29vZ2xlLmNvbS9mb3J1bS8jIW1zZy9tb3ppbGxhLmRldi5wbGF0Zm9ybS9JSGtCWmxIRVRwQS9kd3NNTmNoV0VRQUpcbiAgICBpZiAodHlwZW9mIE1lc3NhZ2VDaGFubmVsICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgbmV3IE1lc3NhZ2VDaGFubmVsKCkucG9ydDEucG9zdE1lc3NhZ2UobmV3IFNoYXJlZEFycmF5QnVmZmVyKDEpKTtcbiAgICB9XG5cbiAgICAvLyBUZXN0IGZvciBXZWJBc3NlbWJseSB0aHJlYWRzIGNhcGFiaWxpdHkgKGZvciBib3RoIGJyb3dzZXJzIGFuZCBOb2RlLmpzKVxuICAgIC8vIFRoaXMgdHlwZWQgYXJyYXkgaXMgYSBXZWJBc3NlbWJseSBwcm9ncmFtIGNvbnRhaW5pbmcgdGhyZWFkZWQgaW5zdHJ1Y3Rpb25zLlxuICAgIHJldHVybiBXZWJBc3NlbWJseS52YWxpZGF0ZShcbiAgICAgIG5ldyBVaW50OEFycmF5KFtcbiAgICAgICAgMCwgOTcsIDExNSwgMTA5LCAxLCAwLCAwLCAwLCAxLCA0LCAxLCA5NiwgMCwgMCwgMywgMiwgMSwgMCwgNSwgNCwgMSwgMywgMSwgMSwgMTAsIDExLCAxLCA5LCAwLCA2NSwgMCwgMjU0LCAxNixcbiAgICAgICAgMiwgMCwgMjYsIDExLFxuICAgICAgXSksXG4gICAgKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuY29uc3QgaXNTaW1kU3VwcG9ydGVkID0gKCk6IGJvb2xlYW4gPT4ge1xuICB0cnkge1xuICAgIC8vIFRlc3QgZm9yIFdlYkFzc2VtYmx5IFNJTUQgY2FwYWJpbGl0eSAoZm9yIGJvdGggYnJvd3NlcnMgYW5kIE5vZGUuanMpXG4gICAgLy8gVGhpcyB0eXBlZCBhcnJheSBpcyBhIFdlYkFzc2VtYmx5IHByb2dyYW0gY29udGFpbmluZyBTSU1EIGluc3RydWN0aW9ucy5cblxuICAgIC8vIFRoZSBiaW5hcnkgZGF0YSBpcyBnZW5lcmF0ZWQgZnJvbSB0aGUgZm9sbG93aW5nIGNvZGUgYnkgd2F0Mndhc206XG4gICAgLy9cbiAgICAvLyAobW9kdWxlXG4gICAgLy8gICAodHlwZSAkdDAgKGZ1bmMpKVxuICAgIC8vICAgKGZ1bmMgJGYwICh0eXBlICR0MClcbiAgICAvLyAgICAgKGRyb3BcbiAgICAvLyAgICAgICAoaTMyeDQuZG90X2kxNng4X3NcbiAgICAvLyAgICAgICAgIChpOHgxNi5zcGxhdFxuICAgIC8vICAgICAgICAgICAoaTMyLmNvbnN0IDApKVxuICAgIC8vICAgICAgICAgKHYxMjguY29uc3QgaTMyeDQgMHgwMDAwMDAwMCAweDAwMDAwMDAwIDB4MDAwMDAwMDAgMHgwMDAwMDAwMCkpKSkpXG5cbiAgICByZXR1cm4gV2ViQXNzZW1ibHkudmFsaWRhdGUoXG4gICAgICBuZXcgVWludDhBcnJheShbXG4gICAgICAgIDAsIDk3LCAxMTUsIDEwOSwgMSwgMCwgMCwgMCwgMSwgNCwgMSwgOTYsIDAsIDAsIDMsIDIsIDEsIDAsIDEwLCAzMCwgMSwgMjgsIDAsIDY1LCAwLCAyNTMsIDE1LCAyNTMsIDEyLCAwLCAwLCAwLFxuICAgICAgICAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAyNTMsIDE4NiwgMSwgMjYsIDExLFxuICAgICAgXSksXG4gICAgKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuY29uc3QgaXNSZWxheGVkU2ltZFN1cHBvcnRlZCA9ICgpOiBib29sZWFuID0+IHtcbiAgdHJ5IHtcbiAgICAvLyBUZXN0IGZvciBXZWJBc3NlbWJseSBSZWxheGVkIFNJTUQgY2FwYWJpbGl0eSAoZm9yIGJvdGggYnJvd3NlcnMgYW5kIE5vZGUuanMpXG4gICAgLy8gVGhpcyB0eXBlZCBhcnJheSBpcyBhIFdlYkFzc2VtYmx5IHByb2dyYW0gY29udGFpbmluZyBSZWxheGVkIFNJTUQgaW5zdHJ1Y3Rpb25zLlxuXG4gICAgLy8gVGhlIGJpbmFyeSBkYXRhIGlzIGdlbmVyYXRlZCBmcm9tIHRoZSBmb2xsb3dpbmcgY29kZSBieSB3YXQyd2FzbTpcbiAgICAvLyAobW9kdWxlXG4gICAgLy8gICAoZnVuYyAocmVzdWx0IHYxMjgpXG4gICAgLy8gICAgICBpMzIuY29uc3QgMVxuICAgIC8vICAgICAgaTh4MTYuc3BsYXRcbiAgICAvLyAgICAgIGkzMi5jb25zdCAyXG4gICAgLy8gICAgICBpOHgxNi5zcGxhdFxuICAgIC8vICAgICAgaTMyLmNvbnN0IDNcbiAgICAvLyAgICAgIGk4eDE2LnNwbGF0XG4gICAgLy8gICAgICBpMzJ4NC5yZWxheGVkX2RvdF9pOHgxNl9pN3gxNl9hZGRfc1xuICAgIC8vICAgKVxuICAgIC8vICApXG4gICAgcmV0dXJuIFdlYkFzc2VtYmx5LnZhbGlkYXRlKFxuICAgICAgbmV3IFVpbnQ4QXJyYXkoW1xuICAgICAgICAwLCA5NywgMTE1LCAxMDksIDEsIDAsIDAsIDAsIDEsIDUsIDEsIDk2LCAwLCAxLCAxMjMsIDMsIDIsIDEsIDAsIDEwLCAxOSwgMSwgMTcsIDAsIDY1LCAxLCAyNTMsIDE1LCA2NSwgMiwgMjUzLFxuICAgICAgICAxNSwgNjUsIDMsIDI1MywgMTUsIDI1MywgMTQ3LCAyLCAxMSxcbiAgICAgIF0pLFxuICAgICk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBpbml0aWFsaXplV2ViQXNzZW1ibHkgPSBhc3luYyAoZmxhZ3M6IEVudi5XZWJBc3NlbWJseUZsYWdzKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGlmIChpbml0aWFsaXplZCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuICBpZiAoaW5pdGlhbGl6aW5nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwibXVsdGlwbGUgY2FsbHMgdG8gJ2luaXRpYWxpemVXZWJBc3NlbWJseSgpJyBkZXRlY3RlZC5cIik7XG4gIH1cbiAgaWYgKGFib3J0ZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJwcmV2aW91cyBjYWxsIHRvICdpbml0aWFsaXplV2ViQXNzZW1ibHkoKScgZmFpbGVkLlwiKTtcbiAgfVxuXG4gIGluaXRpYWxpemluZyA9IHRydWU7XG5cbiAgLy8gd2FzbSBmbGFncyBhcmUgYWxyZWFkeSBpbml0aWFsaXplZFxuICBjb25zdCB0aW1lb3V0ID0gZmxhZ3MuaW5pdFRpbWVvdXQhO1xuICBsZXQgbnVtVGhyZWFkcyA9IGZsYWdzLm51bVRocmVhZHMhO1xuXG4gIC8vIGVuc3VyZSBTSU1EIGlzIHN1cHBvcnRlZFxuICBpZiAoZmxhZ3Muc2ltZCA9PT0gZmFsc2UpIHtcbiAgICAvLyBza2lwIFNJTUQgZmVhdHVyZSBjaGVja2luZyBhcyBpdCBpcyBkaXNhYmxlZCBleHBsaWNpdGx5IGJ5IHVzZXJcbiAgfSBlbHNlIGlmIChmbGFncy5zaW1kID09PSAncmVsYXhlZCcpIHtcbiAgICAvLyBjaGVjayBpZiByZWxheGVkIFNJTUQgaXMgc3VwcG9ydGVkXG4gICAgaWYgKCFpc1JlbGF4ZWRTaW1kU3VwcG9ydGVkKCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVsYXhlZCBXZWJBc3NlbWJseSBTSU1EIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuJyk7XG4gICAgfVxuICB9IGVsc2UgaWYgKCFpc1NpbWRTdXBwb3J0ZWQoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignV2ViQXNzZW1ibHkgU0lNRCBpcyBub3Qgc3VwcG9ydGVkIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50LicpO1xuICB9XG5cbiAgLy8gY2hlY2sgaWYgbXVsdGktdGhyZWFkaW5nIGlzIHN1cHBvcnRlZFxuICBjb25zdCBtdWx0aVRocmVhZFN1cHBvcnRlZCA9IGlzTXVsdGlUaHJlYWRTdXBwb3J0ZWQoKTtcbiAgaWYgKG51bVRocmVhZHMgPiAxICYmICFtdWx0aVRocmVhZFN1cHBvcnRlZCkge1xuICAgIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcgJiYgIXNlbGYuY3Jvc3NPcmlnaW5Jc29sYXRlZCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ2Vudi53YXNtLm51bVRocmVhZHMgaXMgc2V0IHRvICcgK1xuICAgICAgICAgIG51bVRocmVhZHMgK1xuICAgICAgICAgICcsIGJ1dCB0aGlzIHdpbGwgbm90IHdvcmsgdW5sZXNzIHlvdSBlbmFibGUgY3Jvc3NPcmlnaW5Jc29sYXRlZCBtb2RlLiAnICtcbiAgICAgICAgICAnU2VlIGh0dHBzOi8vd2ViLmRldi9jcm9zcy1vcmlnaW4taXNvbGF0aW9uLWd1aWRlLyBmb3IgbW9yZSBpbmZvLicsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgY29uc29sZS53YXJuKFxuICAgICAgJ1dlYkFzc2VtYmx5IG11bHRpLXRocmVhZGluZyBpcyBub3Qgc3VwcG9ydGVkIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50LiAnICsgJ0ZhbGxpbmcgYmFjayB0byBzaW5nbGUtdGhyZWFkaW5nLicsXG4gICAgKTtcblxuICAgIC8vIHNldCBmbGFncy5udW1UaHJlYWRzIHRvIDEgc28gdGhhdCBPcnRJbml0KCkgd2lsbCBub3QgY3JlYXRlIGEgZ2xvYmFsIHRocmVhZCBwb29sLlxuICAgIGZsYWdzLm51bVRocmVhZHMgPSBudW1UaHJlYWRzID0gMTtcbiAgfVxuXG4gIGNvbnN0IHdhc21QYXRocyA9IGZsYWdzLndhc21QYXRocztcbiAgY29uc3Qgd2FzbVByZWZpeE92ZXJyaWRlID0gdHlwZW9mIHdhc21QYXRocyA9PT0gJ3N0cmluZycgPyB3YXNtUGF0aHMgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IG1qc1BhdGhPdmVycmlkZUZsYWcgPSAod2FzbVBhdGhzIGFzIEVudi5XYXNtRmlsZVBhdGhzKT8ubWpzO1xuICBjb25zdCBtanNQYXRoT3ZlcnJpZGUgPSAobWpzUGF0aE92ZXJyaWRlRmxhZyBhcyBVUkwpPy5ocmVmID8/IG1qc1BhdGhPdmVycmlkZUZsYWc7XG4gIGNvbnN0IHdhc21QYXRoT3ZlcnJpZGVGbGFnID0gKHdhc21QYXRocyBhcyBFbnYuV2FzbUZpbGVQYXRocyk/Lndhc207XG4gIGNvbnN0IHdhc21QYXRoT3ZlcnJpZGUgPSAod2FzbVBhdGhPdmVycmlkZUZsYWcgYXMgVVJMKT8uaHJlZiA/PyB3YXNtUGF0aE92ZXJyaWRlRmxhZztcbiAgY29uc3Qgd2FzbUJpbmFyeU92ZXJyaWRlID0gZmxhZ3Mud2FzbUJpbmFyeTtcblxuICBjb25zdCBbb2JqZWN0VXJsLCBvcnRXYXNtRmFjdG9yeV0gPSBhd2FpdCBpbXBvcnRXYXNtTW9kdWxlKG1qc1BhdGhPdmVycmlkZSwgd2FzbVByZWZpeE92ZXJyaWRlLCBudW1UaHJlYWRzID4gMSk7XG5cbiAgbGV0IGlzVGltZW91dCA9IGZhbHNlO1xuXG4gIGNvbnN0IHRhc2tzOiBBcnJheTxQcm9taXNlPHZvaWQ+PiA9IFtdO1xuXG4gIC8vIHByb21pc2UgZm9yIHRpbWVvdXRcbiAgaWYgKHRpbWVvdXQgPiAwKSB7XG4gICAgdGFza3MucHVzaChcbiAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIGlzVGltZW91dCA9IHRydWU7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9LCB0aW1lb3V0KTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICAvLyBwcm9taXNlIGZvciBtb2R1bGUgaW5pdGlhbGl6YXRpb25cbiAgdGFza3MucHVzaChcbiAgICBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBjb25maWc6IFBhcnRpYWw8T3J0V2FzbU1vZHVsZT4gPSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgbnVtYmVyIG9mIHRocmVhZHMuIFdlYkFzc2VtYmx5IHdpbGwgY3JlYXRlIChNb2R1bGUubnVtVGhyZWFkcyAtIDEpIHdvcmtlcnMuIElmIGl0IGlzIDEsIG5vIHdvcmtlciB3aWxsIGJlXG4gICAgICAgICAqIGNyZWF0ZWQuXG4gICAgICAgICAqL1xuICAgICAgICBudW1UaHJlYWRzLFxuICAgICAgfTtcblxuICAgICAgaWYgKHdhc21CaW5hcnlPdmVycmlkZSkge1xuICAgICAgICAvLyBTZXQgYSBjdXN0b20gYnVmZmVyIHdoaWNoIGNvbnRhaW5zIHRoZSBXZWJBc3NlbWJseSBiaW5hcnkuIFRoaXMgd2lsbCBza2lwIHRoZSB3YXNtIGZpbGUgZmV0Y2hpbmcuXG4gICAgICAgIGNvbmZpZy53YXNtQmluYXJ5ID0gd2FzbUJpbmFyeU92ZXJyaWRlO1xuICAgICAgfSBlbHNlIGlmICh3YXNtUGF0aE92ZXJyaWRlIHx8IHdhc21QcmVmaXhPdmVycmlkZSkge1xuICAgICAgICAvLyBBIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGxvY2F0ZSB0aGUgV2ViQXNzZW1ibHkgZmlsZS4gVGhlIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gdGhlIGZ1bGwgcGF0aCBvZiB0aGUgZmlsZS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gU2luY2UgRW1zY3JpcHRlbiAzLjEuNTgsIHRoaXMgZnVuY3Rpb24gaXMgb25seSBjYWxsZWQgZm9yIHRoZSAud2FzbSBmaWxlLlxuICAgICAgICBjb25maWcubG9jYXRlRmlsZSA9IChmaWxlTmFtZSkgPT4gd2FzbVBhdGhPdmVycmlkZSA/PyB3YXNtUHJlZml4T3ZlcnJpZGUgKyBmaWxlTmFtZTtcbiAgICAgIH0gZWxzZSBpZiAobWpzUGF0aE92ZXJyaWRlICYmIG1qc1BhdGhPdmVycmlkZS5pbmRleE9mKCdibG9iOicpICE9PSAwKSB7XG4gICAgICAgIC8vIGlmIG1qcyBwYXRoIGlzIHNwZWNpZmllZCwgdXNlIGl0IGFzIHRoZSBiYXNlIHBhdGggZm9yIHRoZSAud2FzbSBmaWxlLlxuICAgICAgICBjb25maWcubG9jYXRlRmlsZSA9IChmaWxlTmFtZSkgPT4gbmV3IFVSTChmaWxlTmFtZSwgbWpzUGF0aE92ZXJyaWRlKS5ocmVmO1xuICAgICAgfSBlbHNlIGlmIChvYmplY3RVcmwpIHtcbiAgICAgICAgY29uc3QgaW5mZXJyZWRXYXNtUGF0aFByZWZpeCA9IGluZmVyV2FzbVBhdGhQcmVmaXhGcm9tU2NyaXB0U3JjKCk7XG4gICAgICAgIGlmIChpbmZlcnJlZFdhc21QYXRoUHJlZml4KSB7XG4gICAgICAgICAgLy8gaWYgdGhlIHdhc20gbW9kdWxlIGlzIHByZWxvYWRlZCwgdXNlIHRoZSBpbmZlcnJlZCB3YXNtIHBhdGggYXMgdGhlIGJhc2UgcGF0aCBmb3IgdGhlIC53YXNtIGZpbGUuXG4gICAgICAgICAgY29uZmlnLmxvY2F0ZUZpbGUgPSAoZmlsZU5hbWUpID0+IGluZmVycmVkV2FzbVBhdGhQcmVmaXggKyBmaWxlTmFtZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBvcnRXYXNtRmFjdG9yeShjb25maWcpLnRoZW4oXG4gICAgICAgIC8vIHdhc20gbW9kdWxlIGluaXRpYWxpemVkIHN1Y2Nlc3NmdWxseVxuICAgICAgICAobW9kdWxlKSA9PiB7XG4gICAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG4gICAgICAgICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICAgIHdhc20gPSBtb2R1bGU7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIGlmIChvYmplY3RVcmwpIHtcbiAgICAgICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwob2JqZWN0VXJsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIC8vIHdhc20gbW9kdWxlIGZhaWxlZCB0byBpbml0aWFsaXplXG4gICAgICAgICh3aGF0KSA9PiB7XG4gICAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG4gICAgICAgICAgYWJvcnRlZCA9IHRydWU7XG4gICAgICAgICAgcmVqZWN0KHdoYXQpO1xuICAgICAgICB9LFxuICAgICAgKTtcbiAgICB9KSxcbiAgKTtcblxuICBhd2FpdCBQcm9taXNlLnJhY2UodGFza3MpO1xuXG4gIGlmIChpc1RpbWVvdXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFdlYkFzc2VtYmx5IGJhY2tlbmQgaW5pdGlhbGl6aW5nIGZhaWxlZCBkdWUgdG8gdGltZW91dDogJHt0aW1lb3V0fW1zYCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbnN0YW5jZSA9ICgpOiBPcnRXYXNtTW9kdWxlID0+IHtcbiAgaWYgKGluaXRpYWxpemVkICYmIHdhc20pIHtcbiAgICByZXR1cm4gd2FzbTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignV2ViQXNzZW1ibHkgaXMgbm90IGluaXRpYWxpemVkIHlldC4nKTtcbn07XG5cbmV4cG9ydCBjb25zdCBkaXNwb3NlID0gKCk6IHZvaWQgPT4ge1xuICBpZiAoaW5pdGlhbGl6ZWQgJiYgIWluaXRpYWxpemluZyAmJiAhYWJvcnRlZCkge1xuICAgIC8vIFRPRE86IGN1cnJlbnRseSBcIlBUaHJlYWQudGVybWluYXRlQWxsVGhyZWFkcygpXCIgaXMgbm90IGV4cG9zZWQgaW4gdGhlIHdhc20gbW9kdWxlLlxuICAgIC8vICAgICAgIEFuZCB0aGlzIGZ1bmN0aW9uIGlzIG5vdCB5ZXQgY2FsbGVkIGJ5IGFueSBjb2RlLlxuICAgIC8vICAgICAgIElmIGl0IGlzIG5lZWRlZCBpbiB0aGUgZnV0dXJlLCB3ZSBzaG91bGQgZXhwb3NlIGl0IGluIHRoZSB3YXNtIG1vZHVsZSBhbmQgdW5jb21tZW50IHRoZSBmb2xsb3dpbmcgbGluZS5cblxuICAgIC8vIHdhc20/LlBUaHJlYWQ/LnRlcm1pbmF0ZUFsbFRocmVhZHMoKTtcbiAgICB3YXNtID0gdW5kZWZpbmVkO1xuXG4gICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG4gICAgaW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICBhYm9ydGVkID0gdHJ1ZTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgZ2V0SW5zdGFuY2UgfSBmcm9tICcuL3dhc20tZmFjdG9yeSc7XG5cbmV4cG9ydCBjb25zdCBhbGxvY1dhc21TdHJpbmcgPSAoZGF0YTogc3RyaW5nLCBhbGxvY3M6IG51bWJlcltdKTogbnVtYmVyID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG5cbiAgY29uc3QgZGF0YUxlbmd0aCA9IHdhc20ubGVuZ3RoQnl0ZXNVVEY4KGRhdGEpICsgMTtcbiAgY29uc3QgZGF0YU9mZnNldCA9IHdhc20uX21hbGxvYyhkYXRhTGVuZ3RoKTtcbiAgd2FzbS5zdHJpbmdUb1VURjgoZGF0YSwgZGF0YU9mZnNldCwgZGF0YUxlbmd0aCk7XG4gIGFsbG9jcy5wdXNoKGRhdGFPZmZzZXQpO1xuXG4gIHJldHVybiBkYXRhT2Zmc2V0O1xufTtcblxuaW50ZXJmYWNlIEV4dHJhT3B0aW9uc0hhbmRsZXIge1xuICAobmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKTogdm9pZDtcbn1cblxuZXhwb3J0IGNvbnN0IGl0ZXJhdGVFeHRyYU9wdGlvbnMgPSAoXG4gIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBwcmVmaXg6IHN0cmluZyxcbiAgc2VlbjogV2Vha1NldDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4sXG4gIGhhbmRsZXI6IEV4dHJhT3B0aW9uc0hhbmRsZXIsXG4pOiB2b2lkID0+IHtcbiAgaWYgKHR5cGVvZiBvcHRpb25zID09ICdvYmplY3QnICYmIG9wdGlvbnMgIT09IG51bGwpIHtcbiAgICBpZiAoc2Vlbi5oYXMob3B0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2lyY3VsYXIgcmVmZXJlbmNlIGluIG9wdGlvbnMnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2Vlbi5hZGQob3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgT2JqZWN0LmVudHJpZXMob3B0aW9ucykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgY29uc3QgbmFtZSA9IHByZWZpeCA/IHByZWZpeCArIGtleSA6IGtleTtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgaXRlcmF0ZUV4dHJhT3B0aW9ucyh2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgbmFtZSArICcuJywgc2VlbiwgaGFuZGxlcik7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGhhbmRsZXIobmFtZSwgdmFsdWUudG9TdHJpbmcoKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykge1xuICAgICAgaGFuZGxlcihuYW1lLCB2YWx1ZSA/ICcxJyA6ICcwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3QgaGFuZGxlIGV4dHJhIGNvbmZpZyB0eXBlOiAke3R5cGVvZiB2YWx1ZX1gKTtcbiAgICB9XG4gIH0pO1xufTtcblxuLyoqXG4gKiBjaGVjayB3ZWIgYXNzZW1ibHkgQVBJJ3MgbGFzdCBlcnJvciBhbmQgdGhyb3cgZXJyb3IgaWYgYW55IGVycm9yIG9jY3VycmVkLlxuICogQHBhcmFtIG1lc3NhZ2UgYSBtZXNzYWdlIHVzZWQgd2hlbiBhbiBlcnJvciBvY2N1cnJlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IGNoZWNrTGFzdEVycm9yID0gKG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQgPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcblxuICBjb25zdCBzdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XG4gIHRyeSB7XG4gICAgY29uc3QgcHRyU2l6ZSA9IHdhc20uUFRSX1NJWkU7XG4gICAgY29uc3QgcGFyYW1zT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKDIgKiBwdHJTaXplKTtcbiAgICB3YXNtLl9PcnRHZXRMYXN0RXJyb3IocGFyYW1zT2Zmc2V0LCBwYXJhbXNPZmZzZXQgKyBwdHJTaXplKTtcbiAgICBjb25zdCBlcnJvckNvZGUgPSBOdW1iZXIod2FzbS5nZXRWYWx1ZShwYXJhbXNPZmZzZXQsIHB0clNpemUgPT09IDQgPyAnaTMyJyA6ICdpNjQnKSk7XG4gICAgY29uc3QgZXJyb3JNZXNzYWdlUG9pbnRlciA9IHdhc20uZ2V0VmFsdWUocGFyYW1zT2Zmc2V0ICsgcHRyU2l6ZSwgJyonKTtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvck1lc3NhZ2VQb2ludGVyID8gd2FzbS5VVEY4VG9TdHJpbmcoZXJyb3JNZXNzYWdlUG9pbnRlcikgOiAnJztcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bWVzc2FnZX0gRVJST1JfQ09ERTogJHtlcnJvckNvZGV9LCBFUlJPUl9NRVNTQUdFOiAke2Vycm9yTWVzc2FnZX1gKTtcbiAgfSBmaW5hbGx5IHtcbiAgICB3YXNtLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb24gfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBnZXRJbnN0YW5jZSB9IGZyb20gJy4vd2FzbS1mYWN0b3J5JztcbmltcG9ydCB7IGFsbG9jV2FzbVN0cmluZywgY2hlY2tMYXN0RXJyb3IsIGl0ZXJhdGVFeHRyYU9wdGlvbnMgfSBmcm9tICcuL3dhc20tdXRpbHMnO1xuXG5leHBvcnQgY29uc3Qgc2V0UnVuT3B0aW9ucyA9IChvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMpOiBbbnVtYmVyLCBudW1iZXJbXV0gPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgbGV0IHJ1bk9wdGlvbnNIYW5kbGUgPSAwO1xuICBjb25zdCBhbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgY29uc3QgcnVuT3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICB0cnkge1xuICAgIGlmIChvcHRpb25zPy5sb2dTZXZlcml0eUxldmVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJ1bk9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA9IDI7IC8vIERlZmF1bHQgdG8gd2FybmluZ1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICB0eXBlb2Ygb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsICE9PSAnbnVtYmVyJyB8fFxuICAgICAgIU51bWJlci5pc0ludGVnZXIob3B0aW9ucy5sb2dTZXZlcml0eUxldmVsKSB8fFxuICAgICAgb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsIDwgMCB8fFxuICAgICAgb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsID4gNFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgc2VydmVyaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWx9YCk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LmxvZ1ZlcmJvc2l0eUxldmVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJ1bk9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwgPSAwOyAvLyBEZWZhdWx0IHRvIDBcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzSW50ZWdlcihvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsfWApO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy50ZXJtaW5hdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcnVuT3B0aW9ucy50ZXJtaW5hdGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBsZXQgdGFnRGF0YU9mZnNldCA9IDA7XG4gICAgaWYgKG9wdGlvbnM/LnRhZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0YWdEYXRhT2Zmc2V0ID0gYWxsb2NXYXNtU3RyaW5nKG9wdGlvbnMudGFnLCBhbGxvY3MpO1xuICAgIH1cblxuICAgIHJ1bk9wdGlvbnNIYW5kbGUgPSB3YXNtLl9PcnRDcmVhdGVSdW5PcHRpb25zKFxuICAgICAgcnVuT3B0aW9ucy5sb2dTZXZlcml0eUxldmVsISxcbiAgICAgIHJ1bk9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwhLFxuICAgICAgISFydW5PcHRpb25zLnRlcm1pbmF0ZSEsXG4gICAgICB0YWdEYXRhT2Zmc2V0LFxuICAgICk7XG4gICAgaWYgKHJ1bk9wdGlvbnNIYW5kbGUgPT09IDApIHtcbiAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgY3JlYXRlIHJ1biBvcHRpb25zLlwiKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucz8uZXh0cmEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaXRlcmF0ZUV4dHJhT3B0aW9ucyhvcHRpb25zLmV4dHJhLCAnJywgbmV3IFdlYWtTZXQ8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KCksIChrZXksIHZhbHVlKSA9PiB7XG4gICAgICAgIGNvbnN0IGtleURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcoa2V5LCBhbGxvY3MpO1xuICAgICAgICBjb25zdCB2YWx1ZURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcodmFsdWUsIGFsbG9jcyk7XG5cbiAgICAgICAgaWYgKHdhc20uX09ydEFkZFJ1bkNvbmZpZ0VudHJ5KHJ1bk9wdGlvbnNIYW5kbGUsIGtleURhdGFPZmZzZXQsIHZhbHVlRGF0YU9mZnNldCkgIT09IDApIHtcbiAgICAgICAgICBjaGVja0xhc3RFcnJvcihgQ2FuJ3Qgc2V0IGEgcnVuIGNvbmZpZyBlbnRyeTogJHtrZXl9IC0gJHt2YWx1ZX0uYCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBbcnVuT3B0aW9uc0hhbmRsZSwgYWxsb2NzXTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChydW5PcHRpb25zSGFuZGxlICE9PSAwKSB7XG4gICAgICB3YXNtLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyhydW5PcHRpb25zSGFuZGxlKTtcbiAgICB9XG4gICAgYWxsb2NzLmZvckVhY2goKGFsbG9jKSA9PiB3YXNtLl9mcmVlKGFsbG9jKSk7XG4gICAgdGhyb3cgZTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHR5cGUgeyBJbmZlcmVuY2VTZXNzaW9uIH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgZ2V0SW5zdGFuY2UgfSBmcm9tICcuL3dhc20tZmFjdG9yeSc7XG5pbXBvcnQgeyBhbGxvY1dhc21TdHJpbmcsIGNoZWNrTGFzdEVycm9yLCBpdGVyYXRlRXh0cmFPcHRpb25zIH0gZnJvbSAnLi93YXNtLXV0aWxzJztcblxuY29uc3QgZ2V0R3JhcGhPcHRpbXphdGlvbkxldmVsID0gKGdyYXBoT3B0aW1pemF0aW9uTGV2ZWw6IHN0cmluZyB8IHVua25vd24pOiBudW1iZXIgPT4ge1xuICBzd2l0Y2ggKGdyYXBoT3B0aW1pemF0aW9uTGV2ZWwpIHtcbiAgICBjYXNlICdkaXNhYmxlZCc6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlICdiYXNpYyc6XG4gICAgICByZXR1cm4gMTtcbiAgICBjYXNlICdleHRlbmRlZCc6XG4gICAgICByZXR1cm4gMjtcbiAgICBjYXNlICdhbGwnOlxuICAgICAgcmV0dXJuIDk5O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGdyYXBoIG9wdGltaXphdGlvbiBsZXZlbDogJHtncmFwaE9wdGltaXphdGlvbkxldmVsfWApO1xuICB9XG59O1xuXG5jb25zdCBnZXRFeGVjdXRpb25Nb2RlID0gKGV4ZWN1dGlvbk1vZGU6ICdzZXF1ZW50aWFsJyB8ICdwYXJhbGxlbCcpOiBudW1iZXIgPT4ge1xuICBzd2l0Y2ggKGV4ZWN1dGlvbk1vZGUpIHtcbiAgICBjYXNlICdzZXF1ZW50aWFsJzpcbiAgICAgIHJldHVybiAwO1xuICAgIGNhc2UgJ3BhcmFsbGVsJzpcbiAgICAgIHJldHVybiAxO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGV4ZWN1dGlvbiBtb2RlOiAke2V4ZWN1dGlvbk1vZGV9YCk7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGVuZERlZmF1bHRPcHRpb25zID0gKG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiB2b2lkID0+IHtcbiAgaWYgKCFvcHRpb25zLmV4dHJhKSB7XG4gICAgb3B0aW9ucy5leHRyYSA9IHt9O1xuICB9XG4gIGlmICghb3B0aW9ucy5leHRyYS5zZXNzaW9uKSB7XG4gICAgb3B0aW9ucy5leHRyYS5zZXNzaW9uID0ge307XG4gIH1cbiAgY29uc3Qgc2Vzc2lvbiA9IG9wdGlvbnMuZXh0cmEuc2Vzc2lvbiBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBpZiAoIXNlc3Npb24udXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjYW1lbGNhc2VcbiAgICBzZXNzaW9uLnVzZV9vcnRfbW9kZWxfYnl0ZXNfZGlyZWN0bHkgPSAnMSc7XG4gIH1cblxuICAvLyBpZiB1c2luZyBKU0VQIHdpdGggV2ViR1BVLCBhbHdheXMgZGlzYWJsZSBtZW1vcnkgcGF0dGVyblxuICBpZiAoXG4gICAgb3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMgJiZcbiAgICBvcHRpb25zLmV4ZWN1dGlvblByb3ZpZGVycy5zb21lKChlcCkgPT4gKHR5cGVvZiBlcCA9PT0gJ3N0cmluZycgPyBlcCA6IGVwLm5hbWUpID09PSAnd2ViZ3B1JylcbiAgKSB7XG4gICAgb3B0aW9ucy5lbmFibGVNZW1QYXR0ZXJuID0gZmFsc2U7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGVuZFNlc3Npb25Db25maWcgPSAoc2Vzc2lvbk9wdGlvbnNIYW5kbGU6IG51bWJlciwga2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIGFsbG9jczogbnVtYmVyW10pOiB2b2lkID0+IHtcbiAgY29uc3Qga2V5RGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhrZXksIGFsbG9jcyk7XG4gIGNvbnN0IHZhbHVlRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyh2YWx1ZSwgYWxsb2NzKTtcbiAgaWYgKGdldEluc3RhbmNlKCkuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShzZXNzaW9uT3B0aW9uc0hhbmRsZSwga2V5RGF0YU9mZnNldCwgdmFsdWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xuICAgIGNoZWNrTGFzdEVycm9yKGBDYW4ndCBzZXQgYSBzZXNzaW9uIGNvbmZpZyBlbnRyeTogJHtrZXl9IC0gJHt2YWx1ZX0uYCk7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGVuZEVwT3B0aW9uID0gKGVwT3B0aW9uczogQXJyYXk8W251bWJlciwgbnVtYmVyXT4sIGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCBhbGxvY3M6IG51bWJlcltdKTogdm9pZCA9PiB7XG4gIGNvbnN0IGtleURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcoa2V5LCBhbGxvY3MpO1xuICBjb25zdCB2YWx1ZURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcodmFsdWUsIGFsbG9jcyk7XG4gIGVwT3B0aW9ucy5wdXNoKFtrZXlEYXRhT2Zmc2V0LCB2YWx1ZURhdGFPZmZzZXRdKTtcbn07XG5cbmNvbnN0IHNldEV4ZWN1dGlvblByb3ZpZGVycyA9IGFzeW5jIChcbiAgc2Vzc2lvbk9wdGlvbnNIYW5kbGU6IG51bWJlcixcbiAgZXhlY3V0aW9uUHJvdmlkZXJzOiByZWFkb25seSBJbmZlcmVuY2VTZXNzaW9uLkV4ZWN1dGlvblByb3ZpZGVyQ29uZmlnW10sXG4gIGFsbG9jczogbnVtYmVyW10sXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgZm9yIChjb25zdCBlcCBvZiBleGVjdXRpb25Qcm92aWRlcnMpIHtcbiAgICBsZXQgZXBOYW1lID0gdHlwZW9mIGVwID09PSAnc3RyaW5nJyA/IGVwIDogZXAubmFtZTtcbiAgICBjb25zdCBlcE9wdGlvbnM6IEFycmF5PFtudW1iZXIsIG51bWJlcl0+ID0gW107XG5cbiAgICAvLyBjaGVjayBFUCBuYW1lXG4gICAgc3dpdGNoIChlcE5hbWUpIHtcbiAgICAgIGNhc2UgJ3dlYm5uJzpcbiAgICAgICAgZXBOYW1lID0gJ1dFQk5OJztcbiAgICAgICAgaWYgKHR5cGVvZiBlcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBjb25zdCB3ZWJubk9wdGlvbnMgPSBlcCBhcyBJbmZlcmVuY2VTZXNzaW9uLldlYk5ORXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgICAgICAgLy8gY29uc3QgY29udGV4dCA9ICh3ZWJubk9wdGlvbnMgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJOTk9wdGlvbnNXaXRoTUxDb250ZXh0KT8uY29udGV4dDtcbiAgICAgICAgICBjb25zdCBkZXZpY2VUeXBlID0gKHdlYm5uT3B0aW9ucyBhcyBJbmZlcmVuY2VTZXNzaW9uLldlYk5OQ29udGV4dE9wdGlvbnMpPy5kZXZpY2VUeXBlO1xuICAgICAgICAgIGlmIChkZXZpY2VUeXBlKSB7XG4gICAgICAgICAgICBhcHBlbmRTZXNzaW9uQ29uZmlnKHNlc3Npb25PcHRpb25zSGFuZGxlLCAnZGV2aWNlVHlwZScsIGRldmljZVR5cGUsIGFsbG9jcyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnd2ViZ3B1JzpcbiAgICAgICAgaWYgKEJVSUxEX0RFRlMuVVNFX1dFQkdQVV9FUCkge1xuICAgICAgICAgIGVwTmFtZSA9ICdXZWJHUFUnO1xuICAgICAgICAgIGxldCBjdXN0b21EZXZpY2U6IEdQVURldmljZSB8IHVuZGVmaW5lZDtcblxuICAgICAgICAgIGlmICh0eXBlb2YgZXAgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCBjdXN0b21PcHRpb25zID0gZXAgYXMgdW5rbm93biBhcyB7IGRldmljZTogR1BVRGV2aWNlIH07XG4gICAgICAgICAgICBpZiAoY3VzdG9tT3B0aW9ucy5kZXZpY2UpIHtcbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBHUFVEZXZpY2UgIT09ICd1bmRlZmluZWQnICYmIGN1c3RvbU9wdGlvbnMuZGV2aWNlIGluc3RhbmNlb2YgR1BVRGV2aWNlKSB7XG4gICAgICAgICAgICAgICAgY3VzdG9tRGV2aWNlID0gY3VzdG9tT3B0aW9ucy5kZXZpY2U7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEdQVSBkZXZpY2Ugc2V0IGluIFdlYkdQVSBFUCBvcHRpb25zLicpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRPRE86IGhhbmRsZSBtb3JlIG9wdGlvbnNcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBpbmZvID0gZ2V0SW5zdGFuY2UoKS53ZWJncHVSZWdpc3RlckRldmljZSEoY3VzdG9tRGV2aWNlKTtcbiAgICAgICAgICBpZiAoaW5mbykge1xuICAgICAgICAgICAgY29uc3QgW2RldmljZUlkLCBpbnN0YW5jZUhhbmRsZSwgZGV2aWNlSGFuZGxlXSA9IGluZm87XG4gICAgICAgICAgICBhcHBlbmRFcE9wdGlvbihlcE9wdGlvbnMsICdkZXZpY2VJZCcsIGRldmljZUlkLnRvU3RyaW5nKCksIGFsbG9jcyk7XG4gICAgICAgICAgICBhcHBlbmRFcE9wdGlvbihlcE9wdGlvbnMsICd3ZWJncHVJbnN0YW5jZScsIGluc3RhbmNlSGFuZGxlLnRvU3RyaW5nKCksIGFsbG9jcyk7XG4gICAgICAgICAgICBhcHBlbmRFcE9wdGlvbihlcE9wdGlvbnMsICd3ZWJncHVEZXZpY2UnLCBkZXZpY2VIYW5kbGUudG9TdHJpbmcoKSwgYWxsb2NzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZXBOYW1lID0gJ0pTJztcbiAgICAgICAgICBpZiAodHlwZW9mIGVwICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uc3Qgd2ViZ3B1T3B0aW9ucyA9IGVwIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViR3B1RXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgICAgICAgICBpZiAod2ViZ3B1T3B0aW9ucz8ucHJlZmVycmVkTGF5b3V0KSB7XG4gICAgICAgICAgICAgIGlmICh3ZWJncHVPcHRpb25zLnByZWZlcnJlZExheW91dCAhPT0gJ05DSFcnICYmIHdlYmdwdU9wdGlvbnMucHJlZmVycmVkTGF5b3V0ICE9PSAnTkhXQycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHByZWZlcnJlZExheW91dCBtdXN0IGJlIGVpdGhlciAnTkNIVycgb3IgJ05IV0MnOiAke3dlYmdwdU9wdGlvbnMucHJlZmVycmVkTGF5b3V0fWApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGFwcGVuZFNlc3Npb25Db25maWcoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsICdwcmVmZXJyZWRMYXlvdXQnLCB3ZWJncHVPcHRpb25zLnByZWZlcnJlZExheW91dCwgYWxsb2NzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd3YXNtJzpcbiAgICAgIGNhc2UgJ2NwdSc6XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGV4ZWN1dGlvbiBwcm92aWRlcjogJHtlcE5hbWV9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgZXBOYW1lRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhlcE5hbWUsIGFsbG9jcyk7XG4gICAgY29uc3QgZXBPcHRpb25zQ291bnQgPSBlcE9wdGlvbnMubGVuZ3RoO1xuICAgIGxldCBrZXlzT2Zmc2V0ID0gMDtcbiAgICBsZXQgdmFsdWVzT2Zmc2V0ID0gMDtcbiAgICBpZiAoZXBPcHRpb25zQ291bnQgPiAwKSB7XG4gICAgICBrZXlzT2Zmc2V0ID0gZ2V0SW5zdGFuY2UoKS5fbWFsbG9jKGVwT3B0aW9uc0NvdW50ICogZ2V0SW5zdGFuY2UoKS5QVFJfU0laRSk7XG4gICAgICBhbGxvY3MucHVzaChrZXlzT2Zmc2V0KTtcbiAgICAgIHZhbHVlc09mZnNldCA9IGdldEluc3RhbmNlKCkuX21hbGxvYyhlcE9wdGlvbnNDb3VudCAqIGdldEluc3RhbmNlKCkuUFRSX1NJWkUpO1xuICAgICAgYWxsb2NzLnB1c2godmFsdWVzT2Zmc2V0KTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXBPcHRpb25zQ291bnQ7IGkrKykge1xuICAgICAgICBnZXRJbnN0YW5jZSgpLnNldFZhbHVlKGtleXNPZmZzZXQgKyBpICogZ2V0SW5zdGFuY2UoKS5QVFJfU0laRSwgZXBPcHRpb25zW2ldWzBdLCAnKicpO1xuICAgICAgICBnZXRJbnN0YW5jZSgpLnNldFZhbHVlKHZhbHVlc09mZnNldCArIGkgKiBnZXRJbnN0YW5jZSgpLlBUUl9TSVpFLCBlcE9wdGlvbnNbaV1bMV0sICcqJyk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChcbiAgICAgIChhd2FpdCBnZXRJbnN0YW5jZSgpLl9PcnRBcHBlbmRFeGVjdXRpb25Qcm92aWRlcihcbiAgICAgICAgc2Vzc2lvbk9wdGlvbnNIYW5kbGUsXG4gICAgICAgIGVwTmFtZURhdGFPZmZzZXQsXG4gICAgICAgIGtleXNPZmZzZXQsXG4gICAgICAgIHZhbHVlc09mZnNldCxcbiAgICAgICAgZXBPcHRpb25zQ291bnQsXG4gICAgICApKSAhPT0gMFxuICAgICkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoYENhbid0IGFwcGVuZCBleGVjdXRpb24gcHJvdmlkZXI6ICR7ZXBOYW1lfS5gKTtcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBzZXRTZXNzaW9uT3B0aW9ucyA9IGFzeW5jIChvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8W251bWJlciwgbnVtYmVyW11dPiA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBsZXQgc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPSAwO1xuICBjb25zdCBhbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgY29uc3Qgc2Vzc2lvbk9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICBhcHBlbmREZWZhdWx0T3B0aW9ucyhzZXNzaW9uT3B0aW9ucyk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBncmFwaE9wdGltaXphdGlvbkxldmVsID0gZ2V0R3JhcGhPcHRpbXphdGlvbkxldmVsKHNlc3Npb25PcHRpb25zLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWwgPz8gJ2FsbCcpO1xuICAgIGNvbnN0IGV4ZWN1dGlvbk1vZGUgPSBnZXRFeGVjdXRpb25Nb2RlKHNlc3Npb25PcHRpb25zLmV4ZWN1dGlvbk1vZGUgPz8gJ3NlcXVlbnRpYWwnKTtcbiAgICBjb25zdCBsb2dJZERhdGFPZmZzZXQgPVxuICAgICAgdHlwZW9mIHNlc3Npb25PcHRpb25zLmxvZ0lkID09PSAnc3RyaW5nJyA/IGFsbG9jV2FzbVN0cmluZyhzZXNzaW9uT3B0aW9ucy5sb2dJZCwgYWxsb2NzKSA6IDA7XG5cbiAgICBjb25zdCBsb2dTZXZlcml0eUxldmVsID0gc2Vzc2lvbk9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA/PyAyOyAvLyBEZWZhdWx0IHRvIDIgLSB3YXJuaW5nXG4gICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGxvZ1NldmVyaXR5TGV2ZWwpIHx8IGxvZ1NldmVyaXR5TGV2ZWwgPCAwIHx8IGxvZ1NldmVyaXR5TGV2ZWwgPiA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyBzZXJ2ZXJpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke2xvZ1NldmVyaXR5TGV2ZWx9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgbG9nVmVyYm9zaXR5TGV2ZWwgPSBzZXNzaW9uT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCA/PyAwOyAvLyBEZWZhdWx0IHRvIDAgLSB2ZXJib3NlXG4gICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGxvZ1ZlcmJvc2l0eUxldmVsKSB8fCBsb2dWZXJib3NpdHlMZXZlbCA8IDAgfHwgbG9nVmVyYm9zaXR5TGV2ZWwgPiA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyB2ZXJib3NpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke2xvZ1ZlcmJvc2l0eUxldmVsfWApO1xuICAgIH1cblxuICAgIGNvbnN0IG9wdGltaXplZE1vZGVsRmlsZVBhdGhPZmZzZXQgPVxuICAgICAgdHlwZW9mIHNlc3Npb25PcHRpb25zLm9wdGltaXplZE1vZGVsRmlsZVBhdGggPT09ICdzdHJpbmcnXG4gICAgICAgID8gYWxsb2NXYXNtU3RyaW5nKHNlc3Npb25PcHRpb25zLm9wdGltaXplZE1vZGVsRmlsZVBhdGgsIGFsbG9jcylcbiAgICAgICAgOiAwO1xuXG4gICAgc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPSB3YXNtLl9PcnRDcmVhdGVTZXNzaW9uT3B0aW9ucyhcbiAgICAgIGdyYXBoT3B0aW1pemF0aW9uTGV2ZWwsXG4gICAgICAhIXNlc3Npb25PcHRpb25zLmVuYWJsZUNwdU1lbUFyZW5hLFxuICAgICAgISFzZXNzaW9uT3B0aW9ucy5lbmFibGVNZW1QYXR0ZXJuLFxuICAgICAgZXhlY3V0aW9uTW9kZSxcbiAgICAgICEhc2Vzc2lvbk9wdGlvbnMuZW5hYmxlUHJvZmlsaW5nLFxuICAgICAgMCxcbiAgICAgIGxvZ0lkRGF0YU9mZnNldCxcbiAgICAgIGxvZ1NldmVyaXR5TGV2ZWwsXG4gICAgICBsb2dWZXJib3NpdHlMZXZlbCxcbiAgICAgIG9wdGltaXplZE1vZGVsRmlsZVBhdGhPZmZzZXQsXG4gICAgKTtcbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPT09IDApIHtcbiAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgY3JlYXRlIHNlc3Npb24gb3B0aW9ucy5cIik7XG4gICAgfVxuXG4gICAgaWYgKHNlc3Npb25PcHRpb25zLmV4ZWN1dGlvblByb3ZpZGVycykge1xuICAgICAgYXdhaXQgc2V0RXhlY3V0aW9uUHJvdmlkZXJzKHNlc3Npb25PcHRpb25zSGFuZGxlLCBzZXNzaW9uT3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMsIGFsbG9jcyk7XG4gICAgfVxuXG4gICAgaWYgKHNlc3Npb25PcHRpb25zLmVuYWJsZUdyYXBoQ2FwdHVyZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAodHlwZW9mIHNlc3Npb25PcHRpb25zLmVuYWJsZUdyYXBoQ2FwdHVyZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgZW5hYmxlR3JhcGhDYXB0dXJlIG11c3QgYmUgYSBib29sZWFuIHZhbHVlOiAke3Nlc3Npb25PcHRpb25zLmVuYWJsZUdyYXBoQ2FwdHVyZX1gKTtcbiAgICAgIH1cbiAgICAgIGFwcGVuZFNlc3Npb25Db25maWcoXG4gICAgICAgIHNlc3Npb25PcHRpb25zSGFuZGxlLFxuICAgICAgICAnZW5hYmxlR3JhcGhDYXB0dXJlJyxcbiAgICAgICAgc2Vzc2lvbk9wdGlvbnMuZW5hYmxlR3JhcGhDYXB0dXJlLnRvU3RyaW5nKCksXG4gICAgICAgIGFsbG9jcyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHNlc3Npb25PcHRpb25zLmZyZWVEaW1lbnNpb25PdmVycmlkZXMpIHtcbiAgICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhzZXNzaW9uT3B0aW9ucy5mcmVlRGltZW5zaW9uT3ZlcnJpZGVzKSkge1xuICAgICAgICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBmcmVlIGRpbWVuc2lvbiBvdmVycmlkZSBuYW1lIG11c3QgYmUgYSBzdHJpbmc6ICR7bmFtZX1gKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkgfHwgdmFsdWUgPCAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBmcmVlIGRpbWVuc2lvbiBvdmVycmlkZSB2YWx1ZSBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXI6ICR7dmFsdWV9YCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbmFtZU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhuYW1lLCBhbGxvY3MpO1xuICAgICAgICBpZiAod2FzbS5fT3J0QWRkRnJlZURpbWVuc2lvbk92ZXJyaWRlKHNlc3Npb25PcHRpb25zSGFuZGxlLCBuYW1lT2Zmc2V0LCB2YWx1ZSkgIT09IDApIHtcbiAgICAgICAgICBjaGVja0xhc3RFcnJvcihgQ2FuJ3Qgc2V0IGEgZnJlZSBkaW1lbnNpb24gb3ZlcnJpZGU6ICR7bmFtZX0gLSAke3ZhbHVlfS5gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzZXNzaW9uT3B0aW9ucy5leHRyYSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpdGVyYXRlRXh0cmFPcHRpb25zKHNlc3Npb25PcHRpb25zLmV4dHJhLCAnJywgbmV3IFdlYWtTZXQ8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KCksIChrZXksIHZhbHVlKSA9PiB7XG4gICAgICAgIGFwcGVuZFNlc3Npb25Db25maWcoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGtleSwgdmFsdWUsIGFsbG9jcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gW3Nlc3Npb25PcHRpb25zSGFuZGxlLCBhbGxvY3NdO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKHNlc3Npb25PcHRpb25zSGFuZGxlICE9PSAwKSB7XG4gICAgICBpZiAod2FzbS5fT3J0UmVsZWFzZVNlc3Npb25PcHRpb25zKHNlc3Npb25PcHRpb25zSGFuZGxlKSAhPT0gMCkge1xuICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IHJlbGVhc2Ugc2Vzc2lvbiBvcHRpb25zLlwiKTtcbiAgICAgIH1cbiAgICB9XG4gICAgYWxsb2NzLmZvckVhY2goKGFsbG9jKSA9PiB3YXNtLl9mcmVlKGFsbG9jKSk7XG4gICAgdGhyb3cgZTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yIH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuLy8gYSBkdW1teSB0eXBlIGRlY2xhcmF0aW9uIGZvciBGbG9hdDE2QXJyYXkgaW4gY2FzZSBhbnkgcG9seWZpbGwgaXMgYXZhaWxhYmxlLlxuZGVjbGFyZSBnbG9iYWwge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIGNvbnN0IEZsb2F0MTZBcnJheTogYW55O1xufVxuXG4vLyBUaGlzIGZpbGUgaW5jbHVkZXMgY29tbW9uIGRlZmluaXRpb25zLiBUaGV5IGRvIE5PVCBoYXZlIGRlcGVuZGVuY3kgb24gdGhlIFdlYkFzc2VtYmx5IGluc3RhbmNlLlxuXG4vKipcbiAqIENvcGllZCBmcm9tIE9OTlggZGVmaW5pdGlvbi4gVXNlIHRoaXMgdG8gZHJvcCBkZXBlbmRlbmN5ICdvbm54X3Byb3RvJyB0byBkZWNyZWFzZSBjb21waWxlZCAuanMgZmlsZSBzaXplLlxuICovXG5leHBvcnQgY29uc3QgZW51bSBEYXRhVHlwZSB7XG4gIHVuZGVmaW5lZCA9IDAsXG4gIGZsb2F0ID0gMSxcbiAgdWludDggPSAyLFxuICBpbnQ4ID0gMyxcbiAgdWludDE2ID0gNCxcbiAgaW50MTYgPSA1LFxuICBpbnQzMiA9IDYsXG4gIGludDY0ID0gNyxcbiAgc3RyaW5nID0gOCxcbiAgYm9vbCA9IDksXG4gIGZsb2F0MTYgPSAxMCxcbiAgZG91YmxlID0gMTEsXG4gIHVpbnQzMiA9IDEyLFxuICB1aW50NjQgPSAxMyxcbiAgY29tcGxleDY0ID0gMTQsXG4gIGNvbXBsZXgxMjggPSAxNSxcbiAgYmZsb2F0MTYgPSAxNixcblxuICAvLyA0LWJpdCBkYXRhLXR5cGVzXG4gIHVpbnQ0ID0gMjEsXG4gIGludDQgPSAyMixcbn1cblxuLyoqXG4gKiBNYXAgc3RyaW5nIHRlbnNvciBkYXRhIHRvIGVudW0gdmFsdWVcbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtID0gKHR5cGU6IHN0cmluZyk6IERhdGFUeXBlID0+IHtcbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAnaW50OCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuaW50ODtcbiAgICBjYXNlICd1aW50OCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUudWludDg7XG4gICAgY2FzZSAnYm9vbCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuYm9vbDtcbiAgICBjYXNlICdpbnQxNic6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuaW50MTY7XG4gICAgY2FzZSAndWludDE2JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS51aW50MTY7XG4gICAgY2FzZSAnaW50MzInOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmludDMyO1xuICAgIGNhc2UgJ3VpbnQzMic6XG4gICAgICByZXR1cm4gRGF0YVR5cGUudWludDMyO1xuICAgIGNhc2UgJ2Zsb2F0MTYnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmZsb2F0MTY7XG4gICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuZmxvYXQ7XG4gICAgY2FzZSAnZmxvYXQ2NCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuZG91YmxlO1xuICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuc3RyaW5nO1xuICAgIGNhc2UgJ2ludDY0JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5pbnQ2NDtcbiAgICBjYXNlICd1aW50NjQnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnVpbnQ2NDtcbiAgICBjYXNlICdpbnQ0JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5pbnQ0O1xuICAgIGNhc2UgJ3VpbnQ0JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS51aW50NDtcblxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHt0eXBlfWApO1xuICB9XG59O1xuXG4vKipcbiAqIE1hcCBlbnVtIHZhbHVlIHRvIHN0cmluZyB0ZW5zb3IgZGF0YVxuICovXG5leHBvcnQgY29uc3QgdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcgPSAodHlwZVByb3RvOiBEYXRhVHlwZSk6IFRlbnNvci5UeXBlID0+IHtcbiAgc3dpdGNoICh0eXBlUHJvdG8pIHtcbiAgICBjYXNlIERhdGFUeXBlLmludDg6XG4gICAgICByZXR1cm4gJ2ludDgnO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDg6XG4gICAgICByZXR1cm4gJ3VpbnQ4JztcbiAgICBjYXNlIERhdGFUeXBlLmJvb2w6XG4gICAgICByZXR1cm4gJ2Jvb2wnO1xuICAgIGNhc2UgRGF0YVR5cGUuaW50MTY6XG4gICAgICByZXR1cm4gJ2ludDE2JztcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQxNjpcbiAgICAgIHJldHVybiAndWludDE2JztcbiAgICBjYXNlIERhdGFUeXBlLmludDMyOlxuICAgICAgcmV0dXJuICdpbnQzMic7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50MzI6XG4gICAgICByZXR1cm4gJ3VpbnQzMic7XG4gICAgY2FzZSBEYXRhVHlwZS5mbG9hdDE2OlxuICAgICAgcmV0dXJuICdmbG9hdDE2JztcbiAgICBjYXNlIERhdGFUeXBlLmZsb2F0OlxuICAgICAgcmV0dXJuICdmbG9hdDMyJztcbiAgICBjYXNlIERhdGFUeXBlLmRvdWJsZTpcbiAgICAgIHJldHVybiAnZmxvYXQ2NCc7XG4gICAgY2FzZSBEYXRhVHlwZS5zdHJpbmc6XG4gICAgICByZXR1cm4gJ3N0cmluZyc7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQ2NDpcbiAgICAgIHJldHVybiAnaW50NjQnO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDY0OlxuICAgICAgcmV0dXJuICd1aW50NjQnO1xuICAgIGNhc2UgRGF0YVR5cGUuaW50NDpcbiAgICAgIHJldHVybiAnaW50NCc7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50NDpcbiAgICAgIHJldHVybiAndWludDQnO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGVQcm90b31gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBnZXQgdGVuc29yIHNpemUgaW4gYnl0ZXMgYnkgdGhlIGdpdmVuIGRhdGEgdHlwZSBhbmQgZGltZW5zaW9uc1xuICogQHJldHVybnMgc2l6ZSBpbiBpbnRlZ2VyIG9yIHVuZGVmaW5lZCBpZiB0aGUgZGF0YSB0eXBlIGlzIG5vdCBzdXBwb3J0ZWRcbiAqL1xuZXhwb3J0IGNvbnN0IGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzID0gKFxuICBkYXRlVHlwZTogbnVtYmVyLFxuICBkaW1zT3JTaXplOiByZWFkb25seSBudW1iZXJbXSB8IG51bWJlcixcbik6IG51bWJlciB8IHVuZGVmaW5lZCA9PiB7XG4gIGNvbnN0IGVsZW1lbnRTaXplID0gW1xuICAgIC0xLCAvLyB1bmRlZmluZWQgPSAwXG4gICAgNCwgLy8gZmxvYXQgPSAxXG4gICAgMSwgLy8gdWludDggPSAyXG4gICAgMSwgLy8gaW50OCA9IDNcbiAgICAyLCAvLyB1aW50MTYgPSA0XG4gICAgMiwgLy8gaW50MTYgPSA1XG4gICAgNCwgLy8gaW50MzIgPSA2XG4gICAgOCwgLy8gaW50NjQgPSA3XG4gICAgLTEsIC8vIHN0cmluZyA9IDhcbiAgICAxLCAvLyBib29sID0gOVxuICAgIDIsIC8vIGZsb2F0MTYgPSAxMFxuICAgIDgsIC8vIGRvdWJsZSA9IDExXG4gICAgNCwgLy8gdWludDMyID0gMTJcbiAgICA4LCAvLyB1aW50NjQgPSAxM1xuICAgIC0xLCAvLyBjb21wbGV4NjQgPSAxNFxuICAgIC0xLCAvLyBjb21wbGV4MTI4ID0gMTVcbiAgICAtMSwgLy8gYmZsb2F0MTYgPSAxNlxuICAgIC0xLCAvLyBGTE9BVDhFNE0zRk4gPSAxN1xuICAgIC0xLCAvLyBGTE9BVDhFNE0zRk5VWiA9IDE4XG4gICAgLTEsIC8vIEZMT0FUOEU1TTIgPSAxOVxuICAgIC0xLCAvLyBGTE9BVDhFNU0yRk5VWiA9IDIwXG4gICAgMC41LCAvLyB1aW50NCA9IDIxXG4gICAgMC41LCAvLyBpbnQ0ID0gMjJcbiAgXVtkYXRlVHlwZV07XG5cbiAgY29uc3Qgc2l6ZSA9IHR5cGVvZiBkaW1zT3JTaXplID09PSAnbnVtYmVyJyA/IGRpbXNPclNpemUgOiBkaW1zT3JTaXplLnJlZHVjZSgoYSwgYikgPT4gYSAqIGIsIDEpO1xuICByZXR1cm4gZWxlbWVudFNpemUgPiAwID8gTWF0aC5jZWlsKHNpemUgKiBlbGVtZW50U2l6ZSkgOiB1bmRlZmluZWQ7XG59O1xuXG4vKipcbiAqIGdldCB0eXBlZCBhcnJheSBjb25zdHJ1Y3RvciBieSB0aGUgZ2l2ZW4gdGVuc29yIHR5cGVcbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IChcbiAgdHlwZTogVGVuc29yLlR5cGUsXG4pOlxuICB8IEZsb2F0MzJBcnJheUNvbnN0cnVjdG9yXG4gIHwgVWludDhBcnJheUNvbnN0cnVjdG9yXG4gIHwgSW50OEFycmF5Q29uc3RydWN0b3JcbiAgfCBVaW50MTZBcnJheUNvbnN0cnVjdG9yXG4gIHwgSW50MTZBcnJheUNvbnN0cnVjdG9yXG4gIHwgSW50MzJBcnJheUNvbnN0cnVjdG9yXG4gIHwgQmlnSW50NjRBcnJheUNvbnN0cnVjdG9yXG4gIHwgVWludDhBcnJheUNvbnN0cnVjdG9yXG4gIHwgRmxvYXQ2NEFycmF5Q29uc3RydWN0b3JcbiAgfCBVaW50MzJBcnJheUNvbnN0cnVjdG9yXG4gIHwgQmlnVWludDY0QXJyYXlDb25zdHJ1Y3RvciA9PiB7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ2Zsb2F0MTYnOlxuICAgICAgLy8gYWxsb3cgRmxvYXQxNkFycmF5IHBvbHlmaWxsLlxuICAgICAgcmV0dXJuIHR5cGVvZiBGbG9hdDE2QXJyYXkgIT09ICd1bmRlZmluZWQnICYmIEZsb2F0MTZBcnJheS5mcm9tID8gRmxvYXQxNkFycmF5IDogVWludDE2QXJyYXk7XG4gICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICByZXR1cm4gRmxvYXQzMkFycmF5O1xuICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICAgIHJldHVybiBVaW50OEFycmF5O1xuICAgIGNhc2UgJ2ludDgnOlxuICAgICAgcmV0dXJuIEludDhBcnJheTtcbiAgICBjYXNlICd1aW50MTYnOlxuICAgICAgcmV0dXJuIFVpbnQxNkFycmF5O1xuICAgIGNhc2UgJ2ludDE2JzpcbiAgICAgIHJldHVybiBJbnQxNkFycmF5O1xuICAgIGNhc2UgJ2ludDMyJzpcbiAgICAgIHJldHVybiBJbnQzMkFycmF5O1xuICAgIGNhc2UgJ2Jvb2wnOlxuICAgICAgcmV0dXJuIFVpbnQ4QXJyYXk7XG4gICAgY2FzZSAnZmxvYXQ2NCc6XG4gICAgICByZXR1cm4gRmxvYXQ2NEFycmF5O1xuICAgIGNhc2UgJ3VpbnQzMic6XG4gICAgICByZXR1cm4gVWludDMyQXJyYXk7XG4gICAgY2FzZSAnaW50NjQnOlxuICAgICAgcmV0dXJuIEJpZ0ludDY0QXJyYXk7XG4gICAgY2FzZSAndWludDY0JzpcbiAgICAgIHJldHVybiBCaWdVaW50NjRBcnJheTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCB0eXBlOiAke3R5cGV9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogTWFwIHN0cmluZyBsb2cgbGV2ZWwgdG8gaW50ZWdlciB2YWx1ZVxuICovXG5leHBvcnQgY29uc3QgbG9nTGV2ZWxTdHJpbmdUb0VudW0gPSAobG9nTGV2ZWw/OiAndmVyYm9zZScgfCAnaW5mbycgfCAnd2FybmluZycgfCAnZXJyb3InIHwgJ2ZhdGFsJyk6IG51bWJlciA9PiB7XG4gIHN3aXRjaCAobG9nTGV2ZWwpIHtcbiAgICBjYXNlICd2ZXJib3NlJzpcbiAgICAgIHJldHVybiAwO1xuICAgIGNhc2UgJ2luZm8nOlxuICAgICAgcmV0dXJuIDE7XG4gICAgY2FzZSAnd2FybmluZyc6XG4gICAgICByZXR1cm4gMjtcbiAgICBjYXNlICdlcnJvcic6XG4gICAgICByZXR1cm4gMztcbiAgICBjYXNlICdmYXRhbCc6XG4gICAgICByZXR1cm4gNDtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBsb2dnaW5nIGxldmVsOiAke2xvZ0xldmVsfWApO1xuICB9XG59O1xuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIHRlbnNvciB0eXBlIGlzIHN1cHBvcnRlZCBieSBHUFUgYnVmZmVyXG4gKi9cbmV4cG9ydCBjb25zdCBpc0dwdUJ1ZmZlclN1cHBvcnRlZFR5cGUgPSAodHlwZTogVGVuc29yLlR5cGUpOiB0eXBlIGlzIFRlbnNvci5HcHVCdWZmZXJEYXRhVHlwZXMgPT5cbiAgdHlwZSA9PT0gJ2Zsb2F0MzInIHx8XG4gIHR5cGUgPT09ICdmbG9hdDE2JyB8fFxuICB0eXBlID09PSAnaW50MzInIHx8XG4gIHR5cGUgPT09ICdpbnQ2NCcgfHxcbiAgdHlwZSA9PT0gJ3VpbnQzMicgfHxcbiAgdHlwZSA9PT0gJ3VpbnQ4JyB8fFxuICB0eXBlID09PSAnYm9vbCcgfHxcbiAgdHlwZSA9PT0gJ3VpbnQ0JyB8fFxuICB0eXBlID09PSAnaW50NCc7XG5cbi8qKlxuICogQ2hlY2sgd2hldGhlciB0aGUgZ2l2ZW4gdGVuc29yIHR5cGUgaXMgc3VwcG9ydGVkIGJ5IFdlYk5OIE1MVGVuc29yXG4gKi9cbmV4cG9ydCBjb25zdCBpc01MVGVuc29yU3VwcG9ydGVkVHlwZSA9ICh0eXBlOiBUZW5zb3IuVHlwZSk6IHR5cGUgaXMgVGVuc29yLk1MVGVuc29yRGF0YVR5cGVzID0+XG4gIHR5cGUgPT09ICdmbG9hdDMyJyB8fFxuICB0eXBlID09PSAnZmxvYXQxNicgfHxcbiAgdHlwZSA9PT0gJ2ludDMyJyB8fFxuICB0eXBlID09PSAnaW50NjQnIHx8XG4gIHR5cGUgPT09ICd1aW50MzInIHx8XG4gIHR5cGUgPT09ICd1aW50NjQnIHx8XG4gIHR5cGUgPT09ICdpbnQ4JyB8fFxuICB0eXBlID09PSAndWludDgnIHx8XG4gIHR5cGUgPT09ICdib29sJyB8fFxuICB0eXBlID09PSAndWludDQnIHx8XG4gIHR5cGUgPT09ICdpbnQ0JztcblxuLyoqXG4gKiBNYXAgc3RyaW5nIGRhdGEgbG9jYXRpb24gdG8gaW50ZWdlciB2YWx1ZVxuICovXG5leHBvcnQgY29uc3QgZGF0YUxvY2F0aW9uU3RyaW5nVG9FbnVtID0gKGxvY2F0aW9uOiBUZW5zb3IuRGF0YUxvY2F0aW9uKTogbnVtYmVyID0+IHtcbiAgc3dpdGNoIChsb2NhdGlvbikge1xuICAgIGNhc2UgJ25vbmUnOlxuICAgICAgcmV0dXJuIDA7XG4gICAgY2FzZSAnY3B1JzpcbiAgICAgIHJldHVybiAxO1xuICAgIGNhc2UgJ2NwdS1waW5uZWQnOlxuICAgICAgcmV0dXJuIDI7XG4gICAgY2FzZSAndGV4dHVyZSc6XG4gICAgICByZXR1cm4gMztcbiAgICBjYXNlICdncHUtYnVmZmVyJzpcbiAgICAgIHJldHVybiA0O1xuICAgIGNhc2UgJ21sLXRlbnNvcic6XG4gICAgICByZXR1cm4gNTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIGxvY2F0aW9uOiAke2xvY2F0aW9ufWApO1xuICB9XG59O1xuXG4vKipcbiAqIE1hcCBpbnRlZ2VyIGRhdGEgbG9jYXRpb24gdG8gc3RyaW5nIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCBkYXRhTG9jYXRpb25FbnVtVG9TdHJpbmcgPSAobG9jYXRpb246IG51bWJlcik6IFRlbnNvci5EYXRhTG9jYXRpb24gfCB1bmRlZmluZWQgPT5cbiAgKFsnbm9uZScsICdjcHUnLCAnY3B1LXBpbm5lZCcsICd0ZXh0dXJlJywgJ2dwdS1idWZmZXInLCAnbWwtdGVuc29yJ10gYXMgY29uc3QpW2xvY2F0aW9uXTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgaXNOb2RlIH0gZnJvbSAnLi93YXNtLXV0aWxzLWVudic7XG5cbi8qKlxuICogTG9hZCBhIGZpbGUgaW50byBhIFVpbnQ4QXJyYXkuXG4gKlxuICogQHBhcmFtIGZpbGUgLSB0aGUgZmlsZSB0byBsb2FkLiBDYW4gYmUgYSBVUkwvcGF0aCwgYSBCbG9iLCBhbiBBcnJheUJ1ZmZlciwgb3IgYSBVaW50OEFycmF5LlxuICogQHJldHVybnMgYSBVaW50OEFycmF5IGNvbnRhaW5pbmcgdGhlIGZpbGUgZGF0YS5cbiAqL1xuZXhwb3J0IGNvbnN0IGxvYWRGaWxlID0gYXN5bmMgKGZpbGU6IHN0cmluZyB8IEJsb2IgfCBBcnJheUJ1ZmZlckxpa2UgfCBVaW50OEFycmF5KTogUHJvbWlzZTxVaW50OEFycmF5PiA9PiB7XG4gIGlmICh0eXBlb2YgZmlsZSA9PT0gJ3N0cmluZycpIHtcbiAgICBpZiAoaXNOb2RlKSB7XG4gICAgICAvLyBsb2FkIGZpbGUgaW50byBBcnJheUJ1ZmZlciBpbiBOb2RlLmpzXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB7IHJlYWRGaWxlIH0gPSByZXF1aXJlKCdub2RlOmZzL3Byb21pc2VzJyk7XG4gICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCByZWFkRmlsZShmaWxlKSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChlLmNvZGUgPT09ICdFUlJfRlNfRklMRV9UT09fTEFSR0UnKSB7XG4gICAgICAgICAgLy8gZmlsZSBpcyB0b28gbGFyZ2UsIHVzZSBmcy5jcmVhdGVSZWFkU3RyZWFtIGluc3RlYWRcbiAgICAgICAgICBjb25zdCB7IGNyZWF0ZVJlYWRTdHJlYW0gfSA9IHJlcXVpcmUoJ25vZGU6ZnMnKTtcbiAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjcmVhdGVSZWFkU3RyZWFtKGZpbGUpO1xuICAgICAgICAgIGNvbnN0IGNodW5rczogVWludDhBcnJheVtdID0gW107XG4gICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBjaHVuayBvZiBzdHJlYW0pIHtcbiAgICAgICAgICAgIGNodW5rcy5wdXNoKGNodW5rKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KEJ1ZmZlci5jb25jYXQoY2h1bmtzKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gbG9hZCBmaWxlIGludG8gQXJyYXlCdWZmZXIgaW4gYnJvd3NlcnNcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goZmlsZSk7XG4gICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIGxvYWQgZXh0ZXJuYWwgZGF0YSBmaWxlOiAke2ZpbGV9YCk7XG4gICAgICB9XG4gICAgICBjb25zdCBjb250ZW50TGVuZ3RoSGVhZGVyID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ0NvbnRlbnQtTGVuZ3RoJyk7XG4gICAgICBjb25zdCBmaWxlU2l6ZSA9IGNvbnRlbnRMZW5ndGhIZWFkZXIgPyBwYXJzZUludChjb250ZW50TGVuZ3RoSGVhZGVyLCAxMCkgOiAwO1xuICAgICAgaWYgKGZpbGVTaXplIDwgMTA3Mzc0MTgyNCAvKiAxR0IgKi8pIHtcbiAgICAgICAgLy8gd2hlbiBDb250ZW50LUxlbmd0aCBoZWFkZXIgaXMgbm90IHNldCwgd2UgY2Fubm90IGRldGVybWluZSB0aGUgZmlsZSBzaXplLiBXZSBhc3N1bWUgaXQgaXMgc21hbGwgZW5vdWdoIHRvXG4gICAgICAgIC8vIGxvYWQgaW50byBtZW1vcnkuXG4gICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCByZXNwb25zZS5hcnJheUJ1ZmZlcigpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGZpbGUgaXMgdG9vIGxhcmdlLCB1c2Ugc3RyZWFtIGluc3RlYWRcbiAgICAgICAgaWYgKCFyZXNwb25zZS5ib2R5KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBmYWlsZWQgdG8gbG9hZCBleHRlcm5hbCBkYXRhIGZpbGU6ICR7ZmlsZX0sIG5vIHJlc3BvbnNlIGJvZHkuYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVhZGVyID0gcmVzcG9uc2UuYm9keS5nZXRSZWFkZXIoKTtcblxuICAgICAgICBsZXQgYnVmZmVyO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIHRyeSB0byBjcmVhdGUgQXJyYXlCdWZmZXIgZGlyZWN0bHlcbiAgICAgICAgICBidWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIoZmlsZVNpemUpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBSYW5nZUVycm9yKSB7XG4gICAgICAgICAgICAvLyB1c2UgV2ViQXNzZW1ibHkgTWVtb3J5IHRvIGFsbG9jYXRlIGxhcmdlciBBcnJheUJ1ZmZlclxuICAgICAgICAgICAgY29uc3QgcGFnZXMgPSBNYXRoLmNlaWwoZmlsZVNpemUgLyA2NTUzNik7XG4gICAgICAgICAgICBidWZmZXIgPSBuZXcgV2ViQXNzZW1ibHkuTWVtb3J5KHsgaW5pdGlhbDogcGFnZXMsIG1heGltdW06IHBhZ2VzIH0pLmJ1ZmZlcjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgb2Zmc2V0ID0gMDtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnN0YW50LWNvbmRpdGlvblxuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgIGNvbnN0IHsgZG9uZSwgdmFsdWUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgICAgICAgaWYgKGRvbmUpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBjaHVua1NpemUgPSB2YWx1ZS5ieXRlTGVuZ3RoO1xuICAgICAgICAgIGNvbnN0IGNodW5rID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyLCBvZmZzZXQsIGNodW5rU2l6ZSk7XG4gICAgICAgICAgY2h1bmsuc2V0KHZhbHVlKTtcbiAgICAgICAgICBvZmZzZXQgKz0gY2h1bmtTaXplO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShidWZmZXIsIDAsIGZpbGVTaXplKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSBpZiAoZmlsZSBpbnN0YW5jZW9mIEJsb2IpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYXdhaXQgZmlsZS5hcnJheUJ1ZmZlcigpKTtcbiAgfSBlbHNlIGlmIChmaWxlIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgIHJldHVybiBmaWxlO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShmaWxlKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRW52IH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgbG9nTGV2ZWxTdHJpbmdUb0VudW0gfSBmcm9tICcuLi93YXNtLWNvbW1vbic7XG5cbnR5cGUgTG9nTGV2ZWwgPSBOb25OdWxsYWJsZTxFbnZbJ2xvZ0xldmVsJ10+O1xudHlwZSBNZXNzYWdlU3RyaW5nID0gc3RyaW5nO1xudHlwZSBNZXNzYWdlRnVuY3Rpb24gPSAoKSA9PiBzdHJpbmc7XG50eXBlIE1lc3NhZ2UgPSBNZXNzYWdlU3RyaW5nIHwgTWVzc2FnZUZ1bmN0aW9uO1xuXG5jb25zdCBsb2dMZXZlbFByZWZpeCA9IFsnVicsICdJJywgJ1cnLCAnRScsICdGJ107XG5cbmNvbnN0IGRvTG9nID0gKGxldmVsOiBudW1iZXIsIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLmxvZyhgWyR7bG9nTGV2ZWxQcmVmaXhbbGV2ZWxdfSwke25ldyBEYXRlKCkudG9JU09TdHJpbmcoKX1dJHttZXNzYWdlfWApO1xufTtcblxubGV0IGNvbmZpZ0xvZ0xldmVsOiBMb2dMZXZlbCB8IHVuZGVmaW5lZDtcbmxldCBkZWJ1ZzogYm9vbGVhbiB8IHVuZGVmaW5lZDtcblxuZXhwb3J0IGNvbnN0IGNvbmZpZ3VyZUxvZ2dlciA9ICgkY29uZmlnTG9nTGV2ZWw6IExvZ0xldmVsLCAkZGVidWc6IGJvb2xlYW4pOiB2b2lkID0+IHtcbiAgY29uZmlnTG9nTGV2ZWwgPSAkY29uZmlnTG9nTGV2ZWw7XG4gIGRlYnVnID0gJGRlYnVnO1xufTtcblxuLyoqXG4gKiBBIHNpbXBsZSBsb2dnaW5nIHV0aWxpdHkgdG8gbG9nIG1lc3NhZ2VzIHRvIHRoZSBjb25zb2xlLlxuICovXG5leHBvcnQgY29uc3QgTE9HID0gKGxvZ0xldmVsOiBMb2dMZXZlbCwgbXNnOiBNZXNzYWdlKTogdm9pZCA9PiB7XG4gIGNvbnN0IG1lc3NhZ2VMZXZlbCA9IGxvZ0xldmVsU3RyaW5nVG9FbnVtKGxvZ0xldmVsKTtcbiAgY29uc3QgY29uZmlnTGV2ZWwgPSBsb2dMZXZlbFN0cmluZ1RvRW51bShjb25maWdMb2dMZXZlbCk7XG4gIGlmIChtZXNzYWdlTGV2ZWwgPj0gY29uZmlnTGV2ZWwpIHtcbiAgICBkb0xvZyhtZXNzYWdlTGV2ZWwsIHR5cGVvZiBtc2cgPT09ICdmdW5jdGlvbicgPyBtc2coKSA6IG1zZyk7XG4gIH1cbn07XG5cbi8qKlxuICogQSBzaW1wbGUgbG9nZ2luZyB1dGlsaXR5IHRvIGxvZyBtZXNzYWdlcyB0byB0aGUgY29uc29sZS4gT25seSBsb2dzIHdoZW4gZGVidWcgaXMgZW5hYmxlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IExPR19ERUJVRzogdHlwZW9mIExPRyA9ICguLi5hcmdzOiBQYXJhbWV0ZXJzPHR5cGVvZiBMT0c+KSA9PiB7XG4gIGlmIChkZWJ1Zykge1xuICAgIExPRyguLi5hcmdzKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLyogZXNsaW50LWRpc2FibGUgbm8tcGFyYW0tcmVhc3NpZ24gKi9cblxuZXhwb3J0IGNsYXNzIE1hdE11bFV0aWwge1xuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBleHBlY3RlZCBzaGFwZSB3aGVuIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuICAgKiBAcGFyYW0gYSBUaGUgc2hhcGUgb2YgdGVuc29yIEEuIFNob3VsZCBiZSBhIHR1cGxlIG9mIDIgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHBhcmFtIGIgVGhlIHNoYXBlIG9mIHRlbnNvciBCLiBTaG91bGQgYmUgYSB0dXBsZSBvZiAyIHBvc2l0aXZlIGludGVnZXJzXG4gICAqIEByZXR1cm5zIFRoZSBleHBlY3RlZCBzaGFwZSBvZiB0aGUgcmVzdWx0LCBvciB1bmRlZmluZWQgaWYgTi9BXG4gICAqL1xuICBzdGF0aWMgY2FsY01hdE11bFNoYXBlKGE6IFtudW1iZXIsIG51bWJlcl0sIGI6IFtudW1iZXIsIG51bWJlcl0pOiBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gYVsxXSAhPT0gYlswXSA/IHVuZGVmaW5lZCA6IFthWzBdLCBiWzFdXTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQnJvYWRjYXN0VXRpbCB7XG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIGV4cGVjdGVkIHNoYXBlIHdoZW4gYnJvYWRjYXN0aW5nIDIgdGVuc29yc1xuICAgKiBAcGFyYW0gYSBUaGUgc2hhcGUgb2YgdGVuc29yIEEuIFNob3VsZCBiZSBhbiBhcnJheSBvZiBwb3NpdGl2ZSBpbnRlZ2Vyc1xuICAgKiBAcGFyYW0gYiBUaGUgc2hhcGUgb2YgdGVuc29yIEIuIFNob3VsZCBiZSBhbiBhcnJheSBvZiBwb3NpdGl2ZSBpbnRlZ2Vyc1xuICAgKiBAcGFyYW0gaXNNYXRNdWwgV2hldGhlciB0aGUgb3BlcmF0aW9uIGlzIE1hdE11bFxuICAgKiBAcmV0dXJucyBUaGUgZXhwZWN0ZWQgc2hhcGUgb2YgdGhlIHJlc3VsdCwgb3IgdW5kZWZpbmVkIGlmIE4vQVxuICAgKi9cbiAgc3RhdGljIGNhbGNTaGFwZShcbiAgICBhZGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgYmRpbXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGlzTWF0TXVsID0gZmFsc2UsXG4gICk6IHJlYWRvbmx5IG51bWJlcltdIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBhcmFuayA9IGFkaW1zLmxlbmd0aDtcbiAgICBjb25zdCBicmFuayA9IGJkaW1zLmxlbmd0aDtcbiAgICBpZiAoYXJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBiZGltcztcbiAgICB9XG4gICAgaWYgKGJyYW5rID09PSAwKSB7XG4gICAgICByZXR1cm4gYWRpbXM7XG4gICAgfVxuICAgIGNvbnN0IGNyYW5rID0gTWF0aC5tYXgoYWRpbXMubGVuZ3RoLCBiZGltcy5sZW5ndGgpO1xuICAgIGNvbnN0IGNkaW1zID0gbmV3IEFycmF5PG51bWJlcj4oY3JhbmspO1xuXG4gICAgLy8gY2FsY3VsYXRlIHRoZSBsYXN0IDIgZGltZW5zaW9uIGlmIGl0IGlzIE1hdE11bFxuICAgIGlmIChpc01hdE11bCkge1xuICAgICAgaWYgKGFyYW5rIDwgMiB8fCBicmFuayA8IDIpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNTaGFwZU1hdE11bCA9IE1hdE11bFV0aWwuY2FsY01hdE11bFNoYXBlKFxuICAgICAgICBbYWRpbXNbYXJhbmsgLSAyXSwgYWRpbXNbYXJhbmsgLSAxXV0sXG4gICAgICAgIFtiZGltc1ticmFuayAtIDJdLCBiZGltc1ticmFuayAtIDFdXSxcbiAgICAgICk7XG4gICAgICBpZiAoY1NoYXBlTWF0TXVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIFtjZGltc1tjcmFuayAtIDJdLCBjZGltc1tjcmFuayAtIDFdXSA9IGNTaGFwZU1hdE11bDtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gaXNNYXRNdWwgPyAzIDogMTsgaSA8PSBjcmFuazsgaSsrKSB7XG4gICAgICBjb25zdCBhTGVuID0gYXJhbmsgLSBpIDwgMCA/IDEgOiBhZGltc1thcmFuayAtIGldO1xuICAgICAgY29uc3QgYkxlbiA9IGJyYW5rIC0gaSA8IDAgPyAxIDogYmRpbXNbYnJhbmsgLSBpXTtcblxuICAgICAgaWYgKGFMZW4gIT09IGJMZW4gJiYgYUxlbiA+IDEgJiYgYkxlbiA+IDEpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG1heCA9IE1hdGgubWF4KGFMZW4sIGJMZW4pO1xuICAgICAgaWYgKGFMZW4gJiYgYkxlbikge1xuICAgICAgICBjZGltc1tjcmFuayAtIGldID0gTWF0aC5tYXgoYUxlbiwgYkxlbik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyB3aGVuIGVpdGhlciBhTGVuIG9yIGJMZW4gaXMgMCwgdGhlIG90aGVyIHNob3VsZCBiZSBlaXRoZXIgMCBvciAxLCBvdGhlcndpc2UgaXQgaXMgbm90IGJyb2FkY2FzdGFibGUuXG4gICAgICAgIGlmIChtYXggPiAxKSB7XG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBjZGltc1tjcmFuayAtIGldID0gMDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY2RpbXM7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lIGlmIGEgc2hhcGUgaXMgdW5pZGlyZWN0aW9uYWwgYnJvYWRjYXN0YWJsZSB0byBhbm90aGVyIHNoYXBlXG4gICAqIEBwYXJhbSBzaGFwZSBUaGUgaW5wdXQgc2hhcGVcbiAgICogQHBhcmFtIGZpbmFsU2hhcGUgVGhlIGRlc2lyZWQgc2hhcGUgYWZ0ZXIgYnJvYWRjYXN0aW5nXG4gICAqL1xuICBzdGF0aWMgaXNWYWxpZEJyb2FkY2FzdChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGZpbmFsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogYm9vbGVhbiB7XG4gICAgLy8gYWxpZ24gc2hhcGUgdG8gdGhlIHJpZ2h0XG4gICAgY29uc3QgaW5wdXRSYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IGZpbmFsUmFuayA9IGZpbmFsU2hhcGUubGVuZ3RoO1xuICAgIGlmIChpbnB1dFJhbmsgPiBmaW5hbFJhbmspIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPD0gaW5wdXRSYW5rOyBpKyspIHtcbiAgICAgIGlmIChzaGFwZVtpbnB1dFJhbmsgLSBpXSAhPT0gMSAmJiBzaGFwZVtpbnB1dFJhbmsgLSBpXSAhPT0gZmluYWxTaGFwZVtmaW5hbFJhbmsgLSBpXSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTaGFwZVV0aWwge1xuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBzaXplIChudW1iZXIgb2YgZWxlbWVudHMpXG4gICAqL1xuICBzdGF0aWMgc2l6ZShkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IG51bWJlciB7XG4gICAgcmV0dXJuIFNoYXBlVXRpbC5nZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXMsIDAsIGRpbXMubGVuZ3RoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBjb252ZXJ0IGRpbXMgY29ycmVzcG9uZGluZyB0byB0eXBlIGNoYW5nZSB0byBwYWNrLiBleC4gdWludDggZGF0YSB0byB1aW50MzJcbiAgICovXG4gIHN0YXRpYyBjb252ZXJ0U2hhcGUoZGltczogcmVhZG9ubHkgbnVtYmVyW10sIHNpemUgPSA0KTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGNvbnN0IHJhbmsgPSBkaW1zLmxlbmd0aDtcbiAgICBpZiAocmFuayA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBjb25zdCBuZXdEaW1zID0gbmV3IEFycmF5KHJhbmspO1xuICAgIGxldCBpID0gcmFuayAtIDE7XG4gICAgd2hpbGUgKGkgPj0gMCkge1xuICAgICAgaWYgKGRpbXNbaV0gJSBzaXplID09PSAwKSB7XG4gICAgICAgIG5ld0RpbXNbaV0gPSBkaW1zW2ldIC8gc2l6ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAoc2l6ZSAlIGRpbXNbaV0gIT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3QgY29udmVydCBzaGFwZScpO1xuICAgICAgfVxuICAgICAgbmV3RGltc1tpXSA9IDE7XG4gICAgICBzaXplIC89IGRpbXNbaV07XG4gICAgICBpLS07XG4gICAgfVxuICAgIGZvciAoaS0tOyBpID49IDA7IGktLSkge1xuICAgICAgbmV3RGltc1tpXSA9IGRpbXNbaV07XG4gICAgfVxuICAgIHJldHVybiBuZXdEaW1zO1xuICB9XG5cbiAgLyoqXG4gICAqIGNhbGN1bGF0ZSB0aGUgc2l6ZSAobnVtYmVyIG9mIGVsZW1lbnRzKSBmcm9tIHRoZSBnaXZlbiBheGlzIChpbmNsdXNpdmUpXG4gICAqL1xuICBzdGF0aWMgc2l6ZUZyb21EaW1lbnNpb24oZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGF4aXM6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKGF4aXMgPCAwIHx8IGF4aXMgPiBkaW1zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGRpbWVuc2lvbiBvZiAke2F4aXN9IGZvciBzaXplRnJvbURpbWVuc2lvbiBhcyBUZW5zb3IgaGFzICR7ZGltcy5sZW5ndGh9IGRpbWVuc2lvbnMuYCk7XG4gICAgfVxuICAgIHJldHVybiBTaGFwZVV0aWwuZ2V0U2l6ZUZyb21EaW1lbnNpb25SYW5nZShkaW1zLCBheGlzLCBkaW1zLmxlbmd0aCk7XG4gIH1cblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBzaXplIChudW1iZXIgb2YgZWxlbWVudHMpIHRvIHRoZSBnaXZlbiBheGlzIChleGNsdXNpdmUpXG4gICAqL1xuICBzdGF0aWMgc2l6ZVRvRGltZW5zaW9uKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGlzOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmIChheGlzIDwgMCB8fCBheGlzID4gZGltcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkaW1lbnNpb24gb2YgJHtheGlzfSBmb3Igc2l6ZVRvRGltZW5zaW9uIGFzIFRlbnNvciBoYXMgJHtkaW1zLmxlbmd0aH0gZGltZW5zaW9ucy5gKTtcbiAgICB9XG4gICAgcmV0dXJuIFNoYXBlVXRpbC5nZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXMsIDAsIGF4aXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIGNhbGN1bGF0ZSB0aGUgc2l6ZSAobnVtYmVyIG9mIGVsZW1lbnRzKSBmcm9tIGFuZCB0byB0aGUgZ2l2ZW4gYXhpcyBbc3RhcnQsIGVuZClcbiAgICovXG4gIHN0YXRpYyBnZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBzdGFydDogbnVtYmVyLCBlbmQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgbGV0IHNpemUgPSAxO1xuICAgIGZvciAobGV0IGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAvLyBzYWZldHkgY2hlY2sgYXMgdGhpcyBtZXRob2QgaXMgY2FsbGVkIGJ5IG11bHRpcGxlIG90aGVyIG1ldGhvZHMgcmVxdWlyaW5nIHNpemUuXG4gICAgICAvLyBzaXplIGNhbm5vdCBiZSBuZWdhdGl2ZS5cbiAgICAgIGlmIChkaW1zW2ldIDwgMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICAgICAgICAnY2Fubm90IGdldCB2YWxpZCBzaXplIGZyb20gc3BlY2lmaWVkIGRpbWVuc2lvbiByYW5nZS4gTW9zdCBsaWtlbHkgdGhlIHJhbmdlIGNvbnRhaW5zIG5lZ2F0aXZlIHZhbHVlcyBpbiB0aGVtLicsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBzaXplICo9IE51bWJlcihkaW1zW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIHNpemU7XG4gIH1cblxuICBzdGF0aWMgY29tcHV0ZVN0cmlkZXMoZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgY29uc3QgcmFuayA9IGRpbXMubGVuZ3RoO1xuICAgIGlmIChyYW5rID09PSAwKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfSBlbHNlIGlmIChyYW5rID09PSAxKSB7XG4gICAgICByZXR1cm4gWzFdO1xuICAgIH1cbiAgICBjb25zdCBzdHJpZGVzID0gbmV3IEFycmF5KHJhbmspO1xuICAgIHN0cmlkZXNbcmFuayAtIDFdID0gMTtcbiAgICBzdHJpZGVzW3JhbmsgLSAyXSA9IGRpbXNbcmFuayAtIDFdO1xuICAgIGZvciAobGV0IGkgPSByYW5rIC0gMzsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHN0cmlkZXNbaV0gPSBzdHJpZGVzW2kgKyAxXSAqIGRpbXNbaSArIDFdO1xuICAgIH1cbiAgICByZXR1cm4gc3RyaWRlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBub3JtYWlsemUgYXhpcyBvZiByYW5nZSBbLXIsIHIpIGludG8gWzAsIHIpLlxuICAgKi9cbiAgc3RhdGljIG5vcm1hbGl6ZUF4aXMoYXhpczogbnVtYmVyLCB0ZW5zb3JSYW5rOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmIChheGlzIDwgLXRlbnNvclJhbmsgJiYgYXhpcyA+PSB0ZW5zb3JSYW5rKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vuc3VwcG9ydGVkIGF4aXMgZm9yIHRoaXMgb3BlcmF0aW9uLicpO1xuICAgIH1cbiAgICByZXR1cm4gYXhpcyA8IDAgPyBheGlzICsgdGVuc29yUmFuayA6IGF4aXM7XG4gIH1cblxuICBzdGF0aWMgbm9ybWFsaXplQXhlcyhheGVzOiByZWFkb25seSBudW1iZXJbXSwgdGVuc29yUmFuaz86IG51bWJlcik6IG51bWJlcltdIHtcbiAgICByZXR1cm4gYXhlcy5tYXAoKHgpID0+IHRoaXMubm9ybWFsaXplQXhpcyh4LCB0ZW5zb3JSYW5rID8/IGF4ZXMubGVuZ3RoKSk7XG4gIH1cblxuICAvKipcbiAgICogU29ydHMgYSBnaXZlbiBhcnJheSBiYXNlZCBvbiB0aGUgaW5kaWNlcyBpbiB0aGUgUGVybSBhcnJheVxuICAgKiBVc2VkIGluIFRyYW5zcG9zZVxuICAgKiBAcGFyYW0gYSBBcnJheSB0byBiZSBzb3J0ZWQgc3VjaCBhcyBkaW1zIG9yIHN0cmlkZXNcbiAgICogQHBhcmFtIHBlcm0gUGVybSBnaXZlbjsgaWYgbnVsbCBhIHdpbGwgYmUgcmV2ZXJzZWRcbiAgICovXG4gIHN0YXRpYyBzb3J0QmFzZWRPblBlcm0oYTogcmVhZG9ubHkgbnVtYmVyW10sIHBlcm0/OiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBpZiAocGVybSkge1xuICAgICAgcmV0dXJuIHBlcm0ubWFwKCh2KSA9PiBhW3ZdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGEuc2xpY2UoKS5yZXZlcnNlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhZHMgYSBnaXZlbiBzaGFwZSBhY2NvcmRpbmcgdG8gdGhlIHBhZGRpbmcgdmFsdWVzXG4gICAqIEBwYXJhbSBkaW1zIHNoYXBlIG9mIHRoZSBUZW5zb3IgdG8gYmUgcGFkZGVkXG4gICAqIEBwYXJhbSBwYWQgcGFkIHZhbHVlc1xuICAgKi9cbiAgc3RhdGljIHBhZFNoYXBlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBwYWQ6IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGNvbnN0IHJhbmsgPSBkaW1zLmxlbmd0aDtcbiAgICByZXR1cm4gZGltcy5tYXAoKHYsIGkpID0+IHYgKyBwYWRbaV0gKyBwYWRbaSArIHJhbmtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIGlmIHRoZSB0d28gc2hhcGVzIGFyZSBpZGVudGljYWxcbiAgICogQHBhcmFtIHNoYXBlMVxuICAgKiBAcGFyYW0gc2hhcGUyXG4gICAqL1xuICBzdGF0aWMgYXJlRXF1YWwoc2hhcGUxOiByZWFkb25seSBudW1iZXJbXSwgc2hhcGUyOiByZWFkb25seSBudW1iZXJbXSk6IGJvb2xlYW4ge1xuICAgIGlmIChzaGFwZTEubGVuZ3RoICE9PSBzaGFwZTIubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBzaGFwZTEuZXZlcnkoKHYsIGkpID0+IHYgPT09IHNoYXBlMltpXSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFBvb2xDb252VXRpbCB7XG4gIC8qKlxuICAgKiBBZGp1c3QgdGhlIGtlcm5lbCwgc3RyaWRlcywgcGFkcyB0byBjb3JyZWN0IHJhbmsuIFNldCB0byBkZWZhdWx0IHZhbHVlIGlmIG5vdCBwcmVzZW50XG4gICAqIEBwYXJhbSBpc0dsb2JhbE9wZXJhdG9yIElmIHRydWUsIHBlcmZvcm0gZ2xvYmFsIHBvb2xpbmcuXG4gICAqIEBwYXJhbSBpbnB1dERpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb24uXG4gICAqIEBwYXJhbSBrZXJuZWxTaGFwZSBUaGUgc2l6ZSBvZiB0aGUga2VybmVsIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHN0cmlkZXMgU3RyaWRlIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGRpbGF0aW9ucyBEaWxhdGlvbiBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBwYWRzIFBhZGRpbmcgZm9yIHRoZSBiZWdpbm5pbmcgYW5kIGVuZGluZyBhbG9uZyBlYWNoIGF4aXMuXG4gICAqL1xuICBzdGF0aWMgYWRqdXN0UG9vbEF0dHJpYnV0ZXMoXG4gICAgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbixcbiAgICBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGtlcm5lbFNoYXBlOiBudW1iZXJbXSxcbiAgICBzdHJpZGVzOiBudW1iZXJbXSxcbiAgICBkaWxhdGlvbnM6IG51bWJlcltdLFxuICAgIHBhZHM6IG51bWJlcltdLFxuICApOiB2b2lkIHtcbiAgICBpZiAoIWlzR2xvYmFsT3BlcmF0b3IgJiYga2VybmVsU2hhcGUubGVuZ3RoICE9PSBpbnB1dERpbXMubGVuZ3RoIC0gMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2Ygc3BlY2lmaWVkIGtlcm5lbCBzaGFwZXMgc2hvdWxkIGJlIDIgbGVzcyB0aGFuIGxlbmd0aCBvZiBpbnB1dCBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKGlzR2xvYmFsT3BlcmF0b3IpIHtcbiAgICAgIC8vIGFkanVzdCBrZXJuZWwgc2hhcGUgdG8gY292ZXIgdGhlIGlucHV0IGRpbXNcbiAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGlucHV0RGltcy5sZW5ndGggLSAyOyBkaW0rKykge1xuICAgICAgICBpZiAoZGltID49IGtlcm5lbFNoYXBlLmxlbmd0aCkge1xuICAgICAgICAgIGtlcm5lbFNoYXBlLnB1c2goaW5wdXREaW1zW2RpbSArIDJdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBrZXJuZWxTaGFwZVtkaW1dID0gaW5wdXREaW1zW2RpbSArIDJdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gYWRqdXN0IHN0cmlkZXMgbGVuZ3RoIHRvIG1hdGNoIGtlcm5lbCBzaGFwZSBsZW5ndGhcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgc3RyaWRlcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHN0cmlkZXNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0cmlkZXMgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0cmlkZXMucHVzaCgxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhZGp1c3QgZGlsYXRpb24gdmFsdWVcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgZGlsYXRpb25zLmxlbmd0aCkge1xuICAgICAgICBpZiAoZGlsYXRpb25zW2RpbV0gPCAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkaWxhdGlvbnMgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRpbGF0aW9ucy5wdXNoKDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkanVzdCBwYWRzIGxlbmd0aCB0byBtYXRjaCAyICoga2VybmVsIHNoYXBlIGxlbmd0aFxuICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGtlcm5lbFNoYXBlLmxlbmd0aCAqIDI7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgcGFkcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHBhZHNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhZCBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFkcy5wdXNoKDApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNhbml0eSBjaGVja3MgZm9yIHZhbHVlcyBpbiBrZXJuZWwgc2hhcGVzIGFuZCBwYWRzXG4gICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwga2VybmVsU2hhcGUubGVuZ3RoOyBkaW0rKykge1xuICAgICAgaWYgKGtlcm5lbFNoYXBlW2RpbV0gPD0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2tlcm5lbCBzaGFwZXMgbmVlZCB0byBiZSBncmVhdGVyIHRoYW4gMCcpO1xuICAgICAgfVxuXG4gICAgICBpZiAocGFkc1tkaW1dID49IGtlcm5lbFNoYXBlW2RpbV0gfHwgcGFkc1tkaW0gKyBrZXJuZWxTaGFwZS5sZW5ndGhdID49IGtlcm5lbFNoYXBlW2RpbV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwYWRzIHNob3VsZCBiZSBzbWFsbGVyIHRoYW4ga2VybmVsJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gYWRqdXN0IHBhZCB2YWx1ZXMgYmFzZWQgb24gJ2F1dG9QYWQnIGF0dHJpYnV0ZVxuICBzdGF0aWMgYWRqdXN0UGFkc0Jhc2VkT25BdXRvUGFkKFxuICAgIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgcGFkczogbnVtYmVyW10sXG4gICAgaXNDaGFubmVsTGFzdDogYm9vbGVhbixcbiAgICBhdXRvUGFkPzogc3RyaW5nLFxuICApOiB2b2lkIHtcbiAgICBpZiAoIWF1dG9QYWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAocGFkcy5sZW5ndGggIT09IDIgKiAoaW5wdXREaW1zLmxlbmd0aCAtIDIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2xlbmd0aCBvZiBwYWRzIHNob3VsZCBiZSB0d2ljZSB0aGUgbGVuZ3RoIG9mIGRhdGEgZGltZW5zaW9ucycpO1xuICAgIH1cblxuICAgIGlmIChzdHJpZGVzLmxlbmd0aCAhPT0gaW5wdXREaW1zLmxlbmd0aCAtIDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbGVuZ3RoIG9mIHN0cmlkZXMgc2hvdWxkIGJlIHRoZSBsZW5ndGggb2YgZGF0YSBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKGtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gaW5wdXREaW1zLmxlbmd0aCAtIDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbGVuZ3RoIG9mIGtlcm5lbCBzaGFwZXMgc2hvdWxkIGJlIHRoZSBsZW5ndGggb2YgZGF0YSBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwgaW5wdXREaW1zLmxlbmd0aCAtIDI7IGRpbSsrKSB7XG4gICAgICBQb29sQ29udlV0aWwuYWRqdXN0UGFkQW5kUmV0dXJuU2hhcGUoXG4gICAgICAgIGlucHV0RGltc1tkaW0gKyAoaXNDaGFubmVsTGFzdCA/IDEgOiAyKV0sXG4gICAgICAgIHN0cmlkZXNbZGltXSxcbiAgICAgICAgZGlsYXRpb25zW2RpbV0sXG4gICAgICAgIGtlcm5lbFNoYXBlW2RpbV0sXG4gICAgICAgIHBhZHMsXG4gICAgICAgIGRpbSxcbiAgICAgICAgZGltICsgaW5wdXREaW1zLmxlbmd0aCAtIDIsXG4gICAgICAgIGF1dG9QYWQsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIG91dHB1dCBzaGFwZSBmb3IgUG9vbCBvcHMgYmFzZWQgb24gaW5wdXQgYXR0cmlidXRlcy4gKFNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIFBvb2wgb3BzKVxuICAgKiBAcGFyYW0gaXNHbG9iYWxPcGVyYXRvciBJZiB0cnVlLCBwZXJmb3JtIGdsb2JhbCBwb29saW5nLlxuICAgKiBAcGFyYW0gaW5wdXREaW1zIFRoZSBpbnB1dCB0ZW5zb3IgZGltZW5zaW9uLiAoaW5wdXRzWzBdLmRpbXMpXG4gICAqIEBwYXJhbSBzdHJpZGVzIFN0cmlkZSBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBkaWxhdGlvbnMgRGlsYXRpb24gYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0ga2VybmVsU2hhcGUgVGhlIHNpemUgb2YgdGhlIGtlcm5lbCBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBwYWRzIFBhZGRpbmcgZm9yIHRoZSBiZWdpbm5pbmcgYW5kIGVuZGluZyBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBhdXRvUGFkIERFUFJFQ0FURUQgYXR0cmlidXRlIHN1cHBvcnRlZCBmb3IgbGVnYWN5IG1vZGVscy4gU3BlY2lmaWVzIGhvdyB0byBpbXBsaWNpdGx5IGNhbGN1bGF0ZSBwYWRzIGluIGVhY2hcbiAgICogICAgIGRpbWVuc2lvbi4gQ2FuIHRha2UgdmFsdWVzIE5PVFNFVCwgU0FNRV9VUFBFUiwgU0FNRV9MT1dFUiwgb3IgVkFMSUQuXG4gICAqL1xuICBzdGF0aWMgY29tcHV0ZVBvb2xPdXRwdXRTaGFwZShcbiAgICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLFxuICAgIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgc3RyaWRlczogbnVtYmVyW10sXG4gICAgZGlsYXRpb25zOiBudW1iZXJbXSxcbiAgICBrZXJuZWxTaGFwZTogbnVtYmVyW10sXG4gICAgcGFkczogbnVtYmVyW10sXG4gICAgYXV0b1BhZD86IHN0cmluZyxcbiAgKTogbnVtYmVyW10ge1xuICAgIGlmIChpbnB1dERpbXMubGVuZ3RoIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgc2hhcGUgbXVzdCBiZSBvZiBzaXplIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgLy8gQWRkIGJhdGNoIHNpemUgYW5kIG51bWJlciBvZiBjaGFubmVscyBvZiBvdXRwdXRcbiAgICBjb25zdCBvdXRwdXREaW1zID0gW2lucHV0RGltc1swXSwgaW5wdXREaW1zWzFdXTtcblxuICAgIFBvb2xDb252VXRpbC5jb21wdXRlU2hhcGVIZWxwZXIoXG4gICAgICBpc0dsb2JhbE9wZXJhdG9yLFxuICAgICAgaW5wdXREaW1zLFxuICAgICAgb3V0cHV0RGltcyxcbiAgICAgIHN0cmlkZXMsXG4gICAgICBkaWxhdGlvbnMsXG4gICAgICBrZXJuZWxTaGFwZSxcbiAgICAgIHBhZHMsXG4gICAgICBhdXRvUGFkLFxuICAgICk7XG4gICAgcmV0dXJuIG91dHB1dERpbXM7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBvdXRwdXQgc2hhcGUgZm9yIENvbnYgb3AgYmFzZWQgb24gaW5wdXQgYXR0cmlidXRlcy4gKFNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIENvbnYgb3ApXG4gICAqIEBwYXJhbSBpbnB1dERpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb24uIChpbnB1dHNbMF0uZGltcylcbiAgICogQHBhcmFtIGZpbHRlckRpbXMgVGhlIGZpbHRlciB0ZW5zb3IgZGltZW5zaW9uLiAoaW5wdXRzWzFdLmRpbXMpXG4gICAqIEBwYXJhbSBzdHJpZGVzIFN0cmlkZSBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBrZXJuZWxTaGFwZSBUaGUgc2l6ZSBvZiB0aGUga2VybmVsIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHBhZHMgUGFkZGluZyBmb3IgdGhlIGJlZ2lubmluZyBhbmQgZW5kaW5nIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGF1dG9QYWQgREVQUkVDQVRFRCBhdHRyaWJ1dGUgc3VwcG9ydGVkIGZvciBsZWdhY3kgbW9kZWxzLiBTcGVjaWZpZXMgaG93IHRvIGltcGxpY2l0bHkgY2FsY3VsYXRlIHBhZHMgaW4gZWFjaFxuICAgKiAgICAgZGltZW5zaW9uLiBDYW4gdGFrZSB2YWx1ZXMgTk9UU0VULCBTQU1FX1VQUEVSLCBTQU1FX0xPV0VSLCBvciBWQUxJRC5cbiAgICovXG4gIHN0YXRpYyBjb21wdXRlQ29udk91dHB1dFNoYXBlKFxuICAgIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgZmlsdGVyRGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgc3RyaWRlczogbnVtYmVyW10sXG4gICAgZGlsYXRpb25zOiBudW1iZXJbXSxcbiAgICBrZXJuZWxTaGFwZTogbnVtYmVyW10sXG4gICAgcGFkczogbnVtYmVyW10sXG4gICAgYXV0b1BhZD86IHN0cmluZyxcbiAgKTogbnVtYmVyW10ge1xuICAgIGlmIChpbnB1dERpbXMubGVuZ3RoIDw9IDAgfHwgZmlsdGVyRGltcy5sZW5ndGggPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGlucHV0IHRlbnNvciBkaW1zIG9yIGludmFsaWQgZmlsdGVyIHRlbnNvciBkaW1zJyk7XG4gICAgfVxuXG4gICAgLy8gQWRkIGJhdGNoIHNpemUgYW5kIG51bWJlciBvZiBjaGFubmVscyBvZiBvdXRwdXRcbiAgICBjb25zdCBvdXRwdXREaW1zID0gW2lucHV0RGltc1swXSwgZmlsdGVyRGltc1swXV07XG5cbiAgICBQb29sQ29udlV0aWwuY29tcHV0ZVNoYXBlSGVscGVyKGZhbHNlLCBpbnB1dERpbXMsIG91dHB1dERpbXMsIHN0cmlkZXMsIGRpbGF0aW9ucywga2VybmVsU2hhcGUsIHBhZHMsIGF1dG9QYWQpO1xuICAgIHJldHVybiBvdXRwdXREaW1zO1xuICB9XG5cbiAgLy8gd2lsbCBjb21wdXRlIG91dHB1dCBzaGFwZXMgZm9yIGRhdGEgZGltZW5zaW9ucyBPTkxZIChpLmUuKSBubyBiYXRjaCBzaXplIGFuZCBjaGFubmVsc1xuICAvLyBjYWxsZWQgYnkgY29tcHV0ZVBvb2xPdXRwdXRTaGFwZSgpIGFuZCBjb21wdXRlQ29udk91dHB1dFNoYXBlKClcbiAgLy8gYWRqdXN0IHBhZHMgYmFzZWQgb24gJ2F1dG9QYWQnIGF0dHJpYnV0ZSBwcmlvciB0byBzaGFwZSBjb21wdXRhdGlvblxuICBwcml2YXRlIHN0YXRpYyBjb21wdXRlU2hhcGVIZWxwZXIoXG4gICAgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbixcbiAgICBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIG91dHB1dERpbXM6IG51bWJlcltdLFxuICAgIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIHBhZHM6IG51bWJlcltdLFxuICAgIGF1dG9QYWQ/OiBzdHJpbmcsXG4gICkge1xuICAgIGlmIChpc0dsb2JhbE9wZXJhdG9yKSB7XG4gICAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBpbnB1dERpbXMubGVuZ3RoIC0gMjsgZGltKyspIHtcbiAgICAgICAgb3V0cHV0RGltcy5wdXNoKDEpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBpbnB1dERpbXMubGVuZ3RoIC0gMjsgZGltKyspIHtcbiAgICAgICAgb3V0cHV0RGltcy5wdXNoKFxuICAgICAgICAgIFBvb2xDb252VXRpbC5hZGp1c3RQYWRBbmRSZXR1cm5TaGFwZShcbiAgICAgICAgICAgIGlucHV0RGltc1tkaW0gKyAyXSxcbiAgICAgICAgICAgIHN0cmlkZXNbZGltXSxcbiAgICAgICAgICAgIGRpbGF0aW9uc1tkaW1dLFxuICAgICAgICAgICAga2VybmVsU2hhcGVbZGltXSxcbiAgICAgICAgICAgIHBhZHMsXG4gICAgICAgICAgICBkaW0sXG4gICAgICAgICAgICBkaW0gKyBpbnB1dERpbXMubGVuZ3RoIC0gMixcbiAgICAgICAgICAgIGF1dG9QYWQsXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBoZWxwZXIgZm9yIGNvbXB1dGVTaGFwZUhlbHBlcigpIGFuZCBhZGp1c3RQYWRzQmFzZWRPbkF1dG9QYWQoKVxuICAvLyBhZGp1c3RzIHBhZCB2YWx1ZSBmb3IgZ2l2ZW4gJ2F1dG9QYWQnIHN0cmluZyBhbmQgY29tcHV0ZXMgb3V0cHV0IHNoYXBlIGFsb25nIGEgcGFydGljdWxhciBkaW1lbnNpb25cbiAgcHJpdmF0ZSBzdGF0aWMgYWRqdXN0UGFkQW5kUmV0dXJuU2hhcGUoXG4gICAgaW5TaXplOiBudW1iZXIsXG4gICAgc3RyaWRlOiBudW1iZXIsXG4gICAgZGlsYXRpb246IG51bWJlcixcbiAgICBrZXJuZWw6IG51bWJlcixcbiAgICBwYWRzOiBudW1iZXJbXSxcbiAgICBwYWRIZWFkSW5kZXg6IG51bWJlcixcbiAgICBwYWRUYWlsSW5kZXg6IG51bWJlcixcbiAgICBhdXRvUGFkPzogc3RyaW5nLFxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IGRrZXJuZWwgPSBkaWxhdGlvbiAqIChrZXJuZWwgLSAxKSArIDE7XG4gICAgaWYgKGF1dG9QYWQgJiYgYXV0b1BhZCAhPT0gJ05PVFNFVCcpIHtcbiAgICAgIHN3aXRjaCAoYXV0b1BhZCkge1xuICAgICAgICBjYXNlICdWQUxJRCc6XG4gICAgICAgICAgcGFkc1twYWRIZWFkSW5kZXhdID0gMDtcbiAgICAgICAgICBwYWRzW3BhZFRhaWxJbmRleF0gPSAwO1xuICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKChpblNpemUgLSBka2VybmVsKSAvIHN0cmlkZSArIDEpO1xuICAgICAgICBjYXNlICdTQU1FX0xPV0VSJzpcbiAgICAgICAgY2FzZSAnU0FNRV9VUFBFUic6XG4gICAgICAgICAgaWYgKGRpbGF0aW9uICE9PSAxKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RpbGF0aW9uIG5vdCBzdXBwb3J0ZWQgZm9yIFNBTUVfVVBQRVIgb3IgU0FNRV9MT1dFUicpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBsZWdhY3lUYXJnZXRTaXplID0gKGluU2l6ZSArIHN0cmlkZSAtIDEpIC8gc3RyaWRlO1xuICAgICAgICAgICAgY29uc3QgcGFkTmVlZGVkID0gKGxlZ2FjeVRhcmdldFNpemUgLSAxKSAqIHN0cmlkZSArIGtlcm5lbCAtIGluU2l6ZTtcbiAgICAgICAgICAgIHBhZHNbcGFkSGVhZEluZGV4XSA9IGF1dG9QYWQgPT09ICdTQU1FX0xPV0VSJyA/IE1hdGguZmxvb3IoKHBhZE5lZWRlZCArIDEpIC8gMikgOiBNYXRoLmZsb29yKHBhZE5lZWRlZCAvIDIpO1xuICAgICAgICAgICAgcGFkc1twYWRUYWlsSW5kZXhdID0gcGFkTmVlZGVkIC0gcGFkc1twYWRIZWFkSW5kZXhdO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGluU2l6ZSArIHBhZE5lZWRlZCAtIGtlcm5lbCkgLyBzdHJpZGUgKyAxKTtcbiAgICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBBdXRvUGFkIHR5cGUnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGluU2l6ZSArIHBhZHNbcGFkSGVhZEluZGV4XSArIHBhZHNbcGFkVGFpbEluZGV4XSAtIGRrZXJuZWwpIC8gc3RyaWRlICsgMSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBHZW1tVXRpbCB7XG4gIC8vIHdpbGwgbWFrZSBzdXJlIGlucHV0IHNoYXBlcyBhcmUgY29tcGF0aWJsZSBmb3IgdGhpcyBvcFxuICAvLyBhbmQgcmV0dXJuIGJhY2sgdGhlIHNoYXBlIG9mIHRoZSBvdXRwdXQgaW4gdGhlIGZvcm0gb2YgYSB0dXBsZVxuICAvLyB3aWxsIHRocm93IGV4Y2VwdGlvbiBpZiB0aGUgaW5wdXQgc2hhcGVzIGFyZSBub3QgY29tcGF0aWJsZVxuICBzdGF0aWMgZ2V0U2hhcGVPZkdlbW1SZXN1bHQoXG4gICAgbGVmdFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgICB0cmFuc0xlZnQ6IGJvb2xlYW4sXG4gICAgcmlnaHRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgdHJhbnNSaWdodDogYm9vbGVhbixcbiAgICBiaWFzU2hhcGU/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGlmIChsZWZ0U2hhcGUubGVuZ3RoICE9PSAyIHx8IHJpZ2h0U2hhcGUubGVuZ3RoICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NoYXBlIG5lZWQgdG8gYmUgb2Ygc2l6ZSAyJyk7XG4gICAgfVxuXG4gICAgbGV0IE06IG51bWJlcjtcbiAgICBsZXQgSzogbnVtYmVyO1xuICAgIGxldCBOOiBudW1iZXI7XG5cbiAgICBpZiAodHJhbnNMZWZ0KSB7XG4gICAgICBNID0gbGVmdFNoYXBlWzFdO1xuICAgICAgSyA9IGxlZnRTaGFwZVswXTtcbiAgICB9IGVsc2Uge1xuICAgICAgTSA9IGxlZnRTaGFwZVswXTtcbiAgICAgIEsgPSBsZWZ0U2hhcGVbMV07XG4gICAgfVxuXG4gICAgbGV0IGtEaW0gPSAtMTtcblxuICAgIGlmICh0cmFuc1JpZ2h0KSB7XG4gICAgICBOID0gcmlnaHRTaGFwZVswXTtcbiAgICAgIGtEaW0gPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICBOID0gcmlnaHRTaGFwZVsxXTtcbiAgICAgIGtEaW0gPSAwO1xuICAgIH1cblxuICAgIGlmIChyaWdodFNoYXBlW2tEaW1dICE9PSBLKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RpbWVuc2lvbiBtaXNtYXRjaCcpO1xuICAgIH1cblxuICAgIGlmIChNIDw9IDAgfHwgTiA8PSAwIHx8IEsgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNoYXBlIHNwZWNpZmllZCcpO1xuICAgIH1cblxuICAgIGlmIChiaWFzU2hhcGUgJiYgIUJyb2FkY2FzdFV0aWwuaXNWYWxpZEJyb2FkY2FzdChiaWFzU2hhcGUsIFtNLCBOXSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2VtbTogaW52YWxpZCBiaWFzIHNoYXBlIGZvciBicm9hZGNhc3QnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW00sIE4sIEtdO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBNSU5fQ0xJUCA9IC0zLjQwMjgyMzQ2NjM4NTI4ODZlMzg7XG5leHBvcnQgY29uc3QgTUFYX0NMSVAgPSAzLjQwMjgyMzQ2NjM4NTI4ODZlMzg7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3RvciB9IGZyb20gJy4uL3dhc20tY29tbW9uJztcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVZpZXcgPSAoXG4gIGRhdGFCdWZmZXI6IEFycmF5QnVmZmVyLFxuICB0eXBlOiBUZW5zb3IuVHlwZSxcbik6XG4gIHwgSW50MzJBcnJheVxuICB8IFVpbnQzMkFycmF5XG4gIHwgQmlnSW50NjRBcnJheVxuICB8IEJpZ1VpbnQ2NEFycmF5XG4gIHwgVWludDhBcnJheVxuICB8IEZsb2F0MzJBcnJheVxuICB8IEZsb2F0NjRBcnJheVxuICB8IEludDhBcnJheVxuICB8IEludDE2QXJyYXlcbiAgfCBVaW50MTZBcnJheSA9PiBuZXcgKHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3Rvcih0eXBlKSkoZGF0YUJ1ZmZlcik7XG5cbi8qKlxuICogYSBUZW5zb3JWaWV3IGRvZXMgbm90IG93biB0aGUgZGF0YS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JWaWV3IHtcbiAgcmVhZG9ubHkgZGF0YTogbnVtYmVyO1xuICByZWFkb25seSBkYXRhVHlwZTogbnVtYmVyO1xuICByZWFkb25seSBkaW1zOiByZWFkb25seSBudW1iZXJbXTtcblxuICAvKipcbiAgICogZ2V0IGEgRmxvYXQxNkFycmF5IGRhdGEgdmlldyBvZiB0aGUgdGVuc29yIGRhdGEuIHRlbnNvciBkYXRhIG11c3QgYmUgb24gQ1BVLlxuICAgKi9cbiAgZ2V0VWludDE2QXJyYXkoKTogVWludDE2QXJyYXk7XG5cbiAgLyoqXG4gICAqIGdldCBhIEZsb2F0MzJBcnJheSBkYXRhIHZpZXcgb2YgdGhlIHRlbnNvciBkYXRhLiB0ZW5zb3IgZGF0YSBtdXN0IGJlIG9uIENQVS5cbiAgICovXG4gIGdldEZsb2F0MzJBcnJheSgpOiBGbG9hdDMyQXJyYXk7XG5cbiAgLyoqXG4gICAqIGdldCBhIEJpZ0ludDY0QXJyYXkgZGF0YSB2aWV3IG9mIHRoZSB0ZW5zb3IgZGF0YS4gdGVuc29yIGRhdGEgbXVzdCBiZSBvbiBDUFUuXG4gICAqL1xuICBnZXRCaWdJbnQ2NEFycmF5KCk6IEJpZ0ludDY0QXJyYXk7XG5cbiAgLyoqXG4gICAqIGdldCBhIEludDMyQXJyYXkgZGF0YSB2aWV3IG9mIHRoZSB0ZW5zb3IgZGF0YS4gdGVuc29yIGRhdGEgbXVzdCBiZSBvbiBDUFUuXG4gICAqL1xuICBnZXRJbnQzMkFycmF5KCk6IEludDMyQXJyYXk7XG5cbiAgLyoqXG4gICAqIGdldCBhIFVpbnQxNkFycmF5IGRhdGEgdmlldyBvZiB0aGUgdGVuc29yIGRhdGEuIHRlbnNvciBkYXRhIG11c3QgYmUgb24gQ1BVLlxuICAgKi9cbiAgZ2V0VWludDE2QXJyYXkoKTogVWludDE2QXJyYXk7XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhIG5ldyB0ZW5zb3IgdmlldyB3aXRoIHRoZSBzYW1lIGRhdGEgYnV0IGRpZmZlcmVudCBkaW1lbnNpb25zLlxuICAgKi9cbiAgcmVzaGFwZShuZXdEaW1zOiByZWFkb25seSBudW1iZXJbXSk6IFRlbnNvclZpZXc7XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFdlYk5OQmFja2VuZCB9IGZyb20gJy4uL2JhY2tlbmQtd2Vibm4nO1xuaW1wb3J0IHsgdGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yIH0gZnJvbSAnLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgTE9HX0RFQlVHIH0gZnJvbSAnLi4vbG9nJztcblxuLy8gV2ViTk4gQVBJIGN1cnJlbnRseSBkb2VzIG5vdCBoYXZlIGEgVHlwZVNjcmlwdCBkZWZpbml0aW9uIGZpbGUuIFRoaXMgZmlsZSBpcyBhIHdvcmthcm91bmQgd2l0aCB0eXBlcyBnZW5lcmF0ZWQgZnJvbVxuLy8gV2ViTk4gQVBJIHNwZWNpZmljYXRpb24uXG4vLyBodHRwczovL2dpdGh1Yi5jb20vd2VibWFjaGluZWxlYXJuaW5nL3dlYm5uL2lzc3Vlcy82Nzdcbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJ3ZWJubi5kLnRzXCIgLz5cblxuLyoqXG4gKiBNYXAgZnJvbSBNTE9wZXJhbmREYXRhVHlwZSB0byBzaXplIGluIGJpdHMuIFVzaW5nIGJpdHMgaW5zdGVhZCBvZiBieXRlcyB0byBhdm9pZCBwb3NzaWJsZSBwcmVjaXNpb24gbG9zcyBvbiBpbnQ0IGFuZCB1aW50NC5cbiAqL1xuY29uc3Qgd2Vibm5EYXRhVHlwZVRvU2l6ZSA9IG5ldyBNYXA8TUxPcGVyYW5kRGF0YVR5cGUsIG51bWJlcj4oW1xuICBbJ2Zsb2F0MzInLCAzMl0sXG4gIFsnZmxvYXQxNicsIDE2XSxcbiAgWydpbnQzMicsIDMyXSxcbiAgWyd1aW50MzInLCAzMl0sXG4gIFsnaW50NjQnLCA2NF0sXG4gIFsndWludDY0JywgNjRdLFxuICBbJ2ludDgnLCA4XSxcbiAgWyd1aW50OCcsIDhdLFxuICBbJ2ludDQnLCA0XSxcbiAgWyd1aW50NCcsIDRdLFxuXSk7XG5cbi8vIENvbnZlcnQgaW50ZWdlciBkYXRhIHRvIGFuIEludDMyQXJyYXkgYnVmZmVyLlxuLy8gU3VwcG9ydHMgY29udmVyc2lvbiBmcm9tIGludDY0LCB1aW50NjQsIHVpbnQzMiwgaW50OCBhbmQgdWludDggdG8gaW50MzIuXG5leHBvcnQgY29uc3QgY29udmVydERhdGFUb0ludDMyID0gKGRhdGE6IFVpbnQ4QXJyYXksIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSk6IFVpbnQ4QXJyYXkgPT4ge1xuICBpZiAoZGF0YVR5cGUgPT09ICdpbnQzMicpIHtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIGNvbnN0IGRhdGFUeXBlU2l6ZSA9IHdlYm5uRGF0YVR5cGVUb1NpemUuZ2V0KGRhdGFUeXBlKTtcbiAgaWYgKCFkYXRhVHlwZVNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFdlYk5OIGJhY2tlbmQgZG9lcyBub3Qgc3VwcG9ydCBkYXRhIHR5cGU6ICR7ZGF0YVR5cGV9YCk7XG4gIH1cbiAgY29uc3QgYnl0ZXNQZXJFbGVtZW50ID0gZGF0YVR5cGVTaXplIC8gODtcbiAgLy8gTWFrZSBzdXJlIHRoZSBkYXRhIGxlbmd0aCBpcyBhIG11bHRpcGxlIG9mIHRoZSBkYXRhIHR5cGUgc2l6ZS5cbiAgaWYgKGRhdGEuYnl0ZUxlbmd0aCAlIGJ5dGVzUGVyRWxlbWVudCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBVaW50OEFycmF5IGxlbmd0aCAtIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAke2J5dGVzUGVyRWxlbWVudH0uYCk7XG4gIH1cblxuICAvLyBDb252ZXJ0IFVpbnQ4QXJyYXkgdG8gb3JpZ2luYWwgdHlwZWQgYXJyYXkuXG4gIGNvbnN0IG51bUVsZW1lbnRzID0gZGF0YS5ieXRlTGVuZ3RoIC8gYnl0ZXNQZXJFbGVtZW50O1xuICBjb25zdCBvcmlnaW5hbEFycmF5ID0gbmV3ICh0ZW5zb3JUeXBlVG9UeXBlZEFycmF5Q29uc3RydWN0b3IoZGF0YVR5cGUpKShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBudW1FbGVtZW50cyk7XG5cbiAgc3dpdGNoIChkYXRhVHlwZSkge1xuICAgIGNhc2UgJ2ludDY0JzpcbiAgICBjYXNlICd1aW50NjQnOiB7XG4gICAgICAvLyBDb252ZXJ0IG9yaWdpbmFsIHR5cGVkIGFycmF5IHRvIEludDMyQXJyYXkuXG4gICAgICBjb25zdCBpbnQzMkFycmF5ID0gbmV3IEludDMyQXJyYXkobnVtRWxlbWVudHMpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1FbGVtZW50czsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gb3JpZ2luYWxBcnJheVtpXTtcblxuICAgICAgICAvLyBDaGVjayBmb3Igb3ZlcmZsb3cuXG4gICAgICAgIGlmICh2YWx1ZSA+IDIxNDc0ODM2NDduIHx8IHZhbHVlIDwgLTIxNDc0ODM2NDhuKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4gbm90IGNvbnZlcnQgaW50NjQgZGF0YSB0byBpbnQzMiAtIHZhbHVlIG91dCBvZiByYW5nZS5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGludDMyQXJyYXlbaV0gPSBOdW1iZXIodmFsdWUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoaW50MzJBcnJheS5idWZmZXIpO1xuICAgIH1cbiAgICBjYXNlICdpbnQ4JzpcbiAgICBjYXNlICd1aW50OCc6XG4gICAgY2FzZSAndWludDMyJzoge1xuICAgICAgLy8gQ2hlY2sgZm9yIG92ZXJmbG93LlxuICAgICAgaWYgKGRhdGFUeXBlID09PSAndWludDMyJykge1xuICAgICAgICBpZiAob3JpZ2luYWxBcnJheS5zb21lKCh2YWx1ZSkgPT4gdmFsdWUgPiAyMTQ3NDgzNjQ3KSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuIG5vdCBjb252ZXJ0IHVpbnQzMiBkYXRhIHRvIGludDMyIC0gdmFsdWUgb3V0IG9mIHJhbmdlLmApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBDb252ZXJ0IG9yaWdpbmFsIHR5cGVkIGFycmF5IHRvIEludDMyQXJyYXkuXG4gICAgICBjb25zdCBpbnQzMkFycmF5ID0gSW50MzJBcnJheS5mcm9tKG9yaWdpbmFsQXJyYXksIE51bWJlcik7XG4gICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoaW50MzJBcnJheS5idWZmZXIpO1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIGNvbnZlcnNpb24gZnJvbSAke2RhdGFUeXBlfSB0byAnaW50MzInYCk7XG4gIH1cbn07XG5cbi8vIENvbnZlcnQgSW50MzJBcnJheSBkYXRhIHRvIG9yaWdpbmFsIGludGVnZXIgZGF0YSBidWZmZXIuXG4vLyBTdXBwb3J0cyBjb252ZXJzaW9uIGZyb20gaW50MzIgdG8gaW50NjQsIHVpbnQ2NCwgdWludDMyLCBpbnQ4IGFuZCB1aW50OC5cbmV4cG9ydCBjb25zdCBjb252ZXJ0SW50MzJUb0RhdGEgPSAoZGF0YTogVWludDhBcnJheSwgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlKTogVWludDhBcnJheSA9PiB7XG4gIGlmIChkYXRhVHlwZSA9PT0gJ2ludDMyJykge1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgLy8gTWFrZSBzdXJlIHRoZSBkYXRhIGxlbmd0aCBpcyBhIG11bHRpcGxlIG9mIDQgYnl0ZXMgKEludDMyQXJyYXkpLlxuICBpZiAoZGF0YS5ieXRlTGVuZ3RoICUgNCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBVaW50OEFycmF5IGxlbmd0aCAtIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0IChpbnQzMikuJyk7XG4gIH1cblxuICAvLyBDb252ZXJ0IFVpbnQ4QXJyYXkgdG8gSW50MzJBcnJheS5cbiAgY29uc3QgbnVtRWxlbWVudHMgPSBkYXRhLmJ5dGVMZW5ndGggLyA0O1xuICBjb25zdCBpbnQzMkFycmF5ID0gbmV3IEludDMyQXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgbnVtRWxlbWVudHMpO1xuXG4gIHN3aXRjaCAoZGF0YVR5cGUpIHtcbiAgICBjYXNlICdpbnQ2NCc6IHtcbiAgICAgIGNvbnN0IGJpZ0ludDY0QXJyYXkgPSBCaWdJbnQ2NEFycmF5LmZyb20oaW50MzJBcnJheSwgQmlnSW50KTtcbiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShiaWdJbnQ2NEFycmF5LmJ1ZmZlcik7XG4gICAgfVxuICAgIGNhc2UgJ3VpbnQ2NCc6IHtcbiAgICAgIGlmIChpbnQzMkFycmF5LnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA8IDApKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBjb252ZXJ0IGludDMyIGRhdGEgdG8gdWluNjQgLSBuZWdhdGl2ZSB2YWx1ZSBmb3VuZC4nKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGJpZ1VpbnQ2NEFycmF5ID0gQmlnVWludDY0QXJyYXkuZnJvbShpbnQzMkFycmF5LCBCaWdJbnQpO1xuICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGJpZ1VpbnQ2NEFycmF5LmJ1ZmZlcik7XG4gICAgfVxuICAgIGNhc2UgJ2ludDgnOiB7XG4gICAgICBpZiAoaW50MzJBcnJheS5zb21lKCh2YWx1ZSkgPT4gdmFsdWUgPCAtMTI4IHx8IHZhbHVlID4gMTI3KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgY29udmVydCBpbnQzMiBkYXRhIHRvIGludDggLSB2YWx1ZSBvdXQgb2YgcmFuZ2UuJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBpbnQ4QXJyYXkgPSBJbnQ4QXJyYXkuZnJvbShpbnQzMkFycmF5LCBOdW1iZXIpO1xuICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGludDhBcnJheS5idWZmZXIpO1xuICAgIH1cbiAgICBjYXNlICd1aW50OCc6IHtcbiAgICAgIGlmIChpbnQzMkFycmF5LnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA8IDAgfHwgdmFsdWUgPiAyNTUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBjb252ZXJ0IGludDMyIGRhdGEgdG8gdWludDggLSB2YWx1ZSBvdXQgb2YgcmFuZ2UuJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gVWludDhBcnJheS5mcm9tKGludDMyQXJyYXksIE51bWJlcik7XG4gICAgfVxuICAgIGNhc2UgJ3VpbnQzMic6IHtcbiAgICAgIGlmIChpbnQzMkFycmF5LnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA8IDApKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBjb252ZXJ0IGludDMyIGRhdGEgdG8gdWludDMyIC0gbmVnYXRpdmUgdmFsdWUgZm91bmQuJyk7XG4gICAgICB9XG4gICAgICBjb25zdCB1aW50MzJBcnJheSA9IFVpbnQzMkFycmF5LmZyb20oaW50MzJBcnJheSwgTnVtYmVyKTtcbiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSh1aW50MzJBcnJheS5idWZmZXIpO1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIGNvbnZlcnNpb24gZnJvbSAnaW50MzInIHRvICR7ZGF0YVR5cGV9YCk7XG4gIH1cbn07XG5cbmV4cG9ydCB0eXBlIFRlbnNvcklkID0gbnVtYmVyO1xuXG4vKipcbiAqIE1hbmFnZXMgVGVuc29ySWQgdG8gTUxUZW5zb3IgbWFwcGluZy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JNYW5hZ2VyIHtcbiAgLyoqXG4gICAqIFJlc2VydmUgYSBuZXcgVGVuc29ySWQuXG4gICAqL1xuICByZXNlcnZlVGVuc29ySWQoKTogVGVuc29ySWQ7XG4gIC8qKlxuICAgKiBSZWxlYXNlIGEgVGVuc29ySWQuXG4gICAqL1xuICByZWxlYXNlVGVuc29ySWQodGVuc29ySWQ6IFRlbnNvcklkKTogdm9pZDtcbiAgLyoqXG4gICAqIEVuc3VyZSBhIE1MVGVuc29yIGlzIGNyZWF0ZWQgZm9yIHRoZSBUZW5zb3JJZC5cbiAgICovXG4gIGVuc3VyZVRlbnNvcihcbiAgICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgICB0ZW5zb3JJZDogVGVuc29ySWQsXG4gICAgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlLFxuICAgIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBjb3B5T2xkOiBib29sZWFuLFxuICApOiBQcm9taXNlPE1MVGVuc29yPjtcbiAgLyoqXG4gICAqIFVwbG9hZCBkYXRhIHRvIGEgTUxUZW5zb3IuXG4gICAqL1xuICB1cGxvYWQodGVuc29ySWQ6IFRlbnNvcklkLCBkYXRhOiBVaW50OEFycmF5KTogdm9pZDtcbiAgLyoqXG4gICAqIERvd25sb2FkIGRhdGEgZnJvbSBhIE1MVGVuc29yLlxuICAgKi9cbiAgZG93bmxvYWQodGVuc29ySWQ6IFRlbnNvcklkKTogUHJvbWlzZTxBcnJheUJ1ZmZlcj47XG4gIGRvd25sb2FkKHRlbnNvcklkOiBUZW5zb3JJZCwgZHN0VGVuc29yOiBBcnJheUJ1ZmZlclZpZXcgfCBBcnJheUJ1ZmZlcik6IFByb21pc2U8dW5kZWZpbmVkPjtcbiAgLyoqXG4gICAqIFJlbGVhc2UgYWxsIHRlbnNvcnMgZm9yIGEgZ2l2ZW4gc2Vzc2lvbi5cbiAgICovXG4gIHJlbGVhc2VUZW5zb3JzRm9yU2Vzc2lvbihzZXNzaW9uOiBudW1iZXIpOiB2b2lkO1xuICAvKipcbiAgICogUmVnaXN0ZXIgYW4gZXh0ZXJuYWxseSBjcmVhdGVkIE1MVGVuc29yIHdpdGggYSBnaXZlbiBzZXNzaW9uIGlkIGFuZCByZXR1cm4gYSBUZW5zb3JJZC5cbiAgICovXG4gIHJlZ2lzdGVyVGVuc29yKHNlc3Npb25JZDogbnVtYmVyLCBtbFRlbnNvcjogTUxUZW5zb3IsIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSwgc2hhcGU6IG51bWJlcltdKTogVGVuc29ySWQ7XG59XG5cbmxldCB0ZW5zb3JHdWlkID0gMTtcbmNvbnN0IGNyZWF0ZU5ld1RlbnNvcklkID0gKCk6IFRlbnNvcklkID0+IHRlbnNvckd1aWQrKztcblxuLyoqXG4gKiBNYXAgZnJvbSBkYXRhIHR5cGUgdG8gZmFsbGJhY2sgZGF0YSB0eXBlLlxuICogV2hlbiB0aGUgY29udGV4dCBkb2VzIG5vdCBzdXBwb3J0IHRoZSBvcmlnaW5hbCBkYXRhIHR5cGUsIHVzZSBmYWxsYmFjayBkYXRhIHR5cGUgYXMgd29ya2Fyb3VuZC5cbiAqIE5vdGU6IEN1cnJlbnRseSwgd2Ugb25seSBzdXBwb3J0IGZhbGxiYWNrIHRvIGludDMyIGZvciBjZXJ0YWluIGludGVnZXIgZGF0YSB0eXBlcy5cbiAqL1xuY29uc3Qgd2Vibm5EYXRhVHlwZVRvRmFsbGJhY2sgPSBuZXcgTWFwPE1MT3BlcmFuZERhdGFUeXBlLCBNTE9wZXJhbmREYXRhVHlwZT4oW1xuICBbJ2ludDgnLCAnaW50MzInXSxcbiAgWyd1aW50OCcsICdpbnQzMiddLFxuICBbJ3VpbnQzMicsICdpbnQzMiddLFxuICBbJ2ludDY0JywgJ2ludDMyJ10sXG5dKTtcblxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIGJ5dGUgbGVuZ3RoIG9mIGEgdGVuc29yIHdpdGggdGhlIGdpdmVuIGRhdGEgdHlwZSBhbmQgc2hhcGUuXG4gKi9cbmNvbnN0IGNhbGN1bGF0ZUJ5dGVMZW5ndGggPSAoZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlLCBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOiBudW1iZXIgPT4ge1xuICBjb25zdCBkYXRhVHlwZVNpemUgPSB3ZWJubkRhdGFUeXBlVG9TaXplLmdldChkYXRhVHlwZSk7XG4gIGlmICghZGF0YVR5cGVTaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBXZWJOTiBiYWNrZW5kIGRvZXMgbm90IHN1cHBvcnQgZGF0YSB0eXBlOiAke2RhdGFUeXBlfWApO1xuICB9XG4gIHJldHVybiBzaGFwZS5sZW5ndGggPiAwID8gTWF0aC5jZWlsKChzaGFwZS5yZWR1Y2UoKGEsIGIpID0+IGEgKiBiKSAqIGRhdGFUeXBlU2l6ZSkgLyA4KSA6IDA7XG59O1xuXG4vKipcbiAqIFRlbnNvcldyYXBwZXIgd3JhcHMgYW4gTUxUZW5zb3IgYW5kIHByb3ZpZGVzIGEgd2F5IHRvIHRyYWNrIHRoZSBsYXN0IHNlc3Npb24gdGhhdCB1c2VkIGl0LlxuICovXG5jbGFzcyBUZW5zb3JXcmFwcGVyIHtcbiAgLy8gVGhlIGlkIG9mIHRoZSBsYXN0IHNlc3Npb24gdGhhdCB1c2VkIHRoaXMgdGVuc29yLlxuICBwdWJsaWMgc2Vzc2lvbklkOiBudW1iZXI7XG4gIC8vIFRoaXMgZmxhZyBpcyB1c2VkIHRvIGluZGljYXRlIHdoZXRoZXIgdGhlIGRhdGEgaGFzIGJlZW4gY29udmVydGVkIHRvIGZhbGxiYWNrIGRhdGEgdHlwZS5cbiAgcHVibGljIGlzRGF0YUNvbnZlcnRlZCA9IGZhbHNlO1xuXG4gIHByaXZhdGUgbWxDb250ZXh0OiBNTENvbnRleHQ7XG4gIHByaXZhdGUgbWxUZW5zb3I6IE1MVGVuc29yO1xuICBwcml2YXRlIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZTtcbiAgLy8gRmFsbGJhY2sgZGF0YSB0eXBlIHRvIHVzZSB3aGVuIHRoZSBjb250ZXh0IGRvZXMgbm90IHN1cHBvcnQgdGhlIG9yaWdpbmFsIGRhdGEgdHlwZS5cbiAgcHJpdmF0ZSBmYWxsYmFja0RhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSB0ZW5zb3JTaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG5cbiAgY29uc3RydWN0b3IoZGVzY3JpcHRvcjoge1xuICAgIHNlc3Npb25JZDogbnVtYmVyO1xuICAgIGNvbnRleHQ6IE1MQ29udGV4dDtcbiAgICB0ZW5zb3I6IE1MVGVuc29yO1xuICAgIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZTtcbiAgICBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG4gICAgZmFsbGJhY2tEYXRhVHlwZT86IE1MT3BlcmFuZERhdGFUeXBlO1xuICB9KSB7XG4gICAgY29uc3QgeyBzZXNzaW9uSWQsIGNvbnRleHQsIHRlbnNvciwgZGF0YVR5cGUsIHNoYXBlLCBmYWxsYmFja0RhdGFUeXBlIH0gPSBkZXNjcmlwdG9yO1xuICAgIHRoaXMuc2Vzc2lvbklkID0gc2Vzc2lvbklkO1xuICAgIHRoaXMubWxDb250ZXh0ID0gY29udGV4dDtcbiAgICB0aGlzLm1sVGVuc29yID0gdGVuc29yO1xuICAgIHRoaXMuZGF0YVR5cGUgPSBkYXRhVHlwZTtcbiAgICB0aGlzLnRlbnNvclNoYXBlID0gc2hhcGU7XG4gICAgdGhpcy5mYWxsYmFja0RhdGFUeXBlID0gZmFsbGJhY2tEYXRhVHlwZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdGVuc29yKCk6IE1MVGVuc29yIHtcbiAgICByZXR1cm4gdGhpcy5tbFRlbnNvcjtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdHlwZSgpOiBNTE9wZXJhbmREYXRhVHlwZSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YVR5cGU7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGZhbGxiYWNrVHlwZSgpOiBNTE9wZXJhbmREYXRhVHlwZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuZmFsbGJhY2tEYXRhVHlwZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgc2hhcGUoKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIHJldHVybiB0aGlzLnRlbnNvclNoYXBlO1xuICB9XG5cbiAgcHVibGljIGdldCBieXRlTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIGNhbGN1bGF0ZUJ5dGVMZW5ndGgodGhpcy5kYXRhVHlwZSwgdGhpcy50ZW5zb3JTaGFwZSk7XG4gIH1cblxuICBwdWJsaWMgZGVzdHJveSgpOiB2b2lkIHtcbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiAnW1dlYk5OXSBUZW5zb3JXcmFwcGVyLmRlc3Ryb3knKTtcbiAgICB0aGlzLm1sVGVuc29yLmRlc3Ryb3koKTtcbiAgfVxuXG4gIHB1YmxpYyB3cml0ZShkYXRhOiBVaW50OEFycmF5KTogdm9pZCB7XG4gICAgdGhpcy5tbENvbnRleHQud3JpdGVUZW5zb3IodGhpcy5tbFRlbnNvciwgZGF0YSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcmVhZCgpOiBQcm9taXNlPEFycmF5QnVmZmVyPjtcbiAgcHVibGljIGFzeW5jIHJlYWQoZHN0QnVmZmVyPzogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpOiBQcm9taXNlPEFycmF5QnVmZmVyIHwgdW5kZWZpbmVkPjtcbiAgcHVibGljIGFzeW5jIHJlYWQoZHN0QnVmZmVyPzogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpOiBQcm9taXNlPEFycmF5QnVmZmVyIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKHRoaXMuZmFsbGJhY2tEYXRhVHlwZSkge1xuICAgICAgLy8gVGhpcyB0ZW5zb3IgaGFzIGJlZW4gZmFsbGJhY2sgdG8gaW50MzIgYXMgd29ya2Fyb3VuZCwgd2UgbmVlZCB0byByZWFkIGl0IGFzIGl0cyBvcmlnaW5hbCBpbnRlZ2VyIGRhdGEgdHlwZS5cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLm1sQ29udGV4dC5yZWFkVGVuc29yKHRoaXMubWxUZW5zb3IpO1xuICAgICAgY29uc3Qgb3JpZ2luYWxEYXRhID0gY29udmVydEludDMyVG9EYXRhKG5ldyBVaW50OEFycmF5KGRhdGEpLCB0aGlzLmRhdGFUeXBlKTtcblxuICAgICAgaWYgKGRzdEJ1ZmZlcikge1xuICAgICAgICBjb25zdCB0YXJnZXRCdWZmZXIgPVxuICAgICAgICAgIGRzdEJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyXG4gICAgICAgICAgICA/IG5ldyBVaW50OEFycmF5KGRzdEJ1ZmZlcilcbiAgICAgICAgICAgIDogbmV3IFVpbnQ4QXJyYXkoZHN0QnVmZmVyLmJ1ZmZlciwgZHN0QnVmZmVyLmJ5dGVPZmZzZXQsIGRzdEJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgdGFyZ2V0QnVmZmVyLnNldChvcmlnaW5hbERhdGEpO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG9yaWdpbmFsRGF0YS5idWZmZXI7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBkc3RCdWZmZXIgPyB0aGlzLm1sQ29udGV4dC5yZWFkVGVuc29yKHRoaXMubWxUZW5zb3IsIGRzdEJ1ZmZlcikgOiB0aGlzLm1sQ29udGV4dC5yZWFkVGVuc29yKHRoaXMubWxUZW5zb3IpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBjYW5SZXVzZVRlbnNvcihjb250ZXh0OiBNTENvbnRleHQsIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSwgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMubWxDb250ZXh0ID09PSBjb250ZXh0ICYmXG4gICAgICB0aGlzLmRhdGFUeXBlID09PSBkYXRhVHlwZSAmJlxuICAgICAgdGhpcy50ZW5zb3JTaGFwZS5sZW5ndGggPT09IHNoYXBlLmxlbmd0aCAmJlxuICAgICAgdGhpcy50ZW5zb3JTaGFwZS5ldmVyeSgodiwgaSkgPT4gdiA9PT0gc2hhcGVbaV0pXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRJc0RhdGFDb252ZXJ0ZWQoaXNDb252ZXJ0ZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmlzRGF0YUNvbnZlcnRlZCA9IGlzQ29udmVydGVkO1xuICB9XG59XG5cbi8qKlxuICogVGVuc29yVHJhY2tlciB0cmFja3MgdGhlIE1MVGVuc29yIGFuZCBwZW5kaW5nIHVwbG9hZCBkYXRhLlxuICpcbiAqIFdlIG5lZWQgdG8gdHJhY2sgdGhlIE1MVGVuc29yIGFuZCBwZW5kaW5nIHVwbG9hZCBkYXRhIGJlY2F1c2Ugd2UgZGVsYXkgdGhlIGNyZWF0aW9uIG9mIE1MVGVuc29yIHVudGlsXG4gKiB3ZSBrbm93IHRoZSBkYXRhIHR5cGUgYW5kIHNoYXBlLiBUaGlzIGlzIGJlY2F1c2UgV2ViTk4gb25seSBzdXBwb3J0IGNyZWF0aW5nIE1MVGVuc29ycyB3aXRoIGRhdGFUeXBlcyBhbmQgc2hhcGUuXG4gKi9cbmNsYXNzIFRlbnNvcklkVHJhY2tlciB7XG4gIHByaXZhdGUgYWN0aXZlVXBsb2FkPzogVWludDhBcnJheTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHRlbnNvck1hbmFnZXI6IFRlbnNvck1hbmFnZXJJbXBsLFxuICAgIHByaXZhdGUgd3JhcHBlcj86IFRlbnNvcldyYXBwZXIsXG4gICkge31cblxuICBwdWJsaWMgZ2V0IHRlbnNvcldyYXBwZXIoKTogVGVuc29yV3JhcHBlciB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMud3JhcHBlcjtcbiAgfVxuXG4gIHB1YmxpYyByZWxlYXNlVGVuc29yKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnRlbnNvcldyYXBwZXIpIHtcbiAgICAgIHRoaXMudGVuc29yTWFuYWdlci5yZWxlYXNlVGVuc29yKHRoaXMudGVuc29yV3JhcHBlcik7XG4gICAgICB0aGlzLndyYXBwZXIgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIGVuc3VyZVRlbnNvcihcbiAgICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgICBkYXRhVHlwZTogTUxPcGVyYW5kRGF0YVR5cGUsXG4gICAgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGNvcHlPbGQ6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8TUxUZW5zb3I+IHtcbiAgICBjb25zdCBjb250ZXh0ID0gdGhpcy50ZW5zb3JNYW5hZ2VyLmdldE1MQ29udGV4dChzZXNzaW9uSWQpO1xuICAgIGxldCBmYWxsYmFja0RhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSB8IHVuZGVmaW5lZDtcbiAgICAvLyBDaGVjayBpZiB0aGUgY29udGV4dCBzdXBwb3J0cyB0aGUgZGF0YSB0eXBlLiBJZiBub3QsIHRyeSB0byB1c2UgdGhlIGZhbGxiYWNrIGRhdGEgdHlwZS5cbiAgICBpZiAoIWNvbnRleHQub3BTdXBwb3J0TGltaXRzKCkuaW5wdXQuZGF0YVR5cGVzLmluY2x1ZGVzKGRhdGFUeXBlKSkge1xuICAgICAgZmFsbGJhY2tEYXRhVHlwZSA9IHdlYm5uRGF0YVR5cGVUb0ZhbGxiYWNrLmdldChkYXRhVHlwZSk7XG4gICAgICBpZiAoIWZhbGxiYWNrRGF0YVR5cGUgfHwgIWNvbnRleHQub3BTdXBwb3J0TGltaXRzKCkuaW5wdXQuZGF0YVR5cGVzLmluY2x1ZGVzKGZhbGxiYWNrRGF0YVR5cGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgV2ViTk4gYmFja2VuZCBkb2VzIG5vdCBzdXBwb3J0IGRhdGEgdHlwZTogJHtkYXRhVHlwZX1gKTtcbiAgICAgIH1cbiAgICAgIExPR19ERUJVRyhcbiAgICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgICAoKSA9PiBgW1dlYk5OXSBUZW5zb3JJZFRyYWNrZXIuZW5zdXJlVGVuc29yOiBmYWxsYmFjayBkYXRhVHlwZSBmcm9tICR7ZGF0YVR5cGV9IHRvICR7ZmFsbGJhY2tEYXRhVHlwZX1gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy53cmFwcGVyKSB7XG4gICAgICBpZiAodGhpcy53cmFwcGVyLmNhblJldXNlVGVuc29yKGNvbnRleHQsIGRhdGFUeXBlLCBzaGFwZSkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud3JhcHBlci50ZW5zb3I7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoY29weU9sZCkge1xuICAgICAgICAgIGlmICh0aGlzLndyYXBwZXIuYnl0ZUxlbmd0aCAhPT0gY2FsY3VsYXRlQnl0ZUxlbmd0aChkYXRhVHlwZSwgc2hhcGUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBjb3B5IGRhdGEgdG8gdGVuc29yIHdpdGggZGlmZmVyZW50IHNpemUuJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuYWN0aXZlVXBsb2FkID0gbmV3IFVpbnQ4QXJyYXkoYXdhaXQgdGhpcy53cmFwcGVyLnJlYWQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50ZW5zb3JNYW5hZ2VyLnJlbGVhc2VUZW5zb3IodGhpcy53cmFwcGVyKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgIGNvbnN0IHVzYWdlID0gdHlwZW9mIE1MVGVuc29yVXNhZ2UgPT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiBNTFRlbnNvclVzYWdlLlJFQUQgfCBNTFRlbnNvclVzYWdlLldSSVRFO1xuICAgIHRoaXMud3JhcHBlciA9IGF3YWl0IHRoaXMudGVuc29yTWFuYWdlci5nZXRDYWNoZWRUZW5zb3IoXG4gICAgICBzZXNzaW9uSWQsXG4gICAgICBkYXRhVHlwZSxcbiAgICAgIHNoYXBlLFxuICAgICAgdXNhZ2UsXG4gICAgICB0cnVlLFxuICAgICAgdHJ1ZSxcbiAgICAgIGZhbGxiYWNrRGF0YVR5cGUsXG4gICAgKTtcblxuICAgIGlmIChjb3B5T2xkICYmIHRoaXMuYWN0aXZlVXBsb2FkKSB7XG4gICAgICAvLyBXZSBkb24ndCBuZWVkIHRvIGNvbnZlcnQgdGhlIG9yaWdpbmFsIGludGVnZXIgZGF0YSB0byBpbnQzMixcbiAgICAgIC8vIGJlY2F1c2UgaXQgaGFzIGJlZW4gY29udmVydGVkIHdoZW4gaXQgd2FzIHVwbG9hZGVkLlxuICAgICAgdGhpcy53cmFwcGVyLndyaXRlKHRoaXMuYWN0aXZlVXBsb2FkKTtcbiAgICAgIHRoaXMuYWN0aXZlVXBsb2FkID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLndyYXBwZXIudGVuc29yO1xuICB9XG5cbiAgcHVibGljIHVwbG9hZChkYXRhOiBVaW50OEFycmF5KTogdm9pZCB7XG4gICAgbGV0IG5ld0RhdGEgPSBkYXRhO1xuICAgIGlmICh0aGlzLndyYXBwZXIpIHtcbiAgICAgIGlmICh0aGlzLndyYXBwZXIuZmFsbGJhY2tUeXBlKSB7XG4gICAgICAgIGlmICh0aGlzLndyYXBwZXIuZmFsbGJhY2tUeXBlID09PSAnaW50MzInKSB7XG4gICAgICAgICAgLy8gQ29udmVydCBvcmlnaW5hbCBpbnRlZ2VyIGRhdGEgdG8gaW50MzIuXG4gICAgICAgICAgbmV3RGF0YSA9IGNvbnZlcnREYXRhVG9JbnQzMihkYXRhLCB0aGlzLndyYXBwZXIudHlwZSk7XG4gICAgICAgICAgdGhpcy53cmFwcGVyLnNldElzRGF0YUNvbnZlcnRlZCh0cnVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGZhbGxiYWNrIGRhdGEgdHlwZTogJHt0aGlzLndyYXBwZXIuZmFsbGJhY2tUeXBlfWApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIENoZWNrIGlmIHRoZSBkYXRhIHNpemUgbWF0Y2hlcyB0aGUgdGVuc29yIHNpemUuXG4gICAgICBpZiAoZGF0YS5ieXRlTGVuZ3RoID09PSB0aGlzLndyYXBwZXIuYnl0ZUxlbmd0aCkge1xuICAgICAgICAvLyBXcml0ZSB0aGUgbmV3RGF0YSB0byB0aGUgdGVuc29yLlxuICAgICAgICB0aGlzLndyYXBwZXIud3JpdGUobmV3RGF0YSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+ICdEYXRhIHNpemUgZG9lcyBub3QgbWF0Y2ggdGVuc29yIHNpemUuIFJlbGVhc2luZyB0ZW5zb3IuJyk7XG4gICAgICAgIHRoaXMucmVsZWFzZVRlbnNvcigpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmFjdGl2ZVVwbG9hZCkge1xuICAgICAgdGhpcy5hY3RpdmVVcGxvYWQuc2V0KG5ld0RhdGEpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFjdGl2ZVVwbG9hZCA9IG5ldyBVaW50OEFycmF5KG5ld0RhdGEpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBkb3dubG9hZChkc3RCdWZmZXI/OiBBcnJheUJ1ZmZlclZpZXcgfCBBcnJheUJ1ZmZlcik6IFByb21pc2U8QXJyYXlCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICBpZiAodGhpcy5hY3RpdmVVcGxvYWQpIHtcbiAgICAgIC8vIElmIHRoaXMuYWN0aXZlVXBsb2FkIGhhcyBiZWVuIGNvbnZlcnRlZCB0byBpbnQzMiwgd2UgbmVlZCB0byBjb252ZXJ0IGl0IGJhY2sgdG8gb3JpZ2luYWwgaW50ZWdlciBkYXRhIHR5cGUuXG4gICAgICBjb25zdCBkc3REYXRhID0gdGhpcy53cmFwcGVyPy5pc0RhdGFDb252ZXJ0ZWRcbiAgICAgICAgPyBjb252ZXJ0SW50MzJUb0RhdGEodGhpcy5hY3RpdmVVcGxvYWQsIHRoaXMud3JhcHBlcj8udHlwZSlcbiAgICAgICAgOiB0aGlzLmFjdGl2ZVVwbG9hZDtcblxuICAgICAgaWYgKGRzdEJ1ZmZlcikge1xuICAgICAgICBpZiAoZHN0QnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgICBuZXcgVWludDhBcnJheShkc3RCdWZmZXIpLnNldChkc3REYXRhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZXcgVWludDhBcnJheShkc3RCdWZmZXIuYnVmZmVyLCBkc3RCdWZmZXIuYnl0ZU9mZnNldCwgZHN0QnVmZmVyLmJ5dGVMZW5ndGgpLnNldChkc3REYXRhKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZHN0RGF0YS5idWZmZXI7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICghdGhpcy53cmFwcGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBoYXMgbm90IGJlZW4gY3JlYXRlZC4nKTtcbiAgICB9XG5cbiAgICBpZiAoIWRzdEJ1ZmZlcikge1xuICAgICAgcmV0dXJuIHRoaXMud3JhcHBlci5yZWFkKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLndyYXBwZXIucmVhZChkc3RCdWZmZXIpO1xuICB9XG59XG5cbmNsYXNzIFRlbnNvck1hbmFnZXJJbXBsIGltcGxlbWVudHMgVGVuc29yTWFuYWdlciB7XG4gIHByaXZhdGUgdGVuc29yVHJhY2tlcnNCeUlkOiBNYXA8VGVuc29ySWQsIFRlbnNvcklkVHJhY2tlcj4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgZnJlZVRlbnNvcnM6IFRlbnNvcldyYXBwZXJbXSA9IFtdO1xuICBwcml2YXRlIGV4dGVybmFsVGVuc29yczogU2V0PFRlbnNvcldyYXBwZXI+ID0gbmV3IFNldCgpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgYmFja2VuZDogV2ViTk5CYWNrZW5kKSB7fVxuXG4gIHB1YmxpYyBnZXRNTENvbnRleHQoc2Vzc2lvbklkOiBudW1iZXIpOiBNTENvbnRleHQge1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmJhY2tlbmQuZ2V0TUxDb250ZXh0KHNlc3Npb25JZCk7XG4gICAgaWYgKCFjb250ZXh0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01MQ29udGV4dCBub3QgZm91bmQgZm9yIHNlc3Npb24uJyk7XG4gICAgfVxuICAgIHJldHVybiBjb250ZXh0O1xuICB9XG5cbiAgcHVibGljIHJlc2VydmVUZW5zb3JJZCgpOiBUZW5zb3JJZCB7XG4gICAgY29uc3QgdGVuc29ySWQgPSBjcmVhdGVOZXdUZW5zb3JJZCgpO1xuICAgIHRoaXMudGVuc29yVHJhY2tlcnNCeUlkLnNldCh0ZW5zb3JJZCwgbmV3IFRlbnNvcklkVHJhY2tlcih0aGlzKSk7XG4gICAgcmV0dXJuIHRlbnNvcklkO1xuICB9XG5cbiAgcHVibGljIHJlbGVhc2VUZW5zb3JJZCh0ZW5zb3JJZDogVGVuc29ySWQpOiB2b2lkIHtcbiAgICBjb25zdCB0ZW5zb3JUcmFja2VyID0gdGhpcy50ZW5zb3JUcmFja2Vyc0J5SWQuZ2V0KHRlbnNvcklkKTtcbiAgICBpZiAoIXRlbnNvclRyYWNrZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy50ZW5zb3JUcmFja2Vyc0J5SWQuZGVsZXRlKHRlbnNvcklkKTtcbiAgICBpZiAodGVuc29yVHJhY2tlci50ZW5zb3JXcmFwcGVyKSB7XG4gICAgICB0aGlzLnJlbGVhc2VUZW5zb3IodGVuc29yVHJhY2tlci50ZW5zb3JXcmFwcGVyKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZW5zdXJlVGVuc29yKFxuICAgIHNlc3Npb25JZDogbnVtYmVyLFxuICAgIHRlbnNvcklkOiBUZW5zb3JJZCxcbiAgICBkYXRhVHlwZTogTUxPcGVyYW5kRGF0YVR5cGUsXG4gICAgc2hhcGU6IG51bWJlcltdLFxuICAgIGNvcHlPbGQ6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8TUxUZW5zb3I+IHtcbiAgICBMT0dfREVCVUcoXG4gICAgICAndmVyYm9zZScsXG4gICAgICAoKSA9PlxuICAgICAgICBgW1dlYk5OXSBUZW5zb3JNYW5hZ2VyLmVuc3VyZVRlbnNvciB7dGVuc29ySWQ6ICR7dGVuc29ySWR9LCBkYXRhVHlwZTogJHtcbiAgICAgICAgICBkYXRhVHlwZVxuICAgICAgICB9LCBzaGFwZTogJHtzaGFwZX0sIGNvcHlPbGQ6ICR7Y29weU9sZH19YCxcbiAgICApO1xuICAgIGNvbnN0IHRlbnNvciA9IHRoaXMudGVuc29yVHJhY2tlcnNCeUlkLmdldCh0ZW5zb3JJZCk7XG4gICAgaWYgKCF0ZW5zb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIG5vdCBmb3VuZC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRlbnNvci5lbnN1cmVUZW5zb3Ioc2Vzc2lvbklkLCBkYXRhVHlwZSwgc2hhcGUsIGNvcHlPbGQpO1xuICB9XG5cbiAgcHVibGljIHVwbG9hZCh0ZW5zb3JJZDogVGVuc29ySWQsIGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICBjb25zdCB0ZW5zb3IgPSB0aGlzLnRlbnNvclRyYWNrZXJzQnlJZC5nZXQodGVuc29ySWQpO1xuICAgIGlmICghdGVuc29yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBub3QgZm91bmQuJyk7XG4gICAgfVxuICAgIHRlbnNvci51cGxvYWQoZGF0YSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZG93bmxvYWQodGVuc29ySWQ6IFRlbnNvcklkKTogUHJvbWlzZTxBcnJheUJ1ZmZlcj47XG4gIHB1YmxpYyBhc3luYyBkb3dubG9hZCh0ZW5zb3JJZDogVGVuc29ySWQsIGRzdEJ1ZmZlcjogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpOiBQcm9taXNlPHVuZGVmaW5lZD47XG4gIGFzeW5jIGRvd25sb2FkKHRlbnNvcklkOiBUZW5zb3JJZCwgZHN0QnVmZmVyPzogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpOiBQcm9taXNlPEFycmF5QnVmZmVyIHwgdW5kZWZpbmVkPiB7XG4gICAgTE9HX0RFQlVHKFxuICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgKCkgPT4gYFtXZWJOTl0gVGVuc29yTWFuYWdlci5kb3dubG9hZCB7dGVuc29ySWQ6ICR7dGVuc29ySWR9LCBkc3RCdWZmZXI6ICR7ZHN0QnVmZmVyPy5ieXRlTGVuZ3RofX1gLFxuICAgICk7XG4gICAgY29uc3QgdGVuc29yVHJhY2tlciA9IHRoaXMudGVuc29yVHJhY2tlcnNCeUlkLmdldCh0ZW5zb3JJZCk7XG4gICAgaWYgKCF0ZW5zb3JUcmFja2VyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBub3QgZm91bmQuJyk7XG4gICAgfVxuICAgIHJldHVybiB0ZW5zb3JUcmFja2VyLmRvd25sb2FkKGRzdEJ1ZmZlcik7XG4gIH1cblxuICBwdWJsaWMgcmVsZWFzZVRlbnNvcnNGb3JTZXNzaW9uKHNlc3Npb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCB0ZW5zb3Igb2YgdGhpcy5mcmVlVGVuc29ycykge1xuICAgICAgaWYgKHRlbnNvci5zZXNzaW9uSWQgPT09IHNlc3Npb25JZCkge1xuICAgICAgICB0ZW5zb3IuZGVzdHJveSgpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmZyZWVUZW5zb3JzID0gdGhpcy5mcmVlVGVuc29ycy5maWx0ZXIoKHRlbnNvcikgPT4gdGVuc29yLnNlc3Npb25JZCAhPT0gc2Vzc2lvbklkKTtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3RlclRlbnNvcihcbiAgICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgICBtbFRlbnNvcjogTUxUZW5zb3IsXG4gICAgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlLFxuICAgIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogVGVuc29ySWQge1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmdldE1MQ29udGV4dChzZXNzaW9uSWQpO1xuICAgIGNvbnN0IHRlbnNvcklkID0gY3JlYXRlTmV3VGVuc29ySWQoKTtcbiAgICAvLyBEZWZhdWx0aW5nIHRvIFJFQUQgfCBXUklURSBpZiB1c2FnZSBpcyBub3QgcHJvdmlkZWQuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICBjb25zdCB3cmFwcGVyID0gbmV3IFRlbnNvcldyYXBwZXIoe1xuICAgICAgc2Vzc2lvbklkLFxuICAgICAgY29udGV4dCxcbiAgICAgIHRlbnNvcjogbWxUZW5zb3IsXG4gICAgICBkYXRhVHlwZSxcbiAgICAgIHNoYXBlLFxuICAgIH0pO1xuICAgIHRoaXMudGVuc29yVHJhY2tlcnNCeUlkLnNldCh0ZW5zb3JJZCwgbmV3IFRlbnNvcklkVHJhY2tlcih0aGlzLCB3cmFwcGVyKSk7XG4gICAgdGhpcy5leHRlcm5hbFRlbnNvcnMuYWRkKHdyYXBwZXIpO1xuICAgIHJldHVybiB0ZW5zb3JJZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgb3IgY3JlYXRlIGFuIE1MVGVuc29yIHdpdGggdGhlIGdpdmVuIGRhdGEgdHlwZSBhbmQgc2hhcGUuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0Q2FjaGVkVGVuc29yKFxuICAgIHNlc3Npb25JZDogbnVtYmVyLFxuICAgIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSxcbiAgICBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgdXNhZ2U6IE1MVGVuc29yVXNhZ2VGbGFncyB8IHVuZGVmaW5lZCxcbiAgICB3cml0YWJsZTogYm9vbGVhbixcbiAgICByZWFkYWJsZTogYm9vbGVhbixcbiAgICBmYWxsYmFja0RhdGFUeXBlPzogTUxPcGVyYW5kRGF0YVR5cGUsXG4gICk6IFByb21pc2U8VGVuc29yV3JhcHBlcj4ge1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmdldE1MQ29udGV4dChzZXNzaW9uSWQpO1xuICAgIGZvciAoY29uc3QgW2luZGV4LCB0ZW5zb3JdIG9mIHRoaXMuZnJlZVRlbnNvcnMuZW50cmllcygpKSB7XG4gICAgICBpZiAodGVuc29yLmNhblJldXNlVGVuc29yKGNvbnRleHQsIGRhdGFUeXBlLCBzaGFwZSkpIHtcbiAgICAgICAgTE9HX0RFQlVHKFxuICAgICAgICAgICd2ZXJib3NlJyxcbiAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgYFtXZWJOTl0gUmV1c2luZyB0ZW5zb3Ige2RhdGFUeXBlOiAke2RhdGFUeXBlfSwgJHtcbiAgICAgICAgICAgICAgZmFsbGJhY2tEYXRhVHlwZSA/IGBmYWxsYmFja0RhdGFUeXBlOiAke2ZhbGxiYWNrRGF0YVR5cGV9LGAgOiAnJ1xuICAgICAgICAgICAgfSBzaGFwZTogJHtzaGFwZX1gLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCB3cmFwcGVyID0gdGhpcy5mcmVlVGVuc29ycy5zcGxpY2UoaW5kZXgsIDEpWzBdO1xuICAgICAgICB3cmFwcGVyLnNlc3Npb25JZCA9IHNlc3Npb25JZDtcbiAgICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgICB9XG4gICAgfVxuICAgIExPR19ERUJVRyhcbiAgICAgICd2ZXJib3NlJyxcbiAgICAgICgpID0+XG4gICAgICAgIGBbV2ViTk5dIE1MQ29udGV4dC5jcmVhdGVUZW5zb3Ige2RhdGFUeXBlOiAke2RhdGFUeXBlfSwgJHtcbiAgICAgICAgICBmYWxsYmFja0RhdGFUeXBlID8gYGZhbGxiYWNrRGF0YVR5cGU6ICR7ZmFsbGJhY2tEYXRhVHlwZX0sYCA6ICcnXG4gICAgICAgIH0gc2hhcGU6ICR7c2hhcGV9fWAsXG4gICAgKTtcbiAgICBjb25zdCB0ZW5zb3IgPSBhd2FpdCBjb250ZXh0LmNyZWF0ZVRlbnNvcih7XG4gICAgICBkYXRhVHlwZTogZmFsbGJhY2tEYXRhVHlwZSA/PyBkYXRhVHlwZSwgLy8gSWYgZmFsbGJhY2sgZGF0YSB0eXBlIGlzIHByb3ZpZGVkLCB1c2UgaXQuXG4gICAgICBzaGFwZSxcbiAgICAgIGRpbWVuc2lvbnM6IHNoYXBlLFxuICAgICAgdXNhZ2UsXG4gICAgICB3cml0YWJsZSxcbiAgICAgIHJlYWRhYmxlLFxuICAgIH0pO1xuICAgIHJldHVybiBuZXcgVGVuc29yV3JhcHBlcih7IHNlc3Npb25JZCwgY29udGV4dCwgdGVuc29yLCBkYXRhVHlwZSwgc2hhcGUsIGZhbGxiYWNrRGF0YVR5cGUgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVsZWFzZSB0ZW5zb3IgZm9yIHJldXNlIHVubGVzcyBleHRlcm5hbC5cbiAgICovXG4gIHB1YmxpYyByZWxlYXNlVGVuc29yKHRlbnNvcldyYXBwZXI6IFRlbnNvcldyYXBwZXIpIHtcbiAgICBpZiAodGhpcy5leHRlcm5hbFRlbnNvcnMuaGFzKHRlbnNvcldyYXBwZXIpKSB7XG4gICAgICB0aGlzLmV4dGVybmFsVGVuc29ycy5kZWxldGUodGVuc29yV3JhcHBlcik7XG4gICAgfVxuICAgIHRoaXMuZnJlZVRlbnNvcnMucHVzaCh0ZW5zb3JXcmFwcGVyKTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgY3JlYXRlVGVuc29yTWFuYWdlciA9ICguLi5hcmdzOiBDb25zdHJ1Y3RvclBhcmFtZXRlcnM8dHlwZW9mIFRlbnNvck1hbmFnZXJJbXBsPik6IFRlbnNvck1hbmFnZXIgPT5cbiAgbmV3IFRlbnNvck1hbmFnZXJJbXBsKC4uLmFyZ3MpO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vLyBXZWJOTiBBUEkgY3VycmVudGx5IGRvZXMgbm90IGhhdmUgYSBUeXBlU2NyaXB0IGRlZmluaXRpb24gZmlsZS4gVGhpcyBmaWxlIGlzIGEgd29ya2Fyb3VuZCB3aXRoIHR5cGVzIGdlbmVyYXRlZCBmcm9tXG4vLyBXZWJOTiBBUEkgc3BlY2lmaWNhdGlvbi5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS93ZWJtYWNoaW5lbGVhcm5pbmcvd2Vibm4vaXNzdWVzLzY3N1xuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIndlYm5uL3dlYm5uLmQudHNcIiAvPlxuXG5pbXBvcnQgeyBFbnYsIFRlbnNvciB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IERhdGFUeXBlLCB0ZW5zb3JEYXRhVHlwZVN0cmluZ1RvRW51bSB9IGZyb20gJy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IGdldEluc3RhbmNlIH0gZnJvbSAnLi4vd2FzbS1mYWN0b3J5JztcblxuaW1wb3J0IHsgY3JlYXRlVmlldyB9IGZyb20gJy4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgVGVuc29ySWQsIGNyZWF0ZVRlbnNvck1hbmFnZXIsIGNvbnZlcnREYXRhVG9JbnQzMiB9IGZyb20gJy4vd2Vibm4vdGVuc29yLW1hbmFnZXInO1xuaW1wb3J0IHsgY29uZmlndXJlTG9nZ2VyLCBMT0dfREVCVUcgfSBmcm9tICcuL2xvZyc7XG5cbi8qXG4gKiBUZW5zb3JQcm90bzo6ZGF0YV90eXBlIHRvIFdlYk5OIE9wZXJhbmRUeXBlIG1hcHBpbmcuXG4gKi9cbmNvbnN0IG9ubnhEYXRhVHlwZVRvV2Vibm5EYXRhVHlwZSA9IG5ldyBNYXA8RGF0YVR5cGUsIE1MT3BlcmFuZERhdGFUeXBlPihbXG4gIFtEYXRhVHlwZS5mbG9hdCwgJ2Zsb2F0MzInXSxcbiAgW0RhdGFUeXBlLmZsb2F0MTYsICdmbG9hdDE2J10sXG4gIFtEYXRhVHlwZS5pbnQzMiwgJ2ludDMyJ10sXG4gIFtEYXRhVHlwZS51aW50MzIsICd1aW50MzInXSxcbiAgW0RhdGFUeXBlLmludDY0LCAnaW50NjQnXSxcbiAgW0RhdGFUeXBlLnVpbnQ2NCwgJ3VpbnQ2NCddLFxuICBbRGF0YVR5cGUuaW50NCwgJ2ludDQnXSxcbiAgW0RhdGFUeXBlLnVpbnQ0LCAndWludDQnXSxcbiAgW0RhdGFUeXBlLmludDgsICdpbnQ4J10sXG4gIFtEYXRhVHlwZS51aW50OCwgJ3VpbnQ4J10sXG4gIFtEYXRhVHlwZS5ib29sLCAndWludDgnXSxcbl0pO1xuXG50eXBlIE1MQ29udGV4dEVudHJ5ID0ge1xuICBncHVEZXZpY2U/OiBHUFVEZXZpY2U7XG4gIG9wdGlvbnM/OiBNTENvbnRleHRPcHRpb25zO1xuICBtbENvbnRleHQ6IE1MQ29udGV4dDtcbn07XG5cbmNvbnN0IGNvbXBhcmVNTENvbnRleHRPcHRpb25zID0gKGE/OiBNTENvbnRleHRPcHRpb25zLCBiPzogTUxDb250ZXh0T3B0aW9ucyk6IGJvb2xlYW4gPT4ge1xuICBpZiAoYSA9PT0gYikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIGlmIChhID09PSB1bmRlZmluZWQgfHwgYiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IGFLZXlzID0gT2JqZWN0LmtleXMoYSkuc29ydCgpIGFzIEFycmF5PGtleW9mIHR5cGVvZiBhPjtcbiAgY29uc3QgYktleXMgPSBPYmplY3Qua2V5cyhiKS5zb3J0KCkgYXMgQXJyYXk8a2V5b2YgdHlwZW9mIGI+O1xuICByZXR1cm4gYUtleXMubGVuZ3RoID09PSBiS2V5cy5sZW5ndGggJiYgYUtleXMuZXZlcnkoKGtleSwgaW5kZXgpID0+IGtleSA9PT0gYktleXNbaW5kZXhdICYmIGFba2V5XSA9PT0gYltrZXldKTtcbn07XG5cbi8qKlxuICogV2ViTk4gYmFja2VuZCBpbXBsZW1lbnRhdGlvbi4gVGhpcyBjbGFzcyBpcyB1c2VkIHRvIGtlZXAgdHJhY2sgb2YgdGhlIE1MVGVuc29ycyBjcmVhdGVkIGJ5IHRoZSBiYWNrZW5kIGFuZCBrZWVwIHRyYWNrXG4gKiBvZiB0aGUgY3VycmVudCBNTENvbnRleHQgYmVpbmcgdXNlZCBieSB0aGUgc2Vzc2lvbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJOTkJhY2tlbmQge1xuICAvKipcbiAgICogVGVuc29yIG1hbmFnZXJzIGZvciBlYWNoIHNlc3Npb24uXG4gICAqL1xuICBwcml2YXRlIHRlbnNvck1hbmFnZXIgPSBjcmVhdGVUZW5zb3JNYW5hZ2VyKHRoaXMpO1xuICAvKipcbiAgICogTWFwcyBmcm9tIHNlc3Npb24gaWQgdG8gTUxDb250ZXh0cy5cbiAgICovXG4gIHByaXZhdGUgbWxDb250ZXh0QnlTZXNzaW9uSWQgPSBuZXcgTWFwPG51bWJlciwgTUxDb250ZXh0PigpO1xuICAvKipcbiAgICogTWFwcyBmcm9tIE1MQ29udGV4dCB0byBzZXNzaW9uIGlkcy5cbiAgICovXG4gIHByaXZhdGUgc2Vzc2lvbklkc0J5TUxDb250ZXh0ID0gbmV3IE1hcDxNTENvbnRleHQsIFNldDxudW1iZXI+PigpO1xuICAvKipcbiAgICogQ2FjaGUgb2YgTUxDb250ZXh0cy5cbiAgICovXG4gIHByaXZhdGUgbWxDb250ZXh0Q2FjaGU6IE1MQ29udGV4dEVudHJ5W10gPSBbXTtcbiAgLyoqXG4gICAqIEN1cnJlbnQgc2Vzc2lvbiBpZC5cbiAgICovXG4gIHByaXZhdGUgYWN0aXZlU2Vzc2lvbklkPzogbnVtYmVyO1xuICAvKipcbiAgICogTWFwcyBmcm9tIHNlc3Npb24gaWQgdG8gbGlzdCBvZiBncmFwaCBpbnB1dHMuXG4gICAqL1xuICBwcml2YXRlIHNlc3Npb25HcmFwaElucHV0czogTWFwPG51bWJlciwgc3RyaW5nW10+ID0gbmV3IE1hcCgpO1xuICAvKipcbiAgICogTWFwcyBmcm9tIHNlc3Npb24gaWQgdG8gbGlzdCBvZiBncmFwaCBvdXRwdXRzLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXNzaW9uR3JhcGhPdXRwdXRzOiBNYXA8bnVtYmVyLCBzdHJpbmdbXT4gPSBuZXcgTWFwKCk7XG4gIC8qKlxuICAgKiBUZW1wb3JhcnkgZ3JhcGggaW5wdXRzIGZvciB0aGUgY3VycmVudCBzZXNzaW9uLlxuICAgKiBUaGVzZSBpbnB1dHMgd2lsbCBiZSByZWdpc3RlcmVkIHdoZW4gdGhlIHNlc3Npb24gaXMgY3JlYXRlZC5cbiAgICovXG4gIHByaXZhdGUgdGVtcG9yYXJ5R3JhcGhJbnB1dHM6IHN0cmluZ1tdID0gW107XG4gIC8qKlxuICAgKiBUZW1wb3JhcnkgZ3JhcGggb3V0cHV0cyBmb3IgdGhlIGN1cnJlbnQgc2Vzc2lvbi5cbiAgICogVGhlc2Ugb3V0cHV0cyB3aWxsIGJlIHJlZ2lzdGVyZWQgd2hlbiB0aGUgc2Vzc2lvbiBpcyBjcmVhdGVkLlxuICAgKi9cbiAgcHJpdmF0ZSB0ZW1wb3JhcnlHcmFwaE91dHB1dHM6IHN0cmluZ1tdID0gW107XG4gIC8qKlxuICAgKiBUZW1wb3JhcnkgdGVuc29ycyBmb3IgdGhlIGN1cnJlbnQgc2Vzc2lvbi5cbiAgICovXG4gIHByaXZhdGUgdGVtcG9yYXJ5U2Vzc2lvblRlbnNvcklkczogTWFwPG51bWJlciwgVGVuc29ySWRbXT4gPSBuZXcgTWFwKCk7XG5cbiAgY29uc3RydWN0b3IoZW52OiBFbnYpIHtcbiAgICBjb25maWd1cmVMb2dnZXIoZW52LmxvZ0xldmVsISwgISFlbnYuZGVidWcpO1xuICB9XG5cbiAgcHVibGljIGdldCBjdXJyZW50U2Vzc2lvbklkKCk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuYWN0aXZlU2Vzc2lvbklkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYWN0aXZlIHNlc3Npb24nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYWN0aXZlU2Vzc2lvbklkO1xuICB9XG5cbiAgcHVibGljIG9uUnVuU3RhcnQoc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYk5OXSBvblJ1blN0YXJ0IHtzZXNzaW9uSWQ6ICR7c2Vzc2lvbklkfX1gKTtcbiAgICB0aGlzLmFjdGl2ZVNlc3Npb25JZCA9IHNlc3Npb25JZDtcbiAgfVxuXG4gIHB1YmxpYyBvblJ1bkVuZChzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViTk5dIG9uUnVuRW5kIHtzZXNzaW9uSWQ6ICR7c2Vzc2lvbklkfX1gKTtcbiAgICBjb25zdCB0ZW5zb3JJZHMgPSB0aGlzLnRlbXBvcmFyeVNlc3Npb25UZW5zb3JJZHMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCF0ZW5zb3JJZHMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCB0ZW5zb3JJZCBvZiB0ZW5zb3JJZHMpIHtcbiAgICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViTk5dIHJlbGVhc2luZyB0ZW1wb3JhcnkgdGVuc29yIHt0ZW5zb3JJZDogJHt0ZW5zb3JJZH19YCk7XG4gICAgICB0aGlzLnRlbnNvck1hbmFnZXIucmVsZWFzZVRlbnNvcklkKHRlbnNvcklkKTtcbiAgICB9XG4gICAgdGhpcy50ZW1wb3JhcnlTZXNzaW9uVGVuc29ySWRzLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIHRoaXMuYWN0aXZlU2Vzc2lvbklkID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGNyZWF0ZU1MQ29udGV4dChvcHRpb25zT3JEZXZpY2U/OiBNTENvbnRleHRPcHRpb25zIHwgR1BVRGV2aWNlKTogUHJvbWlzZTxNTENvbnRleHQ+IHtcbiAgICBpZiAob3B0aW9uc09yRGV2aWNlIGluc3RhbmNlb2YgR1BVRGV2aWNlKSB7XG4gICAgICBjb25zdCBtbENvbnRleHRJbmRleCA9IHRoaXMubWxDb250ZXh0Q2FjaGUuZmluZEluZGV4KChlbnRyeSkgPT4gZW50cnkuZ3B1RGV2aWNlID09PSBvcHRpb25zT3JEZXZpY2UpO1xuICAgICAgaWYgKG1sQ29udGV4dEluZGV4ICE9PSAtMSkge1xuICAgICAgICByZXR1cm4gdGhpcy5tbENvbnRleHRDYWNoZVttbENvbnRleHRJbmRleF0ubWxDb250ZXh0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgbWxDb250ZXh0ID0gYXdhaXQgbmF2aWdhdG9yLm1sLmNyZWF0ZUNvbnRleHQob3B0aW9uc09yRGV2aWNlKTtcbiAgICAgICAgdGhpcy5tbENvbnRleHRDYWNoZS5wdXNoKHsgZ3B1RGV2aWNlOiBvcHRpb25zT3JEZXZpY2UsIG1sQ29udGV4dCB9KTtcbiAgICAgICAgcmV0dXJuIG1sQ29udGV4dDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG9wdGlvbnNPckRldmljZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBtbENvbnRleHRJbmRleCA9IHRoaXMubWxDb250ZXh0Q2FjaGUuZmluZEluZGV4KFxuICAgICAgICAoZW50cnkpID0+IGVudHJ5Lm9wdGlvbnMgPT09IHVuZGVmaW5lZCAmJiBlbnRyeS5ncHVEZXZpY2UgPT09IHVuZGVmaW5lZCxcbiAgICAgICk7XG4gICAgICBpZiAobWxDb250ZXh0SW5kZXggIT09IC0xKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1sQ29udGV4dENhY2hlW21sQ29udGV4dEluZGV4XS5tbENvbnRleHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBtbENvbnRleHQgPSBhd2FpdCBuYXZpZ2F0b3IubWwuY3JlYXRlQ29udGV4dCgpO1xuICAgICAgICB0aGlzLm1sQ29udGV4dENhY2hlLnB1c2goeyBtbENvbnRleHQgfSk7XG4gICAgICAgIHJldHVybiBtbENvbnRleHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbWxDb250ZXh0SW5kZXggPSB0aGlzLm1sQ29udGV4dENhY2hlLmZpbmRJbmRleCgoZW50cnkpID0+XG4gICAgICBjb21wYXJlTUxDb250ZXh0T3B0aW9ucyhlbnRyeS5vcHRpb25zLCBvcHRpb25zT3JEZXZpY2UpLFxuICAgICk7XG4gICAgaWYgKG1sQ29udGV4dEluZGV4ICE9PSAtMSkge1xuICAgICAgcmV0dXJuIHRoaXMubWxDb250ZXh0Q2FjaGVbbWxDb250ZXh0SW5kZXhdLm1sQ29udGV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgbWxDb250ZXh0ID0gYXdhaXQgbmF2aWdhdG9yLm1sLmNyZWF0ZUNvbnRleHQob3B0aW9uc09yRGV2aWNlKTtcbiAgICAgIHRoaXMubWxDb250ZXh0Q2FjaGUucHVzaCh7IG9wdGlvbnM6IG9wdGlvbnNPckRldmljZSwgbWxDb250ZXh0IH0pO1xuICAgICAgcmV0dXJuIG1sQ29udGV4dDtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcmVnaXN0ZXJNTENvbnRleHQoc2Vzc2lvbklkOiBudW1iZXIsIG1sQ29udGV4dDogTUxDb250ZXh0KTogdm9pZCB7XG4gICAgdGhpcy5tbENvbnRleHRCeVNlc3Npb25JZC5zZXQoc2Vzc2lvbklkLCBtbENvbnRleHQpO1xuICAgIGxldCBzZXNzaW9uSWRzID0gdGhpcy5zZXNzaW9uSWRzQnlNTENvbnRleHQuZ2V0KG1sQ29udGV4dCk7XG4gICAgaWYgKCFzZXNzaW9uSWRzKSB7XG4gICAgICBzZXNzaW9uSWRzID0gbmV3IFNldCgpO1xuICAgICAgdGhpcy5zZXNzaW9uSWRzQnlNTENvbnRleHQuc2V0KG1sQ29udGV4dCwgc2Vzc2lvbklkcyk7XG4gICAgfVxuICAgIHNlc3Npb25JZHMuYWRkKHNlc3Npb25JZCk7XG5cbiAgICBpZiAodGhpcy50ZW1wb3JhcnlHcmFwaElucHV0cy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnNlc3Npb25HcmFwaElucHV0cy5zZXQoc2Vzc2lvbklkLCB0aGlzLnRlbXBvcmFyeUdyYXBoSW5wdXRzKTtcbiAgICAgIHRoaXMudGVtcG9yYXJ5R3JhcGhJbnB1dHMgPSBbXTtcbiAgICB9XG4gICAgaWYgKHRoaXMudGVtcG9yYXJ5R3JhcGhPdXRwdXRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuc2Vzc2lvbkdyYXBoT3V0cHV0cy5zZXQoc2Vzc2lvbklkLCB0aGlzLnRlbXBvcmFyeUdyYXBoT3V0cHV0cyk7XG4gICAgICB0aGlzLnRlbXBvcmFyeUdyYXBoT3V0cHV0cyA9IFtdO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBvblJlbGVhc2VTZXNzaW9uKHNlc3Npb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5zZXNzaW9uR3JhcGhJbnB1dHMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgdGhpcy5zZXNzaW9uR3JhcGhPdXRwdXRzLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIGNvbnN0IG1sQ29udGV4dCA9IHRoaXMubWxDb250ZXh0QnlTZXNzaW9uSWQuZ2V0KHNlc3Npb25JZCkhO1xuICAgIGlmICghbWxDb250ZXh0KSB7XG4gICAgICAvLyBDdXJyZW50IHNlc3Npb24gaXMgbm90IGEgV2ViTk4gc2Vzc2lvbi5cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy50ZW5zb3JNYW5hZ2VyLnJlbGVhc2VUZW5zb3JzRm9yU2Vzc2lvbihzZXNzaW9uSWQpO1xuICAgIHRoaXMubWxDb250ZXh0QnlTZXNzaW9uSWQuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgY29uc3Qgc2Vzc2lvbklkcyA9IHRoaXMuc2Vzc2lvbklkc0J5TUxDb250ZXh0LmdldChtbENvbnRleHQpITtcbiAgICBzZXNzaW9uSWRzLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIGlmIChzZXNzaW9uSWRzLnNpemUgPT09IDApIHtcbiAgICAgIHRoaXMuc2Vzc2lvbklkc0J5TUxDb250ZXh0LmRlbGV0ZShtbENvbnRleHQpO1xuICAgICAgY29uc3QgbWxDb250ZXh0SW5kZXggPSB0aGlzLm1sQ29udGV4dENhY2hlLmZpbmRJbmRleCgoZW50cnkpID0+IGVudHJ5Lm1sQ29udGV4dCA9PT0gbWxDb250ZXh0KTtcbiAgICAgIGlmIChtbENvbnRleHRJbmRleCAhPT0gLTEpIHtcbiAgICAgICAgdGhpcy5tbENvbnRleHRDYWNoZS5zcGxpY2UobWxDb250ZXh0SW5kZXgsIDEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRNTENvbnRleHQoc2Vzc2lvbklkOiBudW1iZXIpOiBNTENvbnRleHQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLm1sQ29udGV4dEJ5U2Vzc2lvbklkLmdldChzZXNzaW9uSWQpO1xuICB9XG5cbiAgcHVibGljIHJlc2VydmVUZW5zb3JJZCgpOiBUZW5zb3JJZCB7XG4gICAgcmV0dXJuIHRoaXMudGVuc29yTWFuYWdlci5yZXNlcnZlVGVuc29ySWQoKTtcbiAgfVxuXG4gIHB1YmxpYyByZWxlYXNlVGVuc29ySWQodGVuc29ySWQ6IFRlbnNvcklkKTogdm9pZCB7XG4gICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJOTl0gcmVsZWFzZVRlbnNvcklkIHt0ZW5zb3JJZDogJHt0ZW5zb3JJZH19YCk7XG4gICAgdGhpcy50ZW5zb3JNYW5hZ2VyLnJlbGVhc2VUZW5zb3JJZCh0ZW5zb3JJZCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZW5zdXJlVGVuc29yKFxuICAgIHNlc3Npb25JZDogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICAgIHRlbnNvcklkOiBUZW5zb3JJZCxcbiAgICBvbm54RGF0YVR5cGU6IERhdGFUeXBlLFxuICAgIGRpbWVuc2lvbnM6IG51bWJlcltdLFxuICAgIGNvcHlPbGQ6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8TUxUZW5zb3I+IHtcbiAgICBjb25zdCB3ZWJubkRhdGFUeXBlID0gb25ueERhdGFUeXBlVG9XZWJubkRhdGFUeXBlLmdldChvbm54RGF0YVR5cGUpO1xuICAgIGlmICghd2Vibm5EYXRhVHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBPTk5YIGRhdGEgdHlwZTogJHtvbm54RGF0YVR5cGV9YCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnRlbnNvck1hbmFnZXIuZW5zdXJlVGVuc29yKFxuICAgICAgc2Vzc2lvbklkID8/IHRoaXMuY3VycmVudFNlc3Npb25JZCxcbiAgICAgIHRlbnNvcklkLFxuICAgICAgd2Vibm5EYXRhVHlwZSxcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgICBjb3B5T2xkLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgY3JlYXRlVGVtcG9yYXJ5VGVuc29yKFxuICAgIHNlc3Npb25JZDogbnVtYmVyLFxuICAgIG9ubnhEYXRhVHlwZTogRGF0YVR5cGUsXG4gICAgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiBQcm9taXNlPFRlbnNvcklkPiB7XG4gICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJOTl0gY3JlYXRlVGVtcG9yYXJ5VGVuc29yIHtvbm54RGF0YVR5cGU6ICR7b25ueERhdGFUeXBlfSwgc2hhcGU6ICR7c2hhcGV9fWApO1xuICAgIGNvbnN0IGRhdGFUeXBlID0gb25ueERhdGFUeXBlVG9XZWJubkRhdGFUeXBlLmdldChvbm54RGF0YVR5cGUpO1xuICAgIGlmICghZGF0YVR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgT05OWCBkYXRhIHR5cGU6ICR7b25ueERhdGFUeXBlfWApO1xuICAgIH1cbiAgICBjb25zdCB0ZW5zb3JJZCA9IHRoaXMudGVuc29yTWFuYWdlci5yZXNlcnZlVGVuc29ySWQoKTtcbiAgICBhd2FpdCB0aGlzLnRlbnNvck1hbmFnZXIuZW5zdXJlVGVuc29yKHNlc3Npb25JZCwgdGVuc29ySWQsIGRhdGFUeXBlLCBzaGFwZSwgZmFsc2UpO1xuICAgIGNvbnN0IHRlbnNvcklkcyA9IHRoaXMudGVtcG9yYXJ5U2Vzc2lvblRlbnNvcklkcy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIXRlbnNvcklkcykge1xuICAgICAgdGhpcy50ZW1wb3JhcnlTZXNzaW9uVGVuc29ySWRzLnNldChzZXNzaW9uSWQsIFt0ZW5zb3JJZF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0ZW5zb3JJZHMucHVzaCh0ZW5zb3JJZCk7XG4gICAgfVxuICAgIHJldHVybiB0ZW5zb3JJZDtcbiAgfVxuXG4gIHB1YmxpYyB1cGxvYWRUZW5zb3IodGVuc29ySWQ6IFRlbnNvcklkLCBkYXRhOiBVaW50OEFycmF5KTogdm9pZCB7XG4gICAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gICAgaWYgKCF3YXNtLnNob3VsZFRyYW5zZmVyVG9NTFRlbnNvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUcnlpbmcgdG8gdXBsb2FkIHRvIGEgTUxUZW5zb3Igd2hpbGUgc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yIGlzIGZhbHNlJyk7XG4gICAgfVxuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViTk5dIHVwbG9hZFRlbnNvciB7dGVuc29ySWQ6ICR7dGVuc29ySWR9LCBkYXRhOiAke2RhdGEuYnl0ZUxlbmd0aH19YCk7XG4gICAgdGhpcy50ZW5zb3JNYW5hZ2VyLnVwbG9hZCh0ZW5zb3JJZCwgZGF0YSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZG93bmxvYWRUZW5zb3IodGVuc29ySWQ6IFRlbnNvcklkLCBkc3RCdWZmZXI6IEFycmF5QnVmZmVyVmlldyB8IEFycmF5QnVmZmVyKTogUHJvbWlzZTx1bmRlZmluZWQ+IHtcbiAgICByZXR1cm4gdGhpcy50ZW5zb3JNYW5hZ2VyLmRvd25sb2FkKHRlbnNvcklkLCBkc3RCdWZmZXIpO1xuICB9XG5cbiAgcHVibGljIGNyZWF0ZU1MVGVuc29yRG93bmxvYWRlcih0ZW5zb3JJZDogVGVuc29ySWQsIHR5cGU6IFRlbnNvci5NTFRlbnNvckRhdGFUeXBlcyk6ICgpID0+IFByb21pc2U8VGVuc29yLkRhdGFUeXBlPiB7XG4gICAgcmV0dXJuIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLnRlbnNvck1hbmFnZXIuZG93bmxvYWQodGVuc29ySWQpO1xuICAgICAgcmV0dXJuIGNyZWF0ZVZpZXcoZGF0YSwgdHlwZSk7XG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3Rlck1MVGVuc29yKHNlc3Npb25JZDogbnVtYmVyLCB0ZW5zb3I6IE1MVGVuc29yLCBvbm54RGF0YVR5cGU6IERhdGFUeXBlLCBkaW1lbnNpb25zOiBudW1iZXJbXSk6IFRlbnNvcklkIHtcbiAgICBjb25zdCB3ZWJubkRhdGFUeXBlID0gb25ueERhdGFUeXBlVG9XZWJubkRhdGFUeXBlLmdldChvbm54RGF0YVR5cGUpO1xuICAgIGlmICghd2Vibm5EYXRhVHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBPTk5YIGRhdGEgdHlwZTogJHtvbm54RGF0YVR5cGV9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgaWQgPSB0aGlzLnRlbnNvck1hbmFnZXIucmVnaXN0ZXJUZW5zb3Ioc2Vzc2lvbklkLCB0ZW5zb3IsIHdlYm5uRGF0YVR5cGUsIGRpbWVuc2lvbnMpO1xuICAgIExPR19ERUJVRyhcbiAgICAgICd2ZXJib3NlJyxcbiAgICAgICgpID0+XG4gICAgICAgIGBbV2ViTk5dIHJlZ2lzdGVyTUxUZW5zb3Ige3RlbnNvcjogJHt0ZW5zb3J9LCBkYXRhVHlwZTogJHt3ZWJubkRhdGFUeXBlfSwgZGltZW5zaW9uczogJHtcbiAgICAgICAgICBkaW1lbnNpb25zXG4gICAgICAgIH19IC0+IHt0ZW5zb3JJZDogJHtpZH19YCxcbiAgICApO1xuICAgIHJldHVybiBpZDtcbiAgfVxuXG4gIC8vIFJlZ2lzdGVyIGEgV2ViTk4gQ29uc3RhbnQgb3BlcmFuZCBmcm9tIGV4dGVybmFsIGRhdGEuXG4gIHB1YmxpYyByZWdpc3Rlck1MQ29uc3RhbnQoXG4gICAgZXh0ZXJuYWxGaWxlUGF0aDogc3RyaW5nLFxuICAgIGRhdGFPZmZzZXQ6IG51bWJlcixcbiAgICBkYXRhTGVuZ3RoOiBudW1iZXIsXG4gICAgYnVpbGRlcjogTUxHcmFwaEJ1aWxkZXIsXG4gICAgZGVzYzogTUxPcGVyYW5kRGVzY3JpcHRvcixcbiAgICBtb3VudGVkRmlsZXM6IE1hcDxzdHJpbmcsIFVpbnQ4QXJyYXk+IHwgdW5kZWZpbmVkLFxuICAgIHNob3VsZENvbnZlcnRJbnQ2NFRvSW50MzIgPSBmYWxzZSxcbiAgKTogTUxPcGVyYW5kIHtcbiAgICAvLyBJZiBhdmFpbGFibGUsIFwiTW9kdWxlLk1vdW50ZWRGaWxlc1wiIGlzIGEgTWFwIGZvciBhbGwgcHJlbG9hZGVkIGZpbGVzLlxuICAgIGlmICghbW91bnRlZEZpbGVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4dGVybmFsIG1vdW50ZWQgZmlsZXMgYXJlIG5vdCBhdmFpbGFibGUuJyk7XG4gICAgfVxuXG4gICAgbGV0IGZpbGVQYXRoID0gZXh0ZXJuYWxGaWxlUGF0aDtcbiAgICBpZiAoZXh0ZXJuYWxGaWxlUGF0aC5zdGFydHNXaXRoKCcuLycpKSB7XG4gICAgICBmaWxlUGF0aCA9IGV4dGVybmFsRmlsZVBhdGguc3Vic3RyaW5nKDIpO1xuICAgIH1cbiAgICBjb25zdCBmaWxlRGF0YSA9IG1vdW50ZWRGaWxlcy5nZXQoZmlsZVBhdGgpO1xuICAgIGlmICghZmlsZURhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmlsZSB3aXRoIG5hbWUgJHtmaWxlUGF0aH0gbm90IGZvdW5kIGluIHByZWxvYWRlZCBmaWxlcy5gKTtcbiAgICB9XG5cbiAgICBpZiAoZGF0YU9mZnNldCArIGRhdGFMZW5ndGggPiBmaWxlRGF0YS5ieXRlTGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ091dCBvZiBib3VuZHM6IGRhdGEgb2Zmc2V0IGFuZCBsZW5ndGggZXhjZWVkIHRoZSBleHRlcm5hbCBmaWxlIGRhdGEgc2l6ZS4nKTtcbiAgICB9XG5cbiAgICBjb25zdCBidWZmZXIgPSBmaWxlRGF0YS5zbGljZShkYXRhT2Zmc2V0LCBkYXRhT2Zmc2V0ICsgZGF0YUxlbmd0aCkuYnVmZmVyO1xuICAgIGxldCBidWZmZXJWaWV3OiBBcnJheUJ1ZmZlclZpZXc7XG4gICAgc3dpdGNoIChkZXNjLmRhdGFUeXBlKSB7XG4gICAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgICAgYnVmZmVyVmlldyA9IG5ldyBGbG9hdDMyQXJyYXkoYnVmZmVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdmbG9hdDE2JzpcbiAgICAgICAgYnVmZmVyVmlldyA9XG4gICAgICAgICAgdHlwZW9mIEZsb2F0MTZBcnJheSAhPT0gJ3VuZGVmaW5lZCcgJiYgRmxvYXQxNkFycmF5LmZyb20gPyBuZXcgRmxvYXQxNkFycmF5KGJ1ZmZlcikgOiBuZXcgVWludDE2QXJyYXkoYnVmZmVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpbnQzMic6XG4gICAgICAgIGJ1ZmZlclZpZXcgPSBuZXcgSW50MzJBcnJheShidWZmZXIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3VpbnQzMic6XG4gICAgICAgIGJ1ZmZlclZpZXcgPSBuZXcgVWludDMyQXJyYXkoYnVmZmVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpbnQ2NCc6XG4gICAgICAgIGlmIChzaG91bGRDb252ZXJ0SW50NjRUb0ludDMyKSB7XG4gICAgICAgICAgLy8gSW50NjQgaXMgbm90IHN1cHBvcnRlZCBieSBjdXJyZW50IGNvbnRleHQsIHVzZSBpbnQzMiBpbnN0ZWFkLlxuICAgICAgICAgIGNvbnN0IGludDMyQnVmZmVyID0gY29udmVydERhdGFUb0ludDMyKG5ldyBVaW50OEFycmF5KGJ1ZmZlciksICdpbnQ2NCcpO1xuICAgICAgICAgIGJ1ZmZlclZpZXcgPSBuZXcgSW50MzJBcnJheShpbnQzMkJ1ZmZlci5idWZmZXIpO1xuICAgICAgICAgIGRlc2MuZGF0YVR5cGUgPSAnaW50MzInO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJ1ZmZlclZpZXcgPSBuZXcgQmlnSW50NjRBcnJheShidWZmZXIpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndWludDY0JzpcbiAgICAgICAgYnVmZmVyVmlldyA9IG5ldyBCaWdVaW50NjRBcnJheShidWZmZXIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2ludDgnOlxuICAgICAgICBidWZmZXJWaWV3ID0gbmV3IEludDhBcnJheShidWZmZXIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2ludDQnOlxuICAgICAgY2FzZSAndWludDQnOlxuICAgICAgY2FzZSAndWludDgnOlxuICAgICAgICBidWZmZXJWaWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHtkZXNjLmRhdGFUeXBlfSBpbiBjcmVhdGluZyBXZWJOTiBDb25zdGFudCBmcm9tIGV4dGVybmFsIGRhdGEuYCk7XG4gICAgfVxuXG4gICAgTE9HX0RFQlVHKFxuICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgKCkgPT5cbiAgICAgICAgYFtXZWJOTl0gcmVnaXN0ZXJNTENvbnN0YW50IHtkYXRhVHlwZTogJHtkZXNjLmRhdGFUeXBlfSwgc2hhcGU6ICR7ZGVzYy5zaGFwZX19fSAke1xuICAgICAgICAgIHNob3VsZENvbnZlcnRJbnQ2NFRvSW50MzIgPyAnKE5vdGU6IGl0IHdhcyBpbnQ2NCBkYXRhIHR5cGUgYW5kIHJlZ2lzdGVyZWQgdG8gaW50MzIgYXMgd29ya2Fyb3VuZCknIDogJydcbiAgICAgICAgfWAsXG4gICAgKTtcblxuICAgIHJldHVybiBidWlsZGVyLmNvbnN0YW50KGRlc2MsIGJ1ZmZlclZpZXcpO1xuICB9XG5cbiAgcHVibGljIHJlZ2lzdGVyR3JhcGhJbnB1dChpbnB1dE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMudGVtcG9yYXJ5R3JhcGhJbnB1dHMucHVzaChpbnB1dE5hbWUpO1xuICB9XG5cbiAgcHVibGljIHJlZ2lzdGVyR3JhcGhPdXRwdXQob3V0cHV0TmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy50ZW1wb3JhcnlHcmFwaE91dHB1dHMucHVzaChvdXRwdXROYW1lKTtcbiAgfVxuXG4gIHB1YmxpYyBpc0dyYXBoSW5wdXQoc2Vzc2lvbklkOiBudW1iZXIsIGlucHV0TmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgaW5wdXROYW1lcyA9IHRoaXMuc2Vzc2lvbkdyYXBoSW5wdXRzLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICghaW5wdXROYW1lcykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gaW5wdXROYW1lcy5pbmNsdWRlcyhpbnB1dE5hbWUpO1xuICB9XG5cbiAgcHVibGljIGlzR3JhcGhPdXRwdXQoc2Vzc2lvbklkOiBudW1iZXIsIG91dHB1dE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG91dHB1dE5hbWVzID0gdGhpcy5zZXNzaW9uR3JhcGhPdXRwdXRzLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICghb3V0cHV0TmFtZXMpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIG91dHB1dE5hbWVzLmluY2x1ZGVzKG91dHB1dE5hbWUpO1xuICB9XG5cbiAgcHVibGljIGlzR3JhcGhJbnB1dE91dHB1dFR5cGVTdXBwb3J0ZWQoc2Vzc2lvbklkOiBudW1iZXIsIHR5cGU6IFRlbnNvci5UeXBlLCBpc0lucHV0ID0gdHJ1ZSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLm1sQ29udGV4dEJ5U2Vzc2lvbklkLmdldChzZXNzaW9uSWQpO1xuICAgIGNvbnN0IGRhdGFUeXBlID0gb25ueERhdGFUeXBlVG9XZWJubkRhdGFUeXBlLmdldCh0ZW5zb3JEYXRhVHlwZVN0cmluZ1RvRW51bSh0eXBlKSk7XG5cbiAgICBpZiAodHlwZW9mIGRhdGFUeXBlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChpc0lucHV0KSB7XG4gICAgICByZXR1cm4gISFjb250ZXh0Py5vcFN1cHBvcnRMaW1pdHMoKS5pbnB1dC5kYXRhVHlwZXMuaW5jbHVkZXMoZGF0YVR5cGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gISFjb250ZXh0Py5vcFN1cHBvcnRMaW1pdHMoKS5vdXRwdXQuZGF0YVR5cGVzLmluY2x1ZGVzKGRhdGFUeXBlKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZmx1c2goKTogdm9pZCB7XG4gICAgLy8gVW5saWtlIHRoZSBXZWJHUFUgYmFja2VuZCwgdGhlIFdlYk5OIGJhY2tlbmQgZG9lcyBub3QgbmVlZCB0byBmbHVzaCBhbnkgcGVuZGluZyBvcGVyYXRpb25zLlxuICB9XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uL3RlbnNvci12aWV3JztcblxuaW1wb3J0IHsgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9vcHMvY29tbW9uJztcblxuZXhwb3J0IHR5cGUgU2Vzc2lvblN0YXRlID0gJ2RlZmF1bHQnIHwgJ2NhcHR1cmluZycgfCAncmVwbGF5aW5nJztcblxuZXhwb3J0IGVudW0gR3B1RGF0YVR5cGUge1xuICBkZWZhdWx0ID0gMCxcbiAgdXBsb2FkID0gMSxcbiAgcHJvZmlsZSA9IDIsXG59XG5leHBvcnQgdHlwZSBHcHVEYXRhSWQgPSBudW1iZXI7XG5cbmV4cG9ydCB0eXBlIEdwdUFyY2hpdGVjdHVyZSA9ICdhbXBlcmUnIHwgJ2dlbi0xMmxwJztcbmV4cG9ydCB0eXBlIEdwdVZlbmRvciA9ICdhbWQnIHwgJ2ludGVsJyB8ICdudmlkaWEnO1xuZXhwb3J0IGludGVyZmFjZSBBZGFwdGVySW5mbyB7XG4gIGlzQXJjaGl0ZWN0dXJlOiAoYXJjaGl0ZWN0dXJlOiBHcHVBcmNoaXRlY3R1cmUpID0+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+O1xuICB2YXI8d29ya2dyb3VwPiB0aHJlYWRfc3VtOiBhcnJheTxmMzIsICR7V0d9PjtcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dEhlbHBlcnMpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoW1dHLCAxLCAxXSl9XG4gICAgbGV0IGJhdGNoSWR4ID0gd29ya2dyb3VwX2lkLnogLyB1bmlmb3Jtcy5udW1faGVhZHM7XG4gICAgbGV0IGhlYWRJZHggPSB3b3JrZ3JvdXBfaWQueiAlIHVuaWZvcm1zLm51bV9oZWFkcztcbiAgICBsZXQgc2VxdWVuY2VfbGVuZ3RoID0gdW5pZm9ybXMuc2VxdWVuY2VfbGVuZ3RoO1xuICAgIHZhciB0b3RhbF9zZXF1ZW5jZV9sZW5ndGggPSB1bmlmb3Jtcy50b3RhbF9zZXF1ZW5jZV9sZW5ndGg7XG4gICAgJHtpbml0VmFyU3R1YihzZXFMZW5zSW5wdXRIZWxwZXIsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dEhlbHBlciwgZmFsc2UpfVxuICAgIGxldCBsb2NhbF9vZmZzZXQgPSBsb2NhbF9pZHggKiB1bmlmb3Jtcy5lbGVtZW50c19wZXJfdGhyZWFkO1xuICAgIGxldCBvZmZzZXQgPSAoZ2xvYmFsX2lkeCAvICR7V0d9KSAqIHVuaWZvcm1zLnRvdGFsX3NlcXVlbmNlX2xlbmd0aCArIGxvY2FsX29mZnNldDtcbiAgICBsZXQgc2VxX2NhdXNhbF9sZW5ndGggPSAke3NlcUxlbnMgPyAndTMyKHBhc3Rfc2VxdWVuY2VfbGVuZ3RoICsgd29ya2dyb3VwX2lkLnkgKyAxKScgOiAndG90YWxfc2VxdWVuY2VfbGVuZ3RoJ307XG4gICAgdmFyIHRocmVhZF9tYXhfdmVjdG9yID0gJHtmMzJUeXBlfSgtMy40MDI4MjNlKzM4Zik7XG4gICAgZm9yICh2YXIgaTogdTMyID0gMDsgaSA8IHVuaWZvcm1zLmVsZW1lbnRzX3Blcl90aHJlYWQgJiYgaSArIGxvY2FsX29mZnNldCA8IHNlcV9jYXVzYWxfbGVuZ3RoOyBpKyspIHtcbiAgICAgIHRocmVhZF9tYXhfdmVjdG9yID0gbWF4KCR7ZjMyVHlwZX0oeFtvZmZzZXQgKyBpXSksIHRocmVhZF9tYXhfdmVjdG9yKTtcbiAgICB9XG4gICAgdGhyZWFkX21heFtsb2NhbF9pZHhdID0gJHsoKCkgPT4ge1xuICAgICAgc3dpdGNoIChjb21wb25lbnRzKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICByZXR1cm4gJ3RocmVhZF9tYXhfdmVjdG9yJztcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHJldHVybiAnbWF4KHRocmVhZF9tYXhfdmVjdG9yLngsIHRocmVhZF9tYXhfdmVjdG9yLnkpJztcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHJldHVybiAnbWF4KG1heCh0aHJlYWRfbWF4X3ZlY3Rvci54LCB0aHJlYWRfbWF4X3ZlY3Rvci55KSwgbWF4KHRocmVhZF9tYXhfdmVjdG9yLnosIHRocmVhZF9tYXhfdmVjdG9yLncpKSc7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBjb21wb25lbnRzOiAke2NvbXBvbmVudHN9YCk7XG4gICAgICB9XG4gICAgfSkoKX07XG4gICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgdmFyIG1heF92YWx1ZSA9ICBmMzIoLTMuNDAyODIzZSszOGYpO1xuICAgIGZvciAodmFyIGkgPSAwdTsgaSA8ICR7V0d9OyBpKyspIHtcbiAgICAgIG1heF92YWx1ZSA9IG1heCh0aHJlYWRfbWF4W2ldLCBtYXhfdmFsdWUpO1xuICAgIH1cblxuICAgIHZhciBzdW1fdmVjdG9yID0gJHtmMzJUeXBlfSgwKTtcbiAgICBmb3IgKHZhciBpOiB1MzIgPSAwOyBpIDwgdW5pZm9ybXMuZWxlbWVudHNfcGVyX3RocmVhZCAmJiBpICsgbG9jYWxfb2Zmc2V0IDwgc2VxX2NhdXNhbF9sZW5ndGg7IGkrKykge1xuICAgICAgc3VtX3ZlY3RvciArPSBleHAoJHtmMzJUeXBlfSh4W29mZnNldCArIGldKSAtIG1heF92YWx1ZSk7XG4gICAgfVxuICAgIHRocmVhZF9zdW1bbG9jYWxfaWR4XSA9ICR7KCgpID0+IHtcbiAgICAgIHN3aXRjaCAoY29tcG9uZW50cykge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgcmV0dXJuICdzdW1fdmVjdG9yJztcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHJldHVybiAnc3VtX3ZlY3Rvci54ICsgc3VtX3ZlY3Rvci55JztcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHJldHVybiAnc3VtX3ZlY3Rvci54ICsgc3VtX3ZlY3Rvci55ICsgc3VtX3ZlY3Rvci56ICsgc3VtX3ZlY3Rvci53JztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGNvbXBvbmVudHM6ICR7Y29tcG9uZW50c31gKTtcbiAgICAgIH1cbiAgICB9KSgpfTtcbiAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICB2YXIgc3VtOiBmMzIgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwdTsgaSA8ICR7V0d9OyBpKyspIHtcbiAgICAgIHN1bSArPSB0aHJlYWRfc3VtW2ldO1xuICAgIH1cblxuICAgIGlmIChzdW0gPT0gMCkge1xuICAgICAgZm9yICh2YXIgaTogdTMyID0gMDsgaSA8IHVuaWZvcm1zLmVsZW1lbnRzX3Blcl90aHJlYWQgJiYgaSArIGxvY2FsX29mZnNldCA8IHNlcV9jYXVzYWxfbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgeFtvZmZzZXQgKyBpXSA9ICR7aW5wdXRIZWxwZXIudHlwZS52YWx1ZX0oJHtlbGVtVmFsdWVUeXBlfSgxLjApIC8gJHtlbGVtVmFsdWVUeXBlfShzZXFfY2F1c2FsX2xlbmd0aCkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKHZhciBpOiB1MzIgPSAwOyBpIDwgdW5pZm9ybXMuZWxlbWVudHNfcGVyX3RocmVhZCAmJiBpICsgbG9jYWxfb2Zmc2V0IDwgc2VxX2NhdXNhbF9sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZjMyaW5wdXQgPSAke2YzMlR5cGV9KHhbb2Zmc2V0ICsgaV0pO1xuICAgICAgICB4W29mZnNldCArIGldID0gJHtpbnB1dEhlbHBlci50eXBlLnZhbHVlfShleHAoZjMyaW5wdXQgLSBtYXhfdmFsdWUpIC8gc3VtKTtcbiAgICAgIH1cbiAgICB9XG4gICAgICAke1xuICAgICAgICBzZXFMZW5zXG4gICAgICAgICAgPyBgXG4gICAgICAgIGZvciAodmFyIHRvdGFsX3NlcV9pZDogdTMyID0gc2VxX2NhdXNhbF9sZW5ndGg7IHRvdGFsX3NlcV9pZCArIGxvY2FsX29mZnNldCA8IHVuaWZvcm1zLnRvdGFsX3NlcXVlbmNlX2xlbmd0aDsgdG90YWxfc2VxX2lkKyspIHtcbiAgICAgICAgICB4W29mZnNldCArIHRvdGFsX3NlcV9pZF0gPSAke2lucHV0SGVscGVyLnR5cGUudmFsdWV9KCR7ZWxlbVZhbHVlVHlwZX0oMCkpO1xuICAgICAgICB9YFxuICAgICAgICAgIDogJydcbiAgICAgIH07XG4gIH1gO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0F0dGVudGlvblByb2JzU29mdG1heCcsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7V0d9OyR7ZGF0YVR5cGV9OyR7Y29tcG9uZW50c31gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW10sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IDEsIHk6IHNlcXVlbmNlTGVuZ3RoLCB6OiBiYXRjaFNpemUgKiBudW1IZWFkcyB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICB9O1xufTtcblxuY29uc3QgY3JlYXRlQXR0ZW50aW9uUHJvYnNQcm9ncmFtSW5mbyA9IChcbiAgb3V0cHV0Q291bnQ6IG51bWJlcixcbiAgcTogVGVuc29yVmlldyxcbiAga2V5OiBUZW5zb3JWaWV3LFxuICBwYXN0S2V5OiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICBhdHRlbnRpb25CaWFzOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICBwYXJhbWV0ZXJzOiBBdHRlbnRpb25QYXJhbWV0ZXJzLFxuICBwYXN0U2VxdWVuY2VMZW5ndGg6IG51bWJlcixcbiAgc2VxTGVuczogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbiAgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0OiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuKSA9PiB7XG4gIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGggPSBwYXN0U2VxdWVuY2VMZW5ndGggKyBwYXJhbWV0ZXJzLmt2U2VxdWVuY2VMZW5ndGg7XG4gIGNvbnN0IHByb2JzU2hhcGUgPSBbcGFyYW1ldGVycy5iYXRjaFNpemUsIHBhcmFtZXRlcnMubnVtSGVhZHMsIHBhcmFtZXRlcnMuc2VxdWVuY2VMZW5ndGgsIHRvdGFsU2VxdWVuY2VMZW5ndGhdO1xuICBjb25zdCBwcmVzZW50S2V5ID0gb3V0cHV0Q291bnQgPiAxICYmIHBhc3RLZXk7XG4gIGNvbnN0IGt2TnVtSGVhZHMgPSBwYXJhbWV0ZXJzLmt2TnVtSGVhZHMgPyBwYXJhbWV0ZXJzLmt2TnVtSGVhZHMgOiBwYXJhbWV0ZXJzLm51bUhlYWRzO1xuICBjb25zdCBwcmVzZW50S2V5U2hhcGUgPSBwcmVzZW50S2V5XG4gICAgPyBbcGFyYW1ldGVycy5iYXRjaFNpemUsIGt2TnVtSGVhZHMsIHRvdGFsU2VxdWVuY2VMZW5ndGgsIHBhcmFtZXRlcnMuaGVhZFNpemVdXG4gICAgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IG5SZXBzID0gcGFyYW1ldGVycy5uUmVwcyA/IHBhcmFtZXRlcnMublJlcHMgOiAxO1xuICAvLyBUT0RPOiBoYW5kbGUgbWFza1xuXG4gIGNvbnN0IGFscGhhID0gcGFyYW1ldGVycy5zY2FsZSA9PT0gMCA/IDEuMCAvIE1hdGguc3FydChwYXJhbWV0ZXJzLmhlYWRTaXplKSA6IHBhcmFtZXRlcnMuc2NhbGU7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKHBhcmFtZXRlcnMuaGVhZFNpemUpO1xuICBjb25zdCB2ZWN0b3JpemVkSGVhZFNpemUgPSBwYXJhbWV0ZXJzLmhlYWRTaXplIC8gY29tcG9uZW50cztcbiAgY29uc3QgVElMRV9TSVpFID0gMTI7XG4gIGNvbnN0IGRpc3BhdGNoID0ge1xuICAgIHg6IE1hdGguY2VpbCh0b3RhbFNlcXVlbmNlTGVuZ3RoIC8gVElMRV9TSVpFKSxcbiAgICB5OiBNYXRoLmNlaWwocGFyYW1ldGVycy5zZXF1ZW5jZUxlbmd0aCAvIFRJTEVfU0laRSksXG4gICAgejogcGFyYW1ldGVycy5iYXRjaFNpemUgKiBwYXJhbWV0ZXJzLm51bUhlYWRzLFxuICB9O1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtZXRlcnMuc2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogdmVjdG9yaXplZEhlYWRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHRvdGFsU2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1ldGVycy5udW1IZWFkcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbWV0ZXJzLmhlYWRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogYWxwaGEgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFzdFNlcXVlbmNlTGVuZ3RoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtZXRlcnMua3ZTZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBuUmVwcyB9LFxuICBdO1xuICAvLyBGZWVkIHBhc3RLZXkgdG8gdGhlIHNoYWRlci1jb2RlIG9ubHkgaWYgaXQgaXMgbm9uLXplcm8gYW5kIHByZXNlbnRLZXkgaXMgYmVpbmcgcHJvZHVjZWRcbiAgY29uc3QgZmVlZFBhc3RLZXkgPSBwcmVzZW50S2V5ICYmIHBhc3RLZXkgJiYgU2hhcGVVdGlsLnNpemUocGFzdEtleS5kaW1zKSA+IDA7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWyd0eXBlJywgJ3R5cGUnXTtcbiAgaWYgKGZlZWRQYXN0S2V5KSB7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgndHlwZScpO1xuICB9XG4gIGlmIChhdHRlbnRpb25CaWFzKSB7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgndHlwZScpO1xuICB9XG4gIGlmIChzZXFMZW5zKSB7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgndHlwZScpO1xuICB9XG4gIGlmICh0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgY29uc3Qgb3V0cHV0cyA9IFt7IGRpbXM6IHByb2JzU2hhcGUsIGRhdGFUeXBlOiBxLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9XTtcbiAgaWYgKHByZXNlbnRLZXkpIHtcbiAgICBvdXRwdXRzLnB1c2goeyBkaW1zOiBwcmVzZW50S2V5U2hhcGUhLCBkYXRhVHlwZTogcS5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHQgfSk7XG4gIH1cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgcUlucHV0ID0gaW5wdXRWYXJpYWJsZSgncScsIHEuZGF0YVR5cGUsIHEuZGltcywgY29tcG9uZW50cyk7XG4gICAgY29uc3Qga0lucHV0ID0gaW5wdXRWYXJpYWJsZSgna2V5Jywga2V5LmRhdGFUeXBlLCBrZXkuZGltcywgY29tcG9uZW50cyk7XG4gICAgY29uc3QgaW5wdXRWYXJzID0gW3FJbnB1dCwga0lucHV0XTtcbiAgICBpZiAoZmVlZFBhc3RLZXkpIHtcbiAgICAgIGNvbnN0IHBhc3RLZXlJbnB1dCA9IGlucHV0VmFyaWFibGUoJ3Bhc3Rfa2V5JywgcGFzdEtleS5kYXRhVHlwZSwgcGFzdEtleS5kaW1zLCBjb21wb25lbnRzKTtcbiAgICAgIGlucHV0VmFycy5wdXNoKHBhc3RLZXlJbnB1dCk7XG4gICAgfVxuICAgIGlmIChhdHRlbnRpb25CaWFzKSB7XG4gICAgICBpbnB1dFZhcnMucHVzaChpbnB1dFZhcmlhYmxlKCdhdHRlbnRpb25fYmlhcycsIGF0dGVudGlvbkJpYXMuZGF0YVR5cGUsIGF0dGVudGlvbkJpYXMuZGltcykpO1xuICAgIH1cbiAgICBjb25zdCBzZXFMZW5zSW5wdXRWYXJpYWJsZSA9IHNlcUxlbnMgPyBpbnB1dFZhcmlhYmxlKCdzZXFfbGVucycsIHNlcUxlbnMuZGF0YVR5cGUsIHNlcUxlbnMuZGltcykgOiB1bmRlZmluZWQ7XG4gICAgaWYgKHNlcUxlbnNJbnB1dFZhcmlhYmxlKSB7XG4gICAgICBpbnB1dFZhcnMucHVzaChzZXFMZW5zSW5wdXRWYXJpYWJsZSk7XG4gICAgfVxuICAgIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFZhcmlhYmxlID0gdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0XG4gICAgICA/IGlucHV0VmFyaWFibGUoJ3RvdGFsX3NlcXVlbmNlX2xlbmd0aF9pbnB1dCcsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dC5kYXRhVHlwZSwgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LmRpbXMpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0VmFyaWFibGUpIHtcbiAgICAgIGlucHV0VmFycy5wdXNoKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFZhcmlhYmxlKTtcbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIHEuZGF0YVR5cGUsIHByb2JzU2hhcGUpO1xuICAgIGNvbnN0IG91dHB1dFZhcnMgPSBbb3V0cHV0XTtcbiAgICBpZiAocHJlc2VudEtleSkge1xuICAgICAgb3V0cHV0VmFycy5wdXNoKG91dHB1dFZhcmlhYmxlKCdwcmVzZW50X2tleScsIHEuZGF0YVR5cGUsIHByZXNlbnRLZXlTaGFwZSEsIGNvbXBvbmVudHMpKTtcbiAgICB9XG4gICAgY29uc3QgZjMyVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoRGF0YVR5cGUuZmxvYXQsIGNvbXBvbmVudHMpO1xuXG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnTScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdLJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ04nLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnbnVtX2hlYWRzJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2hlYWRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdhbHBoYScsIHR5cGU6ICdmMzInIGFzIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUgfSxcbiAgICAgIHsgbmFtZTogJ3Bhc3Rfc2VxdWVuY2VfbGVuZ3RoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2t2X3NlcXVlbmNlX2xlbmd0aCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICduX3JlcHMnLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG4gICAgcmV0dXJuIGBcbiAgY29uc3QgVElMRV9TSVpFID0gJHtUSUxFX1NJWkV9dTtcblxuICB2YXI8d29ya2dyb3VwPiB0aWxlUTogYXJyYXk8JHtxSW5wdXQudHlwZS5zdG9yYWdlfSwgJHtUSUxFX1NJWkUgKiBUSUxFX1NJWkV9PjtcbiAgdmFyPHdvcmtncm91cD4gdGlsZUs6IGFycmF5PCR7cUlucHV0LnR5cGUuc3RvcmFnZX0sICR7VElMRV9TSVpFICogVElMRV9TSVpFfT47XG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJzLCAuLi5vdXRwdXRWYXJzKX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFtUSUxFX1NJWkUsIFRJTEVfU0laRSwgMV0pfVxuICAgIC8vIHggaG9sZHMgdGhlIE4gYW5kIHkgaG9sZHMgdGhlIE1cbiAgICBsZXQgaGVhZElkeCA9IHdvcmtncm91cF9pZC56ICUgdW5pZm9ybXMubnVtX2hlYWRzO1xuICAgIGxldCBrdkhlYWRJZHggPSAke25SZXBzID09PSAxID8gJ2hlYWRJZHgnIDogJ2hlYWRJZHggLyB1bmlmb3Jtcy5uX3JlcHMnfTtcbiAgICBsZXQga3ZfbnVtX2hlYWRzID0gJHtuUmVwcyA9PT0gMSA/ICd1bmlmb3Jtcy5udW1faGVhZHMnIDogJ3VuaWZvcm1zLm51bV9oZWFkcyAvIHVuaWZvcm1zLm5fcmVwcyd9O1xuICAgIGxldCBiYXRjaElkeCA9IHdvcmtncm91cF9pZC56IC8gdW5pZm9ybXMubnVtX2hlYWRzO1xuICAgIGxldCBtID0gd29ya2dyb3VwX2lkLnkgKiBUSUxFX1NJWkU7XG4gICAgbGV0IG4gPSB3b3JrZ3JvdXBfaWQueCAqIFRJTEVfU0laRTtcbiAgICBsZXQgc2VxdWVuY2VfbGVuZ3RoID0gdW5pZm9ybXMuTTtcbiAgICB2YXIgdG90YWxfc2VxdWVuY2VfbGVuZ3RoID0gdW5pZm9ybXMuTjtcbiAgICAke2luaXRWYXJTdHViKHNlcUxlbnNJbnB1dFZhcmlhYmxlLCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRWYXJpYWJsZSwgdHJ1ZSl9XG4gICAgbGV0IGFic0t2SGVhZElkeCA9IGJhdGNoSWR4ICoga3ZfbnVtX2hlYWRzICsga3ZIZWFkSWR4O1xuICAgIGxldCBxT2Zmc2V0ID0gd29ya2dyb3VwX2lkLnogKiB1bmlmb3Jtcy5NICogdW5pZm9ybXMuSyArIG0gKiB1bmlmb3Jtcy5LO1xuICAgICR7ZmVlZFBhc3RLZXkgJiYgcHJlc2VudEtleSA/ICdsZXQgcGFzdEtleU9mZnNldCA9IGFic0t2SGVhZElkeCAqIHVuaWZvcm1zLnBhc3Rfc2VxdWVuY2VfbGVuZ3RoICogdW5pZm9ybXMuSzsnIDogJyd9O1xuICAgIGxldCBrT2Zmc2V0ID0gYWJzS3ZIZWFkSWR4ICogdW5pZm9ybXMua3Zfc2VxdWVuY2VfbGVuZ3RoICogdW5pZm9ybXMuSztcbiAgICAke3ByZXNlbnRLZXkgPyAnbGV0IHByZXNlbnRLZXlPZmZzZXQgPSBhYnNLdkhlYWRJZHggKiB1bmlmb3Jtcy5OICogdW5pZm9ybXMuSzsnIDogJyd9XG4gICAgdmFyIHZhbHVlID0gJHtmMzJUeXBlfSgwKTtcbiAgICBmb3IgKHZhciB3OiB1MzIgPSAwdTsgdyA8IHVuaWZvcm1zLks7IHcgKz0gVElMRV9TSVpFKSB7XG4gICAgICBpZiAoZ2xvYmFsX2lkLnkgPCB1bmlmb3Jtcy5NICYmIHcgKyBsb2NhbF9pZC54IDwgdW5pZm9ybXMuSykge1xuICAgICAgICB0aWxlUVtUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgbG9jYWxfaWQueF0gPSBxW3FPZmZzZXQgKyBsb2NhbF9pZC55ICogdW5pZm9ybXMuSyArIHcgKyBsb2NhbF9pZC54XTtcbiAgICAgIH1cbiAgICAgIGlmIChuICsgbG9jYWxfaWQueSA8IHVuaWZvcm1zLk4gJiYgdyArIGxvY2FsX2lkLnggPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHZhciBpZHggPSBUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgbG9jYWxfaWQueDtcbiAgICAgICR7KCgpID0+IHtcbiAgICAgICAgaWYgKGZlZWRQYXN0S2V5ICYmIHByZXNlbnRLZXkpIHtcbiAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgICBpZiAobiArIGxvY2FsX2lkLnkgPCBwYXN0X3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRpbGVLW2lkeF0gPSBwYXN0X2tleVtwYXN0S2V5T2Zmc2V0ICsgKG4gKyBsb2NhbF9pZC55KSAqIHVuaWZvcm1zLksgKyB3ICsgbG9jYWxfaWQueF07XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAobiArIGxvY2FsX2lkLnkgLSBwYXN0X3NlcXVlbmNlX2xlbmd0aCA8IHVuaWZvcm1zLmt2X3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRpbGVLW2lkeF0gPSBrZXlba09mZnNldCArIChuICsgbG9jYWxfaWQueSAtIHBhc3Rfc2VxdWVuY2VfbGVuZ3RoKSAqIHVuaWZvcm1zLksgKyB3ICsgbG9jYWxfaWQueF07XG4gICAgICAgICAgICAgIH1gO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgaWYgKG4gKyBsb2NhbF9pZC55IDwgdW5pZm9ybXMua3Zfc2VxdWVuY2VfbGVuZ3RoKSB7XG4gICAgICAgICAgICB0aWxlS1tpZHhdID0ga2V5W2tPZmZzZXQgKyAobiArIGxvY2FsX2lkLnkpICogdW5pZm9ybXMuSyArIHcgKyBsb2NhbF9pZC54XTtcbiAgICAgICAgICB9YDtcbiAgICAgICAgfVxuICAgICAgfSkoKX1cbiAgICAgICR7XG4gICAgICAgIHByZXNlbnRLZXlcbiAgICAgICAgICA/IGBpZiAobiArIGxvY2FsX2lkLnkgPCBwcmVzZW50X3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgICBwcmVzZW50X2tleVtwcmVzZW50S2V5T2Zmc2V0ICsgKG4gKyBsb2NhbF9pZC55KSAqIHVuaWZvcm1zLksgKyB3ICsgbG9jYWxfaWQueF0gPSB0aWxlS1tpZHhdO1xuICAgICAgfWBcbiAgICAgICAgICA6ICcnXG4gICAgICB9XG4gICAgICB9XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgIGZvciAodmFyIGs6IHUzMiA9IDB1OyBrIDwgVElMRV9TSVpFICYmIHcrayA8IHVuaWZvcm1zLks7IGsrKykge1xuICAgICAgICAgIHZhbHVlICs9ICR7ZjMyVHlwZX0odGlsZVFbVElMRV9TSVpFICogbG9jYWxfaWQueSArIGtdICogdGlsZUtbVElMRV9TSVpFICogbG9jYWxfaWQueCArIGtdKTtcbiAgICAgIH1cblxuICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICAgIH1cblxuICAgIGlmIChnbG9iYWxfaWQueSA8IHVuaWZvcm1zLk0gJiYgZ2xvYmFsX2lkLnggPCB0b3RhbF9zZXF1ZW5jZV9sZW5ndGgpIHtcbiAgICAgIGxldCBoZWFkT2Zmc2V0ID0gd29ya2dyb3VwX2lkLnogKiB1bmlmb3Jtcy5NICogdW5pZm9ybXMuTjtcbiAgICAgIGxldCBvdXRwdXRJZHggPSBoZWFkT2Zmc2V0ICsgZ2xvYmFsX2lkLnkgKiB1bmlmb3Jtcy5OICsgZ2xvYmFsX2lkLng7XG4gICAgICB2YXIgc3VtOiBmMzIgPSAkeygoKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoY29tcG9uZW50cykge1xuICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHJldHVybiAndmFsdWUnO1xuICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIHJldHVybiAndmFsdWUueCArIHZhbHVlLnknO1xuICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgIHJldHVybiAndmFsdWUueCArIHZhbHVlLnkgKyB2YWx1ZS56ICsgdmFsdWUudyc7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgY29tcG9uZW50czogJHtjb21wb25lbnRzfWApO1xuICAgICAgICB9XG4gICAgICB9KSgpfTtcbiAgICAgICAgb3V0cHV0W291dHB1dElkeF0gPSAke291dHB1dC50eXBlLnZhbHVlfSAoc3VtICogdW5pZm9ybXMuYWxwaGEpICsgJHtcbiAgICAgICAgICBhdHRlbnRpb25CaWFzID8gJ2F0dGVudGlvbl9iaWFzW291dHB1dElkeF0nIDogJzAuMCdcbiAgICAgICAgfTtcbiAgICB9XG4gIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdBdHRlbnRpb25Qcm9icycsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2NvbXBvbmVudHN9OyR7YXR0ZW50aW9uQmlhcyAhPT0gdW5kZWZpbmVkfTske3Bhc3RLZXkgIT09IHVuZGVmaW5lZH07JHtvdXRwdXRDb3VudH1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXMsXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoeyBvdXRwdXRzLCBkaXNwYXRjaEdyb3VwOiBkaXNwYXRjaCwgcHJvZ3JhbVVuaWZvcm1zIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmNvbnN0IGNyZWF0ZVZ4QXR0ZW50aW9uU2NvcmVQcm9ncmFtSW5mbyA9IChcbiAgb3V0cHV0Q291bnQ6IG51bWJlcixcbiAgcHJvYnM6IFRlbnNvclZpZXcsXG4gIHY6IFRlbnNvclZpZXcsXG4gIHBhc3RWYWx1ZTogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbiAgcGFyYW1zOiBBdHRlbnRpb25QYXJhbWV0ZXJzLFxuICBwYXN0U2VxdWVuY2VMZW5ndGg6IG51bWJlcixcbiAgc2VxTGVuczogVGVuc29yVmlldyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0OiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuKSA9PiB7XG4gIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGggPSBwYXN0U2VxdWVuY2VMZW5ndGggKyBwYXJhbXMua3ZTZXF1ZW5jZUxlbmd0aDtcbiAgY29uc3QgblJlcHMgPSBwYXJhbXMublJlcHMgPyBwYXJhbXMublJlcHMgOiAxO1xuICBjb25zdCByZXBlYXRlZFZIaWRkZW5TaXplID0gcGFyYW1zLnZIaWRkZW5TaXplICogblJlcHM7XG4gIGNvbnN0IHByZXNlbnRWYWx1ZSA9IG91dHB1dENvdW50ID4gMSAmJiBwYXN0VmFsdWU7XG4gIGNvbnN0IGt2TnVtSGVhZHMgPSBwYXJhbXMua3ZOdW1IZWFkcyA/IHBhcmFtcy5rdk51bUhlYWRzIDogcGFyYW1zLm51bUhlYWRzO1xuICBjb25zdCBwcmVzZW50VmFsdWVTaGFwZSA9IHByZXNlbnRWYWx1ZVxuICAgID8gW3BhcmFtcy5iYXRjaFNpemUsIGt2TnVtSGVhZHMsIHRvdGFsU2VxdWVuY2VMZW5ndGgsIHBhcmFtcy5oZWFkU2l6ZV1cbiAgICA6IHVuZGVmaW5lZDtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbcGFyYW1zLmJhdGNoU2l6ZSwgcGFyYW1zLnNlcXVlbmNlTGVuZ3RoLCByZXBlYXRlZFZIaWRkZW5TaXplXTtcbiAgY29uc3QgVElMRV9TSVpFID0gMTI7XG4gIGNvbnN0IGRpc3BhdGNoID0ge1xuICAgIHg6IE1hdGguY2VpbChwYXJhbXMudkhlYWRTaXplIC8gVElMRV9TSVpFKSxcbiAgICB5OiBNYXRoLmNlaWwocGFyYW1zLnNlcXVlbmNlTGVuZ3RoIC8gVElMRV9TSVpFKSxcbiAgICB6OiBwYXJhbXMuYmF0Y2hTaXplICogcGFyYW1zLm51bUhlYWRzLFxuICB9O1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1zLnNlcXVlbmNlTGVuZ3RoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHRvdGFsU2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1zLnZIZWFkU2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbXMubnVtSGVhZHMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1zLmhlYWRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHJlcGVhdGVkVkhpZGRlblNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFzdFNlcXVlbmNlTGVuZ3RoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtcy5rdlNlcXVlbmNlTGVuZ3RoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG5SZXBzIH0sXG4gIF07XG4gIC8vIEZlZWQgcGFzdFZhbHVlIHRvIHRoZSBzaGFkZXItY29kZSBvbmx5IGlmIGl0IGlzIG5vbi1lbXB0eSBhbmQgcHJlc2VudFZhbHVlIGlzIGJlaW5nIHByb2R1Y2VkXG4gIGNvbnN0IGZlZWRQYXN0VmFsdWUgPSBwcmVzZW50VmFsdWUgJiYgcGFzdFZhbHVlICYmIFNoYXBlVXRpbC5zaXplKHBhc3RWYWx1ZS5kaW1zKSA+IDA7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWyd0eXBlJywgJ3R5cGUnXTtcbiAgaWYgKGZlZWRQYXN0VmFsdWUpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgaWYgKHNlcUxlbnMpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgaWYgKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCkge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBjb25zdCBvdXRwdXRzID0gW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBwcm9icy5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHQgfV07XG4gIGlmIChwcmVzZW50VmFsdWUpIHtcbiAgICBvdXRwdXRzLnB1c2goeyBkaW1zOiBwcmVzZW50VmFsdWVTaGFwZSEsIGRhdGFUeXBlOiBwcm9icy5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHQgfSk7XG4gIH1cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgcHJvYnNIZWxwZXIgPSBpbnB1dFZhcmlhYmxlKCdwcm9icycsIHByb2JzLmRhdGFUeXBlLCBwcm9icy5kaW1zKTtcbiAgICBjb25zdCB2SGVscGVyID0gaW5wdXRWYXJpYWJsZSgndicsIHYuZGF0YVR5cGUsIHYuZGltcyk7XG4gICAgY29uc3QgaW5wdXRWYXJzID0gW3Byb2JzSGVscGVyLCB2SGVscGVyXTtcbiAgICBpZiAoZmVlZFBhc3RWYWx1ZSkge1xuICAgICAgaW5wdXRWYXJzLnB1c2goaW5wdXRWYXJpYWJsZSgncGFzdF92YWx1ZScsIHBhc3RWYWx1ZS5kYXRhVHlwZSwgcGFzdFZhbHVlLmRpbXMpKTtcbiAgICB9XG4gICAgY29uc3Qgc2VxTGVuc0lucHV0VmFyaWFibGUgPSBzZXFMZW5zID8gaW5wdXRWYXJpYWJsZSgnc2VxX2xlbnMnLCBzZXFMZW5zLmRhdGFUeXBlLCBzZXFMZW5zLmRpbXMpIDogdW5kZWZpbmVkO1xuICAgIGlmIChzZXFMZW5zKSB7XG4gICAgICBpbnB1dFZhcnMucHVzaChzZXFMZW5zSW5wdXRWYXJpYWJsZSEpO1xuICAgIH1cbiAgICBjb25zdCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRWYXJpYWJsZSA9IHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFxuICAgICAgPyBpbnB1dFZhcmlhYmxlKCd0b3RhbF9zZXF1ZW5jZV9sZW5ndGhfaW5wdXQnLCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQuZGF0YVR5cGUsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dC5kaW1zKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgaWYgKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCkge1xuICAgICAgaW5wdXRWYXJzLnB1c2godG90YWxTZXF1ZW5jZUxlbmd0aElucHV0VmFyaWFibGUhKTtcbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIHByb2JzLmRhdGFUeXBlLCBvdXRwdXRTaGFwZSk7XG4gICAgY29uc3Qgb3V0cHV0VmFycyA9IFtvdXRwdXRdO1xuICAgIGlmIChwcmVzZW50VmFsdWUpIHtcbiAgICAgIG91dHB1dFZhcnMucHVzaChvdXRwdXRWYXJpYWJsZSgncHJlc2VudF92YWx1ZScsIHByb2JzLmRhdGFUeXBlLCBwcmVzZW50VmFsdWVTaGFwZSEpKTtcbiAgICB9XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnTScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdLJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ04nLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnbnVtX2hlYWRzJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2hlYWRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICd2X2hpZGRlbl9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3Bhc3Rfc2VxdWVuY2VfbGVuZ3RoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2t2X3NlcXVlbmNlX2xlbmd0aCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICduX3JlcHMnLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG4gICAgcmV0dXJuIGBcbiAgY29uc3QgVElMRV9TSVpFID0gJHtUSUxFX1NJWkV9dTtcbiAgdmFyPHdvcmtncm91cD4gdGlsZVE6IGFycmF5PCR7cHJvYnNIZWxwZXIudHlwZS52YWx1ZX0sICR7VElMRV9TSVpFICogVElMRV9TSVpFfT47XG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGVWOiBhcnJheTwke3Byb2JzSGVscGVyLnR5cGUudmFsdWV9LCAke1RJTEVfU0laRSAqIFRJTEVfU0laRX0+O1xuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFycywgLi4ub3V0cHV0VmFycyl9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydChbVElMRV9TSVpFLCBUSUxFX1NJWkUsIDFdKX1cbiAgIGxldCBoZWFkSWR4ID0gd29ya2dyb3VwX2lkLnogJSB1bmlmb3Jtcy5udW1faGVhZHM7XG4gICBsZXQgYmF0Y2hJZHggPSB3b3JrZ3JvdXBfaWQueiAvIHVuaWZvcm1zLm51bV9oZWFkcztcbiAgIGxldCBrdkhlYWRJZHggPSAke25SZXBzID09PSAxID8gJ2hlYWRJZHgnIDogJ2hlYWRJZHggLyB1bmlmb3Jtcy5uX3JlcHMnfTtcbiAgIGxldCBrdl9udW1faGVhZHMgPSAke25SZXBzID09PSAxID8gJ3VuaWZvcm1zLm51bV9oZWFkcycgOiAndW5pZm9ybXMubnVtX2hlYWRzIC8gdW5pZm9ybXMubl9yZXBzJ307XG4gICBsZXQgbSA9IGdsb2JhbF9pZC55O1xuICAgbGV0IG4gPSBnbG9iYWxfaWQueDtcbiAgIGxldCBzZXF1ZW5jZV9sZW5ndGggPSB1bmlmb3Jtcy5NO1xuICAgdmFyIHRvdGFsX3NlcXVlbmNlX2xlbmd0aCA9IHVuaWZvcm1zLks7XG4gICAke2luaXRWYXJTdHViKHNlcUxlbnNJbnB1dFZhcmlhYmxlLCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRWYXJpYWJsZSwgdHJ1ZSl9XG4gICBsZXQgb2Zmc2V0QSA9IHdvcmtncm91cF9pZC56ICogdW5pZm9ybXMuTSAqIHVuaWZvcm1zLksgKyBtICogdW5pZm9ybXMuSztcbiAgIGxldCBhYnNLdkhlYWRJZHggPSBiYXRjaElkeCAqIGt2X251bV9oZWFkcyArIGt2SGVhZElkeDsgLy8ga3ZIZWFkSWR4IGlzIHJlbGF0aXZlIHRvIHRoZSBiYXRjaFxuICAgJHtmZWVkUGFzdFZhbHVlICYmIHByZXNlbnRWYWx1ZSA/ICdsZXQgcGFzdFZhbHVlT2Zmc2V0ID0gYWJzS3ZIZWFkSWR4ICogdW5pZm9ybXMuTiAqIHVuaWZvcm1zLnBhc3Rfc2VxdWVuY2VfbGVuZ3RoICsgbjsnIDogJyd9O1xuICAgbGV0IHZPZmZzZXQgPSBhYnNLdkhlYWRJZHggKiB1bmlmb3Jtcy5OICogdW5pZm9ybXMua3Zfc2VxdWVuY2VfbGVuZ3RoICsgbjtcbiAgICR7cHJlc2VudFZhbHVlID8gJ2xldCBwcmVzZW50VmFsdWVPZmZzZXQgPSBhYnNLdkhlYWRJZHggKiB1bmlmb3Jtcy5OICogdW5pZm9ybXMuSyArIG47JyA6ICcnfVxuICAgdmFyIHZhbHVlID0gJHtwcm9ic0hlbHBlci50eXBlLnN0b3JhZ2V9KDApO1xuICAgZm9yICh2YXIgdzogdTMyID0gMHU7IHcgPCB1bmlmb3Jtcy5LOyB3ICs9IFRJTEVfU0laRSkge1xuICAgICAgaWYgKG0gPCB1bmlmb3Jtcy5NICYmIHcgKyBsb2NhbF9pZC54IDwgdW5pZm9ybXMuSykge1xuICAgICAgICB0aWxlUVtUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgbG9jYWxfaWQueF0gPSBwcm9ic1tvZmZzZXRBICsgdyArIGxvY2FsX2lkLnhdO1xuICAgICAgfVxuICAgICAgaWYgKG4gPCB1bmlmb3Jtcy5OICYmIHcgKyBsb2NhbF9pZC55IDwgdW5pZm9ybXMuSykge1xuICAgICAgICB2YXIgaWR4ID0gVElMRV9TSVpFICogbG9jYWxfaWQueSArIGxvY2FsX2lkLng7XG4gICAgICAgICR7KCgpID0+IHtcbiAgICAgICAgICBpZiAoZmVlZFBhc3RWYWx1ZSAmJiBwcmVzZW50VmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgIGlmICh3ICsgbG9jYWxfaWQueSA8IHBhc3Rfc2VxdWVuY2VfbGVuZ3RoKSB7XG4gICAgICAgICAgdGlsZVZbaWR4XSA9IHBhc3RfdmFsdWVbcGFzdFZhbHVlT2Zmc2V0ICsgKHcgKyBsb2NhbF9pZC55KSAqIHVuaWZvcm1zLk5dO1xuICAgICAgICB9IGVsc2UgaWYgKHcgKyBsb2NhbF9pZC55IC0gcGFzdF9zZXF1ZW5jZV9sZW5ndGggPCB1bmlmb3Jtcy5rdl9zZXF1ZW5jZV9sZW5ndGgpIHtcbiAgICAgICAgICB0aWxlVltpZHhdID0gdlt2T2Zmc2V0ICsgKHcgKyBsb2NhbF9pZC55IC0gcGFzdF9zZXF1ZW5jZV9sZW5ndGgpICogdW5pZm9ybXMuTl07XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICBpZiAodyArIGxvY2FsX2lkLnkgPCB1bmlmb3Jtcy5rdl9zZXF1ZW5jZV9sZW5ndGgpIHtcbiAgICAgICAgICAgICAgdGlsZVZbaWR4XSA9IHZbdk9mZnNldCArICh3ICsgbG9jYWxfaWQueSkgKiB1bmlmb3Jtcy5OXTtcbiAgICAgICAgICAgIH1gO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKX1cbiAgICAgICAgJHtcbiAgICAgICAgICBwcmVzZW50VmFsdWVcbiAgICAgICAgICAgID8gYFxuICAgICAgICAgICAgaWYgKHcgKyBsb2NhbF9pZC55IDwgcHJlc2VudF9zZXF1ZW5jZV9sZW5ndGgpIHtcbiAgICAgICAgICBwcmVzZW50X3ZhbHVlW3ByZXNlbnRWYWx1ZU9mZnNldCArICh3ICsgbG9jYWxfaWQueSkgKiB1bmlmb3Jtcy5OXSA9IHRpbGVWW2lkeF07XG4gICAgICAgIH1gXG4gICAgICAgICAgICA6ICcnXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICAgICBmb3IgKHZhciBrOiB1MzIgPSAwdTsgayA8IFRJTEVfU0laRSAmJiB3K2sgPCB0b3RhbF9zZXF1ZW5jZV9sZW5ndGg7IGsrKykge1xuICAgICAgIHZhbHVlICs9IHRpbGVRW1RJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBrXSAqIHRpbGVWW1RJTEVfU0laRSAqIGsgKyBsb2NhbF9pZC54XTtcbiAgICAgfVxuICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICB9XG5cbiAgIC8vIHdlIG5lZWQgdG8gdHJhbnNwb3NlIG91dHB1dCBmcm9tIEJOU0hfdiB0byBCU05EX3ZcbiAgIGlmIChtIDwgdW5pZm9ybXMuTSAmJiBuIDwgdW5pZm9ybXMuTikge1xuICAgICBsZXQgb3V0cHV0SWR4ID0gYmF0Y2hJZHggKiB1bmlmb3Jtcy5NICogdW5pZm9ybXMudl9oaWRkZW5fc2l6ZSArIG0gKiB1bmlmb3Jtcy52X2hpZGRlbl9zaXplXG4gICAgICAgKyBoZWFkSWR4ICogdW5pZm9ybXMuTiArIG47XG4gICAgIG91dHB1dFtvdXRwdXRJZHhdID0gdmFsdWU7XG4gICB9XG4gIH1gO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0F0dGVudGlvblNjb3JlJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtwYXN0VmFsdWUgIT09IHVuZGVmaW5lZH07JHtvdXRwdXRDb3VudH1gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7IG91dHB1dHMsIGRpc3BhdGNoR3JvdXA6IGRpc3BhdGNoLCBwcm9ncmFtVW5pZm9ybXMgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGFwcGx5QXR0ZW50aW9uID0gKFxuICBjb250ZXh0OiBDb21wdXRlQ29udGV4dCxcbiAgcTogVGVuc29yVmlldyxcbiAgazogVGVuc29yVmlldyxcbiAgdjogVGVuc29yVmlldyxcbiAgX21hc2tJbmRleDogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbiAgX3Bhc3Q6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4gIHBhc3RLZXk6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4gIHBhc3RWYWx1ZTogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbiAgYXR0ZW50aW9uQmlhc0lucHV0OiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICBwYXJhbWV0ZXJzOiBBdHRlbnRpb25QYXJhbWV0ZXJzLFxuICBzZXFMZW5zOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQ6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4pID0+IHtcbiAgLy8gQXNzdW1wdGlvbiBpcyB0aGF0IHByZXNlbnRLZXkvcHJlc2VudFZhbHVlIGV4aXN0cyBvbmx5IGlmIHBhc3RLZXkvcGFzdFZhbHVlIGV4aXN0cy5cbiAgY29uc3Qgb3V0cHV0Q291bnQgPSBNYXRoLm1pbihjb250ZXh0Lm91dHB1dENvdW50LCAxICsgKHBhc3RLZXkgPyAxIDogMCkgKyAocGFzdFZhbHVlID8gMSA6IDApKTtcbiAgY29uc3QgcGFzdFNlcXVlbmNlTGVuZ3RoID0gb3V0cHV0Q291bnQgPiAxID8gcGFyYW1ldGVycy5wYXN0U2VxdWVuY2VMZW5ndGggOiAwO1xuICBjb25zdCB0b3RhbFNlcXVlbmNlTGVuZ3RoID0gcGFzdFNlcXVlbmNlTGVuZ3RoICsgcGFyYW1ldGVycy5rdlNlcXVlbmNlTGVuZ3RoO1xuICBjb25zdCBhdHRlbnRpb25CaWFzID1cbiAgICBhdHRlbnRpb25CaWFzSW5wdXQgJiYgU2hhcGVVdGlsLnNpemUoYXR0ZW50aW9uQmlhc0lucHV0LmRpbXMpID4gMCA/IGF0dGVudGlvbkJpYXNJbnB1dCA6IHVuZGVmaW5lZDtcblxuICBjb25zdCBpbnB1dHNLID0gW3EsIGtdO1xuICBpZiAob3V0cHV0Q291bnQgPiAxICYmIHBhc3RLZXkgJiYgU2hhcGVVdGlsLnNpemUocGFzdEtleS5kaW1zKSA+IDApIHtcbiAgICBpbnB1dHNLLnB1c2gocGFzdEtleSk7XG4gIH1cbiAgaWYgKGF0dGVudGlvbkJpYXMpIHtcbiAgICBpbnB1dHNLLnB1c2goYXR0ZW50aW9uQmlhcyk7XG4gIH1cbiAgaWYgKHNlcUxlbnMpIHtcbiAgICBpbnB1dHNLLnB1c2goc2VxTGVucyk7XG4gIH1cbiAgaWYgKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCkge1xuICAgIGlucHV0c0sucHVzaCh0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQpO1xuICB9XG4gIC8vIFJ1biBBdHRlbnRpb25Qcm9ic1xuICBjb25zdCBwcm9icyA9IGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVBdHRlbnRpb25Qcm9ic1Byb2dyYW1JbmZvKFxuICAgICAgb3V0cHV0Q291bnQsXG4gICAgICBxLFxuICAgICAgayxcbiAgICAgIHBhc3RLZXksXG4gICAgICBhdHRlbnRpb25CaWFzLFxuICAgICAgcGFyYW1ldGVycyxcbiAgICAgIHBhc3RTZXF1ZW5jZUxlbmd0aCxcbiAgICAgIHNlcUxlbnMsXG4gICAgICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQsXG4gICAgKSxcbiAgICB7IGlucHV0czogaW5wdXRzSywgb3V0cHV0czogb3V0cHV0Q291bnQgPiAxID8gWy0xLCAxXSA6IFstMV0gfSxcbiAgKVswXTtcblxuICAvLyBSdW4gU29mdG1heFxuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlSW5QbGFjZVNvZnRtYXhQcm9ncmFtSW5mbyhcbiAgICAgIHByb2JzLFxuICAgICAgcGFyYW1ldGVycy5iYXRjaFNpemUsXG4gICAgICBwYXJhbWV0ZXJzLm51bUhlYWRzLFxuICAgICAgcGFzdFNlcXVlbmNlTGVuZ3RoLFxuICAgICAgcGFyYW1ldGVycy5zZXF1ZW5jZUxlbmd0aCxcbiAgICAgIHRvdGFsU2VxdWVuY2VMZW5ndGgsXG4gICAgICBzZXFMZW5zLFxuICAgICAgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LFxuICAgICksXG4gICAgeyBpbnB1dHM6IHNlcUxlbnMgJiYgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0ID8gW3Byb2JzLCBzZXFMZW5zLCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRdIDogW3Byb2JzXSwgb3V0cHV0czogW10gfSxcbiAgKTtcblxuICAvLyBSdW4gQXR0ZW50aW9uU2NvcmVcbiAgY29uc3QgaW5wdXRzViA9IFtwcm9icywgdl07XG4gIGlmIChvdXRwdXRDb3VudCA+IDEgJiYgcGFzdFZhbHVlICYmIFNoYXBlVXRpbC5zaXplKHBhc3RWYWx1ZS5kaW1zKSA+IDApIHtcbiAgICBpbnB1dHNWLnB1c2gocGFzdFZhbHVlKTtcbiAgfVxuICBpZiAoc2VxTGVucykge1xuICAgIGlucHV0c1YucHVzaChzZXFMZW5zKTtcbiAgfVxuICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0KSB7XG4gICAgaW5wdXRzVi5wdXNoKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCk7XG4gIH1cbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZVZ4QXR0ZW50aW9uU2NvcmVQcm9ncmFtSW5mbyhcbiAgICAgIG91dHB1dENvdW50LFxuICAgICAgcHJvYnMsXG4gICAgICB2LFxuICAgICAgcGFzdFZhbHVlLFxuICAgICAgcGFyYW1ldGVycyxcbiAgICAgIHBhc3RTZXF1ZW5jZUxlbmd0aCxcbiAgICAgIHNlcUxlbnMsXG4gICAgICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQsXG4gICAgKSxcbiAgICB7XG4gICAgICBpbnB1dHM6IGlucHV0c1YsXG4gICAgICBvdXRwdXRzOiBvdXRwdXRDb3VudCA+IDEgPyBbMCwgMl0gOiBbMF0sXG4gICAgfSxcbiAgKTtcbn07XG5cbmNvbnN0IHByZXBhcmUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIHBhcmFtZXRlcnM6IEF0dGVudGlvblBhcmFtZXRlcnMpID0+IHtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbcGFyYW1ldGVycy5iYXRjaFNpemUsIHBhcmFtZXRlcnMubnVtSGVhZHMsIHBhcmFtZXRlcnMuc2VxdWVuY2VMZW5ndGgsIHBhcmFtZXRlcnMuaGVhZFNpemVdO1xuICBjb25zdCBNID0gcGFyYW1ldGVycy5zZXF1ZW5jZUxlbmd0aDtcbiAgY29uc3QgSyA9IHBhcmFtZXRlcnMuaW5wdXRIaWRkZW5TaXplO1xuICBjb25zdCBOID0gcGFyYW1ldGVycy5oZWFkU2l6ZTtcbiAgY29uc3QgVElMRV9TSVpFID0gMTI7XG4gIGNvbnN0IGRpc3BhdGNoID0ge1xuICAgIHg6IE1hdGguY2VpbChwYXJhbWV0ZXJzLmhlYWRTaXplIC8gVElMRV9TSVpFKSxcbiAgICB5OiBNYXRoLmNlaWwocGFyYW1ldGVycy5zZXF1ZW5jZUxlbmd0aCAvIFRJTEVfU0laRSksXG4gICAgejogcGFyYW1ldGVycy5iYXRjaFNpemUgKiBwYXJhbWV0ZXJzLm51bUhlYWRzLFxuICB9O1xuICBjb25zdCBpbnB1dHMgPSBbY29udGV4dC5pbnB1dHNbMF0sIGNvbnRleHQuaW5wdXRzWzFdLCBjb250ZXh0LmlucHV0c1syXV07XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBLIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE4gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1ldGVycy5udW1IZWFkcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbWV0ZXJzLmhlYWRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtZXRlcnMuaGlkZGVuU2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbWV0ZXJzLmhpZGRlblNpemUgKyBwYXJhbWV0ZXJzLmhpZGRlblNpemUgKyBwYXJhbWV0ZXJzLnZIaWRkZW5TaXplIH0sXG4gIF07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3Qgb3V0cHV0USA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXRfcScsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUpO1xuICAgIGNvbnN0IG91dHB1dEsgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0X2snLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlKTtcbiAgICBjb25zdCBvdXRwdXRWID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dF92JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZSk7XG4gICAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMpO1xuICAgIGNvbnN0IHdlaWdodCA9IGlucHV0VmFyaWFibGUoJ3dlaWdodCcsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMpO1xuICAgIGNvbnN0IGJpYXMgPSBpbnB1dFZhcmlhYmxlKCdiaWFzJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcyk7XG4gICAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dC50eXBlLnN0b3JhZ2U7XG5cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdNJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ0snLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnTicsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdudW1faGVhZHMnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnaGVhZF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2hpZGRlbl9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2xkYicsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICBjb25zdCBUSUxFX1NJWkUgPSAke1RJTEVfU0laRX11O1xuICB2YXI8d29ya2dyb3VwPiB0aWxlSW5wdXQ6IGFycmF5PCR7ZGF0YVR5cGV9LCAke1RJTEVfU0laRSAqIFRJTEVfU0laRX0+O1xuICB2YXI8d29ya2dyb3VwPiB0aWxlV2VpZ2h0UTogYXJyYXk8JHtkYXRhVHlwZX0sICR7VElMRV9TSVpFICogVElMRV9TSVpFfT47XG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGVXZWlnaHRLOiBhcnJheTwke2RhdGFUeXBlfSwgJHtUSUxFX1NJWkUgKiBUSUxFX1NJWkV9PjtcbiAgdmFyPHdvcmtncm91cD4gdGlsZVdlaWdodFY6IGFycmF5PCR7ZGF0YVR5cGV9LCAke1RJTEVfU0laRSAqIFRJTEVfU0laRX0+O1xuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCB3ZWlnaHQsIGJpYXMsIG91dHB1dFEsIG91dHB1dEssIG91dHB1dFYpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoW1RJTEVfU0laRSwgVElMRV9TSVpFLCAxXSl9XG4gICAgbGV0IGJhdGNoSW5kZXggPSB3b3JrZ3JvdXBfaWQueiAvIHVuaWZvcm1zLm51bV9oZWFkcztcbiAgICBsZXQgaGVhZE51bWJlciA9IHdvcmtncm91cF9pZC56ICUgdW5pZm9ybXMubnVtX2hlYWRzO1xuICAgIGxldCBtID0gZ2xvYmFsX2lkLnk7XG4gICAgbGV0IG4gPSBnbG9iYWxfaWQueDtcblxuICAgIGxldCBpbnB1dE9mZnNldCA9IGJhdGNoSW5kZXggKiAodW5pZm9ybXMuTSAqIHVuaWZvcm1zLkspICsgbSAqIHVuaWZvcm1zLks7XG4gICAgbGV0IGJpYXNPZmZzZXRRID0gaGVhZE51bWJlciAqIHVuaWZvcm1zLmhlYWRfc2l6ZTtcbiAgICBsZXQgYmlhc09mZnNldEsgPSB1bmlmb3Jtcy5oaWRkZW5fc2l6ZSArIGJpYXNPZmZzZXRRO1xuICAgIGxldCBiaWFzT2Zmc2V0ViA9IHVuaWZvcm1zLmhpZGRlbl9zaXplICsgYmlhc09mZnNldEs7XG5cbiAgICB2YXIgdmFsdWVRID0gJHtkYXRhVHlwZX0oMCk7XG4gICAgdmFyIHZhbHVlSyA9ICR7ZGF0YVR5cGV9KDApO1xuICAgIHZhciB2YWx1ZVYgPSAke2RhdGFUeXBlfSgwKTtcbiAgICBmb3IgKHZhciB3OiB1MzIgPSAwdTsgdyA8IHVuaWZvcm1zLks7IHcgKz0gVElMRV9TSVpFKSB7XG4gICAgICBpZiAobSA8IHVuaWZvcm1zLk0gJiYgdyArIGxvY2FsX2lkLnggPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHRpbGVJbnB1dFtUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgbG9jYWxfaWQueF0gPSBpbnB1dFtpbnB1dE9mZnNldCArIHcgKyBsb2NhbF9pZC54XTtcbiAgICAgIH1cbiAgICAgIGlmIChuIDwgdW5pZm9ybXMuTiAmJiB3ICsgbG9jYWxfaWQueSA8IHVuaWZvcm1zLkspIHtcbiAgICAgICAgbGV0IG9mZnNldCA9IG4gKyAodyArIGxvY2FsX2lkLnkpICogdW5pZm9ybXMubGRiO1xuICAgICAgICB0aWxlV2VpZ2h0UVtUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgbG9jYWxfaWQueF0gPSB3ZWlnaHRbYmlhc09mZnNldFEgKyBvZmZzZXRdO1xuICAgICAgICB0aWxlV2VpZ2h0S1tUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgbG9jYWxfaWQueF0gPSB3ZWlnaHRbYmlhc09mZnNldEsgKyBvZmZzZXRdO1xuICAgICAgICB0aWxlV2VpZ2h0VltUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgbG9jYWxfaWQueF0gPSB3ZWlnaHRbYmlhc09mZnNldFYgKyBvZmZzZXRdO1xuICAgICAgfVxuICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICAgICAgZm9yICh2YXIgazogdTMyID0gMHU7IGs8VElMRV9TSVpFICYmIHcrayA8IHVuaWZvcm1zLks7IGsrKykge1xuICAgICAgICBsZXQgaW5wdXRUaWxlT2Zmc2V0ID0gVElMRV9TSVpFICogbG9jYWxfaWQueSArIGs7XG4gICAgICAgIGxldCB3ZWlnaHRUaWxlT2Zmc2V0ID0gVElMRV9TSVpFICogayArIGxvY2FsX2lkLng7XG4gICAgICAgIHZhbHVlUSArPSB0aWxlSW5wdXRbaW5wdXRUaWxlT2Zmc2V0XSAqIHRpbGVXZWlnaHRRW3dlaWdodFRpbGVPZmZzZXRdO1xuICAgICAgICB2YWx1ZUsgKz0gdGlsZUlucHV0W2lucHV0VGlsZU9mZnNldF0gKiB0aWxlV2VpZ2h0S1t3ZWlnaHRUaWxlT2Zmc2V0XTtcbiAgICAgICAgdmFsdWVWICs9IHRpbGVJbnB1dFtpbnB1dFRpbGVPZmZzZXRdICogdGlsZVdlaWdodFZbd2VpZ2h0VGlsZU9mZnNldF07XG4gICAgICB9XG5cbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgICB9XG5cbiAgICBsZXQgaGVhZE9mZnNldCA9IChtICogdW5pZm9ybXMuTiArIG4pICUgdW5pZm9ybXMuaGVhZF9zaXplO1xuICAgIHZhbHVlUSArPSBiaWFzW2hlYWRPZmZzZXQgKyBiaWFzT2Zmc2V0UV07XG4gICAgdmFsdWVLICs9IGJpYXNbaGVhZE9mZnNldCArIGJpYXNPZmZzZXRLXTtcbiAgICB2YWx1ZVYgKz0gYmlhc1toZWFkT2Zmc2V0ICsgYmlhc09mZnNldFZdO1xuXG4gICAgbGV0IG9mZnNldCA9IHdvcmtncm91cF9pZC56ICogdW5pZm9ybXMuTSAqIHVuaWZvcm1zLk47XG4gICAgaWYgKG0gPCB1bmlmb3Jtcy5NICYmIG4gPCB1bmlmb3Jtcy5OKSB7XG4gICAgICBsZXQgb3V0cHV0SWR4ID0gb2Zmc2V0ICsgbSAqIHVuaWZvcm1zLk4gKyBuO1xuICAgICAgb3V0cHV0X3Fbb3V0cHV0SWR4XSA9IHZhbHVlUTtcbiAgICAgIG91dHB1dF9rW291dHB1dElkeF0gPSB2YWx1ZUs7XG4gICAgICBvdXRwdXRfdltvdXRwdXRJZHhdID0gdmFsdWVWO1xuICAgIH1cbiAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIGNvbnRleHQuY29tcHV0ZShcbiAgICB7XG4gICAgICBuYW1lOiAnQXR0ZW50aW9uUHJlcGFyZScsXG4gICAgICBzaGFkZXJDYWNoZTogeyBpbnB1dERlcGVuZGVuY2llczogWyd0eXBlJywgJ3R5cGUnLCAndHlwZSddIH0sXG4gICAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9LFxuICAgICAgICAgIHsgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHQgfSxcbiAgICAgICAgICB7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUsIGdwdURhdGFUeXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0IH0sXG4gICAgICAgIF0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6IGRpc3BhdGNoLFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9LFxuICAgIHsgaW5wdXRzLCBvdXRwdXRzOiBbLTEsIC0xLCAtMV0gfSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhdHRlbnRpb24gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEF0dGVudGlvbkF0dHJzKTogdm9pZCA9PiB7XG4gIGNvbnN0IHBhcmFtcyA9IHZhbGlkYXRlQXR0ZW50aW9uSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcblxuICBjb25zdCBbcSwgaywgdl0gPSBwcmVwYXJlKGNvbnRleHQsIHBhcmFtcyk7XG5cbiAgcmV0dXJuIGFwcGx5QXR0ZW50aW9uKFxuICAgIGNvbnRleHQsXG4gICAgcSxcbiAgICBrLFxuICAgIHYsXG4gICAgY29udGV4dC5pbnB1dHNbNF0sXG4gICAgdW5kZWZpbmVkLFxuICAgIHVuZGVmaW5lZCxcbiAgICB1bmRlZmluZWQsXG4gICAgY29udGV4dC5pbnB1dHNbNV0sXG4gICAgcGFyYW1zLFxuICApO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgZW52IH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBnZXRNYXhDb21wb25lbnRzLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJhdGNoTm9ybUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBlcHNpbG9uOiBudW1iZXI7XG4gIHJlYWRvbmx5IG1vbWVudHVtOiBudW1iZXI7XG4gIHJlYWRvbmx5IHNwYXRpYWw6IGJvb2xlYW47XG4gIHJlYWRvbmx5IHRyYWluaW5nTW9kZTogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZm9ybWF0OiAnTkhXQycgfCAnTkNIVyc7XG4gIHJlYWRvbmx5IG91dHB1dENvdW50OiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBCYXRjaE5vcm1BdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0JhdGNoTm9ybWFsaXphdGlvbiByZXF1aXJlcyA1IGlucHV0cycpO1xuICB9XG5cbiAgY29uc3QgY2hlY2tTaGFwZUVxdWFsID0gKGFjdHVhbDogcmVhZG9ubHkgbnVtYmVyW10sIGV4cGVjdGVkOiByZWFkb25seSBudW1iZXJbXSwgbWVzc2FnZTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgciA9IGV4cGVjdGVkLmxlbmd0aDtcbiAgICBpZiAociAhPT0gYWN0dWFsLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21lc3NhZ2V9OiBudW0gZGltZW5zaW9ucyAhPSAke3J9YCk7XG4gICAgfVxuICAgIGV4cGVjdGVkLmZvckVhY2goKHYsIGkpID0+IHtcbiAgICAgIGlmICh2ICE9PSBhY3R1YWxbaV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21lc3NhZ2V9OiBkaW1bJHtpfV0gZG8gbm90IG1hdGNoYCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCA+IDEpIHtcbiAgICBjb25zdCBzaGFwZSA9XG4gICAgICBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnXG4gICAgICAgID8gYXR0cmlidXRlcy5zcGF0aWFsXG4gICAgICAgICAgPyBpbnB1dHNbMF0uZGltcy5zbGljZSgtMSlcbiAgICAgICAgICA6IGlucHV0c1swXS5kaW1zLnNsaWNlKC0xKS5jb25jYXQoaW5wdXRzWzBdLmRpbXMuc2xpY2UoMSwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMSkpXG4gICAgICAgIDogaW5wdXRzWzBdLmRpbXMuc2xpY2UoMSwgYXR0cmlidXRlcy5zcGF0aWFsID8gMiA6IHVuZGVmaW5lZCk7XG4gICAgY2hlY2tTaGFwZUVxdWFsKGlucHV0c1sxXS5kaW1zLCBzaGFwZSwgJ0ludmFsaWQgaW5wdXQgc2NhbGUnKTtcbiAgICBjaGVja1NoYXBlRXF1YWwoaW5wdXRzWzJdLmRpbXMsIHNoYXBlLCAnSW52YWxpZCBpbnB1dCBCJyk7XG4gICAgY2hlY2tTaGFwZUVxdWFsKGlucHV0c1szXS5kaW1zLCBzaGFwZSwgJ0ludmFsaWQgaW5wdXQgbWVhbicpO1xuICAgIGNoZWNrU2hhcGVFcXVhbChpbnB1dHNbNF0uZGltcywgc2hhcGUsICdJbnZhbGlkIGlucHV0IHZhcicpO1xuICB9IGVsc2Uge1xuICAgIGNoZWNrU2hhcGVFcXVhbChpbnB1dHNbMV0uZGltcywgWzFdLCAnSW52YWxpZCBpbnB1dCBzY2FsZScpO1xuICAgIGNoZWNrU2hhcGVFcXVhbChpbnB1dHNbMl0uZGltcywgWzFdLCAnSW52YWxpZCBpbnB1dCBCJyk7XG4gICAgY2hlY2tTaGFwZUVxdWFsKGlucHV0c1szXS5kaW1zLCBbMV0sICdJbnZhbGlkIGlucHV0IG1lYW4nKTtcbiAgICBjaGVja1NoYXBlRXF1YWwoaW5wdXRzWzRdLmRpbXMsIFsxXSwgJ0ludmFsaWQgaW5wdXQgdmFyJyk7XG4gIH1cbn07XG5cbmNvbnN0IGNyZWF0ZUJhdGNoTm9ybUluZmVyZW5jZVByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogQmF0Y2hOb3JtQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgeyBlcHNpbG9uLCBzcGF0aWFsLCBmb3JtYXQgfSA9IGF0dHJpYnV0ZXM7XG4gIGNvbnN0IHlTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBjb21wb25lbnRzID0gc3BhdGlhbCA/IGdldE1heENvbXBvbmVudHMoeVNoYXBlW3lTaGFwZS5sZW5ndGggLSAxXSkgOiAxO1xuICBjb25zdCBjQ29tcG9uZW50cyA9IGZvcm1hdCA9PT0gJ05IV0MnICYmIHlTaGFwZS5sZW5ndGggPiAxID8gY29tcG9uZW50cyA6IDE7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZSh5U2hhcGUpIC8gY29tcG9uZW50cztcbiAgLy8gT25seSBzdXBwb3J0IHVuaWZvcm1zIGZvciBvcHNldCB2ZXJzaW9uID49IDkgKHNwYXRpYWwgPSB0cnVlKS5cbiAgY29uc3QgdXNlU2hhcGVzVW5pZm9ybXMgPSBzcGF0aWFsO1xuICBjb25zdCBzaGFwZU9yUmFuayA9IHVzZVNoYXBlc1VuaWZvcm1zID8geVNoYXBlLmxlbmd0aCA6IHlTaGFwZTtcbiAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLCBjb21wb25lbnRzKTtcbiAgY29uc3Qgc2NhbGUgPSBpbnB1dFZhcmlhYmxlKCdzY2FsZScsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMsIGNDb21wb25lbnRzKTtcbiAgY29uc3QgYmlhcyA9IGlucHV0VmFyaWFibGUoJ2JpYXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLCBjQ29tcG9uZW50cyk7XG4gIGNvbnN0IGlucHV0TWVhbiA9IGlucHV0VmFyaWFibGUoJ2lucHV0TWVhbicsIGlucHV0c1szXS5kYXRhVHlwZSwgaW5wdXRzWzNdLmRpbXMsIGNDb21wb25lbnRzKTtcbiAgY29uc3QgaW5wdXRWYXIgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dFZhcicsIGlucHV0c1s0XS5kYXRhVHlwZSwgaW5wdXRzWzRdLmRpbXMsIGNDb21wb25lbnRzKTtcbiAgY29uc3QgeSA9IG91dHB1dFZhcmlhYmxlKCd5JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBzaGFwZU9yUmFuaywgY29tcG9uZW50cyk7XG4gIC8vIFRPRE86IHN1cHBvcnQgaW5wdXRzIHdpdGggZGlmZmVyZW50IGRhdGEgdHlwZS4gQ3VycmVudCB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSBhbGwgaW5wdXRzIGhhdmUgdGhlIHNhbWUgZGF0YSB0eXBlLlxuICAvLyBPdGhlcndpc2UsIHRoZSBzaGFkZXIgY29tcGlsYXRpb24gd2lsbCBmYWlsLlxuICBjb25zdCBjYWxjQ09mZnNldCA9ICgpOiBzdHJpbmcgPT4ge1xuICAgIGxldCBjT2Zmc2V0ID0gJyc7XG4gICAgaWYgKHNwYXRpYWwpIHtcbiAgICAgIGNPZmZzZXQgPSBgbGV0IGNPZmZzZXQgPSAke1xuICAgICAgICB5U2hhcGUubGVuZ3RoID09PSAxXG4gICAgICAgICAgPyAnMHUnXG4gICAgICAgICAgOiBmb3JtYXQgPT09ICdOSFdDJ1xuICAgICAgICAgICAgPyBgb3V0cHV0SW5kaWNlc1ske3lTaGFwZS5sZW5ndGggLSAxfV0gLyAke2NvbXBvbmVudHN9YFxuICAgICAgICAgICAgOiAnb3V0cHV0SW5kaWNlc1sxXSdcbiAgICAgIH07YDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGZvcm1hdCA9PT0gJ05DSFcnKSB7XG4gICAgICAgIGNPZmZzZXQgPSBgXG4gICAgICAgICAgICAke3kuaW5kaWNlc1NldCgnb3V0cHV0SW5kaWNlcycsICcwJywgJzAnKX1cbiAgICAgICAgICAgIGxldCBjT2Zmc2V0ID0gJHt5LmluZGljZXNUb09mZnNldCgnb3V0cHV0SW5kaWNlcycpfTtgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gdXBkYXRlIEMgY2hhbm5lbC5cbiAgICAgICAgY09mZnNldCA9IGB2YXIgY0luZGljZXMgPSAke3NjYWxlLnR5cGUuaW5kaWNlc30oMCk7XG4gICAgICAgICAgICAgICAgICAgICAgIGNJbmRpY2VzWzBdID0gb3V0cHV0SW5kaWNlc1ske3lTaGFwZS5sZW5ndGggLSAxfV07YDtcbiAgICAgICAgLy8gdXBkYXRlIEQxIHggLi4uIHggRG4gY2hhbm5lbHMuXG4gICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc2NhbGUucmFuazsgaSsrKSB7XG4gICAgICAgICAgY09mZnNldCArPSBgY0luZGljZXNbJHtpfV0gPSBvdXRwdXRJbmRpY2VzWyR7aX1dO2A7XG4gICAgICAgIH1cbiAgICAgICAgY09mZnNldCArPSBgbGV0IGNPZmZzZXQgPSAke3NjYWxlLmluZGljZXNUb09mZnNldCgnY0luZGljZXMnKX07YDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGNPZmZzZXQ7XG4gIH07XG4gIGNvbnN0IGdldEluZmVyZW5jZU1vZGVTaGFkZXJTb3VyY2UgPSAoaGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgY29uc3QgZXBzaWxvbiA9ICR7ZXBzaWxvbn07XG4gICR7aGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0U2l6ZScsICd1MzInKS5kZWNsYXJlVmFyaWFibGVzKHgsIHNjYWxlLCBiaWFzLCBpbnB1dE1lYW4sIGlucHV0VmFyLCB5KX1cbiAgJHtoZWxwZXIubWFpblN0YXJ0KCl9XG4gICR7aGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dFNpemUnKX1cbiAgICB2YXIgb3V0cHV0SW5kaWNlcyA9ICR7eS5vZmZzZXRUb0luZGljZXMoYGdsb2JhbF9pZHggKiAke2NvbXBvbmVudHN9YCl9O1xuICAgICR7Y2FsY0NPZmZzZXQoKX1cbiAgICBsZXQgc2NhbGUgPSAke3NjYWxlLmdldEJ5T2Zmc2V0KCdjT2Zmc2V0Jyl9O1xuICAgIGxldCBiaWFzID0gJHtiaWFzLmdldEJ5T2Zmc2V0KCdjT2Zmc2V0Jyl9O1xuICAgIGxldCBpbnB1dE1lYW4gPSAke2lucHV0TWVhbi5nZXRCeU9mZnNldCgnY09mZnNldCcpfTtcbiAgICBsZXQgaW5wdXRWYXIgPSAke2lucHV0VmFyLmdldEJ5T2Zmc2V0KCdjT2Zmc2V0Jyl9O1xuICAgIGxldCB4ID0gJHt4LmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4Jyl9O1xuICAgIGxldCB2YWx1ZSA9ICh4IC0gaW5wdXRNZWFuKSAqIGludmVyc2VTcXJ0KGlucHV0VmFyICsgZXBzaWxvbikgKiBzY2FsZSArIGJpYXM7XG4gICAgJHt5LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3ZhbHVlJyl9XG4gIH1gO1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdCYXRjaE5vcm1hbGl6YXRpb24nLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmVwc2lsb259XyR7YXR0cmlidXRlcy5mb3JtYXR9XyR7c3BhdGlhbH1fJHtjb21wb25lbnRzfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llczogdXNlU2hhcGVzVW5pZm9ybXMgPyBbJ3JhbmsnLCAndHlwZScsICd0eXBlJywgJ3R5cGUnLCAndHlwZSddIDogdW5kZWZpbmVkLFxuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlOiBnZXRJbmZlcmVuY2VNb2RlU2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBpbnB1dHNbMF0uZGltcywgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogdXNlU2hhcGVzVW5pZm9ybXNcbiAgICAgICAgPyBbeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSwgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoeVNoYXBlKV1cbiAgICAgICAgOiBbeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfV0sXG4gICAgfSksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VCYXRjaE5vcm1BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQmF0Y2hOb3JtQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoYXR0cmlidXRlcyBhcyBPbWl0PEJhdGNoTm9ybUF0dHJpYnV0ZXMsIGtleW9mIEF0dHJpYnV0ZVdpdGhDYWNoZUtleT4pO1xuXG5leHBvcnQgY29uc3QgYmF0Y2hOb3JtID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHZvaWQgPT4ge1xuICBjb25zdCB7IGlucHV0cywgb3V0cHV0Q291bnQgfSA9IGNvbnRleHQ7XG4gIGNvbnN0IHVwZGF0ZWRBdHRyaWJ1dGVzID0gcGFyc2VCYXRjaE5vcm1BdHRyaWJ1dGVzKHsgLi4uYXR0cmlidXRlcywgb3V0cHV0Q291bnQgfSk7XG4gIGlmIChlbnYud2ViZ3B1LnZhbGlkYXRlSW5wdXRDb250ZW50KSB7XG4gICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzLCB1cGRhdGVkQXR0cmlidXRlcyk7XG4gIH1cbiAgaWYgKGF0dHJpYnV0ZXMudHJhaW5pbmdNb2RlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdCYXRjaE5vcm1hbGl6YXRpb24gdHJhaW5pbmdNb2RlIGlzIG5vdCBzdXBwb3J0ZWQgeWV0LicpO1xuICB9IGVsc2Uge1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVCYXRjaE5vcm1JbmZlcmVuY2VQcm9ncmFtSW5mbyhpbnB1dHMsIHVwZGF0ZWRBdHRyaWJ1dGVzKSk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gMykge1xuICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgc2hvdWxkIGhhdmUgMyBkaW1lbnNpb25zJyk7XG4gIH1cblxuICBpZiAoIVszMjAsIDY0MCwgMTI4MF0uaW5jbHVkZXMoaW5wdXRzWzBdLmRpbXNbMl0pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdudW1iZXIgb2YgY2hhbm5lbHMgc2hvdWxkIGJlIDMyMCwgNjQwIG9yIDEyODAnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2JpYXMgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAxIGRpbWVuc2lvbnMnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltc1syXSAhPT0gaW5wdXRzWzFdLmRpbXNbMF0pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2xhc3QgZGltZW5zaW9uIG9mIGlucHV0IGFuZCBiaWFzIGFyZSBub3QgdGhlIHNhbWUnKTtcbiAgfVxufTtcblxuY29uc3QgY3JlYXRlQmlhc0FkZFByb2dyYW1JbmZvID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuXG4gIGNvbnN0IGNoYW5uZWxzID0gaW5wdXRzWzBdLmRpbXNbMl07XG4gIC8vIHNpbmNlIGNoYW5uZWwgbnVtYmVyIGNhbiBiZSBvbmx5IDMyMC82NDAvMTI4MCwgaXQncyBhbHdheXMgZGl2aXNhYmxlIGJ5IDRcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIDQ7XG5cbiAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dHNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBkYXRhVHlwZSwgb3V0cHV0U2hhcGUsIDQpO1xuICBjb25zdCBiaWFzID0gaW5wdXRWYXJpYWJsZSgnYmlhcycsIGRhdGFUeXBlLCBbY2hhbm5lbHNdLCA0KTtcbiAgY29uc3QgcmVzaWR1YWwgPSBpbnB1dFZhcmlhYmxlKCdyZXNpZHVhbCcsIGRhdGFUeXBlLCBvdXRwdXRTaGFwZSwgNCk7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBkYXRhVHlwZSwgb3V0cHV0U2hhcGUsIDQpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICBjb25zdCBjaGFubmVscyA9ICR7Y2hhbm5lbHN9dSAvIDQ7XG4gICR7c2hhZGVySGVscGVyLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIGJpYXMsIHJlc2lkdWFsLCBvdXRwdXQpfVxuXG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMob3V0cHV0U2l6ZSl9XG4gICAgbGV0IHZhbHVlID0gJHtpbnB1dC5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpfVxuICAgICAgKyAke2JpYXMuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHggJSBjaGFubmVscycpfSArICR7cmVzaWR1YWwuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKX07XG4gICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAndmFsdWUnKX1cbiAgfWA7XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQmlhc0FkZCcsXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBiaWFzQWRkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUJpYXNBZGRQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cykpO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlLFxuICBVbmlmb3JtRGF0YUVsZW1lbnRUeXBlLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuXG50eXBlIEJ1aWx0aW5GdW5jdGlvbk5hbWUgPSBzdHJpbmc7XG50eXBlIEVsZW1lbnR3aXNlQ3VzdG9tRXhwcmVzc2lvbiA9IChleHByZXNzaW9uOiBzdHJpbmcpID0+IHN0cmluZztcbnR5cGUgRWxlbWVudHdpc2VGdW5jdGlvbkNhbGwgPSBCdWlsdGluRnVuY3Rpb25OYW1lIHwgRWxlbWVudHdpc2VDdXN0b21FeHByZXNzaW9uO1xuXG5jb25zdCBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1TaGFkZXIgPSAoXG4gIHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyLFxuICBkYXRhc2l6ZTogbnVtYmVyLFxuICBpbnB1dERhdGFUeXBlOiBudW1iZXIsXG4gIG91dHB1dERhdGFUeXBlOiBudW1iZXIsXG4gIGZ1bmNDYWxsOiBFbGVtZW50d2lzZUZ1bmN0aW9uQ2FsbCxcbiAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uPzogc3RyaW5nLFxuICBhZGRpdGlvbmFsVW5pZm9ybXNUeXBlPzogVW5pZm9ybXNBcnJheVR5cGUsXG4pOiBzdHJpbmcgPT4ge1xuICBjb25zdCB2ZWNTaXplID0gTWF0aC5jZWlsKGRhdGFzaXplIC8gNCk7XG5cbiAgbGV0IGV4cHJlc3Npb24gPSAnJztcbiAgaWYgKHR5cGVvZiBmdW5jQ2FsbCA9PT0gJ3N0cmluZycpIHtcbiAgICBleHByZXNzaW9uID0gYCR7ZnVuY0NhbGx9KGEpYDtcbiAgfSBlbHNlIHtcbiAgICBleHByZXNzaW9uID0gZnVuY0NhbGwoJ2EnKTtcbiAgfVxuXG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXREYXRhJywgaW5wdXREYXRhVHlwZSwgW3ZlY1NpemVdLCA0KTtcbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dERhdGEnLCBvdXRwdXREYXRhVHlwZSwgW3ZlY1NpemVdLCA0KTtcbiAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW3sgbmFtZTogJ3ZlY19zaXplJywgdHlwZTogJ3UzMicgfV07XG4gIGlmIChhZGRpdGlvbmFsVW5pZm9ybXNUeXBlKSB7XG4gICAgdW5pZm9ybXMucHVzaCguLi5hZGRpdGlvbmFsVW5pZm9ybXNUeXBlKTtcbiAgfVxuXG4gIHJldHVybiBgXG4gICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBvdXRwdXQpfVxuXG4gICR7YWRkaXRpb25hbEltcGxlbWVudGF0aW9uID8/ICcnfVxuXG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLnZlY19zaXplJyl9XG5cbiAgICBsZXQgYSA9ICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKX07XG4gICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCBleHByZXNzaW9uKX1cbiAgfWA7XG59O1xuXG5jb25zdCBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvID0gKFxuICBpbnB1dDogVGVuc29yVmlldyxcbiAgbmFtZTogc3RyaW5nLFxuICBmdW5jQ2FsbDogRWxlbWVudHdpc2VGdW5jdGlvbkNhbGwsXG4gIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbj86IHN0cmluZyxcbiAgY2FjaGVLZXk/OiBzdHJpbmcsXG4gIG91dHB1dERhdGFUeXBlOiBudW1iZXIgPSBpbnB1dC5kYXRhVHlwZSxcbiAgYWRkaXRpb25hbFVuaWZvcm1zPzogUHJvZ3JhbVVuaWZvcm1bXSxcbiAgYWRkaXRpb25hbFVuaWZvcm1zVHlwZT86IFVuaWZvcm1zQXJyYXlUeXBlLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShpbnB1dC5kaW1zKSAvIDQpIH0sXG4gIF07XG4gIGlmIChhZGRpdGlvbmFsVW5pZm9ybXMpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5hZGRpdGlvbmFsVW5pZm9ybXMpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGNhY2hlS2V5LCBpbnB1dERlcGVuZGVuY2llczogWyd0eXBlJ10gfSxcbiAgICBnZXRTaGFkZXJTb3VyY2U6IChzaGFkZXJIZWxwZXIpID0+XG4gICAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1TaGFkZXIoXG4gICAgICAgIHNoYWRlckhlbHBlcixcbiAgICAgICAgU2hhcGVVdGlsLnNpemUoaW5wdXQuZGltcyksXG4gICAgICAgIGlucHV0LmRhdGFUeXBlLFxuICAgICAgICBvdXRwdXREYXRhVHlwZSxcbiAgICAgICAgZnVuY0NhbGwsXG4gICAgICAgIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbixcbiAgICAgICAgYWRkaXRpb25hbFVuaWZvcm1zVHlwZSxcbiAgICAgICksXG4gICAgZ2V0UnVuRGF0YTogKGlucHV0VGVuc29ycykgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IGlucHV0LmRpbXMsIGRhdGFUeXBlOiBvdXRwdXREYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHtcbiAgICAgICAgeDogTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKGlucHV0VGVuc29yc1swXS5kaW1zKSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovIC8gNCAvKiB2ZWMgc2l6ZSAqLyksXG4gICAgICB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGFicyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0FicycsICdhYnMnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgYWNvcyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0Fjb3MnLCAnYWNvcycpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhY29zaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0Fjb3NoJywgJ2Fjb3NoJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGFzaW4gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdBc2luJywgJ2FzaW4nKSk7XG59O1xuXG5leHBvcnQgY29uc3QgYXNpbmggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdBc2luaCcsICdhc2luaCcpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhdGFuID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQXRhbicsICdhdGFuJykpO1xufTtcbmV4cG9ydCBjb25zdCBhdGFuaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0F0YW5oJywgJ2F0YW5oJykpO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBDYXN0QXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IHRvOiBudW1iZXI7XG4gIHJlYWRvbmx5IHNhdHVyYXRlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNvbnN0IHBhcnNlQ2FzdEF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBDYXN0QXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoYXR0cmlidXRlcyBhcyB7IHRvOiBudW1iZXIgfSk7XG5cbmV4cG9ydCBjb25zdCBjYXN0ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBDYXN0QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBsZXQgZnVuYzogRWxlbWVudHdpc2VGdW5jdGlvbkNhbGw7XG4gIHN3aXRjaCAoYXR0cmlidXRlcy50bykge1xuICAgIGNhc2UgRGF0YVR5cGUuZmxvYXQxNjpcbiAgICAgIGZ1bmMgPSAndmVjNDxmMTY+JztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgRGF0YVR5cGUuZmxvYXQ6XG4gICAgICBmdW5jID0gJ3ZlYzQ8ZjMyPic7XG4gICAgICBicmVhaztcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQzMjpcbiAgICAgIGZ1bmMgPSAndmVjNDx1MzI+JztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgRGF0YVR5cGUuaW50MzI6XG4gICAgICBmdW5jID0gJ3ZlYzQ8aTMyPic7XG4gICAgICBicmVhaztcbiAgICBjYXNlIERhdGFUeXBlLmJvb2w6XG4gICAgICBmdW5jID0gJ3ZlYzQ8Ym9vbD4nO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGBub3Qgc3VwcG9ydGVkIHR5cGUgKHNwZWNpZmllZCBpbiBhdHRyaWJ1dGUgJ3RvJyBmcm9tICdDYXN0JyBvcGVyYXRvcik6ICR7YXR0cmlidXRlcy50b31gKTtcbiAgfVxuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0Nhc3QnLCBmdW5jLCB1bmRlZmluZWQsIGF0dHJpYnV0ZXMuY2FjaGVLZXksIGF0dHJpYnV0ZXMudG8pLFxuICApO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBDbGlwQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IG1pbjogbnVtYmVyO1xuICByZWFkb25seSBtYXg6IG51bWJlcjtcbn1cblxuY29uc3QgZ2VuZXJhdGVDbGlwQXR0cmlidXRlc0Zyb21JbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiBDbGlwQXR0cmlidXRlcyA9PiB7XG4gIGxldCBtaW46IG51bWJlcjtcbiAgbGV0IG1heDogbnVtYmVyO1xuICBjb25zdCBoYXNNaW4gPSBpbnB1dHMubGVuZ3RoID49IDIgJiYgaW5wdXRzWzFdLmRhdGEgIT09IDA7XG4gIGNvbnN0IGhhc01heCA9IGlucHV0cy5sZW5ndGggPj0gMyAmJiBpbnB1dHNbMl0uZGF0YSAhPT0gMDtcblxuICBzd2l0Y2ggKGlucHV0c1swXS5kYXRhVHlwZSkge1xuICAgIGNhc2UgRGF0YVR5cGUuZmxvYXQ6XG4gICAgICBtaW4gPSBoYXNNaW4gPyBpbnB1dHNbMV0uZ2V0RmxvYXQzMkFycmF5KClbMF0gOiAtMy40MDI4MjM0NjYzODUyODg2ZTM4O1xuICAgICAgbWF4ID0gaGFzTWF4ID8gaW5wdXRzWzJdLmdldEZsb2F0MzJBcnJheSgpWzBdIDogMy40MDI4MjM0NjYzODUyODg2ZTM4O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBEYXRhVHlwZS5mbG9hdDE2OlxuICAgICAgbWluID0gaGFzTWluID8gaW5wdXRzWzFdLmdldFVpbnQxNkFycmF5KClbMF0gOiA2NDUxMTsgLy8gdWludDE2KDY0NTExKSA8LT4gZmxvYXQxNigtNjU1MDQuMClcbiAgICAgIG1heCA9IGhhc01heCA/IGlucHV0c1syXS5nZXRVaW50MTZBcnJheSgpWzBdIDogMzE3NDM7IC8vIHVpbnQxNigzMTc0MykgPC0+IGZsb2F0MTYoNjU1MDQuMClcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydCBkYXRhIHR5cGUnKTtcbiAgfVxuXG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBtaW4sIG1heCB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBjbGlwID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBjbGlwQXR0cmlidXRlczogQ2xpcEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgYXR0cmlidXRlcyA9IGNsaXBBdHRyaWJ1dGVzID8gY2xpcEF0dHJpYnV0ZXMgOiBnZW5lcmF0ZUNsaXBBdHRyaWJ1dGVzRnJvbUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICAnQ2xpcCcsXG4gICAgICAoYSkgPT4gYGNsYW1wKCR7YX0sIHZlYzQ8JHtkYXRhVHlwZX0+KHVuaWZvcm1zLm1pbiksIHZlYzQ8JHtkYXRhVHlwZX0+KHVuaWZvcm1zLm1heCkpYCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBbXG4gICAgICAgIHsgdHlwZTogY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUsIGRhdGE6IGF0dHJpYnV0ZXMubWluIH0sXG4gICAgICAgIHsgdHlwZTogY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUsIGRhdGE6IGF0dHJpYnV0ZXMubWF4IH0sXG4gICAgICBdLFxuICAgICAgW1xuICAgICAgICB7IG5hbWU6ICdtaW4nLCB0eXBlOiBkYXRhVHlwZSBhcyBVbmlmb3JtRGF0YUVsZW1lbnRUeXBlIH0sXG4gICAgICAgIHsgbmFtZTogJ21heCcsIHR5cGU6IGRhdGFUeXBlIGFzIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUgfSxcbiAgICAgIF0sXG4gICAgKSxcbiAgICB7IGlucHV0czogWzBdIH0sXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgY2VpbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0NlaWwnLCAnY2VpbCcpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBjb3MgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdDb3MnLCAnY29zJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvc2ggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdDb3NoJywgJ2Nvc2gnKSk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIEFscGhhQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGFscGhhOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBwYXJzZUFscGhhQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEFscGhhQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoYXR0cmlidXRlcyBhcyB7IGFscGhhOiBudW1iZXIgfSk7XG5cbmV4cG9ydCBjb25zdCBlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEFscGhhQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgJ0VsdScsXG4gICAgICAoYSkgPT4gYGVsdV92ZjMyKCR7YX0pYCxcbiAgICAgIGBcbiAgY29uc3QgZWx1X2FscGhhXyA9ICR7ZGF0YVR5cGV9KCR7YXR0cmlidXRlcy5hbHBoYX0pO1xuXG4gIGZuIGVsdV9mMzIoYTogJHtkYXRhVHlwZX0pIC0+ICR7ZGF0YVR5cGV9IHtcbiAgcmV0dXJuIHNlbGVjdCgoZXhwKGEpIC0gMS4wKSAqIGVsdV9hbHBoYV8sIGEsIGEgPj0gMC4wKTtcbiAgfVxuXG4gIGZuIGVsdV92ZjMyKHY6IHZlYzQ8JHtkYXRhVHlwZX0+KSAtPiB2ZWM0PCR7ZGF0YVR5cGV9PiB7XG4gIHJldHVybiB2ZWM0KGVsdV9mMzIodi54KSwgZWx1X2YzMih2LnkpLCBlbHVfZjMyKHYueiksIGVsdV9mMzIodi53KSk7XG4gIH1gLFxuICAgICAgYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICApLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGVyZkltcGwgPSAodmFyVHlwZSA9ICdmMzInKSA9PiBgXG5jb25zdCByMDogJHt2YXJUeXBlfSA9IDAuMzI3NTkxMTtcbmNvbnN0IHIxOiAke3ZhclR5cGV9ID0gMC4yNTQ4Mjk1OTI7XG5jb25zdCByMjogJHt2YXJUeXBlfSA9IC0wLjI4NDQ5NjczNjtcbmNvbnN0IHIzOiAke3ZhclR5cGV9ID0gMS40MjE0MTM3NDE7XG5jb25zdCByNDogJHt2YXJUeXBlfSA9IC0xLjQ1MzE1MjAyNztcbmNvbnN0IHI1OiAke3ZhclR5cGV9ID0gMS4wNjE0MDU0Mjk7XG5cbmZuIGVyZl92ZjMyKHY6IHZlYzQ8JHt2YXJUeXBlfT4pIC0+IHZlYzQ8JHt2YXJUeXBlfT4ge1xuICBsZXQgYWJzdiA9IGFicyh2KTtcbiAgbGV0IHggPSAxLjAgLyAoMS4wICsgcjAgKiBhYnN2KTtcbiAgcmV0dXJuIHNpZ24odikgKiAoMS4wIC0gKCgoKHI1ICogeCArIHI0KSAqIHggKyByMykgKiB4ICsgcjIpICogeCArIHIxKSAqIHggKiBleHAoLWFic3YgKiBhYnN2KSk7XG59YDtcblxuZXhwb3J0IGNvbnN0IGVyZiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0VyZicsIChhKSA9PiBgZXJmX3ZmMzIoJHthfSlgLCBlcmZJbXBsKGRhdGFUeXBlKSkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGV4cCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0V4cCcsICdleHAnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZmxvb3IgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdGbG9vcicsICdmbG9vcicpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZWx1ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICAnR2VsdScsXG4gICAgICAoYSkgPT4gYDAuNSAqICR7YX0gKiAoMS4wICsgZXJmX3ZmMzIoJHthfSAqIDAuNzA3MTA2NzgxMTg2NTQ3NSkpYCxcbiAgICAgIGVyZkltcGwoZGF0YVR5cGUpLFxuICAgICksXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgbGVha3lSZWx1ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBbHBoYUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgICdMZWFreVJlbHUnLFxuICAgICAgKGEpID0+IGBzZWxlY3QobGVha3lfcmVsdV9hbHBoYV8gKiAke2F9LCAke2F9LCAke2F9ID49IHZlYzQ8JHtkYXRhVHlwZX0+KDAuMCkpYCxcbiAgICAgIGBjb25zdCBsZWFreV9yZWx1X2FscGhhXyA9ICR7ZGF0YVR5cGV9KCR7YXR0cmlidXRlcy5hbHBoYX0pO2AsXG4gICAgICBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICksXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3Qgbm90ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnTm90JywgKGEpID0+IGAhJHthfWApKTtcbn07XG5cbmV4cG9ydCBjb25zdCBuZWcgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdOZWcnLCAoYSkgPT4gYC0ke2F9YCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlY2lwcm9jYWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdSZWNpcHJvY2FsJywgKGEpID0+IGAxLjAvJHthfWApKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWx1ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICAnUmVsdScsXG4gICAgICAoYSkgPT4gYHNlbGVjdCh2ZWM0PCR7ZGF0YVR5cGV9PigwLjApLCAke2F9LCAke2F9ID4gdmVjNDwke2RhdGFUeXBlfT4oMC4wKSlgLFxuICAgICksXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3Qgc2lnbW9pZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ1NpZ21vaWQnLCAoYSkgPT4gYCgxLjAgLyAoMS4wICsgZXhwKC0ke2F9KSkpYCkpO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBIYXJkU2lnbW9pZEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBhbHBoYTogbnVtYmVyO1xuICByZWFkb25seSBiZXRhOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBwYXJzZUhhcmRTaWdtb2lkQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEhhcmRTaWdtb2lkQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoXG4gICAgYXR0cmlidXRlcyBhcyB7XG4gICAgICBhbHBoYTogbnVtYmVyO1xuICAgICAgYmV0YTogbnVtYmVyO1xuICAgIH0sXG4gICk7XG5cbmV4cG9ydCBjb25zdCBoYXJkU2lnbW9pZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogSGFyZFNpZ21vaWRBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICAnSGFyZFNpZ21vaWQnLFxuICAgICAgKGEpID0+XG4gICAgICAgIGBtYXgodmVjNDwke2RhdGFUeXBlfT4oMC4wKSwgbWluKHZlYzQ8JHtkYXRhVHlwZX0+KDEuMCksICR7YXR0cmlidXRlcy5hbHBoYX0gKiAke2F9ICsgdmVjNDwke2RhdGFUeXBlfT4oJHthdHRyaWJ1dGVzLmJldGF9KSkpYCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgKSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBzaW4gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdTaW4nLCAnc2luJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHNpbmggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdTaW5oJywgJ3NpbmgnKSk7XG59O1xuXG5leHBvcnQgY29uc3Qgc3FydCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ1NxcnQnLCAnc3FydCcpKTtcbn07XG5cbmV4cG9ydCBjb25zdCB0YW4gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdUYW4nLCAndGFuJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHRhbmhFeHByZXNzaW9uID0gKGE6IHN0cmluZykgPT4gYHNpZ24oJHthfSkgKiAoMSAtIGV4cCgtMiAqIGFicygke2F9KSkpIC8gKDEgKyBleHAoLTIgKiBhYnMoJHthfSkpKWA7XG5cbmV4cG9ydCBjb25zdCB0YW5oID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIC8vIFRPRE86IHJldmlzaXQgYWZ0ZXIgaHR0cHM6Ly9naXRodWIuY29tL2dwdXdlYi9ncHV3ZWIvaXNzdWVzLzQ0NTggaXMgcmVzb2x2ZWRcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdUYW5oJywgdGFuaEV4cHJlc3Npb24pKTtcbn07XG5cbmV4cG9ydCBjb25zdCBmYXN0R2VsdUltcGwgPSAodmFyVHlwZSA9ICdmMzInKSA9PiBgXG5jb25zdCBmYXN0X2dlbHVfYTogJHt2YXJUeXBlfSA9IDAuNTtcbmNvbnN0IGZhc3RfZ2VsdV9iOiAke3ZhclR5cGV9ID0gMC43OTc4ODQ1NjA4MDI4NjU0O1xuY29uc3QgZmFzdF9nZWx1X2M6ICR7dmFyVHlwZX0gPSAwLjAzNTY3NzQwODEzNjMwMDEyNTtcblxuZm4gdGFuaF92KHY6IHZlYzQ8JHt2YXJUeXBlfT4pIC0+IHZlYzQ8JHt2YXJUeXBlfT4ge1xuICByZXR1cm4gJHt0YW5oRXhwcmVzc2lvbigndicpfTtcbn1cbmA7XG5cbmV4cG9ydCBjb25zdCBmYXN0R2VsdUV4cHJlc3Npb24gPSAoeDogc3RyaW5nKSA9PlxuICBgKGZhc3RfZ2VsdV9hICsgZmFzdF9nZWx1X2EgKiB0YW5oX3YoJHt4fSAqIChmYXN0X2dlbHVfYyAqICR7eH0gKiAke3h9ICsgZmFzdF9nZWx1X2IpKSkgKiAke3h9YDtcblxuZXhwb3J0IGNvbnN0IGZhc3RHZWx1ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICAnRmFzdEdlbHUnLFxuICAgICAgZmFzdEdlbHVFeHByZXNzaW9uLFxuICAgICAgZmFzdEdlbHVJbXBsKGRhdGFUeXBlKSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICksXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgdGhyZXNob2xkZWRSZWx1ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBbHBoYUF0dHJpYnV0ZXMpOiBudW1iZXIgPT4ge1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgJ1RocmVzaG9sZGVkUmVsdScsXG4gICAgICAoYSkgPT4gYHNlbGVjdCh2ZWM0PCR7ZGF0YVR5cGV9PigwLjApLCAke2F9LCAke2F9ID4gdGhyZXNob2xkZWRfcmVsdV9hbHBoYV8pYCxcbiAgICAgIGBjb25zdCB0aHJlc2hvbGRlZF9yZWx1X2FscGhhXyA9IHZlYzQ8JHtkYXRhVHlwZX0+KCR7YXR0cmlidXRlcy5hbHBoYX0pO2AsXG4gICAgICBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICksXG4gICk7XG4gIHJldHVybiAwO1xufTtcblxuZXhwb3J0IGNvbnN0IGxvZyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0xvZycsICdsb2cnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcXVpY2tHZWx1SW1wbCA9ICh2YXJUeXBlOiBzdHJpbmcsIGFscGhhOiBudW1iZXIpID0+IGBcbmNvbnN0IGFscGhhID0gdmVjNDwke3ZhclR5cGV9Pigke2FscGhhfSk7XG5jb25zdCBvbmUgPSAke3ZhclR5cGV9KDEuMCk7XG5jb25zdCB6ZXJvID0gJHt2YXJUeXBlfSgwLjApO1xuXG5mbiBxdWlja19nZWx1X2ltcGwoeDogdmVjNDwke3ZhclR5cGV9PikgLT4gdmVjNDwke3ZhclR5cGV9PiB7XG4gIGxldCB2ID0geCAqYWxwaGE7XG4gIHZhciB4MSA6IHZlYzQ8JHt2YXJUeXBlfT47XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgNDsgaSA9IGkgKyAxKSB7XG4gICAgaWYgKHZbaV0gPj0gemVybykge1xuICAgICAgeDFbaV0gPSBvbmUgLyAob25lICsgZXhwKC12W2ldKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHgxW2ldID0gb25lIC0gb25lIC8gKG9uZSArIGV4cCh2W2ldKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB4ICogeDE7XG59XG5gO1xuXG5leHBvcnQgY29uc3QgcXVpY2tHZWx1RXhwcmVzc2lvbiA9ICh4OiBzdHJpbmcpID0+IGBxdWlja19nZWx1X2ltcGwoJHt4fSlgO1xuXG5leHBvcnQgY29uc3QgcXVpY2tnZWx1ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBbHBoYUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgZFR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgICdRdWlja0dlbHUnLFxuICAgICAgcXVpY2tHZWx1RXhwcmVzc2lvbixcbiAgICAgIHF1aWNrR2VsdUltcGwoZFR5cGUsIGF0dHJpYnV0ZXMuYWxwaGEpLFxuICAgICAgYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICksXG4gICk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIsIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSB9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7IGVyZkltcGwgfSBmcm9tICcuL3VuYXJ5LW9wJztcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gMykge1xuICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgc2hvdWxkIGhhdmUgMyBkaW1lbnNpb25zJyk7XG4gIH1cblxuICBpZiAoIVsyNTYwLCA1MTIwLCAxMDI0MF0uaW5jbHVkZXMoaW5wdXRzWzBdLmRpbXNbMl0pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdoaWRkZW4gc3RhdGUgc2hvdWxkIGJlIDI1NjAsIDUxMjAgb3IgMTAyNDAnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2JpYXMgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAxIGRpbWVuc2lvbnMnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltc1syXSAhPT0gaW5wdXRzWzFdLmRpbXNbMF0pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2xhc3QgZGltZW5zaW9uIG9mIGlucHV0IGFuZCBiaWFzIGFyZSBub3QgdGhlIHNhbWUnKTtcbiAgfVxufTtcblxuY29uc3QgY3JlYXRlQmlhc1NwbGl0R2VsdVByb2dyYW1JbmZvID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gIG91dHB1dFNoYXBlWzJdID0gb3V0cHV0U2hhcGVbMl0gLyAyO1xuXG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLCA0KTtcbiAgY29uc3QgYmlhcyA9IGlucHV0VmFyaWFibGUoJ2JpYXMnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIFtpbnB1dHNbMF0uZGltc1syXV0sIDQpO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZSwgNCk7XG5cbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIDQ7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKGlucHV0c1swXS5kYXRhVHlwZSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gIGNvbnN0IE1fU1FSVDIgPSBzcXJ0KDIuMCk7XG4gIGNvbnN0IGhhbGZDaGFubmVscyA9ICR7aW5wdXRzWzBdLmRpbXNbMl0gLyA0IC8gMn11O1xuXG4gICR7c2hhZGVySGVscGVyLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIGJpYXMsIG91dHB1dCl9XG5cbiAgJHtlcmZJbXBsKGRhdGFUeXBlKX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKG91dHB1dFNpemUpfVxuICAgIGxldCBiaWFzSWR4ID0gZ2xvYmFsX2lkeCAlIGhhbGZDaGFubmVscztcbiAgICBsZXQgYmF0Y2hJbmRleCA9IGdsb2JhbF9pZHggLyBoYWxmQ2hhbm5lbHM7XG4gICAgbGV0IGlucHV0T2Zmc2V0ID0gYmlhc0lkeCArIGJhdGNoSW5kZXggKiBoYWxmQ2hhbm5lbHMgKiAyO1xuICAgIGxldCB2YWx1ZUxlZnQgPSBpbnB1dFtpbnB1dE9mZnNldF0gKyBiaWFzW2JpYXNJZHhdO1xuICAgIGxldCB2YWx1ZVJpZ2h0ID0gaW5wdXRbaW5wdXRPZmZzZXQgKyBoYWxmQ2hhbm5lbHNdICsgYmlhc1tiaWFzSWR4ICsgaGFsZkNoYW5uZWxzXTtcbiAgICBsZXQgZ2VsdVJpZ2h0ID0gdmFsdWVSaWdodCAqIDAuNSAqIChlcmZfdmYzMih2YWx1ZVJpZ2h0IC8gTV9TUVJUMikgKyAxKTtcblxuICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3ZhbHVlTGVmdCAqIGdlbHVSaWdodCcpfVxuICB9YDtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdCaWFzU3BsaXRHZWx1JyxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGJpYXNTcGxpdEdlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlQmlhc1NwbGl0R2VsdVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzKSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBCcm9hZGNhc3RVdGlsLCBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbnR5cGUgQnVpbHRpbkZ1bmN0aW9uTmFtZSA9IHN0cmluZztcbnR5cGUgQmluYXJ5Q3VzdG9tRXhwcmVzc2lvbiA9IChleHByZXNzaW9uQTogc3RyaW5nLCBleHByZXNzaW9uQjogc3RyaW5nKSA9PiBzdHJpbmc7XG50eXBlIEJpbmFyeUZ1bmN0aW9uQ2FsbCA9XG4gIHwgQnVpbHRpbkZ1bmN0aW9uTmFtZVxuICB8IEJpbmFyeUN1c3RvbUV4cHJlc3Npb25cbiAgfCB7XG4gICAgICBzY2FsYXI6IEJpbmFyeUN1c3RvbUV4cHJlc3Npb247XG4gICAgICB2ZWN0b3I6IEJpbmFyeUN1c3RvbUV4cHJlc3Npb247XG4gICAgfTtcblxuY29uc3QgY3JlYXRlQmluYXJ5T3BQcm9ncmFtU2hhZGVyID0gKFxuICBzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcixcbiAgZGltc0E6IHJlYWRvbmx5IG51bWJlcltdLFxuICBkaW1zQjogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGRpbXNPdXRwdXQ6IHJlYWRvbmx5IG51bWJlcltdLFxuICB2ZWN0b3JpemU6IGJvb2xlYW4sXG4gIGRvQnJvYWRjYXN0OiBib29sZWFuLFxuICBzaGFyZWREaW1lbnNpb25EaXZpc2libGVCeTQ6IGJvb2xlYW4sXG4gIGZ1bmNDYWxsOiBCaW5hcnlGdW5jdGlvbkNhbGwsXG4gIHR5cGVBOiBudW1iZXIsXG4gIHR5cGVCOiBudW1iZXIsXG4gIHR5cGVPdXRwdXQ6IG51bWJlcixcbiAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uPzogc3RyaW5nLFxuKSA9PiB7XG4gIGxldCBleHByZXNzaW9uU2NhbGFyOiBCaW5hcnlDdXN0b21FeHByZXNzaW9uO1xuICBsZXQgZXhwcmVzc2lvblZlY3RvcjogQmluYXJ5Q3VzdG9tRXhwcmVzc2lvbjtcbiAgaWYgKHR5cGVvZiBmdW5jQ2FsbCA9PT0gJ3N0cmluZycpIHtcbiAgICBleHByZXNzaW9uU2NhbGFyID0gZXhwcmVzc2lvblZlY3RvciA9IChhLCBiKSA9PiBgJHtmdW5jQ2FsbH0oKCR7YX0pLCgke2J9KSlgO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBmdW5jQ2FsbCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGV4cHJlc3Npb25TY2FsYXIgPSBleHByZXNzaW9uVmVjdG9yID0gZnVuY0NhbGw7XG4gIH0gZWxzZSB7XG4gICAgZXhwcmVzc2lvblNjYWxhciA9IGZ1bmNDYWxsLnNjYWxhcjtcbiAgICBleHByZXNzaW9uVmVjdG9yID0gZnVuY0NhbGwudmVjdG9yO1xuICB9XG5cbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dERhdGEnLCB0eXBlT3V0cHV0LCBkaW1zT3V0cHV0Lmxlbmd0aCwgNCk7XG4gIGNvbnN0IGEgPSBpbnB1dFZhcmlhYmxlKCdhRGF0YScsIHR5cGVBLCBkaW1zQS5sZW5ndGgsIDQpO1xuICBjb25zdCBiID0gaW5wdXRWYXJpYWJsZSgnYkRhdGEnLCB0eXBlQiwgZGltc0IubGVuZ3RoLCA0KTtcblxuICBsZXQgYXNzaWdubWVudDogc3RyaW5nO1xuICBpZiAodmVjdG9yaXplKSB7XG4gICAgaWYgKGRvQnJvYWRjYXN0KSB7XG4gICAgICBjb25zdCBpc0FPbmVFbGVtZW50ID0gU2hhcGVVdGlsLnNpemUoZGltc0EpID09PSAxO1xuICAgICAgY29uc3QgaXNCT25lRWxlbWVudCA9IFNoYXBlVXRpbC5zaXplKGRpbXNCKSA9PT0gMTtcbiAgICAgIGNvbnN0IGFMYXN0RGltRGl2aXNpYmxlQnk0ID0gZGltc0EubGVuZ3RoID4gMCAmJiBkaW1zQVtkaW1zQS5sZW5ndGggLSAxXSAlIDQgPT09IDA7XG4gICAgICBjb25zdCBiTGFzdERpbURpdmlzaWJsZUJ5NCA9IGRpbXNCLmxlbmd0aCA+IDAgJiYgZGltc0JbZGltc0IubGVuZ3RoIC0gMV0gJSA0ID09PSAwO1xuICAgICAgaWYgKGlzQU9uZUVsZW1lbnQgfHwgaXNCT25lRWxlbWVudCkge1xuICAgICAgICBhc3NpZ25tZW50ID0gb3V0cHV0LnNldEJ5T2Zmc2V0KFxuICAgICAgICAgICdnbG9iYWxfaWR4JyxcbiAgICAgICAgICBleHByZXNzaW9uVmVjdG9yKFxuICAgICAgICAgICAgaXNBT25lRWxlbWVudCA/IGAke2EudHlwZS52YWx1ZX0oJHthLmdldEJ5T2Zmc2V0KCcwJyl9LngpYCA6IGEuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKSxcbiAgICAgICAgICAgIGlzQk9uZUVsZW1lbnQgPyBgJHtiLnR5cGUudmFsdWV9KCR7Yi5nZXRCeU9mZnNldCgnMCcpfS54KWAgOiBiLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JyksXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgICAgICBsZXQgb3V0cHV0SW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCAqIDR1Jyl9O1xuICAgICAgICAgICAgbGV0IG9mZnNldEEgPSAke2EuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoJ291dHB1dEluZGljZXMnLCBvdXRwdXQpfTtcbiAgICAgICAgICAgIGxldCBvZmZzZXRCID0gJHtiLmJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0KCdvdXRwdXRJbmRpY2VzJywgb3V0cHV0KX07XG4gICAgICAgICAgICAke291dHB1dC5zZXRCeU9mZnNldChcbiAgICAgICAgICAgICAgJ2dsb2JhbF9pZHgnLFxuICAgICAgICAgICAgICBleHByZXNzaW9uVmVjdG9yKFxuICAgICAgICAgICAgICAgIHNoYXJlZERpbWVuc2lvbkRpdmlzaWJsZUJ5NCB8fCBhTGFzdERpbURpdmlzaWJsZUJ5NFxuICAgICAgICAgICAgICAgICAgPyBhLmdldEJ5T2Zmc2V0KCdvZmZzZXRBIC8gNHUnKVxuICAgICAgICAgICAgICAgICAgOiBgJHthLnR5cGUudmFsdWV9KCR7YS5nZXRCeU9mZnNldCgnb2Zmc2V0QSAvIDR1Jyl9W29mZnNldEEgJSA0dV0pYCxcbiAgICAgICAgICAgICAgICBzaGFyZWREaW1lbnNpb25EaXZpc2libGVCeTQgfHwgYkxhc3REaW1EaXZpc2libGVCeTRcbiAgICAgICAgICAgICAgICAgID8gYi5nZXRCeU9mZnNldCgnb2Zmc2V0QiAvIDR1JylcbiAgICAgICAgICAgICAgICAgIDogYCR7Yi50eXBlLnZhbHVlfSgke2IuZ2V0QnlPZmZzZXQoJ29mZnNldEIgLyA0dScpfVtvZmZzZXRCICUgNHVdKWAsXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICApfVxuICAgICAgICAgIGA7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2lnbm1lbnQgPSBvdXRwdXQuc2V0QnlPZmZzZXQoXG4gICAgICAgICdnbG9iYWxfaWR4JyxcbiAgICAgICAgZXhwcmVzc2lvblZlY3RvcihhLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JyksIGIuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKSksXG4gICAgICApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoIWRvQnJvYWRjYXN0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vIG5lY2Vzc2FyeSB0byB1c2Ugc2NhbGFyIGltcGxlbWVudGF0aW9uIGZvciBlbGVtZW50LXdpc2UgYmluYXJ5IG9wIGltcGxlbWVudGF0aW9uLicpO1xuICAgIH1cblxuICAgIGNvbnN0IHNpbmdsZUFzc2lnbm1lbnQgPSAocmVzU3RyOiBzdHJpbmcsIHg6IG51bWJlciwgdHlwZUNhc3QgPSAnJykgPT4ge1xuICAgICAgY29uc3QgZXhwcmVzc2lvbkEgPSBgYURhdGFbaW5kZXhBJHt4fV1bY29tcG9uZW50QSR7eH1dYDtcbiAgICAgIGNvbnN0IGV4cHJlc3Npb25CID0gYGJEYXRhW2luZGV4QiR7eH1dW2NvbXBvbmVudEIke3h9XWA7XG4gICAgICByZXR1cm4gYFxuICAgICAgICAgICAgbGV0IG91dHB1dEluZGljZXMke3h9ID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKGBnbG9iYWxfaWR4ICogNHUgKyAke3h9dWApfTtcbiAgICAgICAgICAgIGxldCBvZmZzZXRBJHt4fSA9ICR7YS5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldChgb3V0cHV0SW5kaWNlcyR7eH1gLCBvdXRwdXQpfTtcbiAgICAgICAgICAgIGxldCBvZmZzZXRCJHt4fSA9ICR7Yi5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldChgb3V0cHV0SW5kaWNlcyR7eH1gLCBvdXRwdXQpfTtcbiAgICAgICAgICAgIGxldCBpbmRleEEke3h9ID0gb2Zmc2V0QSR7eH0gLyA0dTtcbiAgICAgICAgICAgIGxldCBpbmRleEIke3h9ID0gb2Zmc2V0QiR7eH0gLyA0dTtcbiAgICAgICAgICAgIGxldCBjb21wb25lbnRBJHt4fSA9IG9mZnNldEEke3h9ICUgNHU7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50QiR7eH0gPSBvZmZzZXRCJHt4fSAlIDR1O1xuICAgICAgICAgICAgJHtyZXNTdHJ9WyR7eH1dID0gJHt0eXBlQ2FzdH0oJHtleHByZXNzaW9uU2NhbGFyKGV4cHJlc3Npb25BLCBleHByZXNzaW9uQil9KTtcbiAgICAgICAgICBgO1xuICAgIH07XG4gICAgaWYgKHR5cGVPdXRwdXQgPT09IERhdGFUeXBlLmJvb2wpIHtcbiAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgICAgICB2YXIgZGF0YSA9IHZlYzQ8dTMyPigwKTtcbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDAsICd1MzInKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDEsICd1MzInKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDIsICd1MzInKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDMsICd1MzInKX1cbiAgICAgICAgICAgIG91dHB1dERhdGFbZ2xvYmFsX2lkeF0gPSBkb3QodmVjNDx1MzI+KDB4MSwgMHgxMDAsIDB4MTAwMDAsIDB4MTAwMDAwMCksIHZlYzQ8dTMyPihkYXRhKSk7YDtcbiAgICB9IGVsc2Uge1xuICAgICAgYXNzaWdubWVudCA9IGBcbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnb3V0cHV0RGF0YVtnbG9iYWxfaWR4XScsIDApfVxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdvdXRwdXREYXRhW2dsb2JhbF9pZHhdJywgMSl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dERhdGFbZ2xvYmFsX2lkeF0nLCAyKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnb3V0cHV0RGF0YVtnbG9iYWxfaWR4XScsIDMpfVxuICAgICAgICAgIGA7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGBcbiAgICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3JtKCd2ZWNfc2l6ZScsICd1MzInKS5kZWNsYXJlVmFyaWFibGVzKGEsIGIsIG91dHB1dCl9XG5cbiAgICAgICAgJHthZGRpdGlvbmFsSW1wbGVtZW50YXRpb24gPz8gJyd9XG5cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLnZlY19zaXplJyl9XG4gICAgICAgICR7YXNzaWdubWVudH1cbiAgICAgIH1gO1xufTtcblxuY29uc3QgY3JlYXRlQmluYXJ5T3BQcm9ncmFtSW5mbyA9IChcbiAgbmFtZTogc3RyaW5nLFxuICBjYWNoZUtleTogc3RyaW5nLFxuICBhOiBUZW5zb3JWaWV3LFxuICBiOiBUZW5zb3JWaWV3LFxuICBmdW5jQ2FsbDogQmluYXJ5RnVuY3Rpb25DYWxsLFxuICBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24/OiBzdHJpbmcsXG4gIG91dHB1dERhdGFUeXBlOiBudW1iZXIgPSBhLmRhdGFUeXBlLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBhRGltcyA9IGEuZGltcy5tYXAoKHgpID0+IE51bWJlcih4KSA/PyAxKTtcbiAgY29uc3QgYkRpbXMgPSBiLmRpbXMubWFwKCh4KSA9PiBOdW1iZXIoeCkgPz8gMSk7XG4gIGNvbnN0IGlzQnJvYWRjYXN0ID0gIVNoYXBlVXRpbC5hcmVFcXVhbChhRGltcywgYkRpbXMpO1xuICBsZXQgb3V0cHV0U2hhcGUgPSBhRGltcztcbiAgbGV0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShhRGltcyk7XG5cbiAgbGV0IHZlY3Rvcml6ZSA9IGZhbHNlO1xuICBsZXQgc2hhcmVkRGltZW5zaW9uRGl2aXNpYmxlQnk0ID0gZmFsc2U7XG5cbiAgLy8gVE9ETzogZGVhbCB3aXRoIHplcm8tc2l6ZWQgdGVuc29ycyAoZWcuIGRpbXM9WzEsMF0pXG4gIGNvbnN0IGNhY2hlS2V5QXV4ID0gW2lzQnJvYWRjYXN0XTtcbiAgaWYgKGlzQnJvYWRjYXN0KSB7XG4gICAgY29uc3QgY2FsY3VsYXRlZFNoYXBlID0gQnJvYWRjYXN0VXRpbC5jYWxjU2hhcGUoYURpbXMsIGJEaW1zLCBmYWxzZSk7XG4gICAgaWYgKCFjYWxjdWxhdGVkU2hhcGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IHBlcmZvcm0gYmluYXJ5IG9wIG9uIHRoZSBnaXZlbiB0ZW5zb3JzXCIpO1xuICAgIH1cbiAgICBvdXRwdXRTaGFwZSA9IGNhbGN1bGF0ZWRTaGFwZS5zbGljZSgpO1xuICAgIG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gICAgY29uc3QgaXNBT25lRWxlbWVudCA9IFNoYXBlVXRpbC5zaXplKGFEaW1zKSA9PT0gMTtcbiAgICBjb25zdCBpc0JPbmVFbGVtZW50ID0gU2hhcGVVdGlsLnNpemUoYkRpbXMpID09PSAxO1xuICAgIGNvbnN0IGFMYXN0RGltRGl2aXNpYmxlQnk0ID0gYURpbXMubGVuZ3RoID4gMCAmJiBhRGltc1thRGltcy5sZW5ndGggLSAxXSAlIDQgPT09IDA7XG4gICAgY29uc3QgYkxhc3REaW1EaXZpc2libGVCeTQgPSBiRGltcy5sZW5ndGggPiAwICYmIGJEaW1zW2JEaW1zLmxlbmd0aCAtIDFdICUgNCA9PT0gMDtcbiAgICBjYWNoZUtleUF1eC5wdXNoKGlzQU9uZUVsZW1lbnQpO1xuICAgIGNhY2hlS2V5QXV4LnB1c2goaXNCT25lRWxlbWVudCk7XG4gICAgY2FjaGVLZXlBdXgucHVzaChhTGFzdERpbURpdmlzaWJsZUJ5NCk7XG4gICAgY2FjaGVLZXlBdXgucHVzaChiTGFzdERpbURpdmlzaWJsZUJ5NCk7XG4gICAgLy8gY2hlY2sgd2hldGhlciB2ZWN0b3JpemUgY2FuIGJlIGVuYWJsZWRcbiAgICBsZXQgc2hhcmVkRGltZW5zaW9uID0gMTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IG91dHB1dFNoYXBlLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBkaW1BID0gYURpbXNbYURpbXMubGVuZ3RoIC0gaV07XG4gICAgICBjb25zdCBkaW1CID0gYkRpbXNbYkRpbXMubGVuZ3RoIC0gaV07XG4gICAgICBpZiAoZGltQSA9PT0gZGltQikge1xuICAgICAgICBzaGFyZWREaW1lbnNpb24gKj0gZGltQTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoc2hhcmVkRGltZW5zaW9uICUgNCA9PT0gMCkge1xuICAgICAgc2hhcmVkRGltZW5zaW9uRGl2aXNpYmxlQnk0ID0gdHJ1ZTtcbiAgICAgIHZlY3Rvcml6ZSA9IHRydWU7XG4gICAgfSBlbHNlIGlmIChpc0FPbmVFbGVtZW50IHx8IGlzQk9uZUVsZW1lbnQgfHwgYUxhc3REaW1EaXZpc2libGVCeTQgfHwgYkxhc3REaW1EaXZpc2libGVCeTQpIHtcbiAgICAgIHZlY3Rvcml6ZSA9IHRydWU7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIGVsZW1lbnQtd2lzZVxuICAgIHZlY3Rvcml6ZSA9IHRydWU7XG4gIH1cbiAgY2FjaGVLZXlBdXgucHVzaCh2ZWN0b3JpemUpO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogY2FjaGVLZXkgKyBjYWNoZUtleUF1eC5tYXAoKHgpID0+IHgudG9TdHJpbmcoKSkuam9pbignXycpLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuaycsICdyYW5rJ10sXG4gICAgfSxcbiAgICBnZXRTaGFkZXJTb3VyY2U6IChzaGFkZXJIZWxwZXIpID0+XG4gICAgICBjcmVhdGVCaW5hcnlPcFByb2dyYW1TaGFkZXIoXG4gICAgICAgIHNoYWRlckhlbHBlcixcbiAgICAgICAgYURpbXMsXG4gICAgICAgIGJEaW1zLFxuICAgICAgICBvdXRwdXRTaGFwZSxcbiAgICAgICAgdmVjdG9yaXplLFxuICAgICAgICBpc0Jyb2FkY2FzdCxcbiAgICAgICAgc2hhcmVkRGltZW5zaW9uRGl2aXNpYmxlQnk0LFxuICAgICAgICBmdW5jQ2FsbCxcbiAgICAgICAgYS5kYXRhVHlwZSxcbiAgICAgICAgYi5kYXRhVHlwZSxcbiAgICAgICAgb3V0cHV0RGF0YVR5cGUsXG4gICAgICAgIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbixcbiAgICAgICksXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogb3V0cHV0RGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8gLyA0IC8qIGNvbXBvbmVudCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zOiBbXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBNYXRoLmNlaWwoU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gNCkgfSxcbiAgICAgICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoYURpbXMsIGJEaW1zLCBvdXRwdXRTaGFwZSksXG4gICAgICBdLFxuICAgIH0pLFxuICB9O1xufTtcblxuY29uc3QgcnVuQmluYXJ5T3AgPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBuYW1lOiBzdHJpbmcsXG4gIGZ1bmNDYWxsOiBCaW5hcnlGdW5jdGlvbkNhbGwsXG4gIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbj86IHN0cmluZyxcbiAgY2FjaGVLZXk/OiBzdHJpbmcsXG4gIG91dHB1dERhdGFUeXBlPzogbnVtYmVyLFxuKTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVCaW5hcnlPcFByb2dyYW1JbmZvKFxuICAgICAgbmFtZSxcbiAgICAgIGNhY2hlS2V5ID8/ICcnLFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICBjb250ZXh0LmlucHV0c1sxXSxcbiAgICAgIGZ1bmNDYWxsLFxuICAgICAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uLFxuICAgICAgb3V0cHV0RGF0YVR5cGUsXG4gICAgKSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhZGQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgcnVuQmluYXJ5T3AoY29udGV4dCwgJ0FkZCcsIChhLCBiKSA9PiBgJHthfSske2J9YCk7XG59O1xuXG5leHBvcnQgY29uc3QgZGl2ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHJ1bkJpbmFyeU9wKGNvbnRleHQsICdEaXYnLCAoYSwgYikgPT4gYCR7YX0vJHtifWApO1xufTtcblxuZXhwb3J0IGNvbnN0IGVxdWFsID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHJ1bkJpbmFyeU9wKFxuICAgIGNvbnRleHQsXG4gICAgJ0VxdWFsJyxcbiAgICB7IHNjYWxhcjogKGEsIGIpID0+IGB1MzIoJHthfT09JHtifSlgLCB2ZWN0b3I6IChhLCBiKSA9PiBgdmVjNDx1MzI+KCR7YX09PSR7Yn0pYCB9LFxuICAgIHVuZGVmaW5lZCxcbiAgICB1bmRlZmluZWQsXG4gICAgRGF0YVR5cGUuYm9vbCxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBtdWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgcnVuQmluYXJ5T3AoY29udGV4dCwgJ011bCcsIChhLCBiKSA9PiBgJHthfSoke2J9YCk7XG59O1xuXG5leHBvcnQgY29uc3QgcG93ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnN0IHR5cGUgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLCBjb250ZXh0LmlucHV0c1swXS5kaW1zKS50eXBlLnZhbHVlO1xuICBjb25zdCByb3VuZFN0ciA9IHR5cGUgPT09ICdpMzInID8gJ3JvdW5kJyA6ICcnO1xuICBydW5CaW5hcnlPcChcbiAgICBjb250ZXh0LFxuICAgICdQb3cnLFxuICAgIHsgc2NhbGFyOiAoYSwgYikgPT4gYHBvd19jdXN0b20oJHthfSwke2J9KWAsIHZlY3RvcjogKGEsIGIpID0+IGBwb3dfdmVjdG9yX2N1c3RvbSgke2F9LCR7Yn0pYCB9LFxuICAgIGBcbiAgICBmbiBwb3dfY3VzdG9tKGEgOiAke3R5cGV9LCBiIDogJHt0eXBlfSkgLT4gJHt0eXBlfSB7XG4gICAgICBpZiAoYiA9PSAke3R5cGV9KDAuMCkpIHtcbiAgICAgICAgcmV0dXJuICR7dHlwZX0oMS4wKTtcbiAgICAgIH0gZWxzZSBpZiAoYSA8ICR7dHlwZX0oMC4wKSAmJiBmMzIoYikgIT0gZmxvb3IoZjMyKGIpKSkge1xuICAgICAgICByZXR1cm4gJHt0eXBlfShwb3coZjMyKGEpLCBmMzIoYikpKTsgLy8gTmFOXG4gICAgICB9XG4gICAgICByZXR1cm4gc2VsZWN0KHNpZ24oYSksICR7dHlwZX0oMS4wKSwgcm91bmQoZjMyKGFicyhiKSAlICR7dHlwZX0oMi4wKSkpICE9IDEuMCkgKiAke3R5cGV9KCR7cm91bmRTdHJ9KHBvdyhmMzIoYWJzKGEpKSwgZjMyKGIpKSkpO1xuICAgIH1cbiAgICBmbiBwb3dfdmVjdG9yX2N1c3RvbShhIDogdmVjNDwke3R5cGV9PiwgYiA6IHZlYzQ8JHt0eXBlfT4pIC0+IHZlYzQ8JHt0eXBlfT4ge1xuICAgICAgLy8gVE9ETzogaW1wbGVtZW50IHZlY3Rvcml6ZWQgcG93XG4gICAgICByZXR1cm4gdmVjNDwke3R5cGV9Pihwb3dfY3VzdG9tKGEueCwgYi54KSwgcG93X2N1c3RvbShhLnksIGIueSksIHBvd19jdXN0b20oYS56LCBiLnopLCBwb3dfY3VzdG9tKGEudywgYi53KSk7XG4gICAgfVxuICAgICAgYCxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBzdWIgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgcnVuQmluYXJ5T3AoY29udGV4dCwgJ1N1YicsIChhLCBiKSA9PiBgJHthfS0ke2J9YCk7XG59O1xuXG5leHBvcnQgY29uc3QgZ3JlYXRlciA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBydW5CaW5hcnlPcChcbiAgICBjb250ZXh0LFxuICAgICdHcmVhdGVyJyxcbiAgICB7IHNjYWxhcjogKGEsIGIpID0+IGB1MzIoJHthfT4ke2J9KWAsIHZlY3RvcjogKGEsIGIpID0+IGB2ZWM0PHUzMj4oJHthfT4ke2J9KWAgfSxcbiAgICB1bmRlZmluZWQsXG4gICAgdW5kZWZpbmVkLFxuICAgIERhdGFUeXBlLmJvb2wsXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgbGVzcyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBydW5CaW5hcnlPcChcbiAgICBjb250ZXh0LFxuICAgICdMZXNzJyxcbiAgICB7IHNjYWxhcjogKGEsIGIpID0+IGB1MzIoJHthfTwke2J9KWAsIHZlY3RvcjogKGEsIGIpID0+IGB2ZWM0PHUzMj4oJHthfTwke2J9KWAgfSxcbiAgICB1bmRlZmluZWQsXG4gICAgdW5kZWZpbmVkLFxuICAgIERhdGFUeXBlLmJvb2wsXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgZ3JlYXRlck9yRXF1YWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgcnVuQmluYXJ5T3AoXG4gICAgY29udGV4dCxcbiAgICAnR3JlYXRlck9yRXF1YWwnLFxuICAgIHsgc2NhbGFyOiAoYSwgYikgPT4gYHUzMigke2F9Pj0ke2J9KWAsIHZlY3RvcjogKGEsIGIpID0+IGB2ZWM0PHUzMj4oJHthfT49JHtifSlgIH0sXG4gICAgdW5kZWZpbmVkLFxuICAgIHVuZGVmaW5lZCxcbiAgICBEYXRhVHlwZS5ib29sLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGxlc3NPckVxdWFsID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHJ1bkJpbmFyeU9wKFxuICAgIGNvbnRleHQsXG4gICAgJ0xlc3NPckVxdWFsJyxcbiAgICB7IHNjYWxhcjogKGEsIGIpID0+IGB1MzIoJHthfTw9JHtifSlgLCB2ZWN0b3I6IChhLCBiKSA9PiBgdmVjNDx1MzI+KCR7YX08PSR7Yn0pYCB9LFxuICAgIHVuZGVmaW5lZCxcbiAgICB1bmRlZmluZWQsXG4gICAgRGF0YVR5cGUuYm9vbCxcbiAgKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBJbmRpY2VzSGVscGVyLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbmNhdEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBheGlzOiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBheGlzOiBudW1iZXIpOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCA8IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3RvbyBmZXcgaW5wdXRzJyk7XG4gIH1cbiAgY29uc3QgcmVmZXJlbmNlSW5kZXggPSAwO1xuICBjb25zdCByZWZlcmVuY2VJbnB1dCA9IGlucHV0c1tyZWZlcmVuY2VJbmRleF07XG4gIGNvbnN0IGlucHV0VHlwZSA9IHJlZmVyZW5jZUlucHV0LmRhdGFUeXBlO1xuICBjb25zdCBpbnB1dFJhbmsgPSByZWZlcmVuY2VJbnB1dC5kaW1zLmxlbmd0aDtcbiAgaW5wdXRzLmZvckVhY2goKGlucHV0LCBpKSA9PiB7XG4gICAgaWYgKGkgPT09IHJlZmVyZW5jZUluZGV4KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIG1ha2Ugc3VyZSB0eXBlcyBvZiBhbGwgaW5wdXRzIG1hdGNoXG4gICAgaWYgKGlucHV0LmRhdGFUeXBlICE9PSBpbnB1dFR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgdGVuc29ycyBzaG91bGQgYmUgb25lIHR5cGUnKTtcbiAgICB9XG4gICAgLy8gbWFrZSBzdXJlIHRoZSBkaW1lbnNpb25hbGl0eSBvZiBhbGwgaW5wdXRzIGFyZSB0aGUgc2FtZVxuICAgIGlmIChpbnB1dC5kaW1zLmxlbmd0aCAhPT0gaW5wdXRSYW5rKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IHRlbnNvcnMgc2hvdWxkIGhhdmUgdGhlIHNhbWUgc2hhcGUnKTtcbiAgICB9XG4gICAgaW5wdXQuZGltcy5mb3JFYWNoKChkaW0sIGkpID0+IHtcbiAgICAgIGlmIChpICE9PSBheGlzICYmIGRpbSAhPT0gcmVmZXJlbmNlSW5wdXQuZGltc1tpXSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vbiBjb25jYXQgZGltZW5zaW9ucyBtdXN0IG1hdGNoJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufTtcblxuY29uc3QgY2FsY3VsYXRlSW5wdXRJbmRleEltcGwgPSAobnVtYmVyT2ZUZW5zb3JzOiBudW1iZXIsIHNpemVJbkNvbmNhdEF4aXNTdHI6IHN0cmluZyk6IHN0cmluZyA9PiBgXG4gIGZuIGNhbGN1bGF0ZUlucHV0SW5kZXgoaW5kZXg6IHUzMikgLT4gdTMyIHtcbiAgICBsZXQgc2l6ZUluQ29uY2F0QXhpcyA9IGFycmF5PHUzMiwgJHtudW1iZXJPZlRlbnNvcnN9dT4oJHtzaXplSW5Db25jYXRBeGlzU3RyfSk7XG4gICAgZm9yICh2YXIgaTogdTMyID0gMHU7IGkgPCAke251bWJlck9mVGVuc29yc307IGkgKz0gMXUgKSB7XG4gICAgICBpZiAoaW5kZXggPCBzaXplSW5Db25jYXRBeGlzW2ldKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gJHtudW1iZXJPZlRlbnNvcnN9dTtcbiAgfWA7XG5cbmNvbnN0IGFzc2lnbk91dHB1dERhdGEgPSAoaW5wdXRzOiByZWFkb25seSBJbmRpY2VzSGVscGVyW10sIG91dHB1dDogSW5kaWNlc0hlbHBlcikgPT4ge1xuICBjb25zdCBudW1iZXJPZlRlbnNvcnMgPSBpbnB1dHMubGVuZ3RoO1xuXG4gIGNvbnN0IGNvZGVMaW5lczogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlRlbnNvcnM7ICsraSkge1xuICAgIGNvbnN0IHJldHVyblNuaXBwZXQgPSBvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCBpbnB1dHNbaV0uZ2V0QnlJbmRpY2VzKCdpbmRpY2VzJykpO1xuICAgIGlmIChudW1iZXJPZlRlbnNvcnMgPT09IDEpIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKHJldHVyblNuaXBwZXQpO1xuICAgIH0gZWxzZSBpZiAoaSA9PT0gMCkge1xuICAgICAgY29kZUxpbmVzLnB1c2goYGlmIChpbnB1dEluZGV4ID09ICR7aX11KSB7ICR7cmV0dXJuU25pcHBldH0gfWApO1xuICAgIH0gZWxzZSBpZiAoaSA9PT0gbnVtYmVyT2ZUZW5zb3JzIC0gMSkge1xuICAgICAgY29kZUxpbmVzLnB1c2goYGVsc2UgeyAke3JldHVyblNuaXBwZXR9IH1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZUxpbmVzLnB1c2goYGVsc2UgaWYgKGlucHV0SW5kZXggPT0gJHtpfSkgeyAke3JldHVyblNuaXBwZXR9IH1gKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNvZGVMaW5lcy5qb2luKCdcXG4nKTtcbn07XG5cbmNvbnN0IGNyZWF0ZUNvbmNhdFByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYWRqdXN0ZWRBeGlzOiBudW1iZXIsXG4gIG91dHB1dFNoYXBlOiBudW1iZXJbXSxcbiAgZGF0YVR5cGU6IERhdGFUeXBlLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuXG4gIGNvbnN0IHNpemVJbkNvbmNhdEF4aXMgPSBuZXcgQXJyYXk8bnVtYmVyPihpbnB1dHMubGVuZ3RoKTtcbiAgY29uc3QgaW5wdXRWYXJzID0gbmV3IEFycmF5PEluZGljZXNIZWxwZXI+KGlucHV0cy5sZW5ndGgpO1xuXG4gIGxldCBwcmV2aW91c1N1bSA9IDA7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gW107XG4gIGNvbnN0IGlucHV0UmFua3MgPSBbXTtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW3sgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH1dO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0cy5sZW5ndGg7ICsraSkge1xuICAgIHByZXZpb3VzU3VtICs9IGlucHV0c1tpXS5kaW1zW2FkanVzdGVkQXhpc107XG4gICAgc2l6ZUluQ29uY2F0QXhpc1tpXSA9IHByZXZpb3VzU3VtO1xuICAgIGlucHV0UmFua3MucHVzaChpbnB1dHNbaV0uZGltcy5sZW5ndGgpO1xuICAgIGlucHV0VmFyc1tpXSA9IGlucHV0VmFyaWFibGUoYGlucHV0JHtpfWAsIGRhdGFUeXBlLCBpbnB1dFJhbmtzW2ldKTtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCdyYW5rJyk7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHNpemVJbkNvbmNhdEF4aXNbaV0gfSk7XG4gIH1cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dHMubGVuZ3RoOyArK2kpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbaV0uZGltcykpO1xuICB9XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlKSk7XG5cbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICBjb25zdCBpbmRpY2VzQXhpcyA9IG91dHB1dC5pbmRpY2VzR2V0KCdpbmRpY2VzJywgYWRqdXN0ZWRBeGlzKTtcbiAgY29uc3Qgc2l6ZUluQ29uY2F0QXhpc1N0ciA9IEFycmF5LmZyb20oQXJyYXkoc2l6ZUluQ29uY2F0QXhpcy5sZW5ndGgpLmtleXMoKSlcbiAgICAubWFwKChpKSA9PiBgdW5pZm9ybXMuc2l6ZUluQ29uY2F0QXhpcyR7aX1gKVxuICAgIC5qb2luKCcsJyk7XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuXG4gICR7KCgpID0+IHtcbiAgICBzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRTaXplJywgJ3UzMicpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3JtKGBzaXplSW5Db25jYXRBeGlzJHtpfWAsICd1MzInKTtcbiAgICB9XG4gICAgcmV0dXJuIHNoYWRlckhlbHBlci5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFycywgb3V0cHV0KTtcbiAgfSkoKX1cblxuICAke2NhbGN1bGF0ZUlucHV0SW5kZXhJbXBsKHNpemVJbkNvbmNhdEF4aXMubGVuZ3RoLCBzaXplSW5Db25jYXRBeGlzU3RyKX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG5cbiAgICB2YXIgaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcblxuICAgIGxldCBpbnB1dEluZGV4ID0gY2FsY3VsYXRlSW5wdXRJbmRleCgke2luZGljZXNBeGlzfSk7XG4gICAgaWYgKGlucHV0SW5kZXggIT0gMHUpIHtcbiAgICAgIGxldCBzaXplSW5Db25jYXRBeGlzID0gYXJyYXk8dTMyLCAke3NpemVJbkNvbmNhdEF4aXMubGVuZ3RofXU+KCR7c2l6ZUluQ29uY2F0QXhpc1N0cn0pO1xuICAgICAgJHtpbmRpY2VzQXhpc30gLT0gc2l6ZUluQ29uY2F0QXhpc1tpbnB1dEluZGV4IC0gMXVdO1xuICAgIH1cblxuICAgICR7YXNzaWduT3V0cHV0RGF0YShpbnB1dFZhcnMsIG91dHB1dCl9XG4gIH1gO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0NvbmNhdCcsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7YWRqdXN0ZWRBeGlzfWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgY29uY2F0ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBDb25jYXRBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGlucHV0cyA9IGNvbnRleHQuaW5wdXRzO1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGFkanVzdGVkQXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMuYXhpcywgaW5wdXRTaGFwZS5sZW5ndGgpO1xuICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMsIGFkanVzdGVkQXhpcyk7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRTaGFwZS5zbGljZSgpO1xuICBvdXRwdXRTaGFwZVthZGp1c3RlZEF4aXNdID0gaW5wdXRzLnJlZHVjZShcbiAgICAoc3VtLCBpbnB1dCkgPT4gc3VtICsgKGlucHV0LmRpbXMubGVuZ3RoID4gYWRqdXN0ZWRBeGlzID8gaW5wdXQuZGltc1thZGp1c3RlZEF4aXNdIDogMCksXG4gICAgMCxcbiAgKTtcbiAgLy8gMCBsZW5ndGggdGVuc29ycyBhcmUgdmFsaWQgZm9yIGNvbmNhdCwgcmVtb3ZlIHRoZW1cbiAgY29uc3Qgbm9uRW1wdHlJbnB1dHMgPSBpbnB1dHMuZmlsdGVyKChpbnB1dCkgPT4gU2hhcGVVdGlsLnNpemUoaW5wdXQuZGltcykgPiAwKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUNvbmNhdFByb2dyYW1JbmZvKG5vbkVtcHR5SW5wdXRzLCBhZGp1c3RlZEF4aXMsIG91dHB1dFNoYXBlLCBpbnB1dHNbMF0uZGF0YVR5cGUpLCB7XG4gICAgaW5wdXRzOiBub25FbXB0eUlucHV0cyxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VDb25jYXRBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQ29uY2F0QXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBheGlzOiBhdHRyaWJ1dGVzLmF4aXMgYXMgbnVtYmVyIH0pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IE1BWF9DTElQLCBNSU5fQ0xJUCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IFVuaWZvcm1zQXJyYXlUeXBlIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMge1xuICByZWFkb25seSBhY3RpdmF0aW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNsaXBNaW4/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGNsaXBNYXg/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGFscGhhPzogbnVtYmVyO1xuICByZWFkb25seSBiZXRhPzogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgZ2V0QWN0aXZhdGlvblNuaXBwZXQgPSAoXG4gIGF0dHJpYnV0ZXM6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsXG4gIHZhbHVlVHlwZTogc3RyaW5nLFxuICBiYXNlVHlwZSA9ICdmMzInLFxuKTogc3RyaW5nID0+IHtcbiAgc3dpdGNoIChhdHRyaWJ1dGVzLmFjdGl2YXRpb24pIHtcbiAgICBjYXNlICdSZWx1JzpcbiAgICAgIHJldHVybiBgdmFsdWUgPSBtYXgodmFsdWUsICR7dmFsdWVUeXBlfSgwLjApKTtgO1xuICAgIGNhc2UgJ1NpZ21vaWQnOlxuICAgICAgcmV0dXJuIGB2YWx1ZSA9ICgke3ZhbHVlVHlwZX0oMS4wKSAvICgke3ZhbHVlVHlwZX0oMS4wKSArIGV4cCgtdmFsdWUpKSk7YDtcbiAgICBjYXNlICdDbGlwJzpcbiAgICAgIHJldHVybiBgdmFsdWUgPSBjbGFtcCh2YWx1ZSwgJHt2YWx1ZVR5cGV9KCR7YmFzZVR5cGV9KHVuaWZvcm1zLmNsaXBfbWluKSksICR7dmFsdWVUeXBlfSgke1xuICAgICAgICBiYXNlVHlwZVxuICAgICAgfSh1bmlmb3Jtcy5jbGlwX21heCkpKTtgO1xuICAgIGNhc2UgJ0hhcmRTaWdtb2lkJzpcbiAgICAgIHJldHVybiBgdmFsdWUgPSBtYXgoJHt2YWx1ZVR5cGV9KDAuMCksIG1pbigke3ZhbHVlVHlwZX0oMS4wKSwgJHtiYXNlVHlwZX0odW5pZm9ybXMuYWxwaGEpICogdmFsdWUgKyAke1xuICAgICAgICBiYXNlVHlwZVxuICAgICAgfSh1bmlmb3Jtcy5iZXRhKSkpO2A7XG4gICAgY2FzZSAnTGVha3lSZWx1JzpcbiAgICAgIHJldHVybiBgdmFsdWUgPSBzZWxlY3QoJHtiYXNlVHlwZX0odW5pZm9ybXMuYWxwaGEpICogdmFsdWUsIHZhbHVlLCB2YWx1ZSA+PSAke3ZhbHVlVHlwZX0oMC4wKSk7YDtcbiAgICBjYXNlICdUYW5oJzpcbiAgICAgIHJldHVybiBgbGV0IGUyeCA9IGV4cCgtMi4wICogYWJzKHZhbHVlKSk7XG4gICAgICAgICAgICAgIHZhbHVlID0gc2lnbih2YWx1ZSkgKiAoMS4wIC0gZTJ4KSAvICgxLjAgKyBlMngpO1xuICAgICAgICBgO1xuICAgIGNhc2UgJyc6XG4gICAgICByZXR1cm4gJyc7XG4gICAgLy8gVE9ETzogYWRkaW5nIG90aGVyIGFjdGl2YXRpb25zIHRoYXQgY2FuIGJlIGZ1c2VkLlxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGFjdGl2YXRpb24gJHthdHRyaWJ1dGVzLmFjdGl2YXRpb259YCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhID0gKFxuICBhdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLFxuICBwcm9ncmFtVW5pZm9ybTogUHJvZ3JhbVVuaWZvcm1bXSxcbikgPT4ge1xuICBpZiAoYXR0cmlidXRlcy5hY3RpdmF0aW9uID09PSAnQ2xpcCcpIHtcbiAgICBwcm9ncmFtVW5pZm9ybS5wdXNoKFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogYXR0cmlidXRlcy5jbGlwTWF4ISB9LFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogYXR0cmlidXRlcy5jbGlwTWluISB9LFxuICAgICk7XG4gIH0gZWxzZSBpZiAoYXR0cmlidXRlcy5hY3RpdmF0aW9uID09PSAnSGFyZFNpZ21vaWQnKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm0ucHVzaChcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMuYWxwaGEhIH0sXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhdHRyaWJ1dGVzLmJldGEhIH0sXG4gICAgKTtcbiAgfSBlbHNlIGlmIChhdHRyaWJ1dGVzLmFjdGl2YXRpb24gPT09ICdMZWFreVJlbHUnKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm0ucHVzaCh7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhdHRyaWJ1dGVzLmFscGhhISB9KTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcyA9IChhdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUpID0+IHtcbiAgaWYgKGF0dHJpYnV0ZXMuYWN0aXZhdGlvbiA9PT0gJ0NsaXAnKSB7XG4gICAgdW5pZm9ybXMucHVzaCh7IG5hbWU6ICdjbGlwX21heCcsIHR5cGU6ICdmMzInIH0sIHsgbmFtZTogJ2NsaXBfbWluJywgdHlwZTogJ2YzMicgfSk7XG4gIH0gZWxzZSBpZiAoYXR0cmlidXRlcy5hY3RpdmF0aW9uID09PSAnSGFyZFNpZ21vaWQnKSB7XG4gICAgdW5pZm9ybXMucHVzaCh7IG5hbWU6ICdhbHBoYScsIHR5cGU6ICdmMzInIH0sIHsgbmFtZTogJ2JldGEnLCB0eXBlOiAnZjMyJyB9KTtcbiAgfSBlbHNlIGlmIChhdHRyaWJ1dGVzLmFjdGl2YXRpb24gPT09ICdMZWFreVJlbHUnKSB7XG4gICAgdW5pZm9ybXMucHVzaCh7IG5hbWU6ICdhbHBoYScsIHR5cGU6ICdmMzInIH0pO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzID0gKFxuICBhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZCxcbik6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBhY3RpdmF0aW9uID0gKGF0dHJpYnV0ZXM/LmFjdGl2YXRpb24gYXMgc3RyaW5nKSB8fCAnJztcbiAgaWYgKGFjdGl2YXRpb24gPT09ICdIYXJkU2lnbW9pZCcpIHtcbiAgICBjb25zdCBbYWxwaGEsIGJldGFdID0gKGF0dHJpYnV0ZXM/LmFjdGl2YXRpb25fcGFyYW1zIGFzIFtudW1iZXIsIG51bWJlcl0pIHx8IFswLjIsIDAuNV07XG4gICAgcmV0dXJuIHsgYWN0aXZhdGlvbiwgYWxwaGEsIGJldGEgfTtcbiAgfSBlbHNlIGlmIChhY3RpdmF0aW9uID09PSAnQ2xpcCcpIHtcbiAgICBjb25zdCBbY2xpcE1pbiwgY2xpcE1heF0gPSAoYXR0cmlidXRlcz8uYWN0aXZhdGlvbl9wYXJhbXMgYXMgW251bWJlciwgbnVtYmVyXSkgfHwgW01JTl9DTElQLCBNQVhfQ0xJUF07XG4gICAgcmV0dXJuIHsgYWN0aXZhdGlvbiwgY2xpcE1heCwgY2xpcE1pbiB9O1xuICB9IGVsc2UgaWYgKGFjdGl2YXRpb24gPT09ICdMZWFreVJlbHUnKSB7XG4gICAgY29uc3QgW2FscGhhXSA9IChhdHRyaWJ1dGVzPy5hY3RpdmF0aW9uX3BhcmFtcyBhcyBbbnVtYmVyXSkgfHwgWzAuMDFdO1xuICAgIHJldHVybiB7IGFjdGl2YXRpb24sIGFscGhhIH07XG4gIH1cbiAgcmV0dXJuIHsgYWN0aXZhdGlvbiB9O1xufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8vIHNhbXBsZWQgZnJvbSBbQHRlbnNvcmZsb3cvdGZqc10gdGZqcy1iYWNrZW5kLXdlYmdwdS9zcmMvYWN0aXZhdGlvbl91dGlsLnRzXG4vL1xuLy8gbW9kaWZpZWQgdG8gZml0IHRoZSBuZWVkcyBvZiB0aGUgcHJvamVjdFxuXG5leHBvcnQgY29uc3QgdHlwZVNuaXBwZXQgPSAoY29tcG9uZW50OiBudW1iZXIsIGRhdGFUeXBlOiBzdHJpbmcpID0+IHtcbiAgc3dpdGNoIChjb21wb25lbnQpIHtcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gZGF0YVR5cGU7XG4gICAgY2FzZSAyOlxuICAgICAgcmV0dXJuIGB2ZWMyPCR7ZGF0YVR5cGV9PmA7XG4gICAgY2FzZSAzOlxuICAgICAgcmV0dXJuIGB2ZWMzPCR7ZGF0YVR5cGV9PmA7XG4gICAgY2FzZSA0OlxuICAgICAgcmV0dXJuIGB2ZWM0PCR7ZGF0YVR5cGV9PmA7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb21wb25lbnR9LWNvbXBvbmVudCBpcyBub3Qgc3VwcG9ydGVkLmApO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgYmlhc1NuaXBwZXQgPSAoaGFzQmlhczogYm9vbGVhbik6IHN0cmluZyA9PiBgXG4gICAgICAke2hhc0JpYXMgPyAndmFsdWUgPSB2YWx1ZSArIGdldEJpYXNCeU91dHB1dENvb3Jkcyhjb29yZHMpOycgOiAnJ31cbiAgICAgIGA7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG4vLyBzYW1wbGVkIGZyb20gW0B0ZW5zb3JmbG93L3RmanNdIHRmanMtY29yZS9zcmMvb3BzL2NvbnZfdXRpbC50c1xuLy9cbi8vIG1vZGlmaWVkIHRvIGZpdCB0aGUgbmVlZHMgb2YgdGhlIHByb2plY3RcblxuZXhwb3J0IGNvbnN0IHV0aWxGdW5jdGlvbnMgPSAoc3RyaWRlU3RyOiBzdHJpbmcpID0+IGBcbmZuIGdldEluZGV4RnJvbUNvb3JkczREKGNvb3JkcyA6IHZlYzQ8aTMyPiwgc2hhcGUgOiB2ZWM0PGkzMj4pIC0+IGkzMiB7XG4gIHJldHVybiBkb3QoY29vcmRzLCB2ZWM0PGkzMj4oXG4gICAgICBzaGFwZS55ICogc2hhcGUueiAqIHNoYXBlLncsIHNoYXBlLnogKiBzaGFwZS53LCBzaGFwZS53LCAxKSk7XG59XG5mbiBnZXRPdXRwdXRJbmRleEZyb21Db29yZHMoY29vcmRzIDogdmVjNDxpMzI+KSAtPiBpMzIge1xuICByZXR1cm4gZG90KGNvb3JkcywgdmVjNDxpMzI+KFxuICAgIGkzMigke3N0cmlkZVN0cn0ueCksIGkzMigke3N0cmlkZVN0cn0ueSksIGkzMigke3N0cmlkZVN0cn0ueiksIDEpKTtcbn1cbmA7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgZ2V0RWxlbWVudEF0LFxuICBnZXRNYXhDb21wb25lbnRzLFxuICBJbmRpY2VzSGVscGVyLFxuICBpbnB1dFZhcmlhYmxlLFxuICBpbnRlcm5hbFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQge1xuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMsXG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEsXG4gIGdldEFjdGl2YXRpb25TbmlwcGV0LFxuICBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLFxufSBmcm9tICcuL2Z1c2UtdXRpbHMnO1xuXG4vLyBIZWxwZXIgdGhhdCBjb252ZXJ0IG91dHB1dCBiYXRjaCBpbmRpY2VzIHRvIGlucHV0IGJhdGNoIGluZGljZXMgdXNpbmcgb25seSB0aGUgcmFuayBhbmRcbi8vIHRoZSBzaGFwZSBpbmZvcm1hdGlvbiBpbiB1bmlmb3JtXG5leHBvcnQgY29uc3QgY29udmVydE91dHB1dEJhdGNoSW5kaWNlc1RvSW5wdXRCYXRjaEluZGljZXMgPSAoXG4gIHRhcmdldEluZGljZXNOYW1lOiBzdHJpbmcsXG4gIGlucHV0VmFyaWFibGU6IEluZGljZXNIZWxwZXIsXG4gIGlucHV0QmF0Y2hSYW5rOiBudW1iZXIsXG4gIG91dHB1dEJhdGNoUmFuazogbnVtYmVyLFxuICBiYXRjaEluZGljZXNOYW1lOiBzdHJpbmcsXG4pID0+IHtcbiAgLy8gQXNzdW1lIG91dHB1dEJhdGNoUmFuayA+PSBpbnB1dEJhdGNoUmFuaywgdGhlIGZpcnN0IG91dHB1dEJhdGNoUmFuayAtIGlucHV0QmF0Y2hSYW5rIG9mXG4gIC8vIG91dHB1dEJhdGNoUmFuayBzaG91bGQgYmUgaWdub3JlZC5cbiAgY29uc3QgZXh0ZW5kaW5nSW5wdXRSYW5rID0gb3V0cHV0QmF0Y2hSYW5rIC0gaW5wdXRCYXRjaFJhbms7XG4gIHJldHVybiBgXG4gICAgICAke0FycmF5LmZyb20oeyBsZW5ndGg6IGlucHV0QmF0Y2hSYW5rIH0pXG4gICAgICAgIC5tYXAoXG4gICAgICAgICAgKF8sIGkpID0+IGBcbiAgICAgIGlmICgke2dldEVsZW1lbnRBdChpbnB1dFZhcmlhYmxlLnNoYXBlLCBpLCBpbnB1dFZhcmlhYmxlLnJhbmspfSAhPSAxKSB7XG4gICAgICAgICR7aW5wdXRWYXJpYWJsZS5pbmRpY2VzU2V0KHRhcmdldEluZGljZXNOYW1lLCBpLCBnZXRFbGVtZW50QXQoYmF0Y2hJbmRpY2VzTmFtZSwgaSArIGV4dGVuZGluZ0lucHV0UmFuaywgb3V0cHV0QmF0Y2hSYW5rKSl9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAke2lucHV0VmFyaWFibGUuaW5kaWNlc1NldCh0YXJnZXRJbmRpY2VzTmFtZSwgaSwgMCl9XG4gICAgICB9YCxcbiAgICAgICAgKVxuICAgICAgICAuam9pbignJyl9XG5gO1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZU5haXZlTWF0bXVsUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhY3RpdmF0aW9uQXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyxcbiAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICByZXNoYXBlZE91dHB1dFNoYXBlPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGlzQ2hhbm5lbHNMYXN0ID0gZmFsc2UgLyogb25seSB1c2VkIGZvciBjb252MmRCeU1hdE11bCovLFxuICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbj86IChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pID0+IG51bWJlcltdLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBhU2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgYlNoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG5cbiAgY29uc3QgTSA9IGFTaGFwZVthU2hhcGUubGVuZ3RoIC0gMl07XG4gIGNvbnN0IE4gPSBiU2hhcGVbYlNoYXBlLmxlbmd0aCAtIDFdO1xuICBjb25zdCBLID0gYVNoYXBlW2FTaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoTik7XG4gIGNvbnN0IGFDb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhLKTtcbiAgY29uc3Qgb3V0cHV0TnVtYmVyID0gZ2V0TWF4Q29tcG9uZW50cyhNKTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIGNvbXBvbmVudHMgLyBvdXRwdXROdW1iZXI7XG4gIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID4gMjtcbiAgY29uc3Qgb3V0ZXJEaW1zID0gcmVzaGFwZWRPdXRwdXRTaGFwZSA/IHJlc2hhcGVkT3V0cHV0U2hhcGUuc2xpY2UoMCwgLTIpIDogb3V0cHV0U2hhcGUuc2xpY2UoMCwgLTIpO1xuICBjb25zdCBiYXRjaFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRlckRpbXMpO1xuICBjb25zdCBvdXRwdXRTaGFwZUluU2hhZGVyID0gW2JhdGNoU2l6ZSwgTSwgTl07XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE0gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTiB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBLIH0sXG4gIF07XG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEoYWN0aXZhdGlvbkF0dHJpYnV0ZXMsIHByb2dyYW1Vbmlmb3Jtcyk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dGVyRGltcywgYVNoYXBlLCBiU2hhcGUpKTtcbiAgaWYgKGhhc0JpYXMpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMl0uZGltcykpO1xuICB9XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlSW5TaGFkZXIpKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBiYXRjaERpbXMgPSBpbnRlcm5hbFZhcmlhYmxlKCdiYXRjaF9kaW1zJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRlckRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBhID0gaW5wdXRWYXJpYWJsZSgnYScsIGlucHV0c1swXS5kYXRhVHlwZSwgYVNoYXBlLmxlbmd0aCwgYUNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGIgPSBpbnB1dFZhcmlhYmxlKCdiJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBiU2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZUluU2hhZGVyLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgYmFzZVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUob3V0cHV0LnR5cGUudGVuc29yKTtcbiAgICBjb25zdCBhcHBseUFjdGl2YXRpb24gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhY3RpdmF0aW9uQXR0cmlidXRlcywgb3V0cHV0LnR5cGUudmFsdWUsIGJhc2VUeXBlKTtcbiAgICBjb25zdCBpbnB1dFZhcmlhYmxlcyA9IFthLCBiXTtcbiAgICBsZXQgcHJvY2Vzc0JpYXMgPSAnJztcbiAgICBpZiAoaGFzQmlhcykge1xuICAgICAgY29uc3QgYmlhc0NvbXBvbmVudHMgPSBpc0NoYW5uZWxzTGFzdCA/IGNvbXBvbmVudHMgOiAxO1xuICAgICAgaW5wdXRWYXJpYWJsZXMucHVzaChpbnB1dFZhcmlhYmxlKCdiaWFzJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcy5sZW5ndGgsIGJpYXNDb21wb25lbnRzKSk7XG4gICAgICBwcm9jZXNzQmlhcyA9IGAke1xuICAgICAgICBpc0NoYW5uZWxzTGFzdCA/IGB2YWx1ZSArPSBiaWFzW2NvbCAvICR7Ymlhc0NvbXBvbmVudHN9XTtgIDogYHZhbHVlICs9ICR7b3V0cHV0LnR5cGUudmFsdWV9KGJpYXNbcm93ICsgaV0pO2BcbiAgICAgIH1gO1xuICAgIH1cblxuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ00nLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnTicsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdLJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuICAgIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcyhhY3RpdmF0aW9uQXR0cmlidXRlcywgdW5pZm9ybXMpO1xuXG4gICAgY29uc3QgY2FsY1Jlc3VsdCA9ICgpOiBzdHJpbmcgPT4ge1xuICAgICAgbGV0IGNhbGNTdHIgPSBgdmFyIGFfZGF0YTogJHthLnR5cGUudmFsdWV9O2A7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFDb21wb25lbnRzOyBpKyspIHtcbiAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgICAgIGxldCBiX2RhdGEke2l9ID0gYlsoYl9vZmZzZXQgKyAoayArICR7aX0pICogdW5pZm9ybXMuTiArIGNvbCkgLyAke2NvbXBvbmVudHN9XTtgO1xuICAgICAgfVxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXROdW1iZXI7IGkrKykge1xuICAgICAgICBjYWxjU3RyICs9IGBhX2RhdGEgPSBhWyhhX29mZnNldCArIChyb3cgKyAke2l9KSAqIHVuaWZvcm1zLksgKyBrKSAvICR7YUNvbXBvbmVudHN9XTtgO1xuXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgYUNvbXBvbmVudHM7IGorKykge1xuICAgICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgICAgdmFsdWVzWyR7aX1dID0gZm1hKCR7Yi50eXBlLnZhbHVlfShhX2RhdGEke2FDb21wb25lbnRzID09PSAxID8gJycgOiBgWyR7an1dYH0pLCBiX2RhdGEke2p9LCB2YWx1ZXNbJHtpfV0pO1xcbmA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBjYWxjU3RyO1xuICAgIH07XG5cbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlclxuICAgIC5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKVxuICAgIC5yZWdpc3RlckludGVybmFsVmFyaWFibGVzKGJhdGNoRGltcylcbiAgICAuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcmlhYmxlcywgb3V0cHV0KX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICBsZXQgY29sID0gKGdsb2JhbF9pZHggJSAodW5pZm9ybXMuTiAvICR7Y29tcG9uZW50c30pKSAqICR7Y29tcG9uZW50c307XG4gICAgdmFyIGluZGV4MSA9IGdsb2JhbF9pZHggLyAodW5pZm9ybXMuTiAvICR7Y29tcG9uZW50c30pO1xuICAgIGxldCBzdHJpZGUxID0gdW5pZm9ybXMuTSAvICR7b3V0cHV0TnVtYmVyfTtcbiAgICBsZXQgcm93ID0gKGluZGV4MSAlIHN0cmlkZTEpICogJHtvdXRwdXROdW1iZXJ9O1xuICAgIGxldCBiYXRjaCA9IGluZGV4MSAvIHN0cmlkZTE7XG5cbiAgICAke291dHB1dFNoYXBlLmxlbmd0aCA9PT0gMiA/ICcnIDogYGxldCBiYXRjaF9pbmRpY2VzID0gJHtiYXRjaERpbXMub2Zmc2V0VG9JbmRpY2VzKCdiYXRjaCcpfTtgfVxuXG4gICAgdmFyIGFfaW5kaWNlczogJHthLnR5cGUuaW5kaWNlc307XG4gICAgJHtjb252ZXJ0T3V0cHV0QmF0Y2hJbmRpY2VzVG9JbnB1dEJhdGNoSW5kaWNlcygnYV9pbmRpY2VzJywgYSwgYS5yYW5rIC0gMiwgYmF0Y2hEaW1zLnJhbmssICdiYXRjaF9pbmRpY2VzJyl9XG4gICAgJHthLmluZGljZXNTZXQoJ2FfaW5kaWNlcycsIGEucmFuayAtIDIsIDApfVxuICAgICR7YS5pbmRpY2VzU2V0KCdhX2luZGljZXMnLCBhLnJhbmsgLSAxLCAwKX1cbiAgICBsZXQgYV9vZmZzZXQgPSAke2EuaW5kaWNlc1RvT2Zmc2V0KCdhX2luZGljZXMnKX07XG5cbiAgICB2YXIgYl9pbmRpY2VzOiAke2IudHlwZS5pbmRpY2VzfTtcbiAgICAke2NvbnZlcnRPdXRwdXRCYXRjaEluZGljZXNUb0lucHV0QmF0Y2hJbmRpY2VzKCdiX2luZGljZXMnLCBiLCBiLnJhbmsgLSAyLCBiYXRjaERpbXMucmFuaywgJ2JhdGNoX2luZGljZXMnKX1cbiAgICAke2IuaW5kaWNlc1NldCgnYl9pbmRpY2VzJywgYi5yYW5rIC0gMiwgMCl9XG4gICAgJHtiLmluZGljZXNTZXQoJ2JfaW5kaWNlcycsIGIucmFuayAtIDEsIDApfVxuICAgIGxldCBiX29mZnNldCA9ICR7Yi5pbmRpY2VzVG9PZmZzZXQoJ2JfaW5kaWNlcycpfTtcbiAgICB2YXIgdmFsdWVzOiBhcnJheTwke291dHB1dC50eXBlLnZhbHVlfSwgJHtvdXRwdXROdW1iZXJ9PjtcbiAgICBmb3IgKHZhciBrOiB1MzIgPSAwdTsgayA8IHVuaWZvcm1zLks7IGsgPSBrICsgJHthQ29tcG9uZW50c30pIHtcbiAgICAgICR7Y2FsY1Jlc3VsdCgpfVxuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMHU7IGkgPCAke291dHB1dE51bWJlcn11OyBpKyspIHtcbiAgICAgIHZhciB2YWx1ZSA9IHZhbHVlc1tpXTtcbiAgICAgICR7cHJvY2Vzc0JpYXN9XG4gICAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAgIGxldCBjdXJfaW5kaWNlcyA9ICR7b3V0cHV0LnR5cGUuaW5kaWNlc30oYmF0Y2gsIHJvdyArIGksIGNvbCk7XG4gICAgICBsZXQgb2Zmc2V0ID0gJHtvdXRwdXQuaW5kaWNlc1RvT2Zmc2V0KCdjdXJfaW5kaWNlcycpfTtcbiAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KGBvZmZzZXQgLyAke2NvbXBvbmVudHN9YCwgJ3ZhbHVlJyl9O1xuICAgIH1cbiAgfVxuICBgO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdNYXRNdWxOYWl2ZScsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2FjdGl2YXRpb25BdHRyaWJ1dGVzLmFjdGl2YXRpb259OyR7Y29tcG9uZW50c307JHthQ29tcG9uZW50c307JHtvdXRwdXROdW1iZXJ9OyR7aXNDaGFubmVsc0xhc3R9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBoYXNCaWFzID8gWydyYW5rJywgJ3JhbmsnLCAncmFuayddIDogWydyYW5rJywgJ3JhbmsnXSxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBkaW1zOiBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiA/IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uKG91dHB1dFNoYXBlKSA6IG91dHB1dFNoYXBlLFxuICAgICAgICAgIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG4vLyBzYW1wbGVkIGZyb20gW0B0ZW5zb3JmbG93L3RmanNdIHRmanMtYmFja2VuZC13ZWJncHUvc3JjL21hdG11bF9wYWNrZWRfd2ViZ3B1LnRzXG4vL1xuLy8gbW9kaWZpZWQgdG8gZml0IHRoZSBuZWVkcyBvZiB0aGUgcHJvamVjdFxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7IFByb2dyYW1JbmZvLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi8uLi90eXBlcyc7XG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRWYXJpYWJsZSxcbiAgaW50ZXJuYWxWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi4vY29tbW9uJztcbmltcG9ydCB7XG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcyxcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YSxcbiAgZ2V0QWN0aXZhdGlvblNuaXBwZXQsXG4gIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsXG59IGZyb20gJy4uL2Z1c2UtdXRpbHMnO1xuaW1wb3J0IHsgY29udmVydE91dHB1dEJhdGNoSW5kaWNlc1RvSW5wdXRCYXRjaEluZGljZXMgfSBmcm9tICcuLi9tYXRtdWwtc2hhZGVycyc7XG5cbmltcG9ydCB7IHR5cGVTbmlwcGV0IH0gZnJvbSAnLi9hY3RpdmF0aW9uX3V0aWwnO1xuXG5jb25zdCB3cml0ZURhdGFUb1N1YkFWZWM0U25pcHBldCA9ICh0cmFuc3Bvc2U6IGJvb2xlYW4sIGJhdGNoRGltcz86IEluZGljZXNIZWxwZXIpID0+IHtcbiAgaWYgKHRyYW5zcG9zZSkge1xuICAgIHJldHVybiBgXG4gICAgICAgIG1tX0FzdWJbaW5wdXRSb3ddW2lucHV0Q29sXSA9IG1tX3JlYWRBKGJhdGNoLFxuICAgICAgICAgIGtTdGFydCArIGlucHV0Um93LFxuICAgICAgICAgIGdsb2JhbFJvd1N0YXJ0IC8gaW5uZXJFbGVtZW50U2l6ZSArIGlucHV0Q29sJHtiYXRjaERpbXMgPyAnLCBiYXRjaEluZGljZXMnIDogJyd9KTtcbiAgICAgICAgYDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYFxuICAgICAgICBtbV9Bc3ViW2lucHV0Um93XVtpbnB1dENvbF0gPSBtbV9yZWFkQShiYXRjaCxcbiAgICAgICAgICBnbG9iYWxSb3cgKyBpbm5lclJvdyxcbiAgICAgICAgICBrU3RhcnQgLyBpbm5lckVsZW1lbnRTaXplICsgaW5wdXRDb2wke2JhdGNoRGltcyA/ICcsIGJhdGNoSW5kaWNlcycgOiAnJ30pO1xuICAgICAgICBgO1xuICB9XG59O1xuXG5jb25zdCBjYWxjdWxhdGVSZXN1bHRTbmlwcGV0ID0gKHRyYW5zcG9zZUE6IGJvb2xlYW4sIGlubmVyRWxlbWVudFNpemU6IG51bWJlcikgPT4ge1xuICBpZiAodHJhbnNwb3NlQSkge1xuICAgIHJldHVybiBgXG4gICAgICAgIGxldCBBQ2FjaGVkMCA9IG1tX0FzdWJbayAqIGlubmVyRWxlbWVudFNpemVdW2xvY2FsUm93XTtcbiAgICAgICAgbGV0IEFDYWNoZWQxID0gbW1fQXN1YltrICogaW5uZXJFbGVtZW50U2l6ZSArIDFdW2xvY2FsUm93XTtcbiAgICAgICAgbGV0IEFDYWNoZWQyID0gbW1fQXN1YltrICogaW5uZXJFbGVtZW50U2l6ZSArIDJdW2xvY2FsUm93XTtcbiAgICAgICAgJHtpbm5lckVsZW1lbnRTaXplID09PSAzID8gJycgOiAnbGV0IEFDYWNoZWQzID0gbW1fQXN1YltrICogaW5uZXJFbGVtZW50U2l6ZSArIDNdW2xvY2FsUm93XTsnfVxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvd1BlclRocmVhZDsgaSA9IGkgKyAxKSB7XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDAgKiBBQ2FjaGVkMFtpXSArIGFjY1tpXTtcbiAgICAgICAgICBhY2NbaV0gPSBCQ2FjaGVkMSAqIEFDYWNoZWQxW2ldICsgYWNjW2ldO1xuICAgICAgICAgIGFjY1tpXSA9IEJDYWNoZWQyICogQUNhY2hlZDJbaV0gKyBhY2NbaV07XG4gICAgICAgICAgJHtpbm5lckVsZW1lbnRTaXplID09PSAzID8gJycgOiAnYWNjW2ldID0gQkNhY2hlZDMgKiBBQ2FjaGVkM1tpXSArIGFjY1tpXTsnfVxuICAgICAgICB9YDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYFxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvd1BlclRocmVhZDsgaSA9IGkgKyAxKSB7XG4gICAgICAgICAgbGV0IEFDYWNoZWQgPSBtbV9Bc3ViW3RpbGVSb3cgKyBpXVtrXTtcbiAgICAgICAgICBhY2NbaV0gPSBCQ2FjaGVkMCAqIEFDYWNoZWQueCArIGFjY1tpXTtcbiAgICAgICAgICBhY2NbaV0gPSBCQ2FjaGVkMSAqIEFDYWNoZWQueSArIGFjY1tpXTtcbiAgICAgICAgICBhY2NbaV0gPSBCQ2FjaGVkMiAqIEFDYWNoZWQueiArIGFjY1tpXTtcbiAgICAgICAgICAke2lubmVyRWxlbWVudFNpemUgPT09IDMgPyAnJyA6ICdhY2NbaV0gPSBCQ2FjaGVkMyAqIEFDYWNoZWQudyArIGFjY1tpXTsnfVxuICAgICAgICB9YDtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IG1ha2VNYXRNdWxQYWNrZWRWZWM0U291cmNlID0gKFxuICB3b3JrUGVyVGhyZWFkOiBudW1iZXJbXSxcbiAgd29ya2dyb3VwU2l6ZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICB0eXBlID0gJ2YzMicsXG4gIGJhdGNoRGltcz86IEluZGljZXNIZWxwZXIsXG4gIHRyYW5zcG9zZUEgPSBmYWxzZSxcbiAgdGlsZUlubmVyID0gMzIsXG4gIHNwbGl0SyA9IGZhbHNlLFxuICBzcGxpdGVkRGltSW5uZXIgPSAzMixcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IHRpbGVBT3V0ZXIgPSB3b3JrZ3JvdXBTaXplWzFdICogd29ya1BlclRocmVhZFsxXTtcbiAgY29uc3QgdGlsZUJPdXRlciA9IHdvcmtncm91cFNpemVbMF0gKiB3b3JrUGVyVGhyZWFkWzBdO1xuICBjb25zdCB0aWxlQVdpZHRoID0gdHJhbnNwb3NlQSA/IHRpbGVBT3V0ZXIgOiB0aWxlSW5uZXI7XG4gIGNvbnN0IHRpbGVBSGlnaHQgPSB0cmFuc3Bvc2VBID8gdGlsZUlubmVyIDogdGlsZUFPdXRlcjtcbiAgY29uc3QgaW5uZXJFbGVtZW50U2l6ZSA9IHRpbGVBV2lkdGggLyB3b3JrZ3JvdXBTaXplWzBdO1xuICBjb25zdCByb3dQZXJUaHJlYWRCID0gdGlsZUlubmVyIC8gd29ya2dyb3VwU2l6ZVsxXTtcblxuICBpZiAoXG4gICAgIShcbiAgICAgICgodHJhbnNwb3NlQSAmJiBpbm5lckVsZW1lbnRTaXplID09PSA0ICYmIHdvcmtQZXJUaHJlYWRbMV0gPT09IDQpIHx8XG4gICAgICAgICghdHJhbnNwb3NlQSAmJiAoaW5uZXJFbGVtZW50U2l6ZSA9PT0gMyB8fCBpbm5lckVsZW1lbnRTaXplID09PSA0KSkpICYmXG4gICAgICB0aWxlQVdpZHRoICUgd29ya2dyb3VwU2l6ZVswXSA9PT0gMCAmJlxuICAgICAgdGlsZUlubmVyICUgd29ya2dyb3VwU2l6ZVsxXSA9PT0gMCAmJlxuICAgICAgd29ya1BlclRocmVhZFswXSA9PT0gNFxuICAgIClcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJZiB0cmFuc3Bvc2VBICR7dHJhbnNwb3NlQX0gaXMgdHJ1ZSwgaW5uZXJFbGVtZW50U2l6ZSAke2lubmVyRWxlbWVudFNpemV9IGFuZCB3b3JrUGVyVGhyZWFkWzFdICR7d29ya1BlclRocmVhZFsxXX0gbXVzdCBiZSA0LlxuICAgICAgT3RoZXJ3aXNlLCBpbm5lckVsZW1lbnRTaXplICR7aW5uZXJFbGVtZW50U2l6ZX0gbXVzdCBiZSAzIG9yIDQuXG4gIHRpbGVBV2lkdGggJHt0aWxlQVdpZHRofSBtdXN0IGJlIGRpdmlzaWJsZSBieSB3b3JrZ3JvdXBTaXplWzBdJHt3b3JrZ3JvdXBTaXplWzBdfS4gdGlsZUlubmVyICR7dGlsZUlubmVyfSBtdXN0IGJlIGRpdmlzaWJsZSBieSB3b3JrZ3JvdXBTaXplWzFdICR7d29ya2dyb3VwU2l6ZVsxXX0uIGNvbFBlclRocmVhZCAke3dvcmtQZXJUaHJlYWRbMF19IG11c3QgYmUgNC5gKTtcbiAgfVxuICByZXR1cm4gYFxudmFyPHdvcmtncm91cD4gbW1fQXN1YjogYXJyYXk8YXJyYXk8dmVjJHtpbm5lckVsZW1lbnRTaXplfTwke3R5cGV9PiwgJHt0aWxlQVdpZHRoIC8gaW5uZXJFbGVtZW50U2l6ZX0+LCAke3RpbGVBSGlnaHR9PjtcbnZhcjx3b3JrZ3JvdXA+IG1tX0JzdWI6IGFycmF5PGFycmF5PHZlYzQ8JHt0eXBlfT4sICR7dGlsZUJPdXRlciAvIHdvcmtQZXJUaHJlYWRbMF19PiwgJHt0aWxlSW5uZXJ9PjtcblxuY29uc3Qgcm93UGVyVGhyZWFkID0gJHt3b3JrUGVyVGhyZWFkWzFdfTtcbmNvbnN0IGNvbFBlclRocmVhZCA9ICR7d29ya1BlclRocmVhZFswXX07XG5jb25zdCBpbm5lckVsZW1lbnRTaXplID0gJHtpbm5lckVsZW1lbnRTaXplfTtcbmNvbnN0IHRpbGVJbm5lciA9ICR7dGlsZUlubmVyfTtcblxuQGNvbXB1dGUgQHdvcmtncm91cF9zaXplKCR7d29ya2dyb3VwU2l6ZVswXX0sICR7d29ya2dyb3VwU2l6ZVsxXX0sICR7d29ya2dyb3VwU2l6ZVsyXX0pXG5mbiBtYWluKEBidWlsdGluKGxvY2FsX2ludm9jYXRpb25faWQpIGxvY2FsSWQgOiB2ZWMzPHUzMj4sXG4gICAgICAgIEBidWlsdGluKGdsb2JhbF9pbnZvY2F0aW9uX2lkKSBnbG9iYWxJZCA6IHZlYzM8dTMyPixcbiAgICAgICAgQGJ1aWx0aW4od29ya2dyb3VwX2lkKSB3b3JrZ3JvdXBJZCA6IHZlYzM8dTMyPikge1xuICBsZXQgbG9jYWxSb3cgPSBpMzIobG9jYWxJZC55KTtcbiAgbGV0IHRpbGVSb3cgPSBsb2NhbFJvdyAqIHJvd1BlclRocmVhZDtcbiAgbGV0IHRpbGVDb2wgPSBpMzIobG9jYWxJZC54KTtcblxuICBsZXQgZ2xvYmFsUm93ID1pMzIoZ2xvYmFsSWQueSkgKiByb3dQZXJUaHJlYWQ7XG4gIGxldCBnbG9iYWxDb2wgPSBpMzIoZ2xvYmFsSWQueCk7XG4gIGxldCBiYXRjaCA9ICR7c3BsaXRLID8gJzAnIDogJ2kzMihnbG9iYWxJZC56KSd9O1xuICAke2JhdGNoRGltcyA/IGBsZXQgYmF0Y2hJbmRpY2VzID0gJHtiYXRjaERpbXMub2Zmc2V0VG9JbmRpY2VzKCd1MzIoYmF0Y2gpJyl9O2AgOiAnJ31cbiAgbGV0IGdsb2JhbFJvd1N0YXJ0ID0gaTMyKHdvcmtncm91cElkLnkpICogJHt0aWxlQU91dGVyfTtcblxuICBsZXQgbnVtX3RpbGVzID0gJHtzcGxpdEsgPyBgJHtNYXRoLmNlaWwoc3BsaXRlZERpbUlubmVyIC8gdGlsZUlubmVyKX1gIDogJyh1bmlmb3Jtcy5kaW1faW5uZXIgLSAxKSAvIHRpbGVJbm5lciArIDEnfTtcbiAgdmFyIGtTdGFydCA9ICR7c3BsaXRLID8gYGkzMihnbG9iYWxJZC56KSAqICR7c3BsaXRlZERpbUlubmVyfWAgOiAnMCd9O1xuXG4gIHZhciBhY2M6IGFycmF5PHZlYzQ8JHt0eXBlfT4sIHJvd1BlclRocmVhZD47XG5cbiAgLy8gTG9vcCBvdmVyIHNoYXJlZCBkaW1lbnNpb24uXG4gIGxldCB0aWxlUm93QiA9IGxvY2FsUm93ICogJHtyb3dQZXJUaHJlYWRCfTtcbiAgZm9yICh2YXIgdCA9IDA7IHQgPCBudW1fdGlsZXM7IHQgPSB0ICsgMSkge1xuICAgICAgLy8gTG9hZCBvbmUgdGlsZSBvZiBBIGludG8gbG9jYWwgbWVtb3J5LlxuICAgICAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8IHJvd1BlclRocmVhZDsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgICAgICAgICBsZXQgaW5wdXRSb3cgPSB0aWxlUm93ICsgaW5uZXJSb3c7XG4gICAgICAgICAgbGV0IGlucHV0Q29sID0gdGlsZUNvbDtcbiAgICAgICAgICAke3dyaXRlRGF0YVRvU3ViQVZlYzRTbmlwcGV0KHRyYW5zcG9zZUEsIGJhdGNoRGltcyl9XG4gICAgICB9XG5cbiAgICAgIC8vIExvYWQgb25lIHRpbGUgb2YgQiBpbnRvIGxvY2FsIG1lbW9yeS5cbiAgICAgIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCAke3Jvd1BlclRocmVhZEJ9OyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgICAgIGxldCBpbnB1dFJvdyA9IHRpbGVSb3dCICsgaW5uZXJSb3c7XG4gICAgICAgICAgbGV0IGlucHV0Q29sID0gdGlsZUNvbDtcbiAgICAgICAgICBtbV9Cc3ViW2lucHV0Um93XVtpbnB1dENvbF0gPSBtbV9yZWFkQihiYXRjaCwga1N0YXJ0ICsgaW5wdXRSb3csIGdsb2JhbENvbCR7XG4gICAgICAgICAgICBiYXRjaERpbXMgPyAnLCBiYXRjaEluZGljZXMnIDogJydcbiAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGtTdGFydCA9IGtTdGFydCArIHRpbGVJbm5lcjtcbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgLy8gQ29tcHV0ZSBhY2MgdmFsdWVzIGZvciBhIHNpbmdsZSB0aHJlYWQuXG4gICAgICBmb3IgKHZhciBrID0gMDsgayA8IHRpbGVJbm5lciAvIGlubmVyRWxlbWVudFNpemU7IGsgPSBrICsgMSkge1xuICAgICAgICAgIGxldCBCQ2FjaGVkMCA9IG1tX0JzdWJbayAqIGlubmVyRWxlbWVudFNpemVdW3RpbGVDb2xdO1xuICAgICAgICAgIGxldCBCQ2FjaGVkMSA9IG1tX0JzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAxXVt0aWxlQ29sXTtcbiAgICAgICAgICBsZXQgQkNhY2hlZDIgPSBtbV9Cc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplICsgMl1bdGlsZUNvbF07XG4gICAgICAgICAgJHtpbm5lckVsZW1lbnRTaXplID09PSAzID8gJycgOiAnbGV0IEJDYWNoZWQzID0gbW1fQnN1YltrICogaW5uZXJFbGVtZW50U2l6ZSArIDNdW3RpbGVDb2xdOyd9XG5cbiAgICAgICAgICAke2NhbGN1bGF0ZVJlc3VsdFNuaXBwZXQodHJhbnNwb3NlQSwgaW5uZXJFbGVtZW50U2l6ZSl9XG4gICAgICB9XG5cbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgfVxuXG4gIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCByb3dQZXJUaHJlYWQ7IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgICBtbV93cml0ZShiYXRjaCwgZ2xvYmFsUm93ICsgaW5uZXJSb3csIGdsb2JhbENvbCwgYWNjW2lubmVyUm93XSk7XG4gIH1cbn1gO1xufTtcblxuY29uc3Qgd3JpdGVEYXRhVG9TdWJBU25pcHBldCA9ICh0cmFuc3Bvc2U6IGJvb2xlYW4sIGJhdGNoRGltcz86IEluZGljZXNIZWxwZXIpID0+IHtcbiAgaWYgKHRyYW5zcG9zZSkge1xuICAgIHJldHVybiBgXG4gICAgICAgICAgICBtbV9Bc3ViW2lucHV0Um93XVtpbnB1dENvbF0gPSBtbV9yZWFkQShiYXRjaCxcbiAgICAgICAgICAgICAga1N0YXJ0ICsgaW5wdXRSb3csXG4gICAgICAgICAgICAgIGdsb2JhbFJvd1N0YXJ0ICsgaW5wdXRDb2wke2JhdGNoRGltcyA/ICcsIGJhdGNoSW5kaWNlcycgOiAnJ30pO1xuICAgICAgICAgICAgYDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYFxuICAgICAgICAgICAgbW1fQXN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEEoYmF0Y2gsXG4gICAgICAgICAgICAgIGdsb2JhbFJvd1N0YXJ0ICsgaW5wdXRSb3csXG4gICAgICAgICAgICAgIGtTdGFydCArIGlucHV0Q29sJHtiYXRjaERpbXMgPyAnLCBiYXRjaEluZGljZXMnIDogJyd9KTtcbiAgICAgICAgICAgIGA7XG4gIH1cbn07XG5cbmNvbnN0IHJlYWREYXRhRnJvbVN1YkFTbmlwcGV0ID0gKHRyYW5zcG9zZUE6IGJvb2xlYW4pID0+XG4gIHRyYW5zcG9zZUEgPyAnbGV0IEFDYWNoZWQgPSBtbV9Bc3ViW2tdW3RpbGVSb3cgKyBpbm5lclJvd107JyA6ICdsZXQgQUNhY2hlZCA9IG1tX0FzdWJbdGlsZVJvdyArIGlubmVyUm93XVtrXTsnO1xuXG4vLyBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzIG1lYW5zIHNlcXVlbnRpYWwgZGF0YSBpbiBtZW1vcnkgaXMgYWNjZXNzZWQgYnlcbi8vIHRocmVhZHMsIGluc3RlYWQgb2YgYSBzaW5nbGUgdGhyZWFkIChkZWZhdWx0IGJlaGF2aW9yKS5cbmV4cG9ydCBjb25zdCBtYWtlTWF0TXVsUGFja2VkU291cmNlID0gKFxuICB3b3JrUGVyVGhyZWFkOiBudW1iZXJbXSxcbiAgd29ya2dyb3VwU2l6ZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICB0eXBlID0gJ2YzMicsXG4gIGJhdGNoRGltcz86IEluZGljZXNIZWxwZXIsXG4gIHRyYW5zcG9zZUEgPSBmYWxzZSxcbiAgdGlsZUlubmVyID0gMzIsXG4gIHNwbGl0SyA9IGZhbHNlLFxuICBzcGxpdGVkRGltSW5uZXIgPSAzMixcbiAgc2VxdWVudGlhbEFjY2Vzc0J5VGhyZWFkcyA9IGZhbHNlLFxuKTogc3RyaW5nID0+IHtcbiAgY29uc3QgdGlsZUFPdXRlciA9IHdvcmtQZXJUaHJlYWRbMV0gKiB3b3JrZ3JvdXBTaXplWzFdO1xuICBjb25zdCB0aWxlQk91dGVyID0gd29ya1BlclRocmVhZFswXSAqIHdvcmtncm91cFNpemVbMF07XG4gIGNvbnN0IHRpbGVBV2lkdGggPSB0cmFuc3Bvc2VBID8gdGlsZUFPdXRlciA6IHRpbGVJbm5lcjtcbiAgY29uc3QgdGlsZUFIaWdodCA9IHRyYW5zcG9zZUEgPyB0aWxlSW5uZXIgOiB0aWxlQU91dGVyO1xuXG4gIGlmIChcbiAgICAhKHRpbGVBSGlnaHQgJSB3b3JrZ3JvdXBTaXplWzFdID09PSAwICYmIHRpbGVBV2lkdGggJSB3b3JrZ3JvdXBTaXplWzBdID09PSAwICYmIHRpbGVJbm5lciAlIHdvcmtncm91cFNpemVbMV0gPT09IDApXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGB0aWxlQUhpZ2h0ICR7dGlsZUFIaWdodH0gbXVzdCBiZSBkaXZpc2libGUgYnkgd29ya2dyb3VwU2l6ZVsxXSR7d29ya2dyb3VwU2l6ZVsxXX0sIHRpbGVBV2lkdGggJHt0aWxlQVdpZHRofSBtdXN0IGJlIGRpdmlzaWJsZSBieSB3b3JrZ3JvdXBTaXplWzBdJHt3b3JrZ3JvdXBTaXplWzBdfSwgdGlsZUlubmVyICR7dGlsZUlubmVyfSBtdXN0IGJlIGRpdmlzaWJsZSBieSB3b3JrZ3JvdXBTaXplWzFdJHt3b3JrZ3JvdXBTaXplWzFdfWAsXG4gICAgKTtcbiAgfVxuICBjb25zdCByb3dQZXJUaHJlYWRBID0gdGlsZUFIaWdodCAvIHdvcmtncm91cFNpemVbMV07XG4gIGNvbnN0IGNvbFBlclRocmVhZEEgPSB0aWxlQVdpZHRoIC8gd29ya2dyb3VwU2l6ZVswXTtcbiAgY29uc3Qgcm93UGVyVGhyZWFkQiA9IHRpbGVJbm5lciAvIHdvcmtncm91cFNpemVbMV07XG4gIGNvbnN0IG1hdG11bFNuaXBwZXQgPSBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzXG4gICAgPyBgXG4gICAgbGV0IGxvY2FsUm93ID0gaTMyKGxvY2FsSWQueSk7XG4gICAgbGV0IGxvY2FsQ29sID0gaTMyKGxvY2FsSWQueCk7XG4gICAgbGV0IGdsb2JhbFJvd1N0YXJ0ID0gaTMyKHdvcmtncm91cElkLnkpICogJHt0aWxlQU91dGVyfTtcbiAgICBsZXQgZ2xvYmFsQ29sU3RhcnQgPSBpMzIod29ya2dyb3VwSWQueCkgKiAke3RpbGVCT3V0ZXJ9O1xuXG4gICAgLy8gTG9vcCBvdmVyIHNoYXJlZCBkaW1lbnNpb24uXG4gICAgZm9yICh2YXIgdCA9IDA7IHQgPCBudW1fdGlsZXM7IHQgPSB0ICsgMSkge1xuICAgICAgLy8gTG9hZCBvbmUgdGlsZSBvZiBBIGludG8gbG9jYWwgbWVtb3J5LlxuICAgICAgZm9yICh2YXIgaW5wdXRSb3cgPSBsb2NhbFJvdzsgaW5wdXRSb3cgPCAke3RpbGVBSGlnaHR9OyBpbnB1dFJvdyA9IGlucHV0Um93ICsgJHt3b3JrZ3JvdXBTaXplWzFdfSkge1xuICAgICAgICBmb3IgKHZhciBpbnB1dENvbCA9IGxvY2FsQ29sOyBpbnB1dENvbCA8ICR7dGlsZUFXaWR0aH07IGlucHV0Q29sID0gaW5wdXRDb2wgKyAke3dvcmtncm91cFNpemVbMF19KSB7XG4gICAgICAgICAgJHt3cml0ZURhdGFUb1N1YkFTbmlwcGV0KHRyYW5zcG9zZUEsIGJhdGNoRGltcyl9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIExvYWQgb25lIHRpbGUgb2YgQiBpbnRvIGxvY2FsIG1lbW9yeS5cbiAgICAgIGZvciAodmFyIGlucHV0Um93ID0gbG9jYWxSb3c7IGlucHV0Um93IDwgJHt0aWxlSW5uZXJ9OyBpbnB1dFJvdyA9IGlucHV0Um93ICsgJHt3b3JrZ3JvdXBTaXplWzFdfSkge1xuICAgICAgICAgICAgZm9yICh2YXIgaW5wdXRDb2wgPSBsb2NhbENvbDsgaW5wdXRDb2wgPCAke3RpbGVCT3V0ZXJ9OyBpbnB1dENvbCA9IGlucHV0Q29sICsgJHt3b3JrZ3JvdXBTaXplWzBdfSkge1xuICAgICAgICAgIG1tX0JzdWJbaW5wdXRSb3ddW2lucHV0Q29sXSA9IG1tX3JlYWRCKGJhdGNoLFxuICAgICAgICAgICAga1N0YXJ0ICsgaW5wdXRSb3csXG4gICAgICAgICAgICBnbG9iYWxDb2xTdGFydCArIGlucHV0Q29sJHtiYXRjaERpbXMgPyAnLCBiYXRjaEluZGljZXMnIDogJyd9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAga1N0YXJ0ID0ga1N0YXJ0ICsgdGlsZUlubmVyO1xuICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgICAvLyBDb21wdXRlIGFjYyB2YWx1ZXMgZm9yIGEgc2luZ2xlIHRocmVhZC5cbiAgICAgIHZhciBCQ2FjaGVkIDogYXJyYXk8JHt0eXBlfSwgY29sUGVyVGhyZWFkPjtcbiAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgdGlsZUlubmVyOyBrID0gayArIDEpIHtcbiAgICAgICAgZm9yICh2YXIgaW5uZXIgPSAwOyBpbm5lciA8IGNvbFBlclRocmVhZDsgaW5uZXIgPSBpbm5lciArIDEpIHtcbiAgICAgICAgICBCQ2FjaGVkW2lubmVyXSA9IG1tX0JzdWJba11bbG9jYWxDb2wgKyBpbm5lciAqICR7d29ya2dyb3VwU2l6ZVswXX1dO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCByb3dQZXJUaHJlYWQ7IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgICAgICAgbGV0IEFDYWNoZWQgPSAke1xuICAgICAgICAgICAgdHJhbnNwb3NlQVxuICAgICAgICAgICAgICA/IGBtbV9Bc3ViW2tdW2xvY2FsUm93ICsgaW5uZXJSb3cgKiAke3dvcmtncm91cFNpemVbMV19XTtgXG4gICAgICAgICAgICAgIDogYG1tX0FzdWJbbG9jYWxSb3cgKyBpbm5lclJvdyAqICR7d29ya2dyb3VwU2l6ZVsxXX1dW2tdO2BcbiAgICAgICAgICB9XG4gICAgICAgICAgZm9yICh2YXIgaW5uZXJDb2wgPSAwOyBpbm5lckNvbCA8IGNvbFBlclRocmVhZDsgaW5uZXJDb2wgPSBpbm5lckNvbCArIDEpIHtcbiAgICAgICAgICAgIGFjY1tpbm5lclJvd11baW5uZXJDb2xdID0gYWNjW2lubmVyUm93XVtpbm5lckNvbF0gK1xuICAgICAgICAgICAgICAgIEFDYWNoZWQgKiBCQ2FjaGVkW2lubmVyQ29sXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgICB9XG4gICAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8IHJvd1BlclRocmVhZDsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgICAgIGxldCBnUm93ID0gZ2xvYmFsUm93U3RhcnQgKyBsb2NhbFJvdyArIGlubmVyUm93ICogJHt3b3JrZ3JvdXBTaXplWzFdfTtcbiAgICAgIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCBjb2xQZXJUaHJlYWQ7IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICAgIGxldCBnQ29sID0gZ2xvYmFsQ29sU3RhcnQgKyBsb2NhbENvbCArIGlubmVyQ29sICogJHt3b3JrZ3JvdXBTaXplWzBdfTtcbiAgICAgICAgbW1fd3JpdGUoYmF0Y2gsIGdSb3csIGdDb2wsIGFjY1tpbm5lclJvd11baW5uZXJDb2xdKTtcbiAgICAgIH1cbiAgICB9XG4gICAgYFxuICAgIDogYFxubGV0IHRpbGVSb3cgPSBpMzIobG9jYWxJZC55KSAqIHJvd1BlclRocmVhZDtcbmxldCB0aWxlQ29sID0gaTMyKGxvY2FsSWQueCkgKiBjb2xQZXJUaHJlYWQ7XG5cbmxldCBnbG9iYWxSb3cgPSBpMzIoZ2xvYmFsSWQueSkgKiByb3dQZXJUaHJlYWQ7XG5sZXQgZ2xvYmFsQ29sID0gaTMyKGdsb2JhbElkLngpICogY29sUGVyVGhyZWFkO1xubGV0IGdsb2JhbFJvd1N0YXJ0ID0gaTMyKHdvcmtncm91cElkLnkpICogJHt0aWxlQU91dGVyfTtcblxubGV0IHRpbGVSb3dBID0gaTMyKGxvY2FsSWQueSkgKiAke3Jvd1BlclRocmVhZEF9O1xubGV0IHRpbGVDb2xBID0gaTMyKGxvY2FsSWQueCkgKiAke2NvbFBlclRocmVhZEF9O1xubGV0IHRpbGVSb3dCID0gaTMyKGxvY2FsSWQueSkgKiAke3Jvd1BlclRocmVhZEJ9O1xuLy8gTG9vcCBvdmVyIHNoYXJlZCBkaW1lbnNpb24uXG5mb3IgKHZhciB0ID0gMDsgdCA8IG51bV90aWxlczsgdCA9IHQgKyAxKSB7XG4gIC8vIExvYWQgb25lIHRpbGUgb2YgQSBpbnRvIGxvY2FsIG1lbW9yeS5cbiAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8ICR7cm93UGVyVGhyZWFkQX07IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgZm9yICh2YXIgaW5uZXJDb2wgPSAwOyBpbm5lckNvbCA8ICR7Y29sUGVyVGhyZWFkQX07IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICBsZXQgaW5wdXRSb3cgPSB0aWxlUm93QSArIGlubmVyUm93O1xuICAgICAgbGV0IGlucHV0Q29sID0gdGlsZUNvbEEgKyBpbm5lckNvbDtcbiAgICAgICR7d3JpdGVEYXRhVG9TdWJBU25pcHBldCh0cmFuc3Bvc2VBLCBiYXRjaERpbXMpfVxuICAgIH1cbiAgfVxuXG4gIC8vIExvYWQgb25lIHRpbGUgb2YgQiBpbnRvIGxvY2FsIG1lbW9yeS5cbiAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8ICR7cm93UGVyVGhyZWFkQn07IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgZm9yICh2YXIgaW5uZXJDb2wgPSAwOyBpbm5lckNvbCA8IGNvbFBlclRocmVhZDsgaW5uZXJDb2wgPSBpbm5lckNvbCArIDEpIHtcbiAgICAgIGxldCBpbnB1dFJvdyA9IHRpbGVSb3dCICsgaW5uZXJSb3c7XG4gICAgICBsZXQgaW5wdXRDb2wgPSB0aWxlQ29sICsgaW5uZXJDb2w7XG4gICAgICBtbV9Cc3ViW2lucHV0Um93XVtpbnB1dENvbF0gPSBtbV9yZWFkQihiYXRjaCxcbiAgICAgICAga1N0YXJ0ICsgaW5wdXRSb3csXG4gICAgICAgIGdsb2JhbENvbCArIGlubmVyQ29sJHtiYXRjaERpbXMgPyAnLCBiYXRjaEluZGljZXMnIDogJyd9KTtcbiAgICB9XG4gIH1cbiAga1N0YXJ0ID0ga1N0YXJ0ICsgdGlsZUlubmVyO1xuICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgLy8gQ29tcHV0ZSBhY2MgdmFsdWVzIGZvciBhIHNpbmdsZSB0aHJlYWQuXG4gIHZhciBCQ2FjaGVkIDogYXJyYXk8JHt0eXBlfSwgY29sUGVyVGhyZWFkPjtcbiAgZm9yICh2YXIgayA9IDA7IGsgPCB0aWxlSW5uZXI7IGsgPSBrICsgMSkge1xuICAgIGZvciAodmFyIGlubmVyID0gMDsgaW5uZXIgPCBjb2xQZXJUaHJlYWQ7IGlubmVyID0gaW5uZXIgKyAxKSB7XG4gICAgICBCQ2FjaGVkW2lubmVyXSA9IG1tX0JzdWJba11bdGlsZUNvbCArIGlubmVyXTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgJHtyZWFkRGF0YUZyb21TdWJBU25pcHBldCh0cmFuc3Bvc2VBKX1cbiAgICAgIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCBjb2xQZXJUaHJlYWQ7IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICAgIGFjY1tpbm5lclJvd11baW5uZXJDb2xdID0gYWNjW2lubmVyUm93XVtpbm5lckNvbF0gKyBBQ2FjaGVkICogQkNhY2hlZFtpbm5lckNvbF07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgd29ya2dyb3VwQmFycmllcigpO1xufVxuXG5mb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICBmb3IgKHZhciBpbm5lckNvbCA9IDA7IGlubmVyQ29sIDwgY29sUGVyVGhyZWFkOyBpbm5lckNvbCA9IGlubmVyQ29sICsgMSkge1xuICAgIG1tX3dyaXRlKGJhdGNoLCBnbG9iYWxSb3cgKyBpbm5lclJvdywgZ2xvYmFsQ29sICsgaW5uZXJDb2wsXG4gICAgICAgIGFjY1tpbm5lclJvd11baW5uZXJDb2xdKTtcbiAgfVxufVxuYDtcblxuICByZXR1cm4gYFxuICB2YXI8d29ya2dyb3VwPiBtbV9Bc3ViIDogYXJyYXk8YXJyYXk8JHt0eXBlfSwgJHt0aWxlQVdpZHRofT4sICR7dGlsZUFIaWdodH0+O1xuICB2YXI8d29ya2dyb3VwPiBtbV9Cc3ViIDogYXJyYXk8YXJyYXk8JHt0eXBlfSwgJHt0aWxlQk91dGVyfT4sICR7dGlsZUlubmVyfT47XG4gIGNvbnN0IHJvd1BlclRocmVhZCA9ICR7d29ya1BlclRocmVhZFsxXX07XG4gIGNvbnN0IGNvbFBlclRocmVhZCA9ICR7d29ya1BlclRocmVhZFswXX07XG4gIGNvbnN0IHRpbGVJbm5lciA9ICR7dGlsZUlubmVyfTtcblxuQGNvbXB1dGUgQHdvcmtncm91cF9zaXplKCR7d29ya2dyb3VwU2l6ZVswXX0sICR7d29ya2dyb3VwU2l6ZVsxXX0sICR7d29ya2dyb3VwU2l6ZVsyXX0pXG5mbiBtYWluKEBidWlsdGluKGxvY2FsX2ludm9jYXRpb25faWQpIGxvY2FsSWQgOiB2ZWMzPHUzMj4sXG4gICAgICAgIEBidWlsdGluKGdsb2JhbF9pbnZvY2F0aW9uX2lkKSBnbG9iYWxJZCA6IHZlYzM8dTMyPixcbiAgICAgICAgQGJ1aWx0aW4od29ya2dyb3VwX2lkKSB3b3JrZ3JvdXBJZCA6IHZlYzM8dTMyPikge1xuICAgIGxldCBiYXRjaCA9ICR7c3BsaXRLID8gJzAnIDogJ2kzMihnbG9iYWxJZC56KSd9O1xuICAgICR7YmF0Y2hEaW1zID8gYGxldCBiYXRjaEluZGljZXMgPSAke2JhdGNoRGltcy5vZmZzZXRUb0luZGljZXMoJ3UzMihiYXRjaCknKX07YCA6ICcnfVxuICAgIGxldCBudW1fdGlsZXMgPSAke1xuICAgICAgc3BsaXRLID8gYCR7TWF0aC5jZWlsKHNwbGl0ZWREaW1Jbm5lciAvIHRpbGVJbm5lcil9YCA6ICcodW5pZm9ybXMuZGltX2lubmVyIC0gMSkgLyB0aWxlSW5uZXIgKyAxJ1xuICAgIH07XG4gICAgdmFyIGtTdGFydCA9ICR7c3BsaXRLID8gYGkzMihnbG9iYWxJZC56KSAqICR7c3BsaXRlZERpbUlubmVyfWAgOiAnMCd9O1xuXG4gICAgdmFyIGFjYyA6IGFycmF5PGFycmF5PCR7dHlwZX0sIGNvbFBlclRocmVhZD4sIHJvd1BlclRocmVhZD47XG4gICAgJHttYXRtdWxTbmlwcGV0fVxuICB9XG5gO1xufTtcblxuY29uc3QgbWF0TXVsUmVhZFdyaXRlRm5Tb3VyY2UgPSAoXG4gIGNvbXBvbmVudDogbnVtYmVyLFxuICBoYXNCaWFzOiBib29sZWFuLFxuICBhcHBseUFjdGl2YXRpb246IHN0cmluZyxcbiAgdmFyaWFibGVzOiBJbmRpY2VzSGVscGVyW10sXG4gIGlzQ2hhbm5lbHNMYXN0ID0gZmFsc2UsXG4pOiBzdHJpbmcgPT4ge1xuICBjb25zdCBbYmF0Y2hWYXJpYWJsZSwgYVZhcmlhYmxlLCBiVmFyaWFibGUsIG91dHB1dFZhcmlhYmxlXSA9IHZhcmlhYmxlcztcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUodmFyaWFibGVzWzBdLnR5cGUudGVuc29yKTtcblxuICBjb25zdCBzb3VyY2UgPSBgXG4gICAgZm4gbW1fcmVhZEEoYmF0Y2g6IGkzMiwgcm93OiBpMzIsIGNvbEluOiBpMzIsIGJhdGNoSW5kaWNlczogJHtiYXRjaFZhcmlhYmxlLnR5cGUuaW5kaWNlc30pIC0+ICR7dHlwZVNuaXBwZXQoXG4gICAgICBjb21wb25lbnQsXG4gICAgICBkYXRhVHlwZSxcbiAgICApfSB7XG4gICAgICB2YXIgdmFsdWUgPSAke3R5cGVTbmlwcGV0KGNvbXBvbmVudCwgZGF0YVR5cGUpfSgwLjApO1xuICAgICAgbGV0IGNvbCA9IGNvbEluICogJHtjb21wb25lbnR9O1xuICAgICAgaWYocm93IDwgdW5pZm9ybXMuZGltX2Ffb3V0ZXIgJiYgY29sIDwgdW5pZm9ybXMuZGltX2lubmVyKVxuICAgICAge1xuICAgICAgICB2YXIgYUluZGljZXM6ICR7YVZhcmlhYmxlLnR5cGUuaW5kaWNlc307XG4gICAgICAgICR7Y29udmVydE91dHB1dEJhdGNoSW5kaWNlc1RvSW5wdXRCYXRjaEluZGljZXMoXG4gICAgICAgICAgJ2FJbmRpY2VzJyxcbiAgICAgICAgICBhVmFyaWFibGUsXG4gICAgICAgICAgYVZhcmlhYmxlLnJhbmsgLSAyLFxuICAgICAgICAgIGJhdGNoVmFyaWFibGUucmFuayxcbiAgICAgICAgICAnYmF0Y2hJbmRpY2VzJyxcbiAgICAgICAgKX1cbiAgICAgICAgJHthVmFyaWFibGUuaW5kaWNlc1NldCgnYUluZGljZXMnLCBhVmFyaWFibGUucmFuayAtIDIsICd1MzIocm93KScpfVxuICAgICAgICAke2FWYXJpYWJsZS5pbmRpY2VzU2V0KCdhSW5kaWNlcycsIGFWYXJpYWJsZS5yYW5rIC0gMSwgJ3UzMihjb2xJbiknKX1cbiAgICAgICAgdmFsdWUgPSAke2FWYXJpYWJsZS5nZXRCeUluZGljZXMoJ2FJbmRpY2VzJyl9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIGZuIG1tX3JlYWRCKGJhdGNoOiBpMzIsIHJvdzogaTMyLCBjb2xJbjogaTMyLCBiYXRjaEluZGljZXM6ICR7YmF0Y2hWYXJpYWJsZS50eXBlLmluZGljZXN9KSAtPiAke3R5cGVTbmlwcGV0KFxuICAgICAgY29tcG9uZW50LFxuICAgICAgZGF0YVR5cGUsXG4gICAgKX0ge1xuICAgICAgdmFyIHZhbHVlID0gJHt0eXBlU25pcHBldChjb21wb25lbnQsIGRhdGFUeXBlKX0oMC4wKTtcbiAgICAgIGxldCBjb2wgPSBjb2xJbiAqICR7Y29tcG9uZW50fTtcbiAgICAgIGlmKHJvdyA8IHVuaWZvcm1zLmRpbV9pbm5lciAmJiBjb2wgPCB1bmlmb3Jtcy5kaW1fYl9vdXRlcilcbiAgICAgIHtcbiAgICAgICAgdmFyIGJJbmRpY2VzOiAke2JWYXJpYWJsZS50eXBlLmluZGljZXN9O1xuICAgICAgICAke2NvbnZlcnRPdXRwdXRCYXRjaEluZGljZXNUb0lucHV0QmF0Y2hJbmRpY2VzKFxuICAgICAgICAgICdiSW5kaWNlcycsXG4gICAgICAgICAgYlZhcmlhYmxlLFxuICAgICAgICAgIGJWYXJpYWJsZS5yYW5rIC0gMixcbiAgICAgICAgICBiYXRjaFZhcmlhYmxlLnJhbmssXG4gICAgICAgICAgJ2JhdGNoSW5kaWNlcycsXG4gICAgICAgICl9XG4gICAgICAgICR7YlZhcmlhYmxlLmluZGljZXNTZXQoJ2JJbmRpY2VzJywgYlZhcmlhYmxlLnJhbmsgLSAyLCAndTMyKHJvdyknKX1cbiAgICAgICAgJHtiVmFyaWFibGUuaW5kaWNlc1NldCgnYkluZGljZXMnLCBiVmFyaWFibGUucmFuayAtIDEsICd1MzIoY29sSW4pJyl9XG4gICAgICAgIHZhbHVlID0gJHtiVmFyaWFibGUuZ2V0QnlJbmRpY2VzKCdiSW5kaWNlcycpfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICBmbiBtbV93cml0ZShiYXRjaDogaTMyLCByb3c6IGkzMiwgY29sSW46IGkzMiwgdmFsdWVJbjogJHt0eXBlU25pcHBldChjb21wb25lbnQsIGRhdGFUeXBlKX0pIHtcbiAgICAgIGxldCBjb2wgPSBjb2xJbiAqICR7Y29tcG9uZW50fTtcbiAgICAgIGlmIChyb3cgPCB1bmlmb3Jtcy5kaW1fYV9vdXRlciAmJiBjb2wgPCB1bmlmb3Jtcy5kaW1fYl9vdXRlcikge1xuICAgICAgICB2YXIgdmFsdWUgPSB2YWx1ZUluO1xuICAgICAgICBsZXQgY29vcmRzID0gdmVjMzxpMzI+KGJhdGNoLCByb3csIGNvbEluKTtcbiAgICAgICAgJHtcbiAgICAgICAgICBoYXNCaWFzXG4gICAgICAgICAgICA/IGB2YWx1ZSA9IHZhbHVlICsgJHtpc0NoYW5uZWxzTGFzdCA/ICdiaWFzW2NvbEluXScgOiBgJHt0eXBlU25pcHBldChjb21wb25lbnQsIGRhdGFUeXBlKX0oYmlhc1tyb3ddKWB9O2BcbiAgICAgICAgICAgIDogJydcbiAgICAgICAgfVxuICAgICAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAgICAgJHtvdXRwdXRWYXJpYWJsZS5zZXRCeUluZGljZXMoJ3ZlYzM8dTMyPihjb29yZHMpJywgJ3ZhbHVlJyl9XG4gICAgICB9XG4gICAgfVxuICAgIGA7XG4gIHJldHVybiBzb3VyY2U7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhY3RpdmF0aW9uQXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyxcbiAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICByZXNoYXBlZE91dHB1dFNoYXBlPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGlzQ2hhbm5lbHNMYXN0ID0gZmFsc2UgLyogb25seSB1c2VkIGZvciBjb252MmRCeU1hdE11bCovLFxuICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbj86IChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pID0+IG51bWJlcltdLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBhU2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgYlNoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gIGNvbnN0IG91dGVyRGltc0EgPSBhU2hhcGUuc2xpY2UoMCwgLTIpO1xuICBjb25zdCBvdXRlckRpbXNCID0gYlNoYXBlLnNsaWNlKDAsIC0yKTtcbiAgY29uc3Qgb3V0ZXJEaW1zID0gcmVzaGFwZWRPdXRwdXRTaGFwZSA/IHJlc2hhcGVkT3V0cHV0U2hhcGUuc2xpY2UoMCwgLTIpIDogb3V0cHV0U2hhcGUuc2xpY2UoMCwgLTIpO1xuICBjb25zdCBiYXRjaFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRlckRpbXMpO1xuICBjb25zdCBkaW1BT3V0ZXIgPSBhU2hhcGVbYVNoYXBlLmxlbmd0aCAtIDJdO1xuICBjb25zdCBkaW1Jbm5lciA9IGFTaGFwZVthU2hhcGUubGVuZ3RoIC0gMV07XG4gIGNvbnN0IGRpbUJPdXRlciA9IGJTaGFwZVtiU2hhcGUubGVuZ3RoIC0gMV07XG4gIGNvbnN0IGlzVmVjNCA9IGRpbUlubmVyICUgNCA9PT0gMCAmJiBkaW1CT3V0ZXIgJSA0ID09PSAwO1xuXG4gIC8vIFRPRE86IGZpbmUgdHVuZSBzaXplXG4gIGNvbnN0IGVsZW1lbnRzUGVyVGhyZWFkID0gZGltQU91dGVyIDw9IDggPyBbNCwgMSwgMV0gOiBbNCwgNCwgMV07XG4gIGNvbnN0IHdvcmtncm91cFNpemU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9IFs4LCA4LCAxXTtcbiAgY29uc3QgZGlzcGF0Y2ggPSBbXG4gICAgTWF0aC5jZWlsKGRpbUJPdXRlciAvIHdvcmtncm91cFNpemVbMF0gLyBlbGVtZW50c1BlclRocmVhZFswXSksXG4gICAgTWF0aC5jZWlsKGRpbUFPdXRlciAvIHdvcmtncm91cFNpemVbMV0gLyBlbGVtZW50c1BlclRocmVhZFsxXSksXG4gICAgTWF0aC5jZWlsKGJhdGNoU2l6ZSAvIHdvcmtncm91cFNpemVbMl0gLyBlbGVtZW50c1BlclRocmVhZFsyXSksXG4gIF07XG5cbiAgY29uc3QgY29tcG9uZW50cyA9IGlzVmVjNCA/IDQgOiAxO1xuICBjb25zdCBhU2hhcGVUZW1wID0gWy4uLm91dGVyRGltc0EsIGRpbUFPdXRlciwgZGltSW5uZXIgLyBjb21wb25lbnRzXTtcbiAgY29uc3QgYVJhbmsgPSBhU2hhcGVUZW1wLmxlbmd0aDtcbiAgY29uc3QgYlNoYXBlVGVtcCA9IFsuLi5vdXRlckRpbXNCLCBkaW1Jbm5lciwgZGltQk91dGVyIC8gY29tcG9uZW50c107XG4gIGNvbnN0IGJSYW5rID0gYlNoYXBlVGVtcC5sZW5ndGg7XG4gIGNvbnN0IG91dHB1dFNoYXBlVGVtcCA9IFtiYXRjaFNpemUsIGRpbUFPdXRlciwgZGltQk91dGVyIC8gY29tcG9uZW50c107XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBkaW1BT3V0ZXIgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBkaW1CT3V0ZXIgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBkaW1Jbm5lciB9LFxuICBdO1xuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhKGFjdGl2YXRpb25BdHRyaWJ1dGVzLCBwcm9ncmFtVW5pZm9ybXMpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRlckRpbXMsIGFTaGFwZVRlbXAsIGJTaGFwZVRlbXApKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3JhbmsnLCAncmFuayddO1xuXG4gIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID4gMjtcbiAgaWYgKGhhc0JpYXMpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMl0uZGltcykpO1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3JhbmsnKTtcbiAgfVxuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRwdXRTaGFwZVRlbXApKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBiYXRjaFJhbmsgPSBvdXRlckRpbXMubGVuZ3RoO1xuICAgIGNvbnN0IGJhdGNoRGltcyA9IGludGVybmFsVmFyaWFibGUoJ2JhdGNoRGltcycsIGlucHV0c1swXS5kYXRhVHlwZSwgYmF0Y2hSYW5rLCAxKTtcbiAgICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuXG4gICAgY29uc3QgQSA9IGlucHV0VmFyaWFibGUoJ2EnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGFSYW5rLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBCID0gaW5wdXRWYXJpYWJsZSgnYicsIGlucHV0c1sxXS5kYXRhVHlwZSwgYlJhbmssIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdyZXN1bHQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlVGVtcC5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGlucHV0VmFyaWFibGVzID0gW0EsIEJdO1xuICAgIGlmIChoYXNCaWFzKSB7XG4gICAgICBjb25zdCBiaWFzQ29tcG9uZW50cyA9IGlzQ2hhbm5lbHNMYXN0ID8gY29tcG9uZW50cyA6IDE7XG4gICAgICBpbnB1dFZhcmlhYmxlcy5wdXNoKGlucHV0VmFyaWFibGUoJ2JpYXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCwgYmlhc0NvbXBvbmVudHMpKTtcbiAgICB9XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnZGltX2Ffb3V0ZXInLCB0eXBlOiAnaTMyJyB9LFxuICAgICAgeyBuYW1lOiAnZGltX2Jfb3V0ZXInLCB0eXBlOiAnaTMyJyB9LFxuICAgICAgeyBuYW1lOiAnZGltX2lubmVyJywgdHlwZTogJ2kzMicgfSxcbiAgICBdO1xuICAgIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcyhhY3RpdmF0aW9uQXR0cmlidXRlcywgdW5pZm9ybXMpO1xuICAgIGNvbnN0IGJhc2VUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKG91dHB1dC50eXBlLnRlbnNvcik7XG4gICAgY29uc3QgYXBwbHlBY3RpdmF0aW9uID0gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYWN0aXZhdGlvbkF0dHJpYnV0ZXMsIG91dHB1dC50eXBlLnZhbHVlLCBiYXNlVHlwZSk7XG4gICAgY29uc3QgZGVjbGFyZUZ1bmN0aW9ucyA9IG1hdE11bFJlYWRXcml0ZUZuU291cmNlKFxuICAgICAgY29tcG9uZW50cyxcbiAgICAgIGhhc0JpYXMsXG4gICAgICBhcHBseUFjdGl2YXRpb24sXG4gICAgICBbYmF0Y2hEaW1zLCBBLCBCLCBvdXRwdXRdLFxuICAgICAgaXNDaGFubmVsc0xhc3QsXG4gICAgKTtcbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlclxuICAgIC5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKVxuICAgIC5yZWdpc3RlckludGVybmFsVmFyaWFibGVzKGJhdGNoRGltcylcbiAgICAuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcmlhYmxlcywgb3V0cHV0KX1cbiAgJHtkZWNsYXJlRnVuY3Rpb25zfVxuICAke1xuICAgIGlzVmVjNFxuICAgICAgPyBtYWtlTWF0TXVsUGFja2VkVmVjNFNvdXJjZShlbGVtZW50c1BlclRocmVhZCwgd29ya2dyb3VwU2l6ZSwgZGF0YVR5cGUsIGJhdGNoRGltcylcbiAgICAgIDogbWFrZU1hdE11bFBhY2tlZFNvdXJjZShlbGVtZW50c1BlclRocmVhZCwgd29ya2dyb3VwU2l6ZSwgZGF0YVR5cGUsIGJhdGNoRGltcylcbiAgfVxuICAgICAgICAgICAgICAgICAgIGA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ01hdE11bCcsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2VsZW1lbnRzUGVyVGhyZWFkfTske2FjdGl2YXRpb25BdHRyaWJ1dGVzLmFjdGl2YXRpb259OyR7aXNWZWM0fTske2lzQ2hhbm5lbHNMYXN0fWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llcyxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBkaW1zOiBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiA/IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uKG91dHB1dFNoYXBlKSA6IG91dHB1dFNoYXBlLFxuICAgICAgICAgIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBkaXNwYXRjaFswXSwgeTogZGlzcGF0Y2hbMV0sIHo6IGRpc3BhdGNoWzJdIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8vIHNhbXBsZWQgZnJvbSBbQHRlbnNvcmZsb3cvdGZqc10gdGZqcy1iYWNrZW5kLXdlYmdwdS9zcmMvY29udjJkX21tX3dlYmdwdS50c1xuLy9cbi8vIG1vZGlmaWVkIHRvIGZpdCB0aGUgbmVlZHMgb2YgdGhlIHByb2plY3RcblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBMT0dfREVCVUcgfSBmcm9tICcuLi8uLi8uLi9sb2cnO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFByb2dyYW1JbmZvLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi8uLi90eXBlcyc7XG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi4vY29tbW9uJztcbmltcG9ydCB7IENvbnZBdHRyaWJ1dGVzIH0gZnJvbSAnLi4vY29udic7XG5pbXBvcnQgeyBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMsIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEsIGdldEFjdGl2YXRpb25TbmlwcGV0IH0gZnJvbSAnLi4vZnVzZS11dGlscyc7XG5cbmltcG9ydCB7IGJpYXNTbmlwcGV0LCB0eXBlU25pcHBldCB9IGZyb20gJy4vYWN0aXZhdGlvbl91dGlsJztcbmltcG9ydCB7IHV0aWxGdW5jdGlvbnMgfSBmcm9tICcuL2NvbnZfdXRpbCc7XG5pbXBvcnQgeyBtYWtlTWF0TXVsUGFja2VkU291cmNlLCBtYWtlTWF0TXVsUGFja2VkVmVjNFNvdXJjZSB9IGZyb20gJy4vbWF0bXVsX3BhY2tlZF93ZWJncHUnO1xuXG5jb25zdCBjb252MmRDb21tb25TbmlwcGV0ID0gKFxuICBpc0NoYW5uZWxzTGFzdDogYm9vbGVhbixcbiAgZml0QU91dGVyOiBib29sZWFuLFxuICBmaXRCT3V0ZXI6IGJvb2xlYW4sXG4gIGZpdElubmVyOiBib29sZWFuLFxuICBhZGRCaWFzID0gZmFsc2UsXG4gIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzLFxuICBpbm5lckVsZW1lbnRTaXplWCA9IDQsXG4gIGlubmVyRWxlbWVudFNpemVXID0gNCxcbiAgaW5uZXJFbGVtZW50U2l6ZSA9IDQsXG4gIGRhdGFUeXBlID0gJ2YzMicsXG4pOiBzdHJpbmcgPT4ge1xuICBjb25zdCBnZXRYU25pcHBldCA9IChpbm5lckVsZW1lbnRTaXplOiBudW1iZXIpID0+IHtcbiAgICBzd2l0Y2ggKGlubmVyRWxlbWVudFNpemUpIHtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmV0dXJuICdyZXNEYXRhID0geFt4SW5kZXhdOyc7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiBgcmVzRGF0YSA9IHZlYzM8JHtkYXRhVHlwZX0+KHhbeEluZGV4XSwgeFt4SW5kZXggKyAxXSwgeFt4SW5kZXggKyAyXSk7YDtcbiAgICAgIGNhc2UgNDpcbiAgICAgICAgcmV0dXJuICdyZXNEYXRhID0geFt4SW5kZXggLyA0XTsnO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbm5lckVsZW1lbnRTaXplICR7aW5uZXJFbGVtZW50U2l6ZX0gaXMgbm90IHN1cHBvcnRlZC5gKTtcbiAgICB9XG4gIH07XG4gIGNvbnN0IGdldFdTbmlwcGV0ID0gKGlubmVyRWxlbWVudFNpemU6IG51bWJlcikgPT4ge1xuICAgIHN3aXRjaCAoaW5uZXJFbGVtZW50U2l6ZSkge1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gJ3JldHVybiB3W3JvdyAqIGkzMih1bmlmb3Jtcy53X3NoYXBlWzNdKSArIGNvbEluXTsnO1xuICAgICAgY2FzZSA0OlxuICAgICAgICByZXR1cm4gJ3JldHVybiB3W3JvdyAqIGkzMih1bmlmb3Jtcy53X3NoYXBlWzNdKSAvIDQgKyBjb2xJbl07JztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW5uZXJFbGVtZW50U2l6ZSAke2lubmVyRWxlbWVudFNpemV9IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gICAgfVxuICB9O1xuICBjb25zdCBjb29yZEFTbmlwcGV0ID0gaXNDaGFubmVsc0xhc3RcbiAgICA/IGBcbiAgICBsZXQgY29vcmQgPSB2ZWM0PGkzMj4oYmF0Y2gsIHhSb3csIHhDb2wsIHhDaCk7XG4gICAgYFxuICAgIDogYFxuICAgIGxldCBjb29yZCA9IHZlYzQ8aTMyPihiYXRjaCwgeENoLCB4Um93LCB4Q29sKTtcbiAgICBgO1xuXG4gIGNvbnN0IGNvb3JkUmVzU25pcHBldCA9IGlzQ2hhbm5lbHNMYXN0XG4gICAgPyBgXG4gICAgbGV0IGNvb3JkcyA9IHZlYzQ8aTMyPihcbiAgICAgIGJhdGNoLFxuICAgICAgcm93IC8gb3V0V2lkdGgsXG4gICAgICByb3cgJSBvdXRXaWR0aCxcbiAgICAgIGNvbCk7XG4gICAgYFxuICAgIDogYFxuICAgIGxldCBjb29yZHMgPSB2ZWM0PGkzMj4oXG4gICAgICBiYXRjaCxcbiAgICAgIHJvdyxcbiAgICAgIGNvbCAvIG91dFdpZHRoLFxuICAgICAgY29sICUgb3V0V2lkdGgpO1xuICAgIGA7XG5cbiAgY29uc3QgeEhlaWdodCA9IGlzQ2hhbm5lbHNMYXN0ID8gJ2kzMih1bmlmb3Jtcy54X3NoYXBlWzFdKScgOiAnaTMyKHVuaWZvcm1zLnhfc2hhcGVbMl0pJztcbiAgY29uc3QgeFdpZHRoID0gaXNDaGFubmVsc0xhc3QgPyAnaTMyKHVuaWZvcm1zLnhfc2hhcGVbMl0pJyA6ICdpMzIodW5pZm9ybXMueF9zaGFwZVszXSknO1xuICBjb25zdCByb3cgPSBpc0NoYW5uZWxzTGFzdCA/ICdyb3cnIDogJ2NvbCc7XG4gIGNvbnN0IGNvbCA9IGlzQ2hhbm5lbHNMYXN0ID8gJ2NvbCcgOiAncm93JztcbiAgY29uc3QgcmVhZFhTbmlwcGV0ID0gYFxuICAgIGxldCBpbkNoYW5uZWxzID0gaTMyKHVuaWZvcm1zLndfc2hhcGVbMl0pO1xuICAgIGxldCBvdXRXaWR0aCA9ICR7aXNDaGFubmVsc0xhc3QgPyAnaTMyKHVuaWZvcm1zLnJlc3VsdF9zaGFwZVsyXSknIDogJ2kzMih1bmlmb3Jtcy5yZXN1bHRfc2hhcGVbM10pJ307XG4gICAgbGV0IG91dFJvdyA9ICR7cm93fSAvIG91dFdpZHRoO1xuICAgIGxldCBvdXRDb2wgPSAke3Jvd30gJSBvdXRXaWR0aDtcblxuICAgIGxldCBXUm93ID0gJHtjb2x9IC8gKGkzMih1bmlmb3Jtcy53X3NoYXBlWzFdKSAqIGluQ2hhbm5lbHMpO1xuICAgIGxldCBXQ29sID0gJHtjb2x9IC8gaW5DaGFubmVscyAlIGkzMih1bmlmb3Jtcy53X3NoYXBlWzFdKTtcbiAgICBsZXQgeFJvdyA9IG91dFJvdyAqIHVuaWZvcm1zLnN0cmlkZVswXSArIHVuaWZvcm1zLmRpbGF0aW9uWzBdICogV1JvdyAtIHVuaWZvcm1zLnBhZFswXTtcbiAgICBsZXQgeENvbCA9IG91dENvbCAqIHVuaWZvcm1zLnN0cmlkZVsxXSArIHVuaWZvcm1zLmRpbGF0aW9uWzFdICogV0NvbCAtIHVuaWZvcm1zLnBhZFsxXTtcbiAgICBsZXQgeENoID0gJHtjb2x9ICUgaW5DaGFubmVscztcbiAgICB2YXIgcmVzRGF0YSA9ICR7dHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVgsIGRhdGFUeXBlKX0oMC4wKTtcbiAgICAvLyBUaGUgYm91bmRzIGNoZWNraW5nIGlzIGFsd2F5cyBuZWVkZWQgc2luY2Ugd2UgdXNlIGl0IHRvIHBhZCB6ZXJvIGZvclxuICAgIC8vIHRoZSAnc2FtZScgcGFkZGluZyB0eXBlLlxuICAgIGlmICh4Um93ID49IDAgJiYgeFJvdyA8ICR7eEhlaWdodH0gJiYgeENvbCA+PSAwICYmIHhDb2wgPCAke3hXaWR0aH0pIHtcbiAgICAgICR7Y29vcmRBU25pcHBldH1cbiAgICAgIGxldCB4SW5kZXggPSBnZXRJbmRleEZyb21Db29yZHM0RChjb29yZCwgdmVjNDxpMzI+KHVuaWZvcm1zLnhfc2hhcGUpKTtcbiAgICAgICR7Z2V0WFNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVgpfVxuICAgIH1cbiAgICByZXR1cm4gcmVzRGF0YTtgO1xuXG4gIGNvbnN0IHNhbXBsZVggPSBpc0NoYW5uZWxzTGFzdFxuICAgID8gZml0QU91dGVyICYmIGZpdElubmVyXG4gICAgICA/IGBcbiAgICBsZXQgY29sID0gY29sSW4gKiAke2lubmVyRWxlbWVudFNpemVYfTtcbiAgICAke3JlYWRYU25pcHBldH1gXG4gICAgICA6IGBcbiAgICBsZXQgY29sID0gY29sSW4gKiAke2lubmVyRWxlbWVudFNpemVYfTtcbiAgICBpZiAocm93IDwgdW5pZm9ybXMuZGltX2Ffb3V0ZXIgJiYgY29sIDwgdW5pZm9ybXMuZGltX2lubmVyKSB7XG4gICAgICAke3JlYWRYU25pcHBldH1cbiAgICB9XG4gICAgcmV0dXJuICR7dHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVgsIGRhdGFUeXBlKX0oMC4wKTtgXG4gICAgOiBmaXRJbm5lciAmJiBmaXRCT3V0ZXJcbiAgICAgID8gYFxuICAgIGxldCBjb2wgPSBjb2xJbiAqICR7aW5uZXJFbGVtZW50U2l6ZVh9O1xuICAgICR7cmVhZFhTbmlwcGV0fWBcbiAgICAgIDogYFxuICAgIGxldCBjb2wgPSBjb2xJbiAqICR7aW5uZXJFbGVtZW50U2l6ZVh9O1xuICAgIGlmIChyb3cgPCB1bmlmb3Jtcy5kaW1faW5uZXIgJiYgY29sIDwgdW5pZm9ybXMuZGltX2Jfb3V0ZXIpIHtcbiAgICAgICR7cmVhZFhTbmlwcGV0fVxuICAgIH1cbiAgICByZXR1cm4gJHt0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplWCwgZGF0YVR5cGUpfSgwLjApO2A7XG5cbiAgY29uc3Qgc2FtcGxlVyA9IGlzQ2hhbm5lbHNMYXN0XG4gICAgPyBmaXRJbm5lciAmJiBmaXRCT3V0ZXJcbiAgICAgID8gZ2V0V1NuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVcpXG4gICAgICA6IGBcbiAgICBsZXQgY29sID0gY29sSW4gKiAke2lubmVyRWxlbWVudFNpemVXfTtcbiAgICBpZiAocm93IDwgdW5pZm9ybXMuZGltX2lubmVyICYmIGNvbCA8IHVuaWZvcm1zLmRpbV9iX291dGVyKSB7XG4gICAgICAke2dldFdTbmlwcGV0KGlubmVyRWxlbWVudFNpemVXKX1cbiAgICB9XG4gICAgcmV0dXJuICR7dHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVcsIGRhdGFUeXBlKX0oMC4wKTtgXG4gICAgOiBgXG4gICAgbGV0IGNvbCA9IGNvbEluICogJHtpbm5lckVsZW1lbnRTaXplV307XG4gICAgaWYgKHJvdyA8IHVuaWZvcm1zLmRpbV9pbm5lciAmJiBjb2wgPCB1bmlmb3Jtcy5kaW1fYV9vdXRlcikge1xuICAgICAgJHtnZXRXU25pcHBldChpbm5lckVsZW1lbnRTaXplVyl9XG4gICAgfVxuICAgIHJldHVybiAke3R5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVXLCBkYXRhVHlwZSl9KDAuMCk7YDtcblxuICBjb25zdCByZXNUeXBlID0gdHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZSwgZGF0YVR5cGUpO1xuICBjb25zdCBhVHlwZSA9IGlzQ2hhbm5lbHNMYXN0ID8gdHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVgsIGRhdGFUeXBlKSA6IHR5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVXLCBkYXRhVHlwZSk7XG4gIGNvbnN0IGJUeXBlID0gaXNDaGFubmVsc0xhc3QgPyB0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplVywgZGF0YVR5cGUpIDogdHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVgsIGRhdGFUeXBlKTtcbiAgY29uc3QgYXBwbHlBY3RpdmF0aW9uID0gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYXR0cmlidXRlcywgcmVzVHlwZSwgZGF0YVR5cGUpO1xuICBjb25zdCB1c2VyQ29kZSA9IGBcbiAgICBmbiBtbV9yZWFkQShiYXRjaDogaTMyLCByb3cgOiBpMzIsIGNvbEluIDogaTMyKSAtPiAke2FUeXBlfSB7XG4gICAgICAke2lzQ2hhbm5lbHNMYXN0ID8gc2FtcGxlWCA6IHNhbXBsZVd9XG4gICAgfVxuXG4gICAgZm4gbW1fcmVhZEIoYmF0Y2g6IGkzMiwgcm93IDogaTMyLCBjb2xJbiA6IGkzMikgLT4gJHtiVHlwZX0ge1xuICAgICAgJHtpc0NoYW5uZWxzTGFzdCA/IHNhbXBsZVcgOiBzYW1wbGVYfVxuICAgIH1cblxuICAgIGZuIG1tX3dyaXRlKGJhdGNoOiBpMzIsIHJvdyA6IGkzMiwgY29sSW4gOiBpMzIsIHZhbHVlSW4gOiAke3Jlc1R5cGV9KSB7XG4gICAgICBsZXQgY29sID0gY29sSW4gKiAke2lubmVyRWxlbWVudFNpemV9O1xuICAgICAgaWYgKHJvdyA8IHVuaWZvcm1zLmRpbV9hX291dGVyICYmIGNvbCA8IHVuaWZvcm1zLmRpbV9iX291dGVyKVxuICAgICAge1xuICAgICAgdmFyIHZhbHVlID0gdmFsdWVJbjtcbiAgICAgIGxldCBvdXRXaWR0aCA9ICR7aXNDaGFubmVsc0xhc3QgPyAnaTMyKHVuaWZvcm1zLnJlc3VsdF9zaGFwZVsyXSknIDogJ2kzMih1bmlmb3Jtcy5yZXN1bHRfc2hhcGVbM10pJ307XG4gICAgICAke2Nvb3JkUmVzU25pcHBldH1cbiAgICAgICR7Ymlhc1NuaXBwZXQoYWRkQmlhcyl9XG4gICAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAgIHNldE91dHB1dEF0Q29vcmRzKGNvb3Jkc1swXSwgY29vcmRzWzFdLCBjb29yZHNbMl0sIGNvb3Jkc1szXSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH1gO1xuICByZXR1cm4gdXNlckNvZGU7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlQ29udjJETWF0TXVsUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyxcbiAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBkaW1BT3V0ZXI6IG51bWJlcixcbiAgZGltQk91dGVyOiBudW1iZXIsXG4gIGRpbUlubmVyOiBudW1iZXIsXG4gIGhhc0JpYXM6IGJvb2xlYW4sXG4gIHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHM6IGJvb2xlYW4sXG4gIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uPzogKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4gbnVtYmVyW10sXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3QgaW5DaGFubmVscyA9IGlzQ2hhbm5lbHNMYXN0ID8gaW5wdXRzWzBdLmRpbXNbM10gOiBpbnB1dHNbMF0uZGltc1sxXTtcbiAgY29uc3QgYmF0Y2hTaXplID0gb3V0cHV0U2hhcGVbMF07XG4gIGNvbnN0IG91dFdpZHRoID0gaXNDaGFubmVsc0xhc3QgPyBvdXRwdXRTaGFwZVsyXSA6IG91dHB1dFNoYXBlWzNdO1xuICBjb25zdCBvdXRIZWlnaHQgPSBpc0NoYW5uZWxzTGFzdCA/IG91dHB1dFNoYXBlWzFdIDogb3V0cHV0U2hhcGVbMl07XG4gIGNvbnN0IG91dENoYW5uZWxzID0gaXNDaGFubmVsc0xhc3QgPyBvdXRwdXRTaGFwZVszXSA6IG91dHB1dFNoYXBlWzFdO1xuICAvLyBUT0RPOiBlbmFibGUgdmVjNCBmb3IgTkNIV1xuICBjb25zdCBpc1ZlYzQgPSBpc0NoYW5uZWxzTGFzdCAmJiAoaW5DaGFubmVscyAlIDQgPT09IDAgfHwgaW5DaGFubmVscyAlIDMgPT09IDApICYmIG91dENoYW5uZWxzICUgNCA9PT0gMDtcblxuICAvLyBUT0RPOiBmaW5lIHR1bmUgc2l6ZVxuICBjb25zdCBkaXNwYXRjaFggPSBpc0NoYW5uZWxzTGFzdCA/IG91dENoYW5uZWxzIDogb3V0V2lkdGggKiBvdXRIZWlnaHQ7XG4gIGNvbnN0IGRpc3BhdGNoWSA9IGlzQ2hhbm5lbHNMYXN0ID8gb3V0V2lkdGggKiBvdXRIZWlnaHQgOiBvdXRDaGFubmVscztcbiAgY29uc3Qgd29ya0dyb3VwU2l6ZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzgsIDgsIDFdO1xuICBjb25zdCBlbGVtZW50c1BlclRocmVhZCA9IGRpbUFPdXRlciA8PSA4ID8gWzQsIDEsIDFdIDogWzQsIDQsIDFdO1xuICBjb25zdCBkaXNwYXRjaCA9IFtcbiAgICBNYXRoLmNlaWwoZGlzcGF0Y2hYIC8gd29ya0dyb3VwU2l6ZVswXSAvIGVsZW1lbnRzUGVyVGhyZWFkWzBdKSxcbiAgICBNYXRoLmNlaWwoZGlzcGF0Y2hZIC8gd29ya0dyb3VwU2l6ZVsxXSAvIGVsZW1lbnRzUGVyVGhyZWFkWzFdKSxcbiAgICBNYXRoLmNlaWwoYmF0Y2hTaXplIC8gd29ya0dyb3VwU2l6ZVsyXSAvIGVsZW1lbnRzUGVyVGhyZWFkWzJdKSxcbiAgXTtcblxuICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW2NvbnYyZF9tbV93ZWJncHVdIGRpc3BhdGNoID0gJHtkaXNwYXRjaH1gKTtcblxuICBjb25zdCBpbm5lckVsZW1lbnRTaXplID0gaXNWZWM0ID8gKGlzQ2hhbm5lbHNMYXN0ICYmIGluQ2hhbm5lbHMgJSA0ICE9PSAwID8gMyA6IDQpIDogMTtcbiAgY29uc3QgdGlsZUFPdXRlciA9IHdvcmtHcm91cFNpemVbMV0gKiBlbGVtZW50c1BlclRocmVhZFsxXTtcbiAgY29uc3QgdGlsZUJPdXRlciA9IHdvcmtHcm91cFNpemVbMF0gKiBlbGVtZW50c1BlclRocmVhZFswXTtcbiAgY29uc3QgdGlsZUlubmVyID0gTWF0aC5tYXgod29ya0dyb3VwU2l6ZVswXSAqIGlubmVyRWxlbWVudFNpemUsIHdvcmtHcm91cFNpemVbMV0pO1xuICBjb25zdCBmaXRBT3V0ZXIgPSBkaW1BT3V0ZXIgJSB0aWxlQU91dGVyID09PSAwO1xuICBjb25zdCBmaXRCT3V0ZXIgPSBkaW1CT3V0ZXIgJSB0aWxlQk91dGVyID09PSAwO1xuICBjb25zdCBmaXRJbm5lciA9IGRpbUlubmVyICUgdGlsZUlubmVyID09PSAwO1xuICBjb25zdCBlbGVtZW50c1NpemUgPSBpc1ZlYzQgPyBbaW5uZXJFbGVtZW50U2l6ZSwgNCwgNF0gOiBbMSwgMSwgMV07XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGRpbUFPdXRlciB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGRpbUJPdXRlciB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGRpbUlubmVyIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogW2F0dHJpYnV0ZXMucGFkc1swXSwgYXR0cmlidXRlcy5wYWRzWzFdXSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGF0dHJpYnV0ZXMuc3RyaWRlcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGF0dHJpYnV0ZXMuZGlsYXRpb25zIH0sXG4gIF07XG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEoYXR0cmlidXRlcywgcHJvZ3JhbVVuaWZvcm1zKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzBdLmRpbXMsIGlucHV0c1sxXS5kaW1zKSk7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWydyYW5rJywgJ3JhbmsnXTtcbiAgaWYgKGhhc0JpYXMpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMl0uZGltcykpO1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3JhbmsnKTtcbiAgfVxuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRwdXRTaGFwZSkpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ2RpbV9hX291dGVyJywgdHlwZTogJ2kzMicgfSxcbiAgICAgIHsgbmFtZTogJ2RpbV9iX291dGVyJywgdHlwZTogJ2kzMicgfSxcbiAgICAgIHsgbmFtZTogJ2RpbV9pbm5lcicsIHR5cGU6ICdpMzInIH0sXG4gICAgICB7IG5hbWU6ICdwYWQnLCB0eXBlOiAnaTMyJywgbGVuZ3RoOiAyIH0sXG4gICAgICB7IG5hbWU6ICdzdHJpZGUnLCB0eXBlOiAnaTMyJywgbGVuZ3RoOiAyIH0sXG4gICAgICB7IG5hbWU6ICdkaWxhdGlvbicsIHR5cGU6ICdpMzInLCBsZW5ndGg6IDIgfSxcbiAgICBdO1xuICAgIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcyhhdHRyaWJ1dGVzLCB1bmlmb3Jtcyk7XG5cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGNvbXBvbmVudCAyLCAzLlxuICAgIGNvbnN0IGNvbXBvbmVudHMgPSBpc1ZlYzQgPyA0IDogMTtcbiAgICBjb25zdCB0ID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKGlucHV0c1swXS5kYXRhVHlwZSk7XG4gICAgbGV0IGRlY2xhcmVGdW5jdGlvbnMgPSBgXG4gICAgICBmbiBzZXRPdXRwdXRBdEluZGV4KGZsYXRJbmRleCA6IGkzMiwgdmFsdWUgOiAke2lzVmVjNCA/IGB2ZWM0PCR7dH0+YCA6IHR9KSB7XG4gICAgICAgIHJlc3VsdFtmbGF0SW5kZXhdID0gJHtpc1ZlYzQgPyBgdmVjNDwke3R9PmAgOiB0fSh2YWx1ZSk7XG4gICAgICB9XG4gICAgICBmbiBzZXRPdXRwdXRBdENvb3JkcyhkMCA6IGkzMiwgZDEgOiBpMzIsIGQyIDogaTMyLCBkMyA6IGkzMiwgdmFsdWUgOiAke2lzVmVjNCA/IGB2ZWM0PCR7dH0+YCA6IHR9KSB7XG4gICAgICAgIGxldCBmbGF0SW5kZXggPSBnZXRPdXRwdXRJbmRleEZyb21Db29yZHModmVjNDxpMzI+KGQwLCBkMSwgZDIsIGQzKSk7XG4gICAgICAgIHNldE91dHB1dEF0SW5kZXgoZmxhdEluZGV4ICR7aXNWZWM0ID8gJy8gNCcgOiAnJ30sIHZhbHVlKTtcbiAgICAgIH1gO1xuICAgIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKFxuICAgICAgJ3gnLFxuICAgICAgaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgaW5wdXRzWzBdLmRpbXMubGVuZ3RoLFxuICAgICAgaW5uZXJFbGVtZW50U2l6ZSA9PT0gMyA/IDEgOiBpbm5lckVsZW1lbnRTaXplLFxuICAgICk7XG4gICAgY29uc3QgdyA9IGlucHV0VmFyaWFibGUoJ3cnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgaW5wdXRWYXJpYWJsZXMgPSBbeCwgd107XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ3Jlc3VsdCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBpZiAoaGFzQmlhcykge1xuICAgICAgY29uc3QgYmlhcyA9IGlucHV0VmFyaWFibGUoJ2JpYXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgICBpbnB1dFZhcmlhYmxlcy5wdXNoKGJpYXMpO1xuICAgICAgZGVjbGFyZUZ1bmN0aW9ucyArPSBgXG4gICAgICAgIGZuIGdldEJpYXNCeU91dHB1dENvb3Jkcyhjb29yZHMgOiB2ZWM0PGkzMj4pIC0+ICR7aXNWZWM0ID8gYHZlYzQ8JHt0fT5gIDogdH0ge1xuICAgICAgICAgIHJldHVybiBiaWFzW2Nvb3Jkcy4ke2lzQ2hhbm5lbHNMYXN0ID8gJ3cnIDogJ3knfSR7aXNWZWM0ID8gJy8gNCcgOiAnJ31dO1xuICAgICAgICB9YDtcbiAgICB9XG5cbiAgICByZXR1cm4gYFxuICAgICAgICAke3V0aWxGdW5jdGlvbnMoJ3VuaWZvcm1zLnJlc3VsdF9zdHJpZGVzJyl9XG4gICAgICAgIC8vc3RydWN0IFVuaWZvcm1zIHsgeFNoYXBlIDogdmVjNDxpMzI+LCB3U2hhcGUgOiB2ZWM0PGkzMj4sIG91dFNoYXBlIDogdmVjNDxpMzI+LFxuICAgICAgICAvLyAgb3V0U2hhcGVTdHJpZGVzOiB2ZWMzPGkzMj4sIGZpbHRlckRpbXMgOiB2ZWMyPGkzMj4sIHBhZCA6IHZlYzI8aTMyPiwgc3RyaWRlIDogdmVjMjxpMzI+LFxuICAgICAgICAvLyAgZGlsYXRpb24gOiB2ZWMyPGkzMj4sIGRpbUFPdXRlciA6IGkzMiwgZGltQk91dGVyIDogaTMyLCBkaW1Jbm5lciA6IGkzMiB9O1xuICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFyaWFibGVzLCBvdXRwdXQpfVxuICAgICAgICAke2RlY2xhcmVGdW5jdGlvbnN9XG4gICAgICAgICR7Y29udjJkQ29tbW9uU25pcHBldChcbiAgICAgICAgICBpc0NoYW5uZWxzTGFzdCxcbiAgICAgICAgICBmaXRBT3V0ZXIsXG4gICAgICAgICAgZml0Qk91dGVyLFxuICAgICAgICAgIGZpdElubmVyLFxuICAgICAgICAgIGhhc0JpYXMsXG4gICAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICAgICBlbGVtZW50c1NpemVbMF0sXG4gICAgICAgICAgZWxlbWVudHNTaXplWzFdLFxuICAgICAgICAgIGVsZW1lbnRzU2l6ZVsyXSxcbiAgICAgICAgICB0LFxuICAgICAgICApfVxuICAgICAgICAke1xuICAgICAgICAgIGlzVmVjNFxuICAgICAgICAgICAgPyBtYWtlTWF0TXVsUGFja2VkVmVjNFNvdXJjZShlbGVtZW50c1BlclRocmVhZCwgd29ya0dyb3VwU2l6ZSwgdCwgdW5kZWZpbmVkLCAhaXNDaGFubmVsc0xhc3QsIHRpbGVJbm5lcilcbiAgICAgICAgICAgIDogbWFrZU1hdE11bFBhY2tlZFNvdXJjZShcbiAgICAgICAgICAgICAgICBlbGVtZW50c1BlclRocmVhZCxcbiAgICAgICAgICAgICAgICB3b3JrR3JvdXBTaXplLFxuICAgICAgICAgICAgICAgIHQsXG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICFpc0NoYW5uZWxzTGFzdCxcbiAgICAgICAgICAgICAgICB0aWxlSW5uZXIsXG4gICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHMsXG4gICAgICAgICAgICAgIClcbiAgICAgICAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0NvbnYyRE1hdE11bCcsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9OyR7aW5uZXJFbGVtZW50U2l6ZX07JHtpc1ZlYzR9OyR7Zml0QU91dGVyfTske2ZpdEJPdXRlcn07JHtmaXRJbm5lcn07JHt0aWxlQU91dGVyfTske3RpbGVCT3V0ZXJ9OyR7dGlsZUlubmVyfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llcyxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBkaW1zOiBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiA/IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uKG91dHB1dFNoYXBlKSA6IG91dHB1dFNoYXBlLFxuICAgICAgICAgIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBkaXNwYXRjaFswXSwgeTogZGlzcGF0Y2hbMV0sIHo6IGRpc3BhdGNoWzJdIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8vIHNhbXBsZWQgZnJvbSBbQHRlbnNvcmZsb3cvdGZqc10gdGZqcy1iYWNrZW5kLXdlYmdwdS9zcmMvY29udjNkX25haXZlX3dlYmdwdS50c1xuLy9cbi8vIG1vZGlmaWVkIHRvIGZpdCB0aGUgbmVlZHMgb2YgdGhlIHByb2plY3RcblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBMT0dfREVCVUcgfSBmcm9tICcuLi8uLi8uLi9sb2cnO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uLy4uL3R5cGVzJztcbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRFbGVtZW50QXQsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4uL2NvbW1vbic7XG5pbXBvcnQgeyBDb252QXR0cmlidXRlcyB9IGZyb20gJy4uL2NvbnYnO1xuaW1wb3J0IHsgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zLCBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhLCBnZXRBY3RpdmF0aW9uU25pcHBldCB9IGZyb20gJy4uL2Z1c2UtdXRpbHMnO1xuXG5pbXBvcnQgeyB0eXBlU25pcHBldCB9IGZyb20gJy4vYWN0aXZhdGlvbl91dGlsJztcblxuY29uc3QgYXJyYXlQcm9kdWN0ID0gKGFycjogbnVtYmVyW10pID0+IHtcbiAgbGV0IHByb2R1Y3QgPSAxO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgIHByb2R1Y3QgKj0gYXJyW2ldO1xuICB9XG4gIHJldHVybiBwcm9kdWN0O1xufTtcblxuY29uc3QgcGFyc2UzVHVwbGVQYXJhbSA9IChwYXJhbTogbnVtYmVyIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXJdKTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdID0+XG4gIHR5cGVvZiBwYXJhbSA9PT0gJ251bWJlcicgPyBbcGFyYW0sIHBhcmFtLCBwYXJhbV0gOiBwYXJhbTtcblxuY29uc3QgZ2V0RWZmZWN0aXZlRmlsdGVyU2l6ZSA9IChmaWx0ZXJTaXplOiBudW1iZXIsIGRpbGF0aW9uOiBudW1iZXIpOiBudW1iZXIgPT4ge1xuICBpZiAoZGlsYXRpb24gPD0gMSkge1xuICAgIHJldHVybiBmaWx0ZXJTaXplO1xuICB9XG5cbiAgcmV0dXJuIGZpbHRlclNpemUgKyAoZmlsdGVyU2l6ZSAtIDEpICogKGRpbGF0aW9uIC0gMSk7XG59O1xuXG5jb25zdCBjb21wdXRlRGVmYXVsdFBhZCA9IChcbiAgaW5wdXRTaGFwZTogW251bWJlciwgbnVtYmVyXSB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICBmaWVsZFNpemU6IG51bWJlcixcbiAgc3RyaWRlOiBudW1iZXIsXG4gIGRpbGF0aW9uID0gMSxcbik6IG51bWJlciA9PiB7XG4gIGNvbnN0IGVmZmVjdGl2ZUZpZWxkU2l6ZSA9IGdldEVmZmVjdGl2ZUZpbHRlclNpemUoZmllbGRTaXplLCBkaWxhdGlvbik7XG4gIHJldHVybiBNYXRoLmZsb29yKChpbnB1dFNoYXBlWzBdICogKHN0cmlkZSAtIDEpIC0gc3RyaWRlICsgZWZmZWN0aXZlRmllbGRTaXplKSAvIDIpO1xufTtcblxuY29uc3QgY29tcHV0ZU91dHB1dFNoYXBlNEQgPSAoXG4gIGluU2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICBmaWx0ZXJTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICBvdXRDaGFubmVsczogbnVtYmVyLFxuICBzdHJpZGVzOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIHplcm9QYWQ/OiBudW1iZXIsXG4pOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9PiB7XG4gIGlmICh6ZXJvUGFkID09IG51bGwpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICB6ZXJvUGFkID0gY29tcHV0ZURlZmF1bHRQYWQoaW5TaGFwZSwgZmlsdGVyU2hhcGVbMF0sIHN0cmlkZXNbMF0pO1xuICB9XG4gIGNvbnN0IG91dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9IFswLCAwLCAwLCBvdXRDaGFubmVsc107XG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCAzOyBpbmRleCsrKSB7XG4gICAgaWYgKGluU2hhcGVbaW5kZXhdICsgMiAqIHplcm9QYWQgPj0gZmlsdGVyU2hhcGVbaW5kZXhdKSB7XG4gICAgICBvdXRTaGFwZVtpbmRleF0gPSBNYXRoLnRydW5jKChpblNoYXBlW2luZGV4XSAtIGZpbHRlclNoYXBlW2luZGV4XSArIDIgKiB6ZXJvUGFkKSAvIHN0cmlkZXNbaW5kZXhdICsgMSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBvdXRTaGFwZTtcbn07XG5cbmNvbnN0IGdldDNEUGFkQW5kT3V0SW5mbyA9IChcbiAgcGFkOiBudW1iZXIgfCBzdHJpbmcgfCBudW1iZXJbXSxcbiAgaW5EZXB0aDogbnVtYmVyLFxuICBpbkhlaWdodDogbnVtYmVyLFxuICBpbldpZHRoOiBudW1iZXIsXG4gIHN0cmlkZURlcHRoOiBudW1iZXIsXG4gIHN0cmlkZUhlaWdodDogbnVtYmVyLFxuICBzdHJpZGVXaWR0aDogbnVtYmVyLFxuICBmaWx0ZXJEZXB0aDogbnVtYmVyLFxuICBmaWx0ZXJIZWlnaHQ6IG51bWJlcixcbiAgZmlsdGVyV2lkdGg6IG51bWJlcixcbik6IHsgcGFkSW5mbzogUGFkSW5mbzNEOyBvdXREZXB0aDogbnVtYmVyOyBvdXRIZWlnaHQ6IG51bWJlcjsgb3V0V2lkdGg6IG51bWJlciB9ID0+IHtcbiAgbGV0IHBhZEluZm86IFBhZEluZm8zRDtcbiAgbGV0IG91dERlcHRoOiBudW1iZXI7XG4gIGxldCBvdXRIZWlnaHQ6IG51bWJlcjtcbiAgbGV0IG91dFdpZHRoOiBudW1iZXI7XG5cbiAgaWYgKHBhZCA9PT0gJ1ZBTElEJykge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wYXJhbS1yZWFzc2lnblxuICAgIHBhZCA9IDA7XG4gIH1cblxuICBpZiAodHlwZW9mIHBhZCA9PT0gJ251bWJlcicpIHtcbiAgICBwYWRJbmZvID0geyB0b3A6IHBhZCwgYm90dG9tOiBwYWQsIGxlZnQ6IHBhZCwgcmlnaHQ6IHBhZCwgZnJvbnQ6IHBhZCwgYmFjazogcGFkIH07XG4gICAgY29uc3Qgb3V0U2hhcGUgPSBjb21wdXRlT3V0cHV0U2hhcGU0RChcbiAgICAgIFtpbkRlcHRoLCBpbkhlaWdodCwgaW5XaWR0aCwgMV0sXG4gICAgICBbZmlsdGVyRGVwdGgsIGZpbHRlckhlaWdodCwgZmlsdGVyV2lkdGhdLFxuICAgICAgMSxcbiAgICAgIFtzdHJpZGVEZXB0aCwgc3RyaWRlSGVpZ2h0LCBzdHJpZGVXaWR0aF0sXG4gICAgICBwYWQsXG4gICAgKTtcbiAgICBvdXREZXB0aCA9IG91dFNoYXBlWzBdO1xuICAgIG91dEhlaWdodCA9IG91dFNoYXBlWzFdO1xuICAgIG91dFdpZHRoID0gb3V0U2hhcGVbMl07XG4gIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShwYWQpKSB7XG4gICAgaWYgKCFwYWQuZXZlcnkoKHZhbCwgXywgYXJyKSA9PiB2YWwgPT09IGFyclswXSkpIHtcbiAgICAgIHRocm93IEVycm9yKGBVbnN1cHBvcnRlZCBwYWRkaW5nIHBhcmFtZXRlcjogJHtwYWR9YCk7XG4gICAgfVxuICAgIHBhZEluZm8gPSB7IHRvcDogcGFkWzBdLCBib3R0b206IHBhZFsxXSwgbGVmdDogcGFkWzJdLCByaWdodDogcGFkWzNdLCBmcm9udDogcGFkWzRdLCBiYWNrOiBwYWRbNV0gfTtcbiAgICBjb25zdCBvdXRTaGFwZSA9IGNvbXB1dGVPdXRwdXRTaGFwZTREKFxuICAgICAgW2luRGVwdGgsIGluSGVpZ2h0LCBpbldpZHRoLCAxXSxcbiAgICAgIFtmaWx0ZXJEZXB0aCwgZmlsdGVySGVpZ2h0LCBmaWx0ZXJXaWR0aF0sXG4gICAgICAxLFxuICAgICAgW3N0cmlkZURlcHRoLCBzdHJpZGVIZWlnaHQsIHN0cmlkZVdpZHRoXSxcbiAgICAgIHBhZFswXSxcbiAgICApO1xuICAgIG91dERlcHRoID0gb3V0U2hhcGVbMF07XG4gICAgb3V0SGVpZ2h0ID0gb3V0U2hhcGVbMV07XG4gICAgb3V0V2lkdGggPSBvdXRTaGFwZVsyXTtcbiAgfSBlbHNlIGlmIChwYWQgPT09ICdTQU1FX1VQUEVSJykge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgJ1NBTUVfTE9XRVInLlxuICAgIG91dERlcHRoID0gTWF0aC5jZWlsKGluRGVwdGggLyBzdHJpZGVEZXB0aCk7XG4gICAgb3V0SGVpZ2h0ID0gTWF0aC5jZWlsKGluSGVpZ2h0IC8gc3RyaWRlSGVpZ2h0KTtcbiAgICBvdXRXaWR0aCA9IE1hdGguY2VpbChpbldpZHRoIC8gc3RyaWRlV2lkdGgpO1xuICAgIGNvbnN0IHBhZEFsb25nRGVwdGggPSAob3V0RGVwdGggLSAxKSAqIHN0cmlkZURlcHRoICsgZmlsdGVyRGVwdGggLSBpbkRlcHRoO1xuICAgIGNvbnN0IHBhZEFsb25nSGVpZ2h0ID0gKG91dEhlaWdodCAtIDEpICogc3RyaWRlSGVpZ2h0ICsgZmlsdGVySGVpZ2h0IC0gaW5IZWlnaHQ7XG4gICAgY29uc3QgcGFkQWxvbmdXaWR0aCA9IChvdXRXaWR0aCAtIDEpICogc3RyaWRlV2lkdGggKyBmaWx0ZXJXaWR0aCAtIGluV2lkdGg7XG4gICAgY29uc3QgZnJvbnQgPSBNYXRoLmZsb29yKHBhZEFsb25nRGVwdGggLyAyKTtcbiAgICBjb25zdCBiYWNrID0gcGFkQWxvbmdEZXB0aCAtIGZyb250O1xuICAgIGNvbnN0IHRvcCA9IE1hdGguZmxvb3IocGFkQWxvbmdIZWlnaHQgLyAyKTtcbiAgICBjb25zdCBib3R0b20gPSBwYWRBbG9uZ0hlaWdodCAtIHRvcDtcbiAgICBjb25zdCBsZWZ0ID0gTWF0aC5mbG9vcihwYWRBbG9uZ1dpZHRoIC8gMik7XG4gICAgY29uc3QgcmlnaHQgPSBwYWRBbG9uZ1dpZHRoIC0gbGVmdDtcblxuICAgIHBhZEluZm8gPSB7IHRvcCwgYm90dG9tLCBsZWZ0LCByaWdodCwgZnJvbnQsIGJhY2sgfTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBFcnJvcihgVW5rbm93biBwYWRkaW5nIHBhcmFtZXRlcjogJHtwYWR9YCk7XG4gIH1cbiAgcmV0dXJuIHsgcGFkSW5mbywgb3V0RGVwdGgsIG91dEhlaWdodCwgb3V0V2lkdGggfTtcbn07XG5cbnR5cGUgUGFkSW5mbzNEID0ge1xuICB0b3A6IG51bWJlcjtcbiAgbGVmdDogbnVtYmVyO1xuICByaWdodDogbnVtYmVyO1xuICBib3R0b206IG51bWJlcjtcbiAgZnJvbnQ6IG51bWJlcjtcbiAgYmFjazogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgQ29udjNESW5mbyA9IHtcbiAgYmF0Y2hTaXplOiBudW1iZXI7XG4gIGluRGVwdGg6IG51bWJlcjtcbiAgaW5IZWlnaHQ6IG51bWJlcjtcbiAgaW5XaWR0aDogbnVtYmVyO1xuICBpbkNoYW5uZWxzOiBudW1iZXI7XG4gIG91dERlcHRoOiBudW1iZXI7XG4gIG91dEhlaWdodDogbnVtYmVyO1xuICBvdXRXaWR0aDogbnVtYmVyO1xuICBvdXRDaGFubmVsczogbnVtYmVyO1xuICBkYXRhRm9ybWF0OiAnY2hhbm5lbHNGaXJzdCcgfCAnY2hhbm5lbHNMYXN0JztcbiAgc3RyaWRlRGVwdGg6IG51bWJlcjtcbiAgc3RyaWRlSGVpZ2h0OiBudW1iZXI7XG4gIHN0cmlkZVdpZHRoOiBudW1iZXI7XG4gIGRpbGF0aW9uRGVwdGg6IG51bWJlcjtcbiAgZGlsYXRpb25IZWlnaHQ6IG51bWJlcjtcbiAgZGlsYXRpb25XaWR0aDogbnVtYmVyO1xuICBmaWx0ZXJEZXB0aDogbnVtYmVyO1xuICBmaWx0ZXJIZWlnaHQ6IG51bWJlcjtcbiAgZmlsdGVyV2lkdGg6IG51bWJlcjtcbiAgZWZmZWN0aXZlRmlsdGVyRGVwdGg6IG51bWJlcjtcbiAgZWZmZWN0aXZlRmlsdGVySGVpZ2h0OiBudW1iZXI7XG4gIGVmZmVjdGl2ZUZpbHRlcldpZHRoOiBudW1iZXI7XG4gIHBhZEluZm86IFBhZEluZm8zRDtcbiAgaW5TaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgb3V0U2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gIGZpbHRlclNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvbXB1dGVDb252M0RJbmZvID0gKFxuICBpblNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICBmaWx0ZXJTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgc3RyaWRlczogbnVtYmVyIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICBkaWxhdGlvbnM6IG51bWJlciB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgcGFkOiBudW1iZXIgfCBzdHJpbmcgfCBudW1iZXJbXSxcbiAgZGVwdGh3aXNlID0gZmFsc2UsXG4gIGRhdGFGb3JtYXQ6ICdjaGFubmVsc0ZpcnN0JyB8ICdjaGFubmVsc0xhc3QnID0gJ2NoYW5uZWxzTGFzdCcsXG4pOiBDb252M0RJbmZvID0+IHtcbiAgbGV0IGJhdGNoU2l6ZSwgaW5EZXB0aCwgaW5IZWlnaHQsIGluV2lkdGgsIGluQ2hhbm5lbHM7XG4gIGlmIChkYXRhRm9ybWF0ID09PSAnY2hhbm5lbHNMYXN0Jykge1xuICAgIFtiYXRjaFNpemUsIGluRGVwdGgsIGluSGVpZ2h0LCBpbldpZHRoLCBpbkNoYW5uZWxzXSA9IGluU2hhcGU7XG4gIH0gZWxzZSBpZiAoZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzRmlyc3QnKSB7XG4gICAgW2JhdGNoU2l6ZSwgaW5DaGFubmVscywgaW5EZXB0aCwgaW5IZWlnaHQsIGluV2lkdGhdID0gaW5TaGFwZTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gZGF0YUZvcm1hdCAke2RhdGFGb3JtYXR9YCk7XG4gIH1cbiAgY29uc3QgW2ZpbHRlckNoYW5uZWxzLCAsIGZpbHRlckRlcHRoLCBmaWx0ZXJIZWlnaHQsIGZpbHRlcldpZHRoXSA9IGZpbHRlclNoYXBlO1xuXG4gIGNvbnN0IFtzdHJpZGVEZXB0aCwgc3RyaWRlSGVpZ2h0LCBzdHJpZGVXaWR0aF0gPSBwYXJzZTNUdXBsZVBhcmFtKHN0cmlkZXMpO1xuICBjb25zdCBbZGlsYXRpb25EZXB0aCwgZGlsYXRpb25IZWlnaHQsIGRpbGF0aW9uV2lkdGhdID0gcGFyc2UzVHVwbGVQYXJhbShkaWxhdGlvbnMpO1xuXG4gIGNvbnN0IGVmZmVjdGl2ZUZpbHRlckRlcHRoID0gZ2V0RWZmZWN0aXZlRmlsdGVyU2l6ZShmaWx0ZXJEZXB0aCwgZGlsYXRpb25EZXB0aCk7XG4gIGNvbnN0IGVmZmVjdGl2ZUZpbHRlckhlaWdodCA9IGdldEVmZmVjdGl2ZUZpbHRlclNpemUoZmlsdGVySGVpZ2h0LCBkaWxhdGlvbkhlaWdodCk7XG4gIGNvbnN0IGVmZmVjdGl2ZUZpbHRlcldpZHRoID0gZ2V0RWZmZWN0aXZlRmlsdGVyU2l6ZShmaWx0ZXJXaWR0aCwgZGlsYXRpb25XaWR0aCk7XG4gIGNvbnN0IHsgcGFkSW5mbywgb3V0RGVwdGgsIG91dEhlaWdodCwgb3V0V2lkdGggfSA9IGdldDNEUGFkQW5kT3V0SW5mbyhcbiAgICBwYWQsXG4gICAgaW5EZXB0aCxcbiAgICBpbkhlaWdodCxcbiAgICBpbldpZHRoLFxuICAgIHN0cmlkZURlcHRoLFxuICAgIHN0cmlkZUhlaWdodCxcbiAgICBzdHJpZGVXaWR0aCxcbiAgICBlZmZlY3RpdmVGaWx0ZXJEZXB0aCxcbiAgICBlZmZlY3RpdmVGaWx0ZXJIZWlnaHQsXG4gICAgZWZmZWN0aXZlRmlsdGVyV2lkdGgsXG4gICk7XG5cbiAgY29uc3Qgb3V0Q2hhbm5lbHMgPSBkZXB0aHdpc2UgPyBmaWx0ZXJDaGFubmVscyAqIGluQ2hhbm5lbHMgOiBmaWx0ZXJDaGFubmVscztcblxuICBsZXQgb3V0U2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPSBbMCwgMCwgMCwgMCwgMF07XG4gIGlmIChkYXRhRm9ybWF0ID09PSAnY2hhbm5lbHNGaXJzdCcpIHtcbiAgICBvdXRTaGFwZSA9IFtiYXRjaFNpemUsIG91dENoYW5uZWxzLCBvdXREZXB0aCwgb3V0SGVpZ2h0LCBvdXRXaWR0aF07XG4gIH0gZWxzZSBpZiAoZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzTGFzdCcpIHtcbiAgICBvdXRTaGFwZSA9IFtiYXRjaFNpemUsIG91dERlcHRoLCBvdXRIZWlnaHQsIG91dFdpZHRoLCBvdXRDaGFubmVsc107XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGJhdGNoU2l6ZSxcbiAgICBkYXRhRm9ybWF0LFxuICAgIGluRGVwdGgsXG4gICAgaW5IZWlnaHQsXG4gICAgaW5XaWR0aCxcbiAgICBpbkNoYW5uZWxzLFxuICAgIG91dERlcHRoLFxuICAgIG91dEhlaWdodCxcbiAgICBvdXRXaWR0aCxcbiAgICBvdXRDaGFubmVscyxcbiAgICBwYWRJbmZvLFxuICAgIHN0cmlkZURlcHRoLFxuICAgIHN0cmlkZUhlaWdodCxcbiAgICBzdHJpZGVXaWR0aCxcbiAgICBmaWx0ZXJEZXB0aCxcbiAgICBmaWx0ZXJIZWlnaHQsXG4gICAgZmlsdGVyV2lkdGgsXG4gICAgZWZmZWN0aXZlRmlsdGVyRGVwdGgsXG4gICAgZWZmZWN0aXZlRmlsdGVySGVpZ2h0LFxuICAgIGVmZmVjdGl2ZUZpbHRlcldpZHRoLFxuICAgIGRpbGF0aW9uRGVwdGgsXG4gICAgZGlsYXRpb25IZWlnaHQsXG4gICAgZGlsYXRpb25XaWR0aCxcbiAgICBpblNoYXBlLFxuICAgIG91dFNoYXBlLFxuICAgIGZpbHRlclNoYXBlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUNvbnYzRE5haXZlUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyxcbiAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBmaWx0ZXJEaW1zOiByZWFkb25seSBudW1iZXJbXSxcbiAgcGFkczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGRhdGFGb3JtYXQ6IHN0cmluZyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaXNDaGFubmVsTGFzdCA9IGRhdGFGb3JtYXQgPT09ICdjaGFubmVsc0xhc3QnO1xuICBjb25zdCBpbkNoYW5uZWxzID0gaXNDaGFubmVsTGFzdCA/IGlucHV0c1swXS5kaW1zWzNdIDogaW5wdXRzWzBdLmRpbXNbMV07XG4gIC8vIFRPRE86IGVuYWJsZSB2ZWM0LlxuICBjb25zdCBpc1ZlYzQgPSBmYWxzZTtcbiAgY29uc3Qgd29ya0dyb3VwU2l6ZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzY0LCAxLCAxXTtcbiAgY29uc3QgZGlzcGF0Y2hMYXlvdXQgPSB7IHg6IG91dHB1dFNoYXBlLm1hcCgoXywgaSkgPT4gaSkgfTtcbiAgY29uc3QgZGlzcGF0Y2ggPSBbTWF0aC5jZWlsKGFycmF5UHJvZHVjdChkaXNwYXRjaExheW91dC54Lm1hcCgoZCkgPT4gb3V0cHV0U2hhcGVbZF0pKSAvIHdvcmtHcm91cFNpemVbMF0pLCAxLCAxXTtcblxuICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW2NvbnYzZF9uYWl2ZV93ZWJncHVdIGRpc3BhdGNoID0gJHtkaXNwYXRjaH1gKTtcblxuICBjb25zdCBpbm5lckVsZW1lbnRTaXplID0gaXNWZWM0ID8gKGlzQ2hhbm5lbExhc3QgJiYgaW5DaGFubmVscyAlIDQgIT09IDAgPyAzIDogNCkgOiAxO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZmlsdGVyRGltcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYWRzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF0dHJpYnV0ZXMuc3RyaWRlcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLmRpbGF0aW9ucyB9LFxuICBdO1xuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhKGF0dHJpYnV0ZXMsIHByb2dyYW1Vbmlmb3Jtcyk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBpbnB1dHNbMV0uZGltcykpO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsncmFuaycsICdyYW5rJ107XG4gIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID09PSAzO1xuICBpZiAoaGFzQmlhcykge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1syXS5kaW1zKSk7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgncmFuaycpO1xuICB9XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnZmlsdGVyX2RpbXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBmaWx0ZXJEaW1zLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAncGFkcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IHBhZHMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdzdHJpZGVzJywgdHlwZTogJ3UzMicsIGxlbmd0aDogYXR0cmlidXRlcy5zdHJpZGVzLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnZGlsYXRpb25zJywgdHlwZTogJ3UzMicsIGxlbmd0aDogYXR0cmlidXRlcy5kaWxhdGlvbnMubGVuZ3RoIH0sXG4gICAgXTtcbiAgICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMoYXR0cmlidXRlcywgdW5pZm9ybXMpO1xuICAgIC8vIFRPRE86IHN1cHBvcnQgY29tcG9uZW50IDIsIDMuXG4gICAgY29uc3QgY29tcG9uZW50cyA9IGlzVmVjNCA/IDQgOiAxO1xuICAgIGNvbnN0IHQgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcblxuICAgIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKFxuICAgICAgJ3gnLFxuICAgICAgaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgaW5wdXRzWzBdLmRpbXMubGVuZ3RoLFxuICAgICAgaW5uZXJFbGVtZW50U2l6ZSA9PT0gMyA/IDEgOiBpbm5lckVsZW1lbnRTaXplLFxuICAgICk7XG4gICAgY29uc3QgdyA9IGlucHV0VmFyaWFibGUoJ1cnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgaW5wdXRWYXJpYWJsZXMgPSBbeCwgd107XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ3Jlc3VsdCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBsZXQgZGVjbGFyZUZ1bmN0aW9ucyA9ICcnO1xuICAgIGlmIChoYXNCaWFzKSB7XG4gICAgICBjb25zdCBiaWFzID0gaW5wdXRWYXJpYWJsZSgnYmlhcycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICAgIGlucHV0VmFyaWFibGVzLnB1c2goYmlhcyk7XG4gICAgICBkZWNsYXJlRnVuY3Rpb25zICs9IGBcbiAgICAgICAgZm4gZ2V0Qmlhc0J5T3V0cHV0Q29vcmRzKGNvb3JkcyA6IGFycmF5PHUzMiwgNT4pIC0+ICR7aXNWZWM0ID8gYHZlYzQ8JHt0fT5gIDogdH0ge1xuICAgICAgICAgIHJldHVybiBiaWFzWyR7aXNDaGFubmVsTGFzdCA/IGdldEVsZW1lbnRBdCgnY29vcmRzJywgNCwgNSkgOiBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDEsIDUpfSR7XG4gICAgICAgICAgICBpc1ZlYzQgPyAnLyA0JyA6ICcnXG4gICAgICAgICAgfV07XG4gICAgICAgIH1gO1xuICAgIH1cbiAgICBjb25zdCByZXNUeXBlID0gdHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZSwgdCk7XG4gICAgY29uc3QgYXBwbHlBY3RpdmF0aW9uID0gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYXR0cmlidXRlcywgcmVzVHlwZSwgdCk7XG5cbiAgICByZXR1cm4gYFxuICAgICAgICAgICAgJHtkZWNsYXJlRnVuY3Rpb25zfVxuICAgICAgICAgICAgZm4gZ2V0WChkMCA6IHUzMiwgZDEgOiB1MzIsIGQyIDogdTMyLCBkMyA6IHUzMiwgZDQgOiB1MzIpIC0+IGYzMiB7XG4gICAgICAgICAgICAgIGxldCBhSW5kaWNlcyA9IGFycmF5PHUzMiwgNT4oZDAsIGQxLCBkMiwgZDMsIGQ0KTtcbiAgICAgICAgICAgICAgcmV0dXJuICR7eC5nZXRCeUluZGljZXMoJ2FJbmRpY2VzJyl9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm4gZ2V0VyhkMCA6IHUzMiwgZDEgOiB1MzIsIGQyIDogdTMyLCBkMyA6IHUzMiwgZDQgOiB1MzIpIC0+IGYzMiB7XG4gICAgICAgICAgICAgIGxldCBhSW5kaWNlcyA9IGFycmF5PHUzMiwgNT4oZDAsIGQxLCBkMiwgZDMsIGQ0KTtcbiAgICAgICAgICAgICAgcmV0dXJuICR7dy5nZXRCeUluZGljZXMoJ2FJbmRpY2VzJyl9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICAgICAgICAgICAgbGV0IGNvb3JkcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgICAgICAgICAgbGV0IGJhdGNoID0gJHtnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDAsIHgucmFuayl9O1xuICAgICAgICAgICAgICBsZXQgZDIgPSAke1xuICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3QgPyBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIHgucmFuayAtIDEsIHgucmFuaykgOiBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDEsIHgucmFuaylcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgbGV0IHhGUkNDb3JuZXIgPSB2ZWMzPHUzMj4oJHtcbiAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0ID8gZ2V0RWxlbWVudEF0KCdjb29yZHMnLCAxLCB4LnJhbmspIDogZ2V0RWxlbWVudEF0KCdjb29yZHMnLCAyLCB4LnJhbmspXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICR7aXNDaGFubmVsTGFzdCA/IGdldEVsZW1lbnRBdCgnY29vcmRzJywgMiwgeC5yYW5rKSA6IGdldEVsZW1lbnRBdCgnY29vcmRzJywgMywgeC5yYW5rKX0sXG4gICAgICAgICAgICAgICR7XG4gICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdCA/IGdldEVsZW1lbnRBdCgnY29vcmRzJywgMywgeC5yYW5rKSA6IGdldEVsZW1lbnRBdCgnY29vcmRzJywgNCwgeC5yYW5rKVxuICAgICAgICAgICAgICB9KSAqIHVuaWZvcm1zLnN0cmlkZXMgLSB1bmlmb3Jtcy5wYWRzO1xuICAgICAgICAgICAgICBsZXQgeEZDb3JuZXIgPSB4RlJDQ29ybmVyLng7XG4gICAgICAgICAgICAgIGxldCB4UkNvcm5lciA9IHhGUkNDb3JuZXIueTtcbiAgICAgICAgICAgICAgbGV0IHhDQ29ybmVyID0geEZSQ0Nvcm5lci56O1xuICAgICAgICAgICAgICBsZXQgeFNoYXBlWSA9ICR7XG4gICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICAgICAgICAgICAgPyBnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCAxLCB4LnJhbmspXG4gICAgICAgICAgICAgICAgICA6IGdldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIDIsIHgucmFuaylcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgbGV0IHhTaGFwZVogPSAke1xuICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3RcbiAgICAgICAgICAgICAgICAgID8gZ2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgMiwgeC5yYW5rKVxuICAgICAgICAgICAgICAgICAgOiBnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCAzLCB4LnJhbmspXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGxldCB4U2hhcGVXID0gJHtcbiAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgICAgICAgICAgICA/IGdldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIDMsIHgucmFuaylcbiAgICAgICAgICAgICAgICAgIDogZ2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgNCwgeC5yYW5rKVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBsZXQgeFNoYXBlVSA9ICR7XG4gICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICAgICAgICAgICAgPyBnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCA0LCB4LnJhbmspXG4gICAgICAgICAgICAgICAgICA6IGdldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIDEsIHgucmFuaylcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgbGV0IGlucHV0RGVwdGhOZWFyZXN0VmVjNCA9ICh4U2hhcGVVIC8gNCkgKiA0O1xuICAgICAgICAgICAgICBsZXQgaW5wdXREZXB0aFZlYzRSZW1haW5kZXIgPSB4U2hhcGVVICUgNDtcblxuICAgICAgICAgICAgICB2YXIgdmFsdWUgPSAwLjA7XG4gICAgICAgICAgICAgIGZvciAodmFyIHdGID0gMHU7IHdGIDwgdW5pZm9ybXMuZmlsdGVyX2RpbXNbMF07IHdGKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgeEYgPSB4RkNvcm5lciArIHdGICogdW5pZm9ybXMuZGlsYXRpb25zWzBdO1xuICAgICAgICAgICAgICAgIGlmICh4RiA8IDAgfHwgeEYgPj0geFNoYXBlWSkge1xuICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgd1IgPSAwdTsgd1IgPCB1bmlmb3Jtcy5maWx0ZXJfZGltc1sxXTsgd1IrKykge1xuICAgICAgICAgICAgICAgICAgbGV0IHhSID0geFJDb3JuZXIgKyB3UiAqIHVuaWZvcm1zLmRpbGF0aW9uc1sxXTtcbiAgICAgICAgICAgICAgICAgIGlmICh4UiA8IDAgfHwgeFIgPj0geFNoYXBlWikge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgZm9yICh2YXIgd0MgPSAwdTsgd0MgPCB1bmlmb3Jtcy5maWx0ZXJfZGltc1syXTsgd0MrKykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgeEMgPSB4Q0Nvcm5lciArIHdDICogdW5pZm9ybXMuZGlsYXRpb25zWzJdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoeEMgPCAwIHx8IHhDID49IHhTaGFwZVcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGQxID0gMHU7IGQxIDwgaW5wdXREZXB0aE5lYXJlc3RWZWM0OyBkMSArPSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPyBgbGV0IHhWYWx1ZXMgPSB2ZWM0PGYzMj4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgZDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGQxICsgMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgZDEgKyAyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBkMSArIDMpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDogYGxldCB4VmFsdWVzID0gdmVjNDxmMzI+KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIGQxLCB4RiwgeFIsIHhDKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCBkMSArIDEsIHhGLCB4UiwgeEMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIGQxICsgMiwgeEYsIHhSLCB4QyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgZDEgKyAzLCB4RiwgeFIsIHhDKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgd1ZhbHVlcyA9IHZlYzQ8ZjMyPihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFcoZDIsIGQxLCB3Riwgd1IsIHdDKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFcoZDIsIGQxICsgMSwgd0YsIHdSLCB3QyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRXKGQyLCBkMSArIDIsIHdGLCB3Uiwgd0MpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0VyhkMiwgZDEgKyAzLCB3Riwgd1IsIHdDKSk7XG4gICAgICAgICAgICAgICAgICAgICAgdmFsdWUgKz0gZG90KHhWYWx1ZXMsIHdWYWx1ZXMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dERlcHRoVmVjNFJlbWFpbmRlciA9PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBgdmFsdWUgKz0gZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgaW5wdXREZXB0aE5lYXJlc3RWZWM0KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAqIGdldFcoZDIsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCwgd0YsIHdSLCB3Qyk7YFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogYHZhbHVlICs9IGdldFgoYmF0Y2gsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCwgeEYsIHhSLCB4QylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKiBnZXRXKGQyLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQsIHdGLCB3Uiwgd0MpO2BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpbnB1dERlcHRoVmVjNFJlbWFpbmRlciA9PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPyBgbGV0IHhWYWx1ZXMgPSB2ZWMyPGYzMj4oXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgaW5wdXREZXB0aE5lYXJlc3RWZWM0ICsgMSkpO1xuICAgICAgICAgICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgOiBgbGV0IHhWYWx1ZXMgPSB2ZWMyPGYzMj4oXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQsIHhGLCB4UiwgeEMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgaW5wdXREZXB0aE5lYXJlc3RWZWM0ICsgMSwgeEYsIHhSLCB4QykpO1xuICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgd1ZhbHVlcyA9IHZlYzI8ZjMyPihcbiAgICAgICAgICAgICAgICAgICAgICBnZXRXKGQyLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQsIHdGLCB3Uiwgd0MpLFxuICAgICAgICAgICAgICAgICAgICAgIGdldFcoZDIsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCArIDEsIHdGLCB3Uiwgd0MpKTtcbiAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSArPSBkb3QoeFZhbHVlcywgd1ZhbHVlcyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5wdXREZXB0aFZlYzRSZW1haW5kZXIgPT0gMykge1xuICAgICAgICAgICAgICAgICAgICAgICR7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgID8gYGxldCB4VmFsdWVzID0gdmVjMzxmMzI+KFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgaW5wdXREZXB0aE5lYXJlc3RWZWM0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCArIDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgaW5wdXREZXB0aE5lYXJlc3RWZWM0ICsgMikpO1xuICAgICAgICAgICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgOiBgbGV0IHhWYWx1ZXMgPSB2ZWMzPGYzMj4oXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQsIHhGLCB4UiwgeEMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgaW5wdXREZXB0aE5lYXJlc3RWZWM0ICsgMSwgeEYsIHhSLCB4QyksXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgKyAyLCB4RiwgeFIsIHhDKSk7XG4gICAgICAgICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxldCB3VmFsdWVzID0gdmVjMzxmMzI+KFxuICAgICAgICAgICAgICAgICAgICAgIGdldFcoZDIsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCwgd0YsIHdSLCB3QyksXG4gICAgICAgICAgICAgICAgICAgICAgZ2V0VyhkMiwgaW5wdXREZXB0aE5lYXJlc3RWZWM0ICsgMSwgd0YsIHdSLCB3QyksXG4gICAgICAgICAgICAgICAgICAgICAgZ2V0VyhkMiwgaW5wdXREZXB0aE5lYXJlc3RWZWM0ICsgMiwgd0YsIHdSLCB3QykpO1xuICAgICAgICAgICAgICAgICAgICAgIHZhbHVlICs9IGRvdCh4VmFsdWVzLCB3VmFsdWVzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAke2hhc0JpYXMgPyAndmFsdWUgPSB2YWx1ZSArIGdldEJpYXNCeU91dHB1dENvb3Jkcyhjb29yZHMpJyA6ICcnfTtcbiAgICAgICAgICAgICAgJHthcHBseUFjdGl2YXRpb259XG4gICAgICAgICAgICAgIHJlc3VsdFtnbG9iYWxfaWR4XSA9IGYzMih2YWx1ZSk7XG4gICAgICAgICAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0NvbnYzRE5haXZlJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fTske2lzQ2hhbm5lbExhc3R9OyR7aW5uZXJFbGVtZW50U2l6ZX07JHtoYXNCaWFzfWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBkaXNwYXRjaFswXSwgeTogZGlzcGF0Y2hbMV0sIHo6IGRpc3BhdGNoWzJdIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgZ2V0TWF4Q29tcG9uZW50cyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuaW1wb3J0IHsgQ29udkF0dHJpYnV0ZXMgfSBmcm9tICcuL2NvbnYnO1xuaW1wb3J0IHsgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zLCBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhLCBnZXRBY3RpdmF0aW9uU25pcHBldCB9IGZyb20gJy4vZnVzZS11dGlscyc7XG5cbi8qKlxuICogbmFpdmUgZ3JvdXBlZCBjb252IGltcGxlbWVudGF0aW9uLCBzdXBwb3J0cyAxZC8yZCBjb252XG4gKiBAcGFyYW0gc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24gLSBhbiBvcHRpb25hbCBmdW5jdGlvbiB0byBzcXVlZXplIHRoZSBvdXRwdXQgc2hhcGUsIG9ubHkgdXNlZCBpbiBjb252MWRcbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZUdyb3VwZWRDb252UHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyxcbiAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbj86IChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pID0+IG51bWJlcltdLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA+IDI7XG4gIGNvbnN0IHByb2Nlc3NCaWFzID0gaGFzQmlhcyA/ICd2YWx1ZSArPSBiW291dHB1dF9jaGFubmVsXTsnIDogJyc7XG4gIGNvbnN0IHhTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCB3U2hhcGUgPSBpbnB1dHNbMV0uZGltcztcblxuICBjb25zdCBpc0NoYW5uZWxMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3Qgb3V0cHV0Q2hhbm5lbHMgPSBpc0NoYW5uZWxMYXN0ID8gb3V0cHV0U2hhcGVbM10gOiBvdXRwdXRTaGFwZVsxXTtcbiAgY29uc3Qgb3V0cHV0Q2hhbm5lbHNQZXJHcm91cCA9IG91dHB1dENoYW5uZWxzIC8gYXR0cmlidXRlcy5ncm91cDtcbiAgY29uc3QgY29tcG9uZW50cyA9IGlzQ2hhbm5lbExhc3QgJiYgb3V0cHV0Q2hhbm5lbHNQZXJHcm91cCA+PSA0ID8gZ2V0TWF4Q29tcG9uZW50cyhvdXRwdXRDaGFubmVscykgOiAxO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gY29tcG9uZW50cztcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXR0cmlidXRlcy5kaWxhdGlvbnMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogW2F0dHJpYnV0ZXMuc3RyaWRlc1swXSwgYXR0cmlidXRlcy5zdHJpZGVzWzFdXSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBbYXR0cmlidXRlcy5wYWRzWzBdLCBhdHRyaWJ1dGVzLnBhZHNbMV1dIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dENoYW5uZWxzUGVyR3JvdXAgfSxcbiAgXTtcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YShhdHRyaWJ1dGVzLCBwcm9ncmFtVW5pZm9ybXMpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaChcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyh4U2hhcGUsIFt3U2hhcGVbMF0sIHdTaGFwZVsxXSwgd1NoYXBlWzJdLCB3U2hhcGVbM10gLyBjb21wb25lbnRzXSksXG4gICk7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gaGFzQmlhcyA/IFsncmFuaycsICdyYW5rJywgJ3JhbmsnXSA6IFsncmFuaycsICdyYW5rJ107XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKFtvdXRwdXRTaGFwZVswXSwgb3V0cHV0U2hhcGVbMV0sIG91dHB1dFNoYXBlWzJdLCBvdXRwdXRTaGFwZVszXSAvIGNvbXBvbmVudHNdKSxcbiAgKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGJhc2VUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKG91dHB1dC50eXBlLnRlbnNvcik7XG4gICAgY29uc3QgYXBwbHlBY3RpdmF0aW9uID0gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYXR0cmlidXRlcywgb3V0cHV0LnR5cGUudmFsdWUsIGJhc2VUeXBlKTtcbiAgICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0c1swXS5kYXRhVHlwZSwgeFNoYXBlLmxlbmd0aCk7XG4gICAgY29uc3QgdyA9IGlucHV0VmFyaWFibGUoJ3cnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIHdTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGlucHV0VmFycyA9IFt4LCB3XTtcbiAgICBpZiAoaGFzQmlhcykge1xuICAgICAgaW5wdXRWYXJzLnB1c2goaW5wdXRWYXJpYWJsZSgnYicsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMsIGNvbXBvbmVudHMpKTtcbiAgICB9XG5cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdkaWxhdGlvbnMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBhdHRyaWJ1dGVzLmRpbGF0aW9ucy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ3N0cmlkZXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiAyIH0sXG4gICAgICB7IG5hbWU6ICdwYWRzJywgdHlwZTogJ3UzMicsIGxlbmd0aDogMiB9LFxuICAgICAgeyBuYW1lOiAnb3V0cHV0X2NoYW5uZWxzX3Blcl9ncm91cCcsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMoYXR0cmlidXRlcywgdW5pZm9ybXMpO1xuXG4gICAgY29uc3QgY2FsY3VsYXRlUmVzdWx0ID0gaXNDaGFubmVsTGFzdFxuICAgICAgPyBgXG4gICAgICBmb3IgKHZhciB3SGVpZ2h0OiB1MzIgPSAwdTsgd0hlaWdodCA8IHVuaWZvcm1zLndfc2hhcGVbMF07IHdIZWlnaHQrKykge1xuICAgICAgICBsZXQgeEhlaWdodCA9IHhSQ0Nvcm5lci54ICsgd0hlaWdodCAqIHVuaWZvcm1zLmRpbGF0aW9uc1swXTtcblxuICAgICAgICBpZiAoeEhlaWdodCA8IDB1IHx8IHhIZWlnaHQgPj0gdW5pZm9ybXMueF9zaGFwZVsxXSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgd1dpZHRoOiB1MzIgPSAwdTsgd1dpZHRoIDwgdW5pZm9ybXMud19zaGFwZVsxXTsgd1dpZHRoKyspIHtcbiAgICAgICAgICBsZXQgeFdpZHRoID0geFJDQ29ybmVyLnkgKyB3V2lkdGggKiB1bmlmb3Jtcy5kaWxhdGlvbnNbMV07XG4gICAgICAgICAgaWYgKHhXaWR0aCA8IDB1IHx8IHhXaWR0aCA+PSB1bmlmb3Jtcy54X3NoYXBlWzJdKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmb3IgKHZhciB3SW5DaGFubmVsOiB1MzIgPSAwdTsgd0luQ2hhbm5lbCA8IHVuaWZvcm1zLndfc2hhcGVbMl07IHdJbkNoYW5uZWwrKykge1xuICAgICAgICAgICAgbGV0IGlucHV0X2NoYW5uZWwgPSBpbl9jaGFubmVsX29mZnNldCArIHdJbkNoYW5uZWw7XG4gICAgICAgICAgICBsZXQgeFZhbCA9ICR7eC5nZXQoJ2JhdGNoJywgJ3hIZWlnaHQnLCAneFdpZHRoJywgJ2lucHV0X2NoYW5uZWwnKX07XG4gICAgICAgICAgICBsZXQgd1ZhbCA9ICR7dy5nZXQoJ3dIZWlnaHQnLCAnd1dpZHRoJywgJ3dJbkNoYW5uZWwnLCAnb3V0cHV0X2NoYW5uZWwnKX07XG4gICAgICAgICAgICB2YWx1ZSArPSB4VmFsICogd1ZhbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGBcbiAgICAgIDogYFxuICAgICAgZm9yICh2YXIgd0luQ2hhbm5lbDogdTMyID0gMHU7IHdJbkNoYW5uZWwgPCB1bmlmb3Jtcy53X3NoYXBlWzFdOyB3SW5DaGFubmVsKyspIHtcbiAgICAgICAgbGV0IGlucHV0X2NoYW5uZWwgPSBpbl9jaGFubmVsX29mZnNldCArIHdJbkNoYW5uZWw7XG4gICAgICAgIGZvciAodmFyIHdIZWlnaHQ6IHUzMiA9IDB1OyB3SGVpZ2h0IDwgdW5pZm9ybXMud19zaGFwZVsyXTsgd0hlaWdodCsrKSB7XG4gICAgICAgICAgbGV0IHhIZWlnaHQgPSB4UkNDb3JuZXIueCArIHdIZWlnaHQgKiB1bmlmb3Jtcy5kaWxhdGlvbnNbMF07XG5cbiAgICAgICAgICBpZiAoeEhlaWdodCA8IDB1IHx8IHhIZWlnaHQgPj0gdW5pZm9ybXMueF9zaGFwZVsyXSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZm9yICh2YXIgd1dpZHRoOiB1MzIgPSAwdTsgd1dpZHRoIDwgdW5pZm9ybXMud19zaGFwZVszXTsgd1dpZHRoKyspIHtcbiAgICAgICAgICAgIGxldCB4V2lkdGggPSB4UkNDb3JuZXIueSArIHdXaWR0aCAqIHVuaWZvcm1zLmRpbGF0aW9uc1sxXTtcbiAgICAgICAgICAgIGlmICh4V2lkdGggPCAwdSB8fCB4V2lkdGggPj0gdW5pZm9ybXMueF9zaGFwZVszXSkge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHhWYWwgPSAke3guZ2V0KCdiYXRjaCcsICdpbnB1dF9jaGFubmVsJywgJ3hIZWlnaHQnLCAneFdpZHRoJyl9O1xuICAgICAgICAgICAgbGV0IHdWYWwgPSAke3cuZ2V0KCdvdXRwdXRfY2hhbm5lbCcsICd3SW5DaGFubmVsJywgJ3dIZWlnaHQnLCAnd1dpZHRoJyl9O1xuICAgICAgICAgICAgdmFsdWUgKz0geFZhbCAqIHdWYWw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJzLCBvdXRwdXQpfVxuXG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG5cbiAgICBsZXQgb3V0cHV0SW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICBsZXQgYmF0Y2g6IHUzMiA9IG91dHB1dEluZGljZXNbMF07XG4gICAgbGV0IG91dHB1dF9jaGFubmVsOiB1MzIgPSBvdXRwdXRJbmRpY2VzWyR7aXNDaGFubmVsTGFzdCA/IDMgOiAxfV07XG4gICAgbGV0IHhSQ0Nvcm5lcjogdmVjMjx1MzI+ID0gdmVjMjx1MzI+KG91dHB1dEluZGljZXNbJHtpc0NoYW5uZWxMYXN0ID8gMSA6IDJ9XSwgb3V0cHV0SW5kaWNlc1ske1xuICAgICAgaXNDaGFubmVsTGFzdCA/IDIgOiAzXG4gICAgfV0pICogdW5pZm9ybXMuc3RyaWRlcyAtIHVuaWZvcm1zLnBhZHM7XG4gICAgbGV0IGdyb3VwX2lkOiB1MzIgPSBvdXRwdXRfY2hhbm5lbCAqICR7Y29tcG9uZW50c30gLyB1bmlmb3Jtcy5vdXRwdXRfY2hhbm5lbHNfcGVyX2dyb3VwO1xuICAgIHZhciBpbl9jaGFubmVsX29mZnNldCA9IGdyb3VwX2lkICogdW5pZm9ybXMud19zaGFwZVske2lzQ2hhbm5lbExhc3QgPyAyIDogMX1dO1xuXG4gICAgdmFyIHZhbHVlOiAke291dHB1dC50eXBlLnZhbHVlfSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KDApO1xuICAgICR7Y2FsY3VsYXRlUmVzdWx0fVxuICAgICR7cHJvY2Vzc0JpYXN9XG4gICAgJHthcHBseUFjdGl2YXRpb259XG4gICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAndmFsdWUnKX1cbiAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0dyb3VwZWRDb252JyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fV8ke2NvbXBvbmVudHN9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW1xuICAgICAgICB7XG4gICAgICAgICAgZGltczogc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24gPyBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbihvdXRwdXRTaGFwZSkgOiBvdXRwdXRTaGFwZSxcbiAgICAgICAgICBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlR3JvdXBlZENvbnZWZWN0b3JpemVQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uPzogKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4gbnVtYmVyW10sXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID4gMjtcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMob3V0cHV0U2hhcGVbM10pO1xuICBjb25zdCBvdXRwdXROdW1iZXIgPSBnZXRNYXhDb21wb25lbnRzKG91dHB1dFNoYXBlWzJdKTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIGNvbXBvbmVudHMgLyBvdXRwdXROdW1iZXI7XG4gIGNvbnN0IHhTaGFwZSA9IFtpbnB1dHNbMF0uZGltc1swXSwgaW5wdXRzWzBdLmRpbXNbMV0sIGlucHV0c1swXS5kaW1zWzJdLCBpbnB1dHNbMF0uZGltc1szXSAvIGNvbXBvbmVudHNdO1xuICBjb25zdCB3U2hhcGUgPSBbaW5wdXRzWzFdLmRpbXNbMF0sIGlucHV0c1sxXS5kaW1zWzFdLCBpbnB1dHNbMV0uZGltc1syXSwgaW5wdXRzWzFdLmRpbXNbM10gLyBjb21wb25lbnRzXTtcbiAgY29uc3Qgb3V0cHV0U2hhcGVJblNoYWRlciA9IFtvdXRwdXRTaGFwZVswXSwgb3V0cHV0U2hhcGVbMV0sIG91dHB1dFNoYXBlWzJdLCBvdXRwdXRTaGFwZVszXSAvIGNvbXBvbmVudHNdO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IFthdHRyaWJ1dGVzLnN0cmlkZXNbMF0sIGF0dHJpYnV0ZXMuc3RyaWRlc1sxXV0gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBbYXR0cmlidXRlcy5wYWRzWzBdLCBhdHRyaWJ1dGVzLnBhZHNbMV1dIH0sXG4gIF07XG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEoYXR0cmlidXRlcywgcHJvZ3JhbVVuaWZvcm1zKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoeFNoYXBlLCB3U2hhcGUsIG91dHB1dFNoYXBlSW5TaGFkZXIpKTtcbiAgY29uc3QgeE51bWJlciA9IChvdXRwdXROdW1iZXIgLSAxKSAqIGF0dHJpYnV0ZXMuc3RyaWRlc1sxXSArIHdTaGFwZVsxXTtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGVJblNoYWRlci5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGJhc2VUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKG91dHB1dC50eXBlLnRlbnNvcik7XG4gICAgY29uc3QgYXBwbHlBY3RpdmF0aW9uID0gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYXR0cmlidXRlcywgb3V0cHV0LnR5cGUudmFsdWUsIGJhc2VUeXBlKTtcbiAgICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0c1swXS5kYXRhVHlwZSwgeFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgdyA9IGlucHV0VmFyaWFibGUoJ3cnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIHdTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGlucHV0VmFycyA9IFt4LCB3XTtcbiAgICBpZiAoaGFzQmlhcykge1xuICAgICAgaW5wdXRWYXJzLnB1c2goaW5wdXRWYXJpYWJsZSgnYicsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMsIGNvbXBvbmVudHMpKTtcbiAgICB9XG4gICAgY29uc3QgcHJvY2Vzc0JpYXMgPSBoYXNCaWFzID8gJ3ZhbHVlICs9IGJbb3V0cHV0X2NoYW5uZWxdOycgOiAnJztcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdzdHJpZGVzJywgdHlwZTogJ2kzMicsIGxlbmd0aDogMiB9LFxuICAgICAgeyBuYW1lOiAncGFkcycsIHR5cGU6ICdpMzInLCBsZW5ndGg6IDIgfSxcbiAgICBdO1xuICAgIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcyhhdHRyaWJ1dGVzLCB1bmlmb3Jtcyk7XG4gICAgcmV0dXJuIGBcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcnMsIG91dHB1dCl9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgbGV0IHdpZHRoMCA9IHVuaWZvcm1zLm91dHB1dF9zaGFwZVszXTtcbiAgICBsZXQgb3V0cHV0X2NoYW5uZWwgPSBnbG9iYWxfaWR4ICUgd2lkdGgwO1xuICAgIHZhciBpbmRleDEgPSBnbG9iYWxfaWR4IC8gd2lkdGgwO1xuICAgIGxldCB3aWR0aDEgPSB1bmlmb3Jtcy5vdXRwdXRfc2hhcGVbMl0gLyAke291dHB1dE51bWJlcn11O1xuICAgIGxldCBjb2wgPSAoaW5kZXgxICUgd2lkdGgxKSAqICR7b3V0cHV0TnVtYmVyfXU7XG4gICAgaW5kZXgxID0gaW5kZXgxIC8gd2lkdGgxO1xuICAgIGxldCByb3cgPSBpbmRleDEgJSB1bmlmb3Jtcy5vdXRwdXRfc2hhcGVbMV07XG4gICAgbGV0IGJhdGNoID0gaW5kZXgxIC8gdW5pZm9ybXMub3V0cHV0X3NoYXBlWzFdO1xuXG4gICAgbGV0IHhfY29ybmVyID0gdmVjMjxpMzI+KGkzMihyb3cpLCBpMzIoY29sKSkgKiB1bmlmb3Jtcy5zdHJpZGVzIC0gdW5pZm9ybXMucGFkcztcblxuICAgIHZhciB4X3ZhbHM6IGFycmF5PCR7eC50eXBlLnZhbHVlfSwgJHt4TnVtYmVyfT47XG4gICAgdmFyIHZhbHVlczogYXJyYXk8JHtvdXRwdXQudHlwZS52YWx1ZX0sICR7b3V0cHV0TnVtYmVyfT47XG4gICAgbGV0IGlucHV0X2NoYW5uZWwgPSBvdXRwdXRfY2hhbm5lbDtcbiAgICAvLyBVc2UgY29uc3RhbnQgaW5zdGVhZCBvZiB1bmlmb3JtIGNhbiBnaXZlIGJldHRlciBwZXJmb3JtYW5jZSBmb3IgdydzIGhlaWdodC93aWR0aC5cbiAgICBmb3IgKHZhciB3X2hlaWdodDogdTMyID0gMHU7IHdfaGVpZ2h0IDwgJHt3U2hhcGVbMF19OyB3X2hlaWdodCsrKSB7XG4gICAgICBsZXQgeF9oZWlnaHQgPSB4X2Nvcm5lci54ICsgaTMyKHdfaGVpZ2h0KTtcbiAgICAgIGlmICh4X2hlaWdodCA+PSAwICYmIHUzMih4X2hlaWdodCkgPCB1bmlmb3Jtcy54X3NoYXBlWzFdKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgJHt4TnVtYmVyfTsgaSsrKSB7XG4gICAgICAgICAgbGV0IHhfd2lkdGggPSB4X2Nvcm5lci55ICsgaTtcbiAgICAgICAgICBpZiAoeF93aWR0aCA+PSAwICYmIHUzMih4X3dpZHRoKSA8IHVuaWZvcm1zLnhfc2hhcGVbMl0pIHtcbiAgICAgICAgICAgIHhfdmFsc1tpXSA9ICR7eC5nZXQoJ2JhdGNoJywgJ3UzMih4X2hlaWdodCknLCAndTMyKHhfd2lkdGgpJywgJ2lucHV0X2NoYW5uZWwnKX07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHhfdmFsc1tpXSA9ICR7eC50eXBlLnZhbHVlfSgwKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgd193aWR0aDogdTMyID0gMHU7IHdfd2lkdGggPCAke3dTaGFwZVsxXX07IHdfd2lkdGgrKykge1xuICAgICAgICAgIGxldCB3X3ZhbCA9ICR7dy5nZXQoJ3dfaGVpZ2h0JywgJ3dfd2lkdGgnLCAnMCcsICdvdXRwdXRfY2hhbm5lbCcpfTtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMHU7IGkgPCAke291dHB1dE51bWJlcn11OyBpKyspIHtcbiAgICAgICAgICAgIHZhbHVlc1tpXSA9IGZtYSh4X3ZhbHNbaSAqIHUzMih1bmlmb3Jtcy5zdHJpZGVzWzFdKSArIHdfd2lkdGhdLCB3X3ZhbCwgdmFsdWVzW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMHU7IGkgPCAke291dHB1dE51bWJlcn11OyBpKyspIHtcbiAgICAgIHZhciB2YWx1ZSA9IHZhbHVlc1tpXTtcbiAgICAgICR7cHJvY2Vzc0JpYXN9XG4gICAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAgICR7b3V0cHV0LnNldCgnYmF0Y2gnLCAncm93JywgJ2NvbCArIGknLCAnb3V0cHV0X2NoYW5uZWwnLCAndmFsdWUnKX07XG4gICAgfVxuICB9YDtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdHcm91cGVkQ29udi1WZWN0b3JpemUnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fTske2NvbXBvbmVudHN9OyR7b3V0cHV0TnVtYmVyfTske3hOdW1iZXJ9OyR7d1NoYXBlWzBdfTske3dTaGFwZVsxXX1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IGhhc0JpYXMgPyBbJ3JhbmsnLCAncmFuaycsICd0eXBlJ10gOiBbJ3JhbmsnLCAncmFuayddLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGRpbXM6IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uID8gc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24ob3V0cHV0U2hhcGUpIDogb3V0cHV0U2hhcGUsXG4gICAgICAgICAgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFBvb2xDb252VXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0IH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVDb252MkRNYXRNdWxQcm9ncmFtSW5mbyB9IGZyb20gJy4vM3JkLXBhcnR5L2NvbnYyZF9tbV93ZWJncHUnO1xuaW1wb3J0IHsgY29tcHV0ZUNvbnYzREluZm8sIGNyZWF0ZUNvbnYzRE5haXZlUHJvZ3JhbUluZm8gfSBmcm9tICcuLzNyZC1wYXJ0eS9jb252M2RfbmFpdmVfd2ViZ3B1JztcbmltcG9ydCB7IGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvIH0gZnJvbSAnLi8zcmQtcGFydHkvbWF0bXVsX3BhY2tlZF93ZWJncHUnO1xuaW1wb3J0IHsgY3JlYXRlR3JvdXBlZENvbnZQcm9ncmFtSW5mbywgY3JlYXRlR3JvdXBlZENvbnZWZWN0b3JpemVQcm9ncmFtSW5mbyB9IGZyb20gJy4vY29udi1ncm91cGVkJztcbmltcG9ydCB7IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsIHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyB9IGZyb20gJy4vZnVzZS11dGlscyc7XG5pbXBvcnQgeyBjcmVhdGVOYWl2ZU1hdG11bFByb2dyYW1JbmZvIH0gZnJvbSAnLi9tYXRtdWwtc2hhZGVycyc7XG5pbXBvcnQgeyBjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyB9IGZyb20gJy4vdHJhbnNwb3NlJztcblxuZXhwb3J0IGNvbnN0IGNhbGN1bGF0ZU91dHB1dFNoYXBlID0gKFxuICBpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBkaWxhdGlvbnM6IHJlYWRvbmx5IG51bWJlcltdLFxuICBhZGp1c3RQYWRzOiByZWFkb25seSBudW1iZXJbXSxcbiAgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGlzQ2hhbm5lbExhc3Q6IGJvb2xlYW4sXG4pOiBudW1iZXJbXSA9PiB7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IGlucHV0U2hhcGVbMF07XG4gIGNvbnN0IGlucHV0U3BhdGlhbFNoYXBlID0gaW5wdXRTaGFwZS5zbGljZShpc0NoYW5uZWxMYXN0ID8gMSA6IDIsIGlzQ2hhbm5lbExhc3QgPyAzIDogNCk7XG4gIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRTcGF0aWFsU2hhcGUubGVuZ3RoO1xuICBjb25zdCBvdXRDaGFubmVscyA9IGtlcm5lbFNoYXBlWzBdO1xuICBjb25zdCBrZXJuZWxTcGF0aWFsU2hhcGUgPSBrZXJuZWxTaGFwZS5zbGljZSgyKTtcbiAgY29uc3QgZGlsYXRlZEtlcm5lbFNoYXBlID0ga2VybmVsU3BhdGlhbFNoYXBlLm1hcCgodiwgaSkgPT4gdiArICh2IC0gMSkgKiAoZGlsYXRpb25zW2ldIC0gMSkpO1xuICBjb25zdCBpbnB1dFNwYXRpYWxTaGFwZVdpdGhQYWQgPSBpbnB1dFNwYXRpYWxTaGFwZS5tYXAoKHYsIGkpID0+IHYgKyBhZGp1c3RQYWRzW2ldICsgYWRqdXN0UGFkc1tpICsgc3BhdGlhbFJhbmtdKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dFNwYXRpYWxTaGFwZVdpdGhQYWQubWFwKCh2LCBpKSA9PlxuICAgIE1hdGguZmxvb3IoKHYgLSBkaWxhdGVkS2VybmVsU2hhcGVbaV0gKyBzdHJpZGVzW2ldKSAvIHN0cmlkZXNbaV0pLFxuICApO1xuICBvdXRwdXRTaGFwZS5zcGxpY2UoMCwgMCwgYmF0Y2hTaXplKTtcbiAgb3V0cHV0U2hhcGUuc3BsaWNlKGlzQ2hhbm5lbExhc3QgPyAzIDogMSwgMCwgb3V0Q2hhbm5lbHMpO1xuICByZXR1cm4gb3V0cHV0U2hhcGU7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbnZBdHRyaWJ1dGVzIGV4dGVuZHMgSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcywgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXV0b1BhZDogc3RyaW5nO1xuICByZWFkb25seSBkaWxhdGlvbnM6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBmb3JtYXQ6ICdOSFdDJyB8ICdOQ0hXJztcbiAgcmVhZG9ubHkgZ3JvdXA6IG51bWJlcjtcbiAgcmVhZG9ubHkga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBwYWRzOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IHdJc0NvbnN0OiBib29sZWFuO1xufVxuXG4vLyBmb3IgdHJhbnNwb3Npbmcgd2VpZ2h0IHRlbnNvciBmcm9tIFtNLCBDL2dyb3VwLCBLSCwgS1ddIHRvIFtLSCwgS1csIEMvZ3JvdXAsIE1dXG5jb25zdCB3ZWlnaHRUcmFuc3Bvc2VBdHRyaWJ1dGUgPSBbMiwgMywgMSwgMF07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICAvLyBSZWZlciB0byB0aGUgYmVsb3cgbGluayBmb3IgYWxsIGlucHV0IGNoZWNrc1xuICAvLyBodHRwczovL2dpdGh1Yi5jb20vb25ueC9vbm54L2Jsb2IvbWFzdGVyL2RvY3MvT3BlcmF0b3JzLm1kI0NvbnZcbiAgaWYgKCFpbnB1dHMgfHwgKGlucHV0cy5sZW5ndGggIT09IDIgJiYgaW5wdXRzLmxlbmd0aCAhPT0gMykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnYgcmVxdWlyZXMgMiBvciAzIGlucHV0cycpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCA+IDUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dyZWF0ZXIgdGhhbiA1RCBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSBpbnB1dHNbMV0uZGltcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ZpbHRlciBkb2VzIG5vdCBoYXZlIHNhbWUgZGltZW5zaW9uIGFzIGlucHV0Jyk7XG4gIH1cblxuICAvLyBGSUxURVJfSU5fQ0hBTk5FTCBzaG91bGQgYmUgZXF1YWwgdG8gREFUQV9DSEFOTkVMXG4gIGNvbnN0IGRhdGFDaGFubmVsID0gaW5wdXRzWzBdLmRpbXNbYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJyA/IGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDEgOiAxXTtcbiAgY29uc3QgZmlsdGVySW5DaGFubmVsID0gaW5wdXRzWzFdLmRpbXNbMV0gKiBhdHRyaWJ1dGVzLmdyb3VwO1xuICBpZiAoZGF0YUNoYW5uZWwgIT09IGZpbHRlckluQ2hhbm5lbCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRklMVEVSX0lOX0NIQU5ORUwgc2hvdWxkIGJlIGVxdWFsIHRvIERBVEFfQ0hBTk5FTCcpO1xuICB9XG5cbiAgLy8gaWYgYmlhcyBpcyBwcm92aWRlZCBpdCBzaG91bGQgYmUgMUQgYW5kIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgc2hvdWxkIGJlIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgZmVhdHVyZSBtYXBzXG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAzICYmIChpbnB1dHNbMl0uZGltcy5sZW5ndGggIT09IDEgfHwgaW5wdXRzWzFdLmRpbXNbMF0gIT09IGlucHV0c1syXS5kaW1zWzBdKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBiaWFzJyk7XG4gIH1cblxuICBjb25zdCBzcGF0aWFsUmFuayA9IGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDI7XG4gIC8vIHdyb25nIGRpbGF0aW9ucyBkaW1lbnNpb25cbiAgaWYgKGF0dHJpYnV0ZXMuZGlsYXRpb25zLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmspIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYGRpbGF0aW9ucyBzaG91bGQgYmUgJHtzcGF0aWFsUmFua31EYCk7XG4gIH1cblxuICAvLyBXcm9uZyBzdHJpZGVzIGRpbWVuc2lvblxuICBpZiAoYXR0cmlidXRlcy5zdHJpZGVzLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmspIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHN0cmlkZXMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmt9RGApO1xuICB9XG5cbiAgLy8gV3JvbmcgcGFkcyBkaW1lbnNpb25cbiAgaWYgKGF0dHJpYnV0ZXMucGFkcy5sZW5ndGggIT09IHNwYXRpYWxSYW5rICogMikge1xuICAgIHRocm93IG5ldyBFcnJvcihgcGFkcyBzaG91bGQgYmUgJHtzcGF0aWFsUmFuayAqIDJ9RGApO1xuICB9XG5cbiAgLy8gaWYga2VybmVsU2hhcGUgaXMgc3BlY2lmaWVkLCBpdCdzIGRhdGEgbGVuZ3RoIG11c3QgYmUgMiBsZXNzIHRoYW4gZGltcyBsZW5ndGggb2YgdGhlIHdlaWdodHMgdGVuc29yXG4gIC8vICh0aGUgZmlyc3QgMiBkaW1zIGFyZSBiYXRjaF9zaXplIGFuZCBjaGFubmVscylcbiAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoICE9PSAwICYmIGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoICE9PSBpbnB1dHNbMV0uZGltcy5sZW5ndGggLSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGtlcm5lbCBzaGFwZScpO1xuICB9XG59O1xuXG5jb25zdCBnZXRBZGp1c3RlZENvbnZBdHRyaWJ1dGVzID0gPFQgZXh0ZW5kcyBDb252QXR0cmlidXRlcz4oYXR0cmlidXRlczogVCwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiBUID0+IHtcbiAgY29uc3Qga2VybmVsU2hhcGUgPSBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLnNsaWNlKCk7XG4gIC8vIGlmIGtlcm5lbFNoYXBlIGlzIG5vdCB3ZWxsIHNwZWNpZmllZCBpbiB0aGUgYXR0cmlidXRlcywgaW5mZXIgaXQgZnJvbSB0aGUgd2VpZ2h0IHRlbnNvciBkaW1zXG4gIGlmIChrZXJuZWxTaGFwZS5sZW5ndGggPCBpbnB1dHNbMV0uZGltcy5sZW5ndGggLSAyKSB7XG4gICAga2VybmVsU2hhcGUucHVzaCguLi5BcnJheShpbnB1dHNbMV0uZGltcy5sZW5ndGggLSAyIC0ga2VybmVsU2hhcGUubGVuZ3RoKS5maWxsKDApKTtcbiAgfVxuICBmb3IgKGxldCBpID0gMjsgaSA8IGlucHV0c1sxXS5kaW1zLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGtlcm5lbFNoYXBlW2kgLSAyXSA9PT0gMCkge1xuICAgICAga2VybmVsU2hhcGVbaSAtIDJdID0gaW5wdXRzWzFdLmRpbXNbaV07XG4gICAgfVxuICB9XG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHMuc2xpY2UoKTtcbiAgUG9vbENvbnZVdGlsLmFkanVzdFBhZHNCYXNlZE9uQXV0b1BhZChcbiAgICBpbnB1dHNbMF0uZGltcyxcbiAgICBhdHRyaWJ1dGVzLnN0cmlkZXMsXG4gICAgYXR0cmlidXRlcy5kaWxhdGlvbnMsXG4gICAga2VybmVsU2hhcGUsXG4gICAgcGFkcyxcbiAgICBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnLFxuICAgIGF0dHJpYnV0ZXMuYXV0b1BhZCxcbiAgKTtcblxuICAvLyBhbHdheXMgcmV0dXJuIGEgbmV3IG9iamVjdCBzbyBkb2VzIG5vdCBtb2RpZnkgdGhlIG9yaWdpbmFsIGF0dHJpYnV0ZXNcbiAgY29uc3QgbmV3QXR0cmlidXRlczogVCA9IE9iamVjdC5hc3NpZ24oe30sIGF0dHJpYnV0ZXMpO1xuICBPYmplY3QuYXNzaWduKG5ld0F0dHJpYnV0ZXMsIHsga2VybmVsU2hhcGUsIHBhZHMgfSk7XG4gIHJldHVybiBuZXdBdHRyaWJ1dGVzO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQ29udkF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBDb252QXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGFjdGl2YXRpb25BdHRyaWJ1dGVzID0gcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpO1xuICAvLyBUT0RPIDogTWFrZSB0aGlzIGdlbmVyaWMgZW5vdWdoIHRvIGNvbXB1dGUgZGVmYXVsdCBhdHRyaWJ1dGVzIGZvciBtdWx0aS1kaW1lbnNpb25hbCBjb252XG4gIGNvbnN0IGZvcm1hdCA9IGF0dHJpYnV0ZXMuZm9ybWF0IGFzICdOSFdDJyB8ICdOQ0hXJztcbiAgY29uc3QgYXV0b1BhZCA9IFsnTk9UU0VUJywgJ1ZBTElEJywgJ1NBTUVfVVBQRVInLCAnU0FNRV9MT1dFUiddW2F0dHJpYnV0ZXMuYXV0b19wYWQgYXMgbnVtYmVyXTtcbiAgY29uc3QgZGlsYXRpb25zID0gYXR0cmlidXRlcy5kaWxhdGlvbnMgYXMgbnVtYmVyW107XG4gIGNvbnN0IGdyb3VwID0gYXR0cmlidXRlcy5ncm91cCBhcyBudW1iZXI7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxfc2hhcGUgYXMgbnVtYmVyW107XG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHMgYXMgbnVtYmVyW107XG4gIGNvbnN0IHN0cmlkZXMgPSBhdHRyaWJ1dGVzLnN0cmlkZXMgYXMgbnVtYmVyW107XG4gIGNvbnN0IHdJc0NvbnN0ID0gKGF0dHJpYnV0ZXMud19pc19jb25zdCBhcyAoKSA9PiBib29sZWFuKSgpO1xuXG4gIHJldHVybiB7XG4gICAgYXV0b1BhZCxcbiAgICBmb3JtYXQsXG4gICAgZGlsYXRpb25zLFxuICAgIGdyb3VwLFxuICAgIGtlcm5lbFNoYXBlLFxuICAgIHBhZHMsXG4gICAgc3RyaWRlcyxcbiAgICB3SXNDb25zdCxcbiAgICAuLi5hY3RpdmF0aW9uQXR0cmlidXRlcyxcbiAgICBjYWNoZUtleTogYCR7YXR0cmlidXRlcy5mb3JtYXR9OyR7YWN0aXZhdGlvbkF0dHJpYnV0ZXMuYWN0aXZhdGlvbn07YCxcbiAgfTtcbn07XG5cbmNvbnN0IGNvbnYyZCA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyxcbiAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSxcbik6IHZvaWQgPT4ge1xuICAvLyBjaGVjayBhdHRyaWJ1dGVzXG5cbiAgLy8gY29uc3QgaGFzUHJlbHVBY3RpdmF0aW9uV2VpZ2h0cyA9IGZhbHNlOyAvKiBUT0RPOiBhZGQgc3VwcG9ydCBmb3IgcHJlbHUgYWN0aXZhdGlvbiB3ZWlnaHRzICovXG4gIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBjYWxjdWxhdGVPdXRwdXRTaGFwZShcbiAgICBpbnB1dHNbMF0uZGltcyxcbiAgICBpbnB1dHNbMV0uZGltcyxcbiAgICBhdHRyaWJ1dGVzLmRpbGF0aW9ucyxcbiAgICBhdHRyaWJ1dGVzLnBhZHMsXG4gICAgYXR0cmlidXRlcy5zdHJpZGVzLFxuICAgIGlzQ2hhbm5lbHNMYXN0LFxuICApO1xuICBpZiAoYXR0cmlidXRlcy5ncm91cCAhPT0gMSkge1xuICAgIGNvbnN0IGNvbnZJbnB1dHMgPSBbaW5wdXRzWzBdXTtcbiAgICBpZiAoaXNDaGFubmVsc0xhc3QpIHtcbiAgICAgIGNvbnN0IHRyYW5zcG9zZWRXZWlnaHQgPVxuICAgICAgICAoY29udGV4dC5rZXJuZWxDdXN0b21EYXRhLndUIGFzIFRlbnNvclZpZXcgfCB1bmRlZmluZWQpID8/XG4gICAgICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhpbnB1dHNbMV0sIHdlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZSksIHtcbiAgICAgICAgICBpbnB1dHM6IFsxXSxcbiAgICAgICAgICBvdXRwdXRzOiBbYXR0cmlidXRlcy53SXNDb25zdCA/IC0yIDogLTFdLFxuICAgICAgICB9KVswXTtcbiAgICAgIGlmIChhdHRyaWJ1dGVzLndJc0NvbnN0ICYmICFjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QpIHtcbiAgICAgICAgY29udGV4dC5rZXJuZWxDdXN0b21EYXRhLndUID0gdHJhbnNwb3NlZFdlaWdodDtcbiAgICAgIH1cbiAgICAgIGNvbnZJbnB1dHMucHVzaCh0cmFuc3Bvc2VkV2VpZ2h0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udklucHV0cy5wdXNoKGlucHV0c1sxXSk7XG4gICAgfVxuICAgIGlmIChpbnB1dHMubGVuZ3RoID09PSAzKSB7XG4gICAgICBjb252SW5wdXRzLnB1c2goaW5wdXRzWzJdKTtcbiAgICB9XG4gICAgLy8gTlZJRElBIEdQVSB3aXRoIGFtcGVyZSBhcmNoaXRlY3R1cmUgZmFpbHMgd2l0aCBiZWxvdyAyIGNhc2VzLCBidXQgd2UgY291bGRuJ3QgcmVwcm8gdGhlbSB3aXRoIGFueSBvdGhlclxuICAgIC8vIEdQVXMuIFNvIGp1c3QgZGlzYWJsZSB2ZWN0b3JpemUgb24gTlZJRElBIGFtcGVyZSB0byBlbnN1cmUgYWx3YXlzIGNvcnJlY3Qgb3V0cHV0cy5cbiAgICAvLyBbd2ViZ3B1XUNvbnYgLSBjb252IC0gdmVjdG9yaXplIGdyb3VwIC0gQlxuICAgIC8vIFt3ZWJncHVdQ29udiAtIGNvbnYgLSB2ZWN0b3JpemUgZ3JvdXAgLSBEXG4gICAgY29uc3QgZW5hYmxlR3JvdXBlZENvbnZWZWN0b3JpemUgPSAhY29udGV4dC5hZGFwdGVySW5mby5pc0FyY2hpdGVjdHVyZSgnYW1wZXJlJyk7XG4gICAgaWYgKFxuICAgICAgZW5hYmxlR3JvdXBlZENvbnZWZWN0b3JpemUgJiZcbiAgICAgIGlzQ2hhbm5lbHNMYXN0ICYmXG4gICAgICBpbnB1dHNbMV0uZGltc1swXSA9PT0gYXR0cmlidXRlcy5ncm91cCAmJlxuICAgICAgaW5wdXRzWzFdLmRpbXNbMV0gPT09IDEgJiZcbiAgICAgIGF0dHJpYnV0ZXMuZGlsYXRpb25zWzBdID09PSAxICYmXG4gICAgICBhdHRyaWJ1dGVzLmRpbGF0aW9uc1sxXSA9PT0gMVxuICAgICkge1xuICAgICAgY29udGV4dC5jb21wdXRlKFxuICAgICAgICBjcmVhdGVHcm91cGVkQ29udlZlY3Rvcml6ZVByb2dyYW1JbmZvKGNvbnZJbnB1dHMsIGF0dHJpYnV0ZXMsIG91dHB1dFNoYXBlLCBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiksXG4gICAgICAgIHsgaW5wdXRzOiBjb252SW5wdXRzIH0sXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlR3JvdXBlZENvbnZQcm9ncmFtSW5mbyhjb252SW5wdXRzLCBhdHRyaWJ1dGVzLCBvdXRwdXRTaGFwZSwgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24pLCB7XG4gICAgICAgIGlucHV0czogY29udklucHV0cyxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA9PT0gMztcbiAgY29uc3QgaW5wdXRIZWlnaHQgPSBpbnB1dHNbMF0uZGltc1tpc0NoYW5uZWxzTGFzdCA/IDEgOiAyXTtcbiAgY29uc3QgaW5wdXRXaWR0aCA9IGlucHV0c1swXS5kaW1zW2lzQ2hhbm5lbHNMYXN0ID8gMiA6IDNdO1xuICBjb25zdCBpbnB1dENoYW5uZWxzID0gaW5wdXRzWzBdLmRpbXNbaXNDaGFubmVsc0xhc3QgPyAzIDogMV07XG4gIGNvbnN0IHdlaWdodEhlaWdodCA9IGlucHV0c1sxXS5kaW1zWzJdO1xuICBjb25zdCB3ZWlnaHRXaWR0aCA9IGlucHV0c1sxXS5kaW1zWzNdO1xuXG4gIGNvbnN0IG91dEhlaWdodCA9IG91dHB1dFNoYXBlW2lzQ2hhbm5lbHNMYXN0ID8gMSA6IDJdO1xuICBjb25zdCBvdXRXaWR0aCA9IG91dHB1dFNoYXBlW2lzQ2hhbm5lbHNMYXN0ID8gMiA6IDNdO1xuICBjb25zdCBvdXRDaGFubmVscyA9IG91dHB1dFNoYXBlW2lzQ2hhbm5lbHNMYXN0ID8gMyA6IDFdO1xuXG4gIGNvbnN0IHNhbWVTaXplID1cbiAgICBpc0NoYW5uZWxzTGFzdCAmJlxuICAgIHdlaWdodEhlaWdodCA9PT0gaW5wdXRIZWlnaHQgJiZcbiAgICB3ZWlnaHRXaWR0aCA9PT0gaW5wdXRXaWR0aCAmJlxuICAgIGF0dHJpYnV0ZXMucGFkc1swXSA9PT0gMCAmJlxuICAgIGF0dHJpYnV0ZXMucGFkc1sxXSA9PT0gMDtcbiAgaWYgKFxuICAgIHNhbWVTaXplIHx8XG4gICAgKHdlaWdodEhlaWdodCA9PT0gMSAmJlxuICAgICAgd2VpZ2h0V2lkdGggPT09IDEgJiZcbiAgICAgIGF0dHJpYnV0ZXMuZGlsYXRpb25zWzBdID09PSAxICYmXG4gICAgICBhdHRyaWJ1dGVzLmRpbGF0aW9uc1sxXSA9PT0gMSAmJlxuICAgICAgYXR0cmlidXRlcy5zdHJpZGVzWzBdID09PSAxICYmXG4gICAgICBhdHRyaWJ1dGVzLnN0cmlkZXNbMV0gPT09IDEgJiZcbiAgICAgIGF0dHJpYnV0ZXMucGFkc1swXSA9PT0gMCAmJlxuICAgICAgYXR0cmlidXRlcy5wYWRzWzFdID09PSAwKVxuICApIHtcbiAgICAvLyBjb252MmRCeU1hdE11bFxuICAgIGNvbnN0IGJhdGNoID0gb3V0cHV0U2hhcGVbMF07XG4gICAgbGV0IHhSZXNoYXBlZCwgd1Jlc2hhcGVkLCBtYXRtdWxPdXRwdXRTaGFwZTtcbiAgICBjb25zdCBtYXRtdWxJbnB1dHMgPSBbXTtcbiAgICBpZiAoaXNDaGFubmVsc0xhc3QpIHtcbiAgICAgIGNvbnN0IHRyYW5zcG9zZWRXZWlnaHQgPVxuICAgICAgICAoY29udGV4dC5rZXJuZWxDdXN0b21EYXRhLndUIGFzIFRlbnNvclZpZXcgfCB1bmRlZmluZWQpID8/XG4gICAgICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhpbnB1dHNbMV0sIHdlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZSksIHtcbiAgICAgICAgICBpbnB1dHM6IFsxXSxcbiAgICAgICAgICBvdXRwdXRzOiBbYXR0cmlidXRlcy53SXNDb25zdCA/IC0yIDogLTFdLFxuICAgICAgICB9KVswXTtcbiAgICAgIGlmIChhdHRyaWJ1dGVzLndJc0NvbnN0ICYmICFjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QpIHtcbiAgICAgICAgY29udGV4dC5rZXJuZWxDdXN0b21EYXRhLndUID0gdHJhbnNwb3NlZFdlaWdodDtcbiAgICAgIH1cbiAgICAgIGlmIChzYW1lU2l6ZSkge1xuICAgICAgICBjb25zdCBzaGFyZWREaW0gPSBpbnB1dEhlaWdodCAqIGlucHV0V2lkdGggKiBpbnB1dENoYW5uZWxzO1xuICAgICAgICB4UmVzaGFwZWQgPSBpbnB1dHNbMF0ucmVzaGFwZShbMSwgYmF0Y2gsIHNoYXJlZERpbV0pO1xuICAgICAgICB3UmVzaGFwZWQgPSB0cmFuc3Bvc2VkV2VpZ2h0LnJlc2hhcGUoWzEsIHNoYXJlZERpbSwgb3V0Q2hhbm5lbHNdKTtcbiAgICAgICAgbWF0bXVsT3V0cHV0U2hhcGUgPSBbMSwgYmF0Y2gsIG91dENoYW5uZWxzXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHhSZXNoYXBlZCA9IGlucHV0c1swXS5yZXNoYXBlKFtiYXRjaCwgaW5wdXRIZWlnaHQgKiBpbnB1dFdpZHRoLCBpbnB1dENoYW5uZWxzXSk7XG4gICAgICAgIHdSZXNoYXBlZCA9IHRyYW5zcG9zZWRXZWlnaHQucmVzaGFwZShbMSwgaW5wdXRDaGFubmVscywgb3V0Q2hhbm5lbHNdKTtcbiAgICAgICAgbWF0bXVsT3V0cHV0U2hhcGUgPSBbYmF0Y2gsIG91dEhlaWdodCAqIG91dFdpZHRoLCBvdXRDaGFubmVsc107XG4gICAgICB9XG4gICAgICBtYXRtdWxJbnB1dHMucHVzaCh4UmVzaGFwZWQpO1xuICAgICAgbWF0bXVsSW5wdXRzLnB1c2god1Jlc2hhcGVkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgeFJlc2hhcGVkID0gaW5wdXRzWzBdLnJlc2hhcGUoW2JhdGNoLCBpbnB1dENoYW5uZWxzLCBpbnB1dEhlaWdodCAqIGlucHV0V2lkdGhdKTtcbiAgICAgIHdSZXNoYXBlZCA9IGlucHV0c1sxXS5yZXNoYXBlKFsxLCBvdXRDaGFubmVscywgaW5wdXRDaGFubmVsc10pO1xuICAgICAgbWF0bXVsT3V0cHV0U2hhcGUgPSBbYmF0Y2gsIG91dENoYW5uZWxzLCBvdXRIZWlnaHQgKiBvdXRXaWR0aF07XG4gICAgICBtYXRtdWxJbnB1dHMucHVzaCh3UmVzaGFwZWQpO1xuICAgICAgbWF0bXVsSW5wdXRzLnB1c2goeFJlc2hhcGVkKTtcbiAgICB9XG4gICAgaWYgKGhhc0JpYXMpIHtcbiAgICAgIG1hdG11bElucHV0cy5wdXNoKGlucHV0c1syXSk7XG4gICAgfVxuICAgIGNvbnN0IE4gPSBtYXRtdWxPdXRwdXRTaGFwZVsyXTtcbiAgICBjb25zdCBLID0gbWF0bXVsSW5wdXRzWzBdLmRpbXNbbWF0bXVsSW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMV07XG4gICAgLy8gVHVuZSB0aGUgdGhyZXNob2xkLlxuICAgIGlmIChOIDwgOCAmJiBLIDwgOCkge1xuICAgICAgY29udGV4dC5jb21wdXRlKFxuICAgICAgICBjcmVhdGVOYWl2ZU1hdG11bFByb2dyYW1JbmZvKFxuICAgICAgICAgIG1hdG11bElucHV0cyxcbiAgICAgICAgICBhdHRyaWJ1dGVzLFxuICAgICAgICAgIG91dHB1dFNoYXBlLFxuICAgICAgICAgIG1hdG11bE91dHB1dFNoYXBlLFxuICAgICAgICAgIGlzQ2hhbm5lbHNMYXN0LFxuICAgICAgICAgIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uLFxuICAgICAgICApLFxuICAgICAgICB7IGlucHV0czogbWF0bXVsSW5wdXRzIH0sXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0LmNvbXB1dGUoXG4gICAgICAgIGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvKFxuICAgICAgICAgIG1hdG11bElucHV0cyxcbiAgICAgICAgICBhdHRyaWJ1dGVzLFxuICAgICAgICAgIG91dHB1dFNoYXBlLFxuICAgICAgICAgIG1hdG11bE91dHB1dFNoYXBlLFxuICAgICAgICAgIGlzQ2hhbm5lbHNMYXN0LFxuICAgICAgICAgIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uLFxuICAgICAgICApLFxuICAgICAgICB7IGlucHV0czogbWF0bXVsSW5wdXRzIH0sXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBUT0RPOiBpbXBsZW1lbnQgY29udjJkV2l0aEltMkNvbCgpXG5cbiAgY29uc3Qgc2VxdWVudGlhbEFjY2Vzc0J5VGhyZWFkcyA9IC8qIGJhY2tlbmQuYWRhcHRlckluZm8uaXNJbnRlbCgpICovIHRydWU7XG5cbiAgLy8gU1RFUC4xOiB0cmFuc3Bvc2Ugd2VpZ2h0XG4gIGNvbnN0IHRyYW5zcG9zZWRXZWlnaHQgPVxuICAgIChjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QgYXMgVGVuc29yVmlldyB8IHVuZGVmaW5lZCkgPz9cbiAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8oaW5wdXRzWzFdLCB3ZWlnaHRUcmFuc3Bvc2VBdHRyaWJ1dGUpLCB7XG4gICAgICBpbnB1dHM6IFsxXSxcbiAgICAgIG91dHB1dHM6IFthdHRyaWJ1dGVzLndJc0NvbnN0ID8gLTIgOiAtMV0sXG4gICAgfSlbMF07XG4gIGlmIChhdHRyaWJ1dGVzLndJc0NvbnN0ICYmICFjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QpIHtcbiAgICBjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QgPSB0cmFuc3Bvc2VkV2VpZ2h0O1xuICB9XG5cbiAgLy8gU1RFUC4yOiBwcmVwYXJlIHJlc2hhcGVkIGlucHV0c1xuICBjb25zdCBjb252SW5wdXRzID0gW2lucHV0c1swXSwgdHJhbnNwb3NlZFdlaWdodF07XG4gIGlmIChoYXNCaWFzKSB7XG4gICAgY29udklucHV0cy5wdXNoKGlucHV0c1syXSk7XG4gIH1cblxuICAvLyBTVEVQLjM6IGNvbXB1dGUgbWF0bXVsXG4gIGNvbnN0IGRpbUFPdXRlciA9IGlzQ2hhbm5lbHNMYXN0ID8gb3V0SGVpZ2h0ICogb3V0V2lkdGggOiBvdXRDaGFubmVscztcbiAgY29uc3QgZGltQk91dGVyID0gaXNDaGFubmVsc0xhc3QgPyBvdXRDaGFubmVscyA6IG91dEhlaWdodCAqIG91dFdpZHRoO1xuICBjb25zdCBkaW1Jbm5lciA9IHdlaWdodEhlaWdodCAqIHdlaWdodFdpZHRoICogaW5wdXRDaGFubmVscztcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUNvbnYyRE1hdE11bFByb2dyYW1JbmZvKFxuICAgICAgY29udklucHV0cyxcbiAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICBvdXRwdXRTaGFwZSxcbiAgICAgIGRpbUFPdXRlcixcbiAgICAgIGRpbUJPdXRlcixcbiAgICAgIGRpbUlubmVyLFxuICAgICAgaGFzQmlhcyxcbiAgICAgIHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHMsXG4gICAgICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbixcbiAgICApLFxuICAgIHsgaW5wdXRzOiBjb252SW5wdXRzIH0sXG4gICk7XG59O1xuXG5jb25zdCBjb252MWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIC8vIGV4dGVuZCB0aGUgaW5wdXQgdG8gMkQgYnkgYWRkaW5nIEggZGltZW5zaW9uXG4gIGNvbnN0IGlzQ2hhbm5lbExhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBpbnB1dHMgPSBbXG4gICAgY29udGV4dC5pbnB1dHNbMF0ucmVzaGFwZShcbiAgICAgIGlzQ2hhbm5lbExhc3RcbiAgICAgICAgPyAvLyBbTiwgVywgQ10gLT4gW04sIEg9MSwgVywgQ11cbiAgICAgICAgICBbY29udGV4dC5pbnB1dHNbMF0uZGltc1swXSwgMSwgY29udGV4dC5pbnB1dHNbMF0uZGltc1sxXSwgY29udGV4dC5pbnB1dHNbMF0uZGltc1syXV1cbiAgICAgICAgOiAvLyBbTiwgQywgV10gLT4gW04sIEMsIEg9MSwgV11cbiAgICAgICAgICBbY29udGV4dC5pbnB1dHNbMF0uZGltc1swXSwgY29udGV4dC5pbnB1dHNbMF0uZGltc1sxXSwgMSwgY29udGV4dC5pbnB1dHNbMF0uZGltc1syXV0sXG4gICAgKSxcbiAgICAvL1tGSUxURVJfT1VUX0NIQU5ORUwsIEZJTFRFUl9JTl9DSEFOTkVMLCBrV10gLT4gW0ZJTFRFUl9PVVRfQ0hBTk5FTCwgRklMVEVSX0lOX0NIQU5ORUwsIGtIPTEsIGtXXVxuICAgIGNvbnRleHQuaW5wdXRzWzFdLnJlc2hhcGUoW2NvbnRleHQuaW5wdXRzWzFdLmRpbXNbMF0sIGNvbnRleHQuaW5wdXRzWzFdLmRpbXNbMV0sIDEsIGNvbnRleHQuaW5wdXRzWzFdLmRpbXNbMl1dKSxcbiAgXTtcbiAgaWYgKGNvbnRleHQuaW5wdXRzLmxlbmd0aCA9PT0gMykge1xuICAgIGlucHV0cy5wdXNoKGNvbnRleHQuaW5wdXRzWzJdKTtcbiAgfVxuICBjb25zdCBwYWRzID0gWzAsIGF0dHJpYnV0ZXMucGFkc1swXSwgMCwgYXR0cmlidXRlcy5wYWRzWzFdXTtcbiAgY29uc3Qgc3RyaWRlcyA9IFsxXS5jb25jYXQoYXR0cmlidXRlcy5zdHJpZGVzKTtcbiAgY29uc3QgZGlsYXRpb25zID0gWzFdLmNvbmNhdChhdHRyaWJ1dGVzLmRpbGF0aW9ucyk7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gWzFdLmNvbmNhdChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlKTtcbiAgY29uc3QgYWRqdXN0ZWRBdHRyaWJ1dGVzID0gZ2V0QWRqdXN0ZWRDb252QXR0cmlidXRlcyhcbiAgICB7IC4uLmF0dHJpYnV0ZXMsIHBhZHMsIHN0cmlkZXMsIGRpbGF0aW9ucywga2VybmVsU2hhcGUgfSxcbiAgICBpbnB1dHMsXG4gICk7XG4gIGNvbnYyZChjb250ZXh0LCBpbnB1dHMsIGFkanVzdGVkQXR0cmlidXRlcywgKG91dHB1dFNoYXBlKSA9PlxuICAgIGlzQ2hhbm5lbExhc3QgPyBbb3V0cHV0U2hhcGVbMF0sIG91dHB1dFNoYXBlWzJdLCBvdXRwdXRTaGFwZVszXV0gOiBbb3V0cHV0U2hhcGVbMF0sIG91dHB1dFNoYXBlWzFdLCBvdXRwdXRTaGFwZVszXV0sXG4gICk7XG59O1xuXG5jb25zdCBjb252M2QgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBmb3JtYXQgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnID8gJ2NoYW5uZWxzTGFzdCcgOiAnY2hhbm5lbHNGaXJzdCc7XG4gIGNvbnN0IGFkanVzdGVkQXR0cmlidXRlcyA9IGdldEFkanVzdGVkQ29udkF0dHJpYnV0ZXMoYXR0cmlidXRlcywgaW5wdXRzKTtcbiAgY29uc3QgcGFkcyA9IGF0dHJpYnV0ZXMuYXV0b1BhZCA9PT0gJ05PVFNFVCcgPyBhdHRyaWJ1dGVzLnBhZHMgOiBhdHRyaWJ1dGVzLmF1dG9QYWQ7XG4gIGNvbnN0IGNvbnZJbmZvID0gY29tcHV0ZUNvbnYzREluZm8oXG4gICAgaW5wdXRzWzBdLmRpbXMgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgICBpbnB1dHNbMV0uZGltcyBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICAgIGF0dHJpYnV0ZXMuc3RyaWRlcyBhcyBudW1iZXIgfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgYXR0cmlidXRlcy5kaWxhdGlvbnMgYXMgbnVtYmVyIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICAgIHBhZHMgYXMgc3RyaW5nIHwgbnVtYmVyW10sXG4gICAgZmFsc2UsXG4gICAgZm9ybWF0LFxuICApO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlQ29udjNETmFpdmVQcm9ncmFtSW5mbyhcbiAgICAgIGlucHV0cyxcbiAgICAgIGFkanVzdGVkQXR0cmlidXRlcyxcbiAgICAgIGNvbnZJbmZvLm91dFNoYXBlLFxuICAgICAgW2NvbnZJbmZvLmZpbHRlckRlcHRoLCBjb252SW5mby5maWx0ZXJIZWlnaHQsIGNvbnZJbmZvLmZpbHRlcldpZHRoXSxcbiAgICAgIFtjb252SW5mby5wYWRJbmZvLmZyb250LCBjb252SW5mby5wYWRJbmZvLnRvcCwgY29udkluZm8ucGFkSW5mby5sZWZ0XSxcbiAgICAgIGZvcm1hdCxcbiAgICApLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvbnYgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgaWYgKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMubGVuZ3RoID09PSAzKSB7XG4gICAgY29udjFkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9IGVsc2UgaWYgKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMubGVuZ3RoID09PSA1KSB7XG4gICAgY29udjNkKGNvbnRleHQsIGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBhZGp1c3RlZEF0dHJpYnV0ZXMgPSBnZXRBZGp1c3RlZENvbnZBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMsIGNvbnRleHQuaW5wdXRzKTtcbiAgICBjb252MmQoY29udGV4dCwgY29udGV4dC5pbnB1dHMsIGFkanVzdGVkQXR0cmlidXRlcyk7XG4gIH1cbn07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG4vLyBzYW1wbGVkIGZyb20gW0B0ZW5zb3JmbG93L3RmanNdIHRmanMtYmFja2VuZC13ZWJncHUvc3JjL2NvbnZfYmFja3Byb3Bfd2ViZ3B1LnRzXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgTE9HX0RFQlVHIH0gZnJvbSAnLi4vLi4vLi4vbG9nJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7IFByb2dyYW1JbmZvLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi8uLi90eXBlcyc7XG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbiAgZ2V0TWF4Q29tcG9uZW50cyxcbn0gZnJvbSAnLi4vY29tbW9uJztcbmltcG9ydCB7IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzIH0gZnJvbSAnLi4vY29udi10cmFuc3Bvc2UnO1xuXG5leHBvcnQgY29uc3QgY3JlYXRlQ29udlRyYW5zcG9zZTJEUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyxcbiAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPiAyO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGF0dHJpYnV0ZXMub3V0cHV0U2hhcGU7XG4gIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3QgZ3JvdXAgPSBhdHRyaWJ1dGVzLmdyb3VwO1xuICBjb25zdCB3U2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgY29uc3QgaW5wdXRDaGFubmVsc1Blckdyb3VwID0gd1NoYXBlWzJdIC8gZ3JvdXA7XG4gIGNvbnN0IG91dHB1dENoYW5uZWxzUGVyR3JvdXAgPSB3U2hhcGVbM107XG4gIGNvbnN0IGFDb21wb25lbnRzID0gaXNDaGFubmVsc0xhc3QgPyBnZXRNYXhDb21wb25lbnRzKGlucHV0Q2hhbm5lbHNQZXJHcm91cCkgOiAxO1xuICBjb25zdCBwYWNrSW5wdXRBczQgPSBpc0NoYW5uZWxzTGFzdCAmJiBvdXRwdXRDaGFubmVsc1Blckdyb3VwID09PSAxICYmIGlucHV0Q2hhbm5lbHNQZXJHcm91cCA+PSA0O1xuICBjb25zdCBpbnB1dENoYW5uZWxzUGVyR3JvdXBJbnQgPSBwYWNrSW5wdXRBczRcbiAgICA/IE1hdGguZmxvb3IoaW5wdXRDaGFubmVsc1Blckdyb3VwIC8gNCkgKiA0XG4gICAgOiBNYXRoLmZsb29yKGlucHV0Q2hhbm5lbHNQZXJHcm91cCAvIGFDb21wb25lbnRzKSAqIGFDb21wb25lbnRzO1xuICBjb25zdCBpbnB1dENoYW5uZWxzUmVtYWluZGVyID0gaW5wdXRDaGFubmVsc1Blckdyb3VwIC0gaW5wdXRDaGFubmVsc1Blckdyb3VwSW50O1xuICBjb25zdCBjb21wb25lbnRzID0gaXNDaGFubmVsc0xhc3QgPyBnZXRNYXhDb21wb25lbnRzKG91dHB1dENoYW5uZWxzUGVyR3JvdXApIDogMTtcbiAgY29uc3QgYkNvbXBvbmVudHMgPSBpc0NoYW5uZWxzTGFzdCA/IChvdXRwdXRDaGFubmVsc1Blckdyb3VwID09PSAxID8gYUNvbXBvbmVudHMgOiBjb21wb25lbnRzKSA6IDE7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyBjb21wb25lbnRzO1xuICBjb25zdCBkaXNwYXRjaCA9IFtNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0KSwgMSwgMV07XG4gIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbY29udjJkX2JhY2twcm9wX3dlYmdwdV0gZGlzcGF0Y2ggPSAke2Rpc3BhdGNofWApO1xuXG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWydyYW5rJywgJ3JhbmsnXTtcbiAgY29uc3Qgc3RyaWRlcyA9IFthdHRyaWJ1dGVzLnN0cmlkZXNbMF0sIGF0dHJpYnV0ZXMuc3RyaWRlc1sxXV07XG4gIGNvbnN0IGZpbHRlckRpbXMgPSBbYXR0cmlidXRlcy5rZXJuZWxTaGFwZVtpc0NoYW5uZWxzTGFzdCA/IDEgOiAyXSwgYXR0cmlidXRlcy5rZXJuZWxTaGFwZVtpc0NoYW5uZWxzTGFzdCA/IDIgOiAzXV07XG4gIGNvbnN0IGRpbGF0aW9ucyA9IFthdHRyaWJ1dGVzLmRpbGF0aW9uc1swXSwgYXR0cmlidXRlcy5kaWxhdGlvbnNbMV1dO1xuICBjb25zdCBlZmZlY3RpdmVGaWx0ZXJEaW1zID0gW1xuICAgIGZpbHRlckRpbXNbMF0gK1xuICAgICAgKGF0dHJpYnV0ZXMuZGlsYXRpb25zWzBdIDw9IDFcbiAgICAgICAgPyAwXG4gICAgICAgIDogKGF0dHJpYnV0ZXMua2VybmVsU2hhcGVbaXNDaGFubmVsc0xhc3QgPyAxIDogMl0gLSAxKSAqIChhdHRyaWJ1dGVzLmRpbGF0aW9uc1swXSAtIDEpKSxcbiAgICBmaWx0ZXJEaW1zWzFdICtcbiAgICAgIChhdHRyaWJ1dGVzLmRpbGF0aW9uc1sxXSA8PSAxXG4gICAgICAgID8gMFxuICAgICAgICA6IChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlW2lzQ2hhbm5lbHNMYXN0ID8gMiA6IDNdIC0gMSkgKiAoYXR0cmlidXRlcy5kaWxhdGlvbnNbMV0gLSAxKSksXG4gIF07XG4gIGNvbnN0IHBhZHMgPSBbXG4gICAgZWZmZWN0aXZlRmlsdGVyRGltc1swXSAtIDEgLSBNYXRoLmZsb29yKChhdHRyaWJ1dGVzLnBhZHNbMF0gKyBhdHRyaWJ1dGVzLnBhZHNbMl0pIC8gMiksXG4gICAgZWZmZWN0aXZlRmlsdGVyRGltc1sxXSAtIDEgLSBNYXRoLmZsb29yKChhdHRyaWJ1dGVzLnBhZHNbMV0gKyBhdHRyaWJ1dGVzLnBhZHNbM10pIC8gMiksXG4gIF07XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHN0cmlkZXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZmlsdGVyRGltcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBkaWxhdGlvbnMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZWZmZWN0aXZlRmlsdGVyRGltcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IHBhZHMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogaW5wdXRDaGFubmVsc1Blckdyb3VwSW50IH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGlucHV0Q2hhbm5lbHNQZXJHcm91cCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRDaGFubmVsc1Blckdyb3VwIH0sXG4gICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzBdLmRpbXMsIGlucHV0c1sxXS5kaW1zKSxcbiAgXTtcbiAgaWYgKGhhc0JpYXMpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMl0uZGltcykpO1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3JhbmsnKTtcbiAgfVxuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRwdXRTaGFwZSkpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3N0cmlkZXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBzdHJpZGVzLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnZmlsdGVyX2RpbXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBmaWx0ZXJEaW1zLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnZGlsYXRpb25zJywgdHlwZTogJ3UzMicsIGxlbmd0aDogZmlsdGVyRGltcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ2VmZmVjdGl2ZV9maWx0ZXJfZGltcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGVmZmVjdGl2ZUZpbHRlckRpbXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdwYWRzJywgdHlwZTogJ2kzMicsIGxlbmd0aDogcGFkcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ2lucHV0X2NoYW5uZWxzX3Blcl9ncm91cF9pbnQnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnaW5wdXRfY2hhbm5lbHNfcGVyX2dyb3VwJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ291dHB1dF9jaGFubmVsc19wZXJfZ3JvdXAnLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG4gICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgICBjb25zdCByb3dEaW0gPSBpc0NoYW5uZWxzTGFzdCA/IDEgOiAyO1xuICAgIGNvbnN0IGNvbERpbSA9IGlzQ2hhbm5lbHNMYXN0ID8gMiA6IDM7XG4gICAgY29uc3QgY2hhbm5lbERpbSA9IGlzQ2hhbm5lbHNMYXN0ID8gMyA6IDE7XG5cbiAgICBjb25zdCB3ID0gaW5wdXRWYXJpYWJsZSgnVycsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoLCBiQ29tcG9uZW50cyk7XG4gICAgY29uc3QgZHkgPSBpbnB1dFZhcmlhYmxlKCdEeScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoLCBhQ29tcG9uZW50cyk7XG4gICAgY29uc3QgaW5wdXRWYXJpYWJsZXMgPSBbZHksIHddO1xuICAgIGlmIChoYXNCaWFzKSB7XG4gICAgICBpbnB1dFZhcmlhYmxlcy5wdXNoKGlucHV0VmFyaWFibGUoJ2JpYXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIFtvdXRwdXRTaGFwZVtjaGFubmVsRGltXV0ubGVuZ3RoLCBjb21wb25lbnRzKSk7XG4gICAgfVxuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdyZXN1bHQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG5cbiAgICBjb25zdCBjYWxjdWxhdGVSZXN1bHQgPSAoKTogc3RyaW5nID0+IHtcbiAgICAgIGxldCBjYWxjU3RyID0gJyc7XG4gICAgICBpZiAocGFja0lucHV0QXM0KSB7XG4gICAgICAgIGlmIChhQ29tcG9uZW50cyA9PT0gNCkge1xuICAgICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICBsZXQgeFZhbHVlID0gJHtkeS5nZXRCeU9mZnNldCgneF9vZmZzZXQnKX07XG4gICAgICAgIGxldCB3VmFsdWUgPSAke3cuZ2V0QnlPZmZzZXQoJ3dfb2Zmc2V0Jyl9O1xuICAgICAgICBkb3RQcm9kID0gZG90UHJvZCArIGRvdCh4VmFsdWUsIHdWYWx1ZSk7XG4gICAgICAgIHhfb2Zmc2V0ICs9IDF1O1xuICAgICAgICB3X29mZnNldCArPSAxdTtgO1xuICAgICAgICB9IGVsc2UgaWYgKGFDb21wb25lbnRzID09PSAyKSB7XG4gICAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgZG90UHJvZCA9IGRvdFByb2QgKyBkb3QodmVjNDwke2RhdGFUeXBlfT4oJHtkeS5nZXRCeU9mZnNldCgneF9vZmZzZXQnKX0sICR7ZHkuZ2V0QnlPZmZzZXQoJ3hfb2Zmc2V0ICsgMXUnKX0pLCB2ZWM0PCR7ZGF0YVR5cGV9Pigke3cuZ2V0QnlPZmZzZXQoJ3dfb2Zmc2V0Jyl9LCAke3cuZ2V0QnlPZmZzZXQoJ3dfb2Zmc2V0ICsgMXUnKX0pKTtcbiAgICAgICAgICB4X29mZnNldCArPSAydTtcbiAgICAgICAgICB3X29mZnNldCArPSAydTtgO1xuICAgICAgICB9IGVsc2UgaWYgKGFDb21wb25lbnRzID09PSAxKSB7XG4gICAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgZG90UHJvZCA9IGRvdFByb2QgKyBkb3QodmVjNDwke2RhdGFUeXBlfT4oJHtkeS5nZXRCeU9mZnNldCgneF9vZmZzZXQnKX0sICR7ZHkuZ2V0QnlPZmZzZXQoJ3hfb2Zmc2V0ICsgMXUnKX0sICR7ZHkuZ2V0QnlPZmZzZXQoJ3hfb2Zmc2V0ICsgMnUnKX0sICR7ZHkuZ2V0QnlPZmZzZXQoJ3hfb2Zmc2V0ICsgM3UnKX0pLCB2ZWM0PCR7ZGF0YVR5cGV9Pigke3cuZ2V0QnlPZmZzZXQoJ3dfb2Zmc2V0Jyl9LCAke3cuZ2V0QnlPZmZzZXQoJ3dfb2Zmc2V0ICsgMXUnKX0sICR7dy5nZXRCeU9mZnNldCgnd19vZmZzZXQgKyAydScpfSwgJHt3LmdldEJ5T2Zmc2V0KCd3X29mZnNldCArIDN1Jyl9KSk7XG4gICAgICAgICAgeF9vZmZzZXQgKz0gNHU7XG4gICAgICAgICAgd19vZmZzZXQgKz0gNHU7YDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgICAgICAgICBsZXQgeFZhbHVlID0gJHtcbiAgICAgICAgICAgICAgICAgICAgaXNDaGFubmVsc0xhc3RcbiAgICAgICAgICAgICAgICAgICAgICA/IGR5LmdldEJ5T2Zmc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICBgJHtkeS5pbmRpY2VzVG9PZmZzZXQoYCR7ZHkudHlwZS5pbmRpY2VzfShiYXRjaCwgaWR5UiwgaWR5QywgaW5wdXRDaGFubmVsKWApfSAvICR7YUNvbXBvbmVudHN9YCxcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICA6IGR5LmdldCgnYmF0Y2gnLCAnaW5wdXRDaGFubmVsJywgJ2lkeVInLCAnaWR5QycpXG4gICAgICAgICAgICAgICAgICB9O1xuICAgICAgICBgO1xuICAgICAgICBpZiAoYUNvbXBvbmVudHMgPT09IDEpIHtcbiAgICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICBsZXQgd19vZmZzZXQgPSAke3cuaW5kaWNlc1RvT2Zmc2V0KGAke3cudHlwZS5pbmRpY2VzfSh1MzIod1JQZXJtKSwgdTMyKHdDUGVybSksIGlucHV0Q2hhbm5lbCwgd091dENoYW5uZWwpYCl9O1xuICAgICAgICAgIGxldCB3VmFsdWUgPSAke3cuZ2V0QnlPZmZzZXQoYHdfb2Zmc2V0IC8gJHtiQ29tcG9uZW50c31gKX07XG4gICAgICAgICAgZG90UHJvZCA9IGRvdFByb2QgKyB4VmFsdWUgKiB3VmFsdWU7YDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmb3IgKGxldCBjID0gMDsgYyA8IGFDb21wb25lbnRzOyBjKyspIHtcbiAgICAgICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgICAgbGV0IHdWYWx1ZSR7Y30gPSAke3cuZ2V0QnlPZmZzZXQoYCR7dy5pbmRpY2VzVG9PZmZzZXQoYCR7dy50eXBlLmluZGljZXN9KHUzMih3UlBlcm0pLCB1MzIod0NQZXJtKSwgaW5wdXRDaGFubmVsICsgJHtjfSwgd091dENoYW5uZWwpYCl9IC8gJHtiQ29tcG9uZW50c31gKX07XG4gICAgICAgICAgICBkb3RQcm9kID0gZG90UHJvZCArIHhWYWx1ZVske2N9XSAqIHdWYWx1ZSR7Y307YDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBjYWxjU3RyO1xuICAgIH07XG4gICAgY29uc3QgY2FsY3VsYXRlUmVtYWluZGVyID0gKCk6IHN0cmluZyA9PiB7XG4gICAgICBpZiAoaW5wdXRDaGFubmVsc1JlbWFpbmRlciA9PT0gMCkge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgICB9XG4gICAgICBpZiAoIXBhY2tJbnB1dEFzNCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHBhY2tJbnB1dEFzNCAke3BhY2tJbnB1dEFzNH0gaXMgbm90IHRydWUuYCk7XG4gICAgICB9XG4gICAgICBsZXQgY2FsY1N0ciA9ICcnO1xuICAgICAgaWYgKGFDb21wb25lbnRzID09PSAxKSB7XG4gICAgICAgIGNhbGNTdHIgKz0gJ2RvdFByb2QgPSBkb3RQcm9kJztcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENoYW5uZWxzUmVtYWluZGVyOyBpKyspIHtcbiAgICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICAgICsgJHtkeS5nZXRCeU9mZnNldChgeF9vZmZzZXQgKyAke2l9YCl9ICogJHt3LmdldEJ5T2Zmc2V0KGB3X29mZnNldCArICR7aX1gKX1gO1xuICAgICAgICB9XG4gICAgICAgIGNhbGNTdHIgKz0gJzsnO1xuICAgICAgfSBlbHNlIGlmIChhQ29tcG9uZW50cyA9PT0gMikge1xuICAgICAgICBpZiAoaW5wdXRDaGFubmVsc1JlbWFpbmRlciAhPT0gMikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBpbnB1dENoYW5uZWxzUmVtYWluZGVyICR7aW5wdXRDaGFubmVsc1JlbWFpbmRlcn0uYCk7XG4gICAgICAgIH1cbiAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgbGV0IHhWYWx1ZSA9ICR7ZHkuZ2V0QnlPZmZzZXQoJ3hfb2Zmc2V0Jyl9O1xuICAgICAgICAgIGxldCB3VmFsdWUgPSAke3cuZ2V0QnlPZmZzZXQoJ3dfb2Zmc2V0Jyl9O1xuICAgICAgICAgIGRvdFByb2QgPSBkb3RQcm9kICsgZG90KHhWYWx1ZSwgd1ZhbHVlKTtgO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNhbGNTdHI7XG4gICAgfTtcbiAgICBjb25zdCBjb2RlU25pcHBldCA9IGBcbiAgICAgICAgICAgIGxldCBvdXRwdXRJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKGBnbG9iYWxfaWR4ICogJHtjb21wb25lbnRzfWApfTtcbiAgICAgICAgICAgIGxldCBiYXRjaCA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dEluZGljZXMnLCAwKX07XG4gICAgICAgICAgICBsZXQgZDEgPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRJbmRpY2VzJywgY2hhbm5lbERpbSl9O1xuICAgICAgICAgICAgbGV0IHIgPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRJbmRpY2VzJywgcm93RGltKX07XG4gICAgICAgICAgICBsZXQgYyA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dEluZGljZXMnLCBjb2xEaW0pfTtcbiAgICAgICAgICAgIGxldCBkeUNvcm5lciA9IHZlYzI8aTMyPihpMzIociksIGkzMihjKSkgLSB1bmlmb3Jtcy5wYWRzO1xuICAgICAgICAgICAgbGV0IGR5UkNvcm5lciA9IGR5Q29ybmVyLng7XG4gICAgICAgICAgICBsZXQgZHlDQ29ybmVyID0gZHlDb3JuZXIueTtcbiAgICAgICAgICAgIGxldCBncm91cElkID0gZDEgLyB1bmlmb3Jtcy5vdXRwdXRfY2hhbm5lbHNfcGVyX2dyb3VwO1xuICAgICAgICAgICAgbGV0IHdPdXRDaGFubmVsID0gZDEgLSBncm91cElkICogdW5pZm9ybXMub3V0cHV0X2NoYW5uZWxzX3Blcl9ncm91cDtcbiAgICAgICAgICAgIC8vIENvbnZvbHZlIGR5KD8sID8sIGQyKSB3aXRoIHcoOiwgOiwgZDEsIGQyKSB0byBjb21wdXRlIGR4KHhSLCB4QywgZDEpLlxuICAgICAgICAgICAgLy8gPyA9IHRvIGJlIGRldGVybWluZWQuIDogPSBhY3Jvc3MgYWxsIHZhbHVlcyBpbiB0aGF0IGF4aXMuXG4gICAgICAgICAgICB2YXIgZG90UHJvZCA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KDAuMCk7XG4gICAgICAgICAgICB2YXIgd1I6IHUzMiA9IDA7XG4gICAgICAgICAgICBpZiAodW5pZm9ybXMuZGlsYXRpb25zLnggPT0gMSkge1xuICAgICAgICAgICAgICAvLyBNaW5pbXVtIHdSID49IDAgdGhhdCBzYXRpc2ZpZXMgKGR5UkNvcm5lciArIHdSKSAlICh1bmlmb3Jtcy5zdHJpZGVzLngpID09IDBcbiAgICAgICAgICAgICAgd1IgPSB1MzIoKChkeVJDb3JuZXIgKyBpMzIodW5pZm9ybXMuc3RyaWRlcy54KSAtIDEpIC8gaTMyKHVuaWZvcm1zLnN0cmlkZXMueCkpICogaTMyKHVuaWZvcm1zLnN0cmlkZXMueCkgLSBkeVJDb3JuZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICg7IHdSIDwgdW5pZm9ybXMuZWZmZWN0aXZlX2ZpbHRlcl9kaW1zLng7IHdSID0gd1IgKyAxKSB7XG4gICAgICAgICAgICAgIGlmICh3UiAlIHVuaWZvcm1zLmRpbGF0aW9ucy54ICE9IDApIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBsZXQgZHlSID0gKCR7ZGF0YVR5cGV9KGR5UkNvcm5lcikgKyAke2RhdGFUeXBlfSh3UikpIC8gJHtkYXRhVHlwZX0odW5pZm9ybXMuc3RyaWRlc1swXSk7XG4gICAgICAgICAgICAgIGxldCB3UlBlcm0gPSB1bmlmb3Jtcy5maWx0ZXJfZGltcy54IC0gMSAtIHdSIC8gdW5pZm9ybXMuZGlsYXRpb25zLng7XG4gICAgICAgICAgICAgIGlmIChkeVIgPCAwLjAgfHwgZHlSID49ICR7ZGF0YVR5cGV9KHVuaWZvcm1zLkR5X3NoYXBlWyR7cm93RGltfV0pIHx8IGZyYWN0KGR5UikgPiAwLjAgfHxcbiAgICAgICAgICAgICAgICAgIHdSUGVybSA8IDApIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBsZXQgaWR5UjogdTMyID0gdTMyKGR5Uik7XG4gICAgICAgICAgICAgIHZhciB3QzogdTMyID0gMDtcbiAgICAgICAgICAgICAgaWYgKHVuaWZvcm1zLmRpbGF0aW9ucy55ID09IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBNaW5pbXVtIHdDID49IDAgdGhhdCBzYXRpc2ZpZXMgKGR5Q0Nvcm5lciArIHdDKSAlICh1bmlmb3Jtcy5zdHJpZGVzLnkpID09IDBcbiAgICAgICAgICAgICAgICB3QyA9IHUzMigoKGR5Q0Nvcm5lciArIGkzMih1bmlmb3Jtcy5zdHJpZGVzLnkpIC0gMSkgLyBpMzIodW5pZm9ybXMuc3RyaWRlcy55KSkgKiBpMzIodW5pZm9ybXMuc3RyaWRlcy55KSAtIGR5Q0Nvcm5lcik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZm9yICg7IHdDIDwgdW5pZm9ybXMuZWZmZWN0aXZlX2ZpbHRlcl9kaW1zLnk7IHdDID0gd0MgKyAxKSB7XG4gICAgICAgICAgICAgICAgaWYgKHdDICUgdW5pZm9ybXMuZGlsYXRpb25zLnkgIT0gMCkge1xuICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCBkeUMgPSAoJHtkYXRhVHlwZX0oZHlDQ29ybmVyKSArICR7ZGF0YVR5cGV9KHdDKSkgLyAke2RhdGFUeXBlfSh1bmlmb3Jtcy5zdHJpZGVzLnkpO1xuICAgICAgICAgICAgICAgIGxldCB3Q1Blcm0gPSB1bmlmb3Jtcy5maWx0ZXJfZGltcy55IC0gMSAtIHdDIC8gdW5pZm9ybXMuZGlsYXRpb25zLnk7XG4gICAgICAgICAgICAgICAgaWYgKGR5QyA8IDAuMCB8fCBkeUMgPj0gJHtkYXRhVHlwZX0odW5pZm9ybXMuRHlfc2hhcGVbJHtjb2xEaW19XSkgfHxcbiAgICAgICAgICAgICAgICAgICAgZnJhY3QoZHlDKSA+IDAuMCB8fCB3Q1Blcm0gPCAwKSB7XG4gICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGlkeUM6IHUzMiA9IHUzMihkeUMpO1xuICAgICAgICAgICAgICAgIHZhciBpbnB1dENoYW5uZWwgPSBncm91cElkICogdW5pZm9ybXMuaW5wdXRfY2hhbm5lbHNfcGVyX2dyb3VwO1xuICAgICAgICAgICAgICAgICR7XG4gICAgICAgICAgICAgICAgICBwYWNrSW5wdXRBczRcbiAgICAgICAgICAgICAgICAgICAgPyBgXG4gICAgICAgICAgICAgICAgdmFyIHhfb2Zmc2V0ID0gJHtkeS5pbmRpY2VzVG9PZmZzZXQoYCR7ZHkudHlwZS5pbmRpY2VzfShiYXRjaCwgaWR5UiwgaWR5QywgaW5wdXRDaGFubmVsKWApfSAvICR7YUNvbXBvbmVudHN9O1xuICAgICAgICAgICAgICAgIHZhciB3X29mZnNldCA9ICR7dy5pbmRpY2VzVG9PZmZzZXQoYCR7dy50eXBlLmluZGljZXN9KHdSUGVybSwgd0NQZXJtLCBpbnB1dENoYW5uZWwsIHdPdXRDaGFubmVsKWApfSAvICR7YkNvbXBvbmVudHN9O1xuICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICA6ICcnXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGQyOiB1MzIgPSAwOyBkMiA8IHVuaWZvcm1zLmlucHV0X2NoYW5uZWxzX3Blcl9ncm91cF9pbnQ7IGQyID0gZDIgKyAke3BhY2tJbnB1dEFzNCA/IDQgOiBhQ29tcG9uZW50c30pIHtcbiAgICAgICAgICAgICAgICAgICR7Y2FsY3VsYXRlUmVzdWx0KCl9XG4gICAgICAgICAgICAgICAgICBpbnB1dENoYW5uZWwgPSBpbnB1dENoYW5uZWwgKyAke3BhY2tJbnB1dEFzNCA/IDQgOiBhQ29tcG9uZW50c307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICR7Y2FsY3VsYXRlUmVtYWluZGVyKCl9XG4gICAgICAgICAgICAgICAgd0MgPSB3QyArIHVuaWZvcm1zLnN0cmlkZXMueSAtIDE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgd1IgPSB3UiArIHVuaWZvcm1zLnN0cmlkZXNbMF0gLSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHZhbHVlID0gZG90UHJvZCR7aGFzQmlhcyA/IGAgKyBiaWFzW2QxIC8gJHtjb21wb25lbnRzfV1gIDogJyd9O1xuICAgICAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAndmFsdWUnKX07XG4gICAgICAgICAgYDtcblxuICAgIHJldHVybiBgXG4gICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcmlhYmxlcywgb3V0cHV0KX1cbiAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX07XG4gICAgJHtjb2RlU25pcHBldH19YDtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdDb252VHJhbnNwb3NlMkQnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fTske2FDb21wb25lbnRzfSR7YkNvbXBvbmVudHN9JHtjb21wb25lbnRzfSR7cGFja0lucHV0QXM0fSR7aW5wdXRDaGFubmVsc1JlbWFpbmRlcn1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXMsXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBkaXNwYXRjaFswXSwgeTogZGlzcGF0Y2hbMV0sIHo6IGRpc3BhdGNoWzJdIH0sXG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBkaW1zOiBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiA/IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uKG91dHB1dFNoYXBlKSA6IG91dHB1dFNoYXBlLFxuICAgICAgICAgIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlQ29udlRyYW5zcG9zZTJEUHJvZ3JhbUluZm8gfSBmcm9tICcuLzNyZC1wYXJ0eS9jb252X2JhY2twcm9wX3dlYmdwdSc7XG5pbXBvcnQgeyBDb252QXR0cmlidXRlcyB9IGZyb20gJy4vY29udic7XG5pbXBvcnQgeyBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMgfSBmcm9tICcuL2Z1c2UtdXRpbHMnO1xuaW1wb3J0IHsgY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8gfSBmcm9tICcuL3RyYW5zcG9zZSc7XG5cbmNvbnN0IGNvbXB1dGVUb3RhbFBhZCA9IChcbiAgaW5EaW06IG51bWJlcixcbiAgc3RyaWRlOiBudW1iZXIsXG4gIGFkajogbnVtYmVyLFxuICBrZXJuZWw6IG51bWJlcixcbiAgZGlsYXRpb246IG51bWJlcixcbiAgb3V0U2l6ZTogbnVtYmVyLFxuKSA9PiAoaW5EaW0gLSAxKSAqIHN0cmlkZSArIGFkaiArIChrZXJuZWwgLSAxKSAqIGRpbGF0aW9uICsgMSAtIG91dFNpemU7XG5cbmNvbnN0IGRpc3RyaWJ1dGVQYWRkaW5nID0gKHRvdGFsUGFkOiBudW1iZXIsIGF1dG9QYWQ6IHN0cmluZywgcGFkczogbnVtYmVyW10sIGhlYWQ6IG51bWJlciwgdGFpbDogbnVtYmVyKSA9PiB7XG4gIGNvbnN0IHNtYWxsUGFkID0gTWF0aC5mbG9vcih0b3RhbFBhZCAvIDIpO1xuICBpZiAoYXV0b1BhZCA9PT0gJ1NBTUVfVVBQRVInKSB7XG4gICAgcGFkc1toZWFkXSA9IHNtYWxsUGFkO1xuICAgIHBhZHNbdGFpbF0gPSB0b3RhbFBhZCAtIHNtYWxsUGFkO1xuICB9IGVsc2UgaWYgKGF1dG9QYWQgPT09ICdTQU1FX0xPV0VSJykge1xuICAgIHBhZHNbaGVhZF0gPSB0b3RhbFBhZCAtIHNtYWxsUGFkO1xuICAgIHBhZHNbdGFpbF0gPSBzbWFsbFBhZDtcbiAgfVxufTtcblxuY29uc3QgY2FsY3VsYXRlT3V0cHV0U2hhcGVBbmRQYWRzID0gKFxuICBpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBkaWxhdGlvbnM6IHJlYWRvbmx5IG51bWJlcltdLFxuICBhdXRvUGFkOiBzdHJpbmcsXG4gIGdyb3VwOiBudW1iZXIsXG4gIHBhZHM6IG51bWJlcltdLFxuICBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgaXNDaGFubmVsTGFzdDogYm9vbGVhbixcbiAgb3V0cHV0UGFkZGluZzogbnVtYmVyW10sXG4gIG91dHB1dFNoYXBlOiBudW1iZXJbXSxcbikgPT4ge1xuICBjb25zdCBzcGF0aWFsUmFuayA9IGlucHV0U2hhcGUubGVuZ3RoIC0gMjtcbiAgY29uc3QgdXBkYXRlT3V0cHV0U2hhcGUgPSBvdXRwdXRTaGFwZS5sZW5ndGggPT09IDA7XG4gIGlmIChvdXRwdXRQYWRkaW5nLmxlbmd0aCA8IHNwYXRpYWxSYW5rKSB7XG4gICAgb3V0cHV0UGFkZGluZy5wdXNoKC4uLkFycmF5KHNwYXRpYWxSYW5rIC0gb3V0cHV0UGFkZGluZy5sZW5ndGgpLmZpbGwoMCkpO1xuICB9XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IGlucHV0U2hhcGVbMF07XG4gIGNvbnN0IG91dENoYW5uZWxzID0ga2VybmVsU2hhcGVbaXNDaGFubmVsTGFzdCA/IDMgOiAxXSAqIGdyb3VwO1xuICBmb3IgKGxldCBpID0gMCwgaiA9IGlucHV0U2hhcGUubGVuZ3RoIC0gc3BhdGlhbFJhbmsgLSAoaXNDaGFubmVsTGFzdCA/IDEgOiAwKTsgaSA8IHNwYXRpYWxSYW5rOyArK2ksICsraikge1xuICAgIGNvbnN0IGluU2l6ZSA9IGlucHV0U2hhcGVbal07XG4gICAgY29uc3Qgb3V0U2l6ZSA9IHVwZGF0ZU91dHB1dFNoYXBlID8gaW5TaXplICogc3RyaWRlc1tpXSA6IG91dHB1dFNoYXBlW2ldO1xuICAgIGNvbnN0IHRvdGFsUGFkID0gY29tcHV0ZVRvdGFsUGFkKGluU2l6ZSwgc3RyaWRlc1tpXSwgcGFkc1tpXSwga2VybmVsU2hhcGVbal0sIGRpbGF0aW9uc1tpXSwgb3V0U2l6ZSk7XG4gICAgZGlzdHJpYnV0ZVBhZGRpbmcodG90YWxQYWQsIGF1dG9QYWQsIHBhZHMsIGksIGkgKyBzcGF0aWFsUmFuayk7XG4gICAgaWYgKHVwZGF0ZU91dHB1dFNoYXBlKSB7XG4gICAgICBvdXRwdXRTaGFwZS5wdXNoKFxuICAgICAgICBzdHJpZGVzW2ldICogKGluU2l6ZSAtIDEpICtcbiAgICAgICAgICBvdXRwdXRQYWRkaW5nW2ldICtcbiAgICAgICAgICAoa2VybmVsU2hhcGVbal0gLSAxKSAqIGRpbGF0aW9uc1tpXSArXG4gICAgICAgICAgMSAtXG4gICAgICAgICAgcGFkc1tpXSAtXG4gICAgICAgICAgcGFkc1tpICsgc3BhdGlhbFJhbmtdLFxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgb3V0cHV0U2hhcGUuc3BsaWNlKDAsIDAsIGJhdGNoU2l6ZSk7XG4gIG91dHB1dFNoYXBlLnNwbGljZShpc0NoYW5uZWxMYXN0ID8gMyA6IDEsIDAsIG91dENoYW5uZWxzKTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMgZXh0ZW5kcyBDb252QXR0cmlidXRlcyB7XG4gIHJlYWRvbmx5IG91dHB1dFBhZGRpbmc6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG59XG5cbmNvbnN0IGdldEFkanVzdGVkQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMgPSA8VCBleHRlbmRzIENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzPihcbiAgYXR0cmlidXRlczogVCxcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4pOiBUID0+IHtcbiAgY29uc3Qga2VybmVsU2hhcGUgPSBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLnNsaWNlKCk7XG4gIC8vIGlmIGtlcm5lbFNoYXBlIGlzIG5vdCBzcGVjaWZpZWQgaW4gdGhlIGF0dHJpYnV0ZXMgb2YgdGhpcyBvcCwgaW5mZXIgaXQgZnJvbSB0aGUgd2VpZ2h0IHRlbnNvciBkaW1zXG4gIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCA9PT0gMCB8fCBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLnJlZHVjZSgoYSwgYikgPT4gYSAqIGIsIDEpID09PSAwKSB7XG4gICAga2VybmVsU2hhcGUubGVuZ3RoID0gMDtcbiAgICBmb3IgKGxldCBpID0gMjsgaSA8IGlucHV0c1sxXS5kaW1zLmxlbmd0aDsgKytpKSB7XG4gICAgICBrZXJuZWxTaGFwZS5wdXNoKGlucHV0c1sxXS5kaW1zW2ldKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgaXNDaGFubmVsc0xhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBrZXJuZWxTaGFwZS5zcGxpY2UoMCwgMCwgaW5wdXRzWzFdLmRpbXNbMF0pO1xuICBrZXJuZWxTaGFwZS5zcGxpY2UoaXNDaGFubmVsc0xhc3QgPyAzIDogMSwgMCwgaW5wdXRzWzFdLmRpbXNbMV0pO1xuXG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHMuc2xpY2UoKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBhdHRyaWJ1dGVzLm91dHB1dFNoYXBlLnNsaWNlKCk7XG4gIGNvbnN0IG91dHB1dFBhZGRpbmcgPSBhdHRyaWJ1dGVzLm91dHB1dFBhZGRpbmcuc2xpY2UoKTtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBsZXQgZGlsYXRpb25zID0gYXR0cmlidXRlcy5kaWxhdGlvbnMuc2xpY2UoKTtcbiAgaWYgKGRpbGF0aW9ucy5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKSA9PT0gMCkge1xuICAgIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMjtcbiAgICBkaWxhdGlvbnMgPSBuZXcgQXJyYXkoc3BhdGlhbFJhbmspLmZpbGwoMSk7XG4gIH1cbiAgbGV0IHN0cmlkZXMgPSBhdHRyaWJ1dGVzLnN0cmlkZXMuc2xpY2UoKTtcbiAgaWYgKHN0cmlkZXMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgPT09IDApIHtcbiAgICBjb25zdCBzcGF0aWFsUmFuayA9IGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDI7XG4gICAgc3RyaWRlcyA9IG5ldyBBcnJheShzcGF0aWFsUmFuaykuZmlsbCgxKTtcbiAgfVxuICAvLyBJZiBvdXRwdXRTaGFwZSBpcyBub3Qgc3BlY2lmaWVkIGluIHRoZSBhdHRyaWJ1dGVzIG9mIHRoaXMgb3AsIGluZmVyIGl0IGZyb20gdGhlIHBhcmFtZXRlcnNcbiAgLy8gU2ltaWxhcmx5LCBhdXRvbWF0aWNhbGx5IGluZmVyIHBhZHMgaWYgbm90IHNwZWNpZmllZFxuICBjYWxjdWxhdGVPdXRwdXRTaGFwZUFuZFBhZHMoXG4gICAgaW5wdXRTaGFwZSxcbiAgICBrZXJuZWxTaGFwZSxcbiAgICBkaWxhdGlvbnMsXG4gICAgYXR0cmlidXRlcy5hdXRvUGFkLFxuICAgIGF0dHJpYnV0ZXMuZ3JvdXAsXG4gICAgcGFkcyxcbiAgICBzdHJpZGVzLFxuICAgIGlzQ2hhbm5lbHNMYXN0LFxuICAgIG91dHB1dFBhZGRpbmcsXG4gICAgb3V0cHV0U2hhcGUsXG4gICk7XG5cbiAgLy8gYWx3YXlzIHJldHVybiBhIG5ldyBvYmplY3Qgc28gZG9lcyBub3QgbW9kaWZ5IHRoZSBvcmlnaW5hbCBhdHRyaWJ1dGVzXG4gIGNvbnN0IG5ld0F0dHJpYnV0ZXM6IFQgPSBPYmplY3QuYXNzaWduKHt9LCBhdHRyaWJ1dGVzKTtcbiAgT2JqZWN0LmFzc2lnbihuZXdBdHRyaWJ1dGVzLCB7IGtlcm5lbFNoYXBlLCBwYWRzLCBvdXRwdXRQYWRkaW5nLCBvdXRwdXRTaGFwZSwgZGlsYXRpb25zLCBzdHJpZGVzIH0pO1xuICByZXR1cm4gbmV3QXR0cmlidXRlcztcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUNvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBhY3RpdmF0aW9uQXR0cmlidXRlcyA9IHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyhhdHRyaWJ1dGVzKTtcbiAgLy8gVE9ETyA6IE1ha2UgdGhpcyBnZW5lcmljIGVub3VnaCB0byBjb21wdXRlIGRlZmF1bHQgYXR0cmlidXRlcyBmb3IgbXVsdGktZGltZW5zaW9uYWwgY29udlxuICBjb25zdCBmb3JtYXQgPSBhdHRyaWJ1dGVzLmZvcm1hdCBhcyAnTkhXQycgfCAnTkNIVyc7XG4gIGNvbnN0IGF1dG9QYWQgPSBbJ05PVFNFVCcsICdWQUxJRCcsICdTQU1FX1VQUEVSJywgJ1NBTUVfTE9XRVInXVtcbiAgICB0eXBlb2YgYXR0cmlidXRlcy5hdXRvUGFkID09ICd1bmRlZmluZWQnID8gMCA6IChhdHRyaWJ1dGVzLmF1dG9QYWQgYXMgbnVtYmVyKVxuICBdO1xuICBjb25zdCBkaWxhdGlvbnMgPSBhdHRyaWJ1dGVzLmRpbGF0aW9ucyBhcyBbbnVtYmVyLCBudW1iZXJdO1xuICBjb25zdCBncm91cCA9IGF0dHJpYnV0ZXMuZ3JvdXAgYXMgbnVtYmVyO1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUgYXMgW251bWJlciwgbnVtYmVyXTtcbiAgY29uc3QgcGFkcyA9IGF0dHJpYnV0ZXMucGFkcyBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgY29uc3Qgc3RyaWRlcyA9IGF0dHJpYnV0ZXMuc3RyaWRlcyBhcyBbbnVtYmVyLCBudW1iZXJdO1xuICBjb25zdCB3SXNDb25zdCA9IChhdHRyaWJ1dGVzLndJc0NvbnN0IGFzICgpID0+IGJvb2xlYW4pKCk7XG4gIGNvbnN0IG91dHB1dFBhZGRpbmcgPSBhdHRyaWJ1dGVzLm91dHB1dFBhZGRpbmcgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gYXR0cmlidXRlcy5vdXRwdXRTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdO1xuICByZXR1cm4ge1xuICAgIGF1dG9QYWQsXG4gICAgZm9ybWF0LFxuICAgIGRpbGF0aW9ucyxcbiAgICBncm91cCxcbiAgICBrZXJuZWxTaGFwZSxcbiAgICBvdXRwdXRQYWRkaW5nLFxuICAgIG91dHB1dFNoYXBlLFxuICAgIHBhZHMsXG4gICAgc3RyaWRlcyxcbiAgICB3SXNDb25zdCxcbiAgICAuLi5hY3RpdmF0aW9uQXR0cmlidXRlcyxcbiAgICBjYWNoZUtleTogYCR7YXR0cmlidXRlcy5mb3JtYXR9OyR7YWN0aXZhdGlvbkF0dHJpYnV0ZXMuYWN0aXZhdGlvbn07YCxcbiAgfTtcbn07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICAvLyBSZWZlciB0byB0aGUgYmVsb3cgbGluayBmb3IgYWxsIGlucHV0IGNoZWNrc1xuICAvLyBodHRwczovL2dpdGh1Yi5jb20vb25ueC9vbm54L2Jsb2IvbWFpbi9kb2NzL09wZXJhdG9ycy5tZCNDb252VHJhbnNwb3NlXG4gIGlmICghaW5wdXRzIHx8IChpbnB1dHMubGVuZ3RoICE9PSAyICYmIGlucHV0cy5sZW5ndGggIT09IDMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb252IHJlcXVpcmVzIDIgb3IgMyBpbnB1dHMnKTtcbiAgfVxuXG4gIC8vIFRPRE8gOiBOZWVkIHRvIGFkZCBzdXBwb3J0IGZvciBtdWx0aS1kaW1lbnNpb25hbCBjb252XG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDQgJiYgaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjdXJyZW50bHkgb25seSBzdXBwb3J0IDItZGltZW5zaW9uYWwgY29udicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdmaWx0ZXIgZG9lcyBub3QgaGF2ZSBzYW1lIGRpbWVuc2lvbiBhcyBpbnB1dCcpO1xuICB9XG5cbiAgLy8gRklMVEVSX0lOX0NIQU5ORUwgc2hvdWxkIGJlIGVxdWFsIHRvIERBVEFfQ0hBTk5FTFxuICBjb25zdCBkYXRhQ2hhbm5lbCA9IGlucHV0c1swXS5kaW1zW2F0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQycgPyBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAxIDogMV07XG4gIGNvbnN0IGZpbHRlckluQ2hhbm5lbCA9IGlucHV0c1sxXS5kaW1zWzBdO1xuICBpZiAoZGF0YUNoYW5uZWwgIT09IGZpbHRlckluQ2hhbm5lbCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRklMVEVSX0lOX0NIQU5ORUwgc2hvdWxkIGJlIGVxdWFsIHRvIERBVEFfQ0hBTk5FTCcpO1xuICB9XG5cbiAgY29uc3QgZmVhdHVyZU1hcHMgPSBpbnB1dHNbMV0uZGltc1sxXSAqIGF0dHJpYnV0ZXMuZ3JvdXA7XG5cbiAgLy8gaWYgYmlhcyBpcyBwcm92aWRlZCBpdCBzaG91bGQgYmUgMUQgYW5kIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgc2hvdWxkIGJlIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgZmVhdHVyZSBtYXBzXG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAzICYmIChpbnB1dHNbMl0uZGltcy5sZW5ndGggIT09IDEgfHwgaW5wdXRzWzJdLmRpbXNbMF0gIT09IGZlYXR1cmVNYXBzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBiaWFzJyk7XG4gIH1cblxuICBjb25zdCBzcGF0aWFsUmFuayA9IGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDI7XG4gIGNvbnN0IGRpbGF0aW9uc1NldCA9IGF0dHJpYnV0ZXMuZGlsYXRpb25zLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApID4gMDtcbiAgLy8gd3JvbmcgZGlsYXRpb25zIGRpbWVuc2lvblxuICBpZiAoZGlsYXRpb25zU2V0ICYmIGF0dHJpYnV0ZXMuZGlsYXRpb25zLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmspIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYGRpbGF0aW9ucyBzaG91bGQgYmUgJHtzcGF0aWFsUmFua31EYCk7XG4gIH1cblxuICBjb25zdCBzdHJpZGVzU2V0ID0gYXR0cmlidXRlcy5zdHJpZGVzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApID4gMDtcbiAgLy8gV3Jvbmcgc3RyaWRlcyBkaW1lbnNpb25cbiAgaWYgKHN0cmlkZXNTZXQgJiYgYXR0cmlidXRlcy5zdHJpZGVzLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmspIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHN0cmlkZXMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmt9RGApO1xuICB9XG5cbiAgLy8gV3JvbmcgcGFkcyBkaW1lbnNpb25cbiAgY29uc3QgcGFkc1NldCA9IGF0dHJpYnV0ZXMucGFkcy5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKSA+IDA7XG4gIGlmIChwYWRzU2V0ICYmIGF0dHJpYnV0ZXMucGFkcy5sZW5ndGggIT09IHNwYXRpYWxSYW5rICogMikge1xuICAgIHRocm93IG5ldyBFcnJvcihgcGFkcyBzaG91bGQgYmUgJHtzcGF0aWFsUmFuayAqIDJ9RGApO1xuICB9XG5cbiAgLy8gV3Jvbmcgb3V0cHV0IHBhZGRpbmcgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLm91dHB1dFBhZGRpbmcubGVuZ3RoICE9PSBzcGF0aWFsUmFuayAmJiBhdHRyaWJ1dGVzLm91dHB1dFBhZGRpbmcubGVuZ3RoICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBvdXRwdXRfcGFkZGluZyBzaG91bGQgYmUgJHtzcGF0aWFsUmFua31EYCk7XG4gIH1cblxuICAvLyBpZiBrZXJuZWxTaGFwZSBpcyBzcGVjaWZpZWQsIGl0J3MgZGF0YSBsZW5ndGggbXVzdCBiZSAyIGxlc3MgdGhhbiBkaW1zIGxlbmd0aCBvZiB0aGUgd2VpZ2h0cyB0ZW5zb3JcbiAgLy8gKHRoZSBmaXJzdCAyIGRpbXMgYXJlIGJhdGNoX3NpemUgYW5kIGNoYW5uZWxzKVxuICBjb25zdCBrZXJuZWxTaGFwZVNldCA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgPiAwO1xuICBpZiAoXG4gICAga2VybmVsU2hhcGVTZXQgJiZcbiAgICBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gMCAmJlxuICAgIGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoICE9PSBpbnB1dHNbMV0uZGltcy5sZW5ndGggLSAyXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBrZXJuZWwgc2hhcGUnKTtcbiAgfVxuXG4gIC8vIGFzIHdpdGgga2VybmVsU2hhcGUsIG11c3QgaGF2ZSBzYW1lIG51bWJlciBvZiBzcGF0aWFsIGRpbXMgYXMgaW5wdXRcbiAgaWYgKGF0dHJpYnV0ZXMub3V0cHV0U2hhcGUubGVuZ3RoICE9PSAwICYmIGF0dHJpYnV0ZXMub3V0cHV0U2hhcGUubGVuZ3RoICE9PSBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIG91dHB1dCBzaGFwZScpO1xuICB9XG59O1xuXG5jb25zdCBjb252VHJhbnNwb3NlMmQgPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMsXG4gIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uPzogKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4gbnVtYmVyW10sXG4pOiB2b2lkID0+IHtcbiAgLy8gU1RFUC4xOiB0cmFuc3Bvc2Ugd2VpZ2h0XG4gIGNvbnN0IHRyYW5zcG9zZWRXZWlnaHQgPVxuICAgIChjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QgYXMgVGVuc29yVmlldyB8IHVuZGVmaW5lZCkgPz9cbiAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8oaW5wdXRzWzFdLCBbMiwgMywgMCwgMV0pLCB7XG4gICAgICBpbnB1dHM6IFsxXSxcbiAgICAgIG91dHB1dHM6IFthdHRyaWJ1dGVzLndJc0NvbnN0ID8gLTIgOiAtMV0sXG4gICAgfSlbMF07XG4gIGlmIChhdHRyaWJ1dGVzLndJc0NvbnN0ICYmICFjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QpIHtcbiAgICBjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QgPSB0cmFuc3Bvc2VkV2VpZ2h0O1xuICB9XG5cbiAgLy8gU1RFUC4yOiBwcmVwYXJlIHJlc2hhcGVkIGlucHV0c1xuICBjb25zdCBjb252VHJhbnNwb3NlSW5wdXRzID0gW2lucHV0c1swXSwgdHJhbnNwb3NlZFdlaWdodF07XG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAzKSB7XG4gICAgY29udlRyYW5zcG9zZUlucHV0cy5wdXNoKGlucHV0c1syXSk7XG4gIH1cbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUNvbnZUcmFuc3Bvc2UyRFByb2dyYW1JbmZvKGNvbnZUcmFuc3Bvc2VJbnB1dHMsIGF0dHJpYnV0ZXMsIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uKSwge1xuICAgIGlucHV0czogY29udlRyYW5zcG9zZUlucHV0cyxcbiAgfSk7XG59O1xuXG5jb25zdCBjb252VHJhbnNwb3NlMWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIC8vIGV4dGVuZCB0aGUgaW5wdXQgdG8gMkQgYnkgYWRkaW5nIEggZGltZW5zaW9uXG4gIGNvbnN0IGlzQ2hhbm5lbExhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuXG4gIGNvbnN0IGlucHV0cyA9IFtcbiAgICBjb250ZXh0LmlucHV0c1swXS5yZXNoYXBlKFxuICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICA/IC8vIFtOLCBXLCBDXSAtPiBbTiwgSD0xLCBXLCBDXVxuICAgICAgICAgIFtjb250ZXh0LmlucHV0c1swXS5kaW1zWzBdLCAxLCBjb250ZXh0LmlucHV0c1swXS5kaW1zWzFdLCBjb250ZXh0LmlucHV0c1swXS5kaW1zWzJdXVxuICAgICAgICA6IC8vIFtOLCBDLCBXXSAtPiBbTiwgQywgSD0xLCBXXVxuICAgICAgICAgIFtjb250ZXh0LmlucHV0c1swXS5kaW1zWzBdLCBjb250ZXh0LmlucHV0c1swXS5kaW1zWzFdLCAxLCBjb250ZXh0LmlucHV0c1swXS5kaW1zWzJdXSxcbiAgICApLFxuICAgIC8vW0ZJTFRFUl9PVVRfQ0hBTk5FTCwgRklMVEVSX0lOX0NIQU5ORUwsIGtXXSAtPiBbRklMVEVSX09VVF9DSEFOTkVMLCBGSUxURVJfSU5fQ0hBTk5FTCwga0g9MSwga1ddXG4gICAgY29udGV4dC5pbnB1dHNbMV0ucmVzaGFwZShbY29udGV4dC5pbnB1dHNbMV0uZGltc1swXSwgY29udGV4dC5pbnB1dHNbMV0uZGltc1sxXSwgMSwgY29udGV4dC5pbnB1dHNbMV0uZGltc1syXV0pLFxuICBdO1xuICBpZiAoY29udGV4dC5pbnB1dHMubGVuZ3RoID09PSAzKSB7XG4gICAgaW5wdXRzLnB1c2goY29udGV4dC5pbnB1dHNbMl0pO1xuICB9XG4gIGxldCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGU7XG4gIGlmIChrZXJuZWxTaGFwZS5sZW5ndGggPT09IDAgfHwga2VybmVsU2hhcGVbMF0gPT09IDApIHtcbiAgICBrZXJuZWxTaGFwZSA9IFtjb250ZXh0LmlucHV0c1sxXS5kaW1zWzJdXTtcbiAgfVxuICBsZXQgZGlsYXRpb25zID0gYXR0cmlidXRlcy5kaWxhdGlvbnM7XG4gIGlmIChkaWxhdGlvbnMubGVuZ3RoID09PSAwIHx8IGRpbGF0aW9uc1swXSA9PT0gMCkge1xuICAgIGRpbGF0aW9ucyA9IFsxXTtcbiAgfVxuICBsZXQgc3RyaWRlcyA9IGF0dHJpYnV0ZXMuc3RyaWRlcztcbiAgaWYgKHN0cmlkZXMubGVuZ3RoID09PSAwIHx8IHN0cmlkZXNbMF0gPT09IDApIHtcbiAgICBzdHJpZGVzID0gWzFdO1xuICB9XG4gIGxldCBwYWRzID0gYXR0cmlidXRlcy5wYWRzO1xuICBpZiAocGFkcy5sZW5ndGggPT09IDApIHtcbiAgICBwYWRzID0gWzAsIDBdO1xuICB9XG4gIHBhZHMgPSBbMCwgcGFkc1swXSwgMCwgcGFkc1sxXV07XG4gIHN0cmlkZXMgPSBbMV0uY29uY2F0KHN0cmlkZXMpO1xuICBkaWxhdGlvbnMgPSBbMV0uY29uY2F0KGRpbGF0aW9ucyk7XG4gIGtlcm5lbFNoYXBlID0gWzFdLmNvbmNhdChrZXJuZWxTaGFwZSk7XG4gIGxldCBvdXRwdXRQYWRkaW5nID0gYXR0cmlidXRlcy5vdXRwdXRQYWRkaW5nO1xuICBvdXRwdXRQYWRkaW5nID0gWzBdLmNvbmNhdChvdXRwdXRQYWRkaW5nKTtcbiAgY29uc3QgYWRqdXN0ZWRBdHRyaWJ1dGVzID0gZ2V0QWRqdXN0ZWRDb252VHJhbnNwb3NlQXR0cmlidXRlcyhcbiAgICB7IC4uLmF0dHJpYnV0ZXMsIHBhZHMsIHN0cmlkZXMsIGRpbGF0aW9ucywga2VybmVsU2hhcGUsIG91dHB1dFBhZGRpbmcgfSxcbiAgICBpbnB1dHMsXG4gICk7XG5cbiAgY29udlRyYW5zcG9zZTJkKGNvbnRleHQsIGlucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzLCAob3V0cHV0U2hhcGUpID0+XG4gICAgaXNDaGFubmVsTGFzdCA/IFtvdXRwdXRTaGFwZVswXSwgb3V0cHV0U2hhcGVbMl0sIG91dHB1dFNoYXBlWzNdXSA6IFtvdXRwdXRTaGFwZVswXSwgb3V0cHV0U2hhcGVbMV0sIG91dHB1dFNoYXBlWzNdXSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBjb252VHJhbnNwb3NlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGlmIChjb250ZXh0LmlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gMykge1xuICAgIGNvbnZUcmFuc3Bvc2UxZChjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBhZGp1c3RlZEF0dHJpYnV0ZXMgPSBnZXRBZGp1c3RlZENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMsIGNvbnRleHQuaW5wdXRzKTtcbiAgICBjb252VHJhbnNwb3NlMmQoY29udGV4dCwgY29udGV4dC5pbnB1dHMsIGFkanVzdGVkQXR0cmlidXRlcyk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgZ2V0RWxlbWVudEF0LCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEN1bVN1bUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBleGNsdXNpdmU6IGJvb2xlYW47XG4gIHJlYWRvbmx5IHJldmVyc2U6IGJvb2xlYW47XG59XG5jb25zdCBjcmVhdGVDdW1zdW1Qcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRUeXBlOiBudW1iZXIsXG4gIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBheGlzSW5wdXQ6IFRlbnNvclZpZXcsXG4gIGF0dHJpYnV0ZXM6IEN1bVN1bUF0dHJpYnV0ZXMsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShpbnB1dFNoYXBlKTsgLy8gb3V0cHV0U2hhcGUgaXMgc2FtZSBhcyBpbnB1dFNoYXBlLlxuICBjb25zdCByYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7IC8vIGlucHV0L291dHB1dCByYW5rXG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBpbnB1dFR5cGUsIHJhbmspO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRUeXBlLCByYW5rKTtcbiAgY29uc3QgYXhpc1ZhbHVlID1cbiAgICBheGlzSW5wdXQuZGF0YVR5cGUgPT09IERhdGFUeXBlLmludDMyID8gYXhpc0lucHV0LmdldEludDMyQXJyYXkoKVswXSA6IE51bWJlcihheGlzSW5wdXQuZ2V0QmlnSW50NjRBcnJheSgpWzBdKTtcbiAgY29uc3QgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF4aXNWYWx1ZSwgcmFuayk7XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGluZGV4ID0gYCBpMzIoJHtpbnB1dC5pbmRpY2VzR2V0KCdpbnB1dEluZGljZXMnLCAndW5pZm9ybXMuYXhpcycpfSkgYDtcbiAgICBjb25zdCBtYXggPSBnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLmlucHV0X3NoYXBlJywgJ3VuaWZvcm1zLmF4aXMnLCByYW5rKTtcbiAgICBjb25zdCBsb3dlckxpbWl0ID0gYXR0cmlidXRlcy5yZXZlcnNlID8gaW5kZXggKyAoYXR0cmlidXRlcy5leGNsdXNpdmUgPyAnICsgMScgOiAnJykgOiAnMCc7XG4gICAgY29uc3QgdXBwZXJMaW1pdCA9IGF0dHJpYnV0ZXMucmV2ZXJzZSA/IG1heCA6IGluZGV4ICsgKGF0dHJpYnV0ZXMuZXhjbHVzaXZlID8gJycgOiAnICsgMScpO1xuICAgIHJldHVybiBgXG4gICAgICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXJcbiAgICAgICAgICAgICAgICAgIC5yZWdpc3RlclVuaWZvcm0oJ291dHB1dFNpemUnLCAndTMyJylcbiAgICAgICAgICAgICAgICAgIC5yZWdpc3RlclVuaWZvcm0oJ2F4aXMnLCAndTMyJylcbiAgICAgICAgICAgICAgICAgIC5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBvdXRwdXQpfVxuICAgICAgICAgICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0U2l6ZScpfVxuICAgICAgICAgICAgICAgICAgdmFyIGlucHV0SW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgICAgICAgICAgICAgIHZhciBzdW0gPSAke291dHB1dC50eXBlLnZhbHVlfSgwKTtcbiAgICAgICAgICAgICAgICAgIGxldCBmaXJzdCA6IGkzMiA9ICR7bG93ZXJMaW1pdH07XG4gICAgICAgICAgICAgICAgICBsZXQgbGFzdCA6IGkzMiA9ICR7dXBwZXJMaW1pdH07XG4gICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIDogaTMyID0gZmlyc3Q7IGkgPCBsYXN0OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dEluZGljZXMnLCAndW5pZm9ybXMuYXhpcycsICd1MzIoaSknKX07XG4gICAgICAgICAgICAgICAgICAgIHN1bSA9IHN1bSArICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dEluZGljZXMnKX07XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICdzdW0nKX07XG4gICAgICAgICAgICAgICAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0N1bVN1bScsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYXR0cmlidXRlcy5jYWNoZUtleSwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IGlucHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dFR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXM6IFtcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF4aXMgfSxcbiAgICAgICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRTaGFwZSwgaW5wdXRTaGFwZSksXG4gICAgICBdLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBjdW1zdW0gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEN1bVN1bUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGNvbnRleHQuaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGlucHV0VHlwZSA9IGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlO1xuICBjb25zdCBheGlzID0gY29udGV4dC5pbnB1dHNbMV07XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVDdW1zdW1Qcm9ncmFtSW5mbyhpbnB1dFR5cGUsIGlucHV0U2hhcGUsIGF4aXMsIGF0dHJpYnV0ZXMpLCB7IGlucHV0czogWzBdIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQ3VtU3VtQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEN1bVN1bUF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBleGNsdXNpdmUgPSAoYXR0cmlidXRlcy5leGNsdXNpdmUgYXMgbnVtYmVyKSA9PT0gMTtcbiAgY29uc3QgcmV2ZXJzZSA9IChhdHRyaWJ1dGVzLnJldmVyc2UgYXMgbnVtYmVyKSA9PT0gMTtcbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IGV4Y2x1c2l2ZSwgcmV2ZXJzZSB9KTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgSW5kaWNlc0hlbHBlciwgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBGb3JtYXRBdHRyaWJ1dGVzIHtcbiAgcmVhZG9ubHkgZm9ybWF0OiAnTkhXQycgfCAnTkNIVyc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVwdGhUb1NwYWNlQXR0cmlidXRlcyBleHRlbmRzIEZvcm1hdEF0dHJpYnV0ZXMsIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGJsb2Nrc2l6ZTogbnVtYmVyO1xuICByZWFkb25seSBtb2RlOiBzdHJpbmc7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0RlcHRoVG9TcGFjZSByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0RlcHRoVG9TcGFjZSByZXF1aXJlcyA0RCBpbnB1dC4nKTtcbiAgfVxufTtcblxuY29uc3QgcGVybUZ1bmN0aW9uQm9keSA9IChwZXJtOiBudW1iZXJbXSwgcmFuazogbnVtYmVyLCBpbnB1dDogSW5kaWNlc0hlbHBlciwgb3V0cHV0OiBJbmRpY2VzSGVscGVyKTogc3RyaW5nID0+IHtcbiAgY29uc3QgcmV2ZXJzZUZ1bmMgPSBbXTtcbiAgcmV2ZXJzZUZ1bmMucHVzaChgZm4gcGVybShpOiAke291dHB1dC50eXBlLmluZGljZXN9KSAtPiAke2lucHV0LnR5cGUuaW5kaWNlc30ge1xuICAgIHZhciBhOiAke2lucHV0LnR5cGUuaW5kaWNlc307YCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuazsgKytpKSB7XG4gICAgcmV2ZXJzZUZ1bmMucHVzaChpbnB1dC5pbmRpY2VzU2V0KCdhJywgcGVybVtpXSwgYGlbJHtpfV1gKSk7XG4gIH1cbiAgcmV2ZXJzZUZ1bmMucHVzaCgncmV0dXJuIGE7fScpO1xuICByZXR1cm4gcmV2ZXJzZUZ1bmMuam9pbignXFxuJyk7XG59O1xuXG5jb25zdCBjcmVhdGVEZXB0aFRvU3BhY2VQcm9ncmFtSW5mbyA9IChpbnB1dFRlbnNvcjogVGVuc29yVmlldywgYXR0cmlidXRlczogRGVwdGhUb1NwYWNlQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgbGV0IG46IG51bWJlciwgaDogbnVtYmVyLCB3OiBudW1iZXIsIGM6IG51bWJlcjtcbiAgbGV0IHNoYXBlOiBudW1iZXJbXTtcbiAgbGV0IHBlcm06IG51bWJlcltdO1xuICBjb25zdCBpc0NoYW5uZWxMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3QgYmxvY2tzaXplID0gYXR0cmlidXRlcy5ibG9ja3NpemU7XG4gIGNvbnN0IGlzRENSbW9kZSA9IGF0dHJpYnV0ZXMubW9kZSA9PT0gJ0RDUic7XG4gIGlmIChpc0NoYW5uZWxMYXN0KSB7XG4gICAgW24sIGgsIHcsIGNdID0gaW5wdXRUZW5zb3IuZGltcztcbiAgICBzaGFwZSA9IGlzRENSbW9kZVxuICAgICAgPyBbbiwgaCwgdywgYmxvY2tzaXplLCBibG9ja3NpemUsIGMgLyBibG9ja3NpemUgKiogMl1cbiAgICAgIDogW24sIGgsIHcsIGMgLyBibG9ja3NpemUgKiogMiwgYmxvY2tzaXplLCBibG9ja3NpemVdO1xuICAgIHBlcm0gPSBpc0RDUm1vZGUgPyBbMCwgMSwgMywgMiwgNCwgNV0gOiBbMCwgMSwgNCwgMiwgNSwgM107XG4gIH0gZWxzZSB7XG4gICAgW24sIGgsIHcsIGNdID0gW2lucHV0VGVuc29yLmRpbXNbMF0sIGlucHV0VGVuc29yLmRpbXNbMl0sIGlucHV0VGVuc29yLmRpbXNbM10sIGlucHV0VGVuc29yLmRpbXNbMV1dO1xuICAgIHNoYXBlID0gaXNEQ1Jtb2RlXG4gICAgICA/IFtuLCBibG9ja3NpemUsIGJsb2Nrc2l6ZSwgYyAvIGJsb2Nrc2l6ZSAqKiAyLCBoLCB3XVxuICAgICAgOiBbbiwgYyAvIGJsb2Nrc2l6ZSAqKiAyLCBibG9ja3NpemUsIGJsb2Nrc2l6ZSwgaCwgd107XG4gICAgcGVybSA9IGlzRENSbW9kZSA/IFswLCAzLCA0LCAxLCA1LCAyXSA6IFswLCAxLCA0LCAyLCA1LCAzXTtcbiAgfVxuICBjb25zdCByZXNoYXBlZElucHV0VGVuc29yID0gaW5wdXRUZW5zb3IucmVzaGFwZShzaGFwZSk7XG4gIGNvbnN0IHJlc2hhcGVkSW5wdXRSYW5rID0gcmVzaGFwZWRJbnB1dFRlbnNvci5kaW1zLmxlbmd0aDtcbiAgY29uc3QgaW5wdXREYXRhVHlwZSA9IGlucHV0VGVuc29yLmRhdGFUeXBlO1xuXG4gIGNvbnN0IHJlc2hhcGVkSW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdhJywgaW5wdXREYXRhVHlwZSwgcmVzaGFwZWRJbnB1dFJhbmspO1xuICBjb25zdCBwZXJtZWRPdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXREYXRhVHlwZSwgcmVzaGFwZWRJbnB1dFJhbmspO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dF9zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMocmVzaGFwZWRJbnB1dCwgcGVybWVkT3V0cHV0KX1cblxuICAke3Blcm1GdW5jdGlvbkJvZHkocGVybSwgcmVzaGFwZWRJbnB1dFJhbmssIHJlc2hhcGVkSW5wdXQsIHBlcm1lZE91dHB1dCl9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cblxuICAgIGxldCBpbmRpY2VzID0gJHtwZXJtZWRPdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgIGxldCBhSW5kaWNlcyA9IHBlcm0oaW5kaWNlcyk7XG5cbiAgICAke3Blcm1lZE91dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsIHJlc2hhcGVkSW5wdXQuZ2V0QnlJbmRpY2VzKCdhSW5kaWNlcycpKX1cbiAgfWA7XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnRGVwdGhUb1NwYWNlJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7aW5wdXRUZW5zb3IuZGltc307JHthdHRyaWJ1dGVzLmJsb2Nrc2l6ZX07JHthdHRyaWJ1dGVzLm1vZGV9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6IChpbnB1dHMpID0+IHtcbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlID0gaXNDaGFubmVsTGFzdFxuICAgICAgICA/IFtuLCBoICogYmxvY2tzaXplLCB3ICogYmxvY2tzaXplLCBjIC8gYmxvY2tzaXplICoqIDJdXG4gICAgICAgIDogW24sIGMgLyBibG9ja3NpemUgKiogMiwgaCAqIGJsb2Nrc2l6ZSwgdyAqIGJsb2Nrc2l6ZV07XG4gICAgICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICAgICAgY29uc3Qgc2hhcGVCZWZvcmVQZXJtID0gcmVzaGFwZWRJbnB1dFRlbnNvci5kaW1zO1xuICAgICAgY29uc3Qgc2hhcGVBZnRlclBlcm0gPSBTaGFwZVV0aWwuc29ydEJhc2VkT25QZXJtKHNoYXBlQmVmb3JlUGVybSwgcGVybSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXM6IFtcbiAgICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgICAgICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKHNoYXBlQmVmb3JlUGVybSwgc2hhcGVBZnRlclBlcm0pLFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBkZXB0aFRvU3BhY2UgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IERlcHRoVG9TcGFjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRGVwdGhUb1NwYWNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sIGF0dHJpYnV0ZXMpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZURlcHRoVG9TcGFjZUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBEZXB0aFRvU3BhY2VBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7XG4gICAgYmxvY2tzaXplOiBhdHRyaWJ1dGVzLmJsb2Nrc2l6ZSBhcyBudW1iZXIsXG4gICAgbW9kZTogYXR0cmlidXRlcy5tb2RlIGFzIHN0cmluZyxcbiAgICBmb3JtYXQ6IGF0dHJpYnV0ZXMuZm9ybWF0IGFzICdOSFdDJyB8ICdOQ0hXJyxcbiAgfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWluc3VtQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGVxdWF0aW9uOiBzdHJpbmc7XG59XG4vLyBUaGUgZXF1YXRpb24gYXR0cmlidXRlIHZhbHVlIGlzIGEgc3RyaW5nIHdoaWNoIGNvbnNpc3RzIG9mIGxlZnQgaGFuZCBzaWRlIChMSFMpIGFuZCBvcHRpb25hbGx5IHJpZ2h0IGhhbmQgc2lkZSAoUkhTKVxuLy8gc2VwYXJhdGVkIGJ5ICctPicuIEV4LiBcImlqLGprIC0+IGlrXCIgZXhwcmVzc2VzIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuLy8gICAgIFwiaWotPmppXCIgZXhwcmVzc2VzIG1hdHJpeCB0cmFuc3Bvc2Vcbi8vICAgICAgXCJpaS0+aVwiIGRpYWdvbmFsIGVsZW1lbnRzIG9mIGEgc3F1YXJlIG1hdHJpeFxuLy8gTEhTIGNvbnNpc3RzIG9mIGEgc2VxdWVuY2Ugb2YgdGVybXMgc2VwYXJhdGVkIGJ5IGNvbW1hcy4gRWFjaCB0ZXJtIGNvcnJlc3BvbmRzIHRvIGFuIGlucHV0IHZhcmlhYmxlLlxuLy8gRWFjaCBzeW1ib2wgY29ycmVzcG9uZHMgdG8gYSBkaW1lbnNpb24gaW4gdGhlIGlucHV0IHZhcmlhYmxlLiBUaGUgc3ltYm9sIGNhbiBiZSBlaXRoZXIgYSBsZXR0ZXIsICdhJyB0byAneicgb3IgJ0EnIHRvXG4vLyAnWicgb3IgJy4uLicgdG8gcmVwcmVzZW50IGFyYml0cmFyeSBkaW1lbnNpb25zLlxuXG5jb25zdCBzeW1ib2xQYXR0ZXJuID0gJ1thLXpBLVpdfFxcXFwuXFxcXC5cXFxcLic7IC8vIFRoZSBwYXR0ZXJuIGVhY2ggc3ltYm9sIGluIGVhY2ggdGVybSBpbiB0aGUgc3ltYm9saWMgZXF1YXRpb24gc2hvdWxkIG1hdGNoXG5jb25zdCB0ZXJtUGF0dGVybiA9ICcoJyArIHN5bWJvbFBhdHRlcm4gKyAnKSsnOyAvLyBUaGUgcGF0dGVybiBlYWNoIHRlcm0gaW4gdGhlIHN5bWJvbGljIGVxdWF0aW9uIHNob3VsZCBtYXRjaFxuY29uc3QgdGVybVBhdHRlcm5Pbmx5ID0gJ14nICsgdGVybVBhdHRlcm4gKyAnJCc7IC8vIFRoZSBwYXR0ZXJucyBvbmx5IG1hdGNocyBhIHRlcm0gYmVnaW4gdG8gZW5kLlxuY29uc3QgbGhzUGF0dGVybiA9ICcoJyArIHRlcm1QYXR0ZXJuICsgJywpKicgKyB0ZXJtUGF0dGVybjsgLy8gVGhlIHBhdHRlcm4gdGhlIExIUyBzaG91bGQgbWF0Y2hcbmNvbnN0IGxoc1BhdHRlcm5Pbmx5ID0gJ14nICsgbGhzUGF0dGVybiArICckJzsgLy8gVGhlIHBhdHRlcm5zIG9ubHkgbWF0Y2hzIGEgTEhTIGJlZ2luIHRvIGVuZC5cblxuaW50ZXJmYWNlIFN5bWJvbEluZm8ge1xuICBjb3VudDogbnVtYmVyOyAvLyBTeW1ib2wgY29ycmVzcG9uZGluZyB0byBhIGRpbW1lbnNpb24gb2YgYW4gaW5wdXRcbiAgaW5wdXRJbmRpY2VzOiBudW1iZXJbXTsgLy8gTnVtYmVyIG9mIGlucHV0IHZhcmlhYmxlcyB0aGUgc3ltYm9sIGNvcnJlc3BvbmRzIHRvXG4gIGRpbVZhbHVlOiBudW1iZXI7IC8vIE51bWJlciBvZiBkaW1lbnNpb25zIHRoZSBzeW1ib2wgY29ycmVzcG9uZHMgdG9cbn1cblxuY2xhc3MgRWluc3VtVGVybSB7XG4gIGNvbnN0cnVjdG9yKGlucHV0SW5kZXggPSAtMSkge1xuICAgIHRoaXMuc3ltYm9sVG9JbmRpY2VzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcltdPigpO1xuICAgIHRoaXMuaW5wdXRJbmRleCA9IGlucHV0SW5kZXg7XG4gIH1cblxuICAvLyBBZGQgYSBzeW1ib2wgdG8gdGhlIHRlcm1cbiAgYWRkU3ltYm9sKHN5bWJvbDogc3RyaW5nLCBpbmRleDogbnVtYmVyKSB7XG4gICAgbGV0IHZhbHVlID0gdGhpcy5zeW1ib2xUb0luZGljZXMuZ2V0KHN5bWJvbCk7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhbHVlID0gW2luZGV4XTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUucHVzaChpbmRleCk7XG4gICAgfVxuICAgIHRoaXMuc3ltYm9sVG9JbmRpY2VzLnNldChzeW1ib2wsIHZhbHVlKTtcbiAgfVxuXG4gIHN5bWJvbFRvSW5kaWNlczogTWFwPHN0cmluZywgbnVtYmVyW10+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/IGF0dHJpYnV0ZXMgOiBjcmVhdGVTcGxpdEF0dHJpYnV0ZXNGcm9tSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVNwbGl0UHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIHVwZGF0ZWRBdHRyaWJ1dGVzKSwgeyBpbnB1dHM6IFswXSB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZVNwbGl0QXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFNwbGl0QXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGF4aXMgPSBhdHRyaWJ1dGVzLmF4aXMgYXMgbnVtYmVyO1xuICBjb25zdCBzcGxpdFNpemVzOiBudW1iZXJbXSA9IGF0dHJpYnV0ZXMuc3BsaXRTaXplcyBhcyBudW1iZXJbXTtcbiAgY29uc3QgbnVtT3V0cHV0cyA9IChhdHRyaWJ1dGVzLm51bU91dHB1dHMgYXMgbnVtYmVyKSA8IDAgPyBzcGxpdFNpemVzLmxlbmd0aCA6IChhdHRyaWJ1dGVzLm51bU91dHB1dHMgYXMgbnVtYmVyKTtcbiAgaWYgKG51bU91dHB1dHMgIT09IHNwbGl0U2l6ZXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdudW1PdXRwdXRzIGFuZCBzcGxpdFNpemVzIGxlbmdoIG11c3QgYmUgZXF1YWwnKTtcbiAgfVxuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgYXhpcywgbnVtT3V0cHV0cywgc3BsaXRTaXplcyB9KTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyLCBXT1JLR1JPVVBfU0laRSB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzIHtcbiAgcmVhZG9ubHkgaW50ZXJsZWF2ZWQ6IGJvb2xlYW47XG4gIHJlYWRvbmx5IG51bUhlYWRzOiBudW1iZXI7XG4gIHJlYWRvbmx5IHJvdGFyeUVtYmVkZGluZ0RpbTogbnVtYmVyO1xuICByZWFkb25seSBzY2FsZTogbnVtYmVyO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBbaW5wdXQsIHBvc2l0aW9uSWRzLCBjb3NDYWNoZSwgc2luQ2FjaGVdID0gaW5wdXRzO1xuICBjb25zdCB7IG51bUhlYWRzLCByb3RhcnlFbWJlZGRpbmdEaW0gfSA9IGF0dHJpYnV0ZXM7XG5cbiAgaWYgKGlucHV0LmRpbXMubGVuZ3RoICE9PSAzICYmIGlucHV0LmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnB1dCAneCcgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAzIG9yIDQgZGltZW5zaW9ucywgZ290ICR7aW5wdXQuZGltcy5sZW5ndGh9YCk7XG4gIH1cbiAgaWYgKFxuICAgICFTaGFwZVV0aWwuYXJlRXF1YWwocG9zaXRpb25JZHMuZGltcywgW10pICYmXG4gICAgIVNoYXBlVXRpbC5hcmVFcXVhbChwb3NpdGlvbklkcy5kaW1zLCBbMV0pICYmXG4gICAgcG9zaXRpb25JZHMuZGltcy5sZW5ndGggIT09IDJcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnB1dCAncG9zaXRpb25faWRzJyBpcyBleHBlY3RlZCB0byBoYXZlIDAsIDEsIG9yIDIgZGltZW5zaW9ucywgZ290ICR7cG9zaXRpb25JZHMuZGltcy5sZW5ndGh9YCk7XG4gIH1cbiAgaWYgKGNvc0NhY2hlLmRpbXMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnB1dCAnY29zX2NhY2hlJyBpcyBleHBlY3RlZCB0byBoYXZlIDIgZGltZW5zaW9ucywgZ290ICR7Y29zQ2FjaGUuZGltcy5sZW5ndGh9YCk7XG4gIH1cbiAgaWYgKHNpbkNhY2hlLmRpbXMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnB1dCAnc2luX2NhY2hlJyBpcyBleHBlY3RlZCB0byBoYXZlIDIgZGltZW5zaW9ucywgZ290ICR7c2luQ2FjaGUuZGltcy5sZW5ndGh9YCk7XG4gIH1cbiAgaWYgKCFTaGFwZVV0aWwuYXJlRXF1YWwoY29zQ2FjaGUuZGltcywgc2luQ2FjaGUuZGltcykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnB1dHMgJ2Nvc19jYWNoZScgYW5kICdzaW5fY2FjaGUnIGFyZSBleHBlY3RlZCB0byBoYXZlIHRoZSBzYW1lIHNoYXBlXCIpO1xuICB9XG5cbiAgaWYgKHJvdGFyeUVtYmVkZGluZ0RpbSA+IDAgJiYgbnVtSGVhZHMgPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ251bV9oZWFkcyBtdXN0IGJlIHByb3ZpZGVkIGlmIHJvdGFyeV9lbWJlZGRpbmdfZGltIGlzIHNwZWNpZmllZCcpO1xuICB9XG5cbiAgY29uc3QgYmF0Y2hTaXplID0gaW5wdXQuZGltc1swXTtcbiAgY29uc3Qgc2VxdWVuY2VMZW5ndGggPSBpbnB1dC5kaW1zW2lucHV0LmRpbXMubGVuZ3RoIC0gMl07XG4gIGNvbnN0IG1heFNlcXVlbmNlTGVuZ3RoID0gY29zQ2FjaGUuZGltc1swXTtcbiAgY29uc3QgaGlkZGVuU2l6ZSA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbihpbnB1dC5kaW1zLCAxKSAvIHNlcXVlbmNlTGVuZ3RoO1xuICBjb25zdCBoZWFkU2l6ZSA9IHJvdGFyeUVtYmVkZGluZ0RpbSA9PT0gMCA/IGNvc0NhY2hlLmRpbXNbMV0gKiAyIDogaGlkZGVuU2l6ZSAvIG51bUhlYWRzO1xuICBpZiAocm90YXJ5RW1iZWRkaW5nRGltID4gaGVhZFNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3JvdGFyeV9lbWJlZGRpbmdfZGltIG11c3QgYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIGhlYWRfc2l6ZScpO1xuICB9XG5cbiAgaWYgKHBvc2l0aW9uSWRzLmRpbXMubGVuZ3RoID09PSAyKSB7XG4gICAgaWYgKGJhdGNoU2l6ZSAhPT0gcG9zaXRpb25JZHMuZGltc1swXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnB1dCAncG9zaXRpb25faWRzJyBkaW1lbnNpb24gMCBzaG91bGQgYmUgb2Ygc2l6ZSBiYXRjaF9zaXplLCBnb3QgJHtwb3NpdGlvbklkcy5kaW1zWzBdfWApO1xuICAgIH1cbiAgICBpZiAoc2VxdWVuY2VMZW5ndGggIT09IHBvc2l0aW9uSWRzLmRpbXNbMV0pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgJ3Bvc2l0aW9uX2lkcycgZGltZW5zaW9uIDEgc2hvdWxkIGJlIG9mIHNpemUgc2VxdWVuY2VfbGVuZ3RoLCBnb3QgJHtwb3NpdGlvbklkcy5kaW1zWzFdfWApO1xuICAgIH1cbiAgfVxuXG4gIGlmIChoZWFkU2l6ZSAvIDIgIT09IGNvc0NhY2hlLmRpbXNbMV0gJiYgcm90YXJ5RW1iZWRkaW5nRGltIC8gMiAhPT0gY29zQ2FjaGUuZGltc1sxXSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBJbnB1dCAnY29zX2NhY2hlJyBkaW1lbnNpb24gMSBzaG91bGQgYmUgc2FtZSBhcyBoZWFkX3NpemUgLyAyIG9yIHJvdGFyeV9lbWJlZGRpbmdfZGltIC8gMiwgZ290ICR7XG4gICAgICAgIGNvc0NhY2hlLmRpbXNbMV1cbiAgICAgIH1gLFxuICAgICk7XG4gIH1cblxuICBpZiAoc2VxdWVuY2VMZW5ndGggPiBtYXhTZXF1ZW5jZUxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignVXBkYXRpbmcgY29zX2NhY2hlIGFuZCBzaW5fY2FjaGUgaW4gUm90YXJ5RW1iZWRkaW5nIGlzIG5vdCBjdXJyZW50bHkgc3VwcG9ydGVkJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVSb3RhcnlFbWJlZGRpbmdQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IFJvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXMsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IHsgaW50ZXJsZWF2ZWQsIG51bUhlYWRzLCByb3RhcnlFbWJlZGRpbmdEaW0sIHNjYWxlIH0gPSBhdHRyaWJ1dGVzO1xuICBjb25zdCBiYXRjaFNpemUgPSBpbnB1dHNbMF0uZGltc1swXTtcbiAgY29uc3QgYmF0Y2hTdHJpZGUgPSBTaGFwZVV0aWwuc2l6ZUZyb21EaW1lbnNpb24oaW5wdXRzWzBdLmRpbXMsIDEpO1xuICBjb25zdCBzZXF1ZW5jZUxlbmd0aCA9IGlucHV0c1swXS5kaW1zW2lucHV0c1swXS5kaW1zLmxlbmd0aCAtIDJdO1xuICBjb25zdCBoaWRkZW5TaXplID0gYmF0Y2hTdHJpZGUgLyBzZXF1ZW5jZUxlbmd0aDtcbiAgY29uc3QgaGFsZlJvdGFyeUVtYmVkZGluZ0RpbSA9IGlucHV0c1syXS5kaW1zWzFdO1xuICBjb25zdCBoZWFkU2l6ZSA9IHJvdGFyeUVtYmVkZGluZ0RpbSA9PT0gMCA/IGhhbGZSb3RhcnlFbWJlZGRpbmdEaW0gKiAyIDogaGlkZGVuU2l6ZSAvIG51bUhlYWRzO1xuXG4gIC8vIFJvdGFyeSBlbWJlZGRpbmdzIHdpbGwgYmUgY2FsY3VsYXRlZCBpbiBhIHBhaXItd2lzZSBmYXNoaW9uLiBJbiBhY2NvcmRhbmNlLCB1c2UgdGhlIHNoYXBlXG4gIC8vIFtiYXRjaCBzaXplLCBzZXF1ZW5jZSBsZW5ndGgsIG51bSBvZiBoZWFkcywgbnVtIG9mIHBhaXJzIHRvIHJvdGF0ZSArIG51bSBvZiBkaW1zIHRvIGNvcHldXG4gIC8vIHRvIHVuZm9sZCB0aGUgZ2xvYmFsIGluZGV4IGluIHNoYWRlci5cbiAgY29uc3QgZ2xvYmFsU2hhcGUgPSBuZXcgQXJyYXk8bnVtYmVyPihcbiAgICBiYXRjaFNpemUsXG4gICAgc2VxdWVuY2VMZW5ndGgsXG4gICAgaGlkZGVuU2l6ZSAvIGhlYWRTaXplLFxuICAgIGhlYWRTaXplIC0gaGFsZlJvdGFyeUVtYmVkZGluZ0RpbSxcbiAgKTtcbiAgY29uc3QgZ2xvYmFsU3RyaWRlcyA9IFNoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhnbG9iYWxTaGFwZSk7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IHNjYWxlIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGdsb2JhbFNoYXBlIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGdsb2JhbFN0cmlkZXMgfSxcblxuICAgIC8vIHN0cmlkZXMgZm9yIGFkZHJlc3NpbmcgdGhlIGlucHV0L291dHB1dCB0ZW5zb3IsIGluIHBlcm11dGF0ZWQgb3JkZXIgdG8gYWxpZ24gd2l0aCB0aGUgdW5mb2xkZWQgZ2xvYmFsIGluZGV4LFxuICAgIC8vIGkuZS4gQlNOSFxuICAgIC4uLihpbnB1dHNbMF0uZGltcy5sZW5ndGggPT09IDNcbiAgICAgID8gbmV3IEFycmF5PFByb2dyYW1Vbmlmb3JtPih7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogW2JhdGNoU3RyaWRlLCBoaWRkZW5TaXplLCBoZWFkU2l6ZSwgMV0gfSlcbiAgICAgIDogW10pLFxuICAgIC4uLihpbnB1dHNbMF0uZGltcy5sZW5ndGggPT09IDRcbiAgICAgID8gbmV3IEFycmF5PFByb2dyYW1Vbmlmb3JtPih7XG4gICAgICAgICAgdHlwZTogRGF0YVR5cGUudWludDMyLFxuICAgICAgICAgIGRhdGE6IFtiYXRjaFN0cmlkZSwgaGVhZFNpemUsIHNlcXVlbmNlTGVuZ3RoICogaGVhZFNpemUsIDFdLFxuICAgICAgICB9KVxuICAgICAgOiBbXSksXG5cbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgaW5wdXRzWzFdLmRpbXMsIGlucHV0c1syXS5kaW1zLCBpbnB1dHNbM10uZGltcywgaW5wdXRzWzBdLmRpbXMpLFxuICBdO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgcG9zaXRpb25JZHMgPSBpbnB1dFZhcmlhYmxlKCdwb3NpdGlvbl9pZHMnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgY29zQ2FjaGUgPSBpbnB1dFZhcmlhYmxlKCdjb3NfY2FjaGUnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3Qgc2luQ2FjaGUgPSBpbnB1dFZhcmlhYmxlKCdzaW5fY2FjaGUnLCBpbnB1dHNbM10uZGF0YVR5cGUsIGlucHV0c1szXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcblxuICAgIHNoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKFtcbiAgICAgIHsgbmFtZTogJ3NjYWxlJywgdHlwZTogJ2YzMicgfSxcbiAgICAgIHsgbmFtZTogJ2dsb2JhbF9zaGFwZScsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGdsb2JhbFNoYXBlLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnZ2xvYmFsX3N0cmlkZXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBnbG9iYWxTdHJpZGVzLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnaW5wdXRfb3V0cHV0X3N0cmlkZXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBnbG9iYWxTdHJpZGVzLmxlbmd0aCB9LFxuICAgIF0pO1xuXG4gICAgcmV0dXJuIGBcbiAgICAgICAgJHtzaGFkZXJIZWxwZXIuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgcG9zaXRpb25JZHMsIGNvc0NhY2hlLCBzaW5DYWNoZSwgb3V0cHV0KX1cblxuICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoV09SS0dST1VQX1NJWkUpfVxuICAgICAgICAgIGxldCBoYWxmX3JvdGFyeV9lbWJfZGltID0gdW5pZm9ybXMuJHtjb3NDYWNoZS5uYW1lfV9zaGFwZVsxXTtcbiAgICAgICAgICBsZXQgYnNuaCA9IGdsb2JhbF9pZHggLyB1bmlmb3Jtcy5nbG9iYWxfc3RyaWRlcyAlIHVuaWZvcm1zLmdsb2JhbF9zaGFwZTtcbiAgICAgICAgICBsZXQgc2l6ZSA9IHVuaWZvcm1zLmdsb2JhbF9zaGFwZVswXSAqIHVuaWZvcm1zLmdsb2JhbF9zdHJpZGVzWzBdO1xuICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3NpemUnKX1cblxuICAgICAgICAgIGlmIChic25oWzNdIDwgaGFsZl9yb3RhcnlfZW1iX2RpbSkge1xuICAgICAgICAgICAgbGV0IHBvc2l0aW9uX2lkc19pZHggPVxuICAgICAgICAgICAgICAgICR7cG9zaXRpb25JZHMuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoJ2JzbmgueHknLCBvdXRwdXRWYXJpYWJsZSgnJywgcG9zaXRpb25JZHMudHlwZS50ZW5zb3IsIDIpKX07XG4gICAgICAgICAgICBsZXQgcG9zaXRpb25faWQgPVxuICAgICAgICAgICAgICAgIHUzMigke3Bvc2l0aW9uSWRzLmdldEJ5T2Zmc2V0KCdwb3NpdGlvbl9pZHNfaWR4Jyl9KSArIHNlbGVjdCgwLCBic25oWzFdLCBwb3NpdGlvbl9pZHNfaWR4ID09IDApO1xuICAgICAgICAgICAgbGV0IGkgPSBkb3QoYnNuaCwgdW5pZm9ybXMuaW5wdXRfb3V0cHV0X3N0cmlkZXMpICsgc2VsZWN0KDAsIGJzbmhbM10sICR7aW50ZXJsZWF2ZWR9KTtcbiAgICAgICAgICAgIGxldCBqID0gaSArIHNlbGVjdChoYWxmX3JvdGFyeV9lbWJfZGltLCAxLCAke2ludGVybGVhdmVkfSk7XG4gICAgICAgICAgICBsZXQgcmUgPSAke2lucHV0LmdldEJ5T2Zmc2V0KCdpJyl9ICogJHtjb3NDYWNoZS5nZXQoJ3Bvc2l0aW9uX2lkJywgJ2JzbmhbM10nKX0gLVxuICAgICAgICAgICAgICAgICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2onKX0gKiAke3NpbkNhY2hlLmdldCgncG9zaXRpb25faWQnLCAnYnNuaFszXScpfTtcbiAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdpJywgJ3JlJyl9XG4gICAgICAgICAgICBsZXQgaW0gPSAke2lucHV0LmdldEJ5T2Zmc2V0KCdpJyl9ICogJHtzaW5DYWNoZS5nZXQoJ3Bvc2l0aW9uX2lkJywgJ2JzbmhbM10nKX0gK1xuICAgICAgICAgICAgICAgICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2onKX0gKiAke2Nvc0NhY2hlLmdldCgncG9zaXRpb25faWQnLCAnYnNuaFszXScpfTtcbiAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdqJywgJ2ltJyl9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBrID0gZG90KGJzbmgsIHVuaWZvcm1zLmlucHV0X291dHB1dF9zdHJpZGVzKSArIGhhbGZfcm90YXJ5X2VtYl9kaW07XG4gICAgICAgICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnaycsIGlucHV0LmdldEJ5T2Zmc2V0KCdrJykpfVxuICAgICAgICAgIH1cbiAgICAgICAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnUm90YXJ5RW1iZWRkaW5nJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtcbiAgICAgICAgaW50ZXJsZWF2ZWQsXG4gICAgICB9KS5jYWNoZUtleSxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnLCAncmFuaycsICdyYW5rJywgJ3JhbmsnXSxcbiAgICB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogaW5wdXRzWzBdLmRpbXMsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShnbG9iYWxTaGFwZSkgLyBXT1JLR1JPVVBfU0laRSkgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCByb3RhcnlFbWJlZGRpbmcgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlUm90YXJ5RW1iZWRkaW5nUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuXG5pbXBvcnQgeyBhcHBseUF0dGVudGlvbiwgQXR0ZW50aW9uTWFza1R5cGUsIEF0dGVudGlvblBhcmFtZXRlcnMsIEF0dGVudGlvblFrdkZvcm1hdCB9IGZyb20gJy4vYXR0ZW50aW9uJztcbmltcG9ydCB7IG1heWJlVHJhbnNwb3NlVG9CTlNIQW5kQWRkQmlhcyB9IGZyb20gJy4vbXVsdGloZWFkLWF0dGVudGlvbic7XG5pbXBvcnQgeyBjcmVhdGVTcGxpdFByb2dyYW1JbmZvLCBTcGxpdEF0dHJpYnV0ZXMgfSBmcm9tICcuL3NwbGl0JztcbmltcG9ydCB7IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvLCBUcmFuc3Bvc2VBdHRyaWJ1dGVzIH0gZnJvbSAnLi90cmFuc3Bvc2UnO1xuaW1wb3J0IHsgUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcywgY3JlYXRlUm90YXJ5RW1iZWRkaW5nUHJvZ3JhbUluZm8gfSBmcm9tICcuL3JvdGFyeS1lbWJlZGRpbmcnO1xuaW1wb3J0IHsgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciwgVW5pZm9ybXNBcnJheVR5cGUgfSBmcm9tICcuL2NvbW1vbic7XG5leHBvcnQgaW50ZXJmYWNlIEdyb3VwUXVlcnlBdHRlbnRpb25BdHRyaWJ1dGVzIHtcbiAgbnVtSGVhZHM6IG51bWJlcjtcbiAga3ZOdW1IZWFkczogbnVtYmVyO1xuICBzY2FsZTogbnVtYmVyO1xuICBzb2Z0Y2FwOiBudW1iZXI7XG4gIGRvUm90YXJ5OiBudW1iZXI7XG4gIHJvdGFyeUludGVybGVhdmVkOiBudW1iZXI7XG4gIHNtb290aFNvZnRtYXg6IGJvb2xlYW47XG4gIGxvY2FsV2luZG93U2l6ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBHcm91cFF1ZXJ5QXR0ZW50aW9uQXR0cmlidXRlcyxcbik6IEF0dGVudGlvblBhcmFtZXRlcnMgPT4ge1xuICBpZiAoYXR0cmlidXRlcy5kb1JvdGFyeSAmJiBpbnB1dHMubGVuZ3RoIDw9IDcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nvc19jYWNoZSBhbmQgc2luX2NhY2hlIGlucHV0cyBhcmUgcmVxdWlyZWQgaWYgZG9fcm90YXJ5IGlzIHNwZWNpZmllZCcpO1xuICB9XG4gIGNvbnN0IHF1ZXJ5ID0gaW5wdXRzWzBdO1xuICBjb25zdCBrZXkgPSBpbnB1dHNbMV07XG4gIGNvbnN0IHZhbHVlID0gaW5wdXRzWzJdO1xuICBjb25zdCBwYXN0S2V5ID0gaW5wdXRzWzNdO1xuICBjb25zdCBwYXN0VmFsdWUgPSBpbnB1dHNbNF07XG4gIGlmIChhdHRyaWJ1dGVzLmRvUm90YXJ5ICE9PSAwICYmIGlucHV0cy5sZW5ndGggPD0gNykge1xuICAgIHRocm93IG5ldyBFcnJvcignY29zX2Nhc3QgYW5kIHNpbl9jYWNoZSBhcmUgZXhwZWN0ZWQgaWYgZG9fcm90YXJ5IGF0dHJpYnV0ZSBpcyBub24temVybycpO1xuICB9XG4gIGlmIChhdHRyaWJ1dGVzLmxvY2FsV2luZG93U2l6ZSAhPT0gLTEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvY2FsIGF0dGVudGlvbiBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbiAgaWYgKGF0dHJpYnV0ZXMuc29mdGNhcCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignU29mdGNhcCBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbiAgaWYgKGF0dHJpYnV0ZXMucm90YXJ5SW50ZXJsZWF2ZWQgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1JvdGFyeSBpbnRlcmxlYXZlZCBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbiAgaWYgKGF0dHJpYnV0ZXMuc21vb3RoU29mdG1heCkge1xuICAgIHRocm93IG5ldyBFcnJvcignU21vb3RoIHNvZnRtYXggaXMgbm90IHN1cHBvcnRlZCcpO1xuICB9XG4gIC8vIEFiYnJldmlhdGlvbiBhbmQgTWVhbmluZ3M6XG4gIC8vICAgQjogICAgYmF0Y2hfc2l6ZVxuICAvLyAgIFM6ICAgIHNlcXVlbmNlX2xlbmd0aCAoaW5wdXQgc2VxdWVuY2UgbGVuZ3RoIG9mIHF1ZXJ5KVxuICAvLyAgIFA6ICAgIHBhc3Rfc2VxdWVuY2VfbGVuZ3RoIChwYXN0IHNlcXVlbmNlIGxlbmd0aCBvZiBrZXkgb3IgdmFsdWUpXG4gIC8vICAgTDogICAga3Zfc2VxdWVuY2VfbGVuZ3RoIChpbnB1dCBzZXF1ZW5jZSBsZW5ndGggb2Yga2V5IG9yIHZhbHVlKVxuICAvLyAgIE06ICAgIG1heF9zZXF1ZW5jZV9sZW5ndGhcbiAgLy8gICBUOiAgICB0b3RhbF9zZXF1ZW5jZV9sZW5ndGggPSBwYXN0X3NlcXVlbmNlX2xlbmd0aCArIGt2X3NlcXVlbmNlX2xlbmd0aFxuICAvLyAgIE46ICAgIG51bV9oZWFkc1xuICAvLyAgIEg6ICAgIGhlYWQgc2l6ZSBmb3IgUSBhbmQgSywgYWthIHFfaGVhZF9zaXplIG9yIGtfaGVhZF9zaXplIG9yIHFrX2hlYWRfc2l6ZVxuICAvLyAgIEhfdjogIHZfaGVhZF9zaXplXG4gIC8vICAgRF9pOiAgaW5wdXQgaGlkZGVuIHNpemVcbiAgLy8gICBEOiAgICBoaWRkZW4gc2l6ZSBmb3IgUSBhbmQgSyAoRCA9IE4gKiBIKSwgYWthIHFfaGlkZGVuX3NpemUgb3Iga19oaWRkZW5fc2l6ZSBvciBxa19oaWRkZW5fc2l6ZVxuICAvLyAgIERfdjogIHZfaGlkZGVuX3NpemUgPSBudW1faGVhZHMgKiB2X2hlYWRfc2l6ZVxuXG4gIC8vICAgICBwYXN0X2tleSAgICAgICAgICAgICAgICAgICA6IChCLCBOLCBTKiwgSClcbiAgLy8gICAgIHBhc3RfdmFsdWUgICAgICAgICAgICAgICAgIDogKEIsIE4sIFMqLCBIKVxuICAvLyBXaGVuIG5vIHBhY2tpbmcgZm9yIHEvay92OlxuICAvLyAgICAgcXVlcnkgICAgICAgICAgICAoUSkgICAgICAgOiAoQiwgUywgRClcbiAgLy8gICAgIGtleSAgICAgICAgICAgICAgKEspICAgICAgIDogKEIsIEwsIEQpIG9yIChCLCBOLCBTKiwgSClcbiAgLy8gICAgIHZhbHVlICAgICAgICAgICAgKFYpICAgICAgIDogKEIsIEwsIERfdikgb3IgKEIsIE4sIFMqLCBIKVxuICAvLyBXaGVuIHBhY2tlZCBrdiBpcyB1c2VkOlxuICAvLyAgICAgcXVlcnkgICAgICAgICAgICAoUSkgICAgICAgOiAoQiwgUywgRClcbiAgLy8gICAgIGtleSAgICAgICAgICAgICAgKEspICAgICAgIDogKEIsIEwsIE4sIDIsIEgpXG4gIC8vICAgICB2YWx1ZSAgICAgICAgICAgIChWKSAgICAgICA6IE5vbmVcbiAgLy8gV2hlbiBwYWNrZWQgcWt2IGlzIHVzZWQ6XG4gIC8vICAgICBxdWVyeSAgICAgICAgICAgIChRKSAgICAgICA6IChCLCBMLCBOLCAzLCBIKSBvciAoQiwgUywgMypEKVxuICAvLyAgICAga2V5ICAgICAgICAgICAgICAoSykgICAgICAgOiBOb25lXG4gIC8vICAgICB2YWx1ZSAgICAgICAgICAgIChWKSAgICAgICA6IE5vbmVcblxuICBpZiAocXVlcnkuZGltcy5sZW5ndGggIT09IDMgJiYgcXVlcnkuZGltcy5sZW5ndGggIT09IDUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IHF1ZXJ5IGlzIGV4cGVjdGVkIHRvIGhhdmUgMyBvciA1IGRpbWVuc2lvbnMnKTtcbiAgfVxuXG4gIGNvbnN0IGRtbWhhUGFja2luZyA9IGZhbHNlO1xuICBjb25zdCBiYXRjaFNpemUgPSBxdWVyeS5kaW1zWzBdO1xuICBjb25zdCBzZXF1ZW5jZUxlbmd0aCA9IHF1ZXJ5LmRpbXNbMV07XG4gIGxldCBoaWRkZW5TaXplID1cbiAgICBxdWVyeS5kaW1zLmxlbmd0aCA9PT0gMyA/IChkbW1oYVBhY2tpbmcgPyBxdWVyeS5kaW1zWzJdIC8gMyA6IHF1ZXJ5LmRpbXNbMl0pIDogYXR0cmlidXRlcy5udW1IZWFkcyAqIHF1ZXJ5LmRpbXNbNF07XG4gIGxldCBrdlNlcXVlbmNlTGVuZ3RoID0gc2VxdWVuY2VMZW5ndGg7XG5cbiAgbGV0IHBhc3RTZXF1ZW5jZUxlbmd0aCA9IDA7XG4gIGNvbnN0IHBhY2tlZFFLViA9ICFrZXkgfHwga2V5LmRpbXMubGVuZ3RoID09PSAwO1xuICBjb25zdCBoZWFkU2l6ZSA9ICFwYWNrZWRRS1ZcbiAgICA/IE1hdGguZmxvb3IoaGlkZGVuU2l6ZSAvIGF0dHJpYnV0ZXMubnVtSGVhZHMpXG4gICAgOiBNYXRoLmZsb29yKGhpZGRlblNpemUgLyAoYXR0cmlidXRlcy5udW1IZWFkcyArIDIgKiBhdHRyaWJ1dGVzLmt2TnVtSGVhZHMpKTtcbiAgaWYgKHBhY2tlZFFLVikge1xuICAgIGhpZGRlblNpemUgPSBoZWFkU2l6ZSAqIGF0dHJpYnV0ZXMubnVtSGVhZHM7XG4gIH1cbiAgY29uc3QgaGFzUGFzdEtleSA9IHBhc3RLZXkgJiYgcGFzdEtleS5kaW1zLmxlbmd0aCAhPT0gMDtcbiAgY29uc3QgaGFzUGFzdFZhbHVlID0gcGFzdFZhbHVlICYmIHBhc3RWYWx1ZS5kaW1zLmxlbmd0aCAhPT0gMDtcbiAgLy8gQ3VycmVubHkgdGhlIG9ubnhydW50aW1lIEdRQSBzcGVjaWZpY2F0aW9uIG9ubHkgc3VwcG9ydCBrZXkvdmFsdWUgQk5TSCBmb3JtYXQuXG4gIGNvbnN0IGlzUGFzdGt2QlNOSCA9XG4gICAgaGFzUGFzdEtleSAmJlxuICAgIHBhc3RLZXkuZGltcy5sZW5ndGggPT09IDQgJiZcbiAgICBwYXN0S2V5LmRpbXNbMF0gPT09IGJhdGNoU2l6ZSAmJlxuICAgIHBhc3RLZXkuZGltc1sxXSAhPT0gYXR0cmlidXRlcy5rdk51bUhlYWRzICYmXG4gICAgcGFzdEtleS5kaW1zWzJdID09PSBhdHRyaWJ1dGVzLmt2TnVtSGVhZHMgJiZcbiAgICBwYXN0S2V5LmRpbXNbM10gPT09IGhlYWRTaXplO1xuXG4gIGlmIChpc1Bhc3RrdkJTTkgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0JTTkggcGFzdEtleS9wYXN0VmFsdWUgaXMgbm90IHN1cHBvcnRlZCcpO1xuICB9XG4gIGlmIChoYXNQYXN0S2V5ICYmIGhhc1Bhc3RWYWx1ZSkge1xuICAgIGlmIChwYXN0S2V5LmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdF9rZXlcIiBpcyBleHBlY3RlZCB0byBoYXZlIDQgZGltZW5zaW9ucycpO1xuICAgIH1cbiAgICBpZiAocGFzdFZhbHVlLmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdF92YWx1ZVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgNCBkaW1lbnNpb25zJyk7XG4gICAgfVxuICAgIHBhc3RTZXF1ZW5jZUxlbmd0aCA9IHBhc3RLZXkuZGltc1syXTtcbiAgfSBlbHNlIGlmIChoYXNQYXN0S2V5IHx8IGhhc1Bhc3RWYWx1ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0X2tleVwiIGFuZCBcInBhc3RfdmFsdWVcIiBzaGFsbCBiZSBib3RoIHByZXNlbnQgb3IgYm90aCBhYnNlbnQnKTtcbiAgfVxuXG4gIGxldCBxa3ZGb3JtYXQ6IEF0dGVudGlvblFrdkZvcm1hdCA9IEF0dGVudGlvblFrdkZvcm1hdC5xa3ZCTlNIO1xuICBpZiAoa2V5ICYmIGtleS5kaW1zLmxlbmd0aCA+IDApIHtcbiAgICBpZiAocXVlcnkuZGltcy5sZW5ndGggIT09IDMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgMyBkaW1lbnNpb25zIHdoZW4ga2V5IGlzIGdpdmVuJyk7XG4gICAgfVxuICAgIGlmIChrZXkuZGltcy5sZW5ndGggPCAzIHx8IGtleS5kaW1zLmxlbmd0aCA+IDUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJrZXlcIiBpcyBleHBlY3RlZCB0byBoYXZlIDMsIDQsIG9yIDUgZGltZW5zaW9ucycpO1xuICAgIH1cbiAgICBpZiAocXVlcnkuZGltc1swXSAhPT0ga2V5LmRpbXNbMF0pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGFuZCBcImtleVwiIHNoYWxsIGhhdmUgc2FtZSBkaW0gMCAoYmF0Y2ggc2l6ZSknKTtcbiAgICB9XG5cbiAgICBpZiAoa2V5LmRpbXMubGVuZ3RoID09PSAzKSB7XG4gICAgICBpZiAocXVlcnkuZGltc1syXSAlIGtleS5kaW1zWzJdICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRGltZW5zaW9uIDIgb2YgXCJxdWVyeVwiIHNob3VsZCBiZSBhIG11bHRpcGxlIG9mIFwia2V5XCInKTtcbiAgICAgIH1cbiAgICAgIGt2U2VxdWVuY2VMZW5ndGggPSBrZXkuZGltc1sxXTtcbiAgICB9IGVsc2UgaWYgKGtleS5kaW1zLmxlbmd0aCA9PT0gNSkge1xuICAgICAgaWYgKGtleS5kaW1zWzJdICE9PSBhdHRyaWJ1dGVzLm51bUhlYWRzIHx8IGtleS5kaW1zWzNdICE9PSAyIHx8IGtleS5kaW1zWzRdICE9PSBoZWFkU2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdCBcImtleVwiIHNoYXBlIChiYXRjaF9zaXplLCBrdl9zZXF1ZW5jZV9sZW5ndGgsIG51bV9oZWFkcywgMiwgaGVhZF9zaXplKSBmb3IgcGFja2VkIGt2Jyk7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3QgXCJ2YWx1ZVwiIGJlIG5vbmUgd2hlbiBcImtleVwiIGhhcyBwYWNrZWQga3YgZm9ybWF0LicpO1xuICAgICAgfVxuICAgICAga3ZTZXF1ZW5jZUxlbmd0aCA9IGtleS5kaW1zWzFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBrZXlfZGltcy5zaXplKCkgPT0gNCAoY3Jvc3MtYXR0ZW50aW9uIHdpdGggcGFzdF9rZXkpXG4gICAgICBpZiAoa2V5LmRpbXNbMV0gIT09IGF0dHJpYnV0ZXMubnVtSGVhZHMgfHwga2V5LmRpbXNbM10gIT09IGhlYWRTaXplKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0IFwia2V5XCIgc2hhcGUgKGJhdGNoX3NpemUsIG51bV9oZWFkcywga3Zfc2VxdWVuY2VfbGVuZ3RoLCBoZWFkX3NpemUpIGZvciBwYXN0X2tleScpO1xuICAgICAgfVxuICAgICAga3ZTZXF1ZW5jZUxlbmd0aCA9IGtleS5kaW1zWzJdO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBwYWNrZWQgUUtWXG4gICAgaWYgKHF1ZXJ5LmRpbXMubGVuZ3RoICE9PSAzICYmIHF1ZXJ5LmRpbXMubGVuZ3RoICE9PSA1KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicXVlcnlcIiBpcyBleHBlY3RlZCB0byBoYXZlIDMgb3IgNSBkaW1lbnNpb25zIHdoZW4ga2V5IGlzIGVtcHR5Jyk7XG4gICAgfVxuICAgIGlmIChxdWVyeS5kaW1zLmxlbmd0aCA9PT0gNSAmJiAocXVlcnkuZGltc1syXSAhPT0gYXR0cmlidXRlcy5udW1IZWFkcyB8fCBxdWVyeS5kaW1zWzNdICE9PSAzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3QgXCJxdWVyeVwiIHNoYXBlIChiYXRjaF9zaXplLCBrdl9zZXF1ZW5jZV9sZW5ndGgsIG51bV9oZWFkcywgMywgaGVhZF9zaXplKSBmb3IgcGFja2VkIGt2Jyk7XG4gICAgfVxuXG4gICAgcWt2Rm9ybWF0ID0gQXR0ZW50aW9uUWt2Rm9ybWF0LnFrdkJTTjNIO1xuICB9XG5cbiAgY29uc3QgbWFza1R5cGU6IEF0dGVudGlvbk1hc2tUeXBlID0gQXR0ZW50aW9uTWFza1R5cGUubm9uZTtcbiAgbGV0IHBhc3NQYXN0SW5LdiA9IGZhbHNlO1xuICBsZXQgdkhpZGRlblNpemUgPSBhdHRyaWJ1dGVzLmt2TnVtSGVhZHMgPyBoZWFkU2l6ZSAqIGF0dHJpYnV0ZXMua3ZOdW1IZWFkcyA6IGhpZGRlblNpemU7XG4gIGlmICh2YWx1ZSAmJiB2YWx1ZS5kaW1zLmxlbmd0aCA+IDApIHtcbiAgICBpZiAodmFsdWUuZGltcy5sZW5ndGggIT09IDMgJiYgdmFsdWUuZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJ2YWx1ZVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgMyBvciA0IGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBpZiAocXVlcnkuZGltc1swXSAhPT0gdmFsdWUuZGltc1swXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInF1ZXJ5XCIgYW5kIFwidmFsdWVcIiBzaGFsbCBoYXZlIHNhbWUgZGltIDAgKGJhdGNoX3NpemUpJyk7XG4gICAgfVxuXG4gICAgaWYgKHZhbHVlLmRpbXMubGVuZ3RoID09PSAzKSB7XG4gICAgICBpZiAoa3ZTZXF1ZW5jZUxlbmd0aCAhPT0gdmFsdWUuZGltc1sxXSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwia2V5XCIgYW5kIFwidmFsdWVcIiBzaGFsbCBoYXZlIHRoZSBzYW1lIGRpbSAxIChrdl9zZXF1ZW5jZV9sZW5ndGgpJyk7XG4gICAgICB9XG4gICAgICB2SGlkZGVuU2l6ZSA9IHZhbHVlLmRpbXNbMl07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChrdlNlcXVlbmNlTGVuZ3RoICE9PSB2YWx1ZS5kaW1zWzJdKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0X2tleVwiIGFuZCBcInBhc3RfdmFsdWVcIiBzaGFsbCBoYXZlIHRoZSBzYW1lIGRpbSAyIChrdl9zZXF1ZW5jZV9sZW5ndGgpJyk7XG4gICAgICB9XG4gICAgICB2SGlkZGVuU2l6ZSA9IHZhbHVlLmRpbXNbMV0gKiB2YWx1ZS5kaW1zWzNdO1xuICAgICAgcGFzc1Bhc3RJbkt2ID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgY29uc3Qgc2VxbExlbnMgPSBpbnB1dHMubGVuZ3RoID4gNCA/IGlucHV0c1s1XSA6IHVuZGVmaW5lZDtcbiAgaWYgKHNlcWxMZW5zICYmIHNlcWxMZW5zLmRpbXMubGVuZ3RoICE9PSAxICYmIHNlcWxMZW5zLmRpbXNbMF0gIT09IGJhdGNoU2l6ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJzZXFsZW5zXCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAxIGRpbWVuc2lvbiBhbmQgdGhlIHNhbWUgZGltIDAgYXMgYmF0Y2hfc2l6ZScpO1xuICB9XG4gIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGggPSAtMTtcbiAgY29uc3QgbWF4U2VxdWVuY2VMZW5ndGggPSAtMTtcbiAgY29uc3QgYnJvYWRjYXN0UmVzUG9zQmlhcyA9IGZhbHNlO1xuXG4gIHJldHVybiB7XG4gICAgYmF0Y2hTaXplLFxuICAgIHNlcXVlbmNlTGVuZ3RoLFxuICAgIHBhc3RTZXF1ZW5jZUxlbmd0aCxcbiAgICBrdlNlcXVlbmNlTGVuZ3RoLFxuICAgIHRvdGFsU2VxdWVuY2VMZW5ndGgsXG4gICAgbWF4U2VxdWVuY2VMZW5ndGgsXG4gICAgaW5wdXRIaWRkZW5TaXplOiAwLFxuICAgIGhpZGRlblNpemUsXG4gICAgdkhpZGRlblNpemUsXG4gICAgaGVhZFNpemUsXG4gICAgdkhlYWRTaXplOiBNYXRoLmZsb29yKHZIaWRkZW5TaXplIC8gYXR0cmlidXRlcy5rdk51bUhlYWRzKSxcbiAgICBudW1IZWFkczogYXR0cmlidXRlcy5udW1IZWFkcyxcbiAgICBrdk51bUhlYWRzOiBhdHRyaWJ1dGVzLmt2TnVtSGVhZHMsXG4gICAgblJlcHM6IGF0dHJpYnV0ZXMubnVtSGVhZHMgLyBhdHRyaWJ1dGVzLmt2TnVtSGVhZHMsXG4gICAgcGFzdFByZXNlbnRTaGFyZUJ1ZmZlcjogZmFsc2UsXG4gICAgbWFza1R5cGUsXG4gICAgc2NhbGU6IGF0dHJpYnV0ZXMuc2NhbGUsXG4gICAgYnJvYWRjYXN0UmVzUG9zQmlhcyxcbiAgICBwYXNzUGFzdEluS3YsXG4gICAgcWt2Rm9ybWF0LFxuICB9O1xufTtcblxuY29uc3Qgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlOiBUcmFuc3Bvc2VBdHRyaWJ1dGVzID0gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgcGVybTogWzAsIDIsIDEsIDNdIH0pO1xuXG5jb25zdCBtYXliZVRyYW5zcG9zZVRvQk5TSCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgaW5wdXQ6IFRlbnNvclZpZXcsIHBhcmFtczogQXR0ZW50aW9uUGFyYW1ldGVycykgPT4ge1xuICBsZXQgcmVzaGFwZWRJbnB1dCA9IGlucHV0O1xuICBjb25zdCBudW1IZWFkcyA9IHBhcmFtcy5rdk51bUhlYWRzITtcbiAgaWYgKGlucHV0LmRpbXMubGVuZ3RoID09PSAzICYmIHBhcmFtcy5rdlNlcXVlbmNlTGVuZ3RoICE9PSAwKSB7XG4gICAgcmVzaGFwZWRJbnB1dCA9IGlucHV0LnJlc2hhcGUoW3BhcmFtcy5iYXRjaFNpemUsIHBhcmFtcy5rdlNlcXVlbmNlTGVuZ3RoLCBudW1IZWFkcywgcGFyYW1zLmhlYWRTaXplXSk7XG4gICAgcmVzaGFwZWRJbnB1dCA9IGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhyZXNoYXBlZElucHV0LCB3ZWlnaHRUcmFuc3Bvc2VBdHRyaWJ1dGUucGVybSksIHtcbiAgICAgIGlucHV0czogW3Jlc2hhcGVkSW5wdXRdLFxuICAgICAgb3V0cHV0czogWy0xXSxcbiAgICB9KVswXTtcbiAgfVxuXG4gIHJldHVybiByZXNoYXBlZElucHV0O1xufTtcblxuY29uc3QgZ2VuZXJhdGVQb3NpdGlvbklkc1Byb2dyYW1JbmZvID0gKFxuICBiYXRjaFNpemU6IG51bWJlcixcbiAgc2VxdWVuY2VMZW5ndGg6IG51bWJlcixcbiAgc2VxTGVuczogVGVuc29yVmlldyxcbiAgdG90YWxTZXFMZW46IFRlbnNvclZpZXcsXG4pID0+IHtcbiAgY29uc3Qgb3V0cHV0RGF0YVR5cGUgPSBEYXRhVHlwZS5pbnQ2NDtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnLCAndHlwZSddO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IFtiYXRjaFNpemUgKiBzZXF1ZW5jZUxlbmd0aF07XG4gIGNvbnN0IG91dHB1dFNpemUgPSBiYXRjaFNpemUgKiBzZXF1ZW5jZUxlbmd0aDtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHNlcXVlbmNlTGVuZ3RoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGJhdGNoU2l6ZSB9LFxuICBdO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBzZXFMZW5zSW5wdXRIZWxwZXIgPSBpbnB1dFZhcmlhYmxlKCdzZXFfbGVucycsIHNlcUxlbnMuZGF0YVR5cGUsIHNlcUxlbnMuZGltcyk7XG4gICAgY29uc3QgdG90YWxTZXFMZW5JbnB1dEhlbHBlciA9IGlucHV0VmFyaWFibGUoJ3RvdGFsX3NlcV9sZW5zJywgdG90YWxTZXFMZW4uZGF0YVR5cGUsIHRvdGFsU2VxTGVuLmRpbXMpO1xuICAgIGNvbnN0IHBvc2l0aW9uSWRzSGVscGVyID0gb3V0cHV0VmFyaWFibGUoJ3Bvc19pZHMnLCBvdXRwdXREYXRhVHlwZSwgb3V0cHV0U2hhcGUpO1xuXG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnc2VxdWVuY2VfbGVuZ3RoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2JhdGNoX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG5cbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKHNlcUxlbnNJbnB1dEhlbHBlciwgdG90YWxTZXFMZW5JbnB1dEhlbHBlciwgcG9zaXRpb25JZHNIZWxwZXIpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICAgIGxldCB0b3RhbF9zZXF1ZW5jZV9sZW5ndGggPSB1MzIoJHt0b3RhbFNlcUxlbklucHV0SGVscGVyLmdldEJ5T2Zmc2V0KCcwJyl9KTtcbiAgICBsZXQgaXNfc3Vic2VxdWVudF9wcm9tcHQgPSB1bmlmb3Jtcy5zZXF1ZW5jZV9sZW5ndGggPiAxICYmIHVuaWZvcm1zLnNlcXVlbmNlX2xlbmd0aCAhPSB0b3RhbF9zZXF1ZW5jZV9sZW5ndGg7XG4gICAgbGV0IGlzX2ZpcnN0X3Byb21wdCA9ICFpc19zdWJzZXF1ZW50X3Byb21wdCAmJiB1bmlmb3Jtcy5zZXF1ZW5jZV9sZW5ndGggPT0gdG90YWxfc2VxdWVuY2VfbGVuZ3RoO1xuICAgIGxldCBiYXRjaF9pZHggPSBnbG9iYWxfaWR4IC8gdW5pZm9ybXMuc2VxdWVuY2VfbGVuZ3RoO1xuICAgIGxldCBzZXF1ZW5jZV9pZHggPSBpMzIoZ2xvYmFsX2lkeCAlIHVuaWZvcm1zLnNlcXVlbmNlX2xlbmd0aCk7XG4gICAgdmFyIHBvc19pZDogaTMyID0gMDtcbiAgICBsZXQgc2VxbGVuID0gJHtzZXFMZW5zSW5wdXRIZWxwZXIuZ2V0QnlPZmZzZXQoJ2JhdGNoX2lkeCcpfTtcbiAgICBsZXQgdG90YWxfc2VxbGVuID0gc2VxbGVuICsgMTtcbiAgICBpZiAoaXNfZmlyc3RfcHJvbXB0KSB7XG4gICAgICBpZiAoc2VxdWVuY2VfaWR4IDwgdG90YWxfc2VxbGVuKSB7XG4gICAgICAgIHBvc19pZCA9IHNlcXVlbmNlX2lkeDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBvc19pZCA9IDE7XG4gICAgICB9XG4gICAgICAke3Bvc2l0aW9uSWRzSGVscGVyLnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3Bvc19pZCcpfVxuICAgIH0gZWxzZSBpZiAoaXNfc3Vic2VxdWVudF9wcm9tcHQpIHtcbiAgICAgIGxldCBwYXN0X3NlcWxlbiA9IHRvdGFsX3NlcWxlbiAtIGkzMih1bmlmb3Jtcy5zZXF1ZW5jZV9sZW5ndGgpO1xuICAgICAgaWYgKHBhc3Rfc2VxbGVuICsgc2VxdWVuY2VfaWR4IDwgdG90YWxfc2VxbGVuKSB7XG4gICAgICAgIHBvc19pZCA9IHBhc3Rfc2VxbGVuICsgc2VxdWVuY2VfaWR4O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcG9zX2lkID0gMTtcbiAgICAgIH1cbiAgICAgICR7cG9zaXRpb25JZHNIZWxwZXIuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAncG9zX2lkJyl9XG4gICAgfSBlbHNlIGlmIChnbG9iYWxfaWR4IDwgdW5pZm9ybXMuYmF0Y2hfc2l6ZSkge1xuICAgICAgJHtwb3NpdGlvbklkc0hlbHBlci5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICdzZXFsZW4nKX1cbiAgICB9O1xuICB9XG4gIGA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0dlbmVyYXRlUG9zaXRpb25JZHMnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2JhdGNoU2l6ZX07JHtzZXF1ZW5jZUxlbmd0aH1gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IG91dHB1dERhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBncm91cFF1ZXJ5QXR0ZW50aW9uID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBHcm91cFF1ZXJ5QXR0ZW50aW9uQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBwYXJhbXMgPSB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGlmIChjb250ZXh0LmlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gNSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUGFja2VkIFFLViBpcyBub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIGlmIChjb250ZXh0LmlucHV0c1sxXT8uZGltcy5sZW5ndGggPT09IDUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1BhY2tlZCBLViBpcyBub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIGNvbnN0IHEgPSBjb250ZXh0LmlucHV0c1swXTtcbiAgY29uc3QgayA9IGNvbnRleHQuaW5wdXRzWzFdICYmIGNvbnRleHQuaW5wdXRzWzFdLmRpbXMubGVuZ3RoID4gMCA/IGNvbnRleHQuaW5wdXRzWzFdIDogdW5kZWZpbmVkO1xuICBjb25zdCB2ID0gY29udGV4dC5pbnB1dHNbMl0gJiYgY29udGV4dC5pbnB1dHNbMl0uZGltcy5sZW5ndGggPiAwID8gY29udGV4dC5pbnB1dHNbMl0gOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHBhc3RLZXkgPSBjb250ZXh0LmlucHV0c1szXSAmJiBjb250ZXh0LmlucHV0c1szXS5kaW1zLmxlbmd0aCAhPT0gMCA/IGNvbnRleHQuaW5wdXRzWzNdIDogdW5kZWZpbmVkO1xuICBjb25zdCBwYXN0VmFsdWUgPSBjb250ZXh0LmlucHV0c1s0XSAmJiBjb250ZXh0LmlucHV0c1s0XS5kaW1zLmxlbmd0aCAhPT0gMCA/IGNvbnRleHQuaW5wdXRzWzRdIDogdW5kZWZpbmVkO1xuICBjb25zdCBzZXFMZW5zID0gY29udGV4dC5pbnB1dHMubGVuZ3RoID4gNCA/IGNvbnRleHQuaW5wdXRzWzVdIDogdW5kZWZpbmVkO1xuICBjb25zdCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQgPSBjb250ZXh0LmlucHV0cy5sZW5ndGggPiA1ID8gY29udGV4dC5pbnB1dHNbNl0gOiB1bmRlZmluZWQ7XG4gIGNvbnN0IGt2TnVtSGVhZHMgPSBwYXJhbXMua3ZOdW1IZWFkcyA/IHBhcmFtcy5rdk51bUhlYWRzIDogcGFyYW1zLm51bUhlYWRzO1xuXG4gIC8vIFRPRE8gUmVtb3ZlIGV4cGxpY2l0IHNwbGl0IG9wZXJhdGlvbiBhbmQgdXNlIGluZGV4aW5nIGluIEF0dGVudGlvbiBpbXBsZW1lbnRhdGlvbiB0byBhdm9pZCBvdmVyaGVhZC5cblxuICBjb25zdCBzcGxpdEF0dHJpYnV0ZXM6IFNwbGl0QXR0cmlidXRlcyA9IGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7XG4gICAgYXhpczogMixcbiAgICBudW1PdXRwdXRzOiAzLFxuICAgIHNwbGl0U2l6ZXM6IFtwYXJhbXMubnVtSGVhZHMgKiBwYXJhbXMuaGVhZFNpemUsIGt2TnVtSGVhZHMgKiBwYXJhbXMuaGVhZFNpemUsIGt2TnVtSGVhZHMgKiBwYXJhbXMuaGVhZFNpemVdLFxuICB9KTtcbiAgY29uc3QgW3F1ZXJ5LCBrZXksIHZhbHVlXSA9XG4gICAgIWsgJiYgIXZcbiAgICAgID8gY29udGV4dC5jb21wdXRlKGNyZWF0ZVNwbGl0UHJvZ3JhbUluZm8oW3FdLCBzcGxpdEF0dHJpYnV0ZXMpLCB7IGlucHV0czogW3FdLCBvdXRwdXRzOiBbLTEsIC0xLCAtMV0gfSlcbiAgICAgIDogW3EsIGshLCB2IV07XG4gIGxldCBxUm90YXJ5OiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkO1xuICBsZXQga1JvdGFyeTogVGVuc29yVmlldyB8IHVuZGVmaW5lZDtcbiAgaWYgKGF0dHJpYnV0ZXMuZG9Sb3RhcnkpIHtcbiAgICBjb25zdCBwb3NJZHMgPSBjb250ZXh0LmNvbXB1dGUoXG4gICAgICBnZW5lcmF0ZVBvc2l0aW9uSWRzUHJvZ3JhbUluZm8ocGFyYW1zLmJhdGNoU2l6ZSwgcGFyYW1zLnNlcXVlbmNlTGVuZ3RoLCBzZXFMZW5zISwgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0ISksXG4gICAgICB7IGlucHV0czogW3NlcUxlbnMhLCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQhXSwgb3V0cHV0czogWy0xXSB9LFxuICAgIClbMF07XG4gICAgY29uc3QgY29zQ2FjaGUgPSBjb250ZXh0LmlucHV0c1s3XTtcbiAgICBjb25zdCBzaW5DYWNoZSA9IGNvbnRleHQuaW5wdXRzWzhdO1xuICAgIGNvbnN0IHFSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzOiBSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzID0gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtcbiAgICAgIGludGVybGVhdmVkOiBhdHRyaWJ1dGVzLnJvdGFyeUludGVybGVhdmVkICE9PSAwLFxuICAgICAgbnVtSGVhZHM6IHBhcmFtcy5udW1IZWFkcyxcbiAgICAgIHJvdGFyeUVtYmVkZGluZ0RpbTogMCxcbiAgICAgIHNjYWxlOiBhdHRyaWJ1dGVzLnNjYWxlLFxuICAgIH0pO1xuICAgIGNvbnN0IGlucHV0cyA9IFtxdWVyeSwgcG9zSWRzLCBjb3NDYWNoZSwgc2luQ2FjaGVdO1xuICAgIGNvbnN0IG91dHB1dHMgPSBbLTFdO1xuICAgIHFSb3RhcnkgPSBjb250ZXh0LmNvbXB1dGUoY3JlYXRlUm90YXJ5RW1iZWRkaW5nUHJvZ3JhbUluZm8oaW5wdXRzLCBxUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyksIHtcbiAgICAgIGlucHV0cyxcbiAgICAgIG91dHB1dHMsXG4gICAgfSlbMF07XG4gICAgaW5wdXRzLnNwbGljZSgwLCAxLCBrZXkpO1xuICAgIGNvbnN0IGtSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzOiBSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzID0gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtcbiAgICAgIGludGVybGVhdmVkOiBhdHRyaWJ1dGVzLnJvdGFyeUludGVybGVhdmVkICE9PSAwLFxuICAgICAgbnVtSGVhZHM6IHBhcmFtcy5rdk51bUhlYWRzISxcbiAgICAgIHJvdGFyeUVtYmVkZGluZ0RpbTogMCxcbiAgICAgIHNjYWxlOiBhdHRyaWJ1dGVzLnNjYWxlLFxuICAgIH0pO1xuICAgIGtSb3RhcnkgPSBjb250ZXh0LmNvbXB1dGUoY3JlYXRlUm90YXJ5RW1iZWRkaW5nUHJvZ3JhbUluZm8oaW5wdXRzLCBrUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyksIHtcbiAgICAgIGlucHV0cyxcbiAgICAgIG91dHB1dHMsXG4gICAgfSlbMF07XG4gIH1cbiAgY29uc3QgUSA9IG1heWJlVHJhbnNwb3NlVG9CTlNIQW5kQWRkQmlhcyhcbiAgICBjb250ZXh0LFxuICAgIHBhcmFtcy5iYXRjaFNpemUsXG4gICAgcGFyYW1zLm51bUhlYWRzLFxuICAgIHBhcmFtcy5zZXF1ZW5jZUxlbmd0aCxcbiAgICBwYXJhbXMuaGVhZFNpemUsXG4gICAgYXR0cmlidXRlcy5kb1JvdGFyeSA/IHFSb3RhcnkhIDogcXVlcnksXG4gICAgdW5kZWZpbmVkLFxuICAgIDAsXG4gICk7XG4gIGNvbnN0IEsgPSBtYXliZVRyYW5zcG9zZVRvQk5TSChjb250ZXh0LCBhdHRyaWJ1dGVzLmRvUm90YXJ5ID8ga1JvdGFyeSEgOiBrZXksIHBhcmFtcyk7XG4gIGNvbnN0IFYgPSBtYXliZVRyYW5zcG9zZVRvQk5TSChjb250ZXh0LCB2YWx1ZSwgcGFyYW1zKTtcblxuICBhcHBseUF0dGVudGlvbihcbiAgICBjb250ZXh0LFxuICAgIFEsXG4gICAgSyxcbiAgICBWLFxuICAgIHVuZGVmaW5lZCxcbiAgICB1bmRlZmluZWQsXG4gICAgcGFzdEtleSxcbiAgICBwYXN0VmFsdWUsXG4gICAgdW5kZWZpbmVkLFxuICAgIHBhcmFtcyxcbiAgICBzZXFMZW5zLFxuICAgIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCxcbiAgKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvIH0gZnJvbSAnLi90cmFuc3Bvc2UnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgZ2V0TWF4Q29tcG9uZW50cyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgc3VtVmVjdG9yLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBJbnN0YW5jZU5vcm1BdHRyaWJ1dGVzIHtcbiAgZXBzaWxvbjogbnVtYmVyO1xuICBmb3JtYXQ6ICdOSFdDJyB8ICdOQ0hXJztcbn1cblxuY29uc3QgY29tcHV0ZUNoYW5uZWxTY2FsZVNoaWZ0ID0gKFxuICBjb250ZXh0OiBDb21wdXRlQ29udGV4dCxcbiAgaW5wdXQ6IFRlbnNvclZpZXcsXG4gIHNjYWxlOiBUZW5zb3JWaWV3LFxuICBiaWFzOiBUZW5zb3JWaWV3LFxuICBuOiBudW1iZXIsXG4gIGg6IG51bWJlcixcbiAgYzogbnVtYmVyLFxuICBlcHNpbG9uOiBudW1iZXIsXG4pID0+IHtcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoaCk7XG4gIGNvbnN0IGYzMlR5cGUgPSBjb21wb25lbnRzID09PSAxID8gJ2YzMicgOiBgdmVjJHtjb21wb25lbnRzfWZgO1xuICBjb25zdCB3Z1R5cGUgPSBjb21wb25lbnRzID09PSAxID8gJ3ZlYzJmJyA6IGBtYXQyeCR7Y29tcG9uZW50c31mYDtcbiAgY29uc3QgdW5pdHNPZldvcmsgPSBuICogYztcbiAgbGV0IHdvcmtncm91cFNpemUgPSA2NDtcbiAgaWYgKHVuaXRzT2ZXb3JrID09PSAxKSB7XG4gICAgd29ya2dyb3VwU2l6ZSA9IDI1NjtcbiAgfVxuICBjb25zdCBpbnB1dFNoYXBlID0gW24sIGMsIGggLyBjb21wb25lbnRzXTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbbiwgYywgMl07XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWydyYW5rJywgJ3R5cGUnLCAndHlwZSddO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRTaGFwZSwgb3V0cHV0U2hhcGUpKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0LmRhdGFUeXBlLCAzLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBzID0gaW5wdXRWYXJpYWJsZSgnc2NhbGUnLCBzY2FsZS5kYXRhVHlwZSwgc2NhbGUuZGltcyk7XG4gICAgY29uc3QgYiA9IGlucHV0VmFyaWFibGUoJ2JpYXMnLCBiaWFzLmRhdGFUeXBlLCBiaWFzLmRpbXMpO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBEYXRhVHlwZS5mbG9hdCwgMywgMik7XG4gICAgY29uc3QgdmFyaWFibGVzID0gW3gsIHMsIGIsIG91dHB1dF07XG4gICAgcmV0dXJuIGBcbiAgdmFyPHdvcmtncm91cD4gd29ya2dyb3VwX3NoYXJlZCA6IGFycmF5PCR7d2dUeXBlfSwgJHt3b3JrZ3JvdXBTaXplfT47XG4gIGNvbnN0IHdvcmtncm91cF9zaXplID0gJHt3b3JrZ3JvdXBTaXplfXU7XG4gICR7c2hhZGVySGVscGVyLmRlY2xhcmVWYXJpYWJsZXMoLi4udmFyaWFibGVzKX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KHdvcmtncm91cFNpemUpfVxuICAgIGxldCBiYXRjaCA9IHdvcmtncm91cF9pbmRleCAvIHVuaWZvcm1zLnhfc2hhcGVbMV07XG4gICAgbGV0IGNoYW5uZWwgPSB3b3JrZ3JvdXBfaW5kZXggJSB1bmlmb3Jtcy54X3NoYXBlWzFdO1xuICAgIGxldCBoaWdodCA9IHVuaWZvcm1zLnhfc2hhcGVbMl07XG4gICAgLy8gaW5pdGlhbGl6ZSB3b3JrZ3JvdXAgbWVtb3J5XG4gICAgdmFyIHN1bSA9ICR7ZjMyVHlwZX0oMCk7XG4gICAgdmFyIHNxdWFyZWRfc3VtID0gJHtmMzJUeXBlfSgwKTtcbiAgICBmb3IgKHZhciBoID0gbG9jYWxfaWR4OyBoIDwgaGlnaHQ7IGggKz0gd29ya2dyb3VwX3NpemUpIHtcbiAgICAgIGxldCB2YWx1ZSA9ICR7ZjMyVHlwZX0oJHt4LmdldCgnYmF0Y2gnLCAnY2hhbm5lbCcsICdoJyl9KTtcbiAgICAgIHN1bSArPSB2YWx1ZTtcbiAgICAgIHNxdWFyZWRfc3VtICs9IHZhbHVlICogdmFsdWU7XG4gICAgfVxuICAgIHdvcmtncm91cF9zaGFyZWRbbG9jYWxfaWR4XSA9ICR7d2dUeXBlfShzdW0sIHNxdWFyZWRfc3VtKTtcbiAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICBmb3IgKHZhciBjdXJyU2l6ZSA9IHdvcmtncm91cF9zaXplID4+IDE7ICBjdXJyU2l6ZSA+IDA7IGN1cnJTaXplID0gY3VyclNpemUgPj4gMSkge1xuICAgICAgaWYgKGxvY2FsX2lkeCA8IGN1cnJTaXplKSB7XG4gICAgICAgIHdvcmtncm91cF9zaGFyZWRbbG9jYWxfaWR4XSA9IHdvcmtncm91cF9zaGFyZWRbbG9jYWxfaWR4XSArIHdvcmtncm91cF9zaGFyZWRbbG9jYWxfaWR4ICsgY3VyclNpemVdO1xuICAgICAgfVxuICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICAgIH1cbiAgICBpZiAobG9jYWxfaWR4ID09IDApIHtcbiAgICAgIGxldCBzdW1fZmluYWwgPSAke3N1bVZlY3Rvcignd29ya2dyb3VwX3NoYXJlZFswXVswXScsIGNvbXBvbmVudHMpfSAvIGYzMihoaWdodCAqICR7Y29tcG9uZW50c30pO1xuICAgICAgbGV0IHNxdWFyZWRfc3VtX2ZpbmFsID0gJHtzdW1WZWN0b3IoJ3dvcmtncm91cF9zaGFyZWRbMF1bMV0nLCBjb21wb25lbnRzKX0gLyBmMzIoaGlnaHQgKiAke2NvbXBvbmVudHN9KTtcblxuICAgICAgbGV0IGludl9zdGRfZGV2ID0gaW52ZXJzZVNxcnQoc3F1YXJlZF9zdW1fZmluYWwgLSBzdW1fZmluYWwgKiBzdW1fZmluYWwgKyBmMzIoJHtlcHNpbG9ufSkpO1xuICAgICAgbGV0IGNoYW5uZWxfc2NhbGUgPSBpbnZfc3RkX2RldiAqIGYzMihzY2FsZVtjaGFubmVsXSk7XG4gICAgICBsZXQgY2hhbm5lbF9zaGlmdCA9IGYzMihiaWFzW2NoYW5uZWxdKSAtIHN1bV9maW5hbCAqIGNoYW5uZWxfc2NhbGU7XG4gICAgICBvdXRwdXRbd29ya2dyb3VwX2luZGV4XSA9IHZlYzJmKGNoYW5uZWxfc2NhbGUsIGNoYW5uZWxfc2hpZnQpO1xuICAgIH1cbiAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIGNvbnRleHQuY29tcHV0ZShcbiAgICB7XG4gICAgICBuYW1lOiAnSW5zdGFuY2VOb3JtQ29tcHV0ZUNoYW5uZWxTY2FsZVNoaWZ0JyxcbiAgICAgIC8vIFRPRE86IHVzZSBlcHNpbG9uIGFzIHVuaWZvcm0uIEN1cnJlbnRseSBlcHNpbG9uIGFzIHVuaWZvcm0gZmFpbHMgdGVzdF9pbnN0YW5jZW5vcm1fZXBzaWxvbi5cbiAgICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2NvbXBvbmVudHN9OyR7ZXBzaWxvbn07JHt3b3JrZ3JvdXBTaXplfWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IERhdGFUeXBlLmZsb2F0IH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IHVuaXRzT2ZXb3JrIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICAgIH0pLFxuICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIH0sXG4gICAgeyBpbnB1dHM6IFtpbnB1dCwgc2NhbGUsIGJpYXNdLCBvdXRwdXRzOiBbLTFdIH0sXG4gIClbMF07XG59O1xuXG5jb25zdCBjcmVhdGVJbnN0YW5jZU5vcm1Qcm9ncmFtSW5mbyA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBJbnN0YW5jZU5vcm1BdHRyaWJ1dGVzLFxuKSA9PiB7XG4gIGNvbnN0IHhTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IHhTaGFwZTtcbiAgY29uc3QgYXhpcyA9IDI7XG4gIGNvbnN0IE4gPSB4U2hhcGVbMF07XG4gIGNvbnN0IEMgPSB4U2hhcGVbMV07XG4gIGNvbnN0IEggPSBTaGFwZVV0aWwuc2l6ZUZyb21EaW1lbnNpb24oeFNoYXBlLCBheGlzKTtcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoSCk7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyBjb21wb25lbnRzO1xuICAvLyBjb21wdXRlIGNoYW5uZWwgc2NhbGUgYW5kIGNoYW5uZWwgc2hpZnQuXG4gIGNvbnN0IGNoYW5uZWxTY2FsZVNoaWZ0ID0gY29tcHV0ZUNoYW5uZWxTY2FsZVNoaWZ0KFxuICAgIGNvbnRleHQsXG4gICAgaW5wdXRzWzBdLFxuICAgIGlucHV0c1sxXSxcbiAgICBpbnB1dHNbMl0sXG4gICAgTixcbiAgICBILFxuICAgIEMsXG4gICAgYXR0cmlidXRlcy5lcHNpbG9uLFxuICApO1xuXG4gIGNvbnN0IGlucHV0U2hhcGUgPSBbTiwgQywgSCAvIGNvbXBvbmVudHNdO1xuICBjb25zdCBzY2FsZVNoYXBlID0gW04sIENdO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsndHlwZScsICdub25lJ107XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBzY2FsZSA9IGlucHV0VmFyaWFibGUoJ3NjYWxlX3NoaWZ0JywgRGF0YVR5cGUuZmxvYXQsIHNjYWxlU2hhcGUubGVuZ3RoLCAyKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgdmFyaWFibGVzID0gW3gsIHNjYWxlLCBvdXRwdXRdO1xuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyguLi52YXJpYWJsZXMpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICAgIGxldCBvdXRwdXRJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgbGV0IGJhdGNoID0gb3V0cHV0SW5kaWNlc1swXTtcbiAgICAgIGxldCBjaGFubmVsID0gb3V0cHV0SW5kaWNlc1sxXTtcbiAgICAgIGxldCBzY2FsZV9zaGlmdCA9ICR7c2NhbGUuZ2V0QnlJbmRpY2VzKCd2ZWMyPHUzMj4oYmF0Y2gsIGNoYW5uZWwpJyl9O1xuICAgICAgbGV0IHZhbHVlID0gJHt4LmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4Jyl9ICogJHtvdXRwdXQudHlwZS52YWx1ZX0oc2NhbGVfc2hpZnQueCkgKyAke291dHB1dC50eXBlLnZhbHVlfShzY2FsZV9zaGlmdC55KTtcbiAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3ZhbHVlJyl9O1xuICB9YDtcbiAgfTtcblxuICBjb250ZXh0LmNvbXB1dGUoXG4gICAge1xuICAgICAgbmFtZTogJ0luc3RhbmNlTm9ybWFsaXphdGlvbicsXG4gICAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtjb21wb25lbnRzfWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXM6IFtcbiAgICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgICAgICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0U2hhcGUsIHNjYWxlU2hhcGUsIGlucHV0U2hhcGUpLFxuICAgICAgICBdLFxuICAgICAgfSksXG4gICAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgfSxcbiAgICB7IGlucHV0czogW2lucHV0c1swXSwgY2hhbm5lbFNjYWxlU2hpZnRdIH0sXG4gICk7XG59O1xuXG5jb25zdCBjcmVhdGVJbnN0YW5jZU5vcm1OSFdDUHJvZ3JhbUluZm8gPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogSW5zdGFuY2VOb3JtQXR0cmlidXRlcyxcbikgPT4ge1xuICBjb25zdCB4U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSB4U2hhcGU7XG4gIGNvbnN0IE4gPSB4U2hhcGVbMF07XG4gIGNvbnN0IEMgPSB4U2hhcGVbeFNoYXBlLmxlbmd0aCAtIDFdO1xuICBjb25zdCBIID0gU2hhcGVVdGlsLnNpemVGcm9tRGltZW5zaW9uKHhTaGFwZSwgMSkgLyBDO1xuICBjb25zdCBjb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhDKTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIGNvbXBvbmVudHM7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogSCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBNYXRoLmZsb29yKEMgLyBjb21wb25lbnRzKSB9LFxuICBdO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsndHlwZScsICd0eXBlJ107XG5cbiAgLy8gMS4gdHJhbnNwb3NlIHggZnJvbSBOSFdDIHRvIE5DSFdcbiAgbGV0IG5lZWRUcmFuc3Bvc2UgPSBmYWxzZTtcbiAgY29uc3QgdHJhbnNwb3NlZFhQZXJtID0gWzAsIHhTaGFwZS5sZW5ndGggLSAxXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB4U2hhcGUubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgbmVlZFRyYW5zcG9zZSA9IG5lZWRUcmFuc3Bvc2UgfHwgeFNoYXBlW2kgKyAxXSAhPT0gMTtcbiAgICB0cmFuc3Bvc2VkWFBlcm0ucHVzaChpICsgMSk7XG4gIH1cblxuICBuZWVkVHJhbnNwb3NlID0gbmVlZFRyYW5zcG9zZSAmJiB4U2hhcGVbeFNoYXBlLmxlbmd0aCAtIDFdICE9PSAxO1xuXG4gIGNvbnN0IHRyYW5zcG9zZWRYID0gbmVlZFRyYW5zcG9zZVxuICAgID8gY29udGV4dC5jb21wdXRlKGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCB0cmFuc3Bvc2VkWFBlcm0pLCB7XG4gICAgICAgIGlucHV0czogW2NvbnRleHQuaW5wdXRzWzBdXSxcbiAgICAgICAgb3V0cHV0czogWy0xXSxcbiAgICAgIH0pWzBdXG4gICAgOiBjb250ZXh0LmlucHV0c1swXS5yZXNoYXBlKEFycmF5LmZyb20oeyBsZW5ndGg6IHhTaGFwZS5sZW5ndGggfSwgKF8sIGkpID0+IHhTaGFwZVt0cmFuc3Bvc2VkWFBlcm1baV1dKSk7XG4gIC8vIDIuIGNvbXB1dGUgY2hhbm5lbCBzY2FsZSBhbmQgY2hhbm5lbCBzaGlmdC5cbiAgY29uc3QgY2hhbm5lbFNjYWxlU2hpZnQgPSBjb21wdXRlQ2hhbm5lbFNjYWxlU2hpZnQoXG4gICAgY29udGV4dCxcbiAgICB0cmFuc3Bvc2VkWCxcbiAgICBpbnB1dHNbMV0sXG4gICAgaW5wdXRzWzJdLFxuICAgIE4sXG4gICAgSCxcbiAgICBDLFxuICAgIGF0dHJpYnV0ZXMuZXBzaWxvbixcbiAgKTtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgICBjb25zdCBzY2FsZVR5cGUgPSBjb21wb25lbnRzID09PSAxID8gJ3ZlYzJmJyA6IGBtYXQke2NvbXBvbmVudHN9eDJmYDtcbiAgICBjb25zdCBzY2FsZURhdGEgPSAobnVtOiBudW1iZXIpID0+IHtcbiAgICAgIGNvbnN0IGluZGV4ID0gbnVtID09PSAwID8gJ3gnIDogJ3knO1xuICAgICAgY29uc3QgZjMyVHlwZSA9IGNvbXBvbmVudHMgPT09IDEgPyAnZjMyJyA6IGB2ZWMke2NvbXBvbmVudHN9ZmA7XG4gICAgICBzd2l0Y2ggKGNvbXBvbmVudHMpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIHJldHVybiBgJHtkYXRhVHlwZX0oJHtmMzJUeXBlfShzY2FsZS4ke2luZGV4fSkpYDtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHJldHVybiBgdmVjMjwke2RhdGFUeXBlfT4oJHtmMzJUeXBlfShzY2FsZVswXS4ke2luZGV4fSwgc2NhbGVbMV0uJHtpbmRleH0pKWA7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICByZXR1cm4gYHZlYzQ8JHtkYXRhVHlwZX0+KCR7ZjMyVHlwZX0oc2NhbGVbMF0uJHtpbmRleH0sIHNjYWxlWzFdLiR7aW5kZXh9LCBzY2FsZVsyXS4ke2luZGV4fSwgc2NhbGVbM10uJHtpbmRleH0pKWA7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOb3Qgc3VwcG9ydGVkIGNvbXBvZW50cyAke2NvbXBvbmVudHN9YCk7XG4gICAgICB9XG4gICAgfTtcbiAgICBjb25zdCBpbnB1dEhlbHBlciA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcywgY29tcG9uZW50cyk7XG4gICAgY29uc3Qgb3V0cHV0SGVscGVyID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUsIGNvbXBvbmVudHMpO1xuXG4gICAgcmV0dXJuIGBcbiAgQGdyb3VwKDApIEBiaW5kaW5nKDApIHZhcjxzdG9yYWdlLCByZWFkPiBpbnB1dCA6IGFycmF5PCR7aW5wdXRIZWxwZXIudHlwZS5zdG9yYWdlfT47XG4gIEBncm91cCgwKSBAYmluZGluZygxKSB2YXI8c3RvcmFnZSwgcmVhZD4gc2NhbGVfaW5wdXQgOiBhcnJheTwke3NjYWxlVHlwZX0+O1xuICBAZ3JvdXAoMCkgQGJpbmRpbmcoMikgdmFyPHN0b3JhZ2UsIHJlYWRfd3JpdGU+IG91dHB1dCA6IGFycmF5PCR7b3V0cHV0SGVscGVyLnR5cGUuc3RvcmFnZX0+O1xuICBzdHJ1Y3QgVW5pZm9ybXMge0g6IHUzMiwgQyA6IHUzMn07XG4gIEBncm91cCgwKSBAYmluZGluZygzKSB2YXI8dW5pZm9ybT4gdW5pZm9ybXM6IFVuaWZvcm1zO1xuXG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgIGxldCBjdXJyZW50X2ltYWdlX251bWJlciA9IGdsb2JhbF9pZHggLyAodW5pZm9ybXMuQyAqIHVuaWZvcm1zLkgpO1xuICAgIGxldCBjdXJyZW50X2NoYW5uZWxfbnVtYmVyID0gZ2xvYmFsX2lkeCAlIHVuaWZvcm1zLkM7XG5cbiAgICBsZXQgc2NhbGVfb2Zmc2V0ID0gY3VycmVudF9pbWFnZV9udW1iZXIgKiB1bmlmb3Jtcy5DICsgY3VycmVudF9jaGFubmVsX251bWJlcjtcbiAgICBsZXQgc2NhbGUgPSBzY2FsZV9pbnB1dFtzY2FsZV9vZmZzZXRdO1xuICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9IGZtYShpbnB1dFtnbG9iYWxfaWR4XSwgJHtzY2FsZURhdGEoMCl9LCAke3NjYWxlRGF0YSgxKX0pO1xuICB9YDtcbiAgfTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIHtcbiAgICAgIG5hbWU6ICdJbnN0YW5jZU5vcm1hbGl6YXRpb25OSFdDJyxcbiAgICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2NvbXBvbmVudHN9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICAgIH0pLFxuICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIH0sXG4gICAgeyBpbnB1dHM6IFtpbnB1dHNbMF0sIGNoYW5uZWxTY2FsZVNoaWZ0XSB9LFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGluc3RhbmNlTm9ybSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogSW5zdGFuY2VOb3JtQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBpZiAoYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJykge1xuICAgIGNyZWF0ZUluc3RhbmNlTm9ybU5IV0NQcm9ncmFtSW5mbyhjb250ZXh0LCBjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgY3JlYXRlSW5zdGFuY2VOb3JtUHJvZ3JhbUluZm8oY29udGV4dCwgY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjYXN0VG9GMzIsXG4gIGZpbGxWZWN0b3IsXG4gIGdldE1heENvbXBvbmVudHMsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHN1bVZlY3RvcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuXG5pbnRlcmZhY2UgTGF5ZXJOb3JtQXR0cmlidXRlcyB7XG4gIHNpbXBsaWZpZWQ6IGJvb2xlYW47XG4gIGF4aXM6IG51bWJlcjtcbiAgZXBzaWxvbjogbnVtYmVyO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoIDwgMikge1xuICAgIHRocm93IG5ldyBFcnJvcignbGF5ZXJOb3JtIHJlcXVpcmVzIGF0IGxlYXN0IDIgaW5wdXRzLicpO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVMYXllck5vcm1Qcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IExheWVyTm9ybUF0dHJpYnV0ZXMsXG4gIG91dHB1dENvdW50OiBudW1iZXIsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IHNpbXBsaWZpZWQgPSBhdHRyaWJ1dGVzLnNpbXBsaWZpZWQ7XG5cbiAgY29uc3QgeFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IHNjYWxlID0gaW5wdXRzWzFdO1xuICBjb25zdCBiaWFzID0gIXNpbXBsaWZpZWQgJiYgaW5wdXRzWzJdO1xuXG4gIGNvbnN0IG91dHB1dFNoYXBlID0geFNoYXBlO1xuICBjb25zdCBheGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXR0cmlidXRlcy5heGlzLCB4U2hhcGUubGVuZ3RoKTtcbiAgY29uc3Qgbm9ybUNvdW50ID0gU2hhcGVVdGlsLnNpemVUb0RpbWVuc2lvbih4U2hhcGUsIGF4aXMpO1xuICBjb25zdCBub3JtU2l6ZSA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbih4U2hhcGUsIGF4aXMpO1xuXG4gIGNvbnN0IHNjYWxlU2l6ZSA9IFNoYXBlVXRpbC5zaXplKHNjYWxlLmRpbXMpO1xuICBjb25zdCBiaWFzU2l6ZSA9IGJpYXMgPyBTaGFwZVV0aWwuc2l6ZShiaWFzLmRpbXMpIDogMDtcbiAgaWYgKHNjYWxlU2l6ZSAhPT0gbm9ybVNpemUgfHwgKGJpYXMgJiYgYmlhc1NpemUgIT09IG5vcm1TaXplKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgU2l6ZSBvZiBYLnNoYXBlKClbYXhpczpdID09ICR7bm9ybVNpemV9LlxuICAgICAgIFNpemUgb2Ygc2NhbGUgYW5kIGJpYXMgKGlmIHByb3ZpZGVkKSBtdXN0IG1hdGNoIHRoaXMuXG4gICAgICAgR290IHNjYWxlIHNpemUgb2YgJHtzY2FsZVNpemV9IGFuZCBiaWFzIHNpemUgb2YgJHtiaWFzU2l6ZX1gKTtcbiAgfVxuXG4gIGNvbnN0IG1lYW5JbnZTdGREZXZEaW06IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgeFNoYXBlLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGkgPCBheGlzKSB7XG4gICAgICBtZWFuSW52U3RkRGV2RGltLnB1c2goeFNoYXBlW2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbWVhbkludlN0ZERldkRpbS5wdXNoKDEpO1xuICAgIH1cbiAgfVxuICBjb25zdCBjb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhub3JtU2l6ZSk7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWyd0eXBlJywgJ3R5cGUnXTtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBub3JtQ291bnQgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBub3JtU2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBNYXRoLmZsb29yKG5vcm1TaXplIC8gY29tcG9uZW50cykgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhdHRyaWJ1dGVzLmVwc2lsb24gfSxcbiAgXTtcbiAgaWYgKGJpYXMpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgY29uc3QgaGFzTWVhbkRhdGFPdXRwdXQgPSBvdXRwdXRDb3VudCA+IDE7XG4gIGNvbnN0IGhhc0ludlN0ZE91dHB1dCA9IG91dHB1dENvdW50ID4gMjtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuICAgIGNvbnN0IHZhcmlhYmxlcyA9IFtcbiAgICAgIGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLCBjb21wb25lbnRzKSxcbiAgICAgIGlucHV0VmFyaWFibGUoJ3NjYWxlJywgc2NhbGUuZGF0YVR5cGUsIHNjYWxlLmRpbXMsIGNvbXBvbmVudHMpLFxuICAgIF07XG4gICAgaWYgKGJpYXMpIHtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKGlucHV0VmFyaWFibGUoJ2JpYXMnLCBiaWFzLmRhdGFUeXBlLCBiaWFzLmRpbXMsIGNvbXBvbmVudHMpKTtcbiAgICB9XG4gICAgdmFyaWFibGVzLnB1c2gob3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUsIGNvbXBvbmVudHMpKTtcbiAgICBpZiAoaGFzTWVhbkRhdGFPdXRwdXQpIHtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKG91dHB1dFZhcmlhYmxlKCdtZWFuX2RhdGFfb3V0cHV0JywgRGF0YVR5cGUuZmxvYXQsIG1lYW5JbnZTdGREZXZEaW0pKTtcbiAgICB9XG4gICAgaWYgKGhhc0ludlN0ZE91dHB1dCkge1xuICAgICAgdmFyaWFibGVzLnB1c2gob3V0cHV0VmFyaWFibGUoJ2ludl9zdGRfb3V0cHV0JywgRGF0YVR5cGUuZmxvYXQsIG1lYW5JbnZTdGREZXZEaW0pKTtcbiAgICB9XG5cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdub3JtX2NvdW50JywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ25vcm1fc2l6ZScsIHR5cGU6ICdmMzInIH0sXG4gICAgICB7IG5hbWU6ICdub3JtX3NpemVfdmVjdG9yaXplZCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdlcHNpbG9uJywgdHlwZTogJ2YzMicgfSxcbiAgICBdO1xuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4udmFyaWFibGVzKX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMubm9ybV9jb3VudCcpfVxuICAgIGxldCBvZmZzZXQgPSBnbG9iYWxfaWR4ICogdW5pZm9ybXMubm9ybV9zaXplX3ZlY3Rvcml6ZWQ7XG4gICAgdmFyIG1lYW5fdmVjdG9yID0gJHtmaWxsVmVjdG9yKCdmMzInLCBjb21wb25lbnRzKX07XG4gICAgdmFyIG1lYW5fc3F1YXJlX3ZlY3RvciA9ICR7ZmlsbFZlY3RvcignZjMyJywgY29tcG9uZW50cyl9O1xuXG4gICAgZm9yICh2YXIgaDogdTMyID0gMHU7IGggPCB1bmlmb3Jtcy5ub3JtX3NpemVfdmVjdG9yaXplZDsgaCsrKSB7XG4gICAgICBsZXQgdmFsdWUgPSAke2Nhc3RUb0YzMihkYXRhVHlwZSwgY29tcG9uZW50cywgJ3hbaCArIG9mZnNldF0nKX07XG4gICAgICBtZWFuX3ZlY3RvciArPSB2YWx1ZTtcbiAgICAgIG1lYW5fc3F1YXJlX3ZlY3RvciArPSB2YWx1ZSAqIHZhbHVlO1xuICAgIH1cbiAgICBsZXQgbWVhbiA9ICR7c3VtVmVjdG9yKCdtZWFuX3ZlY3RvcicsIGNvbXBvbmVudHMpfSAvIHVuaWZvcm1zLm5vcm1fc2l6ZTtcbiAgICBsZXQgaW52X3N0ZF9kZXYgPSBpbnZlcnNlU3FydCgke3N1bVZlY3RvcignbWVhbl9zcXVhcmVfdmVjdG9yJywgY29tcG9uZW50cyl9IC8gdW5pZm9ybXMubm9ybV9zaXplICR7XG4gICAgICBzaW1wbGlmaWVkID8gJycgOiAnLSBtZWFuICogbWVhbidcbiAgICB9ICsgdW5pZm9ybXMuZXBzaWxvbik7XG5cbiAgICBmb3IgKHZhciBqOiB1MzIgPSAwOyBqIDwgdW5pZm9ybXMubm9ybV9zaXplX3ZlY3Rvcml6ZWQ7IGorKykge1xuICAgICAgbGV0IGYzMmlucHV0ID0gJHtjYXN0VG9GMzIoZGF0YVR5cGUsIGNvbXBvbmVudHMsICd4W2ogKyBvZmZzZXRdJyl9O1xuICAgICAgbGV0IGYzMnNjYWxlID0gJHtjYXN0VG9GMzIoZGF0YVR5cGUsIGNvbXBvbmVudHMsICdzY2FsZVtqXScpfTtcbiAgICAgIG91dHB1dFtqICsgb2Zmc2V0XSA9ICR7dmFyaWFibGVzWzBdLnR5cGUudmFsdWV9KChmMzJpbnB1dCAke3NpbXBsaWZpZWQgPyAnJyA6ICctIG1lYW4nfSkgKiBpbnZfc3RkX2RldiAqIGYzMnNjYWxlXG4gICAgICAgICR7YmlhcyA/IGArICR7Y2FzdFRvRjMyKGRhdGFUeXBlLCBjb21wb25lbnRzLCAnYmlhc1tqXScpfWAgOiAnJ31cbiAgICAgICk7XG4gICAgfVxuXG4gICAgJHtoYXNNZWFuRGF0YU91dHB1dCA/ICdtZWFuX2RhdGFfb3V0cHV0W2dsb2JhbF9pZHhdID0gbWVhbicgOiAnJ307XG4gICAgJHtoYXNJbnZTdGRPdXRwdXQgPyAnaW52X3N0ZF9vdXRwdXRbZ2xvYmFsX2lkeF0gPSBpbnZfc3RkX2RldicgOiAnJ307XG4gIH1gO1xuICB9O1xuICBjb25zdCBvdXRwdXRzID0gW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV07XG4gIGlmIChoYXNNZWFuRGF0YU91dHB1dCkge1xuICAgIG91dHB1dHMucHVzaCh7IGRpbXM6IG1lYW5JbnZTdGREZXZEaW0sIGRhdGFUeXBlOiBEYXRhVHlwZS5mbG9hdCB9KTtcbiAgfVxuICBpZiAoaGFzSW52U3RkT3V0cHV0KSB7XG4gICAgb3V0cHV0cy5wdXNoKHsgZGltczogbWVhbkludlN0ZERldkRpbSwgZGF0YVR5cGU6IERhdGFUeXBlLmZsb2F0IH0pO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnTGF5ZXJOb3JtYWxpemF0aW9uJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtjb21wb25lbnRzfTske291dHB1dENvdW50fTske3NpbXBsaWZpZWR9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0cyxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG5vcm1Db3VudCAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBsYXllck5vcm0gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IExheWVyTm9ybUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlTGF5ZXJOb3JtUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMsIGNvbnRleHQub3V0cHV0Q291bnQpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBCcm9hZGNhc3RVdGlsLCBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0IH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVOYWl2ZU1hdG11bFByb2dyYW1JbmZvIH0gZnJvbSAnLi9tYXRtdWwtc2hhZGVycyc7XG5pbXBvcnQgeyBjcmVhdGVNYXRtdWxQcm9ncmFtSW5mbyB9IGZyb20gJy4vM3JkLXBhcnR5L21hdG11bF9wYWNrZWRfd2ViZ3B1JztcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignTWF0TXVsIHJlcXVpcmVzIDIgaW5wdXRzLicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zW2lucHV0c1swXS5kaW1zLmxlbmd0aCAtIDFdICE9PSBpbnB1dHNbMV0uZGltc1tpbnB1dHNbMV0uZGltcy5sZW5ndGggLSAyXSkge1xuICAgIHRocm93IG5ldyBFcnJvcignc2hhcmVkIGRpbWVuc2lvbiBkb2VzIG5vdCBtYXRjaC4nKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IG1hdE11bCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gQnJvYWRjYXN0VXRpbC5jYWxjU2hhcGUoY29udGV4dC5pbnB1dHNbMF0uZGltcywgY29udGV4dC5pbnB1dHNbMV0uZGltcywgdHJ1ZSk7XG4gIGlmICghb3V0cHV0U2hhcGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4ndCB1c2UgbWF0bXVsIG9uIHRoZSBnaXZlbiB0ZW5zb3JzXCIpO1xuICB9XG4gIGNvbnN0IE4gPSBvdXRwdXRTaGFwZVtvdXRwdXRTaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3QgSyA9IGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbY29udGV4dC5pbnB1dHNbMF0uZGltcy5sZW5ndGggLSAxXTtcbiAgaWYgKE4gPCA4ICYmIEsgPCA4KSB7XG4gICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZU5haXZlTWF0bXVsUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIHsgYWN0aXZhdGlvbjogJycgfSwgb3V0cHV0U2hhcGUpKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBNID0gb3V0cHV0U2hhcGVbb3V0cHV0U2hhcGUubGVuZ3RoIC0gMl07XG4gICAgY29uc3QgYmF0Y2hBID0gU2hhcGVVdGlsLnNpemUoY29udGV4dC5pbnB1dHNbMF0uZGltcy5zbGljZSgwLCAtMikpO1xuICAgIGNvbnN0IGJhdGNoQiA9IFNoYXBlVXRpbC5zaXplKGNvbnRleHQuaW5wdXRzWzFdLmRpbXMuc2xpY2UoMCwgLTIpKTtcbiAgICBpZiAoYmF0Y2hBICE9PSAxICYmIE0gPT09IDEgJiYgYmF0Y2hCID09PSAxKSB7XG4gICAgICAvLyBPcHRpbWl6YXRpb24gZm9yIGJhdGNoZWQgdmVjLW1hdC1tdWxcbiAgICAgIGNvbnN0IHJlc2hhcGVkQSA9IGNvbnRleHQuaW5wdXRzWzBdLnJlc2hhcGUoWzEsIGJhdGNoQSwgS10pO1xuICAgICAgY29uc3QgcmVzaGFwZWRCID0gY29udGV4dC5pbnB1dHNbMV0ucmVzaGFwZShbMSwgSywgTl0pO1xuICAgICAgY29uc3QgbWF0bXVsT3V0cHV0U2hhcGUgPSBbMSwgYmF0Y2hBLCBOXTtcbiAgICAgIGNvbnN0IG1hdG11bElucHV0cyA9IFtyZXNoYXBlZEEsIHJlc2hhcGVkQl07XG4gICAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm8obWF0bXVsSW5wdXRzLCB7IGFjdGl2YXRpb246ICcnIH0sIG91dHB1dFNoYXBlLCBtYXRtdWxPdXRwdXRTaGFwZSksIHtcbiAgICAgICAgaW5wdXRzOiBtYXRtdWxJbnB1dHMsXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCB7IGFjdGl2YXRpb246ICcnIH0sIG91dHB1dFNoYXBlKSk7XG4gICAgfVxuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRNYXhDb21wb25lbnRzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuLy8gIFRPRE8gc3VwcG9ydCBxdWFudGl6YXRpb24gYml0cyBub3QgZXF1YWwgdG8gNFxuZXhwb3J0IGludGVyZmFjZSBNYXRNdWxOQml0c0F0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICBrOiBudW1iZXI7XG4gIG46IG51bWJlcjtcbiAgYWNjdXJhY3lMZXZlbDogbnVtYmVyO1xuICBiaXRzOiBudW1iZXI7XG4gIGJsb2NrU2l6ZTogbnVtYmVyO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogTWF0TXVsTkJpdHNBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmIChpbnB1dHMubGVuZ3RoIDwgMyB8fCBpbnB1dHMubGVuZ3RoID4gNCkge1xuICAgIHRocm93IG5ldyBFcnJvcignTWF0TXVsTkJpdHMgcmVxdWlyZXMgMyBvciA0IGlucHV0cycpO1xuICB9XG4gIGNvbnN0IGEgPSBpbnB1dHNbMF07XG4gIGNvbnN0IGFSYW5rID0gYS5kaW1zLmxlbmd0aDtcbiAgaWYgKGEuZGltc1thUmFuayAtIDFdICE9PSBhdHRyaWJ1dGVzLmspIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBsYXN0IGRpbSBvZiBpbnB1dCBzaGFwZSBkb2VzIG5vdCBtYXRjaCB0aGUgayB2YWx1ZScpO1xuICB9XG4gIGNvbnN0IG5CbG9ja3NQZXJDb2wgPSBNYXRoLmZsb29yKChhdHRyaWJ1dGVzLmsgKyBhdHRyaWJ1dGVzLmJsb2NrU2l6ZSAtIDEpIC8gYXR0cmlidXRlcy5ibG9ja1NpemUpO1xuICBjb25zdCBibG9iU2l6ZSA9IChhdHRyaWJ1dGVzLmJsb2NrU2l6ZSAvIDgpICogYXR0cmlidXRlcy5iaXRzO1xuICBjb25zdCBiID0gaW5wdXRzWzFdO1xuICBpZiAoIVNoYXBlVXRpbC5hcmVFcXVhbChiLmRpbXMsIFthdHRyaWJ1dGVzLm4sIG5CbG9ja3NQZXJDb2wsIGJsb2JTaXplXSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBzZWNvbmQgaW5wdXRzIG11c3QgYmUgM0QgdGVuc29yIHdpdGggc2hhcGUgTiBYIG5CbG9ja3NQZXJDb2wgWCBibG9iU2l6ZScpO1xuICB9XG4gIGNvbnN0IHNjYWxlcyA9IGlucHV0c1syXTtcbiAgY29uc3Qgc2NhbGVzU2hhcGUgPSBzY2FsZXMuZGltcztcbiAgaWYgKFNoYXBlVXRpbC5zaXplKHNjYWxlc1NoYXBlKSAhPT0gYXR0cmlidXRlcy5uICogbkJsb2Nrc1BlckNvbCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc2NhbGVzIGlucHV0IHNpemUgZXJyb3IuJyk7XG4gIH1cbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDQpIHtcbiAgICBjb25zdCB6ZXJvUG9pbnRzID0gaW5wdXRzWzNdO1xuICAgIGNvbnN0IHplcm9Qb2ludHNTaGFwZSA9IHplcm9Qb2ludHMuZGltcztcbiAgICBjb25zdCBleHBlY3RlZFplcm9Qb2ludHNTaXplID1cbiAgICAgIGF0dHJpYnV0ZXMuYml0cyA+IDQgPyBhdHRyaWJ1dGVzLm4gKiBuQmxvY2tzUGVyQ29sIDogYXR0cmlidXRlcy5uICogTWF0aC5mbG9vcigobkJsb2Nrc1BlckNvbCArIDEpIC8gMik7XG4gICAgaWYgKFNoYXBlVXRpbC5zaXplKHplcm9Qb2ludHNTaGFwZSkgIT09IGV4cGVjdGVkWmVyb1BvaW50c1NpemUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignemVyb1BvaW50cyBpbnB1dCBzaXplIGVycm9yLicpO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZU1hdE11bE5CaXRzUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBNYXRNdWxOQml0c0F0dHJpYnV0ZXMsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgYVJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcbiAgY29uc3QgZGltQU91dGVyID0gaW5wdXRTaGFwZVthUmFuayAtIDJdO1xuICBjb25zdCBkaW1Jbm5lciA9IGF0dHJpYnV0ZXMuaztcbiAgY29uc3QgZGltQk91dGVyID0gYXR0cmlidXRlcy5uO1xuICBjb25zdCBiYXRjaERpbXMgPSBpbnB1dFNoYXBlLnNsaWNlKDAsIGFSYW5rIC0gMik7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IFNoYXBlVXRpbC5zaXplKGJhdGNoRGltcyk7XG4gIGNvbnN0IGJsb2JTaXplID0gaW5wdXRzWzFdLmRpbXNbMl07XG4gIGNvbnN0IGJsb2JTaXplSW5Xb3JkcyA9IGJsb2JTaXplIC8gNDtcbiAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dHNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IGFDb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhhdHRyaWJ1dGVzLmspO1xuICBjb25zdCBiQ29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoYmxvYlNpemVJbldvcmRzKTtcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoZGltQk91dGVyKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBiYXRjaERpbXMuY29uY2F0KFtkaW1BT3V0ZXIsIGRpbUJPdXRlcl0pO1xuICBjb25zdCBvdXRwdXROdW1iZXIgPSBkaW1BT3V0ZXIgPiAxICYmIChkaW1CT3V0ZXIgLyBjb21wb25lbnRzKSAlIDIgPT09IDAgPyAyIDogMTtcbiAgY29uc3QgZGlzcGF0Y2hTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gY29tcG9uZW50cyAvIG91dHB1dE51bWJlcjtcblxuICBjb25zdCB3b3JrZ3JvdXBTaXplID0gNjQ7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW107XG4gIGNvbnN0IGlucHV0U2hhcGVUZW1wID0gW2JhdGNoU2l6ZSwgZGltQU91dGVyLCBkaW1Jbm5lciAvIGFDb21wb25lbnRzXTtcbiAgY29uc3QgYlNoYXBlID0gU2hhcGVVdGlsLmNvbnZlcnRTaGFwZShpbnB1dHNbMV0uZGltcykuc2xpY2UoKTtcbiAgYlNoYXBlLnNwbGljZSgtMSwgMSwgYmxvYlNpemVJbldvcmRzIC8gYkNvbXBvbmVudHMpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlVGVtcCkpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhiU2hhcGUpKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzJdLmRpbXMpKTtcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDQpIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhTaGFwZVV0aWwuY29udmVydFNoYXBlKGlucHV0c1szXS5kaW1zKSkpO1xuICB9XG4gIGNvbnN0IG91dHB1dFNoYXBlVGVtcCA9IFtiYXRjaFNpemUsIGRpbUFPdXRlciwgZGltQk91dGVyIC8gY29tcG9uZW50c107XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlVGVtcCkpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlucHV0UmFuayA9IGlucHV0U2hhcGVUZW1wLmxlbmd0aDtcbiAgICBjb25zdCBhID0gaW5wdXRWYXJpYWJsZSgnYScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRSYW5rLCBhQ29tcG9uZW50cyk7XG4gICAgY29uc3QgYiA9IGlucHV0VmFyaWFibGUoJ2InLCBEYXRhVHlwZS51aW50MzIsIGJTaGFwZS5sZW5ndGgsIGJDb21wb25lbnRzKTtcbiAgICBjb25zdCBzY2FsZXMgPSBpbnB1dFZhcmlhYmxlKCdzY2FsZXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgaW5wdXRWYXJpYWJsZXMgPSBbYSwgYiwgc2NhbGVzXTtcbiAgICBjb25zdCB6ZXJvUG9pbnRzID1cbiAgICAgIGlucHV0cy5sZW5ndGggPT09IDQgPyBpbnB1dFZhcmlhYmxlKCd6ZXJvX3BvaW50cycsIERhdGFUeXBlLnVpbnQzMiwgaW5wdXRzWzNdLmRpbXMubGVuZ3RoKSA6IHVuZGVmaW5lZDtcbiAgICBpZiAoemVyb1BvaW50cykge1xuICAgICAgaW5wdXRWYXJpYWJsZXMucHVzaCh6ZXJvUG9pbnRzKTtcbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0UmFuayA9IG91dHB1dFNoYXBlVGVtcC5sZW5ndGg7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0UmFuaywgY29tcG9uZW50cyk7XG4gICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcblxuICAgIGNvbnN0IHFEcURhdGFUeXBlID0gKCgpID0+IHtcbiAgICAgIHN3aXRjaCAoYUNvbXBvbmVudHMpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIHJldHVybiBgYXJyYXk8JHtkYXRhVHlwZX0sIDg+YDtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHJldHVybiBgbWF0NHgyPCR7ZGF0YVR5cGV9PmA7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICByZXR1cm4gYG1hdDJ4NDwke2RhdGFUeXBlfT5gO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHthQ29tcG9uZW50c30tY29tcG9uZW50IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gICAgICB9XG4gICAgfSkoKTtcblxuICAgIGNvbnN0IHByb2Nlc3NPbmVXb3JkID0gKCk6IHN0cmluZyA9PiB7XG4gICAgICBsZXQgY2FsY1N0ciA9IGBcbiAgICAgICAgICAvLyByZXVzZSBhIGRhdGFcbiAgICAgICAgICAgIHZhciBpbnB1dF9vZmZzZXQgPSAke2EuaW5kaWNlc1RvT2Zmc2V0KGAke2EudHlwZS5pbmRpY2VzfShiYXRjaCwgcm93LCB3b3JkX29mZnNldClgKX07XG4gICAgICAgICAgICB2YXIgYV9kYXRhOiAke3FEcURhdGFUeXBlfTtcbiAgICAgICAgICAgIGZvciAodmFyIGo6IHUzMiA9IDA7IGogPCAkezggLyBhQ29tcG9uZW50c307IGorKykge1xuICAgICAgICAgICAgICBhX2RhdGFbal0gPSAke2EuZ2V0QnlPZmZzZXQoJ2lucHV0X29mZnNldCcpfTtcbiAgICAgICAgICAgICAgaW5wdXRfb2Zmc2V0Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgYDtcbiAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgY29tcG9uZW50cyAqIG91dHB1dE51bWJlcjsgYysrKSB7XG4gICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgICAgYl92YWx1ZSA9ICR7YkNvbXBvbmVudHMgPT09IDEgPyBgYiR7Y31fZGF0YWAgOiBgYiR7Y31fZGF0YVtpXWB9O1xuICAgICAgICAgICAgYl92YWx1ZV9sb3dlciA9IHVucGFjazR4VTgoYl92YWx1ZSAmIGJfbWFzayk7XG4gICAgICAgICAgICBiX3ZhbHVlX3VwcGVyID0gdW5wYWNrNHhVOCgoYl92YWx1ZSA+PiA0KSAmIGJfbWFzayk7XG4gICAgICAgICAgICBiX3F1YW50aXplZF92YWx1ZXMgPSAke3FEcURhdGFUeXBlfSgke0FycmF5LmZyb20oXG4gICAgICAgICAgICAgIHsgbGVuZ3RoOiA0IH0sXG4gICAgICAgICAgICAgIChfLCBpKSA9PiBgJHtkYXRhVHlwZX0oYl92YWx1ZV9sb3dlclske2l9XSksICR7ZGF0YVR5cGV9KGJfdmFsdWVfdXBwZXJbJHtpfV0pYCxcbiAgICAgICAgICAgICkuam9pbignLCAnKX0pO1xuICAgICAgICAgICAgYl9kZXF1YW50aXplZF92YWx1ZXMgPSAkeygoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChhQ29tcG9uZW50cyA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBgJHtxRHFEYXRhVHlwZX0oJHtBcnJheS5mcm9tKFxuICAgICAgICAgICAgICAgICAgeyBsZW5ndGg6IDggfSxcbiAgICAgICAgICAgICAgICAgIChfLCBpKSA9PiBgKGJfcXVhbnRpemVkX3ZhbHVlc1ske2l9XSAtICR7emVyb1BvaW50cyA/IGB6ZXJvX3BvaW50JHtjfWAgOiAnemVyb19wb2ludCd9KSAqIHNjYWxlJHtjfWAsXG4gICAgICAgICAgICAgICAgKS5qb2luKCcsICcpfSk7YDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYChiX3F1YW50aXplZF92YWx1ZXMgLSAke3FEcURhdGFUeXBlfSgke0FycmF5KDgpXG4gICAgICAgICAgICAgICAgICAuZmlsbChgJHt6ZXJvUG9pbnRzID8gYHplcm9fcG9pbnQke2N9YCA6ICd6ZXJvX3BvaW50J31gKVxuICAgICAgICAgICAgICAgICAgLmpvaW4oJywnKX0pKSAqIHNjYWxlJHtjfTtgO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSgpfTtcbiAgICAgICAgICAgIHdvcmtncm91cF9zaGFyZWRbbG9jYWxfaWQueCAqICR7b3V0cHV0TnVtYmVyfSArICR7TWF0aC5mbG9vcihjIC8gY29tcG9uZW50cyl9XSR7Y29tcG9uZW50cyA+IDEgPyBgWyR7YyAlIGNvbXBvbmVudHN9XWAgOiAnJ30gKz0gJHtBcnJheS5mcm9tKFxuICAgICAgICAgICAgICB7IGxlbmd0aDogOCAvIGFDb21wb25lbnRzIH0sXG4gICAgICAgICAgICAgIChfLCBpKSA9PlxuICAgICAgICAgICAgICAgIGAke1xuICAgICAgICAgICAgICAgICAgYUNvbXBvbmVudHMgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgPyBgYV9kYXRhWyR7aX1dICogYl9kZXF1YW50aXplZF92YWx1ZXNbJHtpfV1gXG4gICAgICAgICAgICAgICAgICAgIDogYGRvdChhX2RhdGFbJHtpfV0sIGJfZGVxdWFudGl6ZWRfdmFsdWVzWyR7aX1dKWBcbiAgICAgICAgICAgICAgICB9YCxcbiAgICAgICAgICAgICkuam9pbignICsgJyl9O1xuICAgICAgICAgIGA7XG4gICAgICB9XG4gICAgICByZXR1cm4gY2FsY1N0cjtcbiAgICB9O1xuICAgIGNvbnN0IHByZXBhcmVTY2FsZUFuZFplcm9Qb2ludCA9ICgpOiBzdHJpbmcgPT4ge1xuICAgICAgbGV0IGNhbGNTdHIgPSBgXG4gICAgICAgICAgICB2YXIgY29sX2luZGV4ID0gY29sICogJHtjb21wb25lbnRzfTtcbiAgICAgICAgICAgICR7XG4gICAgICAgICAgICAgIHplcm9Qb2ludHNcbiAgICAgICAgICAgICAgICA/IGBcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2J5dGVzX3Blcl9jb2wgPSAobkJsb2Nrc1BlckNvbCArIDEpIC8gMjtcbiAgICAgICAgICAgIHZhciB6ZXJvX3BvaW50X2J5dGVfY291bnQ6IHUzMjtcbiAgICAgICAgICAgIHZhciB6ZXJvX3BvaW50X3dvcmRfaW5kZXg6IHUzMjtcbiAgICAgICAgICAgIHZhciB6ZXJvX3BvaW50X2J5dGVfb2Zmc2V0OiB1MzI7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9uaWJibGVfb2Zmc2V0OiB1MzIgPSBibG9jayAmIDB4MXU7XG4gICAgICAgICAgICB2YXIgemVyb19wb2ludF9iaXRzX29mZnNldDogdTMyO1xuICAgICAgICAgICAgdmFyIHplcm9fcG9pbnRfd29yZDogdTMyO2BcbiAgICAgICAgICAgICAgICA6IGBcbiAgICAgICAgICAgIC8vIFRoZSBkZWZhdWx0IHplcm8gcG9pbnQgaXMgOCBmb3IgdW5zaWduZWQgNC1iaXQgcXVhbnRpemF0aW9uLlxuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnQgPSAke2RhdGFUeXBlfSgkezguMH0pO2BcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGA7XG4gICAgICBmb3IgKGxldCBjID0gMDsgYyA8IGNvbXBvbmVudHMgKiBvdXRwdXROdW1iZXI7IGMrKykge1xuICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICAgIGxldCBzY2FsZSR7Y30gPSAke3NjYWxlcy5nZXRCeU9mZnNldChgY29sX2luZGV4ICogbkJsb2Nrc1BlckNvbCArIGJsb2NrYCl9O1xuICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgemVyb1BvaW50c1xuICAgICAgICAgICAgICAgID8gYFxuICAgICAgICAgICAgemVyb19wb2ludF9ieXRlX2NvdW50ID0gY29sX2luZGV4ICogemVyb19wb2ludF9ieXRlc19wZXJfY29sICsgKGJsb2NrID4+IDB4MXUpO1xuICAgICAgICAgICAgemVyb19wb2ludF93b3JkX2luZGV4ID0gemVyb19wb2ludF9ieXRlX2NvdW50ID4+IDB4MnU7XG4gICAgICAgICAgICB6ZXJvX3BvaW50X2J5dGVfb2Zmc2V0ID0gemVyb19wb2ludF9ieXRlX2NvdW50ICYgMHgzdTtcbiAgICAgICAgICAgIHplcm9fcG9pbnRfYml0c19vZmZzZXQgPSAoemVyb19wb2ludF9ieXRlX29mZnNldCA8PCAzKSArICh6ZXJvX3BvaW50X25pYmJsZV9vZmZzZXQgPDwgMik7XG4gICAgICAgICAgICB6ZXJvX3BvaW50X3dvcmQgPSAke3plcm9Qb2ludHMuZ2V0QnlPZmZzZXQoJ3plcm9fcG9pbnRfd29yZF9pbmRleCcpfSA+PiB6ZXJvX3BvaW50X2JpdHNfb2Zmc2V0O1xuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnQke2N9ID0gJHtkYXRhVHlwZX0oKHplcm9fcG9pbnRfd29yZCkgJiAweEZ1KTtgXG4gICAgICAgICAgICAgICAgOiAnJ1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29sX2luZGV4ICs9IDE7YDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjYWxjU3RyO1xuICAgIH07XG4gICAgY29uc3QgcHJlcGFyZUJEYXRhID0gKCk6IHN0cmluZyA9PiB7XG4gICAgICBsZXQgY2FsY1N0ciA9IGBjb2xfaW5kZXggPSBjb2wgKiAke2NvbXBvbmVudHN9O2A7XG4gICAgICBmb3IgKGxldCBjID0gMDsgYyA8IGNvbXBvbmVudHMgKiBvdXRwdXROdW1iZXI7IGMrKykge1xuICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICAgIGxldCBiJHtjfV9kYXRhID0gJHtiLmdldEJ5SW5kaWNlcyhgJHtiLnR5cGUuaW5kaWNlc30oY29sX2luZGV4LCBibG9jaywgd29yZClgKX07XG4gICAgICAgICAgICBjb2xfaW5kZXggKz0gMTtgO1xuICAgICAgfVxuICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgICB2YXIgYl92YWx1ZTogdTMyO1xuICAgICAgICAgICAgbGV0IGJfbWFzazogdTMyID0gMHgwRjBGMEYwRnU7XG4gICAgICAgICAgICB2YXIgYl92YWx1ZV9sb3dlcjogdmVjNDx1MzI+O1xuICAgICAgICAgICAgdmFyIGJfdmFsdWVfdXBwZXI6IHZlYzQ8dTMyPjtcbiAgICAgICAgICAgIHZhciBiX3F1YW50aXplZF92YWx1ZXM6ICR7cURxRGF0YVR5cGV9O1xuICAgICAgICAgICAgdmFyIGJfZGVxdWFudGl6ZWRfdmFsdWVzOiAke3FEcURhdGFUeXBlfTtgO1xuICAgICAgcmV0dXJuIGNhbGNTdHI7XG4gICAgfTtcbiAgICByZXR1cm4gYFxuICAgICAgICB2YXI8d29ya2dyb3VwPiB3b3JrZ3JvdXBfc2hhcmVkOiBhcnJheTwke291dHB1dC50eXBlLnZhbHVlfSwgJHtvdXRwdXROdW1iZXIgKiB3b3JrZ3JvdXBTaXplfT47XG4gICAgICAgICR7c2hhZGVySGVscGVyLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydChbd29ya2dyb3VwU2l6ZSwgMSwgMV0pfVxuICAgICAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgKGdsb2JhbF9pZHggLyAke3dvcmtncm91cFNpemV9KSAqICR7b3V0cHV0TnVtYmVyfWApfTtcbiAgICAgICAgICBsZXQgY29sID0gb3V0cHV0X2luZGljZXNbMl07XG4gICAgICAgICAgbGV0IHJvdyA9IG91dHB1dF9pbmRpY2VzWzFdO1xuICAgICAgICAgIGxldCBiYXRjaCA9IG91dHB1dF9pbmRpY2VzWzBdO1xuICAgICAgICAgIGxldCBuQmxvY2tzUGVyQ29sID0gdW5pZm9ybXMuYl9zaGFwZVsxXTtcblxuICAgICAgICAgIGZvciAodmFyIGJsb2NrID0gbG9jYWxfaWQueDsgYmxvY2sgPCBuQmxvY2tzUGVyQ29sOyBibG9jayArPSAke3dvcmtncm91cFNpemV9KSB7XG4gICAgICAgICAgICAvL3Byb2Nlc3Mgb25lIGJsb2NrXG4gICAgICAgICAgICB2YXIgd29yZF9vZmZzZXQ6IHUzMiA9IGJsb2NrICogJHthdHRyaWJ1dGVzLmJsb2NrU2l6ZSAvIGFDb21wb25lbnRzfTtcbiAgICAgICAgICAgICR7cHJlcGFyZVNjYWxlQW5kWmVyb1BvaW50KCl9XG4gICAgICAgICAgICBmb3IgKHZhciB3b3JkOiB1MzIgPSAwOyB3b3JkIDwgJHtibG9iU2l6ZUluV29yZHN9OyB3b3JkICs9ICR7YkNvbXBvbmVudHN9KSB7XG4gICAgICAgICAgICAgICR7cHJlcGFyZUJEYXRhKCl9XG4gICAgICAgICAgICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCAke2JDb21wb25lbnRzfTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgJHtwcm9jZXNzT25lV29yZCgpfVxuICAgICAgICAgICAgICAgIHdvcmRfb2Zmc2V0ICs9ICR7OCAvIGFDb21wb25lbnRzfTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgICAgICBpZiAobG9jYWxfaWQueCA8ICR7b3V0cHV0TnVtYmVyfSkge1xuICAgICAgICAgICAgdmFyIG91dHB1dF92YWx1ZTogJHtvdXRwdXQudHlwZS52YWx1ZX0gPSAke291dHB1dC50eXBlLnZhbHVlfSgwKTtcbiAgICAgICAgICAgIHZhciB3b3JrZ3JvdXBfc2hhcmVkX29mZnNldDogdTMyID0gbG9jYWxfaWQueDtcbiAgICAgICAgICAgIGZvciAodmFyIGI6IHUzMiA9IDB1OyBiIDwgJHt3b3JrZ3JvdXBTaXplfXU7IGIrKykge1xuICAgICAgICAgICAgICBvdXRwdXRfdmFsdWUgKz0gd29ya2dyb3VwX3NoYXJlZFt3b3JrZ3JvdXBfc2hhcmVkX29mZnNldF07XG4gICAgICAgICAgICAgIHdvcmtncm91cF9zaGFyZWRfb2Zmc2V0ICs9ICR7b3V0cHV0TnVtYmVyfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5SW5kaWNlcyhgJHtvdXRwdXQudHlwZS5pbmRpY2VzfShiYXRjaCwgcm93LCBjb2wgKyBsb2NhbF9pZC54KWAsICdvdXRwdXRfdmFsdWUnKX07XG4gICAgICAgICAgfVxuICAgICAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnTWF0TXVsTkJpdHMnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmJsb2NrU2l6ZX07JHthdHRyaWJ1dGVzLmJpdHN9OyR7YUNvbXBvbmVudHN9OyR7YkNvbXBvbmVudHN9OyR7Y29tcG9uZW50c307JHtvdXRwdXROdW1iZXJ9OyR7d29ya2dyb3VwU2l6ZX1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IEFycmF5KGlucHV0cy5sZW5ndGgpLmZpbGwoJ3JhbmsnKSxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IGRpc3BhdGNoU2l6ZSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbi8vIEN1cnJlbnRseSwgb25seSBzdXBwb3J0IGJsb2NrU2l6ZSA9IDMyLlxuZXhwb3J0IGNvbnN0IGNyZWF0ZU1hdE11bE5CaXRzQmxvY2tTaXplMzJQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IE1hdE11bE5CaXRzQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBhUmFuayA9IGlucHV0U2hhcGUubGVuZ3RoO1xuICBjb25zdCBkaW1BT3V0ZXIgPSBpbnB1dFNoYXBlW2FSYW5rIC0gMl07XG4gIGNvbnN0IGRpbUlubmVyID0gYXR0cmlidXRlcy5rO1xuICBjb25zdCBkaW1CT3V0ZXIgPSBhdHRyaWJ1dGVzLm47XG4gIGNvbnN0IGJhdGNoRGltcyA9IGlucHV0U2hhcGUuc2xpY2UoMCwgYVJhbmsgLSAyKTtcbiAgY29uc3QgYmF0Y2hTaXplID0gU2hhcGVVdGlsLnNpemUoYmF0Y2hEaW1zKTtcbiAgY29uc3QgYmxvYlNpemUgPSBpbnB1dHNbMV0uZGltc1syXTtcbiAgY29uc3QgYmxvYlNpemVJbldvcmRzID0gYmxvYlNpemUgLyA0O1xuICBjb25zdCBkYXRhVHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgYUNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKGF0dHJpYnV0ZXMuayk7XG4gIGNvbnN0IGJDb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhibG9iU2l6ZUluV29yZHMpO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGJhdGNoRGltcy5jb25jYXQoW2RpbUFPdXRlciwgZGltQk91dGVyXSk7XG5cbiAgY29uc3Qgd29ya2dyb3VwU2l6ZSA9IDEyODtcbiAgY29uc3Qgd29ya2dyb3VwWSA9IGRpbUJPdXRlciAlIDggPT09IDAgPyA4IDogZGltQk91dGVyICUgNCA9PT0gMCA/IDQgOiAxO1xuICBjb25zdCB3b3JrZ3JvdXBYID0gd29ya2dyb3VwU2l6ZSAvIHdvcmtncm91cFk7XG4gIGNvbnN0IHRpbGVTaXplID0gd29ya2dyb3VwWCAqIGJDb21wb25lbnRzICogODsgLy8gZWFjaCB1aW50MzIgaGFzIDggZGF0YS5cbiAgY29uc3QgYUxlbmd0aFBlclRpbGUgPSB0aWxlU2l6ZSAvIGFDb21wb25lbnRzO1xuICBjb25zdCBibG9ja3NQZXJUaWxlID0gdGlsZVNpemUgLyBhdHRyaWJ1dGVzLmJsb2NrU2l6ZTtcbiAgY29uc3QgZGlzcGF0Y2hTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gd29ya2dyb3VwWTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXTtcbiAgY29uc3QgaW5wdXRTaGFwZVRlbXAgPSBbYmF0Y2hTaXplLCBkaW1BT3V0ZXIsIGRpbUlubmVyIC8gYUNvbXBvbmVudHNdO1xuICBjb25zdCBiU2hhcGUgPSBTaGFwZVV0aWwuY29udmVydFNoYXBlKGlucHV0c1sxXS5kaW1zKS5zbGljZSgpO1xuICBiU2hhcGUuc3BsaWNlKC0xLCAxLCBibG9iU2l6ZUluV29yZHMgLyBiQ29tcG9uZW50cyk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0U2hhcGVUZW1wKSk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGJTaGFwZSkpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMl0uZGltcykpO1xuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gNCkge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKFNoYXBlVXRpbC5jb252ZXJ0U2hhcGUoaW5wdXRzWzNdLmRpbXMpKSk7XG4gIH1cbiAgY29uc3Qgb3V0cHV0U2hhcGVUZW1wID0gW2JhdGNoU2l6ZSwgZGltQU91dGVyLCBkaW1CT3V0ZXJdO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRwdXRTaGFwZVRlbXApKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBpbnB1dFJhbmsgPSBpbnB1dFNoYXBlVGVtcC5sZW5ndGg7XG4gICAgY29uc3QgYSA9IGlucHV0VmFyaWFibGUoJ2EnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0UmFuaywgYUNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGIgPSBpbnB1dFZhcmlhYmxlKCdiJywgRGF0YVR5cGUudWludDMyLCBiU2hhcGUubGVuZ3RoLCBiQ29tcG9uZW50cyk7XG4gICAgY29uc3Qgc2NhbGVzID0gaW5wdXRWYXJpYWJsZSgnc2NhbGVzJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcy5sZW5ndGgpO1xuICAgIGNvbnN0IGlucHV0VmFyaWFibGVzID0gW2EsIGIsIHNjYWxlc107XG4gICAgY29uc3QgemVyb1BvaW50cyA9XG4gICAgICBpbnB1dHMubGVuZ3RoID09PSA0ID8gaW5wdXRWYXJpYWJsZSgnemVyb19wb2ludHMnLCBEYXRhVHlwZS51aW50MzIsIGlucHV0c1szXS5kaW1zLmxlbmd0aCkgOiB1bmRlZmluZWQ7XG4gICAgaWYgKHplcm9Qb2ludHMpIHtcbiAgICAgIGlucHV0VmFyaWFibGVzLnB1c2goemVyb1BvaW50cyk7XG4gICAgfVxuICAgIGNvbnN0IG91dHB1dFJhbmsgPSBvdXRwdXRTaGFwZVRlbXAubGVuZ3RoO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFJhbmspO1xuICAgIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKGlucHV0c1swXS5kYXRhVHlwZSk7XG4gICAgY29uc3QgcmVhZEEgPSAoKSA9PiB7XG4gICAgICBzd2l0Y2ggKGFDb21wb25lbnRzKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgIGxldCBhX2RhdGEwID0gdmVjNDwke2RhdGFUeXBlfT4oc3ViX2Fbd29yZF9vZmZzZXRdLCBzdWJfYVt3b3JkX29mZnNldCArIDFdLCBzdWJfYVt3b3JkX29mZnNldCArIDJdLCBzdWJfYVt3b3JkX29mZnNldCArIDNdKTtcbiAgICAgICAgICBsZXQgYV9kYXRhMSA9IHZlYzQ8JHtkYXRhVHlwZX0+KHN1Yl9hW3dvcmRfb2Zmc2V0ICsgNF0sIHN1Yl9hW3dvcmRfb2Zmc2V0ICsgNV0sIHN1Yl9hW3dvcmRfb2Zmc2V0ICsgNl0sIHN1Yl9hW3dvcmRfb2Zmc2V0ICsgN10pO2A7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgIGxldCBhX2RhdGEwID0gdmVjNDwke2RhdGFUeXBlfT4oc3ViX2Fbd29yZF9vZmZzZXRdLCBzdWJfYVt3b3JkX29mZnNldCArIDFdKTtcbiAgICAgICAgICBsZXQgYV9kYXRhMSA9IHZlYzQ8JHtkYXRhVHlwZX0+KHN1Yl9hW3dvcmRfb2Zmc2V0ICsgMl0sIHN1Yl9hW3dvcmRfb2Zmc2V0ICsgM10pO2A7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgIGxldCBhX2RhdGEwID0gc3ViX2Fbd29yZF9vZmZzZXRdO1xuICAgICAgICAgIGxldCBhX2RhdGExID0gc3ViX2Fbd29yZF9vZmZzZXQgKyAxXTtgO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHthQ29tcG9uZW50c30tY29tcG9uZW50IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBgXG4gICAgICAgIHZhcjx3b3JrZ3JvdXA+IHN1Yl9hOiBhcnJheTwke2EudHlwZS52YWx1ZX0sICR7YUxlbmd0aFBlclRpbGV9PjtcbiAgICAgICAgdmFyPHdvcmtncm91cD4gaW50ZXJfcmVzdWx0czogYXJyYXk8YXJyYXk8JHtvdXRwdXQudHlwZS52YWx1ZX0sICR7d29ya2dyb3VwWH0+LCAke3dvcmtncm91cFl9PjtcbiAgICAgICAgJHtzaGFkZXJIZWxwZXIuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcmlhYmxlcywgb3V0cHV0KX1cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFt3b3JrZ3JvdXBYLCB3b3JrZ3JvdXBZLCAxXSl9XG4gICAgICAgICAgbGV0IG91dHB1dF9pbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKGB3b3JrZ3JvdXBfaW5kZXggKiAke3dvcmtncm91cFl9YCl9O1xuICAgICAgICAgIGxldCBjb2wgPSBvdXRwdXRfaW5kaWNlc1syXTtcbiAgICAgICAgICBsZXQgcm93ID0gb3V0cHV0X2luZGljZXNbMV07XG4gICAgICAgICAgbGV0IGJhdGNoID0gb3V0cHV0X2luZGljZXNbMF07XG4gICAgICAgICAgbGV0IG5fYmxvY2tzX3Blcl9jb2wgPSB1bmlmb3Jtcy5iX3NoYXBlWzFdO1xuICAgICAgICAgIGxldCBudW1fdGlsZXMgPSAgKG5fYmxvY2tzX3Blcl9jb2wgLSAxKSAvICR7YmxvY2tzUGVyVGlsZX0gKyAxO1xuXG4gICAgICAgICAgLy8gTG9vcCBvdmVyIHNoYXJlZCBkaW1lbnNpb24uXG4gICAgICAgICAgZm9yICh2YXIgdGlsZTogdTMyID0gMDsgdGlsZSA8IG51bV90aWxlczsgdGlsZSArPSAxKSB7XG4gICAgICAgICAgICBsZXQgYV9jb2xfc3RhcnQgPSB0aWxlICogJHthTGVuZ3RoUGVyVGlsZX07XG4gICAgICAgICAgICAvLyBsb2FkIG9uZSB0aWxlIEEgZGF0YSBpbnRvIHNoYXJlZCBtZW1vcnkuXG4gICAgICAgICAgICBmb3IgKHZhciBhX29mZnNldCA9IGxvY2FsX2lkeDsgYV9vZmZzZXQgPCAke2FMZW5ndGhQZXJUaWxlfTsgYV9vZmZzZXQgKz0gJHt3b3JrZ3JvdXBTaXplfSlcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbGV0IGFfY29sID0gYV9jb2xfc3RhcnQgKyBhX29mZnNldDtcbiAgICAgICAgICAgICAgaWYgKGFfY29sIDwgdW5pZm9ybXMuYV9zaGFwZVsyXSlcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHN1Yl9hW2Ffb2Zmc2V0XSA9ICR7YS5nZXRCeUluZGljZXMoYCR7YS50eXBlLmluZGljZXN9KGJhdGNoLCByb3csIGFfY29sKWApfTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdWJfYVthX29mZnNldF0gPSAke2EudHlwZS52YWx1ZX0oMCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgICAgICAgLy8gZWFjaCB0aHJlYWQgcHJvY2VzcyBvbmUgYmxvY2tcbiAgICAgICAgICAgIGxldCBiX3JvdyA9IGNvbCArIGxvY2FsX2lkLnk7XG4gICAgICAgICAgICBsZXQgYmxvY2sgPSB0aWxlICogJHtibG9ja3NQZXJUaWxlfSArIGxvY2FsX2lkLng7XG4gICAgICAgICAgICAke1xuICAgICAgICAgICAgICB6ZXJvUG9pbnRzXG4gICAgICAgICAgICAgICAgPyBgXG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9ieXRlc19wZXJfY29sID0gKG5fYmxvY2tzX3Blcl9jb2wgKyAxKSAvIDI7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9ieXRlX2NvdW50ID0gYl9yb3cgKiB6ZXJvX3BvaW50X2J5dGVzX3Blcl9jb2wgKyAoYmxvY2sgPj4gMHgxdSk7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF93b3JkX2luZGV4ID0gemVyb19wb2ludF9ieXRlX2NvdW50ID4+IDB4MnU7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9ieXRlX29mZnNldCA9IHplcm9fcG9pbnRfYnl0ZV9jb3VudCAmIDB4M3U7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9uaWJibGVfb2Zmc2V0OiB1MzIgPSBibG9jayAmIDB4MXU7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludF9iaXRzX29mZnNldCA9ICh6ZXJvX3BvaW50X2J5dGVfb2Zmc2V0IDw8IDMpICsgKHplcm9fcG9pbnRfbmliYmxlX29mZnNldCA8PCAyKTtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X3dvcmQgPSAke3plcm9Qb2ludHMuZ2V0QnlPZmZzZXQoJ3plcm9fcG9pbnRfd29yZF9pbmRleCcpfSA+PiB6ZXJvX3BvaW50X2JpdHNfb2Zmc2V0O1xuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnQgPSAke2RhdGFUeXBlfSgoemVyb19wb2ludF93b3JkKSAmIDB4RnUpO2BcbiAgICAgICAgICAgICAgICA6IGBcbiAgICAgICAgICAgIC8vIFRoZSBkZWZhdWx0IHplcm8gcG9pbnQgaXMgOCBmb3IgdW5zaWduZWQgNC1iaXQgcXVhbnRpemF0aW9uLlxuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnQgPSAke2RhdGFUeXBlfSgkezguMH0pO2BcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzY2FsZSA9ICR7c2NhbGVzLmdldEJ5T2Zmc2V0KGBiX3JvdyAqIG5fYmxvY2tzX3Blcl9jb2wgKyBibG9ja2ApfTtcbiAgICAgICAgICAgIGxldCBiX2RhdGEgPSAke2IuZ2V0QnlJbmRpY2VzKGAke2IudHlwZS5pbmRpY2VzfShiX3JvdywgYmxvY2ssIDApYCl9O1xuICAgICAgICAgICAgdmFyIHdvcmRfb2Zmc2V0ID0gbG9jYWxfaWQueCAqICR7YXR0cmlidXRlcy5ibG9ja1NpemUgLyBhQ29tcG9uZW50c307XG4gICAgICAgICAgICBmb3IgKHZhciBpOiB1MzIgPSAwOyBpIDwgJHtiQ29tcG9uZW50c307IGkrKykge1xuICAgICAgICAgICAgICAke3JlYWRBKCl9XG4gICAgICAgICAgICAgIGxldCBiX3ZhbHVlID0gJHtiQ29tcG9uZW50cyA9PT0gMSA/IGBiX2RhdGFgIDogYGJfZGF0YVtpXWB9O1xuICAgICAgICAgICAgICBsZXQgYl92YWx1ZV9sb3dlciA9IHVucGFjazR4VTgoYl92YWx1ZSAmIDB4MEYwRjBGMEZ1KTtcbiAgICAgICAgICAgICAgbGV0IGJfdmFsdWVfdXBwZXIgPSB1bnBhY2s0eFU4KChiX3ZhbHVlID4+IDQpICYgMHgwRjBGMEYwRnUpO1xuICAgICAgICAgICAgICBsZXQgYl9xdWFudGl6ZWRfdmFsdWVzID0gbWF0Mng0PCR7ZGF0YVR5cGV9Pigke0FycmF5LmZyb20oXG4gICAgICAgICAgICAgICAgeyBsZW5ndGg6IDQgfSxcbiAgICAgICAgICAgICAgICAoXywgaSkgPT4gYCR7ZGF0YVR5cGV9KGJfdmFsdWVfbG93ZXJbJHtpfV0pLCAke2RhdGFUeXBlfShiX3ZhbHVlX3VwcGVyWyR7aX1dKWAsXG4gICAgICAgICAgICAgICkuam9pbignLCAnKX0pO1xuICAgICAgICAgICAgICBsZXQgYl9kZXF1YW50aXplZF92YWx1ZXMgPSAoYl9xdWFudGl6ZWRfdmFsdWVzIC0gbWF0Mng0PCR7ZGF0YVR5cGV9Pigke0FycmF5KDgpLmZpbGwoJ3plcm9fcG9pbnQnKS5qb2luKCcsJyl9KSkgKiBzY2FsZTtcbiAgICAgICAgICAgICAgaW50ZXJfcmVzdWx0c1tsb2NhbF9pZC55XVtsb2NhbF9pZC54XSArPSAke0FycmF5LmZyb20oXG4gICAgICAgICAgICAgICAgeyBsZW5ndGg6IDIgfSxcbiAgICAgICAgICAgICAgICAoXywgaSkgPT4gYCR7YGRvdChhX2RhdGEke2l9LCBiX2RlcXVhbnRpemVkX3ZhbHVlc1ske2l9XSlgfWAsXG4gICAgICAgICAgICAgICkuam9pbignICsgJyl9O1xuICAgICAgICAgICAgICB3b3JkX29mZnNldCArPSAkezggLyBhQ29tcG9uZW50c307XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGxvY2FsX2lkeCA8ICR7d29ya2dyb3VwWX0pIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXRfdmFsdWU6ICR7b3V0cHV0LnR5cGUudmFsdWV9ID0gJHtvdXRwdXQudHlwZS52YWx1ZX0oMCk7XG4gICAgICAgICAgICBmb3IgKHZhciBiID0gMHU7IGIgPCAke3dvcmtncm91cFh9OyBiKyspIHtcbiAgICAgICAgICAgICAgb3V0cHV0X3ZhbHVlICs9IGludGVyX3Jlc3VsdHNbbG9jYWxfaWR4XVtiXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb2wgKyBsb2NhbF9pZHggPCB1bmlmb3Jtcy5vdXRwdXRfc2hhcGVbMl0pXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5SW5kaWNlcyhgJHtvdXRwdXQudHlwZS5pbmRpY2VzfShiYXRjaCwgcm93LCBjb2wgKyBsb2NhbF9pZHgpYCwgJ291dHB1dF92YWx1ZScpfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0Jsb2Nrd2lzZU1hdE11bE5CaXRzMzInLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmJsb2NrU2l6ZX07JHthQ29tcG9uZW50c307JHtiQ29tcG9uZW50c307JHt3b3JrZ3JvdXBYfTske3dvcmtncm91cFl9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBBcnJheShpbnB1dHMubGVuZ3RoKS5maWxsKCdyYW5rJyksXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBkaXNwYXRjaFNpemUgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgbWF0TXVsTkJpdHMgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IE1hdE11bE5CaXRzQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGlmIChcbiAgICBhdHRyaWJ1dGVzLmJsb2NrU2l6ZSA9PT0gMzIgJiZcbiAgICBjb250ZXh0LmFkYXB0ZXJJbmZvLmlzVmVuZG9yKCdpbnRlbCcpICYmXG4gICAgY29udGV4dC5hZGFwdGVySW5mby5pc0FyY2hpdGVjdHVyZSgnZ2VuLTEybHAnKVxuICApIHtcbiAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlTWF0TXVsTkJpdHNCbG9ja1NpemUzMlByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKSk7XG4gIH0gZWxzZSB7XG4gICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZU1hdE11bE5CaXRzUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWF0TXVsTkJpdHNBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogTWF0TXVsTkJpdHNBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleShhdHRyaWJ1dGVzIGFzIE9taXQ8TWF0TXVsTkJpdHNBdHRyaWJ1dGVzLCBrZXlvZiBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXk+KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldEVsZW1lbnRBdCxcbiAgSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgVW5pZm9ybURhdGFFbGVtZW50VHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuaW50ZXJmYWNlIFBhZEF0dHJpYnV0ZXMge1xuICAvLyAwLWNvbnN0YW50LCAxLXJlZmxlY3QsIDItZWRnZSwgMy13cmFwXG4gIHJlYWRvbmx5IG1vZGU6IG51bWJlcjtcbiAgcmVhZG9ubHkgdmFsdWU6IG51bWJlcjtcbiAgcmVhZG9ubHkgcGFkczogbnVtYmVyW107XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUb28gZmV3IGlucHV0cycpO1xuICB9XG4gIGlmIChpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0ICYmIGlucHV0c1swXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQxNikge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgdHlwZSBtdXN0IGJlIGZsb2F0IG9yIGZsb2F0MTYuJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzLmxlbmd0aCA+PSAyKSB7XG4gICAgbGV0IHZhbGlkUGFkcyA9IGlucHV0c1swXS5kaW1zLmxlbmd0aCAqIDIgPT09IGlucHV0c1sxXS5kaW1zWzBdO1xuICAgIGlmIChpbnB1dHMubGVuZ3RoID09PSA0KSB7XG4gICAgICB2YWxpZFBhZHMgPSBpbnB1dHNbM10uZGltc1swXSAqIDIgPT09IGlucHV0c1sxXS5kaW1zWzBdO1xuICAgIH1cbiAgICBpZiAoIXZhbGlkUGFkcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgcGFkcyBzaG91bGQgYmUgYSAxRCB0ZW5zb3Igb2Ygc2hhcGUgWzIgKiBpbnB1dF9yYW5rXSBvciBbMiAqIG51bV9heGVzXS4nKTtcbiAgICB9XG4gIH1cbn07XG5cbmNvbnN0IGdldFBhZENvbnN0YW50ID0gKG91dHB1dDogSW5kaWNlc0hlbHBlciwgaW5wdXRSYW5rOiBudW1iZXIsIHBhZHNMZW5ndGg6IG51bWJlcik6IHN0cmluZyA9PiB7XG4gIGxldCBibG9jayA9ICcnO1xuICBmb3IgKGxldCBpID0gaW5wdXRSYW5rIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICBibG9jayArPSBgXG4gICAgICAgICAgICBrID0gaTMyKCR7b3V0cHV0LmluZGljZXNHZXQoJ2luZGljZXMnLCBpKX0pIC0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnBhZHMnLCBpLCBwYWRzTGVuZ3RoKX07XG4gICAgICAgICAgICBpZiAoayA8IDApIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoayA+PSBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCBpLCBpbnB1dFJhbmspfSkpIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvZmZzZXQgKz0gayAqIGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zdHJpZGVzJywgaSwgaW5wdXRSYW5rKX0pO1xuICAgICAgICBgO1xuICB9XG5cbiAgcmV0dXJuIGBcbiAgICAgICAgICB2YWx1ZSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KHVuaWZvcm1zLmNvbnN0YW50X3ZhbHVlKTtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDE7IGkrKykge1xuICAgICAgICAgICAgdmFyIG9mZnNldCA9IDA7XG4gICAgICAgICAgICB2YXIgayA9IDA7XG4gICAgICAgICAgICAke2Jsb2NrfVxuICAgICAgICAgICAgdmFsdWUgPSB4W29mZnNldF07XG4gICAgICAgICAgfVxuICAgICAgYDtcbn07XG5cbmNvbnN0IGdldFBhZFJlZmxlY3QgPSAob3V0cHV0OiBJbmRpY2VzSGVscGVyLCBpbnB1dFJhbms6IG51bWJlciwgcGFkc0xlbmd0aDogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgbGV0IGJsb2NrID0gJyc7XG4gIGZvciAobGV0IGkgPSBpbnB1dFJhbmsgLSAxOyBpID49IDA7IC0taSkge1xuICAgIGJsb2NrICs9IGBcbiAgICAgICAgICAgICAgICBrID0gaTMyKCR7b3V0cHV0LmluZGljZXNHZXQoJ2luZGljZXMnLCBpKX0pIC0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnBhZHMnLCBpLCBwYWRzTGVuZ3RoKX07XG4gICAgICAgICAgICAgICAgaWYgKGsgPCAwKSB7XG4gICAgICAgICAgICAgICAgICBrID0gLWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGxldCBfMm5fMSA9IDIgKiAoaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgaSwgaW5wdXRSYW5rKX0pIC0gMSk7XG4gICAgICAgICAgICAgICAgICBrID0gayAlIF8ybl8xO1xuICAgICAgICAgICAgICAgICAgaWYoayA+PSBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCBpLCBpbnB1dFJhbmspfSkpIHtcbiAgICAgICAgICAgICAgICAgICAgayA9IF8ybl8xIC0gaztcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb2Zmc2V0ICs9IGsgKiBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc3RyaWRlcycsIGksIGlucHV0UmFuayl9KTtcbiAgICAgICAgICAgIGA7XG4gIH1cblxuICByZXR1cm4gYFxuICAgICAgICAgICAgICB2YXIgb2Zmc2V0ID0gMDtcbiAgICAgICAgICAgICAgdmFyIGsgPSAwO1xuICAgICAgICAgICAgICAke2Jsb2NrfVxuICAgICAgICAgICAgICB2YWx1ZSA9IHhbb2Zmc2V0XTtcbiAgICAgICAgICBgO1xufTtcblxuY29uc3QgZ2V0UGFkRWRnZSA9IChvdXRwdXQ6IEluZGljZXNIZWxwZXIsIGlucHV0UmFuazogbnVtYmVyLCBwYWRzTGVuZ3RoOiBudW1iZXIpOiBzdHJpbmcgPT4ge1xuICBsZXQgYmxvY2sgPSAnJztcbiAgZm9yIChsZXQgaSA9IGlucHV0UmFuayAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgYmxvY2sgKz0gYFxuICAgICAgICAgICAgICAgIGsgPSBpMzIoJHtvdXRwdXQuaW5kaWNlc0dldCgnaW5kaWNlcycsIGkpfSkgLSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMucGFkcycsIGksIHBhZHNMZW5ndGgpfTtcbiAgICAgICAgICAgICAgICBpZiAoayA8IDApIHtcbiAgICAgICAgICAgICAgICAgIGsgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoayA+PSBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCBpLCBpbnB1dFJhbmspfSkpIHtcbiAgICAgICAgICAgICAgICAgIGsgPSBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCBpLCBpbnB1dFJhbmspfSkgLSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gayAqIGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zdHJpZGVzJywgaSwgaW5wdXRSYW5rKX0pO1xuICAgICAgICAgICAgYDtcbiAgfVxuXG4gIHJldHVybiBgXG4gICAgICAgICAgICAgIHZhciBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgICB2YXIgayA9IDA7XG4gICAgICAgICAgICAgICR7YmxvY2t9XG4gICAgICAgICAgICAgIHZhbHVlID0geFtvZmZzZXRdO1xuICAgICAgICAgIGA7XG59O1xuXG5jb25zdCBnZXRQYWRXcmFwID0gKG91dHB1dDogSW5kaWNlc0hlbHBlciwgaW5wdXRSYW5rOiBudW1iZXIsIHBhZHNMZW5ndGg6IG51bWJlcik6IHN0cmluZyA9PiB7XG4gIGxldCBibG9jayA9ICcnO1xuICBmb3IgKGxldCBpID0gaW5wdXRSYW5rIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICBibG9jayArPSBgXG4gICAgICAgICAgICAgICAgayA9IGkzMigke291dHB1dC5pbmRpY2VzR2V0KCdpbmRpY2VzJywgaSl9KSAtICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5wYWRzJywgaSwgcGFkc0xlbmd0aCl9O1xuICAgICAgICAgICAgICAgIGlmIChrIDwgMCkgIHtcbiAgICAgICAgICAgICAgICAgIGsgKz0gaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgaSwgaW5wdXRSYW5rKX1dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGsgPj0gaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgaSwgaW5wdXRSYW5rKX0pKSB7XG4gICAgICAgICAgICAgICAgICBrIC09IGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIGksIGlucHV0UmFuayl9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb2Zmc2V0ICs9IGsgKiBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc3RyaWRlcycsIGksIGlucHV0UmFuayl9KTtcbiAgICAgICAgICAgIGA7XG4gIH1cblxuICByZXR1cm4gYFxuICAgICAgICAgICAgICB2YXIgb2Zmc2V0ID0gMDtcbiAgICAgICAgICAgICAgdmFyIGsgPSAwO1xuICAgICAgICAgICAgICAke2Jsb2NrfVxuICAgICAgICAgICAgICB2YWx1ZSA9IHhbb2Zmc2V0XTtcbiAgICAgICAgICBgO1xufTtcblxuY29uc3QgZ2V0UGFkU25pcHBldCA9IChvdXRwdXQ6IEluZGljZXNIZWxwZXIsIGlucHV0UmFuazogbnVtYmVyLCBhdHRyaWJ1dGVzOiBQYWRBdHRyaWJ1dGVzKTogc3RyaW5nID0+IHtcbiAgc3dpdGNoIChhdHRyaWJ1dGVzLm1vZGUpIHtcbiAgICBjYXNlIDA6XG4gICAgICByZXR1cm4gZ2V0UGFkQ29uc3RhbnQob3V0cHV0LCBpbnB1dFJhbmssIGF0dHJpYnV0ZXMucGFkcy5sZW5ndGgpO1xuICAgIGNhc2UgMTpcbiAgICAgIHJldHVybiBnZXRQYWRSZWZsZWN0KG91dHB1dCwgaW5wdXRSYW5rLCBhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoKTtcbiAgICBjYXNlIDI6XG4gICAgICByZXR1cm4gZ2V0UGFkRWRnZShvdXRwdXQsIGlucHV0UmFuaywgYXR0cmlidXRlcy5wYWRzLmxlbmd0aCk7XG4gICAgY2FzZSAzOlxuICAgICAgcmV0dXJuIGdldFBhZFdyYXAob3V0cHV0LCBpbnB1dFJhbmssIGF0dHJpYnV0ZXMucGFkcy5sZW5ndGgpO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgbW9kZScpO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVQYWRQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogUGFkQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBTaGFwZVV0aWwucGFkU2hhcGUoaW5wdXRzWzBdLmRpbXMuc2xpY2UoKSwgYXR0cmlidXRlcy5wYWRzKTtcbiAgY29uc3QgaW5wdXREaW1zID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGF0dHJpYnV0ZXMucGFkcyB9LFxuICBdO1xuXG4gIGNvbnN0IGlzVmFsdWVGcm9tSW5wdXQgPSBpbnB1dHMubGVuZ3RoID49IDMgJiYgaW5wdXRzWzJdLmRhdGE7XG4gIGlmIChhdHRyaWJ1dGVzLm1vZGUgPT09IDApIHtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCh7IHR5cGU6IGlzVmFsdWVGcm9tSW5wdXQgPyBpbnB1dHNbMl0uZGF0YVR5cGUgOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogYXR0cmlidXRlcy52YWx1ZSB9KTtcbiAgfVxuXG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBvdXRwdXRTaGFwZSkpO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsncmFuayddO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gICAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dERpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBkYXRhVHlwZSA9IGlucHV0LnR5cGUudmFsdWU7XG4gICAgY29uc3QgcGFkU25pcHBldCA9IGdldFBhZFNuaXBwZXQob3V0cHV0LCBpbnB1dERpbXMubGVuZ3RoLCBhdHRyaWJ1dGVzKTtcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdwYWRzJywgdHlwZTogJ2kzMicsIGxlbmd0aDogYXR0cmlidXRlcy5wYWRzLmxlbmd0aCB9LFxuICAgIF07XG4gICAgaWYgKGF0dHJpYnV0ZXMubW9kZSA9PT0gMCkge1xuICAgICAgdW5pZm9ybXMucHVzaCh7IG5hbWU6ICdjb25zdGFudF92YWx1ZScsIHR5cGU6IChpc1ZhbHVlRnJvbUlucHV0ID8gZGF0YVR5cGUgOiAnZjMyJykgYXMgVW5pZm9ybURhdGFFbGVtZW50VHlwZSB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gYFxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgb3V0cHV0KX1cbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cblxuICAgICAgICAgICAgbGV0IGluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG5cbiAgICAgICAgICAgIHZhciB2YWx1ZSA9ICR7ZGF0YVR5cGV9KDApO1xuICAgICAgICAgICAgJHtwYWRTbmlwcGV0fVxuICAgICAgICAgICAgb3V0cHV0W2dsb2JhbF9pZHhdID0gdmFsdWU7XG4gICAgICAgIH1gO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1BhZCcsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7YXR0cmlidXRlcy5tb2RlfSR7aXNWYWx1ZUZyb21JbnB1dH1gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmNvbnN0IGNyZWF0ZVBhZEF0dHJpYnV0ZXNGcm9tSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBQYWRBdHRyaWJ1dGVzKTogUGFkQXR0cmlidXRlcyA9PiB7XG4gIGlmIChpbnB1dHMubGVuZ3RoID4gMSkge1xuICAgIGNvbnN0IGJpZ0ludDY0UGFkcyA9IGlucHV0c1sxXS5nZXRCaWdJbnQ2NEFycmF5KCk7XG4gICAgY29uc3QgdmFsdWUgPVxuICAgICAgaW5wdXRzLmxlbmd0aCA+PSAzICYmIGlucHV0c1syXS5kYXRhXG4gICAgICAgID8gaW5wdXRzWzJdLmRhdGFUeXBlID09PSBEYXRhVHlwZS5mbG9hdDE2XG4gICAgICAgICAgPyBpbnB1dHNbMl0uZ2V0VWludDE2QXJyYXkoKVswXVxuICAgICAgICAgIDogaW5wdXRzWzJdLmdldEZsb2F0MzJBcnJheSgpWzBdXG4gICAgICAgIDogMC4wO1xuXG4gICAgY29uc3QgaW5wdXRSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoO1xuICAgIGNvbnN0IHVwZGF0ZVBhZHMgPSBuZXcgSW50MzJBcnJheSgyICogaW5wdXRSYW5rKS5maWxsKDApO1xuICAgIGlmIChpbnB1dHMubGVuZ3RoID49IDQpIHtcbiAgICAgIGNvbnN0IGF4ZXMgPSBpbnB1dHNbM10uZ2V0QmlnSW50NjRBcnJheSgpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBheGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHVwZGF0ZVBhZHNbTnVtYmVyKGF4ZXNbaV0pXSA9IE51bWJlcihiaWdJbnQ2NFBhZHNbaV0pO1xuICAgICAgICB1cGRhdGVQYWRzW051bWJlcihheGVzW2ldKSArIGlucHV0UmFua10gPSBOdW1iZXIoYmlnSW50NjRQYWRzW2kgKyBheGVzLmxlbmd0aF0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBiaWdJbnQ2NFBhZHMuZm9yRWFjaCgodiwgaSkgPT4gKHVwZGF0ZVBhZHNbTnVtYmVyKGkpXSA9IE51bWJlcih2KSkpO1xuICAgIH1cblxuICAgIGNvbnN0IHBhZHM6IG51bWJlcltdID0gW107XG4gICAgdXBkYXRlUGFkcy5mb3JFYWNoKCh2KSA9PiBwYWRzLnB1c2godikpO1xuXG4gICAgcmV0dXJuIHsgbW9kZTogYXR0cmlidXRlcy5tb2RlLCB2YWx1ZSwgcGFkcyB9O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBhdHRyaWJ1dGVzO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcGFkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBQYWRBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgdXBkYXRlZEF0dHJpYnV0ZXMgPSBjcmVhdGVQYWRBdHRyaWJ1dGVzRnJvbUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVQYWRQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgdXBkYXRlZEF0dHJpYnV0ZXMpLCB7IGlucHV0czogWzBdIH0pO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgZW52IH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgUG9vbENvbnZVdGlsLCBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldEVsZW1lbnRBdCxcbiAgSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuLy8gVE9ETzogc3VwcG9ydDpcbi8vIC0gY2VpbF9tb2RlICAgICAgICAgICAgICAgICBcInRlc3RfbWF4cG9vbF8yZF9jZWlsXCJcbi8vIC0gc3RvcmFnZV9vcmRlciAgICAgICAgICAgICBcInRlc3RfbWF4cG9vbF93aXRoX2FyZ21heF8yZF9wcmVjb21wdXRlZF9zdHJpZGVzXCJcbi8vIC0gW01heFBvb2xdIGRpbGF0aW9ucyAgICAgICBcInRlc3RfbWF4cG9vbF8yZF9kaWxhdGlvbnNcIlxuLy8gLSBbTWF4UG9vbF0gb3V0cHV0WzFdICAgICAgIFwidGVzdF9tYXhwb29sX3dpdGhfYXJnbWF4XzJkX3ByZWNvbXB1dGVkX3BhZHNcIlxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoZW52LndlYmdwdS52YWxpZGF0ZUlucHV0Q29udGVudCAmJiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUG9vbCBvcHMgcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxufTtcblxuY29uc3QgZ2V0QWRqdXN0ZWRQb29sQXR0cmlidXRlc0FuZE91dHB1dFNoYXBlID0gPEF0dHJpYnV0ZVR5cGUgZXh0ZW5kcyBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgfCBNYXhQb29sQXR0cmlidXRlcz4oXG4gIGlucHV0OiBUZW5zb3JWaWV3LFxuICBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGVUeXBlLFxuICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLFxuKTogW0F0dHJpYnV0ZVR5cGUsIG51bWJlcltdXSA9PiB7XG4gIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3QgaW5wdXRTaGFwZUFzQ2hhbm5lbEZpcnN0ID0gaW5wdXQuZGltcy5zbGljZSgpO1xuICBpZiAoaXNDaGFubmVsc0xhc3QpIHtcbiAgICBpbnB1dFNoYXBlQXNDaGFubmVsRmlyc3Quc3BsaWNlKDEsIDAsIGlucHV0U2hhcGVBc0NoYW5uZWxGaXJzdC5wb3AoKSEpOyAvLyBNb3ZlIGNoYW5uZWwgdG8gdGhlIHNlY29uZCBwb3NpdGlvbi5cbiAgfVxuICBjb25zdCBoYXNEaWxhdGlvbnMgPSBPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChhdHRyaWJ1dGVzLCAnZGlsYXRpb25zJyk7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5zbGljZSgpO1xuICBjb25zdCBzdHJpZGVzID0gYXR0cmlidXRlcy5zdHJpZGVzLnNsaWNlKCk7XG4gIGNvbnN0IGRpbGF0aW9uczogbnVtYmVyW10gPSBoYXNEaWxhdGlvbnMgPyAoYXR0cmlidXRlcyBhcyBNYXhQb29sQXR0cmlidXRlcykuZGlsYXRpb25zLnNsaWNlKCkgOiBbXTtcbiAgY29uc3QgcGFkcyA9IGF0dHJpYnV0ZXMucGFkcy5zbGljZSgpO1xuICBQb29sQ29udlV0aWwuYWRqdXN0UG9vbEF0dHJpYnV0ZXMoaXNHbG9iYWxPcGVyYXRvciwgaW5wdXRTaGFwZUFzQ2hhbm5lbEZpcnN0LCBrZXJuZWxTaGFwZSwgc3RyaWRlcywgZGlsYXRpb25zLCBwYWRzKTtcblxuICBjb25zdCBvdXRwdXRTaGFwZUFzQ2hhbm5lbEZpcnN0ID0gUG9vbENvbnZVdGlsLmNvbXB1dGVQb29sT3V0cHV0U2hhcGUoXG4gICAgaXNHbG9iYWxPcGVyYXRvcixcbiAgICBpbnB1dFNoYXBlQXNDaGFubmVsRmlyc3QsXG4gICAgc3RyaWRlcyxcbiAgICBkaWxhdGlvbnMsXG4gICAga2VybmVsU2hhcGUsXG4gICAgcGFkcyxcbiAgICBhdHRyaWJ1dGVzLmF1dG9QYWQsXG4gICk7XG5cbiAgY29uc3QgbmV3QXR0cmlidXRlcyA9IE9iamVjdC5hc3NpZ24oe30sIGF0dHJpYnV0ZXMpO1xuICBpZiAoaGFzRGlsYXRpb25zKSB7XG4gICAgT2JqZWN0LmFzc2lnbihuZXdBdHRyaWJ1dGVzLCB7IGtlcm5lbFNoYXBlLCBzdHJpZGVzLCBwYWRzLCBkaWxhdGlvbnMsIGNhY2hlS2V5OiBhdHRyaWJ1dGVzLmNhY2hlS2V5IH0pO1xuICB9IGVsc2Uge1xuICAgIE9iamVjdC5hc3NpZ24obmV3QXR0cmlidXRlcywgeyBrZXJuZWxTaGFwZSwgc3RyaWRlcywgcGFkcywgY2FjaGVLZXk6IGF0dHJpYnV0ZXMuY2FjaGVLZXkgfSk7XG4gIH1cbiAgY29uc3Qgb3V0cHV0U2hhcGVBc0NoYW5uZWxMYXN0ID0gb3V0cHV0U2hhcGVBc0NoYW5uZWxGaXJzdC5zbGljZSgpO1xuICBvdXRwdXRTaGFwZUFzQ2hhbm5lbExhc3QucHVzaChvdXRwdXRTaGFwZUFzQ2hhbm5lbExhc3Quc3BsaWNlKDEsIDEpWzBdKTtcbiAgcmV0dXJuIFtuZXdBdHRyaWJ1dGVzLCBpc0NoYW5uZWxzTGFzdCA/IG91dHB1dFNoYXBlQXNDaGFubmVsTGFzdCA6IG91dHB1dFNoYXBlQXNDaGFubmVsRmlyc3RdO1xufTtcblxuY29uc3QgZ2V0VW5pZm9ybUFuZFBhZEluZm8gPSA8QXR0cmlidXRlVHlwZSBleHRlbmRzIEF2ZXJhZ2VQb29sQXR0cmlidXRlcyB8IE1heFBvb2xBdHRyaWJ1dGVzPihcbiAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGVUeXBlLFxuKTogW1Byb2dyYW1Vbmlmb3JtW10sIFVuaWZvcm1zQXJyYXlUeXBlLCBib29sZWFuLCBib29sZWFuLCBib29sZWFuXSA9PiB7XG4gIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgY29uc3Qga2VybmVsU2l6ZSA9IFNoYXBlVXRpbC5zaXplKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUpO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YToga2VybmVsU2l6ZSB9LFxuICBdO1xuICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgeyBuYW1lOiAnb3V0cHV0U2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgeyBuYW1lOiAna2VybmVsU2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gIF07XG4gIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCA8PSAyKSB7XG4gICAgY29uc3Qga3cgPSBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlW2F0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoIC0gMV07XG4gICAgY29uc3Qgc3cgPSBhdHRyaWJ1dGVzLnN0cmlkZXNbYXR0cmlidXRlcy5zdHJpZGVzLmxlbmd0aCAtIDFdO1xuICAgIGNvbnN0IHB3U3RhcnQgPSBhdHRyaWJ1dGVzLnBhZHNbYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAvIDIgLSAxXTtcbiAgICBjb25zdCBwd0VuZCA9IGF0dHJpYnV0ZXMucGFkc1thdHRyaWJ1dGVzLnBhZHMubGVuZ3RoIC0gMV07XG4gICAgY29uc3QgcHdTdGFydEVuZE5vdFplcm8gPSAhIShwd1N0YXJ0ICsgcHdFbmQpO1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGt3IH0sXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogc3cgfSxcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwd1N0YXJ0IH0sXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcHdFbmQgfSxcbiAgICApO1xuICAgIHVuaWZvcm1zLnB1c2goXG4gICAgICB7IG5hbWU6ICdrdycsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdzdycsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdwd1N0YXJ0JywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3B3RW5kJywgdHlwZTogJ3UzMicgfSxcbiAgICApO1xuXG4gICAgbGV0IHBoU3RhcnRFbmROb3RaZXJvID0gZmFsc2U7XG4gICAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoID09PSAyKSB7XG4gICAgICBjb25zdCBraCA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGVbYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggLSAyXTtcbiAgICAgIGNvbnN0IHNoID0gYXR0cmlidXRlcy5zdHJpZGVzW2F0dHJpYnV0ZXMuc3RyaWRlcy5sZW5ndGggLSAyXTtcbiAgICAgIGNvbnN0IHBoU3RhcnQgPSBhdHRyaWJ1dGVzLnBhZHNbYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAvIDIgLSAyXTtcbiAgICAgIGNvbnN0IHBoRW5kID0gYXR0cmlidXRlcy5wYWRzW2F0dHJpYnV0ZXMucGFkcy5sZW5ndGggLSAyXTtcbiAgICAgIHBoU3RhcnRFbmROb3RaZXJvID0gISEocGhTdGFydCArIHBoRW5kKTtcbiAgICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKFxuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YToga2ggfSxcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHNoIH0sXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwaFN0YXJ0IH0sXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwaEVuZCB9LFxuICAgICAgKTtcblxuICAgICAgdW5pZm9ybXMucHVzaChcbiAgICAgICAgeyBuYW1lOiAna2gnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgICB7IG5hbWU6ICdzaCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICAgIHsgbmFtZTogJ3BoU3RhcnQnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgICB7IG5hbWU6ICdwaEVuZCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gW3Byb2dyYW1Vbmlmb3JtcywgdW5pZm9ybXMsIHRydWUsIHB3U3RhcnRFbmROb3RaZXJvLCBwaFN0YXJ0RW5kTm90WmVyb107XG4gIH0gZWxzZSB7XG4gICAgaWYgKGlzQ2hhbm5lbHNMYXN0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Bvb2xpbmcgd2l0aCBrZXJuZWxTaGFwZS5sZW5ndGggPiAyIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIE5IV0MgZm9ybWF0LicpO1xuICAgIH1cbiAgICBjb25zdCBrZXJuZWxTdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUpO1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGtlcm5lbFN0cmlkZXMgfSxcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLnBhZHMgfSxcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLnN0cmlkZXMgfSxcbiAgICApO1xuICAgIHVuaWZvcm1zLnB1c2goXG4gICAgICB7IG5hbWU6ICdrZXJuZWxTdHJpZGVzJywgdHlwZTogJ3UzMicsIGxlbmd0aDoga2VybmVsU3RyaWRlcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ3BhZHMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdzdHJpZGVzJywgdHlwZTogJ3UzMicsIGxlbmd0aDogYXR0cmlidXRlcy5zdHJpZGVzLmxlbmd0aCB9LFxuICAgICk7XG5cbiAgICBjb25zdCBoYXNQYWRzID0gYXR0cmlidXRlcy5wYWRzLnJlZHVjZSgoc3VtLCBjdXIpID0+IHN1bSArIGN1cik7XG4gICAgcmV0dXJuIFtwcm9ncmFtVW5pZm9ybXMsIHVuaWZvcm1zLCAhIWhhc1BhZHMsIGZhbHNlLCBmYWxzZV07XG4gIH1cbn07XG5cbmNvbnN0IGdlbmVyYXRlUG9vbGluZ0NvZGUgPSA8QXR0cmlidXRlVHlwZSBleHRlbmRzIEF2ZXJhZ2VQb29sQXR0cmlidXRlcyB8IE1heFBvb2xBdHRyaWJ1dGVzPihcbiAgc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIsXG4gIHg6IEluZGljZXNIZWxwZXIsXG4gIHJhbms6IG51bWJlcixcbiAgb3V0cHV0U2hhcGVSYW5rOiBudW1iZXIsXG4gIGF0dHJpYnV0ZXM6IEF0dHJpYnV0ZVR5cGUsXG4gIG9wMTogc3RyaW5nLFxuICBvcDI6IHN0cmluZyxcbiAgc3RhcnQ6IG51bWJlcixcbiAgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlLFxuICBoYXNQYWRzOiBib29sZWFuLFxuICBwd1N0YXJ0RW5kTm90WmVybzogYm9vbGVhbixcbiAgcGhTdGFydEVuZE5vdFplcm86IGJvb2xlYW4sXG4pOiBzdHJpbmcgPT4ge1xuICBjb25zdCBpc0NoYW5uZWxzTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGNvbnN0IGRhdGFUeXBlID0geC50eXBlLnZhbHVlO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgeC50eXBlLnRlbnNvciwgb3V0cHV0U2hhcGVSYW5rKTtcblxuICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggPD0gMikge1xuICAgIGxldCBjb2RlVyA9ICcnO1xuICAgIGxldCBjb2RlSCA9ICcnO1xuICAgIGxldCBjb2RlSEVuZCA9ICcnO1xuICAgIGNvbnN0IGRpbUlkeFcgPSByYW5rIC0gKGlzQ2hhbm5lbHNMYXN0ID8gMiA6IDEpO1xuICAgIGlmIChwd1N0YXJ0RW5kTm90WmVybykge1xuICAgICAgY29kZVcgPSBgXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaTogdTMyID0gMHU7IGkgPCB1bmlmb3Jtcy5rdzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICB4SW5kaWNlc1ske2RpbUlkeFd9XSA9IGluZGljZXNbJHtkaW1JZHhXfV0gKiB1bmlmb3Jtcy5zdyAtIHVuaWZvcm1zLnB3U3RhcnQgKyBpO1xuICAgICAgICAgICAgICAgICAgaWYgKHhJbmRpY2VzWyR7ZGltSWR4V31dIDwgMCB8fCB4SW5kaWNlc1ske2RpbUlkeFd9XVxuICAgICAgICAgICAgICAgICAgICAgID49IHVuaWZvcm1zLnhfc2hhcGVbJHtkaW1JZHhXfV0pIHtcbiAgICAgICAgICAgICAgICAgICAgcGFkKys7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgbGV0IHhfdmFsID0geFske3guaW5kaWNlc1RvT2Zmc2V0KCd4SW5kaWNlcycpfV07XG4gICAgICAgICAgICAgICAgICAke29wMX1cbiAgICAgICAgICAgICAgICB9YDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZVcgPSBgXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaTogdTMyID0gMHU7IGkgPCB1bmlmb3Jtcy5rdzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICB4SW5kaWNlc1ske2RpbUlkeFd9XSA9IGluZGljZXNbJHtkaW1JZHhXfV0gKiB1bmlmb3Jtcy5zdyAtIHVuaWZvcm1zLnB3U3RhcnQgKyBpO1xuICAgICAgICAgICAgICAgICAgbGV0IHhfdmFsID0geFske3guaW5kaWNlc1RvT2Zmc2V0KCd4SW5kaWNlcycpfV07XG4gICAgICAgICAgICAgICAgICAke29wMX1cbiAgICAgICAgICAgICAgICB9YDtcbiAgICB9XG5cbiAgICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggPT09IDIpIHtcbiAgICAgIGNvbnN0IGRpbUlkeEggPSByYW5rIC0gKGlzQ2hhbm5lbHNMYXN0ID8gMyA6IDIpO1xuICAgICAgaWYgKHBoU3RhcnRFbmROb3RaZXJvKSB7XG4gICAgICAgIGNvZGVIID0gYFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGo6IHUzMiA9IDB1OyBqIDwgdW5pZm9ybXMua2g7IGorKykge1xuICAgICAgICAgICAgICAgICAgeEluZGljZXNbJHtkaW1JZHhIfV0gPSBpbmRpY2VzWyR7ZGltSWR4SH1dICogdW5pZm9ybXMuc2ggLSB1bmlmb3Jtcy5waFN0YXJ0ICsgajtcbiAgICAgICAgICAgICAgICAgIGlmICh4SW5kaWNlc1ske2RpbUlkeEh9XSA8IDAgfHwgeEluZGljZXNbJHtkaW1JZHhIfV0gPj0gdW5pZm9ybXMueF9zaGFwZVske2RpbUlkeEh9XSkge1xuICAgICAgICAgICAgICAgICAgICBwYWQgKz0gaTMyKHVuaWZvcm1zLmt3KTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2RlSCA9IGBcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqOiB1MzIgPSAwdTsgaiA8IHVuaWZvcm1zLmtoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgIHhJbmRpY2VzWyR7ZGltSWR4SH1dID0gaW5kaWNlc1ske2RpbUlkeEh9XSAqIHVuaWZvcm1zLnNoIC0gdW5pZm9ybXMucGhTdGFydCArIGo7XG4gICAgICAgICAgICAgICAgYDtcbiAgICAgIH1cbiAgICAgIGNvZGVIRW5kID0gYFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBgO1xuICAgIH1cblxuICAgIGNvbnN0IHBvb2xpbmdDb2RlID0gYFxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyh4LCBvdXRwdXQpfVxuXG4gICAgICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0U2l6ZScpfVxuXG4gICAgICAgICAgICAgIGxldCBpbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgICAgICAgICB2YXIgeEluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG5cbiAgICAgICAgICAgICAgdmFyIHZhbHVlID0gJHtkYXRhVHlwZX0oJHtzdGFydH0pO1xuICAgICAgICAgICAgICB2YXIgcGFkID0gMDtcbiAgICAgICAgICAgICAgJHtjb2RlSH1cbiAgICAgICAgICAgICAgJHtjb2RlV31cbiAgICAgICAgICAgICAgJHtjb2RlSEVuZH1cbiAgICAgICAgICAgICAgJHtvcDJ9XG5cbiAgICAgICAgICAgICAgb3V0cHV0W2dsb2JhbF9pZHhdID0gdmFsdWU7XG4gICAgICAgICAgICB9YDtcbiAgICByZXR1cm4gcG9vbGluZ0NvZGU7XG4gIH0gZWxzZSB7XG4gICAgaWYgKGlzQ2hhbm5lbHNMYXN0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Bvb2xpbmcgd2l0aCBrZXJuZWxTaGFwZS5sZW5ndGggPiAyIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIE5IV0MgZm9ybWF0LicpO1xuICAgIH1cbiAgICBjb25zdCBzdHJpZGVzUmFuayA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IHBhZHNSYW5rID0gYXR0cmlidXRlcy5wYWRzLmxlbmd0aDtcbiAgICBsZXQgcGFkQ29kZSA9ICcnO1xuICAgIGlmIChoYXNQYWRzKSB7XG4gICAgICBwYWRDb2RlID0gYFxuICAgICAgICAgICAgICAgIGlmICh4SW5kaWNlc1tqXSA+PSB1bmlmb3Jtcy54X3NoYXBlW2pdKSB7XG4gICAgICAgICAgICAgICAgICBwYWQrKztcbiAgICAgICAgICAgICAgICAgIGlzUGFkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoIWlzUGFkKSB7XG4gICAgICAgICAgICAgICAgbGV0IHhfdmFsID0geFske3guaW5kaWNlc1RvT2Zmc2V0KCd4SW5kaWNlcycpfV07XG4gICAgICAgICAgICAgICAgJHtvcDF9XG4gICAgICAgICAgICAgIH1gO1xuICAgIH0gZWxzZSB7XG4gICAgICBwYWRDb2RlID0gYFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGxldCB4X3ZhbCA9IHhbJHt4LmluZGljZXNUb09mZnNldCgneEluZGljZXMnKX1dO1xuICAgICAgICAgICAgICAke29wMX1cbiAgICAgICAgICAgIGA7XG4gICAgfVxuICAgIGNvbnN0IHBvb2xpbmdDb2RlID0gYFxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyh4LCBvdXRwdXQpfVxuXG4gICAgICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0U2l6ZScpfVxuICAgICAgICAgICAgICBsZXQgaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgICAgICAgICAgdmFyIHhJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuXG4gICAgICAgICAgICAgIHZhciBvZmZzZXRzOiBhcnJheTx1MzIsICR7c3RyaWRlc1Jhbmt9PjtcblxuICAgICAgICAgICAgICB2YXIgdmFsdWUgPSAke2RhdGFUeXBlfSgke3N0YXJ0fSk7XG4gICAgICAgICAgICAgIHZhciBwYWQgPSAwO1xuICAgICAgICAgICAgICB2YXIgaXNQYWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgICBmb3IgKHZhciBpOiB1MzIgPSAwdTsgaSA8IHVuaWZvcm1zLmtlcm5lbFNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBvZmZzZXQgPSBpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwdTsgaiA8ICR7c3RyaWRlc1JhbmsgLSAxfXU7IGorKykge1xuICAgICAgICAgICAgICAgICAgb2Zmc2V0c1tqXSA9IG9mZnNldCAvICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5rZXJuZWxTdHJpZGVzJywgJ2onLCBzdHJpZGVzUmFuayl9O1xuICAgICAgICAgICAgICAgICAgb2Zmc2V0IC09IG9mZnNldHNbal0gKiAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMua2VybmVsU3RyaWRlcycsICdqJywgc3RyaWRlc1JhbmspfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb2Zmc2V0c1ske3N0cmlkZXNSYW5rIC0gMX1dID0gb2Zmc2V0O1xuXG4gICAgICAgICAgICAgICAgaXNQYWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gJHtyYW5rIC0gc3RyaWRlc1Jhbmt9dTsgaiA8ICR7cmFua311OyBqKyspIHtcbiAgICAgICAgICAgICAgICAgIHhJbmRpY2VzW2pdID0gaW5kaWNlc1tqXSAqICR7Z2V0RWxlbWVudEF0KFxuICAgICAgICAgICAgICAgICAgICAndW5pZm9ybXMuc3RyaWRlcycsXG4gICAgICAgICAgICAgICAgICAgIGBqIC0gJHtyYW5rIC0gc3RyaWRlc1Jhbmt9dWAsXG4gICAgICAgICAgICAgICAgICAgIHN0cmlkZXNSYW5rLFxuICAgICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgICAgICAgICAgKyBvZmZzZXRzW2ogLSAke3JhbmsgLSBzdHJpZGVzUmFua311XSAtICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5wYWRzJywgJ2ogLSAydScsIHBhZHNSYW5rKX07XG4gICAgICAgICAgICAgICAgICAke3BhZENvZGV9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgJHtvcDJ9XG5cbiAgICAgICAgICAgICAgb3V0cHV0W2dsb2JhbF9pZHhdID0gdmFsdWU7XG4gICAgICAgICAgICB9YDtcbiAgICByZXR1cm4gcG9vbGluZ0NvZGU7XG4gIH1cbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgRm9ybWF0QXR0cmlidXRlcyB7XG4gIHJlYWRvbmx5IGZvcm1hdDogJ05IV0MnIHwgJ05DSFcnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBvb2xDb21tb25BdHRyaWJ1dGVzIGV4dGVuZHMgRm9ybWF0QXR0cmlidXRlcyB7XG4gIHJlYWRvbmx5IGF1dG9QYWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgY2VpbE1vZGU6IG51bWJlcjtcbiAgcmVhZG9ubHkga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgcGFkczogcmVhZG9ubHkgbnVtYmVyW107XG59XG5cbmNvbnN0IGNyZWF0ZVNoYWRlcktleUZyb21BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFBvb2xDb21tb25BdHRyaWJ1dGVzKTogc3RyaW5nID0+XG4gIGAke2F0dHJpYnV0ZXMuZm9ybWF0fTske2F0dHJpYnV0ZXMuY2VpbE1vZGV9OyR7YXR0cmlidXRlcy5hdXRvUGFkfTske2F0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RofWA7XG5cbmNvbnN0IGNyZWF0ZUF2ZXJhZ2VQb29sU2hhZGVyS2V5RnJvbUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzKTogc3RyaW5nID0+XG4gIGAke2NyZWF0ZVNoYWRlcktleUZyb21BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpfTske2F0dHJpYnV0ZXMuY291bnRJbmNsdWRlUGFkfWA7XG5cbmNvbnN0IGNyZWF0ZU1heFBvb2xTaGFkZXJLZXlGcm9tQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBNYXhQb29sQXR0cmlidXRlcyk6IHN0cmluZyA9PlxuICBgJHtjcmVhdGVTaGFkZXJLZXlGcm9tQXR0cmlidXRlcyhhdHRyaWJ1dGVzKX07JHthdHRyaWJ1dGVzLnN0b3JhZ2VPcmRlcn07JHthdHRyaWJ1dGVzLmRpbGF0aW9uc31gO1xuXG5jb25zdCBwYXJzZVBvb2xDb21tb25BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogUG9vbENvbW1vbkF0dHJpYnV0ZXMgPT4gKHtcbiAgZm9ybWF0OiBhdHRyaWJ1dGVzLmZvcm1hdCBhcyBGb3JtYXRBdHRyaWJ1dGVzWydmb3JtYXQnXSxcbiAgYXV0b1BhZDogWydOT1RTRVQnLCAnVkFMSUQnLCAnU0FNRV9VUFBFUicsICdTQU1FX0xPV0VSJ11bYXR0cmlidXRlcy5hdXRvX3BhZCBhcyBudW1iZXJdLFxuICBjZWlsTW9kZTogYXR0cmlidXRlcy5jZWlsX21vZGUgYXMgbnVtYmVyLFxuICBrZXJuZWxTaGFwZTogYXR0cmlidXRlcy5rZXJuZWxfc2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSxcbiAgc3RyaWRlczogYXR0cmlidXRlcy5zdHJpZGVzIGFzIFtudW1iZXIsIG51bWJlcl0sXG4gIHBhZHM6IGF0dHJpYnV0ZXMucGFkcyBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbn0pO1xuXG5leHBvcnQgaW50ZXJmYWNlIEF2ZXJhZ2VQb29sQXR0cmlidXRlcyBleHRlbmRzIFBvb2xDb21tb25BdHRyaWJ1dGVzLCBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBjb3VudEluY2x1ZGVQYWQ6IGJvb2xlYW47XG59XG5cbmNvbnN0IGNyZWF0ZUF2ZXJhZ2VQb29sUHJvZ3JhbUluZm8gPSAoXG4gIG5hbWU6IHN0cmluZyxcbiAgaW5wdXQ6IFRlbnNvclZpZXcsXG4gIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sXG4gIGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgW2FkanVzdGVkQXR0cmlidXRlcywgb3V0cHV0U2hhcGVdID0gZ2V0QWRqdXN0ZWRQb29sQXR0cmlidXRlc0FuZE91dHB1dFNoYXBlKFxuICAgIGlucHV0LFxuICAgIGF0dHJpYnV0ZXMsXG4gICAgaXNHbG9iYWxPcGVyYXRvcixcbiAgKTtcbiAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dC5kYXRhVHlwZSwgaW5wdXQuZGltcy5sZW5ndGgpO1xuICBjb25zdCBkYXRhVHlwZSA9IHgudHlwZS52YWx1ZTtcblxuICBjb25zdCBvcDEgPSAndmFsdWUgKz0geF92YWw7JztcbiAgbGV0IG9wMiA9ICcnO1xuICBpZiAoYWRqdXN0ZWRBdHRyaWJ1dGVzLmNvdW50SW5jbHVkZVBhZCkge1xuICAgIG9wMiArPSBgdmFsdWUgLz0gJHtkYXRhVHlwZX0odW5pZm9ybXMua2VybmVsU2l6ZSk7YDtcbiAgfSBlbHNlIHtcbiAgICBvcDIgKz0gYHZhbHVlIC89ICR7ZGF0YVR5cGV9KGkzMih1bmlmb3Jtcy5rZXJuZWxTaXplKSAtIHBhZCk7YDtcbiAgfVxuICBjb25zdCBbcHJvZ3JhbVVuaWZvcm1zLCB1bmlmb3JtcywgaGFzUGFkcywgcHdTdGFydEVuZE5vdFplcm8sIHBoU3RhcnRFbmROb3RaZXJvXSA9IGdldFVuaWZvcm1BbmRQYWRJbmZvKFxuICAgIG91dHB1dFNoYXBlLFxuICAgIGFkanVzdGVkQXR0cmlidXRlcyxcbiAgKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXQuZGltcywgb3V0cHV0U2hhcGUpKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3JhbmsnXTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fTske2hhc1BhZHN9OyR7cHdTdGFydEVuZE5vdFplcm99OyR7cGhTdGFydEVuZE5vdFplcm99YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXQuZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2U6IChzaGFkZXJIZWxwZXIpID0+XG4gICAgICBnZW5lcmF0ZVBvb2xpbmdDb2RlKFxuICAgICAgICBzaGFkZXJIZWxwZXIsXG4gICAgICAgIHgsXG4gICAgICAgIGlucHV0LmRpbXMubGVuZ3RoLFxuICAgICAgICBvdXRwdXRTaGFwZS5sZW5ndGgsXG4gICAgICAgIGFkanVzdGVkQXR0cmlidXRlcyxcbiAgICAgICAgb3AxLFxuICAgICAgICBvcDIsXG4gICAgICAgIDAuMCxcbiAgICAgICAgdW5pZm9ybXMsXG4gICAgICAgIGhhc1BhZHMsXG4gICAgICAgIHB3U3RhcnRFbmROb3RaZXJvLFxuICAgICAgICBwaFN0YXJ0RW5kTm90WmVybyxcbiAgICAgICksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBjb3VudEluY2x1ZGVQYWQgPSAoYXR0cmlidXRlcy5jb3VudF9pbmNsdWRlX3BhZCBhcyBudW1iZXIpID09PSAwID8gZmFsc2UgOiB0cnVlO1xuXG4gIGNvbnN0IGF0dHIgPSBwYXJzZVBvb2xDb21tb25BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpO1xuICAvLyBUT0RPOiBzdXBwb3J0IGF0dHJpYnV0ZSAnY2VpbF9tb2RlJ1xuICBpZiAoYXR0ci5jZWlsTW9kZSAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXNpbmcgY2VpbCgpIGluIHNoYXBlIGNvbXB1dGF0aW9uIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciBBdmVyYWdlUG9vbCcpO1xuICB9XG4gIGNvbnN0IGF2ZXJhZ2VQb29sQXR0cmlidXRlcyA9IHsgY291bnRJbmNsdWRlUGFkLCAuLi5hdHRyLCBjYWNoZUtleTogJycgfTtcbiAgcmV0dXJuIHsgLi4uYXZlcmFnZVBvb2xBdHRyaWJ1dGVzLCBjYWNoZUtleTogY3JlYXRlQXZlcmFnZVBvb2xTaGFkZXJLZXlGcm9tQXR0cmlidXRlcyhhdmVyYWdlUG9vbEF0dHJpYnV0ZXMpIH07XG59O1xuXG5leHBvcnQgY29uc3QgYXZlcmFnZVBvb2wgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVBdmVyYWdlUG9vbFByb2dyYW1JbmZvKCdBdmVyYWdlUG9vbCcsIGNvbnRleHQuaW5wdXRzWzBdLCBmYWxzZSwgYXR0cmlidXRlcykpO1xufTtcblxuY29uc3QgZ2xvYmFsUG9vbEF0dHJpYnV0ZXMgPSB7XG4gIGF1dG9QYWQ6ICcnLFxuICBjZWlsTW9kZTogMCxcbiAgY291bnRJbmNsdWRlUGFkOiBmYWxzZSxcbiAga2VybmVsU2hhcGU6IFtdLFxuICBzdHJpZGVzOiBbXSxcbiAgcGFkczogW10sXG4gIHN0b3JhZ2VPcmRlcjogMCxcbiAgZGlsYXRpb25zOiBbXSxcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdsb2JhbEF2ZXJhZ2VQb29sQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGZvcm1hdCA9IGF0dHJpYnV0ZXMuZm9ybWF0IGFzIEZvcm1hdEF0dHJpYnV0ZXNbJ2Zvcm1hdCddO1xuICByZXR1cm4geyBmb3JtYXQsIC4uLmdsb2JhbFBvb2xBdHRyaWJ1dGVzLCBjYWNoZUtleTogZm9ybWF0IH07XG59O1xuXG5leHBvcnQgY29uc3QgZ2xvYmFsQXZlcmFnZVBvb2wgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVBdmVyYWdlUG9vbFByb2dyYW1JbmZvKCdHbG9iYWxBdmVyYWdlUG9vbCcsIGNvbnRleHQuaW5wdXRzWzBdLCB0cnVlLCBhdHRyaWJ1dGVzKSk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIE1heFBvb2xBdHRyaWJ1dGVzIGV4dGVuZHMgUG9vbENvbW1vbkF0dHJpYnV0ZXMsIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IHN0b3JhZ2VPcmRlcjogbnVtYmVyO1xuICByZWFkb25seSBkaWxhdGlvbnM6IG51bWJlcltdO1xufVxuXG5jb25zdCBjcmVhdGVNYXhQb29sUHJvZ3JhbUluZm8gPSAoXG4gIG5hbWU6IHN0cmluZyxcbiAgaW5wdXQ6IFRlbnNvclZpZXcsXG4gIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sXG4gIGF0dHJpYnV0ZXM6IE1heFBvb2xBdHRyaWJ1dGVzLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBbYWRqdXN0ZWRBdHRyaWJ1dGVzLCBvdXRwdXRTaGFwZV0gPSBnZXRBZGp1c3RlZFBvb2xBdHRyaWJ1dGVzQW5kT3V0cHV0U2hhcGUoXG4gICAgaW5wdXQsXG4gICAgYXR0cmlidXRlcyxcbiAgICBpc0dsb2JhbE9wZXJhdG9yLFxuICApO1xuICBjb25zdCBvcDEgPSBgXG4gICAgICB2YWx1ZSA9IG1heCh4X3ZhbCwgdmFsdWUpO1xuICAgIGA7XG4gIGNvbnN0IG9wMiA9ICcnO1xuICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0LmRhdGFUeXBlLCBpbnB1dC5kaW1zLmxlbmd0aCk7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWydyYW5rJ107XG4gIGNvbnN0IFtwcm9ncmFtVW5pZm9ybXMsIHVuaWZvcm1zLCBoYXNQYWRzLCBwd1N0YXJ0RW5kTm90WmVybywgcGhTdGFydEVuZE5vdFplcm9dID0gZ2V0VW5pZm9ybUFuZFBhZEluZm8oXG4gICAgb3V0cHV0U2hhcGUsXG4gICAgYWRqdXN0ZWRBdHRyaWJ1dGVzLFxuICApO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dC5kaW1zLCBvdXRwdXRTaGFwZSkpO1xuICByZXR1cm4ge1xuICAgIG5hbWUsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9OyR7aGFzUGFkc307JHtwd1N0YXJ0RW5kTm90WmVyb307JHtwaFN0YXJ0RW5kTm90WmVyb31gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXMsXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dC5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZTogKHNoYWRlckhlbHBlcikgPT5cbiAgICAgIGdlbmVyYXRlUG9vbGluZ0NvZGUoXG4gICAgICAgIHNoYWRlckhlbHBlcixcbiAgICAgICAgeCxcbiAgICAgICAgaW5wdXQuZGltcy5sZW5ndGgsXG4gICAgICAgIG91dHB1dFNoYXBlLmxlbmd0aCxcbiAgICAgICAgYWRqdXN0ZWRBdHRyaWJ1dGVzLFxuICAgICAgICBvcDEsXG4gICAgICAgIG9wMixcbiAgICAgICAgaW5wdXQuZGF0YVR5cGUgPT09IERhdGFUeXBlLmZsb2F0MTYgPyAtNjU1MDQgOiAtMWU1LFxuICAgICAgICB1bmlmb3JtcyxcbiAgICAgICAgaGFzUGFkcyxcbiAgICAgICAgcHdTdGFydEVuZE5vdFplcm8sXG4gICAgICAgIHBoU3RhcnRFbmROb3RaZXJvLFxuICAgICAgKSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBtYXhQb29sID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBNYXhQb29sQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVNYXhQb29sUHJvZ3JhbUluZm8oJ01heFBvb2wnLCBjb250ZXh0LmlucHV0c1swXSwgZmFsc2UsIGF0dHJpYnV0ZXMpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZU1heFBvb2xBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogTWF4UG9vbEF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBzdG9yYWdlT3JkZXIgPSBhdHRyaWJ1dGVzLnN0b3JhZ2Vfb3JkZXIgYXMgbnVtYmVyO1xuICBjb25zdCBkaWxhdGlvbnMgPSBhdHRyaWJ1dGVzLmRpbGF0aW9ucyBhcyBbbnVtYmVyLCBudW1iZXJdO1xuXG4gIGNvbnN0IGF0dHIgPSBwYXJzZVBvb2xDb21tb25BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpO1xuICAvLyBUT0RPOiBzdXBwb3J0IGF0dHJpYnV0ZSAnY2VpbF9tb2RlJyBhbmQgJ3N0b3JhZ2Vfb3JkZXInXG4gIGlmIChzdG9yYWdlT3JkZXIgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbHVtbiBtYWpvciBzdG9yYWdlIG9yZGVyIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciBNYXhQb29sJyk7XG4gIH1cbiAgaWYgKGF0dHIuY2VpbE1vZGUgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3VzaW5nIGNlaWwoKSBpbiBzaGFwZSBjb21wdXRhdGlvbiBpcyBub3QgeWV0IHN1cHBvcnRlZCBmb3IgTWF4UG9vbCcpO1xuICB9XG4gIGNvbnN0IG1heFBvb2xBdHRyaWJ1dGVzID0geyBzdG9yYWdlT3JkZXIsIGRpbGF0aW9ucywgLi4uYXR0ciwgY2FjaGVLZXk6ICcnIH07XG4gIHJldHVybiB7IC4uLm1heFBvb2xBdHRyaWJ1dGVzLCBjYWNoZUtleTogY3JlYXRlTWF4UG9vbFNoYWRlcktleUZyb21BdHRyaWJ1dGVzKG1heFBvb2xBdHRyaWJ1dGVzKSB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR2xvYmFsTWF4UG9vbEF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBNYXhQb29sQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGZvcm1hdCA9IGF0dHJpYnV0ZXMuZm9ybWF0IGFzIEZvcm1hdEF0dHJpYnV0ZXNbJ2Zvcm1hdCddO1xuICByZXR1cm4geyBmb3JtYXQsIC4uLmdsb2JhbFBvb2xBdHRyaWJ1dGVzLCBjYWNoZUtleTogZm9ybWF0IH07XG59O1xuXG5leHBvcnQgY29uc3QgZ2xvYmFsTWF4UG9vbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogTWF4UG9vbEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlTWF4UG9vbFByb2dyYW1JbmZvKCdHbG9iYWxNYXhQb29sJywgY29udGV4dC5pbnB1dHNbMF0sIHRydWUsIGF0dHJpYnV0ZXMpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldE1heENvbXBvbmVudHMsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVxdWFudGl6ZUxpbmVyQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIGF4aXM6IG51bWJlcjtcbiAgYmxvY2tTaXplOiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBEZXF1YW50aXplTGluZXJBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmIChpbnB1dHMubGVuZ3RoIDwgMiB8fCBpbnB1dHMubGVuZ3RoID4gMykge1xuICAgIHRocm93IG5ldyBFcnJvcignRGVxdWFudGl6ZUxpbmVhciByZXF1aXJlcyAyIG9yIDMgaW5wdXRzLicpO1xuICB9XG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAzICYmIGlucHV0c1sxXS5kaW1zID09PSBpbnB1dHNbMl0uZGltcykge1xuICAgIHRocm93IG5ldyBFcnJvcigneC1zY2FsZSBhbmQgeC16ZXJvLXBvaW50IG11c3QgaGF2ZSB0aGUgc2FtZSBzaGFwZS4nKTtcbiAgfVxuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMF0uZGF0YVR5cGUgIT09IGlucHV0c1syXS5kYXRhVHlwZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigneCBhbmQgeC16ZXJvLXBvaW50IG11c3QgaGF2ZSB0aGUgc2FtZSBkYXRhIHR5cGUuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1swXS5kYXRhVHlwZSA9PT0gRGF0YVR5cGUuaW50MzIgJiYgaW5wdXRzLmxlbmd0aCA+IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0luIHRoZSBjYXNlIG9mIGRlcXVhbnRpemluZyBpbnQzMiB0aGVyZSBpcyBubyB6ZXJvIHBvaW50LicpO1xuICB9XG4gIGlmIChpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDAgJiYgaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSAxICYmIGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzY2FsZSBpbnB1dCBtdXN0IGJlIGEgc2NhbGFyLCBhIDFEIHRlbnNvciwgb3IgaGF2ZSB0aGUgc2FtZSByYW5rIGFzIHRoZSBpbnB1dCB0ZW5zb3IuJyk7XG4gIH1cbiAgLy8gdmFsaWRhdGUgc2NhbGUgYW5kIHplcm8tcG9pbnQgaW5wdXQgc2hhcGVzXG4gIGlmIChpbnB1dHMubGVuZ3RoID4gMikge1xuICAgIC8vIHplcm8tcG9pbnQgaW5wdXQgdHlwZSBzaG91bGQgYmUgdGhlIHNhbWUgYXMgaW5wdXQgZGF0YSB0eXBlLlxuICAgIGlmIChpbnB1dHNbMF0uZGF0YVR5cGUgIT09IGlucHV0c1syXS5kYXRhVHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd4IGFuZCB4LXplcm8tcG9pbnQgbXVzdCBoYXZlIHRoZSBzYW1lIGRhdGEgdHlwZS4nKTtcbiAgICB9XG4gICAgLy8gU2NhbGUgYW5kIHplcm8tcG9pbnQgaW5wdXRzIG11c3QgaGF2ZSB0aGUgc2FtZSBzaGFwZVxuICAgIGlmIChpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IGlucHV0c1syXS5kaW1zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzY2FsZSBhbmQgemVyby1wb2ludCBpbnB1dHMgbXVzdCBoYXZlIHRoZSBzYW1lIHJhbmsuJyk7XG4gICAgfVxuICAgIGlmICghaW5wdXRzWzFdLmRpbXMubWFwKChkLCBpKSA9PiBkID09PSBpbnB1dHNbMl0uZGltc1tpXSkucmVkdWNlKChhLCBiKSA9PiBhICYmIGIsIHRydWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NjYWxlIGFuZCB6ZXJvLXBvaW50IGlucHV0cyBtdXN0IGhhdmUgdGhlIHNhbWUgc2hhcGUuJyk7XG4gICAgfVxuICB9XG4gIC8vIFZhbGlkYXRlIGJsb2NrU2l6ZVxuICBpZiAoYXR0cmlidXRlcy5ibG9ja1NpemUgPiAwKSB7XG4gICAgLy8gQmxvY2sgcXVuYXRpemF0aW9uXG4gICAgaWYgKGlucHV0c1sxXS5kaW1zLmxlbmd0aCA9PT0gMCB8fCAoaW5wdXRzWzFdLmRpbXMubGVuZ3RoID09PSAxICYmIGlucHV0c1sxXS5kaW1zWzBdID09PSAxKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdibG9ja1NpemUgbXVzdCBiZSBzZXQgb25seSBmb3IgYmxvY2sgcXVhbnRpemF0aW9uLicpO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICAhaW5wdXRzWzFdLmRpbXMubWFwKChkLCBpKSA9PiBpID09PSBhdHRyaWJ1dGVzLmF4aXMgfHwgZCA9PT0gaW5wdXRzWzBdLmRpbXNbaV0pLnJlZHVjZSgoYSwgYikgPT4gYSAmJiBiLCB0cnVlKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGb3IgYmxvY2sgcXVuYXRpemF0aW9uLCBzY2FsZSBpbnB1dCBzaGFwZSB0byBtYXRjaCB0aGUgaW5wdXQgc2hhcGUgZXhjZXB0IGZvciB0aGUgYXhpcycpO1xuICAgIH1cbiAgICAvLyBTY2FsZSBpbnB1dCByYW5rIHNob3VsZCBiZSBzYW1lIGFzIHRoZSBpbnB1dCByYW5rXG4gICAgaWYgKGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZvciBibG9jayBxdW5hdGl6YXRpb24gdGhlIHNjYWxlIGlucHV0IHJhbmsgbXVzdCBiZSB0aGUgc2FtZSBhcyB0aGUgeCByYW5rLicpO1xuICAgIH1cbiAgICBjb25zdCBkSSA9IGlucHV0c1swXS5kaW1zW2F0dHJpYnV0ZXMuYXhpc107XG4gICAgY29uc3Qgc2kgPSBpbnB1dHNbMV0uZGltc1thdHRyaWJ1dGVzLmF4aXNdO1xuICAgIGlmIChhdHRyaWJ1dGVzLmJsb2NrU2l6ZSA8IE1hdGguY2VpbChkSSAvIHNpKSB8fCBhdHRyaWJ1dGVzLmJsb2NrU2l6ZSA+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+IGlucHV0LnB1c2goTnVtYmVyKHYpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgJHtpZHh9IG11c3QgYmUgYW4gYXJyYXkgb2YgaW50MzIgb3IgaW50NjRgKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGlucHV0O1xufTtcblxuY29uc3QgY3JlYXRlU2xpY2VBdHRyaWJ1dGVzRnJvbUlucHV0cyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IFNsaWNlQXR0cmlidXRlcyxcbik6IFNsaWNlQXR0cmlidXRlcyA9PiB7XG4gIGlmIChpbnB1dHMubGVuZ3RoID4gMSkge1xuICAgIGNvbnN0IHN0YXJ0czogbnVtYmVyW10gPSByZWFkSW5wdXQoaW5wdXRzLCAxKTtcbiAgICBjb25zdCBlbmRzOiBudW1iZXJbXSA9IHJlYWRJbnB1dChpbnB1dHMsIDIpO1xuICAgIGxldCBheGVzOiBudW1iZXJbXSA9IHJlYWRJbnB1dChpbnB1dHMsIDMpO1xuICAgIGlmIChheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYXhlcyA9IFsuLi5BcnJheShpbnB1dHNbMF0uZGltcy5sZW5ndGgpLmtleXMoKV07XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBzdGFydHMsIGVuZHMsIGF4ZXMgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZXM7XG4gIH1cbn07XG5cbmNvbnN0IGZpeFN0YXJ0RW5kVmFsdWVzID0gKFxuICB2YWx1ZTogbnVtYmVyLFxuICBpbmRleDogbnVtYmVyLFxuICBpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgYXhlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHN0ZXBzOiByZWFkb25seSBudW1iZXJbXSxcbik6IG51bWJlciA9PiB7XG4gIGxldCBuZXdWYWx1ZSA9IHZhbHVlO1xuICBpZiAodmFsdWUgPCAwKSB7XG4gICAgbmV3VmFsdWUgKz0gaW5wdXRTaGFwZVtheGVzW2luZGV4XV07XG4gIH1cbiAgaWYgKHN0ZXBzW2luZGV4XSA8IDApIHtcbiAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4obmV3VmFsdWUsIGlucHV0U2hhcGVbYXhlc1tpbmRleF1dIC0gMSkpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBNYXRoLm1heCgwLCBNYXRoLm1pbihuZXdWYWx1ZSwgaW5wdXRTaGFwZVtheGVzW2luZGV4XV0pKTtcbiAgfVxufTtcblxuY29uc3QgY2FsY3VsYXRlSW5wdXRJbmRpY2VzSW1wbCA9IChcbiAgaW5wdXQ6IEluZGljZXNIZWxwZXIsXG4gIG91dHB1dDogSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4pOiBzdHJpbmcgPT5cbiAgYGZuIGNhbGN1bGF0ZUlucHV0SW5kaWNlcyhvdXRwdXRfaW5kaWNlczogJHtvdXRwdXQudHlwZS5pbmRpY2VzfSkgLT4gJHtpbnB1dC50eXBlLmluZGljZXN9IHtcbiAgICAgICAgICB2YXIgaW5wdXRfaW5kaWNlczogJHtpbnB1dC50eXBlLmluZGljZXN9O1xuICAgICAgICAgIHZhciBjYXJyeSA9IDB1O1xuICAgICAgICAgIGZvciAodmFyIGkgPSAke2lucHV0U2hhcGUubGVuZ3RofTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGxldCBpbnB1dF9zaGFwZV9pID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLmlucHV0X3NoYXBlJywgJ2knLCBpbnB1dFNoYXBlLmxlbmd0aCl9O1xuICAgICAgICAgICAgbGV0IHN0ZXBzX2kgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMuc3RlcHMnLCAnaScsIGlucHV0U2hhcGUubGVuZ3RoKX07XG4gICAgICAgICAgICBsZXQgc2lnbnNfaSA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5zaWducycsICdpJywgaW5wdXRTaGFwZS5sZW5ndGgpfTtcbiAgICAgICAgICAgIGxldCBzdGFydHNfaSA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5zdGFydHMnLCAnaScsIGlucHV0U2hhcGUubGVuZ3RoKX07XG4gICAgICAgICAgICB2YXIgb3V0cHV0X2luZGV4ID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCAnaScpfTtcbiAgICAgICAgICAgIHZhciBpbnB1dF9pbmRleCA9IG91dHB1dF9pbmRleCAqIHN0ZXBzX2kgKyBzdGFydHNfaSArIGNhcnJ5O1xuICAgICAgICAgICAgY2FycnkgPSBpbnB1dF9pbmRleCAvIGlucHV0X3NoYXBlX2k7XG4gICAgICAgICAgICBpbnB1dF9pbmRleCA9IGlucHV0X2luZGV4ICUgaW5wdXRfc2hhcGVfaTtcbiAgICAgICAgICAgIGlmIChzaWduc19pIDwgMCkge1xuICAgICAgICAgICAgICBpbnB1dF9pbmRleCA9IGlucHV0X3NoYXBlX2kgLSBpbnB1dF9pbmRleCAtIDF1ICsgc3RhcnRzX2k7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0X2luZGljZXMnLCAnaScsICdpbnB1dF9pbmRleCcpfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGlucHV0X2luZGljZXM7XG4gICAgICB9YDtcblxuY29uc3QgY3JlYXRlU2xpY2VQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogU2xpY2VBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGlucHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKGlucHV0U2hhcGUpO1xuICBjb25zdCBheGVzID1cbiAgICBhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoID4gMFxuICAgICAgPyBTaGFwZVV0aWwubm9ybWFsaXplQXhlcyhhdHRyaWJ1dGVzLmF4ZXMsIGlucHV0U2hhcGUubGVuZ3RoKVxuICAgICAgOiBbLi4uQXJyYXkoaW5wdXRTaGFwZS5sZW5ndGgpLmtleXMoKV07XG4gIGxldCBzdGVwcyA9IHJlYWRJbnB1dChpbnB1dHMsIDQpO1xuICBzdGVwcy5mb3JFYWNoKFxuICAgIChzdGVwKSA9PlxuICAgICAgc3RlcCAhPT0gMCB8fFxuICAgICAgKCgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzdGVwIGNhbm5vdCBiZSAwJyk7XG4gICAgICB9KSxcbiAgKTtcbiAgaWYgKHN0ZXBzLmxlbmd0aCA9PT0gMCkge1xuICAgIHN0ZXBzID0gQXJyYXkoYXhlcy5sZW5ndGgpLmZpbGwoMSk7XG4gIH1cbiAgY29uc3Qgc3RhcnRzID0gYXR0cmlidXRlcy5zdGFydHMubWFwKChzdGFydCwgaSkgPT4gZml4U3RhcnRFbmRWYWx1ZXMoc3RhcnQsIGksIGlucHV0U2hhcGUsIGF4ZXMsIHN0ZXBzKSk7XG5cbiAgY29uc3QgZW5kcyA9IGF0dHJpYnV0ZXMuZW5kcy5tYXAoKGVuZCwgaSkgPT4gZml4U3RhcnRFbmRWYWx1ZXMoZW5kLCBpLCBpbnB1dFNoYXBlLCBheGVzLCBzdGVwcykpO1xuXG4gIGlmIChheGVzLmxlbmd0aCAhPT0gc3RhcnRzLmxlbmd0aCB8fCBheGVzLmxlbmd0aCAhPT0gZW5kcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0YXJ0LCBlbmRzIGFuZCBheGVzIHNob3VsZCBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiBlbGVtZW50cycpO1xuICB9XG5cbiAgaWYgKGF4ZXMubGVuZ3RoICE9PSBpbnB1dFNoYXBlLmxlbmd0aCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRTaGFwZS5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKCFheGVzLmluY2x1ZGVzKGkpKSB7XG4gICAgICAgIHN0YXJ0cy5zcGxpY2UoaSwgMCwgMCk7XG4gICAgICAgIGVuZHMuc3BsaWNlKGksIDAsIGlucHV0U2hhcGVbaV0pO1xuICAgICAgICBzdGVwcy5zcGxpY2UoaSwgMCwgMSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGNvbnN0IHNpZ25zID0gc3RlcHMubWFwKChzdGVwKSA9PiBNYXRoLnNpZ24oc3RlcCkpO1xuICAvLyBDb252ZXJ0IG5lZ2F0aXZlIHN0ZXBzIHRvIHBvc2l0aXZlIHN0ZXBzIGFuZCByZXZlcnNlIHN0YXJ0cyBhbmQgZW5kc1xuICBzdGVwcy5mb3JFYWNoKChzdGVwLCBpLCBhcnJheSkgPT4ge1xuICAgIGlmIChzdGVwIDwgMCkge1xuICAgICAgY29uc3QgbnVtU3RlcHMgPSAoZW5kc1tpXSAtIHN0YXJ0c1tpXSkgLyBzdGVwO1xuICAgICAgY29uc3QgbmV3RW5kID0gc3RhcnRzW2ldO1xuICAgICAgY29uc3QgbmV3U3RhcnQgPSBuZXdFbmQgKyBudW1TdGVwcyAqIHN0ZXBzW2ldO1xuICAgICAgc3RhcnRzW2ldID0gbmV3U3RhcnQ7XG4gICAgICBlbmRzW2ldID0gbmV3RW5kO1xuICAgICAgYXJyYXlbaV0gPSAtc3RlcDtcbiAgICB9XG4gIH0pO1xuICAvLyBPdXRwdXQgcmFuayBpcyBleHBlY3RlZCB0byBiZSBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIGlucHV0IHJhbmsuXG4gIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRTaGFwZS5zbGljZSgwKTtcbiAgYXhlcy5mb3JFYWNoKChheGlzLCBfKSA9PiB7XG4gICAgb3V0cHV0U2hhcGVbYXhpc10gPSBNYXRoLmNlaWwoKGVuZHNbYXhpc10gLSBzdGFydHNbYXhpc10pIC8gc3RlcHNbYXhpc10pO1xuICB9KTtcbiAgY29uc3Qgb3V0cHV0VGVuc29ySW5mbzogVGVuc29ySW5mbyA9IHsgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfTtcblxuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgpO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgeyBuYW1lOiAnb3V0cHV0U2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgeyBuYW1lOiAnc3RhcnRzJywgdHlwZTogJ3UzMicsIGxlbmd0aDogc3RhcnRzLmxlbmd0aCB9LFxuICAgIHsgbmFtZTogJ3NpZ25zJywgdHlwZTogJ2kzMicsIGxlbmd0aDogc2lnbnMubGVuZ3RoIH0sXG4gICAgeyBuYW1lOiAnc3RlcHMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBzdGVwcy5sZW5ndGggfSxcbiAgXTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogc3RhcnRzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogc2lnbnMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogc3RlcHMgfSxcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgb3V0cHV0U2hhcGUpLFxuICBdO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgb3V0cHV0KX1cbiAgICAgICAgJHtjYWxjdWxhdGVJbnB1dEluZGljZXNJbXBsKGlucHV0LCBvdXRwdXQsIGlucHV0U2hhcGUpfVxuICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG4gICAgICAgICAgbGV0IG91dHB1dF9pbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgICAgIGxldCBpbnB1dF9pbmRpY2VzID0gY2FsY3VsYXRlSW5wdXRJbmRpY2VzKG91dHB1dF9pbmRpY2VzKTtcbiAgICAgICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsIGlucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpKX1cbiAgICAgIH1gO1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdTbGljZScsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7c2lnbnMubGVuZ3RofV8ke3N0YXJ0cy5sZW5ndGh9XyR7c3RlcHMubGVuZ3RofWAsIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW291dHB1dFRlbnNvckluZm9dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwoaW5wdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3Qgc2xpY2UgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFNsaWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGNvbnN0IHVwZGF0ZWRBdHRyaWJ1dGVzID0gY3JlYXRlU2xpY2VBdHRyaWJ1dGVzRnJvbUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVTbGljZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCB1cGRhdGVkQXR0cmlidXRlcyksIHsgaW5wdXRzOiBbMF0gfSk7XG4gIC8vIGlmIChTaGFwZVV0aWwuc2l6ZShwcm9ncmFtLm91dHB1dHNbMF0uZGltcykgPiAwKSB7XG4gIC8vICAgY29udGV4dC5jb21wdXRlKHByb2dyYW1JbmZvTG9hZGVyLCB7aW5wdXRzOiBbMF19KTtcbiAgLy8gfSBlbHNlIHtcbiAgLy8gICAvLyBUT0RPOiBzdXBwb3J0IGVtcHR5IG91dHB1dFxuICAvLyAgIHRocm93IG5ldyBFcnJvcignc2xpY2U6IG91dHB1dCBzaXplIGlzIDAnKTtcbiAgLy8gfVxufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlU2xpY2VBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogU2xpY2VBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3Qgc3RhcnRzID0gYXR0cmlidXRlcy5zdGFydHMgYXMgbnVtYmVyW107XG4gIGNvbnN0IGVuZHMgPSBhdHRyaWJ1dGVzLmVuZHMgYXMgbnVtYmVyW107XG4gIGNvbnN0IGF4ZXMgPSBhdHRyaWJ1dGVzLmF4ZXMgYXMgbnVtYmVyW107XG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBzdGFydHMsIGVuZHMsIGF4ZXMgfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vLyBUT0RPOiB0aGlzIGlzIHRoZSBzYW1lIG5haXZlIGltcGxlbWVudGF0aW9uIHdlIHVzZSBmb3IgcmVkdWNlIHRoYXQgaGFzXG4vLyBwZXJmb3JtYW5jZSBsaW1pdGF0aW9ucyB3aGVuIHRoZSByZWR1Y2VkIGF4aXMgaXMgbG9uZy4gTmVlZCB0byBhZGRcbi8vIGEgb3B0aW1pemVkIGNvZGVwYXRoIGZvciB0aGlzLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0IH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHsgY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8gfSBmcm9tICcuL3RyYW5zcG9zZSc7XG5cbmltcG9ydCB7XG4gIGdldE1heENvbXBvbmVudHMsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHN1bVZlY3RvcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1NvZnRtYXggb3AgcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxufTtcblxuZXhwb3J0IGludGVyZmFjZSBTb2Z0bWF4QXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGF4aXM6IG51bWJlcjtcbn1cblxuY29uc3QgY3JlYXRlU29mdG1heFByb2dyYW1JbmZvID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBTb2Z0bWF4QXR0cmlidXRlcykgPT4ge1xuICBjb25zdCBpbnB1dCA9IGNvbnRleHQuaW5wdXRzWzBdO1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXQuZGltcztcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKGlucHV0U2hhcGUpO1xuICBjb25zdCBpbnB1dFJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcbiAgY29uc3QgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMuYXhpcywgaW5wdXRSYW5rKTtcbiAgY29uc3QgaXNUcmFuc3Bvc2VSZXF1aXJlZCA9IGF4aXMgPCBpbnB1dFNoYXBlLmxlbmd0aCAtIDE7XG4gIGxldCB0cmFuc3Bvc2VkSW5wdXQ6IFRlbnNvclZpZXc7XG4gIGxldCBwZXJtOiBudW1iZXJbXSA9IFtdO1xuXG4gIGlmIChpc1RyYW5zcG9zZVJlcXVpcmVkKSB7XG4gICAgcGVybSA9IEFycmF5LmZyb20oeyBsZW5ndGg6IGlucHV0UmFuayB9LCAoXywgaSkgPT4gaSk7XG4gICAgcGVybVtheGlzXSA9IGlucHV0UmFuayAtIDE7XG4gICAgcGVybVtpbnB1dFJhbmsgLSAxXSA9IGF4aXM7XG5cbiAgICB0cmFuc3Bvc2VkSW5wdXQgPSBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8oaW5wdXQsIHBlcm0pLCB7XG4gICAgICBpbnB1dHM6IFtpbnB1dF0sXG4gICAgICBvdXRwdXRzOiBbLTFdLFxuICAgIH0pWzBdO1xuICB9IGVsc2Uge1xuICAgIHRyYW5zcG9zZWRJbnB1dCA9IGlucHV0O1xuICB9XG5cbiAgY29uc3QgdHJhbnNwb3NlZElucHV0U2hhcGUgPSB0cmFuc3Bvc2VkSW5wdXQuZGltcztcbiAgY29uc3QgY29scyA9IHRyYW5zcG9zZWRJbnB1dFNoYXBlW2lucHV0UmFuayAtIDFdO1xuICBjb25zdCByb3dzID0gb3V0cHV0U2l6ZSAvIGNvbHM7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKGNvbHMpO1xuICBjb25zdCBwYWNrZWRDb2xzID0gY29scyAvIGNvbXBvbmVudHM7XG4gIGxldCBXRyA9IDY0O1xuICAvLyBJZiBvbmx5IG9uZSB3b3JrZ3JvdXAgaXMgZGlzcGF0Y2hlZCwgaW5jcmVhc2Ugd29ya2dyb3VwU2l6ZSB0byBpbXByb3ZlIHBhcmFsbGVsaXNtLlxuICBpZiAocm93cyA9PT0gMSkge1xuICAgIFdHID0gMjU2O1xuICB9XG4gIGNvbnN0IG1heFZlY3RvciA9IChuYW1lOiBzdHJpbmcsIGNvbXBvbmVudHM6IG51bWJlcikgPT4ge1xuICAgIGlmIChjb21wb25lbnRzID09PSA0KSB7XG4gICAgICByZXR1cm4gYG1heChtYXgoJHtuYW1lfS54LCAke25hbWV9LnkpLCBtYXgoJHtuYW1lfS56LCAke25hbWV9LncpKWA7XG4gICAgfSBlbHNlIGlmIChjb21wb25lbnRzID09PSAyKSB7XG4gICAgICByZXR1cm4gYG1heCgke25hbWV9LngsICR7bmFtZX0ueSlgO1xuICAgIH0gZWxzZSBpZiAoY29tcG9uZW50cyA9PT0gMykge1xuICAgICAgcmV0dXJuIGBtYXgobWF4KCR7bmFtZX0ueCwgJHtuYW1lfS55KSwgJHtuYW1lfS56KWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5hbWU7XG4gIH07XG4gIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKCd4JywgdHJhbnNwb3NlZElucHV0LmRhdGFUeXBlLCB0cmFuc3Bvc2VkSW5wdXQuZGltcywgY29tcG9uZW50cyk7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdyZXN1bHQnLCB0cmFuc3Bvc2VkSW5wdXQuZGF0YVR5cGUsIHRyYW5zcG9zZWRJbnB1dC5kaW1zLCBjb21wb25lbnRzKTtcbiAgY29uc3QgdmFsdWVUeXBlID0geC50eXBlLnZhbHVlO1xuICAvLyA2LjIuNCBpbiB3Z3NsIHNwZWNcbiAgY29uc3QgdGhyZWFkTWF4RGVjbCA9XG4gICAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKHRyYW5zcG9zZWRJbnB1dC5kYXRhVHlwZSkgPT09ICdmMzInXG4gICAgICA/IGB2YXIgdGhyZWFkTWF4ID0gJHt2YWx1ZVR5cGV9KC0zLjQwMjgyM2UrMzhmKTtgXG4gICAgICA6IGB2YXIgdGhyZWFkTWF4ID0gJHt2YWx1ZVR5cGV9KC02NTUwNC4waCk7YDtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICAgICB2YXI8d29ya2dyb3VwPiByb3dNYXhTaGFyZWQgOiAke3ZhbHVlVHlwZX07XG4gICAgICB2YXI8d29ya2dyb3VwPiByb3dTdW1TaGFyZWQgOiAke3ZhbHVlVHlwZX07XG4gICAgICB2YXI8d29ya2dyb3VwPiB0aHJlYWRTaGFyZWQgOiBhcnJheTwke3ZhbHVlVHlwZX0sICR7V0d9PjtcblxuICAgICAgZm4gZ2V0VmFsdWUocm93OiBpMzIsIGNvbDogaTMyLCByb3dfc3RyaWRlOiBpMzIpIC0+ICR7dmFsdWVUeXBlfSB7XG4gICAgICAgIGxldCBpbmRleCA9IHJvdyAqIHJvd19zdHJpZGUgKyBjb2w7XG4gICAgICAgIHJldHVybiB4W2luZGV4XTtcbiAgICAgIH1cblxuICAgICAgZm4gc2V0VmFsdWUocm93OiBpMzIsIGNvbDogaTMyLCByb3dfc3RyaWRlOiBpMzIsIHZhbHVlOiAke3ZhbHVlVHlwZX0pIHtcbiAgICAgICAgbGV0IGluZGV4ID0gcm93ICogcm93X3N0cmlkZSArIGNvbDtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3JtKCdwYWNrZWRDb2xzJywgJ2kzMicpLmRlY2xhcmVWYXJpYWJsZXMoeCwgb3V0cHV0KX1cbiAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydChXRyl9XG4gICAgICAgIGxldCBnaW5kZXggPSBpMzIoZ2xvYmFsX2lkeCk7XG4gICAgICAgIGxldCBsaW5kZXggPSBpMzIobG9jYWxfaWR4KTtcbiAgICAgICAgY29uc3Qgd2cgPSAke1dHfTtcbiAgICAgICAgbGV0IHJvdyA9IGdpbmRleCAvIHdnO1xuICAgICAgICBsZXQgY29scyA9IHVuaWZvcm1zLnBhY2tlZENvbHM7XG4gICAgICAgIGxldCByb3dfc3RyaWRlIDogaTMyID0gdW5pZm9ybXMucGFja2VkQ29scztcblxuICAgICAgICAvLyBmaW5kIHRoZSByb3dzIG1heFxuICAgICAgICAke3RocmVhZE1heERlY2x9XG4gICAgICAgIGZvciAodmFyIGNvbCA9IGxpbmRleDsgY29sIDwgY29sczsgY29sICs9IHdnKSB7XG4gICAgICAgICAgbGV0IHZhbHVlID0gZ2V0VmFsdWUocm93LCBjb2wsIHJvd19zdHJpZGUpO1xuICAgICAgICAgIHRocmVhZE1heCA9IG1heCh0aHJlYWRNYXgsIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGluZGV4IDwgY29scykge1xuICAgICAgICAgIHRocmVhZFNoYXJlZFtsaW5kZXhdID0gdGhyZWFkTWF4O1xuICAgICAgICB9XG4gICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgICB2YXIgcmVkdWNlU2l6ZSA9IG1pbihjb2xzLCB3Zyk7XG4gICAgICAgIGZvciAodmFyIGN1cnJTaXplID0gcmVkdWNlU2l6ZSA+PiAxOyAgY3VyclNpemUgPiAwOyBjdXJyU2l6ZSA9IHJlZHVjZVNpemUgPj4gMSkge1xuICAgICAgICAgIHJlZHVjZVNpemUgPSBjdXJyU2l6ZSArIChyZWR1Y2VTaXplICYgMSk7XG4gICAgICAgICAgaWYgKGxpbmRleCA8IGN1cnJTaXplKSB7XG4gICAgICAgICAgICB0aHJlYWRTaGFyZWRbbGluZGV4XSA9IG1heCh0aHJlYWRTaGFyZWRbbGluZGV4XSwgdGhyZWFkU2hhcmVkW2xpbmRleCArIHJlZHVjZVNpemVdKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsaW5kZXggPT0gMCkge1xuICAgICAgICAgIHJvd01heFNoYXJlZCA9ICR7dmFsdWVUeXBlfSgke21heFZlY3RvcigndGhyZWFkU2hhcmVkWzBdJywgY29tcG9uZW50cyl9KTtcbiAgICAgICAgfVxuICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgICAgLy8gZmluZCB0aGUgcm93cyBzdW1cbiAgICAgICAgdmFyIHRocmVhZFN1bSA9ICR7dmFsdWVUeXBlfSgwLjApO1xuICAgICAgICBmb3IgKHZhciBjb2wgPSBsaW5kZXg7IGNvbCA8IGNvbHM7IGNvbCArPSB3Zykge1xuICAgICAgICAgIGxldCBzdWJFeHAgPSBleHAoZ2V0VmFsdWUocm93LCBjb2wsIHJvd19zdHJpZGUpIC0gcm93TWF4U2hhcmVkKTtcbiAgICAgICAgICB0aHJlYWRTdW0gKz0gc3ViRXhwO1xuICAgICAgICB9XG4gICAgICAgIHRocmVhZFNoYXJlZFtsaW5kZXhdID0gdGhyZWFkU3VtO1xuICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgICAgZm9yICh2YXIgY3VyclNpemUgPSB3ZyA+PiAxOyAgY3VyclNpemUgPiAwOyBjdXJyU2l6ZSA9IGN1cnJTaXplID4+IDEpIHtcbiAgICAgICAgICBpZiAobGluZGV4IDwgY3VyclNpemUpIHtcbiAgICAgICAgICAgIHRocmVhZFNoYXJlZFtsaW5kZXhdID0gdGhyZWFkU2hhcmVkW2xpbmRleF0gKyB0aHJlYWRTaGFyZWRbbGluZGV4ICsgY3VyclNpemVdO1xuICAgICAgICAgIH1cbiAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxpbmRleCA9PSAwKSB7XG4gICAgICAgICAgcm93U3VtU2hhcmVkID0gJHt2YWx1ZVR5cGV9KCR7c3VtVmVjdG9yKCd0aHJlYWRTaGFyZWRbMF0nLCBjb21wb25lbnRzKX0pO1xuICAgICAgICB9XG4gICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgICAvLyBjYWxjdWxhdGUgZmluYWwgdmFsdWUgZm9yIGVhY2ggZWxlbWVudCBpbiB0aGUgcm93XG4gICAgICAgIGZvciAodmFyIGNvbCA9IGxpbmRleDsgY29sIDwgY29sczsgY29sICs9IHdnKSB7XG4gICAgICAgICAgbGV0IHZhbHVlID0gZXhwKGdldFZhbHVlKHJvdywgY29sLCByb3dfc3RyaWRlKSAtIHJvd01heFNoYXJlZCkgLyByb3dTdW1TaGFyZWQ7XG4gICAgICAgICAgc2V0VmFsdWUocm93LCBjb2wsIHJvd19zdHJpZGUsIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfWA7XG4gIGNvbnN0IHJlc3VsdCA9IGNvbnRleHQuY29tcHV0ZShcbiAgICB7XG4gICAgICBuYW1lOiAnU29mdG1heCcsXG4gICAgICAvLyBOb3RlIHRoYXQgaW4gSlNFUCwgV0cgc2l6ZSBpcyBub3QgaW5jbHVkZWQgaW4gY2FjaGUgYnkgZGVmYXVsdCwgYnV0IFdlYkdQVSBFUCBpdCBpcy5cbiAgICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2NvbXBvbmVudHN9OyR7V0d9YCwgaW5wdXREZXBlbmRlbmNpZXM6IFsndHlwZSddIH0sXG4gICAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiB0cmFuc3Bvc2VkSW5wdXRTaGFwZSwgZGF0YVR5cGU6IHRyYW5zcG9zZWRJbnB1dC5kYXRhVHlwZSB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiByb3dzIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtczogW3sgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IHBhY2tlZENvbHMgfV0sXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGlucHV0czogW3RyYW5zcG9zZWRJbnB1dF0sXG4gICAgICBvdXRwdXRzOiBbaXNUcmFuc3Bvc2VSZXF1aXJlZCA/IC0xIDogMF0sXG4gICAgfSxcbiAgKVswXTtcblxuICBpZiAoaXNUcmFuc3Bvc2VSZXF1aXJlZCkge1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhyZXN1bHQsIHBlcm0pLCB7XG4gICAgICBpbnB1dHM6IFtyZXN1bHRdLFxuICAgIH0pO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3Qgc29mdG1heCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogU29mdG1heEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjcmVhdGVTb2Z0bWF4UHJvZ3JhbUluZm8oY29udGV4dCwgYXR0cmlidXRlcyk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VTb2Z0bWF4QXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFNvZnRtYXhBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IGF4aXM6IGF0dHJpYnV0ZXMuYXhpcyBhcyBudW1iZXIgfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgZ2V0UmVwZWF0cyA9IChyZXBlYXRzVGVuc29yVmlldzogVGVuc29yVmlldyk6IHJlYWRvbmx5IG51bWJlcltdID0+XG4gIEFycmF5LmZyb20ocmVwZWF0c1RlbnNvclZpZXcuZ2V0QmlnSW50NjRBcnJheSgpLCBOdW1iZXIpO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaWxlIHJlcXVpcmVzIDIgaW5wdXRzLicpO1xuICB9XG5cbiAgaWYgKFxuICAgIGlucHV0c1swXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQgJiZcbiAgICBpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0MTYgJiZcbiAgICBpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmludDMyICYmXG4gICAgaW5wdXRzWzBdLmRhdGFUeXBlICE9PSBEYXRhVHlwZS51aW50MzJcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaWxlIG9ubHkgc3VwcG9ydCBmbG9hdCwgZmxvYXQxNiwgaW50MzIsIGFuZCB1aW50MzIgZGF0YSB0eXBlcycpO1xuICB9XG5cbiAgaWYgKGlucHV0c1sxXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuaW50NjQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbGUgYHJlcGVhdHNgIGlucHV0IHNob3VsZCBiZSBvZiBpbnQ2NCBkYXRhIHR5cGUnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbGUgYHJlcGVhdHNgIGlucHV0IHNob3VsZCBiZSAxLUQnKTtcbiAgfVxuXG4gIGNvbnN0IHJlcGVhdHM6IHJlYWRvbmx5IG51bWJlcltdID0gZ2V0UmVwZWF0cyhpbnB1dHNbMV0pO1xuXG4gIGlmIChyZXBlYXRzLmxlbmd0aCAhPT0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaWxlIGByZXBlYXRzYCBpbnB1dCBzaG91bGQgaGF2ZSBzYW1lIG51bWJlciBvZiBlbGVtZW50cyBhcyByYW5rIG9mIGlucHV0IGRhdGEgdGVuc29yJyk7XG4gIH1cbn07XG5cbmNvbnN0IGdldE91dHB1dFNoYXBlID0gKGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCByZXBlYXRzOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdID0+IHtcbiAgY29uc3Qgb3V0cHV0U2hhcGU6IG51bWJlcltdID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFNoYXBlLmxlbmd0aDsgKytpKSB7XG4gICAgb3V0cHV0U2hhcGUucHVzaChpbnB1dFNoYXBlW2ldICogcmVwZWF0c1tpXSk7XG4gIH1cblxuICByZXR1cm4gb3V0cHV0U2hhcGU7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVGlsZVByb2dyYW1JbmZvID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBzaGFwZT86IG51bWJlcltdKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IHJlcGVhdHM6IHJlYWRvbmx5IG51bWJlcltdID0gc2hhcGUgPT0gbnVsbCA/IGdldFJlcGVhdHMoaW5wdXRzWzFdKSA6IHNoYXBlO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGdldE91dHB1dFNoYXBlKGlucHV0U2hhcGUsIHJlcGVhdHMpO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuXG4gIGNvbnN0IGRhdGFUeXBlID0gaW5wdXRzWzBdLmRhdGFUeXBlO1xuICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgZGF0YVR5cGUsIGlucHV0U2hhcGUubGVuZ3RoKTtcbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICAgICAgY29uc3QgaW5wdXRTaGFwZSA9ICR7aW5wdXQuaW5kaWNlcyguLi5pbnB1dFNoYXBlKX07XG4gICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dF9zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG4gICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgICBsZXQgb3V0cHV0X2luZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICB2YXIgaW5wdXRfaW5kaWNlczogJHtpbnB1dC50eXBlLmluZGljZXN9O1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAke2lucHV0U2hhcGUubGVuZ3RofTsgaSsrKSB7XG4gICAgICAgIGxldCBpbnB1dF9kaW1faSA9ICR7aW5wdXQuaW5kaWNlc0dldCgndW5pZm9ybXMuaW5wdXRfc2hhcGUnLCAnaScpfTtcbiAgICAgICAgbGV0IGlucHV0X2RpbV92YWx1ZSA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dF9pbmRpY2VzJywgJ2knKX0gICUgaW5wdXRfZGltX2k7XG5cbiAgICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgJ2knLCAnaW5wdXRfZGltX3ZhbHVlJyl9XG4gICAgICB9XG4gICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsIGlucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpKX1cbiAgICB9YDtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdUaWxlJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtyZXBlYXRzfWAsIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgb3V0cHV0U2hhcGUpLFxuICAgICAgXSxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgdGlsZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUaWxlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMpLCB7IGlucHV0czogWzBdIH0pO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgQnJvYWRjYXN0VXRpbCwgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5jb25zdCBjcmVhdGVXaGVyZU9wUHJvZ3JhbVNoYWRlciA9IChcbiAgc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIsXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBkaW1zT3V0cHV0OiByZWFkb25seSBudW1iZXJbXSxcbiAgaXNCcm9hZGNhc3Q6IGJvb2xlYW4sXG4gIHR5cGVPdXRwdXQ6IG51bWJlcixcbikgPT4ge1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0X2RhdGEnLCB0eXBlT3V0cHV0LCBkaW1zT3V0cHV0Lmxlbmd0aCwgNCk7XG4gIGNvbnN0IGEgPSBpbnB1dFZhcmlhYmxlKCdhX2RhdGEnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLmxlbmd0aCwgNCk7XG4gIGNvbnN0IGIgPSBpbnB1dFZhcmlhYmxlKCdiX2RhdGEnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCwgNCk7XG4gIGNvbnN0IGMgPSBpbnB1dFZhcmlhYmxlKCdjX2RhdGEnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLmxlbmd0aCwgNCk7XG5cbiAgbGV0IGFzc2lnbm1lbnQ6IHN0cmluZztcbiAgY29uc3QgZXhwcmVzc2lvbiA9IChhOiBzdHJpbmcsIGI6IHN0cmluZywgYzogc3RyaW5nKSA9PiBgc2VsZWN0KCR7Yn0sICR7YX0sICR7Y30pYDtcbiAgaWYgKCFpc0Jyb2FkY2FzdCkge1xuICAgIGFzc2lnbm1lbnQgPSBvdXRwdXQuc2V0QnlPZmZzZXQoXG4gICAgICAnZ2xvYmFsX2lkeCcsXG4gICAgICBleHByZXNzaW9uKGEuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKSwgYi5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpLCBjLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JykpLFxuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3Qgc2luZ2xlQXNzaWdubWVudCA9IChyZXNTdHI6IHN0cmluZywgeDogbnVtYmVyLCB0eXBlQ2FzdCA9ICcnKSA9PiB7XG4gICAgICBjb25zdCBleHByZXNzaW9uQSA9IGBhX2RhdGFbaW5kZXhfYSR7eH1dW2NvbXBvbmVudF9hJHt4fV1gO1xuICAgICAgY29uc3QgZXhwcmVzc2lvbkIgPSBgYl9kYXRhW2luZGV4X2Ike3h9XVtjb21wb25lbnRfYiR7eH1dYDtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgICBjb25zdCBleHByZXNzaW9uQyA9IGBib29sKGNfZGF0YVtpbmRleF9jJHt4fV0gJiAoMHhmZnUgPDwgKGNvbXBvbmVudF9jJHt4fSAqIDgpKSlgO1xuICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyR7eH0gPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoYGdsb2JhbF9pZHggKiA0dSArICR7eH11YCl9O1xuICAgICAgICAgICAgbGV0IG9mZnNldF9hJHt4fSA9ICR7YS5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldChgb3V0cHV0X2luZGljZXMke3h9YCwgb3V0cHV0KX07XG4gICAgICAgICAgICBsZXQgb2Zmc2V0X2Ike3h9ID0gJHtiLmJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0KGBvdXRwdXRfaW5kaWNlcyR7eH1gLCBvdXRwdXQpfTtcbiAgICAgICAgICAgIGxldCBvZmZzZXRfYyR7eH0gPSAke2MuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoYG91dHB1dF9pbmRpY2VzJHt4fWAsIG91dHB1dCl9O1xuICAgICAgICAgICAgbGV0IGluZGV4X2Eke3h9ID0gb2Zmc2V0X2Eke3h9IC8gNHU7XG4gICAgICAgICAgICBsZXQgaW5kZXhfYiR7eH0gPSBvZmZzZXRfYiR7eH0gLyA0dTtcbiAgICAgICAgICAgIGxldCBpbmRleF9jJHt4fSA9IG9mZnNldF9jJHt4fSAvIDR1O1xuICAgICAgICAgICAgbGV0IGNvbXBvbmVudF9hJHt4fSA9IG9mZnNldF9hJHt4fSAlIDR1O1xuICAgICAgICAgICAgbGV0IGNvbXBvbmVudF9iJHt4fSA9IG9mZnNldF9iJHt4fSAlIDR1O1xuICAgICAgICAgICAgbGV0IGNvbXBvbmVudF9jJHt4fSA9IG9mZnNldF9jJHt4fSAlIDR1O1xuICAgICAgICAgICAgJHtyZXNTdHJ9WyR7eH1dID0gJHt0eXBlQ2FzdH0oJHtleHByZXNzaW9uKGV4cHJlc3Npb25BLCBleHByZXNzaW9uQiwgZXhwcmVzc2lvbkMpfSk7XG4gICAgICAgICAgYDtcbiAgICB9O1xuICAgIGlmICh0eXBlT3V0cHV0ID09PSBEYXRhVHlwZS5ib29sKSB7XG4gICAgICBhc3NpZ25tZW50ID0gYFxuICAgICAgICAgICAgdmFyIGRhdGEgPSB2ZWM0PHUzMj4oMCk7XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAwLCAndTMyJyl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAxLCAndTMyJyl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAyLCAndTMyJyl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAzLCAndTMyJyl9XG4gICAgICAgICAgICBvdXRwdXRfZGF0YVtnbG9iYWxfaWR4XSA9IGRvdCh2ZWM0PHUzMj4oMHgxLCAweDEwMCwgMHgxMDAwMCwgMHgxMDAwMDAwKSwgdmVjNDx1MzI+KGRhdGEpKTtgO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3NpZ25tZW50ID0gYFxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdvdXRwdXRfZGF0YVtnbG9iYWxfaWR4XScsIDApfVxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdvdXRwdXRfZGF0YVtnbG9iYWxfaWR4XScsIDEpfVxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdvdXRwdXRfZGF0YVtnbG9iYWxfaWR4XScsIDIpfVxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdvdXRwdXRfZGF0YVtnbG9iYWxfaWR4XScsIDMpfVxuICAgICAgICAgIGA7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGBcbiAgICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3JtKCd2ZWNfc2l6ZScsICd1MzInKS5kZWNsYXJlVmFyaWFibGVzKGMsIGEsIGIsIG91dHB1dCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy52ZWNfc2l6ZScpfVxuICAgICAgICAke2Fzc2lnbm1lbnR9XG4gICAgICB9YDtcbn07XG5cbmNvbnN0IGNyZWF0ZVdoZXJlT3BQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgZGltc0EgPSBpbnB1dHNbMV0uZGltcztcbiAgY29uc3QgZGltc0IgPSBpbnB1dHNbMl0uZGltcztcbiAgY29uc3QgZGltc0MgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3Qgb3V0cHV0RGF0YVR5cGUgPSBpbnB1dHNbMV0uZGF0YVR5cGU7XG5cbiAgY29uc3QgaXNCcm9hZGNhc3QgPSAhKFNoYXBlVXRpbC5hcmVFcXVhbChkaW1zQSwgZGltc0IpICYmIFNoYXBlVXRpbC5hcmVFcXVhbChkaW1zQiwgZGltc0MpKTtcbiAgbGV0IG91dHB1dFNoYXBlID0gZGltc0E7XG4gIGxldCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUoZGltc0EpO1xuICAvLyBUT0RPOiBkZWFsIHdpdGggemVyby1zaXplZCB0ZW5zb3JzIChlZy4gZGltcz1bMSwwXSlcblxuICBpZiAoaXNCcm9hZGNhc3QpIHtcbiAgICBjb25zdCBjYWxjdWxhdGVkU2hhcGUgPSBCcm9hZGNhc3RVdGlsLmNhbGNTaGFwZShCcm9hZGNhc3RVdGlsLmNhbGNTaGFwZShkaW1zQSwgZGltc0IsIGZhbHNlKSEsIGRpbXNDLCBmYWxzZSk7XG4gICAgaWYgKCFjYWxjdWxhdGVkU2hhcGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IHBlcmZvcm0gd2hlcmUgb3Agb24gdGhlIGdpdmVuIHRlbnNvcnNcIik7XG4gICAgfVxuICAgIG91dHB1dFNoYXBlID0gY2FsY3VsYXRlZFNoYXBlO1xuICAgIG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIH1cblxuICBjb25zdCB2ZWNTaXplID0gTWF0aC5jZWlsKG91dHB1dFNpemUgLyA0KTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdXaGVyZScsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuaycsICdyYW5rJywgJ3JhbmsnXSB9LFxuICAgIGdldFNoYWRlclNvdXJjZTogKHNoYWRlckhlbHBlcikgPT5cbiAgICAgIGNyZWF0ZVdoZXJlT3BQcm9ncmFtU2hhZGVyKHNoYWRlckhlbHBlciwgaW5wdXRzLCBvdXRwdXRTaGFwZSwgaXNCcm9hZGNhc3QsIG91dHB1dERhdGFUeXBlKSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBvdXRwdXREYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLyAvIDQgLyogdmVjIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXM6IFtcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHZlY1NpemUgfSxcbiAgICAgICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoZGltc0MsIGRpbXNBLCBkaW1zQiwgb3V0cHV0U2hhcGUpLFxuICAgICAgXSxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB3aGVyZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlV2hlcmVPcFByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzKSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBhcmdNYXgsIGFyZ01pbiwgcGFyc2VBcmdNaW5NYXhBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvYXJnbWlubWF4JztcbmltcG9ydCB7IGF0dGVudGlvbiB9IGZyb20gJy4vb3BzL2F0dGVudGlvbic7XG5pbXBvcnQgeyBiYXRjaE5vcm0gfSBmcm9tICcuL29wcy9iYXRjaC1ub3JtJztcbmltcG9ydCB7IGJpYXNBZGQgfSBmcm9tICcuL29wcy9iaWFzLWFkZCc7XG5pbXBvcnQgeyBiaWFzU3BsaXRHZWx1IH0gZnJvbSAnLi9vcHMvYmlhcy1zcGxpdC1nZWx1JztcbmltcG9ydCAqIGFzIGJpbmFyeU9wcyBmcm9tICcuL29wcy9iaW5hcnktb3AnO1xuaW1wb3J0IHsgY29uY2F0LCBwYXJzZUNvbmNhdEF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9jb25jYXQnO1xuaW1wb3J0IHsgY29udiwgcGFyc2VDb252QXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2NvbnYnO1xuaW1wb3J0IHsgY29udlRyYW5zcG9zZSwgcGFyc2VDb252VHJhbnNwb3NlQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2NvbnYtdHJhbnNwb3NlJztcbmltcG9ydCB7IGN1bXN1bSwgcGFyc2VDdW1TdW1BdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvY3Vtc3VtJztcbmltcG9ydCB7IGRlcHRoVG9TcGFjZSwgcGFyc2VEZXB0aFRvU3BhY2VBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvZGVwdGgtdG8tc3BhY2UnO1xuaW1wb3J0IHsgZWluc3VtLCBwYXJzZUVpbnN1bUF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9laW5zdW0nO1xuaW1wb3J0IHsgZXhwYW5kIH0gZnJvbSAnLi9vcHMvZXhwYW5kJztcbmltcG9ydCB7IGZhc3RHZWx1IH0gZnJvbSAnLi9vcHMvZmFzdC1nZWx1JztcbmltcG9ydCB7IGdhdGhlciwgcGFyc2VHYXRoZXJBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvZ2F0aGVyJztcbmltcG9ydCB7IGdhdGhlck5ELCBwYXJzZUdhdGhlck5EQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2dhdGhlci1uZCc7XG5pbXBvcnQgeyBnYXRoZXJCbG9ja1F1YW50aXplZCwgcGFyc2VHYXRoZXJCbG9ja1F1YW50aXplZEF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9nYXRoZXItYmxvY2stcXVhbnRpemVkJztcbmltcG9ydCB7IGdhdGhlckVsZW1lbnRzLCBwYXJzZUdhdGhlckVsZW1lbnRzQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2dhdGhlci1lbGVtZW50cyc7XG5pbXBvcnQgeyBnZW1tLCBwYXJzZUdlbW1BdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvZ2VtbSc7XG5pbXBvcnQgeyBncmlkU2FtcGxlLCBwYXJzZUdyaWRTYW1wbGVBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvZ3JpZC1zYW1wbGUnO1xuaW1wb3J0IHsgZ3JvdXBRdWVyeUF0dGVudGlvbiB9IGZyb20gJy4vb3BzL2dyb3VwLXF1ZXJ5LWF0dGVudGlvbic7XG5pbXBvcnQgeyBpbnN0YW5jZU5vcm0gfSBmcm9tICcuL29wcy9pbnN0YW5jZS1ub3JtJztcbmltcG9ydCB7IGxheWVyTm9ybSB9IGZyb20gJy4vb3BzL2xheWVyLW5vcm0nO1xuaW1wb3J0IHsgbWF0TXVsIH0gZnJvbSAnLi9vcHMvbWF0bXVsJztcbmltcG9ydCB7IG1hdE11bE5CaXRzLCBwYXJzZU1hdE11bE5CaXRzQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL21hdG11bG5iaXRzJztcbmltcG9ydCB7IG11bHRpSGVhZEF0dGVudGlvbiwgcGFyc2VNdWx0aUhlYWRBdHRlbnRpb25BdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvbXVsdGloZWFkLWF0dGVudGlvbic7XG5pbXBvcnQgeyBwYWQgfSBmcm9tICcuL29wcy9wYWQnO1xuaW1wb3J0ICogYXMgcG9vbCBmcm9tICcuL29wcy9wb29sJztcbmltcG9ydCB7IGRlcXVhbnRpemVMaW5lYXIsIHBhcnNlRGVxdWFudGl6ZUxpbmVhckF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9xdWFudGl6ZS1saW5lYXInO1xuaW1wb3J0IHsgcmFuZ2UgfSBmcm9tICcuL29wcy9yYW5nZSc7XG5pbXBvcnQgeyBzY2F0dGVyTkQsIHBhcnNlU2NhdHRlck5EQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL3NjYXR0ZXItbmQnO1xuaW1wb3J0IHtcbiAgcmVkdWNlTDEsXG4gIHJlZHVjZUwyLFxuICByZWR1Y2VMb2dTdW0sXG4gIHJlZHVjZUxvZ1N1bUV4cCxcbiAgcmVkdWNlTWF4LFxuICByZWR1Y2VNZWFuLFxuICByZWR1Y2VNaW4sXG4gIHJlZHVjZVByb2QsXG4gIHJlZHVjZVN1bSxcbiAgcmVkdWNlU3VtU3F1YXJlLFxufSBmcm9tICcuL29wcy9yZWR1Y2UnO1xuaW1wb3J0IHsgcGFyc2VSZXNpemVBdHRyaWJ1dGVzLCByZXNpemUgfSBmcm9tICcuL29wcy9yZXNpemUnO1xuaW1wb3J0IHsgcm90YXJ5RW1iZWRkaW5nIH0gZnJvbSAnLi9vcHMvcm90YXJ5LWVtYmVkZGluZyc7XG5pbXBvcnQgeyBza2lwTGF5ZXJOb3JtIH0gZnJvbSAnLi9vcHMvc2tpcC1sYXllci1ub3JtJztcbmltcG9ydCB7IHBhcnNlU2xpY2VBdHRyaWJ1dGVzLCBzbGljZSB9IGZyb20gJy4vb3BzL3NsaWNlJztcbmltcG9ydCB7IHBhcnNlU29mdG1heEF0dHJpYnV0ZXMsIHNvZnRtYXggfSBmcm9tICcuL29wcy9zb2Z0bWF4JztcbmltcG9ydCB7IHBhcnNlU3BsaXRBdHRyaWJ1dGVzLCBzcGxpdCB9IGZyb20gJy4vb3BzL3NwbGl0JztcbmltcG9ydCB7IHRpbGUgfSBmcm9tICcuL29wcy90aWxlJztcbmltcG9ydCB7IHBhcnNlVHJhbnNwb3NlQXR0cmlidXRlcywgdHJhbnNwb3NlIH0gZnJvbSAnLi9vcHMvdHJhbnNwb3NlJztcbmltcG9ydCAqIGFzIHVuYXJ5T3BzIGZyb20gJy4vb3BzL3VuYXJ5LW9wJztcbmltcG9ydCB7IHdoZXJlIH0gZnJvbSAnLi9vcHMvd2hlcmUnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQgfSBmcm9tICcuL3R5cGVzJztcblxuZXhwb3J0IHR5cGUgUnVuRnVuY3Rpb24gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZT86IHVua25vd24pID0+IHZvaWQ7XG5leHBvcnQgdHlwZSBQYXJzZUF0dHJpYnV0ZUZ1bmN0aW9uID0gKGF0dHJpYnV0ZVJhdzogdW5rbm93bikgPT4gdW5rbm93bjtcbmV4cG9ydCB0eXBlIE9wZXJhdG9ySW1wbGVtZW50YXRpb24gPSBbUnVuRnVuY3Rpb25dIHwgW1J1bkZ1bmN0aW9uLCBQYXJzZUF0dHJpYnV0ZUZ1bmN0aW9uXTtcblxuZXhwb3J0IGNvbnN0IFdFQkdQVV9PUF9SRVNPTFZFX1JVTEVTOiBNYXA8c3RyaW5nLCBPcGVyYXRvckltcGxlbWVudGF0aW9uPiA9IG5ldyBNYXAoW1xuICBbJ0FicycsIFt1bmFyeU9wcy5hYnNdXSxcbiAgWydBY29zJywgW3VuYXJ5T3BzLmFjb3NdXSxcbiAgWydBY29zaCcsIFt1bmFyeU9wcy5hY29zaF1dLFxuICBbJ0FkZCcsIFtiaW5hcnlPcHMuYWRkXV0sXG4gIFsnQXJnTWF4JywgW2FyZ01heCwgcGFyc2VBcmdNaW5NYXhBdHRyaWJ1dGVzXV0sXG4gIFsnQXJnTWluJywgW2FyZ01pbiwgcGFyc2VBcmdNaW5NYXhBdHRyaWJ1dGVzXV0sXG4gIFsnQXNpbicsIFt1bmFyeU9wcy5hc2luXV0sXG4gIFsnQXNpbmgnLCBbdW5hcnlPcHMuYXNpbmhdXSxcbiAgWydBdGFuJywgW3VuYXJ5T3BzLmF0YW5dXSxcbiAgWydBdGFuaCcsIFt1bmFyeU9wcy5hdGFuaF1dLFxuICBbJ0F0dGVudGlvbicsIFthdHRlbnRpb25dXSxcbiAgLy8gVE9ETzogc3VwcG9ydCBuZXcgYXR0cmlidXRlcyBmb3IgQXZlcmFnZVBvb2wtMTBcbiAgWydBdmVyYWdlUG9vbCcsIFtwb29sLmF2ZXJhZ2VQb29sLCBwb29sLnBhcnNlQXZlcmFnZVBvb2xBdHRyaWJ1dGVzXV0sXG4gIFsnQmF0Y2hOb3JtYWxpemF0aW9uJywgW2JhdGNoTm9ybV1dLFxuICBbJ0JpYXNBZGQnLCBbYmlhc0FkZF1dLFxuICBbJ0JpYXNTcGxpdEdlbHUnLCBbYmlhc1NwbGl0R2VsdV1dLFxuICBbJ0Nhc3QnLCBbdW5hcnlPcHMuY2FzdCwgdW5hcnlPcHMucGFyc2VDYXN0QXR0cmlidXRlc11dLFxuICBbJ0NlaWwnLCBbdW5hcnlPcHMuY2VpbF1dLFxuICBbJ0NsaXAnLCBbdW5hcnlPcHMuY2xpcF1dLFxuICBbJ0NvbmNhdCcsIFtjb25jYXQsIHBhcnNlQ29uY2F0QXR0cmlidXRlc11dLFxuICBbJ0NvbnYnLCBbY29udiwgcGFyc2VDb252QXR0cmlidXRlc11dLFxuICBbJ0NvbnZUcmFuc3Bvc2UnLCBbY29udlRyYW5zcG9zZSwgcGFyc2VDb252VHJhbnNwb3NlQXR0cmlidXRlc11dLFxuICBbJ0NvcycsIFt1bmFyeU9wcy5jb3NdXSxcbiAgWydDb3NoJywgW3VuYXJ5T3BzLmNvc2hdXSxcbiAgWydDdW1TdW0nLCBbY3Vtc3VtLCBwYXJzZUN1bVN1bUF0dHJpYnV0ZXNdXSxcbiAgWydEZXB0aFRvU3BhY2UnLCBbZGVwdGhUb1NwYWNlLCBwYXJzZURlcHRoVG9TcGFjZUF0dHJpYnV0ZXNdXSxcbiAgWydEZXF1YW50aXplTGluZWFyJywgW2RlcXVhbnRpemVMaW5lYXIsIHBhcnNlRGVxdWFudGl6ZUxpbmVhckF0dHJpYnV0ZXNdXSxcbiAgWydEaXYnLCBbYmluYXJ5T3BzLmRpdl1dLFxuICBbJ0VpbnN1bScsIFtlaW5zdW0sIHBhcnNlRWluc3VtQXR0cmlidXRlc11dLFxuICBbJ0VsdScsIFt1bmFyeU9wcy5lbHUsIHVuYXJ5T3BzLnBhcnNlQWxwaGFBdHRyaWJ1dGVzXV0sXG4gIFsnRXF1YWwnLCBbYmluYXJ5T3BzLmVxdWFsXV0sXG4gIFsnRXJmJywgW3VuYXJ5T3BzLmVyZl1dLFxuICBbJ0V4cCcsIFt1bmFyeU9wcy5leHBdXSxcbiAgWydFeHBhbmQnLCBbZXhwYW5kXV0sXG4gIFsnRmFzdEdlbHUnLCBbZmFzdEdlbHVdXSxcbiAgWydGbG9vcicsIFt1bmFyeU9wcy5mbG9vcl1dLFxuICBbJ0Z1c2VkQ29udicsIFtjb252LCBwYXJzZUNvbnZBdHRyaWJ1dGVzXV0sXG4gIFsnR2F0aGVyJywgW2dhdGhlciwgcGFyc2VHYXRoZXJBdHRyaWJ1dGVzXV0sXG4gIFsnR2F0aGVyRWxlbWVudHMnLCBbZ2F0aGVyRWxlbWVudHMsIHBhcnNlR2F0aGVyRWxlbWVudHNBdHRyaWJ1dGVzXV0sXG4gIFsnR2F0aGVyQmxvY2tRdWFudGl6ZWQnLCBbZ2F0aGVyQmxvY2tRdWFudGl6ZWQsIHBhcnNlR2F0aGVyQmxvY2tRdWFudGl6ZWRBdHRyaWJ1dGVzXV0sXG4gIFsnR2F0aGVyTkQnLCBbZ2F0aGVyTkQsIHBhcnNlR2F0aGVyTkRBdHRyaWJ1dGVzXV0sXG4gIFsnR2VsdScsIFt1bmFyeU9wcy5nZWx1XV0sXG4gIFsnR2VtbScsIFtnZW1tLCBwYXJzZUdlbW1BdHRyaWJ1dGVzXV0sXG4gIFsnR2xvYmFsQXZlcmFnZVBvb2wnLCBbcG9vbC5nbG9iYWxBdmVyYWdlUG9vbCwgcG9vbC5wYXJzZUdsb2JhbEF2ZXJhZ2VQb29sQXR0cmlidXRlc11dLFxuICBbJ0dsb2JhbE1heFBvb2wnLCBbcG9vbC5nbG9iYWxNYXhQb29sLCBwb29sLnBhcnNlR2xvYmFsTWF4UG9vbEF0dHJpYnV0ZXNdXSxcbiAgWydHcmVhdGVyJywgW2JpbmFyeU9wcy5ncmVhdGVyXV0sXG4gIFsnR3JlYXRlck9yRXF1YWwnLCBbYmluYXJ5T3BzLmdyZWF0ZXJPckVxdWFsXV0sXG4gIFsnR3JpZFNhbXBsZScsIFtncmlkU2FtcGxlLCBwYXJzZUdyaWRTYW1wbGVBdHRyaWJ1dGVzXV0sXG4gIFsnR3JvdXBRdWVyeUF0dGVudGlvbicsIFtncm91cFF1ZXJ5QXR0ZW50aW9uXV0sXG4gIFsnSGFyZFNpZ21vaWQnLCBbdW5hcnlPcHMuaGFyZFNpZ21vaWQsIHVuYXJ5T3BzLnBhcnNlSGFyZFNpZ21vaWRBdHRyaWJ1dGVzXV0sXG4gIFsnSW5zdGFuY2VOb3JtYWxpemF0aW9uJywgW2luc3RhbmNlTm9ybV1dLFxuICBbJ0xheWVyTm9ybWFsaXphdGlvbicsIFtsYXllck5vcm1dXSxcbiAgWydMZWFreVJlbHUnLCBbdW5hcnlPcHMubGVha3lSZWx1LCB1bmFyeU9wcy5wYXJzZUFscGhhQXR0cmlidXRlc11dLFxuICBbJ0xlc3MnLCBbYmluYXJ5T3BzLmxlc3NdXSxcbiAgWydMZXNzT3JFcXVhbCcsIFtiaW5hcnlPcHMubGVzc09yRXF1YWxdXSxcbiAgWydMb2cnLCBbdW5hcnlPcHMubG9nXV0sXG4gIFsnTWF0TXVsJywgW21hdE11bF1dLFxuICBbJ01hdE11bE5CaXRzJywgW21hdE11bE5CaXRzLCBwYXJzZU1hdE11bE5CaXRzQXR0cmlidXRlc11dLFxuICAvLyBUT0RPOiBzdXBwb3J0IG5ldyBhdHRyaWJ1dGVzIGZvciBNYXhQb29sLTggYW5kIE1heFBvb2wtMTBcbiAgWydNYXhQb29sJywgW3Bvb2wubWF4UG9vbCwgcG9vbC5wYXJzZU1heFBvb2xBdHRyaWJ1dGVzXV0sXG4gIFsnTXVsJywgW2JpbmFyeU9wcy5tdWxdXSxcbiAgWydNdWx0aUhlYWRBdHRlbnRpb24nLCBbbXVsdGlIZWFkQXR0ZW50aW9uLCBwYXJzZU11bHRpSGVhZEF0dGVudGlvbkF0dHJpYnV0ZXNdXSxcbiAgWydOZWcnLCBbdW5hcnlPcHMubmVnXV0sXG4gIFsnTm90JywgW3VuYXJ5T3BzLm5vdF1dLFxuICBbJ1BhZCcsIFtwYWRdXSxcbiAgWydQb3cnLCBbYmluYXJ5T3BzLnBvd11dLFxuICBbJ1F1aWNrR2VsdScsIFt1bmFyeU9wcy5xdWlja2dlbHUsIHVuYXJ5T3BzLnBhcnNlQWxwaGFBdHRyaWJ1dGVzXV0sXG4gIFsnUmFuZ2UnLCBbcmFuZ2VdXSxcbiAgWydSZWNpcHJvY2FsJywgW3VuYXJ5T3BzLnJlY2lwcm9jYWxdXSxcbiAgWydSZWR1Y2VNaW4nLCBbcmVkdWNlTWluXV0sXG4gIFsnUmVkdWNlTWVhbicsIFtyZWR1Y2VNZWFuXV0sXG4gIFsnUmVkdWNlTWF4JywgW3JlZHVjZU1heF1dLFxuICBbJ1JlZHVjZVN1bScsIFtyZWR1Y2VTdW1dXSxcbiAgWydSZWR1Y2VQcm9kJywgW3JlZHVjZVByb2RdXSxcbiAgWydSZWR1Y2VMMScsIFtyZWR1Y2VMMV1dLFxuICBbJ1JlZHVjZUwyJywgW3JlZHVjZUwyXV0sXG4gIFsnUmVkdWNlTG9nU3VtJywgW3JlZHVjZUxvZ1N1bV1dLFxuICBbJ1JlZHVjZUxvZ1N1bUV4cCcsIFtyZWR1Y2VMb2dTdW1FeHBdXSxcbiAgWydSZWR1Y2VTdW1TcXVhcmUnLCBbcmVkdWNlU3VtU3F1YXJlXV0sXG4gIFsnUmVsdScsIFt1bmFyeU9wcy5yZWx1XV0sXG4gIFsnUmVzaXplJywgW3Jlc2l6ZSwgcGFyc2VSZXNpemVBdHRyaWJ1dGVzXV0sXG4gIFsnUm90YXJ5RW1iZWRkaW5nJywgW3JvdGFyeUVtYmVkZGluZ11dLFxuICBbJ1NjYXR0ZXJORCcsIFtzY2F0dGVyTkQsIHBhcnNlU2NhdHRlck5EQXR0cmlidXRlc11dLFxuICBbJ1NpZ21vaWQnLCBbdW5hcnlPcHMuc2lnbW9pZF1dLFxuICBbJ1NpbicsIFt1bmFyeU9wcy5zaW5dXSxcbiAgWydTaW5oJywgW3VuYXJ5T3BzLnNpbmhdXSxcbiAgWydTbGljZScsIFtzbGljZSwgcGFyc2VTbGljZUF0dHJpYnV0ZXNdXSxcbiAgWydTa2lwTGF5ZXJOb3JtYWxpemF0aW9uJywgW3NraXBMYXllck5vcm1dXSxcbiAgWydTcGxpdCcsIFtzcGxpdCwgcGFyc2VTcGxpdEF0dHJpYnV0ZXNdXSxcbiAgWydTcXJ0JywgW3VuYXJ5T3BzLnNxcnRdXSxcbiAgWydTb2Z0bWF4JywgW3NvZnRtYXgsIHBhcnNlU29mdG1heEF0dHJpYnV0ZXNdXSxcbiAgWydTdWInLCBbYmluYXJ5T3BzLnN1Yl1dLFxuICBbJ1RhbicsIFt1bmFyeU9wcy50YW5dXSxcbiAgWydUYW5oJywgW3VuYXJ5T3BzLnRhbmhdXSxcbiAgWydUaHJlc2hvbGRlZFJlbHUnLCBbdW5hcnlPcHMudGhyZXNob2xkZWRSZWx1LCB1bmFyeU9wcy5wYXJzZUFscGhhQXR0cmlidXRlc11dLFxuICBbJ1RpbGUnLCBbdGlsZV1dLFxuICBbJ1RyYW5zcG9zZScsIFt0cmFuc3Bvc2UsIHBhcnNlVHJhbnNwb3NlQXR0cmlidXRlc11dLFxuICBbJ1doZXJlJywgW3doZXJlXV0sXG5dKTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVFJBQ0VfRlVOQ19CRUdJTiwgVFJBQ0VfRlVOQ19FTkQgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBXZWJHcHVCYWNrZW5kIH0gZnJvbSAnLi4vYmFja2VuZC13ZWJncHUnO1xuaW1wb3J0IHsgTE9HX0RFQlVHIH0gZnJvbSAnLi4vbG9nJztcblxuaW1wb3J0IHsgY3JlYXRlU2hhZGVySGVscGVyIH0gZnJvbSAnLi9vcHMvY29tbW9uJztcbmltcG9ydCB7IEFydGlmYWN0LCBHcHVEYXRhLCBQcm9ncmFtSW5mbyB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIFByb2dyYW1NYW5hZ2VyIGlzIHRoZSBtYWluIGNsYXNzIGJlaGluZCBydW5uaW5nIGNvbXB1dGF0aW9uc1xuICogSXQgYnVpbGRzIFByb2dyYW1JbmZvJ3MgaW50byBBcnRpZmFjdHNcbiAqIEl0IGNvbXBpbGVzIGdpdmVuIFByb2dyYW1JbmZvJ3MgaW50byBXZWJHTCBQcm9yYW1zIChjYWNoZWQgYXMgQXJ0aWZhY3RzKVxuICogVXNlcyB0aGUgYXJ0aWZhY3QgdG8gcnVuIHRoZSBjb21wdXRhdGlvbiBieSBjYWxsaW5nIERyYXcgb25cbiAqIHRoZSBXZWJHTCBkcmF3aW5nIGJ1ZmZlclxuICogUHJvZ3JhbU1hbmFnZXIgYXV0b21hdGljYWxseSBtYXBzIChiaW5kcykgaW5wdXQgdmFyaWFibGVzIHRvIHRoZWlyXG4gKiBjb3JyZXNwb25kaW5nIExvY2F0aW9uJ3MgaW4gdGhlIGJpbmFyeSBwcm9ncmFtXG4gKi9cbmV4cG9ydCBjbGFzcyBQcm9ncmFtTWFuYWdlciB7XG4gIHJlcG86IE1hcDx1bmtub3duLCBBcnRpZmFjdD47IC8vIHRoaXMgc2hvdWxkIGJlIHBlci1zZXNzaW9uIG9iamVjdFxuICBhdHRyaWJ1dGVzQm91bmQ6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBiYWNrZW5kOiBXZWJHcHVCYWNrZW5kKSB7XG4gICAgdGhpcy5yZXBvID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuYXR0cmlidXRlc0JvdW5kID0gZmFsc2U7XG4gIH1cbiAgZ2V0QXJ0aWZhY3Qoa2V5OiB1bmtub3duKTogQXJ0aWZhY3QgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnJlcG8uZ2V0KGtleSk7XG4gIH1cbiAgc2V0QXJ0aWZhY3Qoa2V5OiB1bmtub3duLCBhcnRpZmFjdDogQXJ0aWZhY3QpOiB2b2lkIHtcbiAgICB0aGlzLnJlcG8uc2V0KGtleSwgYXJ0aWZhY3QpO1xuICB9XG4gIHJ1bihcbiAgICBidWlsZEFydGlmYWN0OiBBcnRpZmFjdCxcbiAgICBpbnB1dHM6IEdwdURhdGFbXSxcbiAgICBvdXRwdXRzOiBHcHVEYXRhW10sXG4gICAgZGlzcGF0Y2hHcm91cDogW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICAgIHVuaWZvcm1CdWZmZXJCaW5kaW5nOiBHUFVCaW5kaW5nUmVzb3VyY2UgfCB1bmRlZmluZWQsXG4gICk6IHZvaWQge1xuICAgIFRSQUNFX0ZVTkNfQkVHSU4oYnVpbGRBcnRpZmFjdC5wcm9ncmFtSW5mby5uYW1lKTtcbiAgICBjb25zdCBkZXZpY2UgPSB0aGlzLmJhY2tlbmQuZGV2aWNlO1xuICAgIGNvbnN0IGNvbXB1dGVQYXNzRW5jb2RlciA9IHRoaXMuYmFja2VuZC5nZXRDb21wdXRlUGFzc0VuY29kZXIoKTtcbiAgICB0aGlzLmJhY2tlbmQud3JpdGVUaW1lc3RhbXAodGhpcy5iYWNrZW5kLnBlbmRpbmdEaXNwYXRjaE51bWJlciAqIDIpO1xuICAgIGNvbnN0IGVudHJpZXMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IGlucHV0IG9mIGlucHV0cykge1xuICAgICAgZW50cmllcy5wdXNoKHsgYmluZGluZzogZW50cmllcy5sZW5ndGgsIHJlc291cmNlOiB7IGJ1ZmZlcjogaW5wdXQuYnVmZmVyIH0gfSk7XG4gICAgfVxuICAgIGZvciAoY29uc3Qgb3V0cHV0IG9mIG91dHB1dHMpIHtcbiAgICAgIGVudHJpZXMucHVzaCh7IGJpbmRpbmc6IGVudHJpZXMubGVuZ3RoLCByZXNvdXJjZTogeyBidWZmZXI6IG91dHB1dC5idWZmZXIgfSB9KTtcbiAgICB9XG4gICAgaWYgKHVuaWZvcm1CdWZmZXJCaW5kaW5nKSB7XG4gICAgICBlbnRyaWVzLnB1c2goeyBiaW5kaW5nOiBlbnRyaWVzLmxlbmd0aCwgcmVzb3VyY2U6IHVuaWZvcm1CdWZmZXJCaW5kaW5nIH0pO1xuICAgIH1cbiAgICBjb25zdCBiaW5kR3JvdXAgPSBkZXZpY2UuY3JlYXRlQmluZEdyb3VwKHtcbiAgICAgIGxheW91dDogYnVpbGRBcnRpZmFjdC5jb21wdXRlUGlwZWxpbmUuZ2V0QmluZEdyb3VwTGF5b3V0KDApLFxuICAgICAgZW50cmllcyxcbiAgICAgIGxhYmVsOiBidWlsZEFydGlmYWN0LnByb2dyYW1JbmZvLm5hbWUsXG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5iYWNrZW5kLnNlc3Npb25TdGF0dXMgPT09ICdjYXB0dXJpbmcnKSB7XG4gICAgICBjb25zdCBjb21tYW5kSW5mbyA9IHtcbiAgICAgICAga2VybmVsSWQ6IHRoaXMuYmFja2VuZC5jdXJyZW50S2VybmVsSWQhLFxuICAgICAgICBjb21wdXRlUGlwZWxpbmU6IGJ1aWxkQXJ0aWZhY3QuY29tcHV0ZVBpcGVsaW5lLFxuICAgICAgICBiaW5kR3JvdXAsXG4gICAgICAgIGRpc3BhdGNoR3JvdXAsXG4gICAgICB9O1xuICAgICAgY29uc3Qgc2Vzc2lvbkNvbW1hbmRMaXN0ID0gdGhpcy5iYWNrZW5kLmNhcHR1cmVkQ29tbWFuZExpc3QuZ2V0KHRoaXMuYmFja2VuZC5jdXJyZW50U2Vzc2lvbklkISk7XG4gICAgICBzZXNzaW9uQ29tbWFuZExpc3QhLnB1c2goY29tbWFuZEluZm8pO1xuICAgIH1cblxuICAgIGNvbXB1dGVQYXNzRW5jb2Rlci5zZXRQaXBlbGluZShidWlsZEFydGlmYWN0LmNvbXB1dGVQaXBlbGluZSk7XG4gICAgY29tcHV0ZVBhc3NFbmNvZGVyLnNldEJpbmRHcm91cCgwLCBiaW5kR3JvdXApO1xuICAgIGNvbXB1dGVQYXNzRW5jb2Rlci5kaXNwYXRjaFdvcmtncm91cHMoLi4uZGlzcGF0Y2hHcm91cCk7XG4gICAgdGhpcy5iYWNrZW5kLndyaXRlVGltZXN0YW1wKHRoaXMuYmFja2VuZC5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgKiAyICsgMSk7XG4gICAgdGhpcy5iYWNrZW5kLnBlbmRpbmdEaXNwYXRjaE51bWJlcisrO1xuXG4gICAgaWYgKFxuICAgICAgdGhpcy5iYWNrZW5kLnBlbmRpbmdEaXNwYXRjaE51bWJlciA+PSB0aGlzLmJhY2tlbmQubWF4RGlzcGF0Y2hOdW1iZXIgfHxcbiAgICAgIHRoaXMuYmFja2VuZC5xdWVyeVR5cGUgPT09ICdhdC1wYXNzZXMnXG4gICAgKSB7XG4gICAgICB0aGlzLmJhY2tlbmQuZW5kQ29tcHV0ZVBhc3MoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuYmFja2VuZC5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgPj0gdGhpcy5iYWNrZW5kLm1heERpc3BhdGNoTnVtYmVyKSB7XG4gICAgICB0aGlzLmJhY2tlbmQuZmx1c2goKTtcbiAgICB9XG4gICAgVFJBQ0VfRlVOQ19FTkQoYnVpbGRBcnRpZmFjdC5wcm9ncmFtSW5mby5uYW1lKTtcbiAgfVxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIC8vIHRoaXMucmVwby5mb3JFYWNoKGEgPT4gdGhpcy5nbENvbnRleHQuZGVsZXRlUHJvZ3JhbShhLnByb2dyYW0pKTtcbiAgfVxuICBidWlsZChwcm9ncmFtSW5mbzogUHJvZ3JhbUluZm8sIG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwU2l6ZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdKTogQXJ0aWZhY3Qge1xuICAgIFRSQUNFX0ZVTkNfQkVHSU4ocHJvZ3JhbUluZm8ubmFtZSk7XG4gICAgY29uc3QgZGV2aWNlID0gdGhpcy5iYWNrZW5kLmRldmljZTtcbiAgICBjb25zdCBlbmFibGVEaXJlY3RpdmVzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgLy8gRW5hYmxlIFdHU0wgZXh0ZW5zaW9ucyBiYXNlZCBvbiBhdmFpbGFibGUgV2ViR1BVIGZlYXR1cmVzXG4gICAgY29uc3QgZXh0ZW5zaW9uc0luZm86IEFycmF5PHsgZmVhdHVyZTogR1BVRmVhdHVyZU5hbWU7IGV4dGVuc2lvbjogc3RyaW5nIH0+ID0gW1xuICAgICAgeyBmZWF0dXJlOiAnc2hhZGVyLWYxNicsIGV4dGVuc2lvbjogJ2YxNicgfSxcbiAgICAgIHsgZmVhdHVyZTogJ3N1Ymdyb3VwcycgYXMgR1BVRmVhdHVyZU5hbWUsIGV4dGVuc2lvbjogJ3N1Ymdyb3VwcycgfSxcbiAgICBdO1xuICAgIGV4dGVuc2lvbnNJbmZvLmZvckVhY2goKGluZm8pID0+IHtcbiAgICAgIGlmIChkZXZpY2UuZmVhdHVyZXMuaGFzKGluZm8uZmVhdHVyZSkpIHtcbiAgICAgICAgZW5hYmxlRGlyZWN0aXZlcy5wdXNoKGBlbmFibGUgJHtpbmZvLmV4dGVuc2lvbn07YCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCBzaGFkZXJIZWxwZXIgPSBjcmVhdGVTaGFkZXJIZWxwZXIobm9ybWFsaXplZERpc3BhdGNoR3JvdXBTaXplLCB0aGlzLmJhY2tlbmQuZGV2aWNlLmxpbWl0cyk7XG4gICAgY29uc3QgdXNlckNvZGUgPSBwcm9ncmFtSW5mby5nZXRTaGFkZXJTb3VyY2Uoc2hhZGVySGVscGVyKTtcbiAgICBjb25zdCBjb2RlID0gYCR7ZW5hYmxlRGlyZWN0aXZlcy5qb2luKCdcXG4nKX1cXG4ke3NoYWRlckhlbHBlci5hZGRpdGlvbmFsSW1wbGVtZW50YXRpb25zfVxcbiR7dXNlckNvZGV9YDtcbiAgICBjb25zdCBzaGFkZXJNb2R1bGUgPSBkZXZpY2UuY3JlYXRlU2hhZGVyTW9kdWxlKHsgY29kZSwgbGFiZWw6IHByb2dyYW1JbmZvLm5hbWUgfSk7XG4gICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJHUFVdICR7cHJvZ3JhbUluZm8ubmFtZX0gc2hhZGVyIGNvZGU6ICR7Y29kZX1gKTtcblxuICAgIGNvbnN0IGNvbXB1dGVQaXBlbGluZSA9IGRldmljZS5jcmVhdGVDb21wdXRlUGlwZWxpbmUoe1xuICAgICAgY29tcHV0ZTogeyBtb2R1bGU6IHNoYWRlck1vZHVsZSwgZW50cnlQb2ludDogJ21haW4nIH0sXG4gICAgICBsYXlvdXQ6ICdhdXRvJyxcbiAgICAgIGxhYmVsOiBwcm9ncmFtSW5mby5uYW1lLFxuICAgIH0pO1xuXG4gICAgVFJBQ0VfRlVOQ19FTkQocHJvZ3JhbUluZm8ubmFtZSk7XG4gICAgcmV0dXJuIHsgcHJvZ3JhbUluZm8sIGNvbXB1dGVQaXBlbGluZSwgdW5pZm9ybVZhcmlhYmxlc0luZm86IHNoYWRlckhlbHBlci52YXJpYWJsZXNJbmZvIH07XG4gIH1cblxuICBub3JtYWxpemVEaXNwYXRjaEdyb3VwU2l6ZShcbiAgICBkaXNwYXRjaEdyb3VwOiBSZXR1cm5UeXBlPFByb2dyYW1JbmZvWydnZXRSdW5EYXRhJ10+WydkaXNwYXRjaEdyb3VwJ10sXG4gICk6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSB7XG4gICAgY29uc3QgeCA9IHR5cGVvZiBkaXNwYXRjaEdyb3VwID09PSAnbnVtYmVyJyA/IGRpc3BhdGNoR3JvdXAgOiBkaXNwYXRjaEdyb3VwLng7XG4gICAgY29uc3QgeSA9IHR5cGVvZiBkaXNwYXRjaEdyb3VwID09PSAnbnVtYmVyJyA/IDEgOiBkaXNwYXRjaEdyb3VwLnkgfHwgMTtcbiAgICBjb25zdCB6ID0gdHlwZW9mIGRpc3BhdGNoR3JvdXAgPT09ICdudW1iZXInID8gMSA6IGRpc3BhdGNoR3JvdXAueiB8fCAxO1xuICAgIGNvbnN0IGxpbWl0UGVyRGltZW5zaW9uID0gdGhpcy5iYWNrZW5kLmRldmljZS5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cHNQZXJEaW1lbnNpb247XG4gICAgaWYgKHggPD0gbGltaXRQZXJEaW1lbnNpb24gJiYgeSA8PSBsaW1pdFBlckRpbWVuc2lvbiAmJiB6IDw9IGxpbWl0UGVyRGltZW5zaW9uKSB7XG4gICAgICByZXR1cm4gW3gsIHksIHpdO1xuICAgIH1cbiAgICBjb25zdCBzaXplID0geCAqIHkgKiB6O1xuICAgIGxldCBkaXNwYXRjaEF2ZXJhZ2UgPSBNYXRoLmNlaWwoTWF0aC5zcXJ0KHNpemUpKTtcbiAgICBpZiAoZGlzcGF0Y2hBdmVyYWdlID4gbGltaXRQZXJEaW1lbnNpb24pIHtcbiAgICAgIGRpc3BhdGNoQXZlcmFnZSA9IE1hdGguY2VpbChNYXRoLmNicnQoc2l6ZSkpO1xuICAgICAgaWYgKGRpc3BhdGNoQXZlcmFnZSA+IGxpbWl0UGVyRGltZW5zaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVG90YWwgZGlzcGF0Y2ggc2l6ZSBleGNlZWRzIFdlYkdQVSBtYXhpbXVtLicpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFtkaXNwYXRjaEF2ZXJhZ2UsIGRpc3BhdGNoQXZlcmFnZSwgZGlzcGF0Y2hBdmVyYWdlXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFtkaXNwYXRjaEF2ZXJhZ2UsIGRpc3BhdGNoQXZlcmFnZSwgMV07XG4gICAgfVxuICB9XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IEVudiwgVGVuc29yLCBUUkFDRSwgVFJBQ0VfRlVOQ19CRUdJTiwgVFJBQ0VfRlVOQ19FTkQgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBEYXRhVHlwZSwgdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcgfSBmcm9tICcuLi93YXNtLWNvbW1vbic7XG5cbmltcG9ydCB7IGNvbmZpZ3VyZUxvZ2dlciwgTE9HX0RFQlVHIH0gZnJvbSAnLi9sb2cnO1xuaW1wb3J0IHsgY3JlYXRlVmlldywgVGVuc29yVmlldyB9IGZyb20gJy4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgY3JlYXRlR3B1RGF0YU1hbmFnZXIsIGRvd25sb2FkR3B1RGF0YSwgR3B1RGF0YU1hbmFnZXIgfSBmcm9tICcuL3dlYmdwdS9ncHUtZGF0YS1tYW5hZ2VyJztcbmltcG9ydCB7IFJ1bkZ1bmN0aW9uLCBXRUJHUFVfT1BfUkVTT0xWRV9SVUxFUyB9IGZyb20gJy4vd2ViZ3B1L29wLXJlc29sdmUtcnVsZXMnO1xuaW1wb3J0IHsgUHJvZ3JhbU1hbmFnZXIgfSBmcm9tICcuL3dlYmdwdS9wcm9ncmFtLW1hbmFnZXInO1xuaW1wb3J0IHtcbiAgQWRhcHRlckluZm8sXG4gIENvbXB1dGVDb250ZXh0LFxuICBHcHVBcmNoaXRlY3R1cmUsXG4gIEdwdURhdGEsXG4gIEdwdVZlbmRvcixcbiAgUHJvZ3JhbUluZm8sXG4gIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LFxuICBTZXNzaW9uU3RhdGUsXG4gIFRpbWVzdGFtcFF1ZXJ5LFxufSBmcm9tICcuL3dlYmdwdS90eXBlcyc7XG5cbmludGVyZmFjZSBDb21tYW5kSW5mbyB7XG4gIHJlYWRvbmx5IGtlcm5lbElkOiBudW1iZXI7XG4gIHJlYWRvbmx5IGNvbXB1dGVQaXBlbGluZTogR1BVQ29tcHV0ZVBpcGVsaW5lO1xuICByZWFkb25seSBiaW5kR3JvdXA6IEdQVUJpbmRHcm91cDtcbiAgcmVhZG9ubHkgZGlzcGF0Y2hHcm91cDogW251bWJlciwgbnVtYmVyLCBudW1iZXJdO1xufVxuXG5pbnRlcmZhY2UgS2VybmVsSW5mbyB7XG4gIHJlYWRvbmx5IGtlcm5lbFR5cGU6IHN0cmluZztcbiAgcmVhZG9ubHkga2VybmVsTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBrZXJuZWxFbnRyeTogUnVuRnVuY3Rpb247XG4gIHJlYWRvbmx5IGF0dHJpYnV0ZXM6IFsoKGF0dHJpYnV0ZTogdW5rbm93bikgPT4gdW5rbm93bikgfCB1bmRlZmluZWQsIHVua25vd25dO1xufVxuXG5pbnRlcmZhY2UgUGVuZGluZ0tlcm5lbEluZm8ge1xuICByZWFkb25seSBrZXJuZWxJZDogbnVtYmVyO1xuICByZWFkb25seSBwcm9ncmFtTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBpbnB1dFRlbnNvclZpZXdzOiByZWFkb25seSBUZW5zb3JWaWV3W107XG4gIHJlYWRvbmx5IG91dHB1dFRlbnNvclZpZXdzOiByZWFkb25seSBUZW5zb3JWaWV3W107XG59XG5cbmNvbnN0IGdldFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5S2V5ID0gKFxuICBpbnB1dFRlbnNvcnM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgaW5wdXREZXBlbmRlbmNpZXM6IHJlYWRvbmx5IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10sXG4pOiBzdHJpbmcgPT4ge1xuICBpZiAoaW5wdXREZXBlbmRlbmNpZXMubGVuZ3RoICE9PSBpbnB1dFRlbnNvcnMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYGlucHV0RGVwZW5kZW5jaWVzIGxlbmd0aCAke2lucHV0RGVwZW5kZW5jaWVzLmxlbmd0aH0gaXMgbm90IGVxdWFsIHRvIGlucHV0VGVuc29ycyBsZW5ndGggJHtcbiAgICAgICAgaW5wdXRUZW5zb3JzLmxlbmd0aFxuICAgICAgfS5gLFxuICAgICk7XG4gIH1cblxuICBjb25zdCBpbnB1dEluZm9zOiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0VGVuc29ycy5sZW5ndGg7ICsraSkge1xuICAgIGNvbnN0IHR5cGUgPSBpbnB1dFRlbnNvcnNbaV0uZGF0YVR5cGU7XG4gICAgc3dpdGNoIChpbnB1dERlcGVuZGVuY2llc1tpXSkge1xuICAgICAgY2FzZSAnbm9uZSc6IHtcbiAgICAgICAgaW5wdXRJbmZvcy5wdXNoKCcnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICd0eXBlJzoge1xuICAgICAgICBpbnB1dEluZm9zLnB1c2goYCR7dHlwZX1gKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdyYW5rJzoge1xuICAgICAgICBjb25zdCByYW5rID0gaW5wdXRUZW5zb3JzW2ldLmRpbXMubGVuZ3RoO1xuICAgICAgICBpbnB1dEluZm9zLnB1c2goYCR7dHlwZX07JHtyYW5rfWApO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2RpbXMnOiB7XG4gICAgICAgIGNvbnN0IGRpbXMgPSBpbnB1dFRlbnNvcnNbaV0uZGltcy5qb2luKCcsJyk7XG4gICAgICAgIGlucHV0SW5mb3MucHVzaChgJHt0eXBlfTske2RpbXN9YCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBpbnB1dCBkZXBlbmRlbmN5OiAke2lucHV0RGVwZW5kZW5jaWVzW2ldfWApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBpbnB1dEluZm9zLmpvaW4oJ3wnKTtcbn07XG5cbi8qKlxuICogZ2V0IGEgdW5pcXVlIGtleSByZXByZXNlbnRpbmcgdGhlIHByb2dyYW0gZnJvbSB0aGUgcHJvZ3JhbSBpbmZvLCBpbnB1dCBzaGFwZXMgYW5kIHR5cGVzLlxuICpcbiAqIEByZXR1cm5zIGEgdW5pcXVlIGtleSBpcyBhIHNob3J0ZXIgc3RyaW5nIHRoYW4gdGhlIHNoYWRlciBzb3VyY2UsIHdoaWNoIGNvbnRhaW5zIGFsbCB0aGUgaW5mb3JtYXRpb24gdG8gaWRlbnRpZnkgYVxuICogcHJvZ3JhbS4gaWYgdGhlIGtleSBpcyB0aGUgc2FtZSwgdGhlIHByb2dyYW0gc2hhZGVyIHNvdXJjZSBzaG91bGQgYmUgdGhlIHNhbWUsIHNvIHdlIGNhbiByZXVzZSB0aGUgcHJvZ3JhbS5cbiAqXG4gKi9cbmNvbnN0IGdldFByb2dyYW1JbmZvVW5pcXVlS2V5ID0gKFxuICBwcm9ncmFtSW5mbzogUHJvZ3JhbUluZm8sXG4gIGlucHV0VGVuc29yczogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBpczFEaW1lbnNpb25EaXNwYXRjaDogYm9vbGVhbixcbik6IHN0cmluZyA9PiB7XG4gIC8vIGZpbmFsIGtleSBmb3JtYXQ6XG4gIC8vIDxQUk9HUkFNX05BTUU+WzxQUk9HUkFNX0NVU1RPTV9DQUNIRV9ISU5UPl06aXMxRGltZW5zaW9uRGlzcGF0Y2g6PElOUFVUU19JTkZPXzA+fDxJTlBVVFNfSU5GT18xPnwuLi5cbiAgbGV0IGtleSA9IHByb2dyYW1JbmZvLm5hbWU7XG4gIGlmIChwcm9ncmFtSW5mby5zaGFkZXJDYWNoZT8uaGludCkge1xuICAgIGtleSArPSAnWycgKyBwcm9ncmFtSW5mby5zaGFkZXJDYWNoZS5oaW50ICsgJ10nO1xuICB9XG4gIGtleSArPVxuICAgICc6JyArXG4gICAgaXMxRGltZW5zaW9uRGlzcGF0Y2ggK1xuICAgIGA6JHtnZXRQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeUtleShcbiAgICAgIGlucHV0VGVuc29ycyxcbiAgICAgIHByb2dyYW1JbmZvLnNoYWRlckNhY2hlPy5pbnB1dERlcGVuZGVuY2llcyA/P1xuICAgICAgICBuZXcgQXJyYXk8UHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3k+KGlucHV0VGVuc29ycy5sZW5ndGgpLmZpbGwoJ2RpbXMnKSxcbiAgICApfWA7XG4gIHJldHVybiBrZXk7XG59O1xuXG5jbGFzcyBBZGFwdGVySW5mb0ltcGwgaW1wbGVtZW50cyBBZGFwdGVySW5mbyB7XG4gIHJlYWRvbmx5IGFyY2hpdGVjdHVyZT86IHN0cmluZztcbiAgcmVhZG9ubHkgdmVuZG9yPzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKGFkYXB0ZXJJbmZvOiBHUFVBZGFwdGVySW5mbykge1xuICAgIGlmIChhZGFwdGVySW5mbykge1xuICAgICAgdGhpcy5hcmNoaXRlY3R1cmUgPSBhZGFwdGVySW5mby5hcmNoaXRlY3R1cmU7XG4gICAgICB0aGlzLnZlbmRvciA9IGFkYXB0ZXJJbmZvLnZlbmRvcjtcbiAgICB9XG4gIH1cblxuICBpc0FyY2hpdGVjdHVyZShhcmNoaXRlY3R1cmU6IEdwdUFyY2hpdGVjdHVyZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmFyY2hpdGVjdHVyZSA9PT0gYXJjaGl0ZWN0dXJlO1xuICB9XG5cbiAgaXNWZW5kb3IodmVuZG9yOiBHcHVWZW5kb3IpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy52ZW5kb3IgPT09IHZlbmRvcjtcbiAgfVxufVxuXG4vKipcbiAqIHRoaXMgY2xhc3MgaXMgZGVzaWduZWQgdG8gc3RvcmUgc3RhdHVzIGFuZCBiZWluZyB1c2VkIGFzIGEgc2luZ2xldG9uIGZvciBKU0VQLiBJdCB3aWxsIGJlIHBhc3NlZCB0byBqc2VwSW5pdCgpIGFzXG4gKiB0aGUgZmlyc3QgcGFyYW1ldGVyIHNvIHRoYXQgaXQgaXMgc3RvcmVkIGZvciBmdXR1cmUgdXNlLlxuICovXG5leHBvcnQgY2xhc3MgV2ViR3B1QmFja2VuZCB7XG4gIGFkYXB0ZXJJbmZvOiBBZGFwdGVySW5mb0ltcGw7XG4gIGRldmljZTogR1BVRGV2aWNlO1xuICAvKipcbiAgICogYW4gaW5zdGFuY2Ugb2YgR3B1RGF0YU1hbmFnZXIgdG8gbWFuYWdlIGEgR3B1RGF0YUlkIC0+IEdwdUJ1ZmZlciBtYXBwaW5nXG4gICAqL1xuICBncHVEYXRhTWFuYWdlcjogR3B1RGF0YU1hbmFnZXI7XG4gIC8qKlxuICAgKiBhbiBpbnN0YW5jZSBvZiBQcm9ncmFtTWFuYWdlciB0byBidWlsZCBhbmQgcnVuIFdlYkdQVSBjb21wdXRlIHNoYWRlciBwcm9ncmFtLCBhbmQgbWFuYWdlIGEgUHJvZ3JhbUtleSAtPiBQcm9ncmFtXG4gICAqIGFydGlmYWN0cyBtYXBwaW5nXG4gICAqL1xuICBwcm9ncmFtTWFuYWdlcjogUHJvZ3JhbU1hbmFnZXI7XG5cbiAgLyoqXG4gICAqIHJlcHJlc2VudGluZyB0aGUgc2Vzc2lvbiBJRCBvZiB3aGljaCBpcyBjdXJyZW50bHkgYmVpbmcgcnVuLlxuICAgKiBgbnVsbGAgbWVhbnMgbm8gc2Vzc2lvbiBpcyBiZWluZyBydW4uXG4gICAqIG9ubHkgdmFsaWQgd2hlbiBzZXNzaW9uLnJ1biBpcyBleGVjdXRlZC5cbiAgICovXG4gIGN1cnJlbnRTZXNzaW9uSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gIC8qKlxuICAgKiByZXByZXNlbnRpbmcgdGhlIGtlcm5lbCBJRCBvZiB3aGljaCBpcyBjdXJyZW50bHkgYmVpbmcgY29tcHV0ZWQgKENQVSBjb2RlIHBlcnNwZWN0aXZlKS5cbiAgICogYG51bGxgIG1lYW5zIG5vIGtlcm5lbCBpcyBiZWluZyBjb21wdXRlZC5cbiAgICogb25seSBvbmUga2VybmVsIGNhbiBiZSBjb21wdXRlZCBhdCBhIG1vbWVudC5cbiAgICovXG4gIGN1cnJlbnRLZXJuZWxJZDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gIC8qKlxuICAgKiBhIGxpc3Qgb2YgdGVtcG9yYXJ5IEdQVSBkYXRhIGZvciB0aGUgY3VycmVudCBrZXJuZWwuIHNob3VsZCByZWxlYXNlIHdoZW4gdGhlIGtlcm5lbCBkb25lIGNvbXB1dGF0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSB0ZW1wb3JhcnlEYXRhOiBHcHVEYXRhW107XG4gIC8qKlxuICAgKiBhIEtlcm5lbElEIC0+IGEgR1BVIGRhdGEgbGlzdCwgd2hpY2ggc3RvcmVzIHBlcnNpc3RlbnQgR1BVIGRhdGEgb3duZWQgYnkgdGhlIHNwZWNpZmljIGtlcm5lbC5cbiAgICovXG4gIHByaXZhdGUga2VybmVsUGVyc2lzdGVudERhdGE6IE1hcDxudW1iZXIsIEdwdURhdGFbXT47XG4gIC8qKlxuICAgKiBhIEtlcm5lbElEIC0+IGEgY3VzdG9tIGRhdGEsIHdoaWNoIHN0b3JlcyBjdXN0b20gZGF0YSBvd25lZCBieSB0aGUgc3BlY2lmaWMga2VybmVsLlxuICAgKi9cbiAgcHJpdmF0ZSBrZXJuZWxDdXN0b21EYXRhOiBNYXA8bnVtYmVyLCB7IFtrZXk6IHN0cmluZ106IHVua25vd24gfT47XG4gIC8qKlxuICAgKiBnZXQgdGhlIGN1c3RvbSBkYXRhIG9mIHRoZSBjdXJyZW50IGtlcm5lbFxuICAgKi9cbiAgZ2V0IGN1cnJlbnRLZXJuZWxDdXN0b21EYXRhKCk6IHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9IHtcbiAgICBpZiAodGhpcy5jdXJyZW50S2VybmVsSWQgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY3VycmVudEtlcm5lbEN1c3RvbURhdGEoKTogY3VycmVudEtlcm5lbElkIGlzIG51bGwuIChzaG91bGQgbm90IGhhcHBlbiknKTtcbiAgICB9XG5cbiAgICBsZXQgZGF0YSA9IHRoaXMua2VybmVsQ3VzdG9tRGF0YS5nZXQodGhpcy5jdXJyZW50S2VybmVsSWQpO1xuICAgIGlmICghZGF0YSkge1xuICAgICAgZGF0YSA9IHt9O1xuICAgICAgdGhpcy5rZXJuZWxDdXN0b21EYXRhLnNldCh0aGlzLmN1cnJlbnRLZXJuZWxJZCwgZGF0YSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICAvLyBLZXJuZWxJRCAtPiBrZXJuZWxJbmZvIG1hcHBpbmdcbiAga2VybmVsczogTWFwPG51bWJlciwgS2VybmVsSW5mbz47XG4gIHByaXZhdGUgY29tbWFuZEVuY29kZXI6IEdQVUNvbW1hbmRFbmNvZGVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgY29tcHV0ZVBhc3NFbmNvZGVyOiBHUFVDb21wdXRlUGFzc0VuY29kZXIgfCBudWxsID0gbnVsbDtcbiAgbWF4RGlzcGF0Y2hOdW1iZXIgPSAxNjtcbiAgcGVuZGluZ0Rpc3BhdGNoTnVtYmVyID0gMDtcblxuICAvLyBpbmZvIG9mIGtlcm5lbHMgcGVuZGluZyBzdWJtaXNzaW9uIGZvciBhIHNpbmdsZSBiYXRjaFxuICBwcml2YXRlIHBlbmRpbmdLZXJuZWxzOiBQZW5kaW5nS2VybmVsSW5mb1tdID0gW107XG4gIC8vIHF1ZXJ5UmVhZEJ1ZmZlciAtPiBwZW5kaW5nS2VybmVscyBtYXBwaW5nIGZvciBhbGwgdGhlIGJhdGNoZXNcbiAgcHJpdmF0ZSBwZW5kaW5nUXVlcmllczogTWFwPEdQVUJ1ZmZlciwgUGVuZGluZ0tlcm5lbEluZm9bXT4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgcXVlcnlSZXNvbHZlQnVmZmVyPzogR1BVQnVmZmVyO1xuICBwcml2YXRlIHF1ZXJ5U2V0PzogR1BVUXVlcnlTZXQ7XG4gIHByaXZhdGUgcXVlcnlUaW1lQmFzZT86IGJpZ2ludDtcbiAgcXVlcnlUeXBlOiBUaW1lc3RhbXBRdWVyeTtcblxuICBlbnY6IEVudjtcbiAgc2Vzc2lvblN0YXR1czogU2Vzc2lvblN0YXRlID0gJ2RlZmF1bHQnO1xuICAvKipcbiAgICogYSBTZXNzaW9uSUQgLT4gQ29tbWFuZEluZm9bXSBtYXBwaW5nLiBJdCdzIHVzZWQgdG8gcmVjb3JkIGFsbCBHUFUgY29tbWFuZHMgZm9yIGNvcnJlc3BvbmRpbmcgc2Vzc2lvbi5cbiAgICovXG4gIGNhcHR1cmVkQ29tbWFuZExpc3Q6IE1hcDxudW1iZXIsIENvbW1hbmRJbmZvW10+ID0gbmV3IE1hcCgpO1xuXG4gIC8qKlxuICAgKiBhIFNlc3Npb25JRCAtPiBQZW5kaW5nS2VybmVsSW5mb1tdIG1hcHBpbmcgZm9yIHByb2ZpbGluZy5cbiAgICovXG4gIHByaXZhdGUgY2FwdHVyZWRQZW5kaW5nS2VybmVsczogTWFwPG51bWJlciwgUGVuZGluZ0tlcm5lbEluZm9bXT4gPSBuZXcgTWFwKCk7XG5cbiAgLyoqXG4gICAqIGEgU2Vzc2lvbklEIC0+IGEgTWFwIG9mIChJbnB1dE91dHB1dEluZGV4IC0+IFtJRCwgR1BVQnVmZmVyXSkgbWFwcGluZy5cbiAgICovXG4gIHNlc3Npb25FeHRlcm5hbERhdGFNYXBwaW5nOiBNYXA8bnVtYmVyLCBNYXA8bnVtYmVyLCBbbnVtYmVyLCBHUFVCdWZmZXJdPj4gPSBuZXcgTWFwKCk7XG5cbiAgYXN5bmMgaW5pdGlhbGl6ZShlbnY6IEVudiwgYWRhcHRlcjogR1BVQWRhcHRlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuZW52ID0gZW52O1xuICAgIGNvbnN0IHJlcXVpcmVkRmVhdHVyZXM6IEdQVUZlYXR1cmVOYW1lW10gPSBbXTtcbiAgICBjb25zdCBkZXZpY2VEZXNjcmlwdG9yOiBHUFVEZXZpY2VEZXNjcmlwdG9yID0ge1xuICAgICAgcmVxdWlyZWRMaW1pdHM6IHtcbiAgICAgICAgbWF4Q29tcHV0ZVdvcmtncm91cFN0b3JhZ2VTaXplOiBhZGFwdGVyLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3VwU3RvcmFnZVNpemUsXG4gICAgICAgIG1heENvbXB1dGVXb3JrZ3JvdXBzUGVyRGltZW5zaW9uOiBhZGFwdGVyLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3Vwc1BlckRpbWVuc2lvbixcbiAgICAgICAgbWF4U3RvcmFnZUJ1ZmZlckJpbmRpbmdTaXplOiBhZGFwdGVyLmxpbWl0cy5tYXhTdG9yYWdlQnVmZmVyQmluZGluZ1NpemUsXG4gICAgICAgIG1heEJ1ZmZlclNpemU6IGFkYXB0ZXIubGltaXRzLm1heEJ1ZmZlclNpemUsXG4gICAgICAgIG1heENvbXB1dGVJbnZvY2F0aW9uc1Blcldvcmtncm91cDogYWRhcHRlci5saW1pdHMubWF4Q29tcHV0ZUludm9jYXRpb25zUGVyV29ya2dyb3VwLFxuICAgICAgICBtYXhDb21wdXRlV29ya2dyb3VwU2l6ZVg6IGFkYXB0ZXIubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBTaXplWCxcbiAgICAgICAgbWF4Q29tcHV0ZVdvcmtncm91cFNpemVZOiBhZGFwdGVyLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3VwU2l6ZVksXG4gICAgICAgIG1heENvbXB1dGVXb3JrZ3JvdXBTaXplWjogYWRhcHRlci5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cFNpemVaLFxuICAgICAgfSxcbiAgICAgIHJlcXVpcmVkRmVhdHVyZXMsXG4gICAgfTtcblxuICAgIC8vIFRyeSByZXF1aXJpbmcgV2ViR1BVIGZlYXR1cmVzXG4gICAgY29uc3QgcmVxdWlyZUZlYXR1cmVJZkF2YWlsYWJsZSA9IChmZWF0dXJlOiBHUFVGZWF0dXJlTmFtZSkgPT5cbiAgICAgIGFkYXB0ZXIuZmVhdHVyZXMuaGFzKGZlYXR1cmUpICYmIHJlcXVpcmVkRmVhdHVyZXMucHVzaChmZWF0dXJlKSAmJiB0cnVlO1xuICAgIC8vIFRyeSBjaHJvbWl1bS1leHBlcmltZW50YWwtdGltZXN0YW1wLXF1ZXJ5LWluc2lkZS1wYXNzZXMgYW5kIGZhbGxiYWNrIHRvIHRpbWVzdGFtcC1xdWVyeVxuICAgIGlmICghcmVxdWlyZUZlYXR1cmVJZkF2YWlsYWJsZSgnY2hyb21pdW0tZXhwZXJpbWVudGFsLXRpbWVzdGFtcC1xdWVyeS1pbnNpZGUtcGFzc2VzJyBhcyBHUFVGZWF0dXJlTmFtZSkpIHtcbiAgICAgIHJlcXVpcmVGZWF0dXJlSWZBdmFpbGFibGUoJ3RpbWVzdGFtcC1xdWVyeScpO1xuICAgIH1cbiAgICByZXF1aXJlRmVhdHVyZUlmQXZhaWxhYmxlKCdzaGFkZXItZjE2Jyk7XG4gICAgLy8gVHJ5IHN1Ymdyb3Vwc1xuICAgIHJlcXVpcmVGZWF0dXJlSWZBdmFpbGFibGUoJ3N1Ymdyb3VwcycgYXMgR1BVRmVhdHVyZU5hbWUpO1xuXG4gICAgdGhpcy5kZXZpY2UgPSBhd2FpdCBhZGFwdGVyLnJlcXVlc3REZXZpY2UoZGV2aWNlRGVzY3JpcHRvcik7XG4gICAgdGhpcy5hZGFwdGVySW5mbyA9IG5ldyBBZGFwdGVySW5mb0ltcGwoYWRhcHRlci5pbmZvIHx8IChhd2FpdCBhZGFwdGVyLnJlcXVlc3RBZGFwdGVySW5mbygpKSk7XG4gICAgdGhpcy5ncHVEYXRhTWFuYWdlciA9IGNyZWF0ZUdwdURhdGFNYW5hZ2VyKHRoaXMpO1xuICAgIHRoaXMucHJvZ3JhbU1hbmFnZXIgPSBuZXcgUHJvZ3JhbU1hbmFnZXIodGhpcyk7XG4gICAgdGhpcy5rZXJuZWxzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMua2VybmVsUGVyc2lzdGVudERhdGEgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5rZXJuZWxDdXN0b21EYXRhID0gbmV3IE1hcCgpO1xuXG4gICAgLy8gc2V0IHVwIGZsYWdzIGZvciBsb2dnZXJcbiAgICBjb25maWd1cmVMb2dnZXIoZW52LmxvZ0xldmVsISwgISFlbnYuZGVidWcpO1xuXG4gICAgLy8gVE9ETzogc2V0IHVwIGZsYWdzXG5cbiAgICB0aGlzLmRldmljZS5vbnVuY2FwdHVyZWRlcnJvciA9IChldikgPT4ge1xuICAgICAgaWYgKGV2LmVycm9yIGluc3RhbmNlb2YgR1BVVmFsaWRhdGlvbkVycm9yKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYEFuIHVuY2F1Z2h0IFdlYkdQVSB2YWxpZGF0aW9uIGVycm9yIHdhcyByYWlzZWQ6ICR7ZXYuZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMuZW52LndlYmdwdSwgJ2RldmljZScsIHtcbiAgICAgIHZhbHVlOiB0aGlzLmRldmljZSxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLmVudi53ZWJncHUsICdhZGFwdGVyJywge1xuICAgICAgdmFsdWU6IGFkYXB0ZXIsXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICB9KTtcblxuICAgIC8vIGluaXQgcXVlcnlUeXBlLCB3aGljaCBpcyBuZWNlc3NhcnkgZm9yIEluZmVyZW5jZVNlc3Npb24uY3JlYXRlXG4gICAgdGhpcy5zZXRRdWVyeVR5cGUoKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgaWYgKHR5cGVvZiB0aGlzLnF1ZXJ5U2V0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5xdWVyeVNldC5kZXN0cm95KCk7XG4gICAgfVxuICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgZ2V0Q29tbWFuZEVuY29kZXIoKTogR1BVQ29tbWFuZEVuY29kZXIge1xuICAgIGlmICghdGhpcy5jb21tYW5kRW5jb2Rlcikge1xuICAgICAgdGhpcy5jb21tYW5kRW5jb2RlciA9IHRoaXMuZGV2aWNlLmNyZWF0ZUNvbW1hbmRFbmNvZGVyKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmNvbW1hbmRFbmNvZGVyO1xuICB9XG5cbiAgZ2V0Q29tcHV0ZVBhc3NFbmNvZGVyKCk6IEdQVUNvbXB1dGVQYXNzRW5jb2RlciB7XG4gICAgaWYgKCF0aGlzLmNvbXB1dGVQYXNzRW5jb2Rlcikge1xuICAgICAgY29uc3QgY29tbWFuZEVuY29kZXIgPSB0aGlzLmdldENvbW1hbmRFbmNvZGVyKCk7XG4gICAgICBjb25zdCBjb21wdXRlUGFzc0Rlc2NyaXB0b3I6IEdQVUNvbXB1dGVQYXNzRGVzY3JpcHRvciA9IHt9O1xuXG4gICAgICBpZiAodGhpcy5xdWVyeVR5cGUgPT09ICdhdC1wYXNzZXMnKSB7XG4gICAgICAgIGNvbXB1dGVQYXNzRGVzY3JpcHRvci50aW1lc3RhbXBXcml0ZXMgPSB7XG4gICAgICAgICAgcXVlcnlTZXQ6IHRoaXMucXVlcnlTZXQhLFxuICAgICAgICAgIGJlZ2lubmluZ09mUGFzc1dyaXRlSW5kZXg6IHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMixcbiAgICAgICAgICBlbmRPZlBhc3NXcml0ZUluZGV4OiB0aGlzLnBlbmRpbmdEaXNwYXRjaE51bWJlciAqIDIgKyAxLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICB0aGlzLmNvbXB1dGVQYXNzRW5jb2RlciA9IGNvbW1hbmRFbmNvZGVyLmJlZ2luQ29tcHV0ZVBhc3MoY29tcHV0ZVBhc3NEZXNjcmlwdG9yKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyO1xuICB9XG5cbiAgZW5kQ29tcHV0ZVBhc3MoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyKSB7XG4gICAgICB0aGlzLmNvbXB1dGVQYXNzRW5jb2Rlci5lbmQoKTtcbiAgICAgIHRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBmbHVzaCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY29tbWFuZEVuY29kZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBUUkFDRV9GVU5DX0JFR0lOKCk7XG5cbiAgICB0aGlzLmVuZENvbXB1dGVQYXNzKCk7XG4gICAgbGV0IHF1ZXJ5UmVhZEJ1ZmZlcjogR1BVQnVmZmVyO1xuICAgIGlmICh0aGlzLnF1ZXJ5VHlwZSAhPT0gJ25vbmUnKSB7XG4gICAgICB0aGlzLmNvbW1hbmRFbmNvZGVyLnJlc29sdmVRdWVyeVNldChcbiAgICAgICAgdGhpcy5xdWVyeVNldCEsXG4gICAgICAgIDAsXG4gICAgICAgIHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMixcbiAgICAgICAgdGhpcy5xdWVyeVJlc29sdmVCdWZmZXIhLFxuICAgICAgICAwLFxuICAgICAgKTtcblxuICAgICAgcXVlcnlSZWFkQnVmZmVyID0gdGhpcy5kZXZpY2UuY3JlYXRlQnVmZmVyKFxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgICAgICB7IHNpemU6IHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMiAqIDgsIHVzYWdlOiBHUFVCdWZmZXJVc2FnZS5NQVBfUkVBRCB8IEdQVUJ1ZmZlclVzYWdlLkNPUFlfRFNUIH0sXG4gICAgICApO1xuXG4gICAgICB0aGlzLnBlbmRpbmdRdWVyaWVzLnNldChxdWVyeVJlYWRCdWZmZXIsIHRoaXMucGVuZGluZ0tlcm5lbHMpO1xuICAgICAgdGhpcy5wZW5kaW5nS2VybmVscyA9IFtdO1xuICAgICAgdGhpcy5jb21tYW5kRW5jb2Rlci5jb3B5QnVmZmVyVG9CdWZmZXIoXG4gICAgICAgIHRoaXMucXVlcnlSZXNvbHZlQnVmZmVyISxcbiAgICAgICAgMCxcbiAgICAgICAgcXVlcnlSZWFkQnVmZmVyLFxuICAgICAgICAwLFxuICAgICAgICB0aGlzLnBlbmRpbmdEaXNwYXRjaE51bWJlciAqIDIgKiA4LFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmRldmljZS5xdWV1ZS5zdWJtaXQoW3RoaXMuY29tbWFuZEVuY29kZXIuZmluaXNoKCldKTtcbiAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLnJlZnJlc2hQZW5kaW5nQnVmZmVycygpO1xuICAgIHRoaXMuY29tbWFuZEVuY29kZXIgPSBudWxsO1xuICAgIHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyID0gMDtcblxuICAgIGlmICh0aGlzLnF1ZXJ5VHlwZSAhPT0gJ25vbmUnKSB7XG4gICAgICB2b2lkIHF1ZXJ5UmVhZEJ1ZmZlciEubWFwQXN5bmMoR1BVTWFwTW9kZS5SRUFEKS50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc3QgbWFwcGVkRGF0YSA9IG5ldyBCaWdVaW50NjRBcnJheShxdWVyeVJlYWRCdWZmZXIuZ2V0TWFwcGVkUmFuZ2UoKSk7XG4gICAgICAgIGNvbnN0IHBlbmRpbmdLZXJuZWxzID0gdGhpcy5wZW5kaW5nUXVlcmllcy5nZXQocXVlcnlSZWFkQnVmZmVyKSE7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWFwcGVkRGF0YS5sZW5ndGggLyAyOyBpKyspIHtcbiAgICAgICAgICBjb25zdCBwZW5kaW5nS2VybmVsSW5mbyA9IHBlbmRpbmdLZXJuZWxzW2ldO1xuICAgICAgICAgIGNvbnN0IGtlcm5lbElkID0gcGVuZGluZ0tlcm5lbEluZm8ua2VybmVsSWQ7XG4gICAgICAgICAgY29uc3Qga2VybmVsSW5mbyA9IHRoaXMua2VybmVscy5nZXQoa2VybmVsSWQpITtcbiAgICAgICAgICBjb25zdCBrZXJuZWxUeXBlID0ga2VybmVsSW5mby5rZXJuZWxUeXBlO1xuICAgICAgICAgIGNvbnN0IGtlcm5lbE5hbWUgPSBrZXJuZWxJbmZvLmtlcm5lbE5hbWU7XG4gICAgICAgICAgY29uc3QgcHJvZ3JhbU5hbWUgPSBwZW5kaW5nS2VybmVsSW5mby5wcm9ncmFtTmFtZTtcbiAgICAgICAgICBjb25zdCBpbnB1dFRlbnNvclZpZXdzID0gcGVuZGluZ0tlcm5lbEluZm8uaW5wdXRUZW5zb3JWaWV3cztcbiAgICAgICAgICBjb25zdCBvdXRwdXRUZW5zb3JWaWV3cyA9IHBlbmRpbmdLZXJuZWxJbmZvLm91dHB1dFRlbnNvclZpZXdzO1xuICAgICAgICAgIGNvbnN0IHN0YXJ0VGltZVU2NCA9IG1hcHBlZERhdGFbaSAqIDJdO1xuICAgICAgICAgIGNvbnN0IGVuZFRpbWVVNjQgPSBtYXBwZWREYXRhW2kgKiAyICsgMV07XG5cbiAgICAgICAgICBpZiAodHlwZW9mIHRoaXMucXVlcnlUaW1lQmFzZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRoaXMucXVlcnlUaW1lQmFzZSA9IHN0YXJ0VGltZVU2NDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBzdGFydFRpbWUgPSBOdW1iZXIoc3RhcnRUaW1lVTY0IC0gdGhpcy5xdWVyeVRpbWVCYXNlKTtcbiAgICAgICAgICBjb25zdCBlbmRUaW1lID0gTnVtYmVyKGVuZFRpbWVVNjQgLSB0aGlzLnF1ZXJ5VGltZUJhc2UpO1xuXG4gICAgICAgICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihzdGFydFRpbWUpIHx8ICFOdW1iZXIuaXNTYWZlSW50ZWdlcihlbmRUaW1lKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luY29ycmVjdCB0aW1lc3RhbXAgcmFuZ2UnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodGhpcy5lbnYud2ViZ3B1LnByb2ZpbGluZz8ub25kYXRhKSB7XG4gICAgICAgICAgICB0aGlzLmVudi53ZWJncHUucHJvZmlsaW5nLm9uZGF0YSh7XG4gICAgICAgICAgICAgIHZlcnNpb246IDEsXG4gICAgICAgICAgICAgIGlucHV0c01ldGFkYXRhOiBpbnB1dFRlbnNvclZpZXdzLm1hcCgodmFsdWUpID0+ICh7XG4gICAgICAgICAgICAgICAgZGltczogdmFsdWUuZGltcyxcbiAgICAgICAgICAgICAgICBkYXRhVHlwZTogdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcodmFsdWUuZGF0YVR5cGUpLFxuICAgICAgICAgICAgICB9KSksXG4gICAgICAgICAgICAgIG91dHB1dHNNZXRhZGF0YTogb3V0cHV0VGVuc29yVmlld3MubWFwKCh2YWx1ZSkgPT4gKHtcbiAgICAgICAgICAgICAgICBkaW1zOiB2YWx1ZS5kaW1zLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyh2YWx1ZS5kYXRhVHlwZSksXG4gICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgICAga2VybmVsSWQsXG4gICAgICAgICAgICAgIGtlcm5lbFR5cGUsXG4gICAgICAgICAgICAgIGtlcm5lbE5hbWUsXG4gICAgICAgICAgICAgIHByb2dyYW1OYW1lLFxuICAgICAgICAgICAgICBzdGFydFRpbWUsXG4gICAgICAgICAgICAgIGVuZFRpbWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gaWYgbm8gY2FsbGJhY2sgaXMgcHJvdmlkZWQsIHByaW50IHRoZSBwcm9maWxpbmcgbWVzc2FnZSB0byBjb25zb2xlXG4gICAgICAgICAgICBsZXQgaW5wdXRTaGFwZXMgPSAnJztcbiAgICAgICAgICAgIGlucHV0VGVuc29yVmlld3MuZm9yRWFjaCgodmFsdWUsIGkpID0+IHtcbiAgICAgICAgICAgICAgaW5wdXRTaGFwZXMgKz0gYGlucHV0WyR7aX1dOiBbJHt2YWx1ZS5kaW1zfV0gfCAke3RlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nKHZhbHVlLmRhdGFUeXBlKX0sIGA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGxldCBvdXRwdXRTaGFwZXMgPSAnJztcbiAgICAgICAgICAgIG91dHB1dFRlbnNvclZpZXdzLmZvckVhY2goKHZhbHVlLCBpKSA9PiB7XG4gICAgICAgICAgICAgIG91dHB1dFNoYXBlcyArPSBgb3V0cHV0WyR7aX1dOiBbJHt2YWx1ZS5kaW1zfV0gfCAke3RlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nKHZhbHVlLmRhdGFUeXBlKX0sIGA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgYFtwcm9maWxpbmddIGtlcm5lbCBcIiR7a2VybmVsSWR9fCR7a2VybmVsVHlwZX18JHtrZXJuZWxOYW1lfXwke3Byb2dyYW1OYW1lfVwiICR7aW5wdXRTaGFwZXN9JHtcbiAgICAgICAgICAgICAgICBvdXRwdXRTaGFwZXNcbiAgICAgICAgICAgICAgfWV4ZWN1dGlvbiB0aW1lOiAke2VuZFRpbWUgLSBzdGFydFRpbWV9IG5zYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIFRSQUNFKCdHUFUnLCBgJHtwcm9ncmFtTmFtZX06OiR7c3RhcnRUaW1lVTY0fTo6JHtlbmRUaW1lVTY0fWApO1xuICAgICAgICB9XG4gICAgICAgIHF1ZXJ5UmVhZEJ1ZmZlci51bm1hcCgpO1xuICAgICAgICB0aGlzLnBlbmRpbmdRdWVyaWVzLmRlbGV0ZShxdWVyeVJlYWRCdWZmZXIpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIFRSQUNFX0ZVTkNfRU5EKCk7XG4gIH1cblxuICAvKipcbiAgICogcnVuIGEgV2ViR1BVIHByb2dyYW0uXG4gICAqIEBwYXJhbSBwcm9ncmFtIGEgUHJvZ3JhbUluZm8gaW5zdGFuY2VcbiAgICogQHBhcmFtIGlucHV0VGVuc29yVmlld3MgYSBUZW5zb3JWaWV3IGFycmF5LiBlYWNoIGVsZW1lbnQgcmVwcmVzZW50cyBhIHZhbHVlIGFscmVhZHkgZXhpc3RzIGluIEdQVS5cbiAgICogQHBhcmFtIG91dHB1dEluZGljZXMgYW4gaW5kaWNlcyBhcnJheS4gZWFjaCBlbGVtZW50IGNhbiBiZSBlaXRoZXIgLTEgKHRlbXBvcmFyeSBkYXRhKSwgLTIgKHBlcnNpc3RlbnQgZGF0YSkgb3IgYW5cbiAgICogaW5kZXggdG8gdGhlIGtlcm5lbCdzIG91dHB1dC5cbiAgICogQHBhcmFtIGNyZWF0ZUtlcm5lbE91dHB1dCBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgY3JlYXRlIGEgdmFsdWUgdG8ga2VybmVsJ3Mgb3V0cHV0IHdpdGggdGhlIGdpdmVuIGluZGV4XG4gICAqIEBwYXJhbSBjcmVhdGVJbnRlcm1lZGlhdGVPdXRwdXQgYSBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IGNyZWF0ZSBhIHZhbHVlIGFzIGEgaW50ZXJtZWRpYXRlIHZhbHVlLCBlaXRoZXIgdGVtcG9yYXJ5XG4gICAqIG9yIHBlcnNpc3RlbnQgKG93bmVkIGJ5IHRoZSBjdXJyZW50IGtlcm5lbClcbiAgICogQHJldHVybnMgYSBUZW5zb3JWaWV3IGFycmF5IHJlcHJlc2VudGluZyB0aGUgcmVzdWx0LlxuICAgKi9cbiAgcnVuKFxuICAgIHByb2dyYW06IFByb2dyYW1JbmZvLFxuICAgIGlucHV0VGVuc29yVmlld3M6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgICBvdXRwdXRJbmRpY2VzOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBjcmVhdGVLZXJuZWxPdXRwdXQ6IChpbmRleDogbnVtYmVyLCBkYXRhVHlwZTogbnVtYmVyLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSkgPT4gVGVuc29yVmlldyxcbiAgICBjcmVhdGVJbnRlcm1lZGlhdGVPdXRwdXQ6IChkYXRhVHlwZTogbnVtYmVyLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSkgPT4gVGVuc29yVmlldyxcbiAgICBvdXRwdXRDb3VudDogbnVtYmVyLFxuICApOiBUZW5zb3JWaWV3W10ge1xuICAgIFRSQUNFX0ZVTkNfQkVHSU4ocHJvZ3JhbS5uYW1lKTtcbiAgICAvLyBjcmVhdGUgaW5mbyBmb3IgaW5wdXRzXG4gICAgY29uc3QgaW5wdXREYXRhczogR3B1RGF0YVtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFRlbnNvclZpZXdzLmxlbmd0aDsgKytpKSB7XG4gICAgICBjb25zdCBkYXRhID0gaW5wdXRUZW5zb3JWaWV3c1tpXS5kYXRhO1xuICAgICAgLy8gaWYgdGVuc29yIHZpZXcgZGF0YSBpcyAwLCBpdCBtZWFucyB0aGUgb3V0cHV0IGlzIHplcm8tc2l6ZWQgdGVuc29yLCBhbmQgdGhlcmUgaXMgbm8gR1BVIGRhdGEgZm9yIGl0LlxuICAgICAgaWYgKGRhdGEgPT09IDApIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBncHVEYXRhID0gdGhpcy5ncHVEYXRhTWFuYWdlci5nZXQoZGF0YSk7XG4gICAgICBpZiAoIWdwdURhdGEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBubyBHUFUgZGF0YSBmb3IgaW5wdXQ6ICR7ZGF0YX1gKTtcbiAgICAgIH1cbiAgICAgIGlucHV0RGF0YXMucHVzaChncHVEYXRhKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IG91dHB1dHMsIGRpc3BhdGNoR3JvdXAsIHByb2dyYW1Vbmlmb3JtcyB9ID0gcHJvZ3JhbS5nZXRSdW5EYXRhKGlucHV0VGVuc29yVmlld3MpO1xuXG4gICAgLy8gY2hlY2sgb3V0cHV0IGluZGljZXNcbiAgICBjb25zdCB2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzID0gb3V0cHV0SW5kaWNlcy5sZW5ndGggPT09IDAgPyBvdXRwdXRzLm1hcCgoXywgaSkgPT4gaSkgOiBvdXRwdXRJbmRpY2VzO1xuICAgIGlmICh2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzLmxlbmd0aCAhPT0gb3V0cHV0cy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgT3V0cHV0IHNpemUgJHt2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzLmxlbmd0aH0gbXVzdCBiZSBlcXVhbCB0byAke291dHB1dHMubGVuZ3RofS5gKTtcbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgaW5mbyBmb3Igb3V0cHV0c1xuICAgIGNvbnN0IG91dHB1dFRlbnNvclZpZXdzOiBUZW5zb3JWaWV3W10gPSBbXTtcbiAgICBjb25zdCBvdXRwdXREYXRhczogR3B1RGF0YVtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAvLyB2YWx1ZSAtMSBhbmQgLTIgYXJlIHVzZWQgZm9yIGNyZWF0aW5nIHRlbXBvcmFyeSBhbmQgcGVyc2lzdGVudCBvdXRwdXRzLlxuICAgICAgLy8gdmFsdWUgLTMgaXMgdXNlZCBmb3IgcGxhY2Vob2xkZXIgb3V0cHV0LiBTbyAtMywgLTIsIC0xIGFuZCAwLCAxLCAyLCAuLi4gYXJlIHZhbGlkXG4gICAgICAvLyBvdXRwdXQgaW5kaWNlcy4gc2VlIHR5cGUgZGVmaW5pdGlvbiBvZiBDb21wdXRlQ29udGV4dElucHV0c091dHB1dHNNYXBwaW5nIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICBpZiAoXG4gICAgICAgICFOdW1iZXIuaXNJbnRlZ2VyKHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0pIHx8XG4gICAgICAgIHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0gPCAtMyB8fFxuICAgICAgICB2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldID49IG91dHB1dENvdW50XG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIG91dHB1dCBpbmRleDogJHt2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldfWApO1xuICAgICAgfVxuICAgICAgaWYgKHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0gPT09IC0zKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgaXNUZW1wb3JhcnkgPSB2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldID09PSAtMTtcbiAgICAgIGNvbnN0IGlzUGVyc2lzdGVudCA9IHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0gPT09IC0yO1xuICAgICAgY29uc3QgdGVuc29yVmlldyA9XG4gICAgICAgIGlzVGVtcG9yYXJ5IHx8IGlzUGVyc2lzdGVudFxuICAgICAgICAgID8gY3JlYXRlSW50ZXJtZWRpYXRlT3V0cHV0KG91dHB1dHNbaV0uZGF0YVR5cGUsIG91dHB1dHNbaV0uZGltcylcbiAgICAgICAgICA6IGNyZWF0ZUtlcm5lbE91dHB1dCh2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldLCBvdXRwdXRzW2ldLmRhdGFUeXBlLCBvdXRwdXRzW2ldLmRpbXMpO1xuICAgICAgb3V0cHV0VGVuc29yVmlld3MucHVzaCh0ZW5zb3JWaWV3KTtcbiAgICAgIC8vIGlmIHRlbnNvciB2aWV3IGRhdGEgaXMgMCwgaXQgbWVhbnMgdGhlIG91dHB1dCBpcyB6ZXJvLXNpemVkIHRlbnNvciwgYW5kIHRoZXJlIGlzIG5vIEdQVSBkYXRhIGZvciBpdC5cbiAgICAgIGlmICh0ZW5zb3JWaWV3LmRhdGEgPT09IDApIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBncHVEYXRhID0gdGhpcy5ncHVEYXRhTWFuYWdlci5nZXQodGVuc29yVmlldy5kYXRhKTtcbiAgICAgIGlmICghZ3B1RGF0YSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vIEdQVSBkYXRhIGZvciBvdXRwdXQ6ICR7dGVuc29yVmlldy5kYXRhfWApO1xuICAgICAgfVxuICAgICAgaWYgKGlzVGVtcG9yYXJ5KSB7XG4gICAgICAgIHRoaXMudGVtcG9yYXJ5RGF0YS5wdXNoKGdwdURhdGEpO1xuICAgICAgfVxuICAgICAgaWYgKGlzUGVyc2lzdGVudCkge1xuICAgICAgICBsZXQgcGVyc2lzdGVudERhdGEgPSB0aGlzLmtlcm5lbFBlcnNpc3RlbnREYXRhLmdldCh0aGlzLmN1cnJlbnRLZXJuZWxJZCEpO1xuICAgICAgICBpZiAoIXBlcnNpc3RlbnREYXRhKSB7XG4gICAgICAgICAgcGVyc2lzdGVudERhdGEgPSBbXTtcbiAgICAgICAgICB0aGlzLmtlcm5lbFBlcnNpc3RlbnREYXRhLnNldCh0aGlzLmN1cnJlbnRLZXJuZWxJZCEsIHBlcnNpc3RlbnREYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBwZXJzaXN0ZW50RGF0YS5wdXNoKGdwdURhdGEpO1xuICAgICAgfVxuICAgICAgb3V0cHV0RGF0YXMucHVzaChncHVEYXRhKTtcbiAgICB9XG5cbiAgICAvLyB3aGVuIHRoZXJlIGFyZSBhbnkgemVyby1zaXplZCB0ZW5zb3IgaW4gdGhlIGlucHV0cyBvciBvdXRwdXRzLCB3ZSBzaG91bGQgcmVwb3J0IGVycm9yIHVubGVzcyBhbGwgb3V0cHV0cyBhcmVcbiAgICAvLyB6ZXJvLXNpemVkIHRlbnNvcnMuXG4gICAgaWYgKGlucHV0RGF0YXMubGVuZ3RoICE9PSBpbnB1dFRlbnNvclZpZXdzLmxlbmd0aCB8fCBvdXRwdXREYXRhcy5sZW5ndGggIT09IG91dHB1dFRlbnNvclZpZXdzLmxlbmd0aCkge1xuICAgICAgLy8gaWYgYWxsIG91dHB1dHMgYXJlIHplcm8tc2l6ZWQgdGVuc29ycywgdGhlcmUgaXMgbm8gbmVlZCB0byBydW4gdGhlIHByb2dyYW0uXG4gICAgICBpZiAob3V0cHV0RGF0YXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIFRSQUNFX0ZVTkNfRU5EKHByb2dyYW0ubmFtZSk7XG4gICAgICAgIHJldHVybiBvdXRwdXRUZW5zb3JWaWV3cztcbiAgICAgIH1cbiAgICAgIC8vIGlmIHNvbWUgb3V0cHV0cyBhcmUgemVyby1zaXplZCB0ZW5zb3JzLCByZXBvcnQgYW4gZXJyb3IuXG4gICAgICAvL1xuICAgICAgLy8gVE9ETzogc28gZmFyIHdlIGRvbid0IHNlZSBhbnkgdXNlIGNhc2UgdGhhdCBvdXRwdXRzIGluY2x1ZGUgYm90aCB6ZXJvLXNpemVkIHRlbnNvcnMgYW5kIG5vbi16ZXJvLXNpemVkIHRlbnNvcnMuXG4gICAgICAvLyBJZiB3ZSBzZWUgc3VjaCB1c2UgY2FzZSwgd2UgbmVlZCB0byBtYWtlIGEgY2hhbmdlIGhlcmUgdG8gc3VwcG9ydCBpdC5cbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFByb2dyYW0gJHtwcm9ncmFtLm5hbWV9IGhhcyB6ZXJvLXNpemVkIHRlbnNvcihzKSBpbiBpbnB1dHMgb3Igb3V0cHV0cy4gVGhpcyBpcyBub3Qgc3VwcG9ydGVkIG5vdy5gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBsb2FkIHVuaWZvcm1zXG4gICAgLy8gVE9ETzogYWRkIGNhY2hlIGZvciB1bmlmb3JtIChpcyBpdCBuZWNlc3Nhcnk/KVxuICAgIC8vXG4gICAgbGV0IHVuaWZvcm1CdWZmZXJCaW5kaW5nOiBHUFVCaW5kaW5nUmVzb3VyY2UgfCB1bmRlZmluZWQ7XG4gICAgaWYgKHByb2dyYW1Vbmlmb3Jtcykge1xuICAgICAgbGV0IGN1cnJlbnRPZmZzZXQgPSAwO1xuICAgICAgY29uc3Qgb2Zmc2V0czogbnVtYmVyW10gPSBbXTtcblxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLmZvckVhY2goKHYpID0+IHtcbiAgICAgICAgY29uc3QgZGF0YSA9IHR5cGVvZiB2LmRhdGEgPT09ICdudW1iZXInID8gW3YuZGF0YV0gOiB2LmRhdGE7XG4gICAgICAgIGlmIChkYXRhLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBodHRwczovL3d3dy53My5vcmcvVFIvV0dTTC8jYWxpZ25vZlxuICAgICAgICBjb25zdCBzaXplT2ZFbGVtZW50ID0gdi50eXBlID09PSBEYXRhVHlwZS5mbG9hdDE2ID8gMiA6IDQ7XG4gICAgICAgIGxldCBzaXplT2ZWZWNPck1hdDtcbiAgICAgICAgbGV0IGJhc2VBbGlnbm1lbnQ7XG4gICAgICAgIGlmICh2LnR5cGUgPT09IERhdGFUeXBlLmZsb2F0MTYpIHtcbiAgICAgICAgICBiYXNlQWxpZ25tZW50ID0gZGF0YS5sZW5ndGggPiA0ID8gMTYgOiBkYXRhLmxlbmd0aCA+IDIgPyA4IDogZGF0YS5sZW5ndGggKiBzaXplT2ZFbGVtZW50O1xuICAgICAgICAgIHNpemVPZlZlY09yTWF0ID0gZGF0YS5sZW5ndGggPiA0ID8gMTYgOiBzaXplT2ZFbGVtZW50ICogZGF0YS5sZW5ndGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYmFzZUFsaWdubWVudCA9IGRhdGEubGVuZ3RoIDw9IDIgPyBkYXRhLmxlbmd0aCAqIHNpemVPZkVsZW1lbnQgOiAxNjtcbiAgICAgICAgICBzaXplT2ZWZWNPck1hdCA9IDE2O1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnRPZmZzZXQgPSBNYXRoLmNlaWwoY3VycmVudE9mZnNldCAvIGJhc2VBbGlnbm1lbnQpICogYmFzZUFsaWdubWVudDtcbiAgICAgICAgb2Zmc2V0cy5wdXNoKGN1cnJlbnRPZmZzZXQpO1xuICAgICAgICAvLyBGb3Igbm9uLWZsb2F0MTYgdHlwZSwgd2hlbiBkYXRhLmxlbmd0aCA+IDQsIHRoZSB1bmlmb3JtIHZhcmlhYmxlIGlzIG9mIHR5cGUgYXJyYXk8dmVjNDxpMzJ8dTMyfGYzMj4sTj4sIHdoZXJlXG4gICAgICAgIC8vIE4gPSBNYXRoLmNlaWwoZGF0YS5sZW5ndGggLyA0KSBhbmQgU2l6ZU9mKHZlYzQ8aTMyfHUzMnxmMzI+KSA9IDE2LiBUaGUgdG90YWwgYnl0ZSBsZW5ndGggaXMgTiAqXG4gICAgICAgIC8vIFNpemVPZih2ZWM0PGkzMnx1MzJ8ZjMyPikuIEZvciBmbG9hdDE2IHR5cGUsIHdoZW4gZGF0YS5sZW5ndGggPiA0LCB0aGUgdW5pZm9ybSB2YXJpYWJsZSBpcyBvZiB0eXBlXG4gICAgICAgIC8vIGFycmF5PG1hdDJ4NDxmMTY+LE4+LCB3aGVyZSBOID0gTWF0aC5jZWlsKGRhdGEubGVuZ3RoIC8gOCkgYW5kIFNpemVPZihtYXQyeDQ8ZjE2PikgPSAxNi4gVGhlIHRvdGFsIGJ5dGVcbiAgICAgICAgLy8gbGVuZ3RoIGlzIE4gKiBTaXplT2YobWF0Mng0PGYxNj4pLlxuICAgICAgICBjb25zdCBlbGVtZW50UGVyVmVjT3JNYXQgPSB2LnR5cGUgPT09IERhdGFUeXBlLmZsb2F0MTYgPyA4IDogNDtcbiAgICAgICAgY3VycmVudE9mZnNldCArPVxuICAgICAgICAgIGRhdGEubGVuZ3RoID4gNCA/IE1hdGguY2VpbChkYXRhLmxlbmd0aCAvIGVsZW1lbnRQZXJWZWNPck1hdCkgKiBzaXplT2ZWZWNPck1hdCA6IGRhdGEubGVuZ3RoICogc2l6ZU9mRWxlbWVudDtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBNZWV0IGFsaWdubWVudCBvZiBzdHJ1Y3QgaGVyZTogaHR0cHM6Ly93d3cudzMub3JnL1RSL1dHU0wvI2FsaWdubWVudC1hbmQtc2l6ZS4gRm9yIHNpbXBsaWNpdHksIHNldFxuICAgICAgLy8gbWF4QWxpZ25tZW50T2ZGaWVsZCB0byAxNiBzaW5jZSB0aGUgdW5kZXJseWluZyBidWZmZXIgaGFzIGJlZW4gcm91bmRlZCB1cCB0byAxNi5cbiAgICAgIGNvbnN0IG1heEFsaWdubWVudE9mRmllbGQgPSAxNjtcbiAgICAgIGN1cnJlbnRPZmZzZXQgPSBNYXRoLmNlaWwoY3VycmVudE9mZnNldCAvIG1heEFsaWdubWVudE9mRmllbGQpICogbWF4QWxpZ25tZW50T2ZGaWVsZDtcbiAgICAgIGNvbnN0IGFycmF5QnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKGN1cnJlbnRPZmZzZXQpO1xuICAgICAgcHJvZ3JhbVVuaWZvcm1zLmZvckVhY2goKHYsIGkpID0+IHtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gb2Zmc2V0c1tpXTtcbiAgICAgICAgY29uc3QgZGF0YSA9IHR5cGVvZiB2LmRhdGEgPT09ICdudW1iZXInID8gW3YuZGF0YV0gOiB2LmRhdGE7XG4gICAgICAgIGlmICh2LnR5cGUgPT09IERhdGFUeXBlLmludDMyKSB7XG4gICAgICAgICAgbmV3IEludDMyQXJyYXkoYXJyYXlCdWZmZXIsIG9mZnNldCwgZGF0YS5sZW5ndGgpLnNldChkYXRhKTtcbiAgICAgICAgfSBlbHNlIGlmICh2LnR5cGUgPT09IERhdGFUeXBlLnVpbnQzMikge1xuICAgICAgICAgIG5ldyBVaW50MzJBcnJheShhcnJheUJ1ZmZlciwgb2Zmc2V0LCBkYXRhLmxlbmd0aCkuc2V0KGRhdGEpO1xuICAgICAgICB9IGVsc2UgaWYgKHYudHlwZSA9PT0gRGF0YVR5cGUuZmxvYXQxNikge1xuICAgICAgICAgIG5ldyBVaW50MTZBcnJheShhcnJheUJ1ZmZlciwgb2Zmc2V0LCBkYXRhLmxlbmd0aCkuc2V0KGRhdGEpO1xuICAgICAgICB9IGVsc2UgaWYgKHYudHlwZSA9PT0gRGF0YVR5cGUuZmxvYXQpIHtcbiAgICAgICAgICBuZXcgRmxvYXQzMkFycmF5KGFycmF5QnVmZmVyLCBvZmZzZXQsIGRhdGEubGVuZ3RoKS5zZXQoZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCB1bmlmb3JtIHR5cGU6ICR7dGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcodi50eXBlKX1gKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHVuaWZvcm1CdWZmZXJEYXRhID1cbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICAgICAgdGhpcy5ncHVEYXRhTWFuYWdlci5jcmVhdGUoY3VycmVudE9mZnNldCwgR1BVQnVmZmVyVXNhZ2UuQ09QWV9EU1QgfCBHUFVCdWZmZXJVc2FnZS5VTklGT1JNKTtcbiAgICAgIHRoaXMuZGV2aWNlLnF1ZXVlLndyaXRlQnVmZmVyKHVuaWZvcm1CdWZmZXJEYXRhLmJ1ZmZlciwgMCwgYXJyYXlCdWZmZXIsIDAsIGN1cnJlbnRPZmZzZXQpO1xuICAgICAgdGhpcy5ncHVEYXRhTWFuYWdlci5yZWxlYXNlKHVuaWZvcm1CdWZmZXJEYXRhLmlkKTtcbiAgICAgIHVuaWZvcm1CdWZmZXJCaW5kaW5nID0geyBvZmZzZXQ6IDAsIHNpemU6IGN1cnJlbnRPZmZzZXQsIGJ1ZmZlcjogdW5pZm9ybUJ1ZmZlckRhdGEuYnVmZmVyIH07XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZERpc3BhdGNoR3JvdXAgPSB0aGlzLnByb2dyYW1NYW5hZ2VyLm5vcm1hbGl6ZURpc3BhdGNoR3JvdXBTaXplKGRpc3BhdGNoR3JvdXApO1xuICAgIGNvbnN0IGlzMURpbWVuc2lvbkRpc3BhdGNoID0gbm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMV0gPT09IDEgJiYgbm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMl0gPT09IDE7XG4gICAgLy8gZ2V0IHByb2dyYW0gaW5mb1xuICAgIGNvbnN0IGtleSA9IGdldFByb2dyYW1JbmZvVW5pcXVlS2V5KHByb2dyYW0sIGlucHV0VGVuc29yVmlld3MsIGlzMURpbWVuc2lvbkRpc3BhdGNoKTtcbiAgICBsZXQgYXJ0aWZhY3QgPSB0aGlzLnByb2dyYW1NYW5hZ2VyLmdldEFydGlmYWN0KGtleSk7XG4gICAgaWYgKCFhcnRpZmFjdCkge1xuICAgICAgYXJ0aWZhY3QgPSB0aGlzLnByb2dyYW1NYW5hZ2VyLmJ1aWxkKHByb2dyYW0sIG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwKTtcbiAgICAgIHRoaXMucHJvZ3JhbU1hbmFnZXIuc2V0QXJ0aWZhY3Qoa2V5LCBhcnRpZmFjdCk7XG4gICAgICBMT0dfREVCVUcoJ2luZm8nLCAoKSA9PiBgW2FydGlmYWN0XSBrZXk6ICR7a2V5fSwgcHJvZ3JhbU5hbWU6ICR7cHJvZ3JhbS5uYW1lfWApO1xuICAgIH1cblxuICAgIC8vIHZhbGlkYXRlIHVuaWZvcm0gdmFyaWFibGVzXG4gICAgaWYgKHByb2dyYW1Vbmlmb3JtcyAmJiBhcnRpZmFjdC51bmlmb3JtVmFyaWFibGVzSW5mbykge1xuICAgICAgaWYgKHByb2dyYW1Vbmlmb3Jtcy5sZW5ndGggIT09IGFydGlmYWN0LnVuaWZvcm1WYXJpYWJsZXNJbmZvLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYFVuaWZvcm0gdmFyaWFibGVzIGNvdW50IG1pc21hdGNoOiBleHBlY3QgJHthcnRpZmFjdC51bmlmb3JtVmFyaWFibGVzSW5mby5sZW5ndGh9LCBnb3QgJHtcbiAgICAgICAgICAgIHByb2dyYW1Vbmlmb3Jtcy5sZW5ndGhcbiAgICAgICAgICB9IGluIHByb2dyYW0gXCIke2FydGlmYWN0LnByb2dyYW1JbmZvLm5hbWV9XCIuYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcHJvZ3JhbVVuaWZvcm1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHVuaWZvcm0gPSBwcm9ncmFtVW5pZm9ybXNbaV07XG4gICAgICAgIGNvbnN0IGFjdHVhbFR5cGUgPSB1bmlmb3JtLnR5cGU7XG4gICAgICAgIGNvbnN0IGFjdHVhbExlbmd0aCA9IHR5cGVvZiB1bmlmb3JtLmRhdGEgPT09ICdudW1iZXInID8gMSA6IHVuaWZvcm0uZGF0YS5sZW5ndGg7XG4gICAgICAgIGNvbnN0IFt0eXBlLCBsZW5ndGhdID0gYXJ0aWZhY3QudW5pZm9ybVZhcmlhYmxlc0luZm9baV07XG4gICAgICAgIGlmIChhY3R1YWxUeXBlICE9PSB0eXBlIHx8IGFjdHVhbExlbmd0aCAhPT0gbGVuZ3RoKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFVuaWZvcm0gdmFyaWFibGUgJHtpfSBtaXNtYXRjaDogZXhwZWN0IHR5cGUgJHt0eXBlfSB3aXRoIHNpemUgJHtsZW5ndGh9LCBnb3QgdHlwZSAke1xuICAgICAgICAgICAgICBhY3R1YWxUeXBlXG4gICAgICAgICAgICB9IHdpdGggc2l6ZSAke2FjdHVhbExlbmd0aH0gaW4gcHJvZ3JhbSBcIiR7YXJ0aWZhY3QucHJvZ3JhbUluZm8ubmFtZX1cIi5gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBMT0dfREVCVUcoXG4gICAgICAnaW5mbycsXG4gICAgICAoKSA9PlxuICAgICAgICBgW1Byb2dyYW1NYW5hZ2VyXSBydW4gXCIke3Byb2dyYW0ubmFtZX1cIiAoa2V5PSR7a2V5fSkgd2l0aCAke25vcm1hbGl6ZWREaXNwYXRjaEdyb3VwWzBdfXgke1xuICAgICAgICAgIG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwWzFdXG4gICAgICAgIH14JHtub3JtYWxpemVkRGlzcGF0Y2hHcm91cFsyXX1gLFxuICAgICk7XG5cbiAgICBpZiAodGhpcy5xdWVyeVR5cGUgIT09ICdub25lJyB8fCB0aGlzLnNlc3Npb25TdGF0dXMgPT09ICdjYXB0dXJpbmcnKSB7XG4gICAgICBjb25zdCBwZW5kaW5nS2VybmVsSW5mbzogUGVuZGluZ0tlcm5lbEluZm8gPSB7XG4gICAgICAgIGtlcm5lbElkOiB0aGlzLmN1cnJlbnRLZXJuZWxJZCEsXG4gICAgICAgIHByb2dyYW1OYW1lOiBhcnRpZmFjdC5wcm9ncmFtSW5mby5uYW1lLFxuICAgICAgICBpbnB1dFRlbnNvclZpZXdzLFxuICAgICAgICBvdXRwdXRUZW5zb3JWaWV3cyxcbiAgICAgIH07XG4gICAgICB0aGlzLnBlbmRpbmdLZXJuZWxzLnB1c2gocGVuZGluZ0tlcm5lbEluZm8pO1xuXG4gICAgICBpZiAodGhpcy5zZXNzaW9uU3RhdHVzID09PSAnY2FwdHVyaW5nJykge1xuICAgICAgICBjb25zdCBzZXNzaW9uUGVuZGluZ0tlcm5lbHMgPSB0aGlzLmNhcHR1cmVkUGVuZGluZ0tlcm5lbHMuZ2V0KHRoaXMuY3VycmVudFNlc3Npb25JZCEpO1xuICAgICAgICBzZXNzaW9uUGVuZGluZ0tlcm5lbHMhLnB1c2gocGVuZGluZ0tlcm5lbEluZm8pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMucHJvZ3JhbU1hbmFnZXIucnVuKGFydGlmYWN0LCBpbnB1dERhdGFzLCBvdXRwdXREYXRhcywgbm9ybWFsaXplZERpc3BhdGNoR3JvdXAsIHVuaWZvcm1CdWZmZXJCaW5kaW5nKTtcblxuICAgIFRSQUNFX0ZVTkNfRU5EKHByb2dyYW0ubmFtZSk7XG4gICAgcmV0dXJuIG91dHB1dFRlbnNvclZpZXdzO1xuICB9XG5cbiAgdXBsb2FkKGdwdURhdGFJZDogbnVtYmVyLCBkYXRhOiBVaW50OEFycmF5KTogdm9pZCB7XG4gICAgdGhpcy5ncHVEYXRhTWFuYWdlci51cGxvYWQoZ3B1RGF0YUlkLCBkYXRhKTtcbiAgfVxuXG4gIG1lbWNweShzcmM6IG51bWJlciwgZHN0OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLm1lbWNweShzcmMsIGRzdCk7XG4gIH1cblxuICBhc3luYyBkb3dubG9hZChncHVEYXRhSWQ6IG51bWJlciwgZ2V0VGFyZ2V0QnVmZmVyOiAoKSA9PiBVaW50OEFycmF5KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gdGhlIHVuZGVybHlpbmcgYnVmZmVyIG1heSBiZSBjaGFuZ2VkIGFmdGVyIHRoZSBhc3luYyBmdW5jdGlvbiBpcyBjYWxsZWQuIHNvIHdlIHVzZSBhIGdldHRlciBmdW5jdGlvbiB0byBtYWtlIHN1cmVcbiAgICAvLyB0aGUgYnVmZmVyIGlzIHVwLXRvLWRhdGUuXG4gICAgYXdhaXQgdGhpcy5ncHVEYXRhTWFuYWdlci5kb3dubG9hZChncHVEYXRhSWQsIGdldFRhcmdldEJ1ZmZlcik7XG4gIH1cblxuICBhbGxvYyhzaXplOiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmdwdURhdGFNYW5hZ2VyLmNyZWF0ZShzaXplKS5pZDtcbiAgfVxuXG4gIGZyZWUocHRyOiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmdwdURhdGFNYW5hZ2VyLnJlbGVhc2UocHRyKTtcbiAgfVxuXG4gIGNyZWF0ZUtlcm5lbChrZXJuZWxUeXBlOiBzdHJpbmcsIGtlcm5lbElkOiBudW1iZXIsIGF0dHJpYnV0ZTogdW5rbm93biwga2VybmVsTmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3Qgb3AgPSBXRUJHUFVfT1BfUkVTT0xWRV9SVUxFUy5nZXQoa2VybmVsVHlwZSk7XG4gICAgaWYgKCFvcCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBrZXJuZWwgbm90IGltcGxlbWVudGVkOiAke2tlcm5lbFR5cGV9YCk7XG4gICAgfVxuXG4gICAgY29uc3Qga2VybmVsSW5mbzogS2VybmVsSW5mbyA9IHtcbiAgICAgIGtlcm5lbFR5cGUsXG4gICAgICBrZXJuZWxOYW1lLFxuICAgICAga2VybmVsRW50cnk6IG9wWzBdLFxuICAgICAgYXR0cmlidXRlczogW29wWzFdLCBhdHRyaWJ1dGVdLFxuICAgIH07XG4gICAgdGhpcy5rZXJuZWxzLnNldChrZXJuZWxJZCwga2VybmVsSW5mbyk7XG4gIH1cblxuICByZWxlYXNlS2VybmVsKGtlcm5lbElkOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBwZXJzaXN0ZW50RGF0YSA9IHRoaXMua2VybmVsUGVyc2lzdGVudERhdGEuZ2V0KGtlcm5lbElkKTtcbiAgICBpZiAocGVyc2lzdGVudERhdGEpIHtcbiAgICAgIGZvciAoY29uc3QgZGF0YSBvZiBwZXJzaXN0ZW50RGF0YSkge1xuICAgICAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLnJlbGVhc2UoZGF0YS5pZCk7XG4gICAgICB9XG4gICAgICB0aGlzLmtlcm5lbFBlcnNpc3RlbnREYXRhLmRlbGV0ZShrZXJuZWxJZCk7XG4gICAgfVxuXG4gICAgdGhpcy5rZXJuZWxDdXN0b21EYXRhLmRlbGV0ZShrZXJuZWxJZCk7XG4gICAgdGhpcy5rZXJuZWxzLmRlbGV0ZShrZXJuZWxJZCk7XG4gIH1cblxuICBjb21wdXRlS2VybmVsKGtlcm5lbElkOiBudW1iZXIsIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBlcnJvcnM6IEFycmF5PFByb21pc2U8c3RyaW5nIHwgbnVsbD4+KTogbnVtYmVyIHtcbiAgICBjb25zdCBrZXJuZWwgPSB0aGlzLmtlcm5lbHMuZ2V0KGtlcm5lbElkKTtcbiAgICBpZiAoIWtlcm5lbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBrZXJuZWwgbm90IGNyZWF0ZWQ6ICR7a2VybmVsSWR9YCk7XG4gICAgfVxuICAgIGNvbnN0IGtlcm5lbFR5cGUgPSBrZXJuZWwua2VybmVsVHlwZTtcbiAgICBjb25zdCBrZXJuZWxOYW1lID0ga2VybmVsLmtlcm5lbE5hbWU7XG4gICAgY29uc3Qga2VybmVsRW50cnkgPSBrZXJuZWwua2VybmVsRW50cnk7XG4gICAgY29uc3QgYXR0cmlidXRlcyA9IGtlcm5lbC5hdHRyaWJ1dGVzO1xuICAgIGlmICh0aGlzLmN1cnJlbnRLZXJuZWxJZCAhPT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBrZXJuZWwgXCJbJHtrZXJuZWxUeXBlfV0gJHtrZXJuZWxOYW1lfVwiIGlzIG5vdCBhbGxvd2VkIHRvIGJlIGNhbGxlZCByZWN1cnNpdmVseWApO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnRLZXJuZWxJZCA9IGtlcm5lbElkO1xuXG4gICAgLy8gcGFyc2UgYXR0cmlidXRlcyBpZiBuZWNlc3NhcnlcbiAgICBpZiAoYXR0cmlidXRlc1swXSkge1xuICAgICAgYXR0cmlidXRlc1sxXSA9IGF0dHJpYnV0ZXNbMF0oYXR0cmlidXRlc1sxXSk7XG4gICAgICBhdHRyaWJ1dGVzWzBdID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIExPR19ERUJVRygnaW5mbycsICgpID0+IGBbV2ViR1BVXSBTdGFydCB0byBydW4ga2VybmVsIFwiWyR7a2VybmVsVHlwZX1dICR7a2VybmVsTmFtZX1cIi4uLmApO1xuXG4gICAgY29uc3QgdXNlRXJyb3JTY29wZSA9IHRoaXMuZW52LmRlYnVnO1xuXG4gICAgdGhpcy50ZW1wb3JhcnlEYXRhID0gW107XG4gICAgdHJ5IHtcbiAgICAgIGlmICh1c2VFcnJvclNjb3BlKSB7XG4gICAgICAgIHRoaXMuZGV2aWNlLnB1c2hFcnJvclNjb3BlKCd2YWxpZGF0aW9uJyk7XG4gICAgICB9XG5cbiAgICAgIGtlcm5lbEVudHJ5KGNvbnRleHQsIGF0dHJpYnV0ZXNbMV0pO1xuICAgICAgcmV0dXJuIDA7IC8vIE9SVF9PS1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGVycm9ycy5wdXNoKFByb21pc2UucmVzb2x2ZShgW1dlYkdQVV0gS2VybmVsIFwiWyR7a2VybmVsVHlwZX1dICR7a2VybmVsTmFtZX1cIiBmYWlsZWQuICR7ZX1gKSk7XG4gICAgICByZXR1cm4gMTsgLy8gT1JUX0ZBSUxcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKHVzZUVycm9yU2NvcGUpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goXG4gICAgICAgICAgdGhpcy5kZXZpY2VcbiAgICAgICAgICAgIC5wb3BFcnJvclNjb3BlKClcbiAgICAgICAgICAgIC50aGVuKChlcnIpID0+XG4gICAgICAgICAgICAgIGVyciA/IGBHUFUgdmFsaWRhdGlvbiBlcnJvciBmb3Iga2VybmVsIFwiWyR7a2VybmVsVHlwZX1dICR7a2VybmVsTmFtZX1cIjogJHtlcnIubWVzc2FnZX1gIDogbnVsbCxcbiAgICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgZGF0YSBvZiB0aGlzLnRlbXBvcmFyeURhdGEpIHtcbiAgICAgICAgdGhpcy5ncHVEYXRhTWFuYWdlci5yZWxlYXNlKGRhdGEuaWQpO1xuICAgICAgfVxuICAgICAgdGhpcy50ZW1wb3JhcnlEYXRhID0gW107XG4gICAgICB0aGlzLmN1cnJlbnRLZXJuZWxJZCA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8gI3JlZ2lvbiBleHRlcm5hbCBidWZmZXJcbiAgcmVnaXN0ZXJCdWZmZXIoc2Vzc2lvbklkOiBudW1iZXIsIGluZGV4OiBudW1iZXIsIGJ1ZmZlcjogR1BVQnVmZmVyLCBzaXplOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCBzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nID0gdGhpcy5zZXNzaW9uRXh0ZXJuYWxEYXRhTWFwcGluZy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIXNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmcpIHtcbiAgICAgIHNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmcgPSBuZXcgTWFwKCk7XG4gICAgICB0aGlzLnNlc3Npb25FeHRlcm5hbERhdGFNYXBwaW5nLnNldChzZXNzaW9uSWQsIHNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmcpO1xuICAgIH1cblxuICAgIC8vIHRoZSBidWZmZXIgbWF5IGJlIHVzZXIgY3JlYXRlZCwgb3IgbWFuYWdlZCBieSBHUFUgZGF0YSBtYW5hZ2VyLlxuICAgIC8vIFRoZSBHUFUgZGF0YSBtYW5hZ2VyIHdpbGwgbm90IG1hbmFnZSB0aGVzZSBidWZmZXJzLiB3ZSByZWdpc3RlciB0aGVtIGFzIGV4dGVybmFsIGJ1ZmZlcnMuXG4gICAgLy9cbiAgICAvLyBUaGUgbWFwIGBzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nYCBpcyB1c2VkIHRvIHN0b3JlIHRoZSBkYXRhIElEIGFuZCBidWZmZXIgZm9yIGVhY2ggaW5wdXQvb3V0cHV0LiBPbmNlIGFcbiAgICAvLyBzcGVjaWZpYyBpbnB1dC9vdXRwdXQgaXMgcmVnaXN0ZXJlZCwgdGhlIGRhdGEgSUQgd2lsbCBub3QgY2hhbmdlLlxuICAgIGNvbnN0IHByZXZpb3VzQnVmZmVyID0gc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZy5nZXQoaW5kZXgpO1xuICAgIGNvbnN0IGlkID0gdGhpcy5ncHVEYXRhTWFuYWdlci5yZWdpc3RlckV4dGVybmFsQnVmZmVyKGJ1ZmZlciwgc2l6ZSwgcHJldmlvdXNCdWZmZXIpO1xuICAgIHNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmcuc2V0KGluZGV4LCBbaWQsIGJ1ZmZlcl0pO1xuICAgIHJldHVybiBpZDtcbiAgfVxuICB1bnJlZ2lzdGVyQnVmZmVycyhzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmcgPSB0aGlzLnNlc3Npb25FeHRlcm5hbERhdGFNYXBwaW5nLmdldChzZXNzaW9uSWQpO1xuICAgIGlmIChzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nKSB7XG4gICAgICBzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nLmZvckVhY2goKGJ1ZmZlckluZm8pID0+IHRoaXMuZ3B1RGF0YU1hbmFnZXIudW5yZWdpc3RlckV4dGVybmFsQnVmZmVyKGJ1ZmZlckluZm9bMF0pKTtcbiAgICAgIHRoaXMuc2Vzc2lvbkV4dGVybmFsRGF0YU1hcHBpbmcuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgfVxuICB9XG4gIGdldEJ1ZmZlcihncHVEYXRhSWQ6IG51bWJlcik6IEdQVUJ1ZmZlciB7XG4gICAgY29uc3QgZ3B1RGF0YSA9IHRoaXMuZ3B1RGF0YU1hbmFnZXIuZ2V0KGdwdURhdGFJZCk7XG4gICAgaWYgKCFncHVEYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vIEdQVSBkYXRhIGZvciBidWZmZXI6ICR7Z3B1RGF0YUlkfWApO1xuICAgIH1cbiAgICByZXR1cm4gZ3B1RGF0YS5idWZmZXI7XG4gIH1cbiAgY3JlYXRlRG93bmxvYWRlcihcbiAgICBncHVCdWZmZXI6IEdQVUJ1ZmZlcixcbiAgICBzaXplOiBudW1iZXIsXG4gICAgdHlwZTogVGVuc29yLkdwdUJ1ZmZlckRhdGFUeXBlcyxcbiAgKTogKCkgPT4gUHJvbWlzZTxUZW5zb3IuRGF0YVR5cGU+IHtcbiAgICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGRvd25sb2FkR3B1RGF0YSh0aGlzLCBncHVCdWZmZXIsIHNpemUpO1xuICAgICAgcmV0dXJuIGNyZWF0ZVZpZXcoZGF0YS5idWZmZXIsIHR5cGUpO1xuICAgIH07XG4gIH1cbiAgLy8gI2VuZHJlZ2lvblxuICB3cml0ZVRpbWVzdGFtcChpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucXVlcnlUeXBlICE9PSAnaW5zaWRlLXBhc3NlcycpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICh0aGlzLmNvbXB1dGVQYXNzRW5jb2RlciBhcyBhbnkpLndyaXRlVGltZXN0YW1wKHRoaXMucXVlcnlTZXQsIGluZGV4KTtcbiAgfVxuICBzZXRRdWVyeVR5cGUoKTogdm9pZCB7XG4gICAgdGhpcy5xdWVyeVR5cGUgPSAnbm9uZSc7XG4gICAgaWYgKFxuICAgICAgdGhpcy5lbnYud2ViZ3B1LnByb2ZpbGluZz8ubW9kZSA9PT0gJ2RlZmF1bHQnIHx8XG4gICAgICAodHlwZW9mIHRoaXMuZW52LnRyYWNlID09PSAndW5kZWZpbmVkJyA/IHRoaXMuZW52Lndhc20udHJhY2UgOiB0aGlzLmVudi50cmFjZSlcbiAgICApIHtcbiAgICAgIGlmICh0aGlzLmRldmljZS5mZWF0dXJlcy5oYXMoJ2Nocm9taXVtLWV4cGVyaW1lbnRhbC10aW1lc3RhbXAtcXVlcnktaW5zaWRlLXBhc3NlcycpKSB7XG4gICAgICAgIHRoaXMucXVlcnlUeXBlID0gJ2luc2lkZS1wYXNzZXMnO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLmRldmljZS5mZWF0dXJlcy5oYXMoJ3RpbWVzdGFtcC1xdWVyeScpKSB7XG4gICAgICAgIHRoaXMucXVlcnlUeXBlID0gJ2F0LXBhc3Nlcyc7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnF1ZXJ5VHlwZSAhPT0gJ25vbmUnICYmIHR5cGVvZiB0aGlzLnF1ZXJ5U2V0ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aGlzLnF1ZXJ5U2V0ID0gdGhpcy5kZXZpY2UuY3JlYXRlUXVlcnlTZXQoe1xuICAgICAgICAgIHR5cGU6ICd0aW1lc3RhbXAnLFxuICAgICAgICAgIGNvdW50OiB0aGlzLm1heERpc3BhdGNoTnVtYmVyICogMixcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucXVlcnlSZXNvbHZlQnVmZmVyID0gdGhpcy5kZXZpY2UuY3JlYXRlQnVmZmVyKFxuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgICAgICAgeyBzaXplOiB0aGlzLm1heERpc3BhdGNoTnVtYmVyICogMiAqIDgsIHVzYWdlOiBHUFVCdWZmZXJVc2FnZS5DT1BZX1NSQyB8IEdQVUJ1ZmZlclVzYWdlLlFVRVJZX1JFU09MVkUgfSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjYXB0dXJlQmVnaW4oKTogdm9pZCB7XG4gICAgTE9HX0RFQlVHKCdpbmZvJywgJ2NhcHR1cmVCZWdpbicpO1xuICAgIGlmICghdGhpcy5jYXB0dXJlZENvbW1hbmRMaXN0LmdldCh0aGlzLmN1cnJlbnRTZXNzaW9uSWQhKSkge1xuICAgICAgdGhpcy5jYXB0dXJlZENvbW1hbmRMaXN0LnNldCh0aGlzLmN1cnJlbnRTZXNzaW9uSWQhLCBbXSk7XG4gICAgfVxuICAgIGlmICghdGhpcy5jYXB0dXJlZFBlbmRpbmdLZXJuZWxzLmdldCh0aGlzLmN1cnJlbnRTZXNzaW9uSWQhKSkge1xuICAgICAgdGhpcy5jYXB0dXJlZFBlbmRpbmdLZXJuZWxzLnNldCh0aGlzLmN1cnJlbnRTZXNzaW9uSWQhLCBbXSk7XG4gICAgfVxuICAgIC8vIGZsdXNoIHRoZSBsZWZ0IGNvbW1hbmRzIGJlZm9yZSB3ZSBjaGFuZ2UgdGhlIHN0YXR1cy5cbiAgICB0aGlzLmZsdXNoKCk7XG4gICAgdGhpcy5zZXNzaW9uU3RhdHVzID0gJ2NhcHR1cmluZyc7XG4gIH1cbiAgY2FwdHVyZUVuZCgpOiB2b2lkIHtcbiAgICBMT0dfREVCVUcoJ2luZm8nLCAnY2FwdHVyZUVuZCcpO1xuICAgIC8vIGZsdXNoIHRoZSBsZWZ0IGNvbW1hbmRzIGJlZm9yZSB3ZSBjaGFuZ2UgdGhlIHN0YXR1cy5cbiAgICB0aGlzLmZsdXNoKCk7XG4gICAgdGhpcy5zZXNzaW9uU3RhdHVzID0gJ2RlZmF1bHQnO1xuICB9XG4gIHJlcGxheSgpOiB2b2lkIHtcbiAgICBMT0dfREVCVUcoJ2luZm8nLCAncmVwbGF5Jyk7XG4gICAgdGhpcy5zZXNzaW9uU3RhdHVzID0gJ3JlcGxheWluZyc7XG4gICAgY29uc3Qgc2Vzc2lvbkNvbW1hbmRMaXN0ID0gdGhpcy5jYXB0dXJlZENvbW1hbmRMaXN0LmdldCh0aGlzLmN1cnJlbnRTZXNzaW9uSWQhKTtcbiAgICBjb25zdCBzZXNzaW9uUGVuZGluZ0tlcm5lbHMgPSB0aGlzLmNhcHR1cmVkUGVuZGluZ0tlcm5lbHMuZ2V0KHRoaXMuY3VycmVudFNlc3Npb25JZCEpO1xuICAgIGNvbnN0IGxlbmd0aCA9IHNlc3Npb25Db21tYW5kTGlzdCEubGVuZ3RoO1xuICAgIHRoaXMucGVuZGluZ0tlcm5lbHMgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBjb21wdXRlUGFzc0VuY29kZXIgPSB0aGlzLmdldENvbXB1dGVQYXNzRW5jb2RlcigpO1xuICAgICAgY29uc3QgY29tbWFuZCA9IHNlc3Npb25Db21tYW5kTGlzdCFbaV07XG4gICAgICB0aGlzLndyaXRlVGltZXN0YW1wKHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMik7XG4gICAgICBjb21wdXRlUGFzc0VuY29kZXIuc2V0UGlwZWxpbmUoY29tbWFuZC5jb21wdXRlUGlwZWxpbmUpO1xuICAgICAgY29tcHV0ZVBhc3NFbmNvZGVyLnNldEJpbmRHcm91cCgwLCBjb21tYW5kLmJpbmRHcm91cCk7XG4gICAgICBjb21wdXRlUGFzc0VuY29kZXIuZGlzcGF0Y2hXb3JrZ3JvdXBzKC4uLmNvbW1hbmQuZGlzcGF0Y2hHcm91cCk7XG4gICAgICB0aGlzLndyaXRlVGltZXN0YW1wKHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMiArIDEpO1xuICAgICAgdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIrKztcbiAgICAgIGlmICh0aGlzLnF1ZXJ5VHlwZSAhPT0gJ25vbmUnKSB7XG4gICAgICAgIHRoaXMucGVuZGluZ0tlcm5lbHMucHVzaChzZXNzaW9uUGVuZGluZ0tlcm5lbHMhW2ldKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLnBlbmRpbmdEaXNwYXRjaE51bWJlciA+PSB0aGlzLm1heERpc3BhdGNoTnVtYmVyIHx8IHRoaXMucXVlcnlUeXBlID09PSAnYXQtcGFzc2VzJykge1xuICAgICAgICB0aGlzLmVuZENvbXB1dGVQYXNzKCk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgPj0gdGhpcy5tYXhEaXNwYXRjaE51bWJlcikge1xuICAgICAgICB0aGlzLmZsdXNoKCk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIGZsdXNoIHRoZSBsZWZ0IGNvbW1hbmRzIGJlZm9yZSB3ZSBjaGFuZ2UgdGhlIHN0YXR1cy5cbiAgICB0aGlzLmZsdXNoKCk7XG4gICAgdGhpcy5zZXNzaW9uU3RhdHVzID0gJ2RlZmF1bHQnO1xuICB9XG5cbiAgb25DcmVhdGVTZXNzaW9uKCk6IHZvaWQge1xuICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIub25DcmVhdGVTZXNzaW9uKCk7XG4gIH1cblxuICBvblJlbGVhc2VTZXNzaW9uKHNlc3Npb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy51bnJlZ2lzdGVyQnVmZmVycyhzZXNzaW9uSWQpO1xuICAgIGlmICh0aGlzLmNhcHR1cmVkQ29tbWFuZExpc3QuaGFzKHNlc3Npb25JZCkpIHtcbiAgICAgIHRoaXMuY2FwdHVyZWRDb21tYW5kTGlzdC5kZWxldGUoc2Vzc2lvbklkKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuY2FwdHVyZWRQZW5kaW5nS2VybmVscy5oYXMoc2Vzc2lvbklkKSkge1xuICAgICAgdGhpcy5jYXB0dXJlZFBlbmRpbmdLZXJuZWxzLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIH1cbiAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLm9uUmVsZWFzZVNlc3Npb24oc2Vzc2lvbklkKTtcbiAgfVxuXG4gIG9uUnVuU3RhcnQoc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRTZXNzaW9uSWQgPSBzZXNzaW9uSWQ7XG4gICAgdGhpcy5zZXRRdWVyeVR5cGUoKTtcbiAgfVxufVxuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgdHlwZSB7IEVudiB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzLCBEYXRhVHlwZSB9IGZyb20gJy4uL3dhc20tY29tbW9uJztcblxuaW1wb3J0IHR5cGUgeyBPcnRXYXNtTW9kdWxlIH0gZnJvbSAnLi4vd2FzbS10eXBlcyc7XG5cbmltcG9ydCB0eXBlIHsgV2ViR3B1QmFja2VuZCB9IGZyb20gJy4vYmFja2VuZC13ZWJncHUnO1xuaW1wb3J0IHsgTE9HX0RFQlVHIH0gZnJvbSAnLi9sb2cnO1xuaW1wb3J0IHR5cGUgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuL3V0aWwnO1xuaW1wb3J0IHR5cGUgeyBBZGFwdGVySW5mbywgQ29tcHV0ZUNvbnRleHQsIENvbXB1dGVDb250ZXh0SW5wdXRzT3V0cHV0c01hcHBpbmcsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi93ZWJncHUvdHlwZXMnO1xuaW1wb3J0IHsgV2ViTk5CYWNrZW5kIH0gZnJvbSAnLi9iYWNrZW5kLXdlYm5uJztcblxuLyogZXNsaW50LWRpc2FibGUgbm8tYml0d2lzZSAqL1xuXG5jbGFzcyBUZW5zb3JWaWV3SW1wbCBpbXBsZW1lbnRzIFRlbnNvclZpZXcge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIG1vZHVsZTogT3J0V2FzbU1vZHVsZSxcbiAgICBwdWJsaWMgcmVhZG9ubHkgZGF0YVR5cGU6IG51bWJlcixcbiAgICBwdWJsaWMgcmVhZG9ubHkgZGF0YTogbnVtYmVyLFxuICAgIHB1YmxpYyByZWFkb25seSBkaW1zOiByZWFkb25seSBudW1iZXJbXSxcbiAgKSB7fVxuXG4gIGdldEZsb2F0MzJBcnJheSgpOiBGbG9hdDMyQXJyYXkge1xuICAgIGlmICh0aGlzLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5mbG9hdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRhdGEgdHlwZScpO1xuICAgIH1cbiAgICBjb25zdCBlbGVtZW50Q291bnQgPSBTaGFwZVV0aWwuc2l6ZSh0aGlzLmRpbXMpO1xuICAgIHJldHVybiBlbGVtZW50Q291bnQgPT09IDBcbiAgICAgID8gbmV3IEZsb2F0MzJBcnJheSgpXG4gICAgICA6IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5tb2R1bGUuSEVBUDguYnVmZmVyLCB0aGlzLmRhdGEsIGVsZW1lbnRDb3VudCk7XG4gIH1cblxuICBnZXRCaWdJbnQ2NEFycmF5KCk6IEJpZ0ludDY0QXJyYXkge1xuICAgIGlmICh0aGlzLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5pbnQ2NCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRhdGEgdHlwZScpO1xuICAgIH1cbiAgICBjb25zdCBlbGVtZW50Q291bnQgPSBTaGFwZVV0aWwuc2l6ZSh0aGlzLmRpbXMpO1xuICAgIHJldHVybiBlbGVtZW50Q291bnQgPT09IDBcbiAgICAgID8gbmV3IEJpZ0ludDY0QXJyYXkoKVxuICAgICAgOiBuZXcgQmlnSW50NjRBcnJheSh0aGlzLm1vZHVsZS5IRUFQOC5idWZmZXIsIHRoaXMuZGF0YSwgZWxlbWVudENvdW50KTtcbiAgfVxuXG4gIGdldEludDMyQXJyYXkoKTogSW50MzJBcnJheSB7XG4gICAgaWYgKHRoaXMuZGF0YVR5cGUgIT09IERhdGFUeXBlLmludDMyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZGF0YSB0eXBlJyk7XG4gICAgfVxuICAgIGNvbnN0IGVsZW1lbnRDb3VudCA9IFNoYXBlVXRpbC5zaXplKHRoaXMuZGltcyk7XG4gICAgcmV0dXJuIGVsZW1lbnRDb3VudCA9PT0gMCA/IG5ldyBJbnQzMkFycmF5KCkgOiBuZXcgSW50MzJBcnJheSh0aGlzLm1vZHVsZS5IRUFQOC5idWZmZXIsIHRoaXMuZGF0YSwgZWxlbWVudENvdW50KTtcbiAgfVxuXG4gIGdldFVpbnQxNkFycmF5KCk6IFVpbnQxNkFycmF5IHtcbiAgICBpZiAodGhpcy5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQxNiAmJiB0aGlzLmRhdGFUeXBlICE9PSBEYXRhVHlwZS51aW50MTYpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBkYXRhIHR5cGUnKTtcbiAgICB9XG4gICAgY29uc3QgZWxlbWVudENvdW50ID0gU2hhcGVVdGlsLnNpemUodGhpcy5kaW1zKTtcbiAgICByZXR1cm4gZWxlbWVudENvdW50ID09PSAwID8gbmV3IFVpbnQxNkFycmF5KCkgOiBuZXcgVWludDE2QXJyYXkodGhpcy5tb2R1bGUuSEVBUDguYnVmZmVyLCB0aGlzLmRhdGEsIGVsZW1lbnRDb3VudCk7XG4gIH1cblxuICByZXNoYXBlKG5ld0RpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yVmlldyB7XG4gICAgaWYgKFNoYXBlVXRpbC5zaXplKG5ld0RpbXMpICE9PSBTaGFwZVV0aWwuc2l6ZSh0aGlzLmRpbXMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgbmV3IHNoYXBlJyk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgVGVuc29yVmlld0ltcGwodGhpcy5tb2R1bGUsIHRoaXMuZGF0YVR5cGUsIHRoaXMuZGF0YSwgbmV3RGltcyk7XG4gIH1cbn1cblxuY2xhc3MgQ29tcHV0ZUNvbnRleHRJbXBsIGltcGxlbWVudHMgQ29tcHV0ZUNvbnRleHQge1xuICByZWFkb25seSBhZGFwdGVySW5mbzogQWRhcHRlckluZm87XG4gIHJlYWRvbmx5IG9wS2VybmVsQ29udGV4dDogbnVtYmVyO1xuICByZWFkb25seSBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXTtcbiAgcmVhZG9ubHkgb3V0cHV0Q291bnQ6IG51bWJlcjtcbiAgZ2V0IGtlcm5lbEN1c3RvbURhdGEoKTogeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0ge1xuICAgIHJldHVybiB0aGlzLmJhY2tlbmQuY3VycmVudEtlcm5lbEN1c3RvbURhdGE7XG4gIH1cbiAgZ2V0IGN1c3RvbURhdGFCdWZmZXIoKTogVWludDhBcnJheSB7XG4gICAgcmV0dXJuIHRoaXMubW9kdWxlLkhFQVBVOC5zdWJhcnJheSh0aGlzLmN1c3RvbURhdGFPZmZzZXQsIHRoaXMuY3VzdG9tRGF0YU9mZnNldCArIHRoaXMuY3VzdG9tRGF0YVNpemUpO1xuICB9XG4gIHByaXZhdGUgY3VzdG9tRGF0YU9mZnNldCA9IDA7XG4gIHByaXZhdGUgY3VzdG9tRGF0YVNpemUgPSAwO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIG1vZHVsZTogT3J0V2FzbU1vZHVsZSxcbiAgICBwcml2YXRlIGJhY2tlbmQ6IFdlYkdwdUJhY2tlbmQsXG4gICAgY29udGV4dERhdGFPZmZzZXQ6IG51bWJlcixcbiAgKSB7XG4gICAgdGhpcy5hZGFwdGVySW5mbyA9IGJhY2tlbmQuYWRhcHRlckluZm87XG5cbiAgICAvLyBleHRyYWN0IGNvbnRleHQgZGF0YVxuICAgIGNvbnN0IHB0clNpemUgPSBtb2R1bGUuUFRSX1NJWkU7XG4gICAgbGV0IGRhdGFJbmRleCA9IGNvbnRleHREYXRhT2Zmc2V0IC8gbW9kdWxlLlBUUl9TSVpFO1xuICAgIGNvbnN0IHR5cGUgPSBwdHJTaXplID09PSA0ID8gJ2kzMicgOiAnaTY0JztcbiAgICB0aGlzLm9wS2VybmVsQ29udGV4dCA9IE51bWJlcihtb2R1bGUuZ2V0VmFsdWUocHRyU2l6ZSAqIGRhdGFJbmRleCsrLCB0eXBlKSk7XG4gICAgY29uc3QgaW5wdXRDb3VudCA9IE51bWJlcihtb2R1bGUuZ2V0VmFsdWUocHRyU2l6ZSAqIGRhdGFJbmRleCsrLCB0eXBlKSk7XG4gICAgdGhpcy5vdXRwdXRDb3VudCA9IE51bWJlcihtb2R1bGUuZ2V0VmFsdWUocHRyU2l6ZSAqIGRhdGFJbmRleCsrLCB0eXBlKSk7XG4gICAgdGhpcy5jdXN0b21EYXRhT2Zmc2V0ID0gTnVtYmVyKG1vZHVsZS5nZXRWYWx1ZShwdHJTaXplICogZGF0YUluZGV4KyssICcqJykpO1xuICAgIHRoaXMuY3VzdG9tRGF0YVNpemUgPSBOdW1iZXIobW9kdWxlLmdldFZhbHVlKHB0clNpemUgKiBkYXRhSW5kZXgrKywgdHlwZSkpO1xuXG4gICAgY29uc3QgaW5wdXRzOiBUZW5zb3JWaWV3W10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Q291bnQ7IGkrKykge1xuICAgICAgY29uc3QgZGF0YVR5cGUgPSBOdW1iZXIobW9kdWxlLmdldFZhbHVlKHB0clNpemUgKiBkYXRhSW5kZXgrKywgdHlwZSkpO1xuICAgICAgY29uc3QgZGF0YSA9IE51bWJlcihtb2R1bGUuZ2V0VmFsdWUocHRyU2l6ZSAqIGRhdGFJbmRleCsrLCAnKicpKTtcbiAgICAgIGNvbnN0IGRpbSA9IE51bWJlcihtb2R1bGUuZ2V0VmFsdWUocHRyU2l6ZSAqIGRhdGFJbmRleCsrLCB0eXBlKSk7XG4gICAgICBjb25zdCBkaW1zOiBudW1iZXJbXSA9IFtdO1xuICAgICAgZm9yIChsZXQgZCA9IDA7IGQgPCBkaW07IGQrKykge1xuICAgICAgICBkaW1zLnB1c2goTnVtYmVyKG1vZHVsZS5nZXRWYWx1ZShwdHJTaXplICogZGF0YUluZGV4KyssIHR5cGUpKSk7XG4gICAgICB9XG4gICAgICBpbnB1dHMucHVzaChuZXcgVGVuc29yVmlld0ltcGwobW9kdWxlLCBkYXRhVHlwZSwgZGF0YSwgZGltcykpO1xuICAgIH1cbiAgICB0aGlzLmlucHV0cyA9IGlucHV0cztcbiAgfVxuXG4gIGNvbXB1dGUocHJvZ3JhbTogUHJvZ3JhbUluZm8sIGlucHV0c091dHB1dHNNYXBwaW5nPzogQ29tcHV0ZUNvbnRleHRJbnB1dHNPdXRwdXRzTWFwcGluZyk6IFRlbnNvclZpZXdbXSB7XG4gICAgLy8gcHJlcGFyZSBpbnB1dHMuIGlucHV0cyBzaG91bGQgYWx3YXlzIGJlIHZhbGlkIGRhdGEuXG4gICAgY29uc3QgbWFwcGVkSW5wdXRzID1cbiAgICAgIGlucHV0c091dHB1dHNNYXBwaW5nPy5pbnB1dHM/Lm1hcCgoaSkgPT4gKHR5cGVvZiBpID09PSAnbnVtYmVyJyA/IHRoaXMuaW5wdXRzW2ldIDogaSkpID8/IHRoaXMuaW5wdXRzO1xuICAgIC8vIHByZXBhcmUgb3V0cHV0cy5cbiAgICBjb25zdCBvdXRwdXRJbmRpY2VzID0gaW5wdXRzT3V0cHV0c01hcHBpbmc/Lm91dHB1dHMgPz8gW107XG4gICAgY29uc3QgY3JlYXRlS2VybmVsT3V0cHV0ID0gKGluZGV4OiBudW1iZXIsIGRhdGFUeXBlOiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yVmlldyA9PlxuICAgICAgbmV3IFRlbnNvclZpZXdJbXBsKHRoaXMubW9kdWxlLCBkYXRhVHlwZSwgdGhpcy5vdXRwdXQoaW5kZXgsIGRpbXMpLCBkaW1zKTtcbiAgICBjb25zdCBjcmVhdGVUZW1wb3JhcnlPdXRwdXQgPSAoZGF0YVR5cGU6IG51bWJlciwgZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3JWaWV3ID0+IHtcbiAgICAgIGNvbnN0IGJ1ZmZlclNpemUgPSBjYWxjdWxhdGVUZW5zb3JTaXplSW5CeXRlcyhkYXRhVHlwZSwgZGltcyk7XG4gICAgICBpZiAoIWJ1ZmZlclNpemUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZGF0YVR5cGV9YCk7XG4gICAgICB9XG4gICAgICBjb25zdCBncHVEYXRhSWQgPSBidWZmZXJTaXplID4gMCA/IHRoaXMuYmFja2VuZC5ncHVEYXRhTWFuYWdlci5jcmVhdGUoYnVmZmVyU2l6ZSkuaWQgOiAwO1xuICAgICAgcmV0dXJuIG5ldyBUZW5zb3JWaWV3SW1wbCh0aGlzLm1vZHVsZSwgZGF0YVR5cGUsIGdwdURhdGFJZCwgZGltcyk7XG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5iYWNrZW5kLnJ1bihcbiAgICAgIHByb2dyYW0sXG4gICAgICBtYXBwZWRJbnB1dHMsXG4gICAgICBvdXRwdXRJbmRpY2VzLFxuICAgICAgY3JlYXRlS2VybmVsT3V0cHV0LFxuICAgICAgY3JlYXRlVGVtcG9yYXJ5T3V0cHV0LFxuICAgICAgdGhpcy5vdXRwdXRDb3VudCxcbiAgICApO1xuICB9XG5cbiAgb3V0cHV0KGluZGV4OiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICBjb25zdCBzdGFjayA9IHRoaXMubW9kdWxlLnN0YWNrU2F2ZSgpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwdHJTaXplID0gdGhpcy5tb2R1bGUuUFRSX1NJWkU7XG4gICAgICBjb25zdCB0eXBlID0gcHRyU2l6ZSA9PT0gNCA/ICdpMzInIDogJ2k2NCc7XG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5tb2R1bGUuc3RhY2tBbGxvYygoMSArIGRpbXMubGVuZ3RoKSAqIHB0clNpemUgLyogc2l6ZW9mKHNpemVfdCkgKi8pO1xuICAgICAgdGhpcy5tb2R1bGUuc2V0VmFsdWUoZGF0YSwgZGltcy5sZW5ndGgsIHR5cGUpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMubW9kdWxlLnNldFZhbHVlKGRhdGEgKyBwdHJTaXplICogKGkgKyAxKSwgZGltc1tpXSwgdHlwZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5tb2R1bGUuX0pzZXBPdXRwdXQhKHRoaXMub3BLZXJuZWxDb250ZXh0LCBpbmRleCwgZGF0YSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIGdlbmVyYXRlIGtlcm5lbCdzIG91dHB1dFske2luZGV4fV0gd2l0aCBkaW1zIFske2RpbXN9XS4gYCArXG4gICAgICAgICAgJ0lmIHlvdSBhcmUgcnVubmluZyB3aXRoIHByZS1hbGxvY2F0ZWQgb3V0cHV0LCBwbGVhc2UgbWFrZSBzdXJlIHRoZSBvdXRwdXQgdHlwZS9kaW1zIGFyZSBjb3JyZWN0LiAnICtcbiAgICAgICAgICBgRXJyb3I6ICR7ZX1gLFxuICAgICAgKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5tb2R1bGUuc3RhY2tSZXN0b3JlKHN0YWNrKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBJbml0aWFsaXplIEpTRVAgd2l0aCBXZWJHUFUgYmFja2VuZC5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGFmdGVyIHRoZSBXZWJBc3NlbWJseSBtb2R1bGUgaXMgbG9hZGVkIGFuZCBpbml0aWFsaXplZCAoXCJfT3J0SW5pdFwiIGlzIGNhbGxlZCksIG9uY2UgZm9yXG4gKiBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgRVBzIGlmIHRoZXkgYXJlIHNwZWNpZmllZDpcbiAqIC0gXCJ3ZWJncHVcIlxuICogLSBcIndlYm5uXCJcbiAqXG4gKiBGb3IgV2ViR1BVLCB0aGlzIGZ1bmN0aW9uIGV4cGVjdHM6XG4gKiAgLSBXZWJHUFUgaXMgZW5hYmxlZCBpbiBidWlsZCAoQlVJTERfREVGUy5ESVNBQkxFX0pTRVAgPT09IGZhbHNlKS5cbiAqICAtIFdlYkdQVSBpcyBhdmFpbGFibGUgaW4gY3VycmVudCBlbnZpcm9ubWVudC4gKGEgdmFsaWQgR1BVQWRhcHRlciBpcyBwYXNzZWQgaW4pXG4gKlxuICogRm9yIFdlYk5OLCB0aGlzIGZ1bmN0aW9uIGV4cGVjdHM6XG4gKiAtIFdlYk5OIGlzIGVuYWJsZWQgaW4gYnVpbGQgKEJVSUxEX0RFRlMuRElTQUJMRV9KU0VQID09PSBmYWxzZSkuXG4gKiAtIFdlYk5OIGlzIGF2YWlsYWJsZSBpbiBjdXJyZW50IGVudmlyb25tZW50LiAobmF2aWdhdG9yLm1sIGlzIG5vdCB1bmRlZmluZWQpXG4gKlxuICogSWYgdGhlIFdlYkFzc2VtYmx5IG1vZHVsZSBpcyBub3QgYnVpbHQgd2l0aCBKU0VQIHN1cHBvcnQsIHRoaXMgZnVuY3Rpb24gd2lsbCB0aHJvdyBhbiBlcnJvci4gVGhpcyB3aWxsIGludmFsaWRhdGVcbiAqICd3ZWJncHUnLyd3ZWJubicgYmFja2VuZC5cbiAqXG4gKiBAcGFyYW0gbmFtZSAtIHRoZSBuYW1lIG9mIHRoZSBFUCwgZWl0aGVyIFwid2ViZ3B1XCIgb3IgXCJ3ZWJublwiXG4gKiBAcGFyYW0gbW9kdWxlIC0gdGhlIE9SVCBXZWJBc3NlbWJseSBtb2R1bGVcbiAqIEBwYXJhbSBlbnYgLSB0aGUgT1JUIGVudmlyb25tZW50IHZhcmlhYmxlIChvcnQuZW52KVxuICogQHBhcmFtIGdwdUFkYXB0ZXIgLSB0aGUgcHJlLWNyZWF0ZWQgR1BVIGFkYXB0ZXJcbiAqL1xuZXhwb3J0IGNvbnN0IGluaXQgPSBhc3luYyAoXG4gIG5hbWU6ICd3ZWJncHUnIHwgJ3dlYm5uJyxcbiAgbW9kdWxlOiBPcnRXYXNtTW9kdWxlLFxuICBlbnY6IEVudixcbiAgZ3B1QWRhcHRlcj86IEdQVUFkYXB0ZXIsXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgY29uc3QganNlcEluaXQgPSBtb2R1bGUuanNlcEluaXQ7XG4gIGlmICghanNlcEluaXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBpbml0aWFsaXplIEpTRVAuIFRoZSBXZWJBc3NlbWJseSBtb2R1bGUgaXMgbm90IGJ1aWx0IHdpdGggSlNFUCBzdXBwb3J0LicpO1xuICB9XG5cbiAgaWYgKG5hbWUgPT09ICd3ZWJncHUnKSB7XG4gICAgaWYgKCFCVUlMRF9ERUZTLlVTRV9XRUJHUFVfRVApIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgICBjb25zdCB3ZWJHcHVCYWNrZW5kSW1wbCA9IHJlcXVpcmUoJy4vYmFja2VuZC13ZWJncHUnKS5XZWJHcHVCYWNrZW5kO1xuICAgICAgY29uc3QgYmFja2VuZCA9IG5ldyB3ZWJHcHVCYWNrZW5kSW1wbCgpO1xuICAgICAgYXdhaXQgYmFja2VuZC5pbml0aWFsaXplKGVudiwgZ3B1QWRhcHRlciEpO1xuXG4gICAgICBqc2VwSW5pdCgnd2ViZ3B1JywgW1xuICAgICAgICAvLyBiYWNrZW5kXG4gICAgICAgIGJhY2tlbmQsXG5cbiAgICAgICAgLy8ganNlcEFsbG9jKClcbiAgICAgICAgKHNpemU6IG51bWJlcikgPT4gYmFja2VuZC5hbGxvYyhOdW1iZXIoc2l6ZSkpLFxuXG4gICAgICAgIC8vIGpzZXBGcmVlKClcbiAgICAgICAgKHB0cjogbnVtYmVyKSA9PiBiYWNrZW5kLmZyZWUocHRyKSxcblxuICAgICAgICAvLyBqc2VwQ29weShzcmMsIGRzdCwgc2l6ZSwgaXNTb3VyY2VHcHUpXG4gICAgICAgIChzcmM6IG51bWJlciwgZHN0OiBudW1iZXIsIHNpemU6IG51bWJlciwgaXNTb3VyY2VHcHUgPSBmYWxzZSkgPT4ge1xuICAgICAgICAgIGlmIChpc1NvdXJjZUdwdSkge1xuICAgICAgICAgICAgTE9HX0RFQlVHKFxuICAgICAgICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICAgICAgICgpID0+IGBbV2ViR1BVXSBqc2VwQ29weUdwdVRvR3B1OiBzcmM9JHtOdW1iZXIoc3JjKX0sIGRzdD0ke051bWJlcihkc3QpfSwgc2l6ZT0ke051bWJlcihzaXplKX1gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGJhY2tlbmQubWVtY3B5KE51bWJlcihzcmMpLCBOdW1iZXIoZHN0KSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExPR19ERUJVRyhcbiAgICAgICAgICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgICAgIGBbV2ViR1BVXSBqc2VwQ29weUNwdVRvR3B1OiBkYXRhT2Zmc2V0PSR7TnVtYmVyKHNyYyl9LCBncHVEYXRhSWQ9JHtOdW1iZXIoZHN0KX0sIHNpemU9JHtOdW1iZXIoc2l6ZSl9YCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0gbW9kdWxlLkhFQVBVOC5zdWJhcnJheShOdW1iZXIoc3JjID4+PiAwKSwgTnVtYmVyKHNyYyA+Pj4gMCkgKyBOdW1iZXIoc2l6ZSkpO1xuICAgICAgICAgICAgYmFja2VuZC51cGxvYWQoTnVtYmVyKGRzdCksIGRhdGEpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICAvLyBqc2VwQ29weUFzeW5jKHNyYywgZHN0LCBzaXplKVxuICAgICAgICBhc3luYyAoZ3B1RGF0YUlkOiBudW1iZXIsIGRhdGFPZmZzZXQ6IG51bWJlciwgc2l6ZTogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgTE9HX0RFQlVHKFxuICAgICAgICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgICAgICAgKCkgPT4gYFtXZWJHUFVdIGpzZXBDb3B5R3B1VG9DcHU6IGdwdURhdGFJZD0ke2dwdURhdGFJZH0sIGRhdGFPZmZzZXQ9JHtkYXRhT2Zmc2V0fSwgc2l6ZT0ke3NpemV9YCxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgYXdhaXQgYmFja2VuZC5kb3dubG9hZChOdW1iZXIoZ3B1RGF0YUlkKSwgKCkgPT5cbiAgICAgICAgICAgIG1vZHVsZS5IRUFQVTguc3ViYXJyYXkoTnVtYmVyKGRhdGFPZmZzZXQpID4+PiAwLCBOdW1iZXIoZGF0YU9mZnNldCArIHNpemUpID4+PiAwKSxcbiAgICAgICAgICApO1xuICAgICAgICB9LFxuXG4gICAgICAgIC8vIGpzZXBDcmVhdGVLZXJuZWxcbiAgICAgICAgKGtlcm5lbFR5cGU6IHN0cmluZywga2VybmVsSWQ6IG51bWJlciwgYXR0cmlidXRlOiB1bmtub3duKSA9PlxuICAgICAgICAgIGJhY2tlbmQuY3JlYXRlS2VybmVsKFxuICAgICAgICAgICAga2VybmVsVHlwZSxcbiAgICAgICAgICAgIE51bWJlcihrZXJuZWxJZCksXG4gICAgICAgICAgICBhdHRyaWJ1dGUsXG4gICAgICAgICAgICBtb2R1bGUuVVRGOFRvU3RyaW5nKG1vZHVsZS5fSnNlcEdldE5vZGVOYW1lIShOdW1iZXIoa2VybmVsSWQpKSksXG4gICAgICAgICAgKSxcblxuICAgICAgICAvLyBqc2VwUmVsZWFzZUtlcm5lbFxuICAgICAgICAoa2VybmVsOiBudW1iZXIpID0+IGJhY2tlbmQucmVsZWFzZUtlcm5lbChrZXJuZWwpLFxuXG4gICAgICAgIC8vIGpzZXBSdW5cbiAgICAgICAgKGtlcm5lbDogbnVtYmVyLCBjb250ZXh0RGF0YU9mZnNldDogbnVtYmVyLCBzZXNzaW9uSGFuZGxlOiBudW1iZXIsIGVycm9yczogQXJyYXk8UHJvbWlzZTxzdHJpbmcgfCBudWxsPj4pID0+IHtcbiAgICAgICAgICBMT0dfREVCVUcoXG4gICAgICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgICBgW1dlYkdQVV0ganNlcFJ1bjogc2Vzc2lvbkhhbmRsZT0ke3Nlc3Npb25IYW5kbGV9LCBrZXJuZWw9JHtrZXJuZWx9LCBjb250ZXh0RGF0YU9mZnNldD0ke2NvbnRleHREYXRhT2Zmc2V0fWAsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBjb250ZXh0ID0gbmV3IENvbXB1dGVDb250ZXh0SW1wbChtb2R1bGUsIGJhY2tlbmQsIE51bWJlcihjb250ZXh0RGF0YU9mZnNldCkpO1xuICAgICAgICAgIHJldHVybiBiYWNrZW5kLmNvbXB1dGVLZXJuZWwoTnVtYmVyKGtlcm5lbCksIGNvbnRleHQsIGVycm9ycyk7XG4gICAgICAgIH0sXG4gICAgICAgIC8vIGpzZXBDYXB0dXJlQmVnaW5cbiAgICAgICAgKCkgPT4gYmFja2VuZC5jYXB0dXJlQmVnaW4oKSxcbiAgICAgICAgLy8ganNlcENhcHR1cmVFbmRcbiAgICAgICAgKCkgPT4gYmFja2VuZC5jYXB0dXJlRW5kKCksXG4gICAgICAgIC8vIGpzZXBSZXBsYXlcbiAgICAgICAgKCkgPT4gYmFja2VuZC5yZXBsYXkoKSxcbiAgICAgIF0pO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjb25zdCBiYWNrZW5kID0gbmV3IFdlYk5OQmFja2VuZChlbnYpO1xuICAgIGpzZXBJbml0KCd3ZWJubicsIFtcbiAgICAgIGJhY2tlbmQsXG4gICAgICAvLyBqc2VwUmVzZXJ2ZVRlbnNvcklkXG4gICAgICAoKSA9PiBiYWNrZW5kLnJlc2VydmVUZW5zb3JJZCgpLFxuICAgICAgLy8ganNlcFJlbGVhc2VUZW5zb3JJZCxcbiAgICAgICh0ZW5zb3JJZDogbnVtYmVyKSA9PiBiYWNrZW5kLnJlbGVhc2VUZW5zb3JJZCh0ZW5zb3JJZCksXG4gICAgICAvLyBqc2VwRW5zdXJlVGVuc29yXG4gICAgICBhc3luYyAoc2Vzc2lvbklkOiBudW1iZXIgfCB1bmRlZmluZWQsIHRlbnNvcklkOiBudW1iZXIsIG9ubnhEYXRhVHlwZTogbnVtYmVyLCBzaGFwZTogbnVtYmVyW10sIGNvcHlPbGQpID0+XG4gICAgICAgIGJhY2tlbmQuZW5zdXJlVGVuc29yKHNlc3Npb25JZCwgdGVuc29ySWQsIG9ubnhEYXRhVHlwZSwgc2hhcGUsIGNvcHlPbGQpLFxuICAgICAgLy8ganNlcFVwbG9hZFRlbnNvclxuICAgICAgKHRlbnNvcklkOiBudW1iZXIsIGRhdGE6IFVpbnQ4QXJyYXkpID0+IHtcbiAgICAgICAgYmFja2VuZC51cGxvYWRUZW5zb3IodGVuc29ySWQsIGRhdGEpO1xuICAgICAgfSxcbiAgICAgIC8vIGpzZXBEb3dubG9hZFRlbnNvclxuICAgICAgYXN5bmMgKHRlbnNvcklkOiBudW1iZXIsIGRzdEJ1ZmZlcjogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpID0+IGJhY2tlbmQuZG93bmxvYWRUZW5zb3IodGVuc29ySWQsIGRzdEJ1ZmZlciksXG4gICAgXSk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8vIFdlYk5OIEFQSSBjdXJyZW50bHkgZG9lcyBub3QgaGF2ZSBhIFR5cGVTY3JpcHQgZGVmaW5pdGlvbiBmaWxlLiBUaGlzIGZpbGUgaXMgYSB3b3JrYXJvdW5kIHdpdGggdHlwZXMgZ2VuZXJhdGVkIGZyb21cbi8vIFdlYk5OIEFQSSBzcGVjaWZpY2F0aW9uLlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3dlYm1hY2hpbmVsZWFybmluZy93ZWJubi9pc3N1ZXMvNjc3XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwianNlcC93ZWJubi93ZWJubi5kLnRzXCIgLz5cblxuaW1wb3J0IHsgRW52LCBJbmZlcmVuY2VTZXNzaW9uLCBUZW5zb3IgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge1xuICBTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlcixcbiAgU2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhLFxuICBTZXJpYWxpemFibGVUZW5zb3JNZXRhZGF0YSxcbiAgVGVuc29yTWV0YWRhdGEsXG59IGZyb20gJy4vcHJveHktbWVzc2FnZXMnO1xuaW1wb3J0IHsgc2V0UnVuT3B0aW9ucyB9IGZyb20gJy4vcnVuLW9wdGlvbnMnO1xuaW1wb3J0IHsgc2V0U2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuL3Nlc3Npb24tb3B0aW9ucyc7XG5pbXBvcnQge1xuICBjYWxjdWxhdGVUZW5zb3JTaXplSW5CeXRlcyxcbiAgZGF0YUxvY2F0aW9uU3RyaW5nVG9FbnVtLFxuICBpc0dwdUJ1ZmZlclN1cHBvcnRlZFR5cGUsXG4gIGlzTUxUZW5zb3JTdXBwb3J0ZWRUeXBlLFxuICBsb2dMZXZlbFN0cmluZ1RvRW51bSxcbiAgdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcsXG4gIHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtLFxuICB0ZW5zb3JUeXBlVG9UeXBlZEFycmF5Q29uc3RydWN0b3IsXG59IGZyb20gJy4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgZ2V0SW5zdGFuY2UgfSBmcm9tICcuL3dhc20tZmFjdG9yeSc7XG5pbXBvcnQgeyBhbGxvY1dhc21TdHJpbmcsIGNoZWNrTGFzdEVycm9yIH0gZnJvbSAnLi93YXNtLXV0aWxzJztcbmltcG9ydCB7IGxvYWRGaWxlIH0gZnJvbSAnLi93YXNtLXV0aWxzLWxvYWQtZmlsZSc7XG5cbi8vICNyZWdpb24gSW5pdGlhbGl6YXRpb25zXG5cbi8qKlxuICogVGhlcmUgYXJlIDQgZGlmZmVyZW50IFwiaW5pdGlhbGl6YXRpb25cIiBzdGVwcyBmb3IgT1JULiBUaGV5IGhhcHBlbiBpbiBkaWZmZXJlbnQgcGxhY2VzIGFuZCBkaWZmZXJlbnQgdGltZS5cbiAqXG4gKiAxLiBKYXZhU2NyaXB0IGluaXRpYWxpemF0aW9uIGZvciBvbm54cnVudGltZS1jb21tb24gYW5kIG9ubnhydW50aW1lLXdlYi5cbiAqICAgIFRoaXMgaXMgdGhlIGZpcnN0IGluaXRpYWxpemF0aW9uIHN0ZXAuIEluIHRoaXMgc3RlcCwgb25ueHJ1bnRpbWUtd2ViIGNhbGxzIG9ubnhydW50aW1lLWNvbW1vbidzIHJlZ2lzdGVyQmFja2VuZCgpXG4gKiBmdW5jdGlvbiBtdWx0aXBsZSB0aW1lcyB0byByZWdpc3RlciBhbGwgdGhlIGF2YWlsYWJsZSBiYWNrZW5kcy4gVGhlIGJhY2tlbmQgcmVnaXN0cmF0aW9uIGlzIHZlcnkgZmFzdC4gSXQgb25seVxuICogcmVnaXN0ZXJzIHRoZSBiYWNrZW5kIG5hbWUgd2l0aCB0aGUgdW5pbml0aWFsaXplZCBiYWNrZW5kIG9iamVjdC4gTm8gaGVhdnkgaW5pdGlhbGl6YXRpb24gaXMgZG9uZSBpbiB0aGlzIHN0ZXAuXG4gKiAgICBSZWZlciB0byB3ZWIvbGliL2luZGV4LnRzIGZvciB0aGUgYmFja2VuZCByZWdpc3RyYXRpb24uXG4gKlxuICogMi4gV2ViQXNzZW1ibHkgYXJ0aWZhY3QgaW5pdGlhbGl6YXRpb24uXG4gKiAgICBUaGlzIGhhcHBlbnMgd2hlbiBhbnkgcmVnaXN0ZXJlZCB3YXNtIGJhY2tlbmQgaXMgdXNlZCBmb3IgdGhlIGZpcnN0IHRpbWUgKGllLiBgb3J0LkluZmVyZW5jZVNlc3Npb24uY3JlYXRlKClgIGlzXG4gKiBjYWxsZWQpLiBJbiB0aGlzIHN0ZXAsIG9ubnhydW50aW1lLXdlYiBkb2VzIHRoZSBmb2xsb3dpbmdzOlxuICogICAgIC0gY3JlYXRlIGEgcHJveHkgd29ya2VyIGFuZCBtYWtlIHN1cmUgdGhlIHByb3h5IHdvcmtlciBpcyByZWFkeSB0byByZWNlaXZlIG1lc3NhZ2VzLCBpZiBwcm94eSBpcyBlbmFibGVkLlxuICogICAgIC0gcGVyZm9ybSBmZWF0dXJlIGRldGVjdGlvbiwgbG9jYXRlIGNvcnJlY3QgV2ViQXNzZW1ibHkgYXJ0aWZhY3QgcGF0aCBhbmQgY2FsbCB0aGUgRW1zY3JpcHRlbiBnZW5lcmF0ZWRcbiAqIEphdmFTY3JpcHQgY29kZSB0byBpbml0aWFsaXplIHRoZSBXZWJBc3NlbWJseSBydW50aW1lLlxuICogICAgICAgICAtIGlmIHByb3h5IGlzIGVuYWJsZWQsIHRoaXMgc3RlcCBoYXBwZW5zIGluIHRoZSBwcm94eSB3b3JrZXIgdXNpbmcgbWVzc2FnZSAnaW5pdC13YXNtJy5cbiAqICAgICAgICAgLSBkb3dubG9hZGluZyB0aGUgJ29ydC13YXNtey4uLn0ud2FzbScgZmlsZSBpcyBkb25lIGluIHRoaXMgc3RlcC5cbiAqICAgICAgICAgLSBpZiBtdWx0aS10aHJlYWQgaXMgZW5hYmxlZCwgb25lIG9yIG1vcmUgd2Vid29ya2VyIHdpbGwgYmUgY3JlYXRlZCB0byBpbml0aWFsaXplIHRoZSBQVGhyZWFkIHRocmVhZHBvb2wuXG4gKlxuICogMy4gT1JUIGVudmlyb25tZW50IGluaXRpYWxpemF0aW9uLlxuICogICAgVGhpcyBoYXBwZW5zIGFmdGVyIHN0ZXAgMi4gSW4gdGhpcyBzdGVwLCBvbm54cnVudGltZS13ZWIgcGVyZm9ybXMgT05OWCBSdW50aW1lIGVudmlyb25tZW50IGluaXRpYWxpemF0aW9uLlxuICogRnVuY3Rpb24gYF9PcnRJbml0KClgIGlzIGNhbGxlZCBpbiB0aGlzIHN0ZXAuXG4gKiAgICAgLSBpZiBwcm94eSBpcyBlbmFibGVkLCB0aGlzIHN0ZXAgaGFwcGVucyBpbiB0aGUgcHJveHkgd29ya2VyIHVzaW5nIG1lc3NhZ2UgJ2luaXQtb3J0Jy5cbiAqICAgICAtIGxvZ2dpbmcgbGV2ZWwgKG9ydC5lbnYubG9nTGV2ZWwpIGFuZCB0aHJlYWQgbnVtYmVyIChvcnQuZW52Lndhc20ubnVtVGhyZWFkcykgYXJlIHNldCBpbiB0aGlzIHN0ZXAuXG4gKlxuICogNC4gU2Vzc2lvbiBpbml0aWFsaXphdGlvbi5cbiAqICAgIFRoaXMgaGFwcGVucyB3aGVuIGBvcnQuSW5mZXJlbmNlU2Vzc2lvbi5jcmVhdGUoKWAgaXMgY2FsbGVkLiBVbmxpa2UgdGhlIGZpcnN0IDMgc3RlcHMgKHRoZXkgb25seSBjYWxsZWQgb25jZSksXG4gKiB0aGlzIHN0ZXAgd2lsbCBiZSBkb25lIGZvciBlYWNoIHNlc3Npb24uIEluIHRoaXMgc3RlcCwgb25ueHJ1bnRpbWUtd2ViIGRvZXMgdGhlIGZvbGxvd2luZ3M6XG4gKiAgICBJZiB0aGUgcGFyYW1ldGVyIGlzIGEgVVJMOlxuICogICAgLSBkb3dubG9hZCB0aGUgbW9kZWwgZGF0YSBmcm9tIHRoZSBVUkwuXG4gKiAgICAtIGNvcHkgdGhlIG1vZGVsIGRhdGEgdG8gdGhlIFdBU00gaGVhcC4gKHByb3h5OiAnY29weS1mcm9tJylcbiAqICAgIC0gZGVyZWZlcmVuY2UgdGhlIG1vZGVsIGJ1ZmZlci4gVGhpcyBzdGVwIGFsbG93cyB0aGUgb3JpZ2luYWwgQXJyYXlCdWZmZXIgdG8gYmUgZ2FyYmFnZSBjb2xsZWN0ZWQuXG4gKiAgICAtIGNhbGwgYF9PcnRDcmVhdGVTZXNzaW9uKClgIHRvIGNyZWF0ZSB0aGUgc2Vzc2lvbi4gKHByb3h5OiAnY3JlYXRlJylcbiAqXG4gKiAgICBJZiB0aGUgcGFyYW1ldGVyIGlzIGEgVWludDhBcnJheSBvYmplY3Q6XG4gKiAgICAtIGNvcHkgdGhlIG1vZGVsIGRhdGEgdG8gdGhlIFdBU00gaGVhcC4gKHByb3h5OiAnY29weS1mcm9tJylcbiAqICAgIC0gY2FsbCBgX09ydENyZWF0ZVNlc3Npb24oKWAgdG8gY3JlYXRlIHRoZSBzZXNzaW9uLiAocHJveHk6ICdjcmVhdGUnKVxuICpcbiAqXG4gKi9cblxuLyoqXG4gKiBpbml0aWFsaXplIE9SVCBlbnZpcm9ubWVudC5cbiAqXG4gKiBAcGFyYW0gbnVtVGhyZWFkcyBTZXRHbG9iYWxJbnRyYU9wTnVtVGhyZWFkcyhudW1UaHJlYWRzKVxuICogQHBhcmFtIGxvZ2dpbmdMZXZlbCBDcmVhdGVFbnYoc3RhdGljX2Nhc3Q8T3J0TG9nZ2luZ0xldmVsPihsb2dnaW5nX2xldmVsKSlcbiAqL1xuY29uc3QgaW5pdE9ydCA9IChudW1UaHJlYWRzOiBudW1iZXIsIGxvZ2dpbmdMZXZlbDogbnVtYmVyKTogdm9pZCA9PiB7XG4gIGNvbnN0IGVycm9yQ29kZSA9IGdldEluc3RhbmNlKCkuX09ydEluaXQobnVtVGhyZWFkcywgbG9nZ2luZ0xldmVsKTtcbiAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xuICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgaW5pdGlhbGl6ZSBvbm54cnVudGltZS5cIik7XG4gIH1cbn07XG5cbi8qKlxuICogaW5pdGlhbGl6ZSBydW50aW1lIGVudmlyb25tZW50LlxuICogQHBhcmFtIGVudiBwYXNzZWQgaW4gdGhlIGVudmlyb25tZW50IGNvbmZpZyBvYmplY3QuXG4gKi9cbmV4cG9ydCBjb25zdCBpbml0UnVudGltZSA9IGFzeW5jIChlbnY6IEVudik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAvLyBpbml0IE9SVFxuICBpbml0T3J0KGVudi53YXNtLm51bVRocmVhZHMhLCBsb2dMZXZlbFN0cmluZ1RvRW51bShlbnYubG9nTGV2ZWwpKTtcbn07XG5cbi8qKlxuICogcGVyZm9ybSBFUCBzcGVjaWZpYyBpbml0aWFsaXphdGlvbi5cbiAqXG4gKiBAcGFyYW0gZW52XG4gKiBAcGFyYW0gZXBOYW1lXG4gKi9cbmV4cG9ydCBjb25zdCBpbml0RXAgPSBhc3luYyAoZW52OiBFbnYsIGVwTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIC8vIGluaXRpYWxpemUgQVNZTkNJRlkgc3VwcG9ydFxuICBnZXRJbnN0YW5jZSgpLmFzeW5jSW5pdD8uKCk7XG5cbiAgaWYgKGVwTmFtZSA9PT0gJ3dlYmdwdScgJiYgQlVJTERfREVGUy5VU0VfV0VCR1BVX0VQKSB7XG4gICAgZ2V0SW5zdGFuY2UoKS53ZWJncHVJbml0ISgoZGV2aWNlKSA9PiB7XG4gICAgICBlbnYud2ViZ3B1LmRldmljZSA9IGRldmljZTtcbiAgICB9KTtcbiAgfVxuXG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX0pTRVApIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICAgIGNvbnN0IGluaXRKc2VwID0gcmVxdWlyZSgnLi9qc2VwL2luaXQnKS5pbml0O1xuXG4gICAgaWYgKGVwTmFtZSA9PT0gJ3dlYmdwdScgJiYgIUJVSUxEX0RFRlMuVVNFX1dFQkdQVV9FUCkge1xuICAgICAgLy8gcGVyZm9ybSBXZWJHUFUgYXZhaWxhYmlsaXR5IGNoZWNrXG4gICAgICBpZiAodHlwZW9mIG5hdmlnYXRvciA9PT0gJ3VuZGVmaW5lZCcgfHwgIW5hdmlnYXRvci5ncHUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdXZWJHUFUgaXMgbm90IHN1cHBvcnRlZCBpbiBjdXJyZW50IGVudmlyb25tZW50Jyk7XG4gICAgICB9XG5cbiAgICAgIGxldCBhZGFwdGVyID0gZW52LndlYmdwdS5hZGFwdGVyIGFzIEdQVUFkYXB0ZXIgfCBudWxsO1xuICAgICAgaWYgKCFhZGFwdGVyKSB7XG4gICAgICAgIC8vIGlmIGFkYXB0ZXIgaXMgbm90IHNldCwgcmVxdWVzdCBhIG5ldyBhZGFwdGVyLlxuICAgICAgICBjb25zdCBwb3dlclByZWZlcmVuY2UgPSBlbnYud2ViZ3B1LnBvd2VyUHJlZmVyZW5jZTtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHBvd2VyUHJlZmVyZW5jZSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgcG93ZXJQcmVmZXJlbmNlICE9PSAnbG93LXBvd2VyJyAmJlxuICAgICAgICAgIHBvd2VyUHJlZmVyZW5jZSAhPT0gJ2hpZ2gtcGVyZm9ybWFuY2UnXG4gICAgICAgICkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBwb3dlclByZWZlcmVuY2Ugc2V0dGluZzogXCIke3Bvd2VyUHJlZmVyZW5jZX1cImApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZvcmNlRmFsbGJhY2tBZGFwdGVyID0gZW52LndlYmdwdS5mb3JjZUZhbGxiYWNrQWRhcHRlcjtcbiAgICAgICAgaWYgKGZvcmNlRmFsbGJhY2tBZGFwdGVyICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIGZvcmNlRmFsbGJhY2tBZGFwdGVyICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgZm9yY2VGYWxsYmFja0FkYXB0ZXIgc2V0dGluZzogXCIke2ZvcmNlRmFsbGJhY2tBZGFwdGVyfVwiYCk7XG4gICAgICAgIH1cbiAgICAgICAgYWRhcHRlciA9IGF3YWl0IG5hdmlnYXRvci5ncHUucmVxdWVzdEFkYXB0ZXIoeyBwb3dlclByZWZlcmVuY2UsIGZvcmNlRmFsbGJhY2tBZGFwdGVyIH0pO1xuICAgICAgICBpZiAoIWFkYXB0ZXIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnRmFpbGVkIHRvIGdldCBHUFUgYWRhcHRlci4gJyArXG4gICAgICAgICAgICAgICdZb3UgbWF5IG5lZWQgdG8gZW5hYmxlIGZsYWcgXCItLWVuYWJsZS11bnNhZmUtd2ViZ3B1XCIgaWYgeW91IGFyZSB1c2luZyBDaHJvbWUuJyxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBpZiBhZGFwdGVyIGlzIHNldCwgdmFsaWRhdGUgaXQuXG4gICAgICAgIGlmIChcbiAgICAgICAgICB0eXBlb2YgYWRhcHRlci5saW1pdHMgIT09ICdvYmplY3QnIHx8XG4gICAgICAgICAgdHlwZW9mIGFkYXB0ZXIuZmVhdHVyZXMgIT09ICdvYmplY3QnIHx8XG4gICAgICAgICAgdHlwZW9mIGFkYXB0ZXIucmVxdWVzdERldmljZSAhPT0gJ2Z1bmN0aW9uJ1xuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgR1BVIGFkYXB0ZXIgc2V0IGluIGBlbnYud2ViZ3B1LmFkYXB0ZXJgLiBJdCBtdXN0IGJlIGEgR1BVQWRhcHRlciBvYmplY3QuJyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgYXdhaXQgaW5pdEpzZXAoJ3dlYmdwdScsIGdldEluc3RhbmNlKCksIGVudiwgYWRhcHRlcik7XG4gICAgfVxuICAgIGlmIChlcE5hbWUgPT09ICd3ZWJubicpIHtcbiAgICAgIC8vIHBlcmZvcm0gV2ViTk4gYXZhaWxhYmlsaXR5IGNoZWNrXG4gICAgICBpZiAodHlwZW9mIG5hdmlnYXRvciA9PT0gJ3VuZGVmaW5lZCcgfHwgIShuYXZpZ2F0b3IgYXMgdW5rbm93biBhcyB7IG1sOiB1bmtub3duIH0pLm1sKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignV2ViTk4gaXMgbm90IHN1cHBvcnRlZCBpbiBjdXJyZW50IGVudmlyb25tZW50Jyk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGluaXRKc2VwKCd3ZWJubicsIGdldEluc3RhbmNlKCksIGVudik7XG4gICAgfVxuICB9XG59O1xuXG4vLyAjZW5kcmVnaW9uIEluaXRpYWxpemF0aW9uc1xuXG4vKipcbiAqIHZhbGlkIGRhdGEgbG9jYXRpb25zIGZvciBpbnB1dC9vdXRwdXQgdGVuc29ycy5cbiAqL1xudHlwZSBTdXBwb3J0ZWRUZW5zb3JEYXRhTG9jYXRpb25Gb3JJbnB1dE91dHB1dCA9XG4gIHwgJ2NwdSdcbiAgfCAnY3B1LXBpbm5lZCdcbiAgfCAnZ3B1LWJ1ZmZlcidcbiAgfCAnbWwtdGVuc29yJ1xuICAvLyBVc2UgJ21sLXRlbnNvcicgZHVyaW5nIGluZmVyZW5jZSwgYnV0IG91dHB1dCBhIHRlbnNvciBsb2NhdGVkIG9uIHRoZSBDUFUuXG4gIHwgJ21sLXRlbnNvci1jcHUtb3V0cHV0JztcblxudHlwZSBJT0JpbmRpbmdTdGF0ZSA9IHtcbiAgLyoqXG4gICAqIHRoZSBoYW5kbGUgb2YgSU8gYmluZGluZy5cbiAgICovXG4gIHJlYWRvbmx5IGhhbmRsZTogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiB0aGUgcHJlZmVycmVkIGxvY2F0aW9uIGZvciBlYWNoIG91dHB1dCB0ZW5zb3IuXG4gICAqXG4gICAqIHZhbHVlIGlzIG9uZSBvZiAnY3B1JywgJ2NwdS1waW5uZWQnLCAnZ3B1LWJ1ZmZlcicsICdtbC10ZW5zb3InLlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zOiByZWFkb25seSBTdXBwb3J0ZWRUZW5zb3JEYXRhTG9jYXRpb25Gb3JJbnB1dE91dHB1dFtdO1xuXG4gIC8qKlxuICAgKiBlbnVtIHZhbHVlIG9mIHRoZSBwcmVmZXJyZWQgbG9jYXRpb24gZm9yIGVhY2ggb3V0cHV0IHRlbnNvci5cbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dFByZWZlcnJlZExvY2F0aW9uc0VuY29kZWQ6IHJlYWRvbmx5IG51bWJlcltdO1xufTtcblxuLyoqXG4gKiAgdHVwbGUgZWxlbWVudHMgYXJlOiBJbmZlcmVuY2VTZXNzaW9uIElEOyBpbnB1dE5hbWVzVVRGOEVuY29kZWQ7IG91dHB1dE5hbWVzVVRGOEVuY29kZWQ7IGJpbmRpbmdTdGF0ZVxuICovXG50eXBlIFNlc3Npb25NZXRhZGF0YSA9IFtcbiAgaW5mZXJlbmNlU2Vzc2lvbklkOiBudW1iZXIsXG4gIGlucHV0TmFtZXNVVEY4RW5jb2RlZDogbnVtYmVyW10sXG4gIG91dHB1dE5hbWVzVVRGOEVuY29kZWQ6IG51bWJlcltdLFxuICBiaW5kaW5nU3RhdGU6IElPQmluZGluZ1N0YXRlIHwgbnVsbCxcbiAgZW5hYmxlR3JhcGhDYXB0dXJlOiBib29sZWFuLFxuICBpbnB1dE91dHB1dEJvdW5kOiBib29sZWFuLFxuXTtcblxuY29uc3QgYWN0aXZlU2Vzc2lvbnMgPSBuZXcgTWFwPG51bWJlciwgU2Vzc2lvbk1ldGFkYXRhPigpO1xuXG4vKipcbiAqIGdldCB0aGUgaW5wdXQvb3V0cHV0IGNvdW50IG9mIHRoZSBzZXNzaW9uLlxuICogQHBhcmFtIHNlc3Npb25IYW5kbGUgdGhlIGhhbmRsZSByZXByZXNlbnRpbmcgdGhlIHNlc3Npb24uIHNob3VsZCBiZSBub24temVyby5cbiAqIEByZXR1cm5zIGEgdHVwbGUgaW5jbHVkaW5nIDIgbnVtYmVycywgcmVwcmVzZW50aW5nIHRoZSBpbnB1dCBjb3VudCBhbmQgb3V0cHV0IGNvdW50LlxuICovXG5jb25zdCBnZXRTZXNzaW9uSW5wdXRPdXRwdXRDb3VudCA9IChzZXNzaW9uSGFuZGxlOiBudW1iZXIpOiBbbnVtYmVyLCBudW1iZXJdID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IHN0YWNrID0gd2FzbS5zdGFja1NhdmUoKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBwdHJTaXplID0gd2FzbS5QVFJfU0laRTtcbiAgICBjb25zdCBkYXRhT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKDIgKiBwdHJTaXplKTtcbiAgICBjb25zdCBlcnJvckNvZGUgPSB3YXNtLl9PcnRHZXRJbnB1dE91dHB1dENvdW50KHNlc3Npb25IYW5kbGUsIGRhdGFPZmZzZXQsIGRhdGFPZmZzZXQgKyBwdHJTaXplKTtcbiAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGdldCBzZXNzaW9uIGlucHV0L291dHB1dCBjb3VudC5cIik7XG4gICAgfVxuICAgIGNvbnN0IHR5cGUgPSBwdHJTaXplID09PSA0ID8gJ2kzMicgOiAnaTY0JztcbiAgICByZXR1cm4gW051bWJlcih3YXNtLmdldFZhbHVlKGRhdGFPZmZzZXQsIHR5cGUpKSwgTnVtYmVyKHdhc20uZ2V0VmFsdWUoZGF0YU9mZnNldCArIHB0clNpemUsIHR5cGUpKV07XG4gIH0gZmluYWxseSB7XG4gICAgd2FzbS5zdGFja1Jlc3RvcmUoc3RhY2spO1xuICB9XG59O1xuXG5jb25zdCBnZXRTZXNzaW9uSW5wdXRPdXRwdXRNZXRhZGF0YSA9IChcbiAgc2Vzc2lvbkhhbmRsZTogbnVtYmVyLFxuICBpbmRleDogbnVtYmVyLFxuKTogW25hbWVPZmZzZXQ6IG51bWJlciwgZWxlbWVudFR5cGU6IG51bWJlciwgZGltcz86IEFycmF5PG51bWJlciB8IHN0cmluZz5dID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IHN0YWNrID0gd2FzbS5zdGFja1NhdmUoKTtcbiAgbGV0IG1ldGFkYXRhT2Zmc2V0ID0gMDtcbiAgdHJ5IHtcbiAgICBjb25zdCBwdHJTaXplID0gd2FzbS5QVFJfU0laRTtcbiAgICBjb25zdCBkYXRhT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKDIgKiBwdHJTaXplKTtcbiAgICBjb25zdCBlcnJvckNvZGUgPSB3YXNtLl9PcnRHZXRJbnB1dE91dHB1dE1ldGFkYXRhKHNlc3Npb25IYW5kbGUsIGluZGV4LCBkYXRhT2Zmc2V0LCBkYXRhT2Zmc2V0ICsgcHRyU2l6ZSk7XG4gICAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBnZXQgc2Vzc2lvbiBpbnB1dC9vdXRwdXQgbWV0YWRhdGEuXCIpO1xuICAgIH1cbiAgICBjb25zdCBuYW1lT2Zmc2V0ID0gTnVtYmVyKHdhc20uZ2V0VmFsdWUoZGF0YU9mZnNldCwgJyonKSk7XG4gICAgbWV0YWRhdGFPZmZzZXQgPSBOdW1iZXIod2FzbS5nZXRWYWx1ZShkYXRhT2Zmc2V0ICsgcHRyU2l6ZSwgJyonKSk7XG4gICAgLy8gZ2V0IGVsZW1lbnQgdHlwZVxuICAgIGNvbnN0IGVsZW1lbnRUeXBlID0gd2FzbS5IRUFQMzJbbWV0YWRhdGFPZmZzZXQgLyA0XTtcbiAgICBpZiAoZWxlbWVudFR5cGUgPT09IDApIHtcbiAgICAgIHJldHVybiBbbmFtZU9mZnNldCwgMF07IC8vIG5vbi10ZW5zb3JcbiAgICB9XG5cbiAgICAvLyBnZXQgZGltcyBjb3VudFxuICAgIGNvbnN0IGRpbXNDb3VudCA9IHdhc20uSEVBUFUzMlttZXRhZGF0YU9mZnNldCAvIDQgKyAxXTtcbiAgICAvLyBnZXQgZGltc1xuICAgIGNvbnN0IGRpbXM6IEFycmF5PG51bWJlciB8IHN0cmluZz4gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRpbXNDb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBzeW1ib2xpY0RpbU5hbWVPZmZzZXQgPSBOdW1iZXIod2FzbS5nZXRWYWx1ZShtZXRhZGF0YU9mZnNldCArIDggKyBpICogcHRyU2l6ZSwgJyonKSk7XG4gICAgICBkaW1zLnB1c2goXG4gICAgICAgIHN5bWJvbGljRGltTmFtZU9mZnNldCAhPT0gMFxuICAgICAgICAgID8gd2FzbS5VVEY4VG9TdHJpbmcoc3ltYm9saWNEaW1OYW1lT2Zmc2V0KVxuICAgICAgICAgIDogTnVtYmVyKHdhc20uZ2V0VmFsdWUobWV0YWRhdGFPZmZzZXQgKyA4ICsgKGkgKyBkaW1zQ291bnQpICogcHRyU2l6ZSwgJyonKSksXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gW25hbWVPZmZzZXQsIGVsZW1lbnRUeXBlLCBkaW1zXTtcbiAgfSBmaW5hbGx5IHtcbiAgICB3YXNtLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gICAgaWYgKG1ldGFkYXRhT2Zmc2V0ICE9PSAwKSB7XG4gICAgICB3YXNtLl9PcnRGcmVlKG1ldGFkYXRhT2Zmc2V0KTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogYWxsb2NhdGUgdGhlIG1lbW9yeSBhbmQgbWVtY3B5IHRoZSBleHRlcm5hbCBidWZmZXIuXG4gKlxuICogQHBhcmFtIG1vZGVsIC0gdGhlIGV4dGVybmFsIGJ1ZmZlciBjb250YWluaW5nIHRoZSBtb2RlbCBkYXRhLiBNdXN0IG5vdCBiZSB0aGUgc2FtZSBidWZmZXIgYXMgdGhlIFdBU00gaGVhcC5cbiAqIEByZXR1cm5zIGEgMi1lbGVtZW50cyB0dXBsZSAtIHRoZSBwb2ludGVyIGFuZCBzaXplIG9mIHRoZSBhbGxvY2F0ZWQgYnVmZmVyXG4gKi9cbmV4cG9ydCBjb25zdCBjb3B5RnJvbUV4dGVybmFsQnVmZmVyID0gKG1vZGVsOiBVaW50OEFycmF5KTogW251bWJlciwgbnVtYmVyXSA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBjb25zdCBtb2RlbERhdGFPZmZzZXQgPSB3YXNtLl9tYWxsb2MobW9kZWwuYnl0ZUxlbmd0aCk7XG4gIGlmIChtb2RlbERhdGFPZmZzZXQgPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGNyZWF0ZSBhIHNlc3Npb24uIGZhaWxlZCB0byBhbGxvY2F0ZSBhIGJ1ZmZlciBvZiBzaXplICR7bW9kZWwuYnl0ZUxlbmd0aH0uYCk7XG4gIH1cbiAgd2FzbS5IRUFQVTguc2V0KG1vZGVsLCBtb2RlbERhdGFPZmZzZXQpO1xuICByZXR1cm4gW21vZGVsRGF0YU9mZnNldCwgbW9kZWwuYnl0ZUxlbmd0aF07XG59O1xuXG4vKipcbiAqIGNyZWF0ZSBhbiBpbmZlcmVuY2Ugc2Vzc2lvbiBmcm9tIGEgbW9kZWwgZGF0YSBidWZmZXIuXG4gKlxuICogQHBhcmFtIG1vZGVsRGF0YSAtIGVpdGhlciBhIFVpbnQ4QXJyYXkgb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgbW9kZWwgZGF0YSwgb3IgYSAyLWVsZW1lbnRzIHR1cGxlIGNvbnRhaW5pbmcgdGhlXG4gKiAgICAgcG9pbnRlciBhbmQgc2l6ZSBvZiB0aGUgbW9kZWwgZGF0YSBidWZmZXIuXG4gKiBAcGFyYW0gb3B0aW9ucyBhbiBvcHRpb25hbCBzZXNzaW9uIG9wdGlvbnMgb2JqZWN0LlxuICogQHJldHVybnMgYSAzLWVsZW1lbnRzIHR1cGxlIGNvbnRhaW5pbmcgW3Nlc3Npb24gaGFuZGxlLCBpbnB1dCBuYW1lcywgb3V0cHV0IG5hbWVzXVxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlU2Vzc2lvbiA9IGFzeW5jIChcbiAgbW9kZWxEYXRhOiBVaW50OEFycmF5IHwgU2VyaWFsaXphYmxlSW50ZXJuYWxCdWZmZXIsXG4gIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zLFxuKTogUHJvbWlzZTxTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGE+ID0+IHtcbiAgbGV0IG1vZGVsRGF0YU9mZnNldDogbnVtYmVyLCBtb2RlbERhdGFMZW5ndGg6IG51bWJlcjtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkobW9kZWxEYXRhKSkge1xuICAgIC8vIGlmIG1vZGVsIGRhdGEgaXMgYW4gYXJyYXksIGl0IG11c3QgYmUgYSAyLWVsZW1lbnRzIHR1cGxlIGNvbnRhaW5pbmcgdGhlIHBvaW50ZXIgYW5kIHNpemUgb2YgdGhlIG1vZGVsIGRhdGFcbiAgICBbbW9kZWxEYXRhT2Zmc2V0LCBtb2RlbERhdGFMZW5ndGhdID0gbW9kZWxEYXRhO1xuICB9IGVsc2UgaWYgKG1vZGVsRGF0YS5idWZmZXIgPT09IHdhc20uSEVBUFU4LmJ1ZmZlcikge1xuICAgIC8vIGlmIG1vZGVsIGRhdGEgdXNlcyB0aGUgc2FtZSBidWZmZXIgYXMgdGhlIFdBU00gaGVhcCwgd2UgZG9uJ3QgbmVlZCB0byBjb3B5IGl0LlxuICAgIFttb2RlbERhdGFPZmZzZXQsIG1vZGVsRGF0YUxlbmd0aF0gPSBbbW9kZWxEYXRhLmJ5dGVPZmZzZXQsIG1vZGVsRGF0YS5ieXRlTGVuZ3RoXTtcbiAgfSBlbHNlIHtcbiAgICAvLyBvdGhlcndpc2UsIGNvcHkgdGhlIG1vZGVsIGRhdGEgdG8gdGhlIFdBU00gaGVhcC5cbiAgICBbbW9kZWxEYXRhT2Zmc2V0LCBtb2RlbERhdGFMZW5ndGhdID0gY29weUZyb21FeHRlcm5hbEJ1ZmZlcihtb2RlbERhdGEpO1xuICB9XG5cbiAgbGV0IHNlc3Npb25IYW5kbGUgPSAwO1xuICBsZXQgc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPSAwO1xuICBsZXQgaW9CaW5kaW5nSGFuZGxlID0gMDtcbiAgbGV0IGFsbG9jczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgaW5wdXROYW1lc1VURjhFbmNvZGVkID0gW107XG4gIGNvbnN0IG91dHB1dE5hbWVzVVRGOEVuY29kZWQgPSBbXTtcblxuICB0cnkge1xuICAgIFtzZXNzaW9uT3B0aW9uc0hhbmRsZSwgYWxsb2NzXSA9IGF3YWl0IHNldFNlc3Npb25PcHRpb25zKG9wdGlvbnMpO1xuXG4gICAgaWYgKG9wdGlvbnM/LmV4dGVybmFsRGF0YSAmJiB3YXNtLm1vdW50RXh0ZXJuYWxEYXRhKSB7XG4gICAgICBjb25zdCBsb2FkaW5nUHJvbWlzZXMgPSBbXTtcbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBvcHRpb25zLmV4dGVybmFsRGF0YSkge1xuICAgICAgICBjb25zdCBwYXRoID0gdHlwZW9mIGZpbGUgPT09ICdzdHJpbmcnID8gZmlsZSA6IGZpbGUucGF0aDtcbiAgICAgICAgbG9hZGluZ1Byb21pc2VzLnB1c2goXG4gICAgICAgICAgbG9hZEZpbGUodHlwZW9mIGZpbGUgPT09ICdzdHJpbmcnID8gZmlsZSA6IGZpbGUuZGF0YSkudGhlbigoZGF0YSkgPT4ge1xuICAgICAgICAgICAgd2FzbS5tb3VudEV4dGVybmFsRGF0YShwYXRoLCBkYXRhKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gd2FpdCBmb3IgYWxsIGV4dGVybmFsIGRhdGEgZmlsZXMgdG8gYmUgbG9hZGVkXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChsb2FkaW5nUHJvbWlzZXMpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgcHJvdmlkZXIgb2Ygb3B0aW9ucz8uZXhlY3V0aW9uUHJvdmlkZXJzID8/IFtdKSB7XG4gICAgICBjb25zdCBwcm92aWRlck5hbWUgPSB0eXBlb2YgcHJvdmlkZXIgPT09ICdzdHJpbmcnID8gcHJvdmlkZXIgOiBwcm92aWRlci5uYW1lO1xuICAgICAgaWYgKHByb3ZpZGVyTmFtZSA9PT0gJ3dlYm5uJykge1xuICAgICAgICB3YXNtLnNob3VsZFRyYW5zZmVyVG9NTFRlbnNvciA9IGZhbHNlO1xuICAgICAgICBpZiAodHlwZW9mIHByb3ZpZGVyICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbnN0IHdlYm5uT3B0aW9ucyA9IHByb3ZpZGVyIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViTk5FeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICAgICAgICBjb25zdCBjb250ZXh0ID0gKHdlYm5uT3B0aW9ucyBhcyBJbmZlcmVuY2VTZXNzaW9uLldlYk5OT3B0aW9uc1dpdGhNTENvbnRleHQpPy5jb250ZXh0O1xuICAgICAgICAgIGNvbnN0IGdwdURldmljZSA9ICh3ZWJubk9wdGlvbnMgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJOTk9wdGlvbnNXZWJHcHUpPy5ncHVEZXZpY2U7XG4gICAgICAgICAgY29uc3QgZGV2aWNlVHlwZSA9ICh3ZWJubk9wdGlvbnMgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJOTkNvbnRleHRPcHRpb25zKT8uZGV2aWNlVHlwZTtcbiAgICAgICAgICBjb25zdCBwb3dlclByZWZlcmVuY2UgPSAod2Vibm5PcHRpb25zIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViTk5Db250ZXh0T3B0aW9ucyk/LnBvd2VyUHJlZmVyZW5jZTtcbiAgICAgICAgICBpZiAoY29udGV4dCkge1xuICAgICAgICAgICAgd2FzbS5jdXJyZW50Q29udGV4dCA9IGNvbnRleHQgYXMgTUxDb250ZXh0O1xuICAgICAgICAgIH0gZWxzZSBpZiAoZ3B1RGV2aWNlKSB7XG4gICAgICAgICAgICB3YXNtLmN1cnJlbnRDb250ZXh0ID0gYXdhaXQgd2FzbS53ZWJubkNyZWF0ZU1MQ29udGV4dCEoZ3B1RGV2aWNlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2FzbS5jdXJyZW50Q29udGV4dCA9IGF3YWl0IHdhc20ud2Vibm5DcmVhdGVNTENvbnRleHQhKHsgZGV2aWNlVHlwZSwgcG93ZXJQcmVmZXJlbmNlIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB3YXNtLmN1cnJlbnRDb250ZXh0ID0gYXdhaXQgd2FzbS53ZWJubkNyZWF0ZU1MQ29udGV4dCEoKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBzZXNzaW9uSGFuZGxlID0gYXdhaXQgd2FzbS5fT3J0Q3JlYXRlU2Vzc2lvbihtb2RlbERhdGFPZmZzZXQsIG1vZGVsRGF0YUxlbmd0aCwgc2Vzc2lvbk9wdGlvbnNIYW5kbGUpO1xuICAgIHdhc20ud2ViZ3B1T25DcmVhdGVTZXNzaW9uPy4oc2Vzc2lvbkhhbmRsZSk7XG4gICAgaWYgKHNlc3Npb25IYW5kbGUgPT09IDApIHtcbiAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgY3JlYXRlIGEgc2Vzc2lvbi5cIik7XG4gICAgfVxuXG4gICAgd2FzbS5qc2VwT25DcmVhdGVTZXNzaW9uPy4oKTtcblxuICAgIC8vIGNsZWFyIGN1cnJlbnQgTUxDb250ZXh0IGFmdGVyIHNlc3Npb24gY3JlYXRpb25cbiAgICBpZiAod2FzbS5jdXJyZW50Q29udGV4dCkge1xuICAgICAgd2FzbS53ZWJublJlZ2lzdGVyTUxDb250ZXh0IShzZXNzaW9uSGFuZGxlLCB3YXNtLmN1cnJlbnRDb250ZXh0KTtcbiAgICAgIHdhc20uY3VycmVudENvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgICB3YXNtLnNob3VsZFRyYW5zZmVyVG9NTFRlbnNvciA9IHRydWU7XG4gICAgfVxuXG4gICAgY29uc3QgW2lucHV0Q291bnQsIG91dHB1dENvdW50XSA9IGdldFNlc3Npb25JbnB1dE91dHB1dENvdW50KHNlc3Npb25IYW5kbGUpO1xuXG4gICAgY29uc3QgZW5hYmxlR3JhcGhDYXB0dXJlID0gISFvcHRpb25zPy5lbmFibGVHcmFwaENhcHR1cmU7XG5cbiAgICBjb25zdCBpbnB1dE5hbWVzID0gW107XG4gICAgY29uc3Qgb3V0cHV0TmFtZXMgPSBbXTtcbiAgICBjb25zdCBpbnB1dE1ldGFkYXRhOiBJbmZlcmVuY2VTZXNzaW9uLlZhbHVlTWV0YWRhdGFbXSA9IFtdO1xuICAgIGNvbnN0IG91dHB1dE1ldGFkYXRhOiBJbmZlcmVuY2VTZXNzaW9uLlZhbHVlTWV0YWRhdGFbXSA9IFtdO1xuICAgIGNvbnN0IG91dHB1dFByZWZlcnJlZExvY2F0aW9uczogU3VwcG9ydGVkVGVuc29yRGF0YUxvY2F0aW9uRm9ySW5wdXRPdXRwdXRbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBbbmFtZU9mZnNldCwgZWxlbWVudFR5cGUsIHNoYXBlXSA9IGdldFNlc3Npb25JbnB1dE91dHB1dE1ldGFkYXRhKHNlc3Npb25IYW5kbGUsIGkpO1xuICAgICAgaWYgKG5hbWVPZmZzZXQgPT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBnZXQgYW4gaW5wdXQgbmFtZS5cIik7XG4gICAgICB9XG4gICAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWQucHVzaChuYW1lT2Zmc2V0KTtcbiAgICAgIGNvbnN0IG5hbWUgPSB3YXNtLlVURjhUb1N0cmluZyhuYW1lT2Zmc2V0KTtcbiAgICAgIGlucHV0TmFtZXMucHVzaChuYW1lKTtcbiAgICAgIGlucHV0TWV0YWRhdGEucHVzaChcbiAgICAgICAgZWxlbWVudFR5cGUgPT09IDBcbiAgICAgICAgICA/IHsgbmFtZSwgaXNUZW5zb3I6IGZhbHNlIH1cbiAgICAgICAgICA6IHsgbmFtZSwgaXNUZW5zb3I6IHRydWUsIHR5cGU6IHRlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nKGVsZW1lbnRUeXBlKSwgc2hhcGU6IHNoYXBlISB9LFxuICAgICAgKTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBbbmFtZU9mZnNldCwgZWxlbWVudFR5cGUsIHNoYXBlXSA9IGdldFNlc3Npb25JbnB1dE91dHB1dE1ldGFkYXRhKHNlc3Npb25IYW5kbGUsIGkgKyBpbnB1dENvdW50KTtcbiAgICAgIGlmIChuYW1lT2Zmc2V0ID09PSAwKSB7XG4gICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgZ2V0IGFuIG91dHB1dCBuYW1lLlwiKTtcbiAgICAgIH1cbiAgICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWQucHVzaChuYW1lT2Zmc2V0KTtcbiAgICAgIGNvbnN0IG5hbWVTdHJpbmcgPSB3YXNtLlVURjhUb1N0cmluZyhuYW1lT2Zmc2V0KTtcbiAgICAgIG91dHB1dE5hbWVzLnB1c2gobmFtZVN0cmluZyk7XG4gICAgICBvdXRwdXRNZXRhZGF0YS5wdXNoKFxuICAgICAgICBlbGVtZW50VHlwZSA9PT0gMFxuICAgICAgICAgID8geyBuYW1lOiBuYW1lU3RyaW5nLCBpc1RlbnNvcjogZmFsc2UgfVxuICAgICAgICAgIDogeyBuYW1lOiBuYW1lU3RyaW5nLCBpc1RlbnNvcjogdHJ1ZSwgdHlwZTogdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcoZWxlbWVudFR5cGUpLCBzaGFwZTogc2hhcGUhIH0sXG4gICAgICApO1xuXG4gICAgICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQKSB7XG4gICAgICAgIGlmIChlbmFibGVHcmFwaENhcHR1cmUgJiYgb3B0aW9ucz8ucHJlZmVycmVkT3V0cHV0TG9jYXRpb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG91dHB1dFByZWZlcnJlZExvY2F0aW9ucy5wdXNoKCdncHUtYnVmZmVyJyk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbG9jYXRpb24gPVxuICAgICAgICAgIHR5cGVvZiBvcHRpb25zPy5wcmVmZXJyZWRPdXRwdXRMb2NhdGlvbiA9PT0gJ3N0cmluZydcbiAgICAgICAgICAgID8gb3B0aW9ucy5wcmVmZXJyZWRPdXRwdXRMb2NhdGlvblxuICAgICAgICAgICAgOiAob3B0aW9ucz8ucHJlZmVycmVkT3V0cHV0TG9jYXRpb24/LltuYW1lU3RyaW5nXSA/PyAnY3B1Jyk7XG4gICAgICAgIGNvbnN0IGlzR3JhcGhPdXRwdXQgPSB3YXNtLndlYm5uSXNHcmFwaE91dHB1dDtcbiAgICAgICAgaWYgKGxvY2F0aW9uID09PSAnY3B1JyAmJiBpc0dyYXBoT3V0cHV0ICYmIGlzR3JhcGhPdXRwdXQoc2Vzc2lvbkhhbmRsZSwgbmFtZVN0cmluZykpIHtcbiAgICAgICAgICBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnMucHVzaCgnbWwtdGVuc29yLWNwdS1vdXRwdXQnKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobG9jYXRpb24gIT09ICdjcHUnICYmIGxvY2F0aW9uICE9PSAnY3B1LXBpbm5lZCcgJiYgbG9jYXRpb24gIT09ICdncHUtYnVmZmVyJyAmJiBsb2NhdGlvbiAhPT0gJ21sLXRlbnNvcicpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vdCBzdXBwb3J0ZWQgcHJlZmVycmVkIG91dHB1dCBsb2NhdGlvbjogJHtsb2NhdGlvbn0uYCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVuYWJsZUdyYXBoQ2FwdHVyZSAmJiBsb2NhdGlvbiAhPT0gJ2dwdS1idWZmZXInKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYE5vdCBzdXBwb3J0ZWQgcHJlZmVycmVkIG91dHB1dCBsb2NhdGlvbjogJHtsb2NhdGlvbn0uIE9ubHkgJ2dwdS1idWZmZXInIGxvY2F0aW9uIGlzIHN1cHBvcnRlZCB3aGVuIGVuYWJsZUdyYXBoQ2FwdHVyZSBpcyB0cnVlLmAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnMucHVzaChsb2NhdGlvbik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdXNlIElPIGJpbmRpbmcgb25seSB3aGVuIGF0IGxlYXN0IG9uZSBvdXRwdXQgaXMgcHJlZmVycmVkIHRvIGJlIG9uIEdQVS5cbiAgICBsZXQgYmluZGluZ1N0YXRlOiBJT0JpbmRpbmdTdGF0ZSB8IG51bGwgPSBudWxsO1xuICAgIGlmIChcbiAgICAgICFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUCAmJlxuICAgICAgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zLnNvbWUoKGwpID0+IGwgPT09ICdncHUtYnVmZmVyJyB8fCBsID09PSAnbWwtdGVuc29yJyB8fCBsID09PSAnbWwtdGVuc29yLWNwdS1vdXRwdXQnKVxuICAgICkge1xuICAgICAgaW9CaW5kaW5nSGFuZGxlID0gd2FzbS5fT3J0Q3JlYXRlQmluZGluZyhzZXNzaW9uSGFuZGxlKTtcbiAgICAgIGlmIChpb0JpbmRpbmdIYW5kbGUgPT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBjcmVhdGUgSU8gYmluZGluZy5cIik7XG4gICAgICB9XG5cbiAgICAgIGJpbmRpbmdTdGF0ZSA9IHtcbiAgICAgICAgaGFuZGxlOiBpb0JpbmRpbmdIYW5kbGUsXG4gICAgICAgIG91dHB1dFByZWZlcnJlZExvY2F0aW9ucyxcbiAgICAgICAgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zRW5jb2RlZDogb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zXG4gICAgICAgICAgLy8gJ21sLXRlbnNvci1jcHUtb3V0cHV0JyBpcyB0cmVhdGVkIGFzICdtbC10ZW5zb3InIGZvciB0aGUgcHVycG9zZSBvZiBJTyBiaW5kaW5nLlxuICAgICAgICAgIC5tYXAoKGwpID0+IChsID09PSAnbWwtdGVuc29yLWNwdS1vdXRwdXQnID8gJ21sLXRlbnNvcicgOiBsKSlcbiAgICAgICAgICAubWFwKChsKSA9PiBkYXRhTG9jYXRpb25TdHJpbmdUb0VudW0obCkpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBhY3RpdmVTZXNzaW9ucy5zZXQoc2Vzc2lvbkhhbmRsZSwgW1xuICAgICAgc2Vzc2lvbkhhbmRsZSxcbiAgICAgIGlucHV0TmFtZXNVVEY4RW5jb2RlZCxcbiAgICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWQsXG4gICAgICBiaW5kaW5nU3RhdGUsXG4gICAgICBlbmFibGVHcmFwaENhcHR1cmUsXG4gICAgICBmYWxzZSxcbiAgICBdKTtcbiAgICByZXR1cm4gW3Nlc3Npb25IYW5kbGUsIGlucHV0TmFtZXMsIG91dHB1dE5hbWVzLCBpbnB1dE1ldGFkYXRhLCBvdXRwdXRNZXRhZGF0YV07XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWQuZm9yRWFjaCgoYnVmKSA9PiB3YXNtLl9PcnRGcmVlKGJ1ZikpO1xuICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWQuZm9yRWFjaCgoYnVmKSA9PiB3YXNtLl9PcnRGcmVlKGJ1ZikpO1xuXG4gICAgaWYgKGlvQmluZGluZ0hhbmRsZSAhPT0gMCkge1xuICAgICAgaWYgKHdhc20uX09ydFJlbGVhc2VCaW5kaW5nKGlvQmluZGluZ0hhbmRsZSkgIT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIElPIGJpbmRpbmcuXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzZXNzaW9uSGFuZGxlICE9PSAwKSB7XG4gICAgICBpZiAod2FzbS5fT3J0UmVsZWFzZVNlc3Npb24oc2Vzc2lvbkhhbmRsZSkgIT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIHNlc3Npb24uXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIHdhc20uX2ZyZWUobW9kZWxEYXRhT2Zmc2V0KTtcbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUgIT09IDApIHtcbiAgICAgIGlmICh3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnMoc2Vzc2lvbk9wdGlvbnNIYW5kbGUpICE9PSAwKSB7XG4gICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgcmVsZWFzZSBzZXNzaW9uIG9wdGlvbnMuXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICBhbGxvY3MuZm9yRWFjaCgoYWxsb2MpID0+IHdhc20uX2ZyZWUoYWxsb2MpKTtcblxuICAgIC8vIHVubW91bnQgZXh0ZXJuYWwgZGF0YSBpZiBuZWNlc3NhcnlcbiAgICB3YXNtLnVubW91bnRFeHRlcm5hbERhdGE/LigpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVsZWFzZVNlc3Npb24gPSAoc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IHNlc3Npb24gPSBhY3RpdmVTZXNzaW9ucy5nZXQoc2Vzc2lvbklkKTtcbiAgaWYgKCFzZXNzaW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgcmVsZWFzZSBzZXNzaW9uLiBpbnZhbGlkIHNlc3Npb24gaWQ6ICR7c2Vzc2lvbklkfWApO1xuICB9XG4gIGNvbnN0IFtzZXNzaW9uSGFuZGxlLCBpbnB1dE5hbWVzVVRGOEVuY29kZWQsIG91dHB1dE5hbWVzVVRGOEVuY29kZWQsIGlvQmluZGluZ1N0YXRlLCBlbmFibGVHcmFwaENhcHR1cmVdID0gc2Vzc2lvbjtcblxuICBpZiAoaW9CaW5kaW5nU3RhdGUpIHtcbiAgICBpZiAoZW5hYmxlR3JhcGhDYXB0dXJlKSB7XG4gICAgICBpZiAod2FzbS5fT3J0Q2xlYXJCb3VuZE91dHB1dHMoaW9CaW5kaW5nU3RhdGUuaGFuZGxlKSAhPT0gMCkge1xuICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGNsZWFyIGJvdW5kIG91dHB1dHMuXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAod2FzbS5fT3J0UmVsZWFzZUJpbmRpbmcoaW9CaW5kaW5nU3RhdGUuaGFuZGxlKSAhPT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIElPIGJpbmRpbmcuXCIpO1xuICAgIH1cbiAgfVxuXG4gIHdhc20uanNlcE9uUmVsZWFzZVNlc3Npb24/LihzZXNzaW9uSWQpO1xuICB3YXNtLndlYm5uT25SZWxlYXNlU2Vzc2lvbj8uKHNlc3Npb25JZCk7XG4gIHdhc20ud2ViZ3B1T25SZWxlYXNlU2Vzc2lvbj8uKHNlc3Npb25JZCk7XG5cbiAgaW5wdXROYW1lc1VURjhFbmNvZGVkLmZvckVhY2goKGJ1ZikgPT4gd2FzbS5fT3J0RnJlZShidWYpKTtcbiAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5mb3JFYWNoKChidWYpID0+IHdhc20uX09ydEZyZWUoYnVmKSk7XG4gIGlmICh3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbihzZXNzaW9uSGFuZGxlKSAhPT0gMCkge1xuICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgcmVsZWFzZSBzZXNzaW9uLlwiKTtcbiAgfVxuICBhY3RpdmVTZXNzaW9ucy5kZWxldGUoc2Vzc2lvbklkKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwcmVwYXJlSW5wdXRPdXRwdXRUZW5zb3IgPSBhc3luYyAoXG4gIHRlbnNvcjogVGVuc29yTWV0YWRhdGEgfCBudWxsLFxuICB0ZW5zb3JIYW5kbGVzOiBudW1iZXJbXSxcbiAgYWxsb2NzOiBudW1iZXJbXSxcbiAgc2Vzc2lvbklkOiBudW1iZXIsXG4gIHRlbnNvck5hbWVVVEY4RW5jb2RlZDogbnVtYmVyLFxuICBpbmRleDogbnVtYmVyLFxuICBlbmFibGVHcmFwaENhcHR1cmUgPSBmYWxzZSxcbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoIXRlbnNvcikge1xuICAgIHRlbnNvckhhbmRsZXMucHVzaCgwKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3QgcHRyU2l6ZSA9IHdhc20uUFRSX1NJWkU7XG5cbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JbMF07XG4gIGNvbnN0IGRpbXMgPSB0ZW5zb3JbMV07XG4gIGNvbnN0IGxvY2F0aW9uID0gdGVuc29yWzNdO1xuICBsZXQgYWN0dWFsTG9jYXRpb24gPSBsb2NhdGlvbjtcblxuICBsZXQgcmF3RGF0YTogbnVtYmVyO1xuICBsZXQgZGF0YUJ5dGVMZW5ndGg6IG51bWJlcjtcblxuICBpZiAoZGF0YVR5cGUgPT09ICdzdHJpbmcnICYmIChsb2NhdGlvbiA9PT0gJ2dwdS1idWZmZXInIHx8IGxvY2F0aW9uID09PSAnbWwtdGVuc29yJykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1N0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCBvbiBHUFUuJyk7XG4gIH1cblxuICBpZiAoZW5hYmxlR3JhcGhDYXB0dXJlICYmIGxvY2F0aW9uICE9PSAnZ3B1LWJ1ZmZlcicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRXh0ZXJuYWwgYnVmZmVyIG11c3QgYmUgcHJvdmlkZWQgZm9yIGlucHV0L291dHB1dCBpbmRleCAke2luZGV4fSB3aGVuIGVuYWJsZUdyYXBoQ2FwdHVyZSBpcyB0cnVlLmAsXG4gICAgKTtcbiAgfVxuXG4gIGlmIChsb2NhdGlvbiA9PT0gJ2dwdS1idWZmZXInKSB7XG4gICAgY29uc3QgZ3B1QnVmZmVyID0gdGVuc29yWzJdLmdwdUJ1ZmZlcjtcbiAgICBkYXRhQnl0ZUxlbmd0aCA9IGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzKHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKGRhdGFUeXBlKSwgZGltcykhO1xuXG4gICAgaWYgKEJVSUxEX0RFRlMuVVNFX1dFQkdQVV9FUCkge1xuICAgICAgY29uc3QgcmVnaXN0ZXJCdWZmZXIgPSB3YXNtLndlYmdwdVJlZ2lzdGVyQnVmZmVyO1xuICAgICAgaWYgKCFyZWdpc3RlckJ1ZmZlcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiBcImdwdS1idWZmZXJcIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViR1BVLicpO1xuICAgICAgfVxuXG4gICAgICByYXdEYXRhID0gcmVnaXN0ZXJCdWZmZXIoZ3B1QnVmZmVyLCBzZXNzaW9uSWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCByZWdpc3RlckJ1ZmZlciA9IHdhc20uanNlcFJlZ2lzdGVyQnVmZmVyO1xuICAgICAgaWYgKCFyZWdpc3RlckJ1ZmZlcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiBcImdwdS1idWZmZXJcIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViR1BVLicpO1xuICAgICAgfVxuICAgICAgcmF3RGF0YSA9IHJlZ2lzdGVyQnVmZmVyKHNlc3Npb25JZCwgaW5kZXgsIGdwdUJ1ZmZlciwgZGF0YUJ5dGVMZW5ndGgpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChsb2NhdGlvbiA9PT0gJ21sLXRlbnNvcicpIHtcbiAgICBjb25zdCBtbFRlbnNvciA9IHRlbnNvclsyXS5tbFRlbnNvciBhcyBNTFRlbnNvcjtcbiAgICBkYXRhQnl0ZUxlbmd0aCA9IGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzKHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKGRhdGFUeXBlKSwgZGltcykhO1xuXG4gICAgY29uc3QgcmVnaXN0ZXJNTFRlbnNvciA9IHdhc20ud2Vibm5SZWdpc3Rlck1MVGVuc29yO1xuICAgIGlmICghcmVnaXN0ZXJNTFRlbnNvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUZW5zb3IgbG9jYXRpb24gXCJtbC10ZW5zb3JcIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7XG4gICAgfVxuICAgIHJhd0RhdGEgPSByZWdpc3Rlck1MVGVuc29yKHNlc3Npb25JZCwgbWxUZW5zb3IsIHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKGRhdGFUeXBlKSwgZGltcyk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgZGF0YSA9IHRlbnNvclsyXTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgICAvLyBzdHJpbmcgdGVuc29yXG4gICAgICBkYXRhQnl0ZUxlbmd0aCA9IHB0clNpemUgKiBkYXRhLmxlbmd0aDtcbiAgICAgIHJhd0RhdGEgPSB3YXNtLl9tYWxsb2MoZGF0YUJ5dGVMZW5ndGgpO1xuICAgICAgYWxsb2NzLnB1c2gocmF3RGF0YSk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2ldICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYHRlbnNvciBkYXRhIGF0IGluZGV4ICR7aX0gaXMgbm90IGEgc3RyaW5nYCk7XG4gICAgICAgIH1cbiAgICAgICAgd2FzbS5zZXRWYWx1ZShyYXdEYXRhICsgaSAqIHB0clNpemUsIGFsbG9jV2FzbVN0cmluZyhkYXRhW2ldLCBhbGxvY3MpLCAnKicpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBpc0dyYXBoSW5wdXQgPSB3YXNtLndlYm5uSXNHcmFwaElucHV0O1xuICAgICAgY29uc3QgaXNHcmFwaE91dHB1dCA9IHdhc20ud2Vibm5Jc0dyYXBoT3V0cHV0O1xuICAgICAgaWYgKGRhdGFUeXBlICE9PSAnc3RyaW5nJyAmJiBpc0dyYXBoSW5wdXQgJiYgaXNHcmFwaE91dHB1dCkge1xuICAgICAgICBjb25zdCB0ZW5zb3JOYW1lID0gd2FzbS5VVEY4VG9TdHJpbmcodGVuc29yTmFtZVVURjhFbmNvZGVkKTtcbiAgICAgICAgLy8gUHJvbW90ZSB0aGUgdGVuc29yIHRvICdtbC10ZW5zb3InIGlmIGl0IGlzIGEgZ3JhcGggaW5wdXQuXG4gICAgICAgIGlmIChpc0dyYXBoSW5wdXQoc2Vzc2lvbklkLCB0ZW5zb3JOYW1lKSB8fCBpc0dyYXBoT3V0cHV0KHNlc3Npb25JZCwgdGVuc29yTmFtZSkpIHtcbiAgICAgICAgICBjb25zdCBkYXRhVHlwZUVudW0gPSB0ZW5zb3JEYXRhVHlwZVN0cmluZ1RvRW51bShkYXRhVHlwZSk7XG4gICAgICAgICAgZGF0YUJ5dGVMZW5ndGggPSBjYWxjdWxhdGVUZW5zb3JTaXplSW5CeXRlcyhkYXRhVHlwZUVudW0sIGRpbXMpITtcbiAgICAgICAgICBhY3R1YWxMb2NhdGlvbiA9ICdtbC10ZW5zb3InO1xuICAgICAgICAgIGNvbnN0IGNyZWF0ZVRlbXBvcmFyeVRlbnNvciA9IHdhc20ud2Vibm5DcmVhdGVUZW1wb3JhcnlUZW5zb3I7XG4gICAgICAgICAgY29uc3QgdXBsb2FkVGVuc29yID0gd2FzbS53ZWJublVwbG9hZFRlbnNvcjtcbiAgICAgICAgICBpZiAoIWNyZWF0ZVRlbXBvcmFyeVRlbnNvciB8fCAhdXBsb2FkVGVuc29yKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiBcIm1sLXRlbnNvclwiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJOTi4nKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgdGVuc29ySWQgPSBhd2FpdCBjcmVhdGVUZW1wb3JhcnlUZW5zb3Ioc2Vzc2lvbklkLCBkYXRhVHlwZUVudW0sIGRpbXMgYXMgbnVtYmVyW10pO1xuICAgICAgICAgIHVwbG9hZFRlbnNvcih0ZW5zb3JJZCwgbmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgZGF0YS5ieXRlTGVuZ3RoKSk7XG4gICAgICAgICAgcmF3RGF0YSA9IHRlbnNvcklkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRhdGFCeXRlTGVuZ3RoID0gZGF0YS5ieXRlTGVuZ3RoO1xuICAgICAgICAgIHJhd0RhdGEgPSB3YXNtLl9tYWxsb2MoZGF0YUJ5dGVMZW5ndGgpO1xuICAgICAgICAgIGFsbG9jcy5wdXNoKHJhd0RhdGEpO1xuICAgICAgICAgIHdhc20uSEVBUFU4LnNldChuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhQnl0ZUxlbmd0aCksIHJhd0RhdGEpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkYXRhQnl0ZUxlbmd0aCA9IGRhdGEuYnl0ZUxlbmd0aDtcbiAgICAgICAgcmF3RGF0YSA9IHdhc20uX21hbGxvYyhkYXRhQnl0ZUxlbmd0aCk7XG4gICAgICAgIGFsbG9jcy5wdXNoKHJhd0RhdGEpO1xuICAgICAgICB3YXNtLkhFQVBVOC5zZXQobmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgZGF0YUJ5dGVMZW5ndGgpLCByYXdEYXRhKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBzdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XG4gIGNvbnN0IGRpbXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2MoNCAqIGRpbXMubGVuZ3RoKTtcbiAgdHJ5IHtcbiAgICBkaW1zLmZvckVhY2goKGQsIGluZGV4KSA9PiB3YXNtLnNldFZhbHVlKGRpbXNPZmZzZXQgKyBpbmRleCAqIHB0clNpemUsIGQsIHB0clNpemUgPT09IDQgPyAnaTMyJyA6ICdpNjQnKSk7XG4gICAgY29uc3QgdGVuc29yID0gd2FzbS5fT3J0Q3JlYXRlVGVuc29yKFxuICAgICAgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0oZGF0YVR5cGUpLFxuICAgICAgcmF3RGF0YSxcbiAgICAgIGRhdGFCeXRlTGVuZ3RoLFxuICAgICAgZGltc09mZnNldCxcbiAgICAgIGRpbXMubGVuZ3RoLFxuICAgICAgZGF0YUxvY2F0aW9uU3RyaW5nVG9FbnVtKGFjdHVhbExvY2F0aW9uKSxcbiAgICApO1xuICAgIGlmICh0ZW5zb3IgPT09IDApIHtcbiAgICAgIGNoZWNrTGFzdEVycm9yKGBDYW4ndCBjcmVhdGUgdGVuc29yIGZvciBpbnB1dC9vdXRwdXQuIHNlc3Npb249JHtzZXNzaW9uSWR9LCBpbmRleD0ke2luZGV4fS5gKTtcbiAgICB9XG4gICAgdGVuc29ySGFuZGxlcy5wdXNoKHRlbnNvcik7XG4gIH0gZmluYWxseSB7XG4gICAgd2FzbS5zdGFja1Jlc3RvcmUoc3RhY2spO1xuICB9XG59O1xuXG4vKipcbiAqIHBlcmZvcm0gaW5mZXJlbmNlIHJ1blxuICovXG5leHBvcnQgY29uc3QgcnVuID0gYXN5bmMgKFxuICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgaW5wdXRJbmRpY2VzOiBudW1iZXJbXSxcbiAgaW5wdXRUZW5zb3JzOiBUZW5zb3JNZXRhZGF0YVtdLFxuICBvdXRwdXRJbmRpY2VzOiBudW1iZXJbXSxcbiAgb3V0cHV0VGVuc29yczogQXJyYXk8VGVuc29yTWV0YWRhdGEgfCBudWxsPixcbiAgb3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zLFxuKTogUHJvbWlzZTxUZW5zb3JNZXRhZGF0YVtdPiA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBjb25zdCBwdHJTaXplID0gd2FzbS5QVFJfU0laRTtcbiAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xuICBpZiAoIXNlc3Npb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCBydW4gaW5mZXJlbmNlLiBpbnZhbGlkIHNlc3Npb24gaWQ6ICR7c2Vzc2lvbklkfWApO1xuICB9XG4gIGNvbnN0IHNlc3Npb25IYW5kbGUgPSBzZXNzaW9uWzBdO1xuICBjb25zdCBpbnB1dE5hbWVzVVRGOEVuY29kZWQgPSBzZXNzaW9uWzFdO1xuICBjb25zdCBvdXRwdXROYW1lc1VURjhFbmNvZGVkID0gc2Vzc2lvblsyXTtcbiAgY29uc3QgaW9CaW5kaW5nU3RhdGUgPSBzZXNzaW9uWzNdO1xuICBjb25zdCBlbmFibGVHcmFwaENhcHR1cmUgPSBzZXNzaW9uWzRdO1xuICBjb25zdCBpbnB1dE91dHB1dEJvdW5kID0gc2Vzc2lvbls1XTtcblxuICBjb25zdCBpbnB1dENvdW50ID0gaW5wdXRJbmRpY2VzLmxlbmd0aDtcbiAgY29uc3Qgb3V0cHV0Q291bnQgPSBvdXRwdXRJbmRpY2VzLmxlbmd0aDtcblxuICBsZXQgcnVuT3B0aW9uc0hhbmRsZSA9IDA7XG4gIGxldCBydW5PcHRpb25zQWxsb2NzOiBudW1iZXJbXSA9IFtdO1xuXG4gIGNvbnN0IGlucHV0VGVuc29ySGFuZGxlczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3Qgb3V0cHV0VGVuc29ySGFuZGxlczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgaW5wdXRPdXRwdXRBbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgY29uc3QgYmVmb3JlUnVuU3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xuICBjb25zdCBpbnB1dFZhbHVlc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhpbnB1dENvdW50ICogcHRyU2l6ZSk7XG4gIGNvbnN0IGlucHV0TmFtZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2MoaW5wdXRDb3VudCAqIHB0clNpemUpO1xuICBjb25zdCBvdXRwdXRWYWx1ZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2Mob3V0cHV0Q291bnQgKiBwdHJTaXplKTtcbiAgY29uc3Qgb3V0cHV0TmFtZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2Mob3V0cHV0Q291bnQgKiBwdHJTaXplKTtcblxuICB0cnkge1xuICAgIFtydW5PcHRpb25zSGFuZGxlLCBydW5PcHRpb25zQWxsb2NzXSA9IHNldFJ1bk9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICAvLyBjcmVhdGUgaW5wdXQgdGVuc29yc1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XG4gICAgICBhd2FpdCBwcmVwYXJlSW5wdXRPdXRwdXRUZW5zb3IoXG4gICAgICAgIGlucHV0VGVuc29yc1tpXSxcbiAgICAgICAgaW5wdXRUZW5zb3JIYW5kbGVzLFxuICAgICAgICBpbnB1dE91dHB1dEFsbG9jcyxcbiAgICAgICAgc2Vzc2lvbklkLFxuICAgICAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWRbaW5wdXRJbmRpY2VzW2ldXSxcbiAgICAgICAgaW5wdXRJbmRpY2VzW2ldLFxuICAgICAgICBlbmFibGVHcmFwaENhcHR1cmUsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSBvdXRwdXQgdGVuc29yc1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xuICAgICAgYXdhaXQgcHJlcGFyZUlucHV0T3V0cHV0VGVuc29yKFxuICAgICAgICBvdXRwdXRUZW5zb3JzW2ldLFxuICAgICAgICBvdXRwdXRUZW5zb3JIYW5kbGVzLFxuICAgICAgICBpbnB1dE91dHB1dEFsbG9jcyxcbiAgICAgICAgc2Vzc2lvbklkLFxuICAgICAgICBvdXRwdXROYW1lc1VURjhFbmNvZGVkW291dHB1dEluZGljZXNbaV1dLFxuICAgICAgICBpbnB1dENvdW50ICsgb3V0cHV0SW5kaWNlc1tpXSxcbiAgICAgICAgZW5hYmxlR3JhcGhDYXB0dXJlLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Q291bnQ7IGkrKykge1xuICAgICAgd2FzbS5zZXRWYWx1ZShpbnB1dFZhbHVlc09mZnNldCArIGkgKiBwdHJTaXplLCBpbnB1dFRlbnNvckhhbmRsZXNbaV0sICcqJyk7XG4gICAgICB3YXNtLnNldFZhbHVlKGlucHV0TmFtZXNPZmZzZXQgKyBpICogcHRyU2l6ZSwgaW5wdXROYW1lc1VURjhFbmNvZGVkW2lucHV0SW5kaWNlc1tpXV0sICcqJyk7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xuICAgICAgd2FzbS5zZXRWYWx1ZShvdXRwdXRWYWx1ZXNPZmZzZXQgKyBpICogcHRyU2l6ZSwgb3V0cHV0VGVuc29ySGFuZGxlc1tpXSwgJyonKTtcbiAgICAgIHdhc20uc2V0VmFsdWUob3V0cHV0TmFtZXNPZmZzZXQgKyBpICogcHRyU2l6ZSwgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZFtvdXRwdXRJbmRpY2VzW2ldXSwgJyonKTtcbiAgICB9XG5cbiAgICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQICYmIGlvQmluZGluZ1N0YXRlICYmICFpbnB1dE91dHB1dEJvdW5kKSB7XG4gICAgICBjb25zdCB7IGhhbmRsZSwgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zLCBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnNFbmNvZGVkIH0gPSBpb0JpbmRpbmdTdGF0ZTtcblxuICAgICAgaWYgKGlucHV0TmFtZXNVVEY4RW5jb2RlZC5sZW5ndGggIT09IGlucHV0Q291bnQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBpbnB1dCBjb3VudCBmcm9tIGZlZWRzICgke2lucHV0Q291bnR9KSBpcyBleHBlY3RlZCB0byBiZSBhbHdheXMgZXF1YWwgdG8gbW9kZWwncyBpbnB1dCBjb3VudCAoJHtpbnB1dE5hbWVzVVRGOEVuY29kZWQubGVuZ3RofSkuYCxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gcHJvY2VzcyBpbnB1dHNcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gaW5wdXRJbmRpY2VzW2ldO1xuICAgICAgICBjb25zdCBlcnJvckNvZGUgPSBhd2FpdCB3YXNtLl9PcnRCaW5kSW5wdXQoaGFuZGxlLCBpbnB1dE5hbWVzVVRGOEVuY29kZWRbaW5kZXhdLCBpbnB1dFRlbnNvckhhbmRsZXNbaV0pO1xuICAgICAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICAgICAgY2hlY2tMYXN0RXJyb3IoYENhbid0IGJpbmQgaW5wdXRbJHtpfV0gZm9yIHNlc3Npb249JHtzZXNzaW9uSWR9LmApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIHByb2Nlc3MgcHJlLWFsbG9jYXRlZCBvdXRwdXRzXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dENvdW50OyBpKyspIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBvdXRwdXRJbmRpY2VzW2ldO1xuICAgICAgICBjb25zdCBsb2NhdGlvbiA9IG91dHB1dFRlbnNvcnNbaV0/LlszXTsgLy8gdW5kZWZpbmVkIG1lYW5zIG91dHB1dCBpcyBub3QgcHJlLWFsbG9jYXRlZC5cblxuICAgICAgICBpZiAobG9jYXRpb24pIHtcbiAgICAgICAgICAvLyBvdXRwdXQgaXMgcHJlLWFsbG9jYXRlZC4gYmluZCB0aGUgdGVuc29yLlxuICAgICAgICAgIGNvbnN0IGVycm9yQ29kZSA9IHdhc20uX09ydEJpbmRPdXRwdXQoaGFuZGxlLCBvdXRwdXROYW1lc1VURjhFbmNvZGVkW2luZGV4XSwgb3V0cHV0VGVuc29ySGFuZGxlc1tpXSwgMCk7XG4gICAgICAgICAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xuICAgICAgICAgICAgY2hlY2tMYXN0RXJyb3IoYENhbid0IGJpbmQgcHJlLWFsbG9jYXRlZCBvdXRwdXRbJHtpfV0gZm9yIHNlc3Npb249JHtzZXNzaW9uSWR9LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBvdXRwdXQgaXMgbm90IHByZS1hbGxvY2F0ZWQuIHJlc2V0IHByZWZlcnJlZCBsb2NhdGlvbi5cbiAgICAgICAgICBjb25zdCBlcnJvckNvZGUgPSB3YXNtLl9PcnRCaW5kT3V0cHV0KFxuICAgICAgICAgICAgaGFuZGxlLFxuICAgICAgICAgICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZFtpbmRleF0sXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zRW5jb2RlZFtpbmRleF0sXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICAgICAgICBjaGVja0xhc3RFcnJvcihgQ2FuJ3QgYmluZCBvdXRwdXRbJHtpfV0gdG8gJHtvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnNbaV19IGZvciBzZXNzaW9uPSR7c2Vzc2lvbklkfS5gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGFjdGl2ZVNlc3Npb25zLnNldChzZXNzaW9uSWQsIFtcbiAgICAgICAgc2Vzc2lvbkhhbmRsZSxcbiAgICAgICAgaW5wdXROYW1lc1VURjhFbmNvZGVkLFxuICAgICAgICBvdXRwdXROYW1lc1VURjhFbmNvZGVkLFxuICAgICAgICBpb0JpbmRpbmdTdGF0ZSxcbiAgICAgICAgZW5hYmxlR3JhcGhDYXB0dXJlLFxuICAgICAgICB0cnVlLFxuICAgICAgXSk7XG4gICAgfVxuXG4gICAgd2FzbS5qc2VwT25SdW5TdGFydD8uKHNlc3Npb25IYW5kbGUpO1xuICAgIHdhc20ud2Vibm5PblJ1blN0YXJ0Py4oc2Vzc2lvbkhhbmRsZSk7XG5cbiAgICBsZXQgZXJyb3JDb2RlOiBudW1iZXI7XG4gICAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUCAmJiBpb0JpbmRpbmdTdGF0ZSkge1xuICAgICAgZXJyb3JDb2RlID0gYXdhaXQgd2FzbS5fT3J0UnVuV2l0aEJpbmRpbmcoXG4gICAgICAgIHNlc3Npb25IYW5kbGUsXG4gICAgICAgIGlvQmluZGluZ1N0YXRlLmhhbmRsZSxcbiAgICAgICAgb3V0cHV0Q291bnQsXG4gICAgICAgIG91dHB1dFZhbHVlc09mZnNldCxcbiAgICAgICAgcnVuT3B0aW9uc0hhbmRsZSxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVycm9yQ29kZSA9IGF3YWl0IHdhc20uX09ydFJ1bihcbiAgICAgICAgc2Vzc2lvbkhhbmRsZSxcbiAgICAgICAgaW5wdXROYW1lc09mZnNldCxcbiAgICAgICAgaW5wdXRWYWx1ZXNPZmZzZXQsXG4gICAgICAgIGlucHV0Q291bnQsXG4gICAgICAgIG91dHB1dE5hbWVzT2Zmc2V0LFxuICAgICAgICBvdXRwdXRDb3VudCxcbiAgICAgICAgb3V0cHV0VmFsdWVzT2Zmc2V0LFxuICAgICAgICBydW5PcHRpb25zSGFuZGxlLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICBjaGVja0xhc3RFcnJvcignZmFpbGVkIHRvIGNhbGwgT3J0UnVuKCkuJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0OiBUZW5zb3JNZXRhZGF0YVtdID0gW107XG4gICAgY29uc3Qgb3V0cHV0UHJvbWlzZXM6IEFycmF5PFByb21pc2U8W251bWJlciwgVGVuc29yLkRhdGFUeXBlXT4+ID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dENvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IHRlbnNvciA9IE51bWJlcih3YXNtLmdldFZhbHVlKG91dHB1dFZhbHVlc09mZnNldCArIGkgKiBwdHJTaXplLCAnKicpKTtcbiAgICAgIGlmICh0ZW5zb3IgPT09IG91dHB1dFRlbnNvckhhbmRsZXNbaV0pIHtcbiAgICAgICAgLy8gb3V0cHV0IHRlbnNvciBpcyBwcmUtYWxsb2NhdGVkLiBubyBuZWVkIHRvIGNvcHkgZGF0YS5cbiAgICAgICAgb3V0cHV0LnB1c2gob3V0cHV0VGVuc29yc1tpXSEpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYmVmb3JlR2V0VGVuc29yRGF0YVN0YWNrID0gd2FzbS5zdGFja1NhdmUoKTtcbiAgICAgIC8vIHN0YWNrIGFsbG9jYXRlIDQgcG9pbnRlciB2YWx1ZVxuICAgICAgY29uc3QgdGVuc29yRGF0YU9mZnNldCA9IHdhc20uc3RhY2tBbGxvYyg0ICogcHRyU2l6ZSk7XG5cbiAgICAgIGxldCBrZWVwT3V0cHV0VGVuc29yID0gZmFsc2U7XG4gICAgICBsZXQgdHlwZTogVGVuc29yLlR5cGUgfCB1bmRlZmluZWQsXG4gICAgICAgIGRhdGFPZmZzZXQgPSAwO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZXJyb3JDb2RlID0gd2FzbS5fT3J0R2V0VGVuc29yRGF0YShcbiAgICAgICAgICB0ZW5zb3IsXG4gICAgICAgICAgdGVuc29yRGF0YU9mZnNldCxcbiAgICAgICAgICB0ZW5zb3JEYXRhT2Zmc2V0ICsgcHRyU2l6ZSxcbiAgICAgICAgICB0ZW5zb3JEYXRhT2Zmc2V0ICsgMiAqIHB0clNpemUsXG5cbiAgICAgICAgICB0ZW5zb3JEYXRhT2Zmc2V0ICsgMyAqIHB0clNpemUsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICAgICAgICBjaGVja0xhc3RFcnJvcihgQ2FuJ3QgYWNjZXNzIG91dHB1dCB0ZW5zb3IgZGF0YSBvbiBpbmRleCAke2l9LmApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZhbHVlVHlwZSA9IHB0clNpemUgPT09IDQgPyAnaTMyJyA6ICdpNjQnO1xuICAgICAgICBjb25zdCBkYXRhVHlwZSA9IE51bWJlcih3YXNtLmdldFZhbHVlKHRlbnNvckRhdGFPZmZzZXQsIHZhbHVlVHlwZSkpO1xuICAgICAgICBkYXRhT2Zmc2V0ID0gd2FzbS5nZXRWYWx1ZSh0ZW5zb3JEYXRhT2Zmc2V0ICsgcHRyU2l6ZSwgJyonKTtcbiAgICAgICAgY29uc3QgZGltc09mZnNldCA9IHdhc20uZ2V0VmFsdWUodGVuc29yRGF0YU9mZnNldCArIHB0clNpemUgKiAyLCAnKicpO1xuICAgICAgICBjb25zdCBkaW1zTGVuZ3RoID0gTnVtYmVyKHdhc20uZ2V0VmFsdWUodGVuc29yRGF0YU9mZnNldCArIHB0clNpemUgKiAzLCB2YWx1ZVR5cGUpKTtcbiAgICAgICAgY29uc3QgZGltcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRpbXNMZW5ndGg7IGkrKykge1xuICAgICAgICAgIGRpbXMucHVzaChOdW1iZXIod2FzbS5nZXRWYWx1ZShkaW1zT2Zmc2V0ICsgaSAqIHB0clNpemUsIHZhbHVlVHlwZSkpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAod2FzbS5fT3J0RnJlZShkaW1zT2Zmc2V0KSAhPT0gMCkge1xuICAgICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgZnJlZSBtZW1vcnkgZm9yIHRlbnNvciBkaW1zLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzaXplID0gZGltcy5yZWR1Y2UoKGEsIGIpID0+IGEgKiBiLCAxKTtcbiAgICAgICAgdHlwZSA9IHRlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nKGRhdGFUeXBlKTtcblxuICAgICAgICBjb25zdCBwcmVmZXJyZWRMb2NhdGlvbiA9IGlvQmluZGluZ1N0YXRlPy5vdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnNbb3V0cHV0SW5kaWNlc1tpXV07XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgaWYgKHByZWZlcnJlZExvY2F0aW9uID09PSAnZ3B1LWJ1ZmZlcicgfHwgcHJlZmVycmVkTG9jYXRpb24gPT09ICdtbC10ZW5zb3InKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1N0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCBvbiBHUFUuJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHN0cmluZ0RhdGE6IHN0cmluZ1tdID0gW107XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHdhc20uZ2V0VmFsdWUoZGF0YU9mZnNldCArIGkgKiBwdHJTaXplLCAnKicpO1xuICAgICAgICAgICAgY29uc3QgbmV4dE9mZnNldCA9IHdhc20uZ2V0VmFsdWUoZGF0YU9mZnNldCArIChpICsgMSkgKiBwdHJTaXplLCAnKicpO1xuICAgICAgICAgICAgY29uc3QgbWF4Qnl0ZXNUb1JlYWQgPSBpID09PSBzaXplIC0gMSA/IHVuZGVmaW5lZCA6IG5leHRPZmZzZXQgLSBvZmZzZXQ7XG4gICAgICAgICAgICBzdHJpbmdEYXRhLnB1c2god2FzbS5VVEY4VG9TdHJpbmcob2Zmc2V0LCBtYXhCeXRlc1RvUmVhZCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvdXRwdXQucHVzaChbdHlwZSwgZGltcywgc3RyaW5nRGF0YSwgJ2NwdSddKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBJZiBhIGNlcnRhaW4gb3V0cHV0J3MgcHJlZmVycmVkIGxvY2F0aW9uIGlzIEdQVSBidXQgdGhlIHRlbnNvciBpcyBlbXB0eSwgd2Ugc3RpbGwgbmVlZCB0byBjcmVhdGUgYSBDUFVcbiAgICAgICAgICAvLyB0ZW5zb3IgZm9yIGl0LiBUaGVyZSBpcyBubyBtYXBwaW5nIEdQVSBidWZmZXIgZm9yIGFuIGVtcHR5IHRlbnNvci5cbiAgICAgICAgICBpZiAocHJlZmVycmVkTG9jYXRpb24gPT09ICdncHUtYnVmZmVyJyAmJiBzaXplID4gMCkge1xuICAgICAgICAgICAgY29uc3QgZ2V0QnVmZmVyID0gQlVJTERfREVGUy5VU0VfV0VCR1BVX0VQID8gd2FzbS53ZWJncHVHZXRCdWZmZXIgOiB3YXNtLmpzZXBHZXRCdWZmZXI7XG4gICAgICAgICAgICBpZiAoIWdldEJ1ZmZlcikge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ByZWZlcnJlZExvY2F0aW9uIFwiZ3B1LWJ1ZmZlclwiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJHUFUuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBncHVCdWZmZXIgPSBnZXRCdWZmZXIoZGF0YU9mZnNldCk7XG4gICAgICAgICAgICBjb25zdCBidWZmZXJTaXplID0gY2FsY3VsYXRlVGVuc29yU2l6ZUluQnl0ZXMoZGF0YVR5cGUsIHNpemUpO1xuICAgICAgICAgICAgaWYgKGJ1ZmZlclNpemUgPT09IHVuZGVmaW5lZCB8fCAhaXNHcHVCdWZmZXJTdXBwb3J0ZWRUeXBlKHR5cGUpKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGV9YCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGRvIG5vdCByZWxlYXNlIHRoZSB0ZW5zb3IgcmlnaHQgbm93LiBpdCB3aWxsIGJlIHJlbGVhc2VkIHdoZW4gdXNlciBjYWxscyB0ZW5zb3IuZGlzcG9zZSgpLlxuICAgICAgICAgICAga2VlcE91dHB1dFRlbnNvciA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChCVUlMRF9ERUZTLlVTRV9XRUJHUFVfRVApIHtcbiAgICAgICAgICAgICAgd2FzbS53ZWJncHVSZWdpc3RlckJ1ZmZlciEoZ3B1QnVmZmVyLCBzZXNzaW9uSWQsIGRhdGFPZmZzZXQpO1xuICAgICAgICAgICAgICBjb25zdCBkb3dubG9hZERhdGFGdW5jdGlvbiA9IHdhc20ud2ViZ3B1Q3JlYXRlRG93bmxvYWRlciEoZ3B1QnVmZmVyLCBidWZmZXJTaXplLCBzZXNzaW9uSWQpO1xuICAgICAgICAgICAgICBvdXRwdXQucHVzaChbXG4gICAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgICBkaW1zLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGdwdUJ1ZmZlcixcbiAgICAgICAgICAgICAgICAgIGRvd25sb2FkOiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGFycmF5QnVmZmVyID0gYXdhaXQgZG93bmxvYWREYXRhRnVuY3Rpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IG5ldyAodGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yKHR5cGUhKSkoYXJyYXlCdWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YSBhcyBUZW5zb3IuRGF0YVR5cGVNYXBbVGVuc29yLkdwdUJ1ZmZlckRhdGFUeXBlc107XG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgZGlzcG9zZTogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2FzbS5fT3J0UmVsZWFzZVRlbnNvcih0ZW5zb3IpICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIHRlbnNvci5cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAnZ3B1LWJ1ZmZlcicsXG4gICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgb3V0cHV0LnB1c2goW1xuICAgICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICAgICAgZGltcyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBncHVCdWZmZXIsXG4gICAgICAgICAgICAgICAgICBkb3dubG9hZDogd2FzbS5qc2VwQ3JlYXRlRG93bmxvYWRlciEoZ3B1QnVmZmVyLCBidWZmZXJTaXplLCB0eXBlKSxcbiAgICAgICAgICAgICAgICAgIGRpc3Bvc2U6ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhc20uX09ydFJlbGVhc2VUZW5zb3IodGVuc29yKSAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgcmVsZWFzZSB0ZW5zb3IuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ2dwdS1idWZmZXInLFxuICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKHByZWZlcnJlZExvY2F0aW9uID09PSAnbWwtdGVuc29yJyAmJiBzaXplID4gMCkge1xuICAgICAgICAgICAgY29uc3QgZW5zdXJlVGVuc29yID0gd2FzbS53ZWJubkVuc3VyZVRlbnNvcjtcbiAgICAgICAgICAgIGNvbnN0IGlzR3JhcGhJbnB1dE91dHB1dFR5cGVTdXBwb3J0ZWQgPSB3YXNtLndlYm5uSXNHcmFwaElucHV0T3V0cHV0VHlwZVN1cHBvcnRlZDtcbiAgICAgICAgICAgIGlmICghZW5zdXJlVGVuc29yIHx8ICFpc0dyYXBoSW5wdXRPdXRwdXRUeXBlU3VwcG9ydGVkKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncHJlZmVycmVkTG9jYXRpb24gXCJtbC10ZW5zb3JcIiBpcyBub3Qgc3VwcG9ydGVkIHdpdGhvdXQgdXNpbmcgV2ViTk4uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB0ZW5zb3JTaXplID0gY2FsY3VsYXRlVGVuc29yU2l6ZUluQnl0ZXMoZGF0YVR5cGUsIHNpemUpO1xuICAgICAgICAgICAgaWYgKHRlbnNvclNpemUgPT09IHVuZGVmaW5lZCB8fCAhaXNNTFRlbnNvclN1cHBvcnRlZFR5cGUodHlwZSkpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dHlwZX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNHcmFwaElucHV0T3V0cHV0VHlwZVN1cHBvcnRlZChzZXNzaW9uSWQsIHR5cGUsIGZhbHNlKSkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgYHByZWZlcnJlZExvY2F0aW9uIFwibWwtdGVuc29yXCIgZm9yICR7dHlwZX0gb3V0cHV0IGlzIG5vdCBzdXBwb3J0ZWQgYnkgY3VycmVudCBXZWJOTiBDb250ZXh0LmAsXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElmIHRoZSBncmFwaCBoYXMgYmVlbiBwYXJ0aXRpb25lZCwgdGhlIG91dHB1dCB0ZW5zb3IgbWF5IGhhdmUgbm90IGJlZW4gY3JlYXRlZC4gRm9yIHRoaXMgcmVhc29uLCB3ZSB1c2VcbiAgICAgICAgICAgIC8vIGVuc3VyZVRlbnNvciB0byBnZXQvY3JlYXRlIHRoZSBNTFRlbnNvci4gSW4gd2hpY2ggY2FzZSwgd2UgZG9uJ3QgbmVlZCB0byBjb3B5IHRoZSBkYXRhIGlmIGEgbmV3IHRlbnNvclxuICAgICAgICAgICAgLy8gaGFzIGJlZW4gY3JlYXRlZC5cbiAgICAgICAgICAgIGNvbnN0IG1sVGVuc29yID0gYXdhaXQgZW5zdXJlVGVuc29yKHNlc3Npb25JZCwgZGF0YU9mZnNldCwgZGF0YVR5cGUsIGRpbXMsIGZhbHNlKTtcblxuICAgICAgICAgICAgLy8gZG8gbm90IHJlbGVhc2UgdGhlIHRlbnNvciByaWdodCBub3cuIGl0IHdpbGwgYmUgcmVsZWFzZWQgd2hlbiB1c2VyIGNhbGxzIHRlbnNvci5kaXNwb3NlKCkuXG4gICAgICAgICAgICBrZWVwT3V0cHV0VGVuc29yID0gdHJ1ZTtcblxuICAgICAgICAgICAgb3V0cHV0LnB1c2goW1xuICAgICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgICBkaW1zLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbWxUZW5zb3IsXG4gICAgICAgICAgICAgICAgZG93bmxvYWQ6IHdhc20ud2Vibm5DcmVhdGVNTFRlbnNvckRvd25sb2FkZXIhKGRhdGFPZmZzZXQsIHR5cGUpLFxuICAgICAgICAgICAgICAgIGRpc3Bvc2U6ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgIHdhc20ud2Vibm5SZWxlYXNlVGVuc29ySWQhKGRhdGFPZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVRlbnNvcih0ZW5zb3IpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICdtbC10ZW5zb3InLFxuICAgICAgICAgICAgXSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChwcmVmZXJyZWRMb2NhdGlvbiA9PT0gJ21sLXRlbnNvci1jcHUtb3V0cHV0JyAmJiBzaXplID4gMCkge1xuICAgICAgICAgICAgY29uc3QgZGF0YSA9IHdhc20ud2Vibm5DcmVhdGVNTFRlbnNvckRvd25sb2FkZXIhKGRhdGFPZmZzZXQsIHR5cGUgYXMgVGVuc29yLk1MVGVuc29yRGF0YVR5cGVzKSgpO1xuICAgICAgICAgICAgY29uc3QgaW5kZXggPSBvdXRwdXQubGVuZ3RoO1xuICAgICAgICAgICAgLy8gRGVsYXkgdGhlIGRhdGEgZG93bmxvYWQgYW5kIHJlbGVhc2luZyB0aGUgdGVuc29yIHVudGlsIHdlIGNhbiB3YWl0IGZvciBhbGwgb3V0cHV0IHRlbnNvcnMgdG8gYmUgZG93bmxvYWRlZC5cbiAgICAgICAgICAgIGtlZXBPdXRwdXRUZW5zb3IgPSB0cnVlO1xuICAgICAgICAgICAgb3V0cHV0UHJvbWlzZXMucHVzaChcbiAgICAgICAgICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQ6IFtudW1iZXIsIFRlbnNvci5EYXRhVHlwZV0gPSBbaW5kZXgsIGF3YWl0IGRhdGFdO1xuICAgICAgICAgICAgICAgIHdhc20ud2Vibm5SZWxlYXNlVGVuc29ySWQhKGRhdGFPZmZzZXQpO1xuICAgICAgICAgICAgICAgIHdhc20uX09ydFJlbGVhc2VUZW5zb3IodGVuc29yKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICB9KSgpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIG91dHB1dC5wdXNoKFt0eXBlLCBkaW1zLCBbXSwgJ2NwdSddKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgdHlwZWRBcnJheUNvbnN0cnVjdG9yID0gdGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yKHR5cGUpO1xuICAgICAgICAgICAgY29uc3QgZGF0YSA9IG5ldyB0eXBlZEFycmF5Q29uc3RydWN0b3Ioc2l6ZSk7XG4gICAgICAgICAgICBuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhLmJ5dGVMZW5ndGgpLnNldChcbiAgICAgICAgICAgICAgd2FzbS5IRUFQVTguc3ViYXJyYXkoZGF0YU9mZnNldCwgZGF0YU9mZnNldCArIGRhdGEuYnl0ZUxlbmd0aCksXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgb3V0cHV0LnB1c2goW3R5cGUsIGRpbXMsIGRhdGEsICdjcHUnXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB3YXNtLnN0YWNrUmVzdG9yZShiZWZvcmVHZXRUZW5zb3JEYXRhU3RhY2spO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycgJiYgZGF0YU9mZnNldCkge1xuICAgICAgICAgIHdhc20uX2ZyZWUoZGF0YU9mZnNldCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFrZWVwT3V0cHV0VGVuc29yKSB7XG4gICAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVRlbnNvcih0ZW5zb3IpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlvQmluZGluZ1N0YXRlICYmICFlbmFibGVHcmFwaENhcHR1cmUpIHtcbiAgICAgIGlmICh3YXNtLl9PcnRDbGVhckJvdW5kT3V0cHV0cyhpb0JpbmRpbmdTdGF0ZS5oYW5kbGUpICE9PSAwKSB7XG4gICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgY2xlYXIgYm91bmQgb3V0cHV0cy5cIik7XG4gICAgICB9XG4gICAgICBhY3RpdmVTZXNzaW9ucy5zZXQoc2Vzc2lvbklkLCBbXG4gICAgICAgIHNlc3Npb25IYW5kbGUsXG4gICAgICAgIGlucHV0TmFtZXNVVEY4RW5jb2RlZCxcbiAgICAgICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZCxcbiAgICAgICAgaW9CaW5kaW5nU3RhdGUsXG4gICAgICAgIGVuYWJsZUdyYXBoQ2FwdHVyZSxcbiAgICAgICAgZmFsc2UsXG4gICAgICBdKTtcbiAgICB9XG4gICAgLy8gV2FpdCBmb3IgYWxsIG91dHB1dCB0ZW5zb3IgZGF0YSB0byBiZSBkb3dubG9hZGVkLlxuICAgIGZvciAoY29uc3QgW2luZGV4LCBkYXRhXSBvZiBhd2FpdCBQcm9taXNlLmFsbChvdXRwdXRQcm9taXNlcykpIHtcbiAgICAgIG91dHB1dFtpbmRleF1bMl0gPSBkYXRhO1xuICAgIH1cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9IGZpbmFsbHkge1xuICAgIHdhc20ud2Vibm5PblJ1bkVuZD8uKHNlc3Npb25IYW5kbGUpO1xuXG4gICAgd2FzbS5zdGFja1Jlc3RvcmUoYmVmb3JlUnVuU3RhY2spO1xuXG4gICAgaWYgKEJVSUxEX0RFRlMuVVNFX1dFQkdQVV9FUCkge1xuICAgICAgaW5wdXRUZW5zb3JzLmZvckVhY2goKHQpID0+IHtcbiAgICAgICAgaWYgKHQgJiYgdFszXSA9PT0gJ2dwdS1idWZmZXInKSB7XG4gICAgICAgICAgd2FzbS53ZWJncHVVbnJlZ2lzdGVyQnVmZmVyISh0WzJdLmdwdUJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgb3V0cHV0VGVuc29ycy5mb3JFYWNoKCh0KSA9PiB7XG4gICAgICAgIGlmICh0ICYmIHRbM10gPT09ICdncHUtYnVmZmVyJykge1xuICAgICAgICAgIHdhc20ud2ViZ3B1VW5yZWdpc3RlckJ1ZmZlciEodFsyXS5ncHVCdWZmZXIpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgaW5wdXRUZW5zb3JIYW5kbGVzLmZvckVhY2goKHYpID0+IHdhc20uX09ydFJlbGVhc2VUZW5zb3IodikpO1xuICAgIG91dHB1dFRlbnNvckhhbmRsZXMuZm9yRWFjaCgodikgPT4gd2FzbS5fT3J0UmVsZWFzZVRlbnNvcih2KSk7XG4gICAgaW5wdXRPdXRwdXRBbGxvY3MuZm9yRWFjaCgocCkgPT4gd2FzbS5fZnJlZShwKSk7XG5cbiAgICBpZiAocnVuT3B0aW9uc0hhbmRsZSAhPT0gMCkge1xuICAgICAgd2FzbS5fT3J0UmVsZWFzZVJ1bk9wdGlvbnMocnVuT3B0aW9uc0hhbmRsZSk7XG4gICAgfVxuICAgIHJ1bk9wdGlvbnNBbGxvY3MuZm9yRWFjaCgocCkgPT4gd2FzbS5fZnJlZShwKSk7XG4gIH1cbn07XG5cbi8qKlxuICogZW5kIHByb2ZpbGluZ1xuICovXG5leHBvcnQgY29uc3QgZW5kUHJvZmlsaW5nID0gKHNlc3Npb25JZDogbnVtYmVyKTogdm9pZCA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBjb25zdCBzZXNzaW9uID0gYWN0aXZlU2Vzc2lvbnMuZ2V0KHNlc3Npb25JZCk7XG4gIGlmICghc2Vzc2lvbikge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBzZXNzaW9uIGlkJyk7XG4gIH1cbiAgY29uc3Qgc2Vzc2lvbkhhbmRsZSA9IHNlc3Npb25bMF07XG5cbiAgLy8gcHJvZmlsZSBmaWxlIG5hbWUgaXMgbm90IHVzZWQgeWV0LCBidXQgaXQgbXVzdCBiZSBmcmVlZC5cbiAgY29uc3QgcHJvZmlsZUZpbGVOYW1lID0gd2FzbS5fT3J0RW5kUHJvZmlsaW5nKHNlc3Npb25IYW5kbGUpO1xuICBpZiAocHJvZmlsZUZpbGVOYW1lID09PSAwKSB7XG4gICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBnZXQgYW4gcHJvZmlsZSBmaWxlIG5hbWUuXCIpO1xuICB9XG4gIHdhc20uX09ydEZyZWUocHJvZmlsZUZpbGVOYW1lKTtcbn07XG5cbmV4cG9ydCBjb25zdCBleHRyYWN0VHJhbnNmZXJhYmxlQnVmZmVycyA9ICh0ZW5zb3JzOiByZWFkb25seSBTZXJpYWxpemFibGVUZW5zb3JNZXRhZGF0YVtdKTogQXJyYXlCdWZmZXJMaWtlW10gPT4ge1xuICBjb25zdCBidWZmZXJzOiBBcnJheUJ1ZmZlckxpa2VbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHRlbnNvciBvZiB0ZW5zb3JzKSB7XG4gICAgY29uc3QgZGF0YSA9IHRlbnNvclsyXTtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkgJiYgJ2J1ZmZlcicgaW4gZGF0YSkge1xuICAgICAgYnVmZmVycy5wdXNoKGRhdGEuYnVmZmVyKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJ1ZmZlcnM7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBlbnYsIEluZmVyZW5jZVNlc3Npb24gfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge1xuICBPcnRXYXNtTWVzc2FnZSxcbiAgU2VyaWFsaXphYmxlSW50ZXJuYWxCdWZmZXIsXG4gIFNlcmlhbGl6YWJsZVNlc3Npb25NZXRhZGF0YSxcbiAgU2VyaWFsaXphYmxlVGVuc29yTWV0YWRhdGEsXG4gIFRlbnNvck1ldGFkYXRhLFxufSBmcm9tICcuL3Byb3h5LW1lc3NhZ2VzJztcbmltcG9ydCAqIGFzIGNvcmUgZnJvbSAnLi93YXNtLWNvcmUtaW1wbCc7XG5pbXBvcnQgeyBpbml0aWFsaXplV2ViQXNzZW1ibHkgfSBmcm9tICcuL3dhc20tZmFjdG9yeSc7XG5pbXBvcnQge1xuICBpbXBvcnRQcm94eVdvcmtlcixcbiAgaW5mZXJXYXNtUGF0aFByZWZpeEZyb21TY3JpcHRTcmMsXG4gIGlzRXNtSW1wb3J0TWV0YVVybEhhcmRjb2RlZEFzRmlsZVVyaSxcbn0gZnJvbSAnLi93YXNtLXV0aWxzLWltcG9ydCc7XG5cbmNvbnN0IGlzUHJveHkgPSAoKTogYm9vbGVhbiA9PiAhIWVudi53YXNtLnByb3h5ICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCc7XG5sZXQgcHJveHlXb3JrZXI6IFdvcmtlciB8IHVuZGVmaW5lZDtcbmxldCBpbml0aWFsaXppbmcgPSBmYWxzZTtcbmxldCBpbml0aWFsaXplZCA9IGZhbHNlO1xubGV0IGFib3J0ZWQgPSBmYWxzZTtcbmxldCB0ZW1wb3JhcnlPYmplY3RVcmw6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxudHlwZSBQcm9taXNlQ2FsbGJhY2tzPFQgPSB2b2lkPiA9IFtyZXNvbHZlOiAocmVzdWx0OiBUKSA9PiB2b2lkLCByZWplY3Q6IChyZWFzb246IHVua25vd24pID0+IHZvaWRdO1xubGV0IGluaXRXYXNtQ2FsbGJhY2tzOiBQcm9taXNlQ2FsbGJhY2tzO1xuY29uc3QgcXVldWVkQ2FsbGJhY2tzOiBNYXA8T3J0V2FzbU1lc3NhZ2VbJ3R5cGUnXSwgQXJyYXk8UHJvbWlzZUNhbGxiYWNrczx1bmtub3duPj4+ID0gbmV3IE1hcCgpO1xuXG5jb25zdCBlbnF1ZXVlQ2FsbGJhY2tzID0gKHR5cGU6IE9ydFdhc21NZXNzYWdlWyd0eXBlJ10sIGNhbGxiYWNrczogUHJvbWlzZUNhbGxiYWNrczx1bmtub3duPik6IHZvaWQgPT4ge1xuICBjb25zdCBxdWV1ZSA9IHF1ZXVlZENhbGxiYWNrcy5nZXQodHlwZSk7XG4gIGlmIChxdWV1ZSkge1xuICAgIHF1ZXVlLnB1c2goY2FsbGJhY2tzKTtcbiAgfSBlbHNlIHtcbiAgICBxdWV1ZWRDYWxsYmFja3Muc2V0KHR5cGUsIFtjYWxsYmFja3NdKTtcbiAgfVxufTtcblxuY29uc3QgZW5zdXJlV29ya2VyID0gKCk6IHZvaWQgPT4ge1xuICBpZiAoaW5pdGlhbGl6aW5nIHx8ICFpbml0aWFsaXplZCB8fCBhYm9ydGVkIHx8ICFwcm94eVdvcmtlcikge1xuICAgIHRocm93IG5ldyBFcnJvcignd29ya2VyIG5vdCByZWFkeScpO1xuICB9XG59O1xuXG5jb25zdCBvblByb3h5V29ya2VyTWVzc2FnZSA9IChldjogTWVzc2FnZUV2ZW50PE9ydFdhc21NZXNzYWdlPik6IHZvaWQgPT4ge1xuICBzd2l0Y2ggKGV2LmRhdGEudHlwZSkge1xuICAgIGNhc2UgJ2luaXQtd2FzbSc6XG4gICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICBhYm9ydGVkID0gdHJ1ZTtcbiAgICAgICAgaW5pdFdhc21DYWxsYmFja3NbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICBpbml0V2FzbUNhbGxiYWNrc1swXSgpO1xuICAgICAgfVxuICAgICAgaWYgKHRlbXBvcmFyeU9iamVjdFVybCkge1xuICAgICAgICBVUkwucmV2b2tlT2JqZWN0VVJMKHRlbXBvcmFyeU9iamVjdFVybCk7XG4gICAgICAgIHRlbXBvcmFyeU9iamVjdFVybCA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2luaXQtZXAnOlxuICAgIGNhc2UgJ2NvcHktZnJvbSc6XG4gICAgY2FzZSAnY3JlYXRlJzpcbiAgICBjYXNlICdyZWxlYXNlJzpcbiAgICBjYXNlICdydW4nOlxuICAgIGNhc2UgJ2VuZC1wcm9maWxpbmcnOiB7XG4gICAgICBjb25zdCBjYWxsYmFja3MgPSBxdWV1ZWRDYWxsYmFja3MuZ2V0KGV2LmRhdGEudHlwZSkhO1xuICAgICAgaWYgKGV2LmRhdGEuZXJyKSB7XG4gICAgICAgIGNhbGxiYWNrcy5zaGlmdCgpIVsxXShldi5kYXRhLmVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFja3Muc2hpZnQoKSFbMF0oZXYuZGF0YS5vdXQhKTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICB9XG59O1xuXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZVdlYkFzc2VtYmx5QW5kT3J0UnVudGltZSA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKGluaXRpYWxpemVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChpbml0aWFsaXppbmcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJtdWx0aXBsZSBjYWxscyB0byAnaW5pdFdhc20oKScgZGV0ZWN0ZWQuXCIpO1xuICB9XG4gIGlmIChhYm9ydGVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwicHJldmlvdXMgY2FsbCB0byAnaW5pdFdhc20oKScgZmFpbGVkLlwiKTtcbiAgfVxuXG4gIGluaXRpYWxpemluZyA9IHRydWU7XG5cbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgcHJveHlXb3JrZXI/LnRlcm1pbmF0ZSgpO1xuXG4gICAgICB2b2lkIGltcG9ydFByb3h5V29ya2VyKCkudGhlbigoW29iamVjdFVybCwgd29ya2VyXSkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHByb3h5V29ya2VyID0gd29ya2VyO1xuICAgICAgICAgIHByb3h5V29ya2VyLm9uZXJyb3IgPSAoZXY6IEVycm9yRXZlbnQpID0+IHJlamVjdChldik7XG4gICAgICAgICAgcHJveHlXb3JrZXIub25tZXNzYWdlID0gb25Qcm94eVdvcmtlck1lc3NhZ2U7XG4gICAgICAgICAgaW5pdFdhc21DYWxsYmFja3MgPSBbcmVzb2x2ZSwgcmVqZWN0XTtcbiAgICAgICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHsgdHlwZTogJ2luaXQtd2FzbScsIGluOiBlbnYgfTtcblxuICAgICAgICAgIC8vIGlmIHRoZSBwcm94eSB3b3JrZXIgaXMgbG9hZGVkIGZyb20gYSBibG9iIFVSTCwgd2UgbmVlZCB0byBtYWtlIHN1cmUgdGhlIHBhdGggaW5mb3JtYXRpb24gaXMgbm90IGxvc3QuXG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyB3aGVuIGBlbnYud2FzbS53YXNtUGF0aHNgIGlzIG5vdCBzZXQsIHdlIG5lZWQgdG8gcGFzcyB0aGUgcGF0aCBpbmZvcm1hdGlvbiB0byB0aGUgd29ya2VyLlxuICAgICAgICAgIC8vXG4gICAgICAgICAgaWYgKCFCVUlMRF9ERUZTLkVOQUJMRV9CVU5ETEVfV0FTTV9KUyAmJiAhbWVzc2FnZS5pbiEud2FzbS53YXNtUGF0aHMgJiYgb2JqZWN0VXJsKSB7XG4gICAgICAgICAgICAvLyBmb3IgYSBidWlsZCBub3QgYnVuZGxlZCB0aGUgd2FzbSBKUywgd2UgbmVlZCB0byBwYXNzIHRoZSBwYXRoIHByZWZpeCB0byB0aGUgd29ya2VyLlxuICAgICAgICAgICAgLy8gdGhlIHBhdGggcHJlZml4IHdpbGwgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwYXRoIHRvIGJvdGggdGhlIHdhc20gSlMgYW5kIHRoZSB3YXNtIGZpbGUuXG4gICAgICAgICAgICBjb25zdCBpbmZlcnJlZFdhc21QYXRoUHJlZml4ID0gaW5mZXJXYXNtUGF0aFByZWZpeEZyb21TY3JpcHRTcmMoKTtcbiAgICAgICAgICAgIGlmIChpbmZlcnJlZFdhc21QYXRoUHJlZml4KSB7XG4gICAgICAgICAgICAgIG1lc3NhZ2UuaW4hLndhc20ud2FzbVBhdGhzID0gaW5mZXJyZWRXYXNtUGF0aFByZWZpeDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBCVUlMRF9ERUZTLklTX0VTTSAmJlxuICAgICAgICAgICAgQlVJTERfREVGUy5FTkFCTEVfQlVORExFX1dBU01fSlMgJiZcbiAgICAgICAgICAgICFtZXNzYWdlLmluIS53YXNtLndhc21QYXRocyAmJlxuICAgICAgICAgICAgKG9iamVjdFVybCB8fCBpc0VzbUltcG9ydE1ldGFVcmxIYXJkY29kZWRBc0ZpbGVVcmkpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICAvLyBmb3IgYSBidWlsZCBidW5kbGVkIHRoZSB3YXNtIEpTLCBpZiBlaXRoZXIgb2YgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGlzIG1ldDpcbiAgICAgICAgICAgIC8vIC0gdGhlIHByb3h5IHdvcmtlciBpcyBsb2FkZWQgZnJvbSBhIGJsb2IgVVJMXG4gICAgICAgICAgICAvLyAtIGBpbXBvcnQubWV0YS51cmxgIGlzIGEgZmlsZSBVUkwsIGl0IG1lYW5zIGl0IGlzIG92ZXJ3cml0ZW4gYnkgdGhlIGJ1bmRsZXIuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gaW4gZWl0aGVyIGNhc2UsIHRoZSBwYXRoIGluZm9ybWF0aW9uIGlzIGxvc3QsIHdlIG5lZWQgdG8gcGFzcyB0aGUgcGF0aCBvZiB0aGUgLndhc20gZmlsZSB0byB0aGUgd29ya2VyLlxuICAgICAgICAgICAgLy8gd2UgbmVlZCB0byB1c2UgdGhlIGJ1bmRsZXIgcHJlZmVycmVkIFVSTCBmb3JtYXQ6XG4gICAgICAgICAgICAvLyBuZXcgVVJMKCdmaWxlbmFtZScsIGltcG9ydC5tZXRhLnVybClcbiAgICAgICAgICAgIC8vIHNvIHRoYXQgdGhlIGJ1bmRsZXIgY2FuIGhhbmRsZSB0aGUgZmlsZSB1c2luZyBjb3JyZXNwb25kaW5nIGxvYWRlcnMuXG4gICAgICAgICAgICBtZXNzYWdlLmluIS53YXNtLndhc21QYXRocyA9IHtcbiAgICAgICAgICAgICAgd2FzbTogIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQXG4gICAgICAgICAgICAgICAgPyBuZXcgVVJMKCdvcnQtd2FzbS1zaW1kLXRocmVhZGVkLmpzZXAud2FzbScsIEJVSUxEX0RFRlMuRVNNX0lNUE9SVF9NRVRBX1VSTCkuaHJlZlxuICAgICAgICAgICAgICAgIDogbmV3IFVSTCgnb3J0LXdhc20tc2ltZC10aHJlYWRlZC53YXNtJywgQlVJTERfREVGUy5FU01fSU1QT1JUX01FVEFfVVJMKS5ocmVmLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcHJveHlXb3JrZXIucG9zdE1lc3NhZ2UobWVzc2FnZSk7XG4gICAgICAgICAgdGVtcG9yYXJ5T2JqZWN0VXJsID0gb2JqZWN0VXJsO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9LCByZWplY3QpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBpbml0aWFsaXplV2ViQXNzZW1ibHkoZW52Lndhc20pO1xuICAgICAgYXdhaXQgY29yZS5pbml0UnVudGltZShlbnYpO1xuICAgICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGFib3J0ZWQgPSB0cnVlO1xuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZU9ydEVwID0gYXN5bmMgKGVwTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgZW5zdXJlV29ya2VyKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGVucXVldWVDYWxsYmFja3MoJ2luaXQtZXAnLCBbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHsgdHlwZTogJ2luaXQtZXAnLCBpbjogeyBlcE5hbWUsIGVudiB9IH07XG4gICAgICBwcm94eVdvcmtlciEucG9zdE1lc3NhZ2UobWVzc2FnZSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgYXdhaXQgY29yZS5pbml0RXAoZW52LCBlcE5hbWUpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgY29weUZyb21FeHRlcm5hbEJ1ZmZlciA9IGFzeW5jIChidWZmZXI6IFVpbnQ4QXJyYXkpOiBQcm9taXNlPFNlcmlhbGl6YWJsZUludGVybmFsQnVmZmVyPiA9PiB7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgZW5zdXJlV29ya2VyKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPFNlcmlhbGl6YWJsZUludGVybmFsQnVmZmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBlbnF1ZXVlQ2FsbGJhY2tzKCdjb3B5LWZyb20nLCBbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHsgdHlwZTogJ2NvcHktZnJvbScsIGluOiB7IGJ1ZmZlciB9IH07XG4gICAgICBwcm94eVdvcmtlciEucG9zdE1lc3NhZ2UobWVzc2FnZSwgW2J1ZmZlci5idWZmZXJdKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY29yZS5jb3B5RnJvbUV4dGVybmFsQnVmZmVyKGJ1ZmZlcik7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVTZXNzaW9uID0gYXN5bmMgKFxuICBtb2RlbDogU2VyaWFsaXphYmxlSW50ZXJuYWxCdWZmZXIgfCBVaW50OEFycmF5LFxuICBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyxcbik6IFByb21pc2U8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPiA9PiB7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgLy8gY2hlY2sgdW5zdXBwb3J0ZWQgb3B0aW9uc1xuICAgIGlmIChvcHRpb25zPy5wcmVmZXJyZWRPdXRwdXRMb2NhdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzZXNzaW9uIG9wdGlvbiBcInByZWZlcnJlZE91dHB1dExvY2F0aW9uXCIgaXMgbm90IHN1cHBvcnRlZCBmb3IgcHJveHkuJyk7XG4gICAgfVxuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGE+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGVucXVldWVDYWxsYmFja3MoJ2NyZWF0ZScsIFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0geyB0eXBlOiAnY3JlYXRlJywgaW46IHsgbW9kZWwsIG9wdGlvbnM6IHsgLi4ub3B0aW9ucyB9IH0gfTtcbiAgICAgIGNvbnN0IHRyYW5zZmVyYWJsZTogVHJhbnNmZXJhYmxlW10gPSBbXTtcbiAgICAgIGlmIChtb2RlbCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICAgICAgdHJhbnNmZXJhYmxlLnB1c2gobW9kZWwuYnVmZmVyKTtcbiAgICAgIH1cbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlLCB0cmFuc2ZlcmFibGUpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBjb3JlLmNyZWF0ZVNlc3Npb24obW9kZWwsIG9wdGlvbnMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVsZWFzZVNlc3Npb24gPSBhc3luYyAoc2Vzc2lvbklkOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZW5xdWV1ZUNhbGxiYWNrcygncmVsZWFzZScsIFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0geyB0eXBlOiAncmVsZWFzZScsIGluOiBzZXNzaW9uSWQgfTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBjb3JlLnJlbGVhc2VTZXNzaW9uKHNlc3Npb25JZCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBydW4gPSBhc3luYyAoXG4gIHNlc3Npb25JZDogbnVtYmVyLFxuICBpbnB1dEluZGljZXM6IG51bWJlcltdLFxuICBpbnB1dHM6IFRlbnNvck1ldGFkYXRhW10sXG4gIG91dHB1dEluZGljZXM6IG51bWJlcltdLFxuICBvdXRwdXRzOiBBcnJheTxUZW5zb3JNZXRhZGF0YSB8IG51bGw+LFxuICBvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMsXG4pOiBQcm9taXNlPFRlbnNvck1ldGFkYXRhW10+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICAvLyBjaGVjayBpbnB1dHMgbG9jYXRpb25cbiAgICBpZiAoaW5wdXRzLnNvbWUoKHQpID0+IHRbM10gIT09ICdjcHUnKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCB0ZW5zb3Igb24gR1BVIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIHByb3h5LicpO1xuICAgIH1cbiAgICAvLyBjaGVjayBvdXRwdXRzIGxvY2F0aW9uXG4gICAgaWYgKG91dHB1dHMuc29tZSgodCkgPT4gdCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncHJlLWFsbG9jYXRlZCBvdXRwdXQgdGVuc29yIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIHByb3h5LicpO1xuICAgIH1cbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8U2VyaWFsaXphYmxlVGVuc29yTWV0YWRhdGFbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZW5xdWV1ZUNhbGxiYWNrcygncnVuJywgW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgY29uc3Qgc2VyaWFsaXphYmxlSW5wdXRzID0gaW5wdXRzIGFzIFNlcmlhbGl6YWJsZVRlbnNvck1ldGFkYXRhW107IC8vIGV2ZXJ5IGlucHV0IGlzIG9uIENQVS5cbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0ge1xuICAgICAgICB0eXBlOiAncnVuJyxcbiAgICAgICAgaW46IHsgc2Vzc2lvbklkLCBpbnB1dEluZGljZXMsIGlucHV0czogc2VyaWFsaXphYmxlSW5wdXRzLCBvdXRwdXRJbmRpY2VzLCBvcHRpb25zIH0sXG4gICAgICB9O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UsIGNvcmUuZXh0cmFjdFRyYW5zZmVyYWJsZUJ1ZmZlcnMoc2VyaWFsaXphYmxlSW5wdXRzKSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGNvcmUucnVuKHNlc3Npb25JZCwgaW5wdXRJbmRpY2VzLCBpbnB1dHMsIG91dHB1dEluZGljZXMsIG91dHB1dHMsIG9wdGlvbnMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZW5kUHJvZmlsaW5nID0gYXN5bmMgKHNlc3Npb25JZDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgZW5zdXJlV29ya2VyKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGVucXVldWVDYWxsYmFja3MoJ2VuZC1wcm9maWxpbmcnLCBbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHsgdHlwZTogJ2VuZC1wcm9maWxpbmcnLCBpbjogc2Vzc2lvbklkIH07XG4gICAgICBwcm94eVdvcmtlciEucG9zdE1lc3NhZ2UobWVzc2FnZSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgY29yZS5lbmRQcm9maWxpbmcoc2Vzc2lvbklkKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtcbiAgSW5mZXJlbmNlU2Vzc2lvbixcbiAgSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIsXG4gIFNlc3Npb25IYW5kbGVyLFxuICBUZW5zb3IsXG4gIFRSQUNFX0ZVTkNfQkVHSU4sXG4gIFRSQUNFX0ZVTkNfRU5ELFxufSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlciwgVGVuc29yTWV0YWRhdGEgfSBmcm9tICcuL3Byb3h5LW1lc3NhZ2VzJztcbmltcG9ydCB7IGNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIsIGNyZWF0ZVNlc3Npb24sIGVuZFByb2ZpbGluZywgcmVsZWFzZVNlc3Npb24sIHJ1biB9IGZyb20gJy4vcHJveHktd3JhcHBlcic7XG5pbXBvcnQgeyBpc0dwdUJ1ZmZlclN1cHBvcnRlZFR5cGUsIGlzTUxUZW5zb3JTdXBwb3J0ZWRUeXBlIH0gZnJvbSAnLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBpc05vZGUgfSBmcm9tICcuL3dhc20tdXRpbHMtZW52JztcbmltcG9ydCB7IGxvYWRGaWxlIH0gZnJvbSAnLi93YXNtLXV0aWxzLWxvYWQtZmlsZSc7XG5cbmV4cG9ydCBjb25zdCBlbmNvZGVUZW5zb3JNZXRhZGF0YSA9ICh0ZW5zb3I6IFRlbnNvciwgZ2V0TmFtZTogKCkgPT4gc3RyaW5nKTogVGVuc29yTWV0YWRhdGEgPT4ge1xuICBzd2l0Y2ggKHRlbnNvci5sb2NhdGlvbikge1xuICAgIGNhc2UgJ2NwdSc6XG4gICAgICByZXR1cm4gW3RlbnNvci50eXBlLCB0ZW5zb3IuZGltcywgdGVuc29yLmRhdGEsICdjcHUnXTtcbiAgICBjYXNlICdncHUtYnVmZmVyJzpcbiAgICAgIHJldHVybiBbdGVuc29yLnR5cGUsIHRlbnNvci5kaW1zLCB7IGdwdUJ1ZmZlcjogdGVuc29yLmdwdUJ1ZmZlciB9LCAnZ3B1LWJ1ZmZlciddO1xuICAgIGNhc2UgJ21sLXRlbnNvcic6XG4gICAgICByZXR1cm4gW3RlbnNvci50eXBlLCB0ZW5zb3IuZGltcywgeyBtbFRlbnNvcjogdGVuc29yLm1sVGVuc29yIH0sICdtbC10ZW5zb3InXTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGRhdGEgbG9jYXRpb246ICR7dGVuc29yLmxvY2F0aW9ufSBmb3IgJHtnZXROYW1lKCl9YCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBkZWNvZGVUZW5zb3JNZXRhZGF0YSA9ICh0ZW5zb3I6IFRlbnNvck1ldGFkYXRhKTogVGVuc29yID0+IHtcbiAgc3dpdGNoICh0ZW5zb3JbM10pIHtcbiAgICBjYXNlICdjcHUnOlxuICAgICAgcmV0dXJuIG5ldyBUZW5zb3IodGVuc29yWzBdLCB0ZW5zb3JbMl0sIHRlbnNvclsxXSk7XG4gICAgY2FzZSAnZ3B1LWJ1ZmZlcic6IHtcbiAgICAgIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yWzBdO1xuICAgICAgaWYgKCFpc0dwdUJ1ZmZlclN1cHBvcnRlZFR5cGUoZGF0YVR5cGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm90IHN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZGF0YVR5cGV9IGZvciBkZXNlcmlhbGl6aW5nIEdQVSB0ZW5zb3JgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHsgZ3B1QnVmZmVyLCBkb3dubG9hZCwgZGlzcG9zZSB9ID0gdGVuc29yWzJdO1xuICAgICAgcmV0dXJuIFRlbnNvci5mcm9tR3B1QnVmZmVyKGdwdUJ1ZmZlciwgeyBkYXRhVHlwZSwgZGltczogdGVuc29yWzFdLCBkb3dubG9hZCwgZGlzcG9zZSB9KTtcbiAgICB9XG4gICAgY2FzZSAnbWwtdGVuc29yJzoge1xuICAgICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JbMF07XG4gICAgICBpZiAoIWlzTUxUZW5zb3JTdXBwb3J0ZWRUeXBlKGRhdGFUeXBlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vdCBzdXBwb3J0ZWQgZGF0YSB0eXBlOiAke2RhdGFUeXBlfSBmb3IgZGVzZXJpYWxpemluZyBNTFRlbnNvciB0ZW5zb3JgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHsgbWxUZW5zb3IsIGRvd25sb2FkLCBkaXNwb3NlIH0gPSB0ZW5zb3JbMl07XG4gICAgICByZXR1cm4gVGVuc29yLmZyb21NTFRlbnNvcihtbFRlbnNvciwgeyBkYXRhVHlwZSwgZGltczogdGVuc29yWzFdLCBkb3dubG9hZCwgZGlzcG9zZSB9KTtcbiAgICB9XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkYXRhIGxvY2F0aW9uOiAke3RlbnNvclszXX1gKTtcbiAgfVxufTtcblxuZXhwb3J0IGNsYXNzIE9ubnhydW50aW1lV2ViQXNzZW1ibHlTZXNzaW9uSGFuZGxlciBpbXBsZW1lbnRzIEluZmVyZW5jZVNlc3Npb25IYW5kbGVyIHtcbiAgcHJpdmF0ZSBzZXNzaW9uSWQ6IG51bWJlcjtcblxuICBpbnB1dE5hbWVzOiByZWFkb25seSBzdHJpbmdbXTtcbiAgb3V0cHV0TmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICBpbnB1dE1ldGFkYXRhOiByZWFkb25seSBJbmZlcmVuY2VTZXNzaW9uLlZhbHVlTWV0YWRhdGFbXTtcbiAgb3V0cHV0TWV0YWRhdGE6IHJlYWRvbmx5IEluZmVyZW5jZVNlc3Npb24uVmFsdWVNZXRhZGF0YVtdO1xuXG4gIGFzeW5jIGZldGNoTW9kZWxBbmRDb3B5VG9XYXNtTWVtb3J5KHBhdGg6IHN0cmluZyk6IFByb21pc2U8U2VyaWFsaXphYmxlSW50ZXJuYWxCdWZmZXI+IHtcbiAgICAvLyBmZXRjaCBtb2RlbCBmcm9tIHVybCBhbmQgbW92ZSB0byB3YXNtIGhlYXAuXG4gICAgcmV0dXJuIGNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIoYXdhaXQgbG9hZEZpbGUocGF0aCkpO1xuICB9XG5cbiAgYXN5bmMgbG9hZE1vZGVsKHBhdGhPckJ1ZmZlcjogc3RyaW5nIHwgVWludDhBcnJheSwgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBUUkFDRV9GVU5DX0JFR0lOKCk7XG4gICAgbGV0IG1vZGVsOiBQYXJhbWV0ZXJzPHR5cGVvZiBjcmVhdGVTZXNzaW9uPlswXTtcblxuICAgIGlmICh0eXBlb2YgcGF0aE9yQnVmZmVyID09PSAnc3RyaW5nJykge1xuICAgICAgaWYgKGlzTm9kZSkge1xuICAgICAgICAvLyBub2RlXG4gICAgICAgIG1vZGVsID0gYXdhaXQgbG9hZEZpbGUocGF0aE9yQnVmZmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGJyb3dzZXJcbiAgICAgICAgLy8gZmV0Y2ggbW9kZWwgYW5kIGNvcHkgdG8gd2FzbSBoZWFwLlxuICAgICAgICBtb2RlbCA9IGF3YWl0IHRoaXMuZmV0Y2hNb2RlbEFuZENvcHlUb1dhc21NZW1vcnkocGF0aE9yQnVmZmVyKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbW9kZWwgPSBwYXRoT3JCdWZmZXI7XG4gICAgfVxuXG4gICAgW3RoaXMuc2Vzc2lvbklkLCB0aGlzLmlucHV0TmFtZXMsIHRoaXMub3V0cHV0TmFtZXMsIHRoaXMuaW5wdXRNZXRhZGF0YSwgdGhpcy5vdXRwdXRNZXRhZGF0YV0gPSBhd2FpdCBjcmVhdGVTZXNzaW9uKFxuICAgICAgbW9kZWwsXG4gICAgICBvcHRpb25zLFxuICAgICk7XG4gICAgVFJBQ0VfRlVOQ19FTkQoKTtcbiAgfVxuXG4gIGFzeW5jIGRpc3Bvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHJlbGVhc2VTZXNzaW9uKHRoaXMuc2Vzc2lvbklkKTtcbiAgfVxuXG4gIGFzeW5jIHJ1bihcbiAgICBmZWVkczogU2Vzc2lvbkhhbmRsZXIuRmVlZHNUeXBlLFxuICAgIGZldGNoZXM6IFNlc3Npb25IYW5kbGVyLkZldGNoZXNUeXBlLFxuICAgIG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxTZXNzaW9uSGFuZGxlci5SZXR1cm5UeXBlPiB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTigpO1xuICAgIGNvbnN0IGlucHV0QXJyYXk6IFRlbnNvcltdID0gW107XG4gICAgY29uc3QgaW5wdXRJbmRpY2VzOiBudW1iZXJbXSA9IFtdO1xuICAgIE9iamVjdC5lbnRyaWVzKGZlZWRzKS5mb3JFYWNoKChrdnApID0+IHtcbiAgICAgIGNvbnN0IG5hbWUgPSBrdnBbMF07XG4gICAgICBjb25zdCB0ZW5zb3IgPSBrdnBbMV07XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMuaW5wdXROYW1lcy5pbmRleE9mKG5hbWUpO1xuICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgaW5wdXQgJyR7bmFtZX0nYCk7XG4gICAgICB9XG4gICAgICBpbnB1dEFycmF5LnB1c2godGVuc29yKTtcbiAgICAgIGlucHV0SW5kaWNlcy5wdXNoKGluZGV4KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IG91dHB1dEFycmF5OiBBcnJheTxUZW5zb3IgfCBudWxsPiA9IFtdO1xuICAgIGNvbnN0IG91dHB1dEluZGljZXM6IG51bWJlcltdID0gW107XG4gICAgT2JqZWN0LmVudHJpZXMoZmV0Y2hlcykuZm9yRWFjaCgoa3ZwKSA9PiB7XG4gICAgICBjb25zdCBuYW1lID0ga3ZwWzBdO1xuICAgICAgY29uc3QgdGVuc29yID0ga3ZwWzFdO1xuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLm91dHB1dE5hbWVzLmluZGV4T2YobmFtZSk7XG4gICAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBvdXRwdXQgJyR7bmFtZX0nYCk7XG4gICAgICB9XG4gICAgICBvdXRwdXRBcnJheS5wdXNoKHRlbnNvcik7XG4gICAgICBvdXRwdXRJbmRpY2VzLnB1c2goaW5kZXgpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgaW5wdXRzID0gaW5wdXRBcnJheS5tYXAoKHQsIGkpID0+XG4gICAgICBlbmNvZGVUZW5zb3JNZXRhZGF0YSh0LCAoKSA9PiBgaW5wdXQgXCIke3RoaXMuaW5wdXROYW1lc1tpbnB1dEluZGljZXNbaV1dfVwiYCksXG4gICAgKTtcbiAgICBjb25zdCBvdXRwdXRzID0gb3V0cHV0QXJyYXkubWFwKCh0LCBpKSA9PlxuICAgICAgdCA/IGVuY29kZVRlbnNvck1ldGFkYXRhKHQsICgpID0+IGBvdXRwdXQgXCIke3RoaXMub3V0cHV0TmFtZXNbb3V0cHV0SW5kaWNlc1tpXV19XCJgKSA6IG51bGwsXG4gICAgKTtcblxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBydW4odGhpcy5zZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRzLCBvdXRwdXRJbmRpY2VzLCBvdXRwdXRzLCBvcHRpb25zKTtcblxuICAgIGNvbnN0IHJlc3VsdE1hcDogU2Vzc2lvbkhhbmRsZXIuUmV0dXJuVHlwZSA9IHt9O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVzdWx0cy5sZW5ndGg7IGkrKykge1xuICAgICAgcmVzdWx0TWFwW3RoaXMub3V0cHV0TmFtZXNbb3V0cHV0SW5kaWNlc1tpXV1dID0gb3V0cHV0QXJyYXlbaV0gPz8gZGVjb2RlVGVuc29yTWV0YWRhdGEocmVzdWx0c1tpXSk7XG4gICAgfVxuICAgIFRSQUNFX0ZVTkNfRU5EKCk7XG4gICAgcmV0dXJuIHJlc3VsdE1hcDtcbiAgfVxuXG4gIHN0YXJ0UHJvZmlsaW5nKCk6IHZvaWQge1xuICAgIC8vIFRPRE86IGltcGxlbWVudCBwcm9maWxpbmdcbiAgfVxuXG4gIGVuZFByb2ZpbGluZygpOiB2b2lkIHtcbiAgICB2b2lkIGVuZFByb2ZpbGluZyh0aGlzLnNlc3Npb25JZCk7XG4gIH1cbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgQmFja2VuZCwgZW52LCBJbmZlcmVuY2VTZXNzaW9uLCBJbmZlcmVuY2VTZXNzaW9uSGFuZGxlciB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IGluaXRpYWxpemVPcnRFcCwgaW5pdGlhbGl6ZVdlYkFzc2VtYmx5QW5kT3J0UnVudGltZSB9IGZyb20gJy4vd2FzbS9wcm94eS13cmFwcGVyJztcbmltcG9ydCB7IE9ubnhydW50aW1lV2ViQXNzZW1ibHlTZXNzaW9uSGFuZGxlciB9IGZyb20gJy4vd2FzbS9zZXNzaW9uLWhhbmRsZXItaW5mZXJlbmNlJztcblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIGluaXRpYWxpemVzIGFsbCBmbGFncyBmb3IgV2ViQXNzZW1ibHkuXG4gKlxuICogVGhvc2UgZmxhZ3MgYXJlIGFjY2Vzc2libGUgZnJvbSBgb3J0LmVudi53YXNtYC4gVXNlcnMgYXJlIGFsbG93IHRvIHNldCB0aG9zZSBmbGFncyBiZWZvcmUgdGhlIGZpcnN0IGluZmVyZW5jZSBzZXNzaW9uXG4gKiBiZWluZyBjcmVhdGVkLCB0byBvdmVycmlkZSBkZWZhdWx0IHZhbHVlLlxuICovXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZUZsYWdzID0gKCk6IHZvaWQgPT4ge1xuICBpZiAodHlwZW9mIGVudi53YXNtLmluaXRUaW1lb3V0ICE9PSAnbnVtYmVyJyB8fCBlbnYud2FzbS5pbml0VGltZW91dCA8IDApIHtcbiAgICBlbnYud2FzbS5pbml0VGltZW91dCA9IDA7XG4gIH1cblxuICBjb25zdCBzaW1kID0gZW52Lndhc20uc2ltZDtcbiAgaWYgKHR5cGVvZiBzaW1kICE9PSAnYm9vbGVhbicgJiYgc2ltZCAhPT0gdW5kZWZpbmVkICYmIHNpbWQgIT09ICdmaXhlZCcgJiYgc2ltZCAhPT0gJ3JlbGF4ZWQnKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLndhcm4oXG4gICAgICBgUHJvcGVydHkgXCJlbnYud2FzbS5zaW1kXCIgaXMgc2V0IHRvIHVua25vd24gdmFsdWUgXCIke3NpbWR9XCIuIFJlc2V0IGl0IHRvIFxcYGZhbHNlXFxgIGFuZCBpZ25vcmUgU0lNRCBmZWF0dXJlIGNoZWNraW5nLmAsXG4gICAgKTtcbiAgICBlbnYud2FzbS5zaW1kID0gZmFsc2U7XG4gIH1cblxuICBpZiAodHlwZW9mIGVudi53YXNtLnByb3h5ICE9PSAnYm9vbGVhbicpIHtcbiAgICBlbnYud2FzbS5wcm94eSA9IGZhbHNlO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBlbnYud2FzbS50cmFjZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgZW52Lndhc20udHJhY2UgPSBmYWxzZTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgZW52Lndhc20ubnVtVGhyZWFkcyAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc0ludGVnZXIoZW52Lndhc20ubnVtVGhyZWFkcykgfHwgZW52Lndhc20ubnVtVGhyZWFkcyA8PSAwKSB7XG4gICAgLy8gVGhlIGZvbGxvd2luZyBsb2dpYyBvbmx5IGFwcGxpZXMgd2hlbiBgb3J0LmVudi53YXNtLm51bVRocmVhZHNgIGlzIG5vdCBzZXQgYnkgdXNlci4gV2Ugd2lsbCBhbHdheXMgaG9ub3IgdXNlcidzXG4gICAgLy8gc2V0dGluZyBpZiBpdCBpcyBwcm92aWRlZC5cblxuICAgIC8vIEJyb3dzZXI6IHdoZW4gY3Jvc3NPcmlnaW5Jc29sYXRlZCBpcyBmYWxzZSwgU2hhcmVkQXJyYXlCdWZmZXIgaXMgbm90IGF2YWlsYWJsZSBzbyBXZWJBc3NlbWJseSB0aHJlYWRzIHdpbGwgbm90XG4gICAgLy8gd29yay4gSW4gdGhpcyBjYXNlLCB3ZSB3aWxsIHNldCBudW1UaHJlYWRzIHRvIDEuXG4gICAgLy9cbiAgICAvLyBUaGVyZSBpcyBhbiBleGNlcHRpb246IHdoZW4gdGhlIGJyb3dzZXIgaXMgY29uZmlndXJlZCB0byBmb3JjZS1lbmFibGUgU2hhcmVkQXJyYXlCdWZmZXIgKGUuZy4gQ2hyb211aW0gd2l0aFxuICAgIC8vIC0tZW5hYmxlLWZlYXR1cmVzPVNoYXJlZEFycmF5QnVmZmVyKSwgaXQgaXMgcG9zc2libGUgdGhhdCBgc2VsZi5jcm9zc09yaWdpbklzb2xhdGVkYCBpcyBmYWxzZSBhbmRcbiAgICAvLyBTaGFyZWRBcnJheUJ1ZmZlciBpcyBhdmFpbGFibGUgYXQgdGhlIHNhbWUgdGltZS4gVGhpcyBpcyB1c3VhbGx5IGZvciB0ZXN0aW5nLiBJbiB0aGlzIGNhc2UsICB3ZSB3aWxsIHN0aWxsIHNldFxuICAgIC8vIG51bVRocmVhZHMgdG8gMSBoZXJlLiBJZiB3ZSB3YW50IHRvIGVuYWJsZSBtdWx0aS10aHJlYWRpbmcgaW4gdGVzdCwgd2Ugc2hvdWxkIHNldCBgb3J0LmVudi53YXNtLm51bVRocmVhZHNgIHRvIGFcbiAgICAvLyB2YWx1ZSBncmVhdGVyIHRoYW4gMS5cbiAgICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmICFzZWxmLmNyb3NzT3JpZ2luSXNvbGF0ZWQpIHtcbiAgICAgIGVudi53YXNtLm51bVRocmVhZHMgPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBudW1DcHVMb2dpY2FsQ29yZXMgPVxuICAgICAgICB0eXBlb2YgbmF2aWdhdG9yID09PSAndW5kZWZpbmVkJyA/IHJlcXVpcmUoJ25vZGU6b3MnKS5jcHVzKCkubGVuZ3RoIDogbmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3k7XG4gICAgICBlbnYud2FzbS5udW1UaHJlYWRzID0gTWF0aC5taW4oNCwgTWF0aC5jZWlsKChudW1DcHVMb2dpY2FsQ29yZXMgfHwgMSkgLyAyKSk7XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgY2xhc3MgT25ueHJ1bnRpbWVXZWJBc3NlbWJseUJhY2tlbmQgaW1wbGVtZW50cyBCYWNrZW5kIHtcbiAgLyoqXG4gICAqIFRoaXMgZnVuY3Rpb24gaW5pdGlhbGl6ZXMgdGhlIFdlYkFzc2VtYmx5IGJhY2tlbmQuXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgb25seSBvbmNlIGZvciBlYWNoIGJhY2tlbmQgbmFtZS4gSXQgd2lsbCBiZSBjYWxsZWQgdGhlIGZpcnN0IHRpbWUgd2hlblxuICAgKiBgb3J0LkluZmVyZW5jZVNlc3Npb24uY3JlYXRlKClgIGlzIGNhbGxlZCB3aXRoIGEgcmVnaXN0ZXJlZCBiYWNrZW5kIG5hbWUuXG4gICAqXG4gICAqIEBwYXJhbSBiYWNrZW5kTmFtZSAtIHRoZSByZWdpc3RlcmVkIGJhY2tlbmQgbmFtZS5cbiAgICovXG4gIGFzeW5jIGluaXQoYmFja2VuZE5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIHBvcHVsYXRlIHdhc20gZmxhZ3NcbiAgICBpbml0aWFsaXplRmxhZ3MoKTtcblxuICAgIC8vIGluaXQgd2FzbVxuICAgIGF3YWl0IGluaXRpYWxpemVXZWJBc3NlbWJseUFuZE9ydFJ1bnRpbWUoKTtcblxuICAgIC8vIHBlcmZvcm1lIEVQIHNwZWNpZmljIGluaXRpYWxpemF0aW9uXG4gICAgYXdhaXQgaW5pdGlhbGl6ZU9ydEVwKGJhY2tlbmROYW1lKTtcbiAgfVxuICBjcmVhdGVJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcihcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMsXG4gICk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXI+O1xuICBjcmVhdGVJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcihcbiAgICBidWZmZXI6IFVpbnQ4QXJyYXksXG4gICAgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMsXG4gICk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXI+O1xuICBhc3luYyBjcmVhdGVJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcihcbiAgICBwYXRoT3JCdWZmZXI6IHN0cmluZyB8IFVpbnQ4QXJyYXksXG4gICAgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMsXG4gICk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXI+IHtcbiAgICBjb25zdCBoYW5kbGVyID0gbmV3IE9ubnhydW50aW1lV2ViQXNzZW1ibHlTZXNzaW9uSGFuZGxlcigpO1xuICAgIGF3YWl0IGhhbmRsZXIubG9hZE1vZGVsKHBhdGhPckJ1ZmZlciwgb3B0aW9ucyk7XG4gICAgcmV0dXJuIGhhbmRsZXI7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IHdhc21CYWNrZW5kID0gbmV3IE9ubnhydW50aW1lV2ViQXNzZW1ibHlCYWNrZW5kKCk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXMsIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMgKi9cblxuLy8gV2UgdXNlIFwicmVxdWlyZVwiIGluc3RlYWQgb2YgXCJpbXBvcnRcIiBoZXJlIGJlY2F1c2UgaW1wb3J0IHN0YXRlbWVudCBtdXN0IGJlIHB1dCBpbiB0b3AgbGV2ZWwuIE91ciBjdXJyZW50IGNvZGUgZG9lc1xuLy8gbm90IGFsbG93IGJ1bmRsZXIgdG8gdHJlZS1zaGFraW5nIGNvZGUgYXMgZXhwZWN0ZWQgYmVjYXVzZSBzb21lIGNvZGVzIGFyZSB0cmVhdGVkIGFzIGhhdmluZyBzaWRlIGVmZmVjdHMuXG4vLyBTbyB3ZSBpbXBvcnQgY29kZSBpbnNpZGUgdGhlIGlmLWNsYXVzZSB0byBhbGxvdyBidW5kbGVyIHJlbW92ZSB0aGUgY29kZSBzYWZlbHkuXG5cbmV4cG9ydCAqIGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5pbXBvcnQgKiBhcyBvcnQgZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcbmV4cG9ydCBkZWZhdWx0IG9ydDtcblxuaW1wb3J0IHsgcmVnaXN0ZXJCYWNrZW5kLCBlbnYgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuaW1wb3J0IHsgdmVyc2lvbiB9IGZyb20gJy4vdmVyc2lvbic7XG5cbmlmICghQlVJTERfREVGUy5ESVNBQkxFX1dFQkdMKSB7XG4gIGNvbnN0IG9ubnhqc0JhY2tlbmQgPSByZXF1aXJlKCcuL2JhY2tlbmQtb25ueGpzJykub25ueGpzQmFja2VuZDtcbiAgcmVnaXN0ZXJCYWNrZW5kKCd3ZWJnbCcsIG9ubnhqc0JhY2tlbmQsIC0xMCk7XG59XG5cbmlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU00pIHtcbiAgY29uc3Qgd2FzbUJhY2tlbmQgPSByZXF1aXJlKCcuL2JhY2tlbmQtd2FzbScpLndhc21CYWNrZW5kO1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQKSB7XG4gICAgcmVnaXN0ZXJCYWNrZW5kKCd3ZWJncHUnLCB3YXNtQmFja2VuZCwgNSk7XG4gICAgcmVnaXN0ZXJCYWNrZW5kKCd3ZWJubicsIHdhc21CYWNrZW5kLCA1KTtcbiAgfVxuICByZWdpc3RlckJhY2tlbmQoJ2NwdScsIHdhc21CYWNrZW5kLCAxMCk7XG4gIHJlZ2lzdGVyQmFja2VuZCgnd2FzbScsIHdhc21CYWNrZW5kLCAxMCk7XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShlbnYudmVyc2lvbnMsICd3ZWInLCB7IHZhbHVlOiB2ZXJzaW9uLCBlbnVtZXJhYmxlOiB0cnVlIH0pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vLyBUaGlzIGZpbGUgaXMgZ2VuZXJhdGVkIGJ5IC9qcy9zY3JpcHRzL3VwZGF0ZS12ZXJzaW9uLnRzXG4vLyBEbyBub3QgbW9kaWZ5IGZpbGUgY29udGVudCBtYW51YWxseS5cblxuZXhwb3J0IGNvbnN0IHZlcnNpb24gPSAnMS4yMy4wJztcbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsTUFnQk0sVUFDQSwwQkFZTyxpQkF3Q1AsZ0NBd0NPO0FBN0diOztBQWdCQSxNQUFNLFdBQXFDLG9CQUFJLElBQUc7QUFDbEQsTUFBTSwyQkFBcUMsQ0FBQTtBQVlwQyxNQUFNLGtCQUFrQixDQUFDLE1BQWMsU0FBa0IsYUFBMEI7QUFDeEYsWUFBSSxXQUFXLE9BQU8sUUFBUSxTQUFTLGNBQWMsT0FBTyxRQUFRLGtDQUFrQyxZQUFZO0FBQ2hILGdCQUFNLGlCQUFpQixTQUFTLElBQUksSUFBSTtBQUN4QyxjQUFJLG1CQUFtQixRQUFXO0FBQ2hDLHFCQUFTLElBQUksTUFBTSxFQUFFLFNBQVMsU0FBUSxDQUFFO3FCQUMvQixlQUFlLFdBQVcsVUFBVTtBQUU3QztxQkFDUyxlQUFlLGFBQWEsVUFBVTtBQUMvQyxnQkFBSSxlQUFlLFlBQVksU0FBUztBQUN0QyxvQkFBTSxJQUFJLE1BQU0sNEJBQTRCLElBQUksb0JBQW9CLFFBQVEsRUFBRTs7O0FBSWxGLGNBQUksWUFBWSxHQUFHO0FBQ2pCLGtCQUFNLElBQUkseUJBQXlCLFFBQVEsSUFBSTtBQUMvQyxnQkFBSSxNQUFNLElBQUk7QUFDWix1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IlRlbnNvciIsICJUZW5zb3IiLCAiSW5mZXJlbmNlU2Vzc2lvbiIsICJJbmZlcmVuY2VTZXNzaW9uIiwgIlRlbnNvciIsICJlbnYiLCAiZW52IiwgIndhc20iLCAid2FzbSIsICJ3YXNtIiwgImxvY2F0aW9uIiwgInBhZCIsICJ0ZW5zb3IiLCAiZW52IiwgIm1sQ29udGV4dEluZGV4IiwgIndhc20iLCAiaW5pdCIsICJvZmZzZXRzIiwgImluZGljZXMiLCAiaW1wbCIsICJ2YWxpZGF0ZUlucHV0cyIsICJyZWR1Y2VPcHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiZW52IiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgImEiLCAiYiIsICJ2YWxpZGF0ZUlucHV0cyIsICJpIiwgImlucHV0VmFyaWFibGUiLCAidHJhbnNwb3NlIiwgIm91dHB1dFZhcmlhYmxlIiwgImlubmVyRWxlbWVudFNpemUiLCAicGFkIiwgInZhbGlkYXRlSW5wdXRzIiwgImNvbnZJbnB1dHMiLCAidHJhbnNwb3NlZFdlaWdodCIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJwZXJtRnVuY3Rpb25Cb2R5IiwgInN5bWJvbCIsICJyZWR1Y2VPcHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiY2FsY3VsYXRlT3V0cHV0U2hhcGUiLCAiZmFzdEdlbHUiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiaW5wdXRzIiwgIm91dHB1dFNpemUiLCAidmFsaWRhdGVJbnB1dHMiLCAid2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgIndlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZSIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJkYXRhVHlwZSIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJlbnYiLCAidmFsaWRhdGVJbnB1dHMiLCAiZW52IiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgImNvbXBvbmVudHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiZ2V0T3V0cHV0U2hhcGUiLCAiYSIsICJiIiwgImMiLCAiZmFzdEdlbHUiLCAiZW52IiwgImkiLCAiZW52IiwgImVudiIsICJ3YXNtIiwgImxvY2F0aW9uIiwgImluZGV4IiwgInRlbnNvciIsICJlcnJvckNvZGUiLCAiaSIsICJpbml0aWFsaXppbmciLCAiaW5pdGlhbGl6ZWQiLCAiYWJvcnRlZCIsICJjb3B5RnJvbUV4dGVybmFsQnVmZmVyIiwgImNyZWF0ZVNlc3Npb24iLCAicmVsZWFzZVNlc3Npb24iLCAicnVuIiwgImVuZFByb2ZpbGluZyIsICJlbnYiLCAiVGVuc29yIiwgImNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIiLCAiY3JlYXRlU2Vzc2lvbiIsICJyZWxlYXNlU2Vzc2lvbiIsICJydW4iLCAiZW5kUHJvZmlsaW5nIiwgImVudiIsICJJbmZlcmVuY2VTZXNzaW9uIiwgIlRlbnNvciIsICJlbnYiLCAidmVyc2lvbiIsICJ3YXNtQmFja2VuZCIsICJlbnYiLCAidmVyc2lvbiJdCn0K